void AmRtpStream::recvPacket() { AmRtpPacket* p = mem.newPacket(); if (!p) { // drop received data AmRtpPacket dummy; dummy.recv(l_sd); return; } if(p->recv(l_sd) > 0){ int parse_res = p->parse(); gettimeofday(&p->recv_time,NULL); if (parse_res == -1) { DBG("error while parsing RTP packet.\n"); clearRTPTimeout(&p->recv_time); mem.freePacket(p); } else { bufferPacket(p); } } else { mem.freePacket(p); } }
int AmRtpStream::ping() { // TODO: // - we'd better send an empty UDP packet // for this purpose. unsigned char ping_chr[2]; ping_chr[0] = 0; ping_chr[1] = 0; AmRtpPacket rp; rp.payload = payload; rp.marker = true; rp.sequence = sequence++; rp.timestamp = 0; rp.ssrc = l_ssrc; rp.compile((unsigned char*)ping_chr,2); rp.setAddr(&r_saddr); if(rp.send(l_sd) < 0){ ERROR("while sending RTP packet.\n"); return -1; } return 2; }
void AmRtpReceiver::run() { unsigned int tmp_nfds = 0; struct pollfd* tmp_fds = new struct pollfd[MAX_RTP_SESSIONS]; while(true){ fds_mut.lock(); tmp_nfds = nfds; memcpy(tmp_fds,fds,nfds*sizeof(struct pollfd)); fds_mut.unlock(); int ret = poll(tmp_fds,tmp_nfds,RTP_POLL_TIMEOUT); if(ret < 0) ERROR("AmRtpReceiver: poll: %s\n",strerror(errno)); if(ret < 1) continue; for(unsigned int i=0; i<tmp_nfds; i++) { if(!(tmp_fds[i].revents & POLLIN)) continue; streams_mut.lock(); Streams::iterator it = streams.find(tmp_fds[i].fd); if(it != streams.end()) { AmRtpPacket* p = it->second->newPacket(); if (!p) { // drop received data AmRtpPacket dummy; dummy.recv(tmp_fds[i].fd); streams_mut.unlock(); continue; } if(p->recv(tmp_fds[i].fd) > 0){ int parse_res = p->parse(); gettimeofday(&p->recv_time,NULL); if (parse_res == -1) { DBG("error while parsing RTP packet.\n"); it->second->clearRTPTimeout(&p->recv_time); it->second->freePacket(p); } else { it->second->bufferPacket(p); } } else { it->second->freePacket(p); } } streams_mut.unlock(); } } }
int AmRtpStream::send( unsigned int ts, unsigned char* buffer, unsigned int size ) { if ((mute) || (hold)) return 0; if(!size) return -1; AmRtpPacket rp; rp.payload = payload; rp.marker = false; rp.sequence = sequence++; rp.timestamp = ts; rp.ssrc = l_ssrc; rp.compile((unsigned char*)buffer,size); rp.setAddr(&r_saddr); #ifdef WITH_ZRTP if (session->zrtp_audio) { zrtp_status_t status = zrtp_status_fail; unsigned int size = rp.getBufferSize(); status = zrtp_process_rtp(session->zrtp_audio, (char*)rp.getBuffer(), &size); switch (status) { case zrtp_status_drop: { DBG("ZRTP says: drop packet! %u - %u\n", size, rp.getBufferSize()); return 0; } case zrtp_status_ok: { // DBG("ZRTP says: ok!\n"); if (rp.getBufferSize() != size) // DBG("SEND packet size before: %d, after %d\n", // rp.getBufferSize(), size); rp.setBufferSize(size); } break; default: case zrtp_status_fail: { DBG("ZRTP says: fail!\n"); // DBG("(f)"); return 0; } } } #endif if(rp.send(l_sd) < 0){ ERROR("while sending RTP packet.\n"); return -1; } return size; }
int AmRtpStream::send_raw( char* packet, unsigned int length ) { if ((mute) || (hold)) return 0; AmRtpPacket rp; rp.compile_raw((unsigned char*)packet, length); rp.setAddr(&r_saddr); if(rp.send(l_sd) < 0){ ERROR("while sending raw RTP packet.\n"); return -1; } return length; }
int AmRtpStream::nextPacket(AmRtpPacket& p) { if (!receiving && !passive) return RTP_EMPTY; struct timeval now; struct timeval diff; gettimeofday(&now,NULL); receive_mut.lock(); timersub(&now,&last_recv_time,&diff); if(AmConfig::DeadRtpTime && (diff.tv_sec > 0) && ((unsigned int)diff.tv_sec > AmConfig::DeadRtpTime)){ WARN("RTP Timeout detected. Last received packet is too old.\n"); DBG("diff.tv_sec = %i\n",(unsigned int)diff.tv_sec); receive_mut.unlock(); return RTP_TIMEOUT; } if(receive_buf.empty()){ receive_mut.unlock(); return RTP_EMPTY; } AmRtpPacket& pp = receive_buf.begin()->second; p.copy(&pp); receive_buf.erase(receive_buf.begin()); receive_mut.unlock(); return 1; }
int AmRtpStream::receive( unsigned char* buffer, unsigned int size, unsigned int& ts, int &out_payload) { AmRtpPacket* rp = NULL; int err = nextPacket(rp); if(err <= 0) return err; if (!rp) return 0; handleSymmetricRtp(rp); /* do we have a new talk spurt? */ begin_talk = ((last_payload == 13) || rp->marker); last_payload = rp->payload; if(!rp->getDataSize()) { mem.freePacket(rp); return RTP_EMPTY; } if (rp->payload == getLocalTelephoneEventPT()) { dtmf_payload_t* dpl = (dtmf_payload_t*)rp->getData(); DBG("DTMF: event=%i; e=%i; r=%i; volume=%i; duration=%i; ts=%u\n", dpl->event,dpl->e,dpl->r,dpl->volume,ntohs(dpl->duration),rp->timestamp); session->postDtmfEvent(new AmRtpDtmfEvent(dpl, getLocalTelephoneEventRate(), rp->timestamp)); mem.freePacket(rp); return RTP_DTMF; } assert(rp->getData()); if(rp->getDataSize() > size){ ERROR("received too big RTP packet\n"); mem.freePacket(rp); return RTP_BUFFER_SIZE; } memcpy(buffer,rp->getData(),rp->getDataSize()); ts = rp->timestamp; out_payload = rp->payload; int res = rp->getDataSize(); mem.freePacket(rp); return res; }
int AmRtpStream::send( unsigned int ts, unsigned char* buffer, unsigned int size ) { if ((mute) || (hold)) return 0; if(!size) return -1; AmRtpPacket rp; rp.payload = payload; rp.marker = false; rp.sequence = sequence++; rp.timestamp = ts; rp.ssrc = l_ssrc; rp.compile((unsigned char*)buffer,size); rp.setAddr(&r_saddr); if(rp.send(l_sd) < 0){ ERROR("while sending RTP packet.\n"); return -1; } return size; }
int AmRtpStream::receive( unsigned char* buffer, unsigned int size, unsigned int& ts, int &out_payload) { AmRtpPacket* rp = NULL; int err = nextPacket(rp); if(err <= 0) return err; if (!rp) return 0; #ifndef SUPPORT_IPV6 if(passive) { // #ifdef SUPPORT_IPV6 // struct sockaddr_storage recv_addr; // #else struct sockaddr_in recv_addr; rp->getAddr(&recv_addr); // symmetric RTP if ((recv_addr.sin_port != r_saddr.sin_port) || (recv_addr.sin_addr.s_addr != r_saddr.sin_addr.s_addr)) { string addr_str = get_addr_str(recv_addr.sin_addr); int port = ntohs(recv_addr.sin_port); setRAddr(addr_str,port); DBG("Symmetric RTP: setting new remote address: %s:%i\n", addr_str.c_str(),port); // avoid comparing each time sender address } else { DBG("Symmetric RTP: remote end sends RTP from advertised address. Leaving passive mode.\n"); } passive = false; } #endif /* do we have a new talk spurt? */ begin_talk = ((last_payload == 13) || rp->marker); last_payload = rp->payload; if(!rp->getDataSize()) { mem.freePacket(rp); return RTP_EMPTY; } if (telephone_event_pt.get() && rp->payload == telephone_event_pt->payload_type) { dtmf_payload_t* dpl = (dtmf_payload_t*)rp->getData(); DBG("DTMF: event=%i; e=%i; r=%i; volume=%i; duration=%i\n", dpl->event,dpl->e,dpl->r,dpl->volume,ntohs(dpl->duration)); session->postDtmfEvent(new AmRtpDtmfEvent(dpl, getTelephoneEventRate())); mem.freePacket(rp); return RTP_DTMF; } assert(rp->getData()); if(rp->getDataSize() > size){ ERROR("received too big RTP packet\n"); mem.freePacket(rp); return RTP_BUFFER_SIZE; } memcpy(buffer,rp->getData(),rp->getDataSize()); ts = rp->timestamp; out_payload = rp->payload; int res = rp->getDataSize(); mem.freePacket(rp); return res; }