bool InboundMJPGHTTPStreamProtocol::PutData(uint8_t *pBuffer, uint32_t length) {
  int obuflen = 0;
	if (!_headersSent) {
		_outputBuffer.ReadFromString("HTTP/1.0 200 OK\r\n");
		_outputBuffer.ReadFromString(HTTP_HEADERS_SERVER": "HTTP_HEADERS_SERVER_US"\r\n");
		_outputBuffer.ReadFromString(HTTP_HEADERS_X_POWERED_BY": "HTTP_HEADERS_X_POWERED_BY_US"\r\n");
    _outputBuffer.ReadFromString("Connection: close\r\n");
		_outputBuffer.ReadFromString("Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n");
		_outputBuffer.ReadFromString("Pragma: no-cache\r\n");
		_outputBuffer.ReadFromString("Expires: Mon, 3 Jan 2000 00:00:00 GMT\r\n");
		_outputBuffer.ReadFromString("Content-Type: multipart/x-mixed-replace;boundary="BOUNDARY"\r\n");
    _outputBuffer.ReadFromString("\r\n");
    _outputBuffer.ReadFromString("--"BOUNDARY"\r\n");
    EnqueueForOutbound();
		_headersSent = true;
	}
  obuflen = GETAVAILABLEBYTESCOUNT(_outputBuffer);
  if(obuflen > MAX_OUTPUT_BUFFER_SIZE){
    FATAL("output congestion! drop frame now %d", obuflen);
    _outputBuffer.IgnoreAll();
  }
	_outputBuffer.ReadFromString("Content-Type: image/jpeg\r\n");
	_outputBuffer.ReadFromString(format("Content-Length: %d\r\n", length));
  _outputBuffer.ReadFromString("\r\n");
	_outputBuffer.ReadFromBuffer(pBuffer, length);
  _outputBuffer.ReadFromString("\r\n--"BOUNDARY"\r\n");
  return EnqueueForOutbound();
}
示例#2
0
bool OutboundSSLProtocol::DoHandshake() {
    if (_sslHandshakeCompleted)
        return true;
    int32_t errorCode = SSL_ERROR_NONE;
    errorCode = SSL_connect(_pSSL);
    if (errorCode < 0) {
        int32_t error = SSL_get_error(_pSSL, errorCode);
        if (error != SSL_ERROR_WANT_READ &&
                error != SSL_ERROR_WANT_WRITE) {
            FATAL("Unable to connect SSL: %d; %s", error, STR(GetSSLErrors()));
            return false;
        }
    }

    _sslHandshakeCompleted = SSL_is_init_finished(_pSSL);

    if (!PerformIO()) {
        FATAL("Unable to perform I/O");
        return false;
    }

    if (_sslHandshakeCompleted)
        return EnqueueForOutbound();

    return true;
}
bool InboundMJPGHTTPStreamProtocol::Send404NotFound() {
	_outputBuffer.ReadFromString("HTTP/1.0 404 Not found\r\n");
	_outputBuffer.ReadFromString(HTTP_HEADERS_SERVER": "HTTP_HEADERS_SERVER_US"\r\n");
	_outputBuffer.ReadFromString(HTTP_HEADERS_X_POWERED_BY": "HTTP_HEADERS_X_POWERED_BY_US"\r\n\r\n");
	if (!EnqueueForOutbound()) {
		FATAL("Unable to enqueue for outbound");
		return false;
	}
	GracefullyEnqueueForDelete();
	return true;
}
bool InboundJSONCLIProtocol::SendMessage(Variant &message) {
	string json;
	if (!message.SerializeToJSON(json)) {
		FATAL("Unable to serialize to JSON");
		return false;
	}
	json += "\r\n";
	if (_useLengthPadding) {
		uint32_t size = EHTONL((uint32_t) json.length());
		_outputBuffer.ReadFromBuffer((uint8_t *) & size, 4);
	}
	_outputBuffer.ReadFromString(json);
	return EnqueueForOutbound();
}
示例#5
0
bool InboundXMLCLIProtocol::SendMessage(Variant &message) {
  string xml;
#if (defined(HAS_TINYXML))
  if (!message.SerializeToXml(xml, true)) {
    FATAL("Unable to serialize to XML");
    return false;
  }

  xml += "\r\n\r\n";
  if (_useLengthPadding) {
    uint32_t size = EHTONL((uint32_t) xml.length());
    _outputBuffer.ReadFromBuffer((uint8_t *) & size, 4);
  }
  _outputBuffer.ReadFromString(xml);
  return EnqueueForOutbound();
#else
  FATAL("Unable to serialize to XML, must enable tinyXML");
  return false;
#endif
}
bool InboundRTMPProtocol::PerformSimpleHandshake(IOBuffer &buffer) {
	if (_pOutputBuffer == NULL) {
		_pOutputBuffer = new uint8_t[1536];
	} else {
		delete[] _pOutputBuffer;
		_pOutputBuffer = new uint8_t[1536];
	}

	for (uint32_t i = 0; i < 1536; i++) {
		_pOutputBuffer[i] = rand() % 256;
	}
	for (uint32_t i = 0; i < 10; i++) {
		uint32_t index = (rand() + 8) % (1536 - HTTP_HEADERS_SERVER_US_LEN);
		memcpy(_pOutputBuffer + index, HTTP_HEADERS_SERVER_US, HTTP_HEADERS_SERVER_US_LEN);
	}

	_outputBuffer.ReadFromByte(3);
	_outputBuffer.ReadFromBuffer(_pOutputBuffer, 1536);
	_outputBuffer.ReadFromBuffer(GETIBPOINTER(buffer), 1536);

	//final cleanup
	delete[] _pOutputBuffer;
	_pOutputBuffer = NULL;
	if (!buffer.Ignore(1536)) {
		FATAL("Unable to ignore input buffer");
		return false;
	}

	//signal outbound data
	if (!EnqueueForOutbound()) {
		FATAL("Unable to signal outbound data");
		return false;
	}

	//move to the next stage in the handshake
	_rtmpState = RTMP_STATE_SERVER_RESPONSE_SENT;

	return true;
}
bool InboundMJPGHTTPStreamProtocol::SendCrossDomain() {
	if (!fileExists(_crossDomainFile)) {
		FATAL("cross domain file %s not found", STR(_crossDomainFile));
		return Send404NotFound();
	}
	File cd;
	if (!cd.Initialize(_crossDomainFile, FILE_OPEN_MODE_READ)) {
		FATAL("cross domain file %s could not be read", STR(_crossDomainFile));
		return Send404NotFound();
	}
	_outputBuffer.ReadFromString("HTTP/1.0 200 OK\r\n");
	_outputBuffer.ReadFromString(HTTP_HEADERS_SERVER": "HTTP_HEADERS_SERVER_US"\r\n");
	_outputBuffer.ReadFromString(HTTP_HEADERS_X_POWERED_BY": "HTTP_HEADERS_X_POWERED_BY_US"\r\n");
	_outputBuffer.ReadFromString(HTTP_HEADERS_CONTENT_TYPE": text/xml\r\n");
	_outputBuffer.ReadFromString(format("%s: %"PRIu64"\r\n\r\n", HTTP_HEADERS_CONTENT_LENGTH, cd.Size()));
	_outputBuffer.ReadFromFs(cd, cd.Size());
	//FINEST("_outputBuffer:\n%s", STR(_outputBuffer));
	if (!EnqueueForOutbound()) {
		FATAL("Unable to enqueue for outbound");
		return false;
	}
	GracefullyEnqueueForDelete();
	return true;
}
示例#8
0
bool BaseVariantProtocol::Send(Variant &variant) {
	//1. Do we have a protocol?
	if (_pFarProtocol == NULL) {
		FATAL("This protocol is not linked");
		return false;
	}

	//2. Save the variant
	_lastSent = variant;

	//3. Depending on the far protocol, we do different stuff
	string rawContent = "";
	switch (_pFarProtocol->GetType()) {
		case PT_TCP:
		{
			//5. Serialize it
			if (!Serialize(rawContent, variant)) {
				FATAL("Unable to serialize variant");
				return false;
			}

			_outputBuffer.ReadFromRepeat(0, 4);
			uint32_t rawContentSize = rawContent.size();
			EHTONLP(GETIBPOINTER(_outputBuffer), rawContentSize);
			_outputBuffer.ReadFromString(rawContent);

			//6. enqueue for outbound
			if (!EnqueueForOutbound()) {
				FATAL("Unable to enqueue for outbound");
				return false;
			}
			GracefullyEnqueueForDelete();
			return true;
		}
		case PT_OUTBOUND_HTTP:
		{
#ifdef HAS_PROTOCOL_HTTP
			//7. This is a HTTP request. So, first things first: get the http protocol
			OutboundHTTPProtocol *pHTTP = (OutboundHTTPProtocol *) _pFarProtocol;

			//8. We wish to disconnect after the transfer is complete
			pHTTP->SetDisconnectAfterTransfer(true);

			//9. This will always be a POST
			pHTTP->Method(HTTP_METHOD_POST);

			//10. Our document and the host
			pHTTP->Document(variant["document"]);
			pHTTP->Host(variant["host"]);

			//11. Serialize it
			if (!Serialize(rawContent, variant["payload"])) {
				FATAL("Unable to serialize variant");
				return false;
			}

			_outputBuffer.ReadFromString(rawContent);

			//12. enqueue for outbound
			return EnqueueForOutbound();
#else
			FATAL("HTTP protocol not supported");
			return false;
#endif /* HAS_PROTOCOL_HTTP */
		}
		case PT_INBOUND_HTTP:
		{
#ifdef HAS_PROTOCOL_HTTP
			if (!Serialize(rawContent, variant)) {
				FATAL("Unable to serialize variant");
				return false;
			}

			_outputBuffer.ReadFromString(rawContent);

			return EnqueueForOutbound();
#else
			FATAL("HTTP protocol not supported");
			return false;
#endif /* HAS_PROTOCOL_HTTP */
		}
		default:
		{
			ASSERT("We should not be here");
			return false;
		}
	}
}
bool InboundRTMPProtocol::PerformComplexHandshake(IOBuffer &buffer, bool encrypted) {
	//get the buffers
	uint8_t *pInputBuffer = GETIBPOINTER(buffer);
	if (_pOutputBuffer == NULL) {
		_pOutputBuffer = new uint8_t[3072];
	} else {
		delete[] _pOutputBuffer;
		_pOutputBuffer = new uint8_t[3072];
	}

	//timestamp
	EHTONLP(_pOutputBuffer, (uint32_t) time(NULL));

	//version
	EHTONLP(_pOutputBuffer + 4, (uint32_t) 0x00000000);

	//generate random data
	for (uint32_t i = 8; i < 3072; i++) {
		_pOutputBuffer[i] = rand() % 256;
	}
	for (uint32_t i = 0; i < 10; i++) {
		uint32_t index = rand() % (3072 - HTTP_HEADERS_SERVER_US_LEN);
		memcpy(_pOutputBuffer + index, HTTP_HEADERS_SERVER_US, HTTP_HEADERS_SERVER_US_LEN);
	}

	//**** FIRST 1536 bytes from server response ****//
	//compute DH key position
	uint32_t serverDHOffset = GetDHOffset(_pOutputBuffer, _handshakeScheme);
	uint32_t clientDHOffset = GetDHOffset(pInputBuffer, _handshakeScheme);

	//generate DH key
	DHWrapper dhWrapper(1024);

	if (!dhWrapper.Initialize()) {
		FATAL("Unable to initialize DH wrapper");
		return false;
	}

	if (!dhWrapper.CreateSharedKey(pInputBuffer + clientDHOffset, 128)) {
		FATAL("Unable to create shared key");
		return false;
	}

	if (!dhWrapper.CopyPublicKey(_pOutputBuffer + serverDHOffset, 128)) {
		FATAL("Couldn't write public key!");
		return false;
	}

	if (encrypted) {
		uint8_t secretKey[128];
		if (!dhWrapper.CopySharedKey(secretKey, sizeof (secretKey))) {
			FATAL("Unable to copy shared key");
			return false;
		}

		_pKeyIn = new RC4_KEY;
		_pKeyOut = new RC4_KEY;
		InitRC4Encryption(
				secretKey,
				(uint8_t*) & pInputBuffer[clientDHOffset],
				(uint8_t*) & _pOutputBuffer[serverDHOffset],
				_pKeyIn,
				_pKeyOut);

		//bring the keys to correct cursor
		uint8_t data[1536];
		RC4(_pKeyIn, 1536, data, data);
		RC4(_pKeyOut, 1536, data, data);
	}

	//generate the digest
	uint32_t serverDigestOffset = GetDigestOffset(_pOutputBuffer, _handshakeScheme);

	uint8_t *pTempBuffer = new uint8_t[1536 - 32];
	memcpy(pTempBuffer, _pOutputBuffer, serverDigestOffset);
	memcpy(pTempBuffer + serverDigestOffset, _pOutputBuffer + serverDigestOffset + 32,
			1536 - serverDigestOffset - 32);

	uint8_t *pTempHash = new uint8_t[512];
	HMACsha256(pTempBuffer, 1536 - 32, genuineFMSKey, 36, pTempHash);

	//put the digest in place
	memcpy(_pOutputBuffer + serverDigestOffset, pTempHash, 32);

	//cleanup
	delete[] pTempBuffer;
	delete[] pTempHash;


	//**** SECOND 1536 bytes from server response ****//
	//Compute the chalange index from the initial client request
	uint32_t keyChallengeIndex = GetDigestOffset(pInputBuffer, _handshakeScheme);

	//compute the key
	pTempHash = new uint8_t[512];
	HMACsha256(pInputBuffer + keyChallengeIndex, //pData
			32, //dataLength
			BaseRTMPProtocol::genuineFMSKey, //key
			68, //keyLength
			pTempHash //pResult
			);

	//generate the hash
	uint8_t *pLastHash = new uint8_t[512];
	HMACsha256(_pOutputBuffer + 1536, //pData
			1536 - 32, //dataLength
			pTempHash, //key
			32, //keyLength
			pLastHash //pResult
			);

	//put the hash where it belongs
	memcpy(_pOutputBuffer + 1536 * 2 - 32, pLastHash, 32);


	//cleanup
	delete[] pTempHash;
	delete[] pLastHash;
	//***** DONE BUILDING THE RESPONSE ***//


	//wire the response
	if (encrypted)
		_outputBuffer.ReadFromByte(6);
	else
		_outputBuffer.ReadFromByte(3);
	_outputBuffer.ReadFromBuffer(_pOutputBuffer, 3072);

	//final cleanup
	delete[] _pOutputBuffer;
	_pOutputBuffer = NULL;
	if (!buffer.IgnoreAll()) {
		FATAL("Unable to ignore input buffer");
		return false;
	}

	//signal outbound data
	if (!EnqueueForOutbound()) {
		FATAL("Unable to signal outbound data");
		return false;
	}

	//move to the next stage in the handshake
	_rtmpState = RTMP_STATE_SERVER_RESPONSE_SENT;

	return true;
}