bool OutboundRTMPProtocol::PerformHandshake(IOBuffer &buffer) {
	switch (_rtmpState) {
		case RTMP_STATE_NOT_INITIALIZED:
		{
			_encrypted = (VariantType) _customParameters[CONF_PROTOCOL] == V_STRING &&
					_customParameters[CONF_PROTOCOL] == CONF_PROTOCOL_OUTBOUND_RTMPE;
			_usedScheme = _encrypted ? 1 : 0;

			if ((VariantType) _customParameters[CONF_PROTOCOL] == V_STRING &&
					_customParameters[CONF_PROTOCOL] == CONF_PROTOCOL_OUTBOUND_RTMPE) {
				return PerformHandshakeStage1(true);
			} else {
				return PerformHandshakeStage1(false);
			}
		}
		case RTMP_STATE_CLIENT_REQUEST_SENT:
		{
			if (GETAVAILABLEBYTESCOUNT(buffer) < 3073)
				return true;

			if (!PerformHandshakeStage2(buffer, _encrypted)) {
				FATAL("Unable to handshake");
				return false;
			}

			if (_pFarProtocol != NULL) {
				if (!_pFarProtocol->EnqueueForOutbound()) {
					FATAL("Unable to signal output data");
					return false;
				}
			}

			if (_pKeyIn != NULL && _pKeyOut != NULL) {
				//insert the RTMPE protocol in the current protocol stack
				BaseProtocol *pFarProtocol = GetFarProtocol();
				RTMPEProtocol *pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut,
						GETAVAILABLEBYTESCOUNT(_outputBuffer));
				ResetFarProtocol();
				pFarProtocol->SetNearProtocol(pRTMPE);
				pRTMPE->SetNearProtocol(this);
				//FINEST("New protocol chain: %s", STR(*pFarProtocol));
			}

			if (!buffer.Ignore(3073)) {
				FATAL("Unable to ignore 3073 bytes");
				return false;
			}
			_handshakeCompleted = true;
			return true;
		}
		default:
		{
			FATAL("Invalid RTMP state: %d", _rtmpState);
			return false;
		}
	}
}
Exemplo n.º 2
0
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;
		}
	}
}