bool BaseVariantProtocol::SignalInputData(IOBuffer &buffer) { if (_pProtocolHandler == NULL) { FATAL("This protocol is not registered to any application yet"); return false; } if (_pFarProtocol->GetType() == PT_OUTBOUND_HTTP || _pFarProtocol->GetType() == PT_INBOUND_HTTP) { #ifdef HAS_PROTOCOL_HTTP //1. This is a HTTP based transfer. We only start doing stuff //after a complete request is made. BaseHTTPProtocol *pHTTPProtocol = (BaseHTTPProtocol *) _pFarProtocol; if (!pHTTPProtocol->TransferCompleted()) return true; if (!Deserialize(GETIBPOINTER(buffer), pHTTPProtocol->GetContentLength(), _lastReceived)) { FATAL("Unable to deserialize content"); return false; } buffer.Ignore(pHTTPProtocol->GetContentLength()); _lastReceived.Compact(); return _pProtocolHandler->ProcessMessage(this, _lastSent, _lastReceived); #else FATAL("HTTP protocol not supported"); return false; #endif /* HAS_PROTOCOL_HTTP */ } else if (_pFarProtocol->GetType() == PT_TCP) { while (GETAVAILABLEBYTESCOUNT(buffer) > 4) { uint32_t size = ENTOHLP(GETIBPOINTER(buffer)); if (size > 4 * 1024 * 1024) { FATAL("Size too big: %u", size); return false; } if (GETAVAILABLEBYTESCOUNT(buffer) < size + 4) { FINEST("Need more data"); return true; } if (!Deserialize(GETIBPOINTER(buffer) + 4, size, _lastReceived)) { FATAL("Unable to deserialize variant"); return false; } buffer.Ignore(size + 4); _lastReceived.Compact(); if (!_pProtocolHandler->ProcessMessage(this, _lastSent, _lastReceived)) { FATAL("Unable to process message"); return false; } } return true; } else { FATAL("Invalid protocol stack"); return false; } }
bool AMF0Serializer::ReadLongString(IOBuffer &buffer, Variant &variant, bool readType) { if (readType) { AMF_CHECK_BOUNDARIES(buffer, 1); if (GETIBPOINTER(buffer)[0] != AMF0_LONG_STRING) { FATAL("AMF type not valid: want: %hhu; got: %hhu", AMF0_LONG_STRING, GETIBPOINTER(buffer)[0]); return false; } if (!buffer.Ignore(1)) { FATAL("Unable to ignore 1 bytes"); return false; } } AMF_CHECK_BOUNDARIES(buffer, 4); uint32_t length = ENTOHLP(GETIBPOINTER(buffer)); //----MARKED-LONG--- if (!buffer.Ignore(4)) { FATAL("Unable to ignore 4 bytes"); return false; } AMF_CHECK_BOUNDARIES(buffer, length); variant = string((char *) (GETIBPOINTER(buffer)), length); if (!buffer.Ignore(length)) { FATAL("Unable to ignore %u bytes", length); return false; } return true; }
bool _VIDEO_AVC::Deserialize(IOBuffer &src, _VIDEO_AVC &dest) { dest.Clear(); uint8_t *pBuffer = GETIBPOINTER(src); uint32_t length = GETAVAILABLEBYTESCOUNT(src); if (length<sizeof (dest._spsLength)) { FATAL("Not enough data"); return false; } dest._spsLength = ENTOHSP(pBuffer); if (length < ( sizeof (dest._spsLength) + dest._spsLength + sizeof (dest._ppsLength) + 2 * sizeof (uint32_t))) { FATAL("Not enough data"); return false; } dest._ppsLength = ENTOHSP(pBuffer + sizeof (dest._spsLength) + dest._spsLength); if (length < ( sizeof (dest._spsLength) + dest._spsLength + sizeof (dest._ppsLength) + dest._ppsLength + 2 * sizeof (uint32_t))) { FATAL("Not enough data"); return false; } if (!dest.Init( pBuffer + sizeof (dest._spsLength), dest._spsLength, pBuffer + sizeof (dest._spsLength) + dest._spsLength + sizeof (dest._ppsLength), dest._ppsLength)) { FATAL("Unable to init AVC"); return false; } dest._widthOverride = ENTOHLP(pBuffer + sizeof (dest._spsLength) + dest._spsLength + sizeof (dest._ppsLength) + dest._ppsLength); dest._heightOverride = ENTOHLP(pBuffer + sizeof (dest._spsLength) + dest._spsLength + sizeof (dest._ppsLength) + dest._ppsLength + sizeof (uint32_t)); return src.Ignore(sizeof (dest._spsLength) + dest._spsLength + sizeof (dest._ppsLength) + dest._ppsLength + sizeof (uint32_t) + sizeof (uint32_t)); }
bool StreamCapabilities::Deserialize(IOBuffer &src, StreamCapabilities &capabilities) { uint8_t *pBuffer = GETIBPOINTER(src); uint32_t length = GETAVAILABLEBYTESCOUNT(src); if (length < 28) { FATAL("Not enough data"); return false; } uint64_t ver = ENTOHLLP(pBuffer); if (ver != __STREAM_CAPABILITIES_VERSION) { FATAL("Invalid stream capabilities version. Wanted: %"PRIu64"; Got: %"PRIu64, __STREAM_CAPABILITIES_VERSION, ver); return false; } capabilities.Clear(); capabilities.videoCodecId = ENTOHLLP(pBuffer + 8); capabilities.audioCodecId = ENTOHLLP(pBuffer + 16); capabilities.bandwidthHint = ENTOHLP(pBuffer + 24); src.Ignore(28); switch (capabilities.videoCodecId) { case CODEC_VIDEO_AVC: { if (!_VIDEO_AVC::Deserialize(src, capabilities.avc)) { FATAL("Unable to deserialize avc"); return false; } break; } default: { break; } } switch (capabilities.audioCodecId) { case CODEC_AUDIO_AAC: { if (!_AUDIO_AAC::Deserialize(src, capabilities.aac)) { FATAL("Unable to deserialize aac"); return false; } break; } default: { break; } } return true; }
bool VariantConnection::SendMessage(Variant &message, Variant &response) { string rawContent = " "; if (!message.SerializeToBin(rawContent)) { FATAL("Unable to serialize message"); return false; } uint8_t *pBuffer = (uint8_t *) rawContent.c_str(); uint32_t size = rawContent.size(); EHTONLP(pBuffer, size - 4); int32_t totalSentAmount = 0; int32_t sentAmount = 0; while (totalSentAmount < (int32_t) size) { sentAmount = send(_fd, pBuffer + totalSentAmount, size - totalSentAmount, 0); if (sentAmount <= 0) { return false; } totalSentAmount += sentAmount; } _buffer.IgnoreAll(); int32_t recvAmount = 0; for (;;) { if (!_buffer.ReadFromTCPFd(_fd, 1024 * 1024, recvAmount)) { FATAL("Unable to read from socket"); return false; } size = GETAVAILABLEBYTESCOUNT(_buffer); pBuffer = GETIBPOINTER(_buffer); if (size < 4) { WARN("not enough data. Wait for more..."); continue; } uint32_t variantSize = ENTOHLP(pBuffer); if (variantSize + 4 > size) { WARN("not enough data. Wait for more..."); continue; } if (!Variant::DeserializeFromBin(pBuffer + 4, variantSize, response)) { FATAL("Unable to deserialize buffer"); return false; } return true; } }
bool _AUDIO_AAC::Deserialize(IOBuffer &src, _AUDIO_AAC &dest) { dest.Clear(); uint8_t *pBuffer = GETIBPOINTER(src); uint32_t length = GETAVAILABLEBYTESCOUNT(src); if (length<sizeof (dest._aacLength)) { FATAL("Not enough data"); return false; } dest._aacLength = ENTOHLP(pBuffer); if (length<sizeof (dest._aacLength) + dest._aacLength) { FATAL("Not enough data"); return false; } if (!dest.Init(pBuffer + sizeof (dest._aacLength), dest._aacLength)) { FATAL("Unable to init AAC"); return false; } return src.Ignore(sizeof (dest._aacLength) + dest._aacLength); }
bool Header::Read(uint32_t channelId, uint8_t type, IOBuffer &buffer, uint32_t availableBytes) { ht = type; ci = channelId; switch (ht) { case HT_FULL: { isAbsolute = true; if (availableBytes < 11) { readCompleted = false; return true; } memcpy(hf.datac + 1, GETIBPOINTER(buffer), 11); hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG--- hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG--- if (hf.s.ts == 0x00ffffff) { skip4bytes = true; if (availableBytes < 15) { readCompleted = false; return true; } hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 11); readCompleted = true; return buffer.Ignore(15); } else { skip4bytes = false; readCompleted = true; return buffer.Ignore(11); } } case HT_SAME_STREAM: { isAbsolute = false; if (availableBytes < 7) { readCompleted = false; return true; } memcpy(hf.datac + 1, GETIBPOINTER(buffer), 7); hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG--- hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG--- if (hf.s.ts == 0x00ffffff) { skip4bytes = true; if (availableBytes < 11) { readCompleted = false; return true; } hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 7); readCompleted = true; return buffer.Ignore(11); } else { skip4bytes = false; readCompleted = true; return buffer.Ignore(7); } } case HT_SAME_LENGTH_AND_STREAM: { isAbsolute = false; if (availableBytes < 3) { readCompleted = false; return true; } memcpy(hf.datac + 1, GETIBPOINTER(buffer), 3); hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG--- if (hf.s.ts == 0x00ffffff) { skip4bytes = true; if (availableBytes < 7) { readCompleted = false; return true; } hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 3); readCompleted = true; return buffer.Ignore(7); } else { skip4bytes = false; readCompleted = true; return buffer.Ignore(3); } } case HT_CONTINUATION: { isAbsolute = false; if (skip4bytes) { if (availableBytes < 4) { readCompleted = false; return true; } readCompleted = true; return buffer.Ignore(4); } else { readCompleted = true; return true; } } default: { FATAL("Invalid header type: %hhu", ht); return false; } } }
void CommonTestsSuite::test_Endianess() { uint16_t ui16 = 0x0102; uint32_t ui32 = 0x01020304; uint64_t ui64 = 0x0102030405060708LL; double d = 123.456; //host to network uint8_t *pBuffer = NULL; ui16 = EHTONS(ui16); pBuffer = (uint8_t *) & ui16; TS_ASSERT(pBuffer[0] == 0x01); TS_ASSERT(pBuffer[1] == 0x02); pBuffer = NULL; ui32 = EHTONL(ui32); pBuffer = (uint8_t *) & ui32; TS_ASSERT(pBuffer[0] == 0x01); TS_ASSERT(pBuffer[1] == 0x02); TS_ASSERT(pBuffer[2] == 0x03); TS_ASSERT(pBuffer[3] == 0x04); pBuffer = NULL; ui32 = 0x01020304; ui32 = EHTONA(ui32); pBuffer = (uint8_t *) & ui32; TS_ASSERT(pBuffer[0] == 0x02); TS_ASSERT(pBuffer[1] == 0x03); TS_ASSERT(pBuffer[2] == 0x04); TS_ASSERT(pBuffer[3] == 0x01); pBuffer = NULL; ui64 = EHTONLL(ui64); pBuffer = (uint8_t *) & ui64; TS_ASSERT(pBuffer[0] == 0x01); TS_ASSERT(pBuffer[1] == 0x02); TS_ASSERT(pBuffer[2] == 0x03); TS_ASSERT(pBuffer[3] == 0x04); TS_ASSERT(pBuffer[4] == 0x05); TS_ASSERT(pBuffer[5] == 0x06); TS_ASSERT(pBuffer[6] == 0x07); TS_ASSERT(pBuffer[7] == 0x08); pBuffer = NULL; EHTOND(d, ui64); pBuffer = (uint8_t *) & ui64; TS_ASSERT(pBuffer[0] == 0x40); TS_ASSERT(pBuffer[1] == 0x5e); TS_ASSERT(pBuffer[2] == 0xdd); TS_ASSERT(pBuffer[3] == 0x2f); TS_ASSERT(pBuffer[4] == 0x1a); TS_ASSERT(pBuffer[5] == 0x9f); TS_ASSERT(pBuffer[6] == 0xbe); TS_ASSERT(pBuffer[7] == 0x77); //network to host pointer char buffer[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; ui16 = ENTOHSP(buffer); TS_ASSERT(ui16 == 0x0001); ui16 = ENTOHSP(buffer + 1); TS_ASSERT(ui16 == 0x0102); ui16 = ENTOHSP(buffer + 2); TS_ASSERT(ui16 == 0x0203); ui16 = ENTOHSP(buffer + 3); TS_ASSERT(ui16 == 0x0304); ui16 = ENTOHSP(buffer + 4); TS_ASSERT(ui16 == 0x0405); ui16 = ENTOHSP(buffer + 5); TS_ASSERT(ui16 == 0x0506); ui16 = ENTOHSP(buffer + 6); TS_ASSERT(ui16 == 0x0607); ui16 = ENTOHSP(buffer + 7); TS_ASSERT(ui16 == 0x0708); ui16 = ENTOHSP(buffer + 8); TS_ASSERT(ui16 == 0x0809); ui16 = ENTOHSP(buffer + 9); TS_ASSERT(ui16 == 0x090a); ui16 = ENTOHSP(buffer + 10); TS_ASSERT(ui16 == 0x0a0b); ui16 = ENTOHSP(buffer + 11); TS_ASSERT(ui16 == 0x0b0c); ui16 = ENTOHSP(buffer + 12); TS_ASSERT(ui16 == 0x0c0d); ui16 = ENTOHSP(buffer + 13); TS_ASSERT(ui16 == 0x0d0e); ui16 = ENTOHSP(buffer + 14); TS_ASSERT(ui16 == 0x0e0f); ui32 = ENTOHLP(buffer); TS_ASSERT(ui32 == 0x00010203); ui32 = ENTOHLP(buffer + 1); TS_ASSERT(ui32 == 0x01020304); ui32 = ENTOHLP(buffer + 2); TS_ASSERT(ui32 == 0x02030405); ui32 = ENTOHLP(buffer + 3); TS_ASSERT(ui32 == 0x03040506); ui32 = ENTOHLP(buffer + 4); TS_ASSERT(ui32 == 0x04050607); ui32 = ENTOHLP(buffer + 5); TS_ASSERT(ui32 == 0x05060708); ui32 = ENTOHLP(buffer + 6); TS_ASSERT(ui32 == 0x06070809); ui32 = ENTOHLP(buffer + 7); TS_ASSERT(ui32 == 0x0708090a); ui32 = ENTOHLP(buffer + 8); TS_ASSERT(ui32 == 0x08090a0b); ui32 = ENTOHLP(buffer + 9); TS_ASSERT(ui32 == 0x090a0b0c); ui32 = ENTOHLP(buffer + 10); TS_ASSERT(ui32 == 0x0a0b0c0d); ui32 = ENTOHLP(buffer + 11); TS_ASSERT(ui32 == 0x0b0c0d0e); ui32 = ENTOHLP(buffer + 12); TS_ASSERT(ui32 == 0x0c0d0e0f); ui32 = ENTOHAP(buffer); TS_ASSERT(ui32 == 0x03000102); ui32 = ENTOHAP(buffer + 1); TS_ASSERT(ui32 == 0x04010203); ui32 = ENTOHAP(buffer + 2); TS_ASSERT(ui32 == 0x05020304); ui32 = ENTOHAP(buffer + 3); TS_ASSERT(ui32 == 0x06030405); ui32 = ENTOHAP(buffer + 4); TS_ASSERT(ui32 == 0x07040506); ui32 = ENTOHAP(buffer + 5); TS_ASSERT(ui32 == 0x08050607); ui32 = ENTOHAP(buffer + 6); TS_ASSERT(ui32 == 0x09060708); ui32 = ENTOHAP(buffer + 7); TS_ASSERT(ui32 == 0x0a070809); ui32 = ENTOHAP(buffer + 8); TS_ASSERT(ui32 == 0x0b08090a); ui32 = ENTOHAP(buffer + 9); TS_ASSERT(ui32 == 0x0c090a0b); ui32 = ENTOHAP(buffer + 10); TS_ASSERT(ui32 == 0x0d0a0b0c); ui32 = ENTOHAP(buffer + 11); TS_ASSERT(ui32 == 0x0e0b0c0d); ui32 = ENTOHAP(buffer + 12); TS_ASSERT(ui32 == 0x0f0c0d0e); ui64 = ENTOHLLP(buffer); TS_ASSERT(ui64 == 0x0001020304050607LL); ui64 = ENTOHLLP(buffer + 1); TS_ASSERT(ui64 == 0x0102030405060708LL); ui64 = ENTOHLLP(buffer + 2); TS_ASSERT(ui64 == 0x0203040506070809LL); ui64 = ENTOHLLP(buffer + 3); TS_ASSERT(ui64 == 0x030405060708090aLL); ui64 = ENTOHLLP(buffer + 4); TS_ASSERT(ui64 == 0x0405060708090a0bLL); ui64 = ENTOHLLP(buffer + 5); TS_ASSERT(ui64 == 0x05060708090a0b0cLL); ui64 = ENTOHLLP(buffer + 6); TS_ASSERT(ui64 == 0x060708090a0b0c0dLL); ui64 = ENTOHLLP(buffer + 7); TS_ASSERT(ui64 == 0x0708090a0b0c0d0eLL); ui64 = ENTOHLLP(buffer + 8); TS_ASSERT(ui64 == 0x08090a0b0c0d0e0fLL); char *pTempBuffer = new char[64 + 8]; unsigned char rawDouble[] = {0x40, 0x5E, 0xDD, 0x2F, 0x1A, 0x9F, 0xBE, 0x77}; double tempDoubleVal = 0; for (int i = 0; i <= 64; i++) { memset(pTempBuffer, 0, i); memcpy(pTempBuffer + i, rawDouble, 8); memset(pTempBuffer + i + 8, 0, 64 + 8 - i - 8); ENTOHDP((pTempBuffer + i), tempDoubleVal); TS_ASSERT(d == tempDoubleVal); } delete[] pTempBuffer; //network to host #ifdef LITTLE_ENDIAN_BYTE_ALIGNED TS_ASSERT(ENTOHA(0x01040302) == 0x01020304); TS_ASSERT(ENTOHLL(0x0807060504030201LL) == 0x0102030405060708LL); ENTOHD(0x77BE9F1A2FDD5E40LL, tempDoubleVal); TS_ASSERT(d == tempDoubleVal); #endif /* LITTLE_ENDIAN_BYTE_ALIGNED */ #ifdef LITTLE_ENDIAN_SHORT_ALIGNED TS_ASSERT(ENTOHA(0x01040302) == 0x01020304); TS_ASSERT(ENTOHLL(0x0807060504030201LL) == 0x0102030405060708LL); ENTOHD(0x77BE9F1A2FDD5E40LL, tempDoubleVal); TS_ASSERT(d == tempDoubleVal); #endif /* LITTLE_ENDIAN_SHORT_ALIGNED */ #ifdef BIG_ENDIAN_BYTE_ALIGNED TS_ASSERT(ENTOHA(0x02030401) == 0x01020304); TS_ASSERT(ENTOHLL(0x0102030405060708LL) == 0x0102030405060708LL); #error ENTOHD not tested #endif /* BIG_ENDIAN_BYTE_ALIGNED */ #ifdef BIG_ENDIAN_SHORT_ALIGNED #error BIG_ENDIAN_SHORT_ALIGNED set of tests not yet implemented!!! Please take care of this first!!! #endif /* BIG_ENDIAN_SHORT_ALIGNED */ //double mirror TS_ASSERT(ENTOHS(EHTONS(0x0102)) == 0x0102); TS_ASSERT(EHTONS(ENTOHS(0x0102)) == 0x0102); TS_ASSERT(ENTOHL(EHTONL(0x01020304)) == 0x01020304); TS_ASSERT(EHTONL(ENTOHL(0x01020304)) == 0x01020304); TS_ASSERT(ENTOHLL(EHTONLL(0x0102030405060708LL)) == 0x0102030405060708LL); TS_ASSERT(EHTONLL(ENTOHLL(0x0102030405060708LL)) == 0x0102030405060708LL); //EHTOND/ENTOHD are different. Requires 2 parameters. So, no double mirror TS_ASSERT(ENTOHA(EHTONA(0x01020304)) == 0x01020304); TS_ASSERT(EHTONA(ENTOHA(0x01020304)) == 0x01020304); // Buffer Put routines for (int i = 0; i < 16; i++) { EHTONSP(buffer + i, 0x0102); TS_ASSERT(ENTOHSP(buffer + i) == 0x0102); EHTONLP(buffer + i, 0x01020304); TS_ASSERT(ENTOHLP(buffer + i) == 0x01020304); EHTONLLP(buffer + i, 0x0102030405060708LL); TS_ASSERT(ENTOHLLP(buffer + i) == 0x0102030405060708LL); EHTONDP(d, (buffer + i)); ENTOHDP(buffer + i, tempDoubleVal); TS_ASSERT(d == tempDoubleVal); } }
bool InboundRTMPProtocol::PerformHandshake(IOBuffer &buffer) { switch (_rtmpState) { case RTMP_STATE_NOT_INITIALIZED: { if (GETAVAILABLEBYTESCOUNT(buffer) < 1537) { return true; } uint8_t handshakeType = GETIBPOINTER(buffer)[0]; if (!buffer.Ignore(1)) { FATAL("Unable to ignore one byte"); return false; } _currentFPVersion = ENTOHLP(GETIBPOINTER(buffer) + 4); switch (handshakeType) { case 3: //plain { return PerformHandshake(buffer, false); } case 6: //encrypted { return PerformHandshake(buffer, true); } default: { FATAL("Handshake type not implemented: %hhu", handshakeType); return false; } } } case RTMP_STATE_SERVER_RESPONSE_SENT: { if (GETAVAILABLEBYTESCOUNT(buffer) < 1536) { return true; } else { //ignore the client's last handshake part if (!buffer.Ignore(1536)) { FATAL("Unable to ignore inbound data"); return false; } _handshakeCompleted = true; _rtmpState = RTMP_STATE_DONE; if (_pKeyIn != NULL && _pKeyOut != NULL) { //insert the RTMPE protocol in the current protocol stack BaseProtocol *pFarProtocol = GetFarProtocol(); RTMPEProtocol *pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut); ResetFarProtocol(); pFarProtocol->SetNearProtocol(pRTMPE); pRTMPE->SetNearProtocol(this); FINEST("New protocol chain: %s", STR(*pFarProtocol)); //decrypt the leftovers RC4(_pKeyIn, GETAVAILABLEBYTESCOUNT(buffer), GETIBPOINTER(buffer), GETIBPOINTER(buffer)); } return true; } } default: { FATAL("Invalid RTMP state: %d", _rtmpState); return false; } } }
bool RTCPProtocol::SignalInputData(IOBuffer &buffer, sockaddr_in *pPeerAddress) { //0. Save the last known address if (&_lastAddress != pPeerAddress) { _lastAddress = *pPeerAddress; _validLastAddress = true; } //1. Parse the SR uint8_t *pBuffer = GETIBPOINTER(buffer); uint32_t bufferLength = GETAVAILABLEBYTESCOUNT(buffer); while (bufferLength > 0) { if (bufferLength < 4) { buffer.IgnoreAll(); return true; } uint8_t PT = pBuffer[1]; uint16_t len = ENTOHSP(pBuffer + 2); len = (len + 1)*4; if (len > bufferLength) { buffer.IgnoreAll(); return true; } switch (PT) { case 200: //SR { if (len < 28) { buffer.IgnoreAll(); return true; } uint32_t ntpSec = ENTOHLP(pBuffer + 8) - 2208988800UL; uint32_t ntpFrac = ENTOHLP(pBuffer + 12); uint64_t ntpMicroseconds = (uint32_t) (((double) ntpFrac / (double) (0x100000000LL))*1000000.0); ntpMicroseconds += ((uint64_t) ntpSec)*1000000; uint32_t rtpTimestamp = ENTOHLP(pBuffer + 16); if (_pConnectivity == NULL) { FATAL("No connectivity, unable to send SR"); return false; } _pConnectivity->ReportSR(ntpMicroseconds, rtpTimestamp, _isAudio); _lsr = ENTOHLP(pBuffer + 10); if (!_pConnectivity->SendRR(_isAudio)) { FATAL("Unable to send RR"); _pConnectivity->EnqueueForDelete(); _pConnectivity = NULL; return false; } break; } case 203: //BYE { if (_pConnectivity == NULL) { FATAL("No connectivity, BYE packet ignored"); return false; } _pConnectivity->EnqueueForDelete(); _pConnectivity = NULL; break; } default: { break; } } buffer.Ignore(len); pBuffer = GETIBPOINTER(buffer); bufferLength = GETAVAILABLEBYTESCOUNT(buffer); } return true; }
bool OutboundConnectivity::FeedData(MSGHDR &message, double absoluteTimestamp, bool isAudio) { if (absoluteTimestamp == 0) { return true; } #if 0 //double rate = isAudio ? _pOutStream->GetCapabilities()->aac._sampleRate : 90000.0; double rate = 90000.0; if (isAudio) { BaseInStream *pPCMInStream = NULL; pPCMInStream = reinterpret_cast<BaseInStream*>(_pOutStream->GetStreamsManager()->FindFirstByTypeByName(ST_IN_AUDIO_PCM, QIC_STREAM_WAVE)); StreamCapabilities *pAudioCapabilities = NULL; if (pPCMInStream == NULL) { FATAL("Inbound stream %s not found", QIC_STREAM_WAVE); return false; } else { pAudioCapabilities = pPCMInStream->GetCapabilities(); if (pAudioCapabilities == NULL) { FATAL("Inbound stream capability %s not found", QIC_STREAM_WAVE); return false; } } rate = (CODEC_AUDIO_PCM == pAudioCapabilities->audioCodecId) ? pAudioCapabilities->pcm._sampleRate : _pOutStream->GetCapabilities()->aac._sampleRate; } uint32_t ssrc = isAudio ? _pOutStream->AudioSSRC() : _pOutStream->VideoSSRC(); #endif uint16_t messageLength = 0; for (uint32_t i = 0; i < (uint32_t) message.MSGHDR_MSG_IOVLEN; i++) { messageLength += (uint16_t) message.MSGHDR_MSG_IOV[i].IOVEC_IOV_LEN; } bool &hasTrack = isAudio ? _rtpClient.hasAudio : _rtpClient.hasVideo; uint32_t &packetsCount = isAudio ? _rtpClient.audioPacketsCount : _rtpClient.videoPacketsCount; uint32_t &bytesCount = isAudio ? _rtpClient.audioBytesCount : _rtpClient.videoBytesCount; uint32_t &startRTP = isAudio ? _rtpClient.audioStartRTP : _rtpClient.videoStartRTP; double &startTS = isAudio ? _rtpClient.audioStartTS : _rtpClient.videoStartTS; if (!hasTrack) { return true; } if (startRTP == 0xffffffff) { startRTP = ENTOHLP(((uint8_t *) message.MSGHDR_MSG_IOV[0].IOVEC_IOV_BASE) + 4); startTS = absoluteTimestamp; } #if 0 /* ** temporary disable it to prevent client to enable a/v sync mechanism ** because video/audio timestamp could somehow out of sync ** it could make video or audio packets been dropped due to PTS out of range */ if ((packetsCount % 500) == 0) { //FINEST("Send %c RTCP: %u", isAudio ? 'A' : 'V', packetsCount); EHTONLP(((uint8_t *) _rtcpMessage.MSGHDR_MSG_IOV[0].IOVEC_IOV_BASE) + 4, ssrc); //SSRC //NTP uint32_t integerValue = (uint32_t) (absoluteTimestamp / 1000.0); double fractionValue = (absoluteTimestamp / 1000.0 - ((uint32_t) (absoluteTimestamp / 1000.0)))*4294967296.0; uint64_t ntpVal = (_startupTime + integerValue + 2208988800ULL) << 32; ntpVal |= (uint32_t) fractionValue; EHTONLLP(_pRTCPNTP, ntpVal); //RTP uint64_t rtp = (uint64_t) (((double) (integerValue) + fractionValue / 4294967296.0) * rate); rtp &= 0xffffffff; EHTONLP(_pRTCPRTP, (uint32_t) rtp); //packet count EHTONLP(_pRTCPSPC, packetsCount); //octet count EHTONLP(_pRTCPSOC, bytesCount); // FINEST("\n%s", STR(IOBuffer::DumpBuffer(((uint8_t *) _rtcpMessage.MSGHDR_MSG_IOV[0].IOVEC_IOV_BASE), // _rtcpMessage.MSGHDR_MSG_IOV[0].IOVEC_IOV_LEN))); if (_rtpClient.isUdp) { SOCKET rtcpFd = isAudio ? _audioRTCPFd : _videoRTCPFd; sockaddr_in &rtcpAddress = isAudio ? _rtpClient.audioRtcpAddress : _rtpClient.videoRtcpAddress; _rtcpMessage.MSGHDR_MSG_NAME = (sockaddr *) & rtcpAddress; _amountSent = SENDMSG(rtcpFd, &_rtcpMessage, 0, &_dummyValue); if (_amountSent < 0) { FATAL("Unable to send message"); return false; } ADD_OUT_BYTES_MANAGED(IOHT_UDP_CARRIER, _amountSent); } else { if (_pRTSPProtocol != NULL) { if (!_pRTSPProtocol->SendRaw(&_rtcpMessage, (uint16_t) (_rtcpMessage.MSGHDR_MSG_IOV[0].IOVEC_IOV_LEN), &_rtpClient, isAudio, false)) { FATAL("Unable to send raw rtcp audio data"); return false; } } } } #endif if (_rtpClient.isUdp) { SOCKET dataFd = isAudio ? _audioDataFd : _videoDataFd; sockaddr_in &dataAddress = isAudio ? _rtpClient.audioDataAddress : _rtpClient.videoDataAddress; message.MSGHDR_MSG_NAME = (sockaddr *) & dataAddress; _amountSent = SENDMSG(dataFd, &message, 0, &_dummyValue); if (_amountSent < 0) { int err = errno; FATAL("Unable to send message: %d; %s", err, strerror(errno)); return false; } ADD_OUT_BYTES_MANAGED(IOHT_UDP_CARRIER, _amountSent); } else { if (_pRTSPProtocol != NULL) { if (!_pRTSPProtocol->SendRaw(&message, messageLength, &_rtpClient, isAudio, true)) { FATAL("Unable to send raw rtcp audio data"); return false; } } } //INFO("send rtp data pkt %d byte cout %d", packetsCount, bytesCount); packetsCount++; bytesCount += messageLength; return true; }