RTPAddress *RTPByteAddress::CreateCopy(RTPMemoryManager *mgr) const { RTPByteAddress *a = RTPNew(mgr, RTPMEM_TYPE_CLASS_RTPADDRESS) RTPByteAddress(hostaddress, addresslength, port); return a; }
RTPAddress *RTPIPv6Address::CreateCopy(RTPMemoryManager *mgr) const { RTPIPv6Address *newaddr = RTPNew(mgr,RTPMEM_TYPE_CLASS_RTPADDRESS) RTPIPv6Address(ip,port); return newaddr; }
int RTPPacket::BuildPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr, uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs, bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata, void *buffer,size_t maxsize) { if (numcsrcs > RTP_MAXCSRCS) return ERR_RTP_PACKET_TOOMANYCSRCS; if (payloadtype > 127) // high bit should not be used return ERR_RTP_PACKET_BADPAYLOADTYPE; if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types return ERR_RTP_PACKET_BADPAYLOADTYPE; packetlength = sizeof(RTPHeader); packetlength += sizeof(uint32_t)*((size_t)numcsrcs); if (gotextension) { packetlength += sizeof(RTPExtensionHeader); packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords); } packetlength += payloadlen; if (maxsize > 0 && packetlength > maxsize) { packetlength = 0; return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE; } // Ok, now we'll just fill in... RTPHeader *rtphdr; if (buffer == 0) { packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength]; if (packet == 0) { packetlength = 0; return ERR_RTP_OUTOFMEM; } externalbuffer = false; } else { packet = (uint8_t *)buffer; externalbuffer = true; } RTPPacket::hasmarker = gotmarker; RTPPacket::hasextension = gotextension; RTPPacket::numcsrcs = numcsrcs; RTPPacket::payloadtype = payloadtype; RTPPacket::extseqnr = (uint32_t)seqnr; RTPPacket::timestamp = timestamp; RTPPacket::ssrc = ssrc; RTPPacket::payloadlength = payloadlen; RTPPacket::extid = extensionid; RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t); rtphdr = (RTPHeader *)packet; rtphdr->version = RTP_VERSION; rtphdr->padding = 0; if (gotmarker) rtphdr->marker = 1; else rtphdr->marker = 0; if (gotextension) rtphdr->extension = 1; else rtphdr->extension = 0; rtphdr->csrccount = numcsrcs; rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set rtphdr->sequencenumber = htons(seqnr); rtphdr->timestamp = htonl(timestamp); rtphdr->ssrc = htonl(ssrc); uint32_t *curcsrc; int i; curcsrc = (uint32_t *)(packet+sizeof(RTPHeader)); for (i = 0 ; i < numcsrcs ; i++,curcsrc++) *curcsrc = htonl(csrcs[i]); payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t); if (gotextension) { RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload; rtpexthdr->extid = htons(extensionid); rtpexthdr->length = htons((uint16_t)extensionlen_numwords); payload += sizeof(RTPExtensionHeader); memcpy(payload,extensiondata,RTPPacket::extensionlength); payload += RTPPacket::extensionlength; } memcpy(payload,payloaddata,payloadlen); return 0; }
int RTCPCompoundPacketBuilder::EndBuild() { if (!arebuilding) return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING; if (report.headerlength == 0) return ERR_RTP_RTCPCOMPPACKBUILDER_NOREPORTPRESENT; uint8_t *buf; size_t len; #ifndef RTP_SUPPORT_RTCPUNKNOWN len = appsize+byesize+report.NeededBytes()+sdes.NeededBytes(); #else len = appsize+unknownsize+byesize+report.NeededBytes()+sdes.NeededBytes(); #endif // RTP_SUPPORT_RTCPUNKNOWN if (!external) { buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPCOMPOUNDPACKET) uint8_t[len]; if (buf == 0) return ERR_RTP_OUTOFMEM; } else buf = buffer; uint8_t *curbuf = buf; RTCPPacket *p; // first, we'll add all report info { bool firstpacket = true; bool done = false; std::list<Buffer>::const_iterator it = report.reportblocks.begin(); do { RTCPCommonHeader *hdr = (RTCPCommonHeader *)curbuf; size_t offset; hdr->version = 2; hdr->padding = 0; if (firstpacket && report.isSR) { hdr->packettype = RTP_RTCPTYPE_SR; memcpy((curbuf+sizeof(RTCPCommonHeader)),report.headerdata,report.headerlength); offset = sizeof(RTCPCommonHeader)+report.headerlength; } else { hdr->packettype = RTP_RTCPTYPE_RR; memcpy((curbuf+sizeof(RTCPCommonHeader)),report.headerdata,sizeof(uint32_t)); offset = sizeof(RTCPCommonHeader)+sizeof(uint32_t); } firstpacket = false; uint8_t count = 0; while (it != report.reportblocks.end() && count < 31) { memcpy(curbuf+offset,(*it).packetdata,(*it).packetlength); offset += (*it).packetlength; count++; it++; } size_t numwords = offset/sizeof(uint32_t); hdr->length = htons((uint16_t)(numwords-1)); hdr->count = count; // add entry in parent's list if (hdr->packettype == RTP_RTCPTYPE_SR) p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSRPACKET) RTCPSRPacket(curbuf,offset); else p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPRRPACKET) RTCPRRPacket(curbuf,offset); if (p == 0) { if (!external) RTPDeleteByteArray(buf,GetMemoryManager()); ClearPacketList(); return ERR_RTP_OUTOFMEM; } rtcppacklist.push_back(p); curbuf += offset; if (it == report.reportblocks.end()) done = true; } while (!done); } // then, we'll add the sdes info if (!sdes.sdessources.empty()) { bool done = false; std::list<SDESSource *>::const_iterator sourceit = sdes.sdessources.begin(); do { RTCPCommonHeader *hdr = (RTCPCommonHeader *)curbuf; size_t offset = sizeof(RTCPCommonHeader); hdr->version = 2; hdr->padding = 0; hdr->packettype = RTP_RTCPTYPE_SDES; uint8_t sourcecount = 0; while (sourceit != sdes.sdessources.end() && sourcecount < 31) { uint32_t *ssrc = (uint32_t *)(curbuf+offset); *ssrc = htonl((*sourceit)->ssrc); offset += sizeof(uint32_t); std::list<Buffer>::const_iterator itemit,itemend; itemit = (*sourceit)->items.begin(); itemend = (*sourceit)->items.end(); while (itemit != itemend) { memcpy(curbuf+offset,(*itemit).packetdata,(*itemit).packetlength); offset += (*itemit).packetlength; itemit++; } curbuf[offset] = 0; // end of item list; offset++; size_t r = offset&0x03; if (r != 0) // align to 32 bit boundary { size_t num = 4-r; size_t i; for (i = 0 ; i < num ; i++) curbuf[offset+i] = 0; offset += num; } sourceit++; sourcecount++; } size_t numwords = offset/4; hdr->count = sourcecount; hdr->length = htons((uint16_t)(numwords-1)); p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSDESPACKET) RTCPSDESPacket(curbuf,offset); if (p == 0) { if (!external) RTPDeleteByteArray(buf,GetMemoryManager()); ClearPacketList(); return ERR_RTP_OUTOFMEM; } rtcppacklist.push_back(p); curbuf += offset; if (sourceit == sdes.sdessources.end()) done = true; } while (!done); } // adding the app data { std::list<Buffer>::const_iterator it; for (it = apppackets.begin() ; it != apppackets.end() ; it++) { memcpy(curbuf,(*it).packetdata,(*it).packetlength); p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPAPPPACKET) RTCPAPPPacket(curbuf,(*it).packetlength); if (p == 0) { if (!external) RTPDeleteByteArray(buf,GetMemoryManager()); ClearPacketList(); return ERR_RTP_OUTOFMEM; } rtcppacklist.push_back(p); curbuf += (*it).packetlength; } } #ifdef RTP_SUPPORT_RTCPUNKNOWN // adding the unknown data { std::list<Buffer>::const_iterator it; for (it = unknownpackets.begin() ; it != unknownpackets.end() ; it++) { memcpy(curbuf,(*it).packetdata,(*it).packetlength); p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET) RTCPUnknownPacket(curbuf,(*it).packetlength); if (p == 0) { if (!external) RTPDeleteByteArray(buf,GetMemoryManager()); ClearPacketList(); return ERR_RTP_OUTOFMEM; } rtcppacklist.push_back(p); curbuf += (*it).packetlength; } } #endif // RTP_SUPPORT_RTCPUNKNOWN // adding bye packets { std::list<Buffer>::const_iterator it; for (it = byepackets.begin() ; it != byepackets.end() ; it++) { memcpy(curbuf,(*it).packetdata,(*it).packetlength); p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPBYEPACKET) RTCPBYEPacket(curbuf,(*it).packetlength); if (p == 0) { if (!external) RTPDeleteByteArray(buf,GetMemoryManager()); ClearPacketList(); return ERR_RTP_OUTOFMEM; } rtcppacklist.push_back(p); curbuf += (*it).packetlength; } } compoundpacket = buf; compoundpacketlength = len; arebuilding = false; ClearBuildBuffers(); return 0; }
int RTCPCompoundPacketBuilder::AddBYEPacket(uint32_t *ssrcs,uint8_t numssrcs,const void *reasondata,uint8_t reasonlength) { if (!arebuilding) return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING; if (numssrcs > 31) return ERR_RTP_RTCPCOMPPACKBUILDER_TOOMANYSSRCS; size_t packsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)*((size_t)numssrcs); size_t zerobytes = 0; if (reasonlength > 0) { packsize += 1; // 1 byte for the length; packsize += (size_t)reasonlength; size_t r = (packsize&0x03); if (r != 0) { zerobytes = 4-r; packsize += zerobytes; } } #ifndef RTP_SUPPORT_RTCPUNKNOWN size_t totalotherbytes = appsize+byesize+sdes.NeededBytes()+report.NeededBytes(); #else size_t totalotherbytes = appsize+unknownsize+byesize+sdes.NeededBytes()+report.NeededBytes(); #endif // RTP_SUPPORT_RTCPUNKNOWN if ((totalotherbytes + packsize) > maximumpacketsize) return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT; uint8_t *buf; size_t numwords; buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPBYEPACKET) uint8_t[packsize]; if (buf == 0) return ERR_RTP_OUTOFMEM; RTCPCommonHeader *hdr = (RTCPCommonHeader *)buf; hdr->version = 2; hdr->padding = 0; hdr->count = numssrcs; numwords = packsize/sizeof(uint32_t); hdr->length = htons((uint16_t)(numwords-1)); hdr->packettype = RTP_RTCPTYPE_BYE; uint32_t *sources = (uint32_t *)(buf+sizeof(RTCPCommonHeader)); uint8_t srcindex; for (srcindex = 0 ; srcindex < numssrcs ; srcindex++) sources[srcindex] = htonl(ssrcs[srcindex]); if (reasonlength != 0) { size_t offset = sizeof(RTCPCommonHeader)+((size_t)numssrcs)*sizeof(uint32_t); buf[offset] = reasonlength; memcpy((buf+offset+1),reasondata,(size_t)reasonlength); for (size_t i = 0 ; i < zerobytes ; i++) buf[packsize-1-i] = 0; } byepackets.push_back(Buffer(buf,packsize)); byesize += packsize; return 0; }
int RTCPCompoundPacketBuilder::AddSDESNormalItem(RTCPSDESPacket::ItemType t,const void *itemdata,uint8_t itemlength) { if (!arebuilding) return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING; if (sdes.sdessources.empty()) return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE; uint8_t itemid; switch(t) { case RTCPSDESPacket::CNAME: itemid = RTCP_SDES_ID_CNAME; break; case RTCPSDESPacket::NAME: itemid = RTCP_SDES_ID_NAME; break; case RTCPSDESPacket::EMAIL: itemid = RTCP_SDES_ID_EMAIL; break; case RTCPSDESPacket::PHONE: itemid = RTCP_SDES_ID_PHONE; break; case RTCPSDESPacket::LOC: itemid = RTCP_SDES_ID_LOCATION; break; case RTCPSDESPacket::TOOL: itemid = RTCP_SDES_ID_TOOL; break; case RTCPSDESPacket::NOTE: itemid = RTCP_SDES_ID_NOTE; break; default: return ERR_RTP_RTCPCOMPPACKBUILDER_INVALIDITEMTYPE; } #ifndef RTP_SUPPORT_RTCPUNKNOWN size_t totalotherbytes = byesize+appsize+report.NeededBytes(); #else size_t totalotherbytes = byesize+appsize+unknownsize+report.NeededBytes(); #endif // RTP_SUPPORT_RTCPUNKNOWN size_t sdessizewithextraitem = sdes.NeededBytesWithExtraItem(itemlength); if ((sdessizewithextraitem+totalotherbytes) > maximumpacketsize) return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT; uint8_t *buf; size_t len; buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPSDESBLOCK) uint8_t[sizeof(RTCPSDESHeader)+(size_t)itemlength]; if (buf == 0) return ERR_RTP_OUTOFMEM; len = sizeof(RTCPSDESHeader)+(size_t)itemlength; RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(buf); sdeshdr->sdesid = itemid; sdeshdr->length = itemlength; if (itemlength != 0) memcpy((buf + sizeof(RTCPSDESHeader)),itemdata,(size_t)itemlength); sdes.AddItem(buf,len); return 0; }