public override bool SignalInputData(InputStream inputStream, IPEndPoint address) { if (address != _lastAddress) { _lastAddress = address; _validLastAddress = true; } var bufferLength = inputStream.AvaliableByteCounts; var pos = inputStream.Position; //1. Parse the SR if (bufferLength < 16) return true; inputStream.Reader.ReadByte(); var PT = inputStream.Reader.ReadByte(); var len = inputStream.Reader.ReadUInt16(); len = (ushort) ((len + 1) * 4); if (len > bufferLength) { inputStream.IgnoreAll(); return true; } switch (PT) { case 200: if (len < 28) { Logger.WARN("Invalid RTCP packet length: {0}", len); inputStream.IgnoreAll(); return true; } inputStream.Reader.ReadUInt32(); var ntpSec = inputStream.Reader.ReadUInt32()- 2208988800U; var ntpFrac = inputStream.Reader.ReadUInt32(); ulong ntpMicroseconds = (ulong)((ntpFrac / (double)(0x100000000L))*1000000.0); ntpMicroseconds += ((ulong)ntpSec) * 1000000; var rtpTimestamp = inputStream.Reader.ReadUInt32(); _pConnectivity.ReportSR(ntpMicroseconds, rtpTimestamp, _isAudio); break; default: inputStream.IgnoreAll(); return true; } inputStream.Position = pos + 10; _lsr = inputStream.Reader.ReadUInt32(); inputStream.IgnoreAll(); //2. Send the RR if (_pConnectivity == null) { Logger.FATAL("no connectivity"); return false; } if (!_pConnectivity.SendRR(_isAudio)) { Logger.FATAL("Unable to send RR"); _pConnectivity.EnqueueForDelete(); _pConnectivity = null; return false; } return true; }
public override bool SignalInputData(InputStream inputStream, IPEndPoint address) { inputStream.CopyPartTo(Buffer, (int)inputStream.AvaliableByteCounts); Buffer.Position = 0; Middle.FarProtocol.IOHandler.SignalOutputData(LocalEndPoint, Buffer); return true; }
protected override bool PerformHandshake(InputStream buffer) { switch (_rtmpState) { case RTMPState.RTMP_STATE_NOT_INITIALIZED: if (buffer.AvaliableByteCounts < 1537) return true; var handshakeType = buffer.ReadByte(); var temp = new byte[4]; _currentFPVersion = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer.GetBuffer(), (int)(buffer.Position + 4))); switch (handshakeType) { case 3: //plain return PerformHandshake(buffer, false); case 6: //encrypted return PerformHandshake(buffer, true); default: Logger.FATAL("Handshake type not implemented: {0}", handshakeType); return false; } case RTMPState.RTMP_STATE_SERVER_RESPONSE_SENT: if (buffer.AvaliableByteCounts < 1537) return true; buffer.Ignore(1536); _handshakeCompleted = true; _rtmpState = RTMPState.RTMP_STATE_DONE; if (_pKeyIn != null && _pKeyOut != null) { //insert the RTMPE protocol in the current protocol stack BaseProtocol pFarProtocol = FarProtocol; var pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut); ResetFarProtocol(); pFarProtocol.NearProtocol = pRTMPE; pRTMPE.NearProtocol = this; this.Log().Info("New protocol chain: {0}", pFarProtocol); //decrypt the leftovers Utils.RC4(new BufferWithOffset(buffer), _pKeyIn, buffer.AvaliableByteCounts); } return true; default: Logger.FATAL("Invalid RTMP state: {0}", _rtmpState); return false; } return true; }
public override bool SignalInputData(InputStream inputStream, IPEndPoint address) { var reader = inputStream.Reader; var id = reader.ReadUInt32() ^ reader.ReadUInt32() ^ reader.ReadUInt32(); reader.BaseStream.Position = 4; lock (Session.OutputBuffer) { Session.Decode(reader); Session.SetEndPoint(address); Session.PacketHandler(reader); } inputStream.Recycle(true); return true; }
public override bool SignalInputData(InputStream inputStream, IPEndPoint address) { inputStream.CopyPartTo(Buffer,(int) inputStream.AvaliableByteCounts); if (!Connections.ContainsKey(address)) { Connections[address] = new Middle2ServerRTMFPProtocol { Application = Application, LocalEndPoint = address, ServerEndPoint = new IPEndPoint(IPAddress.Parse("202.109.143.196"), 19352) }; } Connections[address].EnqueueForOutbound(Buffer); return true; }
public override bool SignalInputData(InputStream inputStream, IPEndPoint address) { //inputStream.CopyDataTo(OutputBuffer, (int)inputStream.AvaliableByteCounts); //if (!Connections.ContainsKey(address)) //{ // Connections[address] = new Middle2ServerRTMFPProtocol // { // Application = Application, // LocalEndPoint = address, // Middle = this, // ServerEndPoint = new IPEndPoint(IPAddress.Parse("202.109.143.196"), 19352) // }; // Connections[address].Start(); //} //Connections[address].EnqueueForOutbound(OutputBuffer); var reader = inputStream.Reader; var id = reader.ReadUInt32() ^ reader.ReadUInt32() ^ reader.ReadUInt32(); reader.BaseStream.Position = 4; var session = id == 0 ? HandShakeSession : Sessions.ContainsKey(id) ? Sessions[id] : null; if (session == null) { Debug.WriteLine($"unknown session {id}"); FarProtocol.InputBuffer.Recycle(true); return true; } session.Decode(reader); if (!session.Checked) { session.Checked = true; var pCookieComputing = session.Peer.GetUserState<CookieComputing>(); HandShakeSession.CommitCookie(pCookieComputing.Value); } //reader.Read24(); //id = reader.ReadByte(); //Logger.Debug("{0:X}", id); session.SetEndPoint(address); lock (session.OutputBuffer) { session.PacketHandler(reader); } FarProtocol.InputBuffer.Recycle(true); return true; }
bool ValidateClient(InputStream inputBuffer) { if (_currentFPVersion == 0) { Logger.WARN("This version of player doesn't support validation"); return true; } if (ValidateClientScheme(inputBuffer, 0)) { _validationScheme = 0; return true; } if (ValidateClientScheme(inputBuffer, 1)) { _validationScheme = 1; return true; } Logger.FATAL("Unable to validate client"); return false; }
public override bool SignalInputData(InputStream inputStream, IPEndPoint address) { inputStream.IgnoreAll(); if (OutboundAddress == null) return true; if (!OutboundAddress.Address.Equals(address.Address)) { WARN("Attempt to divert traffic. DoS attack!?"); return true; } if (OutboundAddress.Port == address.Port) { INFO("The client has public endpoint: {0}:{1}",OutboundAddress.Address.ToString(),OutboundAddress.Port); } else { INFO("The client is behind firewall: {0}:{1} -> {0}:{2}", OutboundAddress.Address.ToString(), OutboundAddress.Port,address.Port); OutboundAddress.Port = address.Port; } OutboundAddress = null; return true; }
protected override bool PerformHandshake(InputStream buffer) { switch (_rtmpState) { case RTMPState.RTMP_STATE_NOT_INITIALIZED: return PerformHandshakeStage1((string)CustomParameters[Defines.CONF_PROTOCOL] == Defines.CONF_PROTOCOL_OUTBOUND_RTMPE); case RTMPState.RTMP_STATE_CLIENT_REQUEST_SENT: if (buffer.AvaliableByteCounts < 3073) return true; _usedScheme = (byte) ((string) CustomParameters[Defines.CONF_PROTOCOL] == Defines.CONF_PROTOCOL_OUTBOUND_RTMPE? 1: 0); if (!PerformHandshakeStage2(buffer, _usedScheme==1)) { Logger.FATAL("Unable to handshake"); return false; } if (!EnqueueForOutbound(OutputBuffer)) { Logger.FATAL("Unable to signal output data"); return false; } if (_pKeyIn != null && _pKeyOut != null) { var pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut, (uint)OutputBuffer.Length); ResetFarProtocol(); _farProtocol.NearProtocol = pRTMPE; pRTMPE.NearProtocol = this; this.Log().Info("New protocol chain:{0}",_farProtocol); } buffer.Ignore(3073); _handshakeCompleted = true; return true; default: Logger.FATAL("Invalid RTMP state:{0}",_rtmpState); return false; } }
protected abstract bool PerformHandshake(InputStream buffer);
private bool ProcessBytes(InputStream buffer) { while (true) { var availableBytesCount = buffer.AvaliableByteCounts; if (_selectedChannel < 0) { if (availableBytesCount < 1) return true; var temp = buffer.ReadByte(); switch (temp & 0x3f) { case 0: if (availableBytesCount < 2) { FINEST("Not enough data"); return true; } _selectedChannel = 64 + buffer.ReadByte(); GetChannel((uint)_selectedChannel).lastInHeaderType = (byte) (temp >> 6); availableBytesCount -= 2; break; case 1: FATAL("The server doesn't support channel ids bigger than 319"); return false; default: _selectedChannel = temp & 0x3f; GetChannel((uint)_selectedChannel).lastInHeaderType = (byte) (temp >> 6); availableBytesCount -= 1; break; } } if (_selectedChannel >= MAX_CHANNELS_COUNT) { FATAL("Bogus connection. Drop it like is hot"); return false; } var channel = GetChannel((uint)_selectedChannel); switch (channel.state) { case Channel.CS_HEADER: if (!channel.lastInHeader.Read((uint)_selectedChannel, channel.lastInHeaderType, buffer, availableBytesCount)) { FATAL("Unable to read header"); return false; } if (!channel.lastInHeader.ReadCompleted) return true; var ts = channel.lastInHeader.TimeStramp; switch (channel.lastInHeaderType) { case HT_FULL: channel.lastInAbsTs = ts; break; case HT_SAME_STREAM: case HT_SAME_LENGTH_AND_STREAM: channel.lastInAbsTs += ts; break; case HT_CONTINUATION: if (channel.lastInProcBytes == 0) channel.lastInAbsTs += ts; break; } channel.state = Channel.CS_PAYLOAD; goto case Channel.CS_PAYLOAD; case Channel.CS_PAYLOAD: var ml = channel.lastInHeader.MessageLength; var si = channel.lastInHeader.StreamId; var tempSize = ml - channel.lastInProcBytes; tempSize = tempSize >= _inboundChunkSize ? _inboundChunkSize : tempSize; if (tempSize > buffer.AvaliableByteCounts) return true; channel.state = Channel.CS_HEADER; _selectedChannel = -1; var msgType = channel.lastInHeader.MessageType; switch (msgType) { case RM_HEADER_MESSAGETYPE_VIDEODATA: if (si >= MAX_STREAMS_COUNT) { FATAL("The server doesn't support stream ids bigger than {0}", MAX_STREAMS_COUNT); return false; } if (_streams[si]?.Type == ST_IN_NET_RTMP) { if (!_streams[si].FeedData(buffer, tempSize, channel.lastInProcBytes, ml, channel.lastInAbsTs, false)) { FATAL("Unable to feed video"); return false; } } channel.lastInProcBytes += tempSize; if (ml == channel.lastInProcBytes)channel.lastInProcBytes = 0; buffer.Ignore(tempSize); break; case RM_HEADER_MESSAGETYPE_AUDIODATA: if (si >= MAX_STREAMS_COUNT) { FATAL("The server doesn't support stream ids bigger than {0}",MAX_STREAMS_COUNT); return false; } if (_streams[si]?.Type == ST_IN_NET_RTMP) { if (!_streams[si].FeedData(buffer, tempSize, channel.lastInProcBytes, ml, channel.lastInAbsTs, true)) { FATAL("Unable to feed video"); return false; } } channel.lastInProcBytes += tempSize; if (ml == channel.lastInProcBytes) { channel.lastInProcBytes = 0; } buffer.Ignore(tempSize); break; default: buffer.CopyPartTo(channel.inputData.BaseStream, (int)tempSize); buffer.Recycle(); channel.lastInProcBytes += tempSize; if (ml == channel.lastInProcBytes) { channel.lastInProcBytes = 0; if (_pProtocolHandler == null) { FATAL("RTMP connection no longer associated with an application"); return false; } channel.inputData.BaseStream.Position = 0; if (msgType != 0) { var messageBody = _rtmpProtocolSerializer.Deserialize(msgType, channel.inputData); bool recycleBody; if (!_pProtocolHandler.InboundMessageAvailable(this, messageBody, channel, out recycleBody)) { if (recycleBody) messageBody.Recycle(); FATAL("Unable to send rtmp message to application"); return false; } if (recycleBody) messageBody.Recycle(); _rxInvokes++; if (channel.inputData.BaseStream.Position < channel.inputData.BaseStream.Length) { FATAL("Invalid message!!! We have leftovers:{0} bytes", channel.inputData.BaseStream.Position < channel.inputData.BaseStream.Length); return false; } } channel.inputData.BaseStream.Recycle(); } break; } break; } } }
bool PerformHandshake(InputStream buffer, bool encrypted) { if (!ValidateClient(buffer)) { if (encrypted || _pProtocolHandler.ValidateHandshake) { Logger.FATAL("Unable to validate client"); return false; } else { Logger.WARN("Client not validated"); _validationScheme = 0; } } _pOutputBuffer = Utils.GenerateRandomBytes(3072); _pOutputBuffer.Write(0, (uint)DateTime.Now.SecondsFrom1970()); _pOutputBuffer.Write(0, (uint)0); var serverBytes = Encoding.ASCII.GetBytes(Defines.HTTP_HEADERS_SERVER_US); for (var i = 0; i < 10; i++) { var index = Utils.Random.Next(0, 3072 - Defines.HTTP_HEADERS_SERVER_US_LEN); Buffer.BlockCopy(serverBytes, 0, _pOutputBuffer, index, serverBytes.Length); } var _pOutputBufferWithOffset = new BufferWithOffset(_pOutputBuffer); var pInputBuffer = new BufferWithOffset(buffer); var serverDHOffset = GetDHOffset(_pOutputBufferWithOffset, _validationScheme); var clientDHOffset = GetDHOffset(pInputBuffer, _validationScheme); var dhWrapper = new DHWrapper(); var pubKeyIn = new byte[128]; Buffer.BlockCopy(buffer.GetBuffer(), (int)(buffer.Position + clientDHOffset), pubKeyIn, 0, 128); var sharedkey = dhWrapper.CreateSharedKey(pubKeyIn); var pubKeyOut = dhWrapper.PublicKey; Buffer.BlockCopy(pubKeyOut, 0, _pOutputBuffer, (int)serverDHOffset, 128); if (encrypted) { _pKeyIn = new RC4_KEY(); _pKeyOut = new RC4_KEY(); Utils.InitRC4Encryption(sharedkey, pubKeyIn, pubKeyOut, _pKeyIn, _pKeyOut); var data = new byte[1536]; Utils.RC4(data, _pKeyIn, 1536); Utils.RC4(data, _pKeyOut, 1536); } var serverDigestOffset = GetDigestOffset(_pOutputBufferWithOffset, _validationScheme); var pTempBuffer = new byte[1536 - 32]; Buffer.BlockCopy(_pOutputBuffer, 0, pTempBuffer, 0, (int)serverDigestOffset); Buffer.BlockCopy(_pOutputBuffer, (int)serverDigestOffset + 32, pTempBuffer, (int)serverDigestOffset, (int)(1536 - serverDigestOffset - 32)); var pTempHash = HMACsha256(pTempBuffer, 1536 - 32, GenuineFmsKey, 36); Buffer.BlockCopy(pTempHash, 0, _pOutputBuffer, (int)serverDigestOffset, 32); var keyChallengeIndex = GetDigestOffset(pInputBuffer, _validationScheme); pInputBuffer.Offset += (int)keyChallengeIndex; pTempHash = HMACsha256(pInputBuffer, 32, GenuineFmsKey, 68); Buffer.BlockCopy(_pOutputBuffer, 1536, pTempBuffer, 0, 1536 - 32); pTempBuffer = new HMACSHA256(pTempHash).ComputeHash(pTempBuffer, 0, 1536 - 32); Buffer.BlockCopy(pTempBuffer, 0, _pOutputBuffer, 1536 * 2 - 32, 32); OutputBuffer.WriteByte((byte)(encrypted ? 6 : 3)); OutputBuffer.Write(_pOutputBuffer, 0, 3072); buffer.Recycle(true); if (!EnqueueForOutbound(OutputBuffer)) { Logger.FATAL("Unable to signal outbound data"); return false; } _rtmpState = RTMPState.RTMP_STATE_SERVER_RESPONSE_SENT; return true; }
private bool PerformHandshakeStage2(InputStream inputBuffer, bool encrypted) { if (encrypted || _pProtocolHandler.ValidateHandshake) { if (!VerifyServer(inputBuffer)) { Logger.FATAL("Unable to verify server"); return false; } } var pBuffer = new BufferWithOffset(inputBuffer); pBuffer.Offset++; var serverDHOffset = GetDHOffset(pBuffer, _usedScheme); if (_pDHWrapper == null) { Logger.FATAL("dh wrapper not initialized"); return false; } var pubKey= new byte[128]; Buffer.BlockCopy(pBuffer.Buffer, (pBuffer.Offset + (int)serverDHOffset), pubKey, 0, 128); var secretKey = _pDHWrapper.CreateSharedKey(pubKey); if (encrypted) { _pKeyIn = new RC4_KEY(); _pKeyOut = new RC4_KEY(); var pubKeyIn = new byte[128]; Buffer.BlockCopy(pBuffer.Buffer,(int) (pBuffer.Offset+serverDHOffset),pubKeyIn,0,128); Utils.InitRC4Encryption(secretKey, pubKeyIn, _pClientPublicKey,_pKeyIn,_pKeyOut); } var serverDigestOffset = GetDigestOffset(pBuffer, _usedScheme); _pOutputBuffer = Utils.GenerateRandomBytes(1536); pBuffer.Offset += (int)serverDigestOffset; var pChallangeKey = HMACsha256(pBuffer, 32, GenuineFpKey, 62);//Hmacsha256.ComputeHash(pBuffer.Buffer, pBuffer.Offset, 32); var pDigest = new HMACSHA256(pChallangeKey).ComputeHash(_pOutputBuffer, 0, 1536 - 32); Buffer.BlockCopy(pDigest,0,_pOutputBuffer,1536-32,32); OutputBuffer.Write(_pOutputBuffer, 0, 1536); _pOutputBuffer = null; _rtmpState = RTMPState.RTMP_STATE_DONE; return true; }
private bool VerifyServer(InputStream inputBuffer) { var pBuffer = new BufferWithOffset(inputBuffer); pBuffer.Offset++; var serverDigestPos = GetDigestOffset(pBuffer, _usedScheme); var pTempBuffer = new byte[1536 - 32]; Buffer.BlockCopy(inputBuffer.GetBuffer(), pBuffer.Offset, pTempBuffer, 0, (int)serverDigestPos); Buffer.BlockCopy(inputBuffer.GetBuffer(), (int)(pBuffer.Offset+serverDigestPos + 32), pTempBuffer, (int)serverDigestPos, (int)(1536 - serverDigestPos - 32)); var pDigest = HMACsha256(pTempBuffer, 1536 - 32, GenuineFmsKey, 36); for (var i = 0; i < 32; i++) { if (pDigest[i] != pBuffer[(int) (i + serverDigestPos)]) { Logger.FATAL("Server not verified"); return false; } } pBuffer.Offset += 1536; var pChallange = HMACsha256(_pClientDigest, 32, GenuineFmsKey, 68); pDigest = new HMACSHA256(pChallange).ComputeHash(pBuffer.Buffer, pBuffer.Offset, 1536 - 32); for (var i = 0; i < 32; i++) { if (pDigest[i] != pBuffer[i + 1536 - 32]) { Logger.FATAL("Server not verified"); return false; } } return true; }
private bool ValidateClientScheme(InputStream inputBuffer, byte scheme) { var pBuffer = new BufferWithOffset(inputBuffer); var clientDigestOffset = GetDigestOffset(pBuffer, scheme); var pTempBuffer = new byte[1536 - 32]; Buffer.BlockCopy(pBuffer.Buffer, pBuffer.Offset, pTempBuffer, 0, (int)clientDigestOffset); Buffer.BlockCopy(pBuffer.Buffer, (int)(pBuffer.Offset + clientDigestOffset + 32), pTempBuffer, (int)clientDigestOffset, (int)(1536 - clientDigestOffset - 32)); var pTempHash = HMACsha256(pTempBuffer, 1536 - 32, GenuineFpKey, 30);//Hmacsha256.ComputeHash(pTempBuffer, 0, 1536 - 32); for (var i = 0; i < 32; i++) if (pBuffer[(int)(clientDigestOffset + i)] != pTempHash[i]) return false; return true; }
public override bool SignalInputData(InputStream inputStream, IPEndPoint address) { DecodedBytesCount += inputStream.AvaliableByteCounts; return _nearProtocol?.SignalInputData(inputStream, address)??false; }
public bool FeedData(uint channelId, InputStream buffer,uint length) { //1. Is the chanel number a valid chanel? if (channelId >= 4) { FATAL("Invalid chanel number: {0}", channelId); return false; } if (!_protocols.ContainsKey(channelId)) { FATAL("Invalid chanel number: {0}", channelId); return false; } _inputBuffer.IgnoreAll(); buffer.CopyPartTo(_inputBuffer,(int)length); _inputBuffer.Published = length; _inputBuffer.Position = 0; //_protocols[channelId].InputBuffer.WriteBytes(buffer); return _protocols[channelId].SignalInputData(_inputBuffer, _dummyAddress); }
public bool SetReceiveBuffer(InputStream ms, SocketAsyncEventArgs socketAsyncEventArgs) { lock (ms) { ms.SetLength(ms.Published + 4096); socketAsyncEventArgs.SetBuffer(ms.GetBuffer(), (int)ms.Published, 4096); } return true; }
public bool Read(uint channelId, byte type, InputStream buffer, uint availableBytes) { HeaderType = type; ChannelId = channelId; var reader = buffer.Reader; //var temp = hf.datac; switch (HeaderType) { case HT_FULL: IsAbsolute = true; if (availableBytes < 11) { ReadCompleted = false; return true; } TimeStramp = reader.ReadU24(); MessageLength = reader.ReadU24(); MessageType = (byte) buffer.ReadByte(); //StreamId = ((uint)buffer.ReadByte()) | ((uint)buffer.ReadByte() << 8) | ((uint)buffer.ReadByte() << 16) | ((uint)buffer.ReadByte() << 24); StreamId = reader._ReadUInt32(); if (TimeStramp == 0x00ffffff) { Skip4Bytes = true; if (availableBytes < 15) { ReadCompleted = false; return true; } TimeStramp = reader.ReadUInt32(); ReadCompleted = true; return true; } Skip4Bytes = false; ReadCompleted = true; return true; case HT_SAME_STREAM: IsAbsolute = false; if (availableBytes < 7) { ReadCompleted = false; return true; } TimeStramp = reader.ReadU24(); MessageLength = reader.ReadU24(); MessageType = (byte) buffer.ReadByte(); //buffer.Read(temp, 1, 7); //hf.datac = temp; //ts = (uint)IPAddress.NetworkToHostOrder((int)ts) & 0x00ffffff; //ml = (uint)IPAddress.NetworkToHostOrder((int)ml) >>8; if (TimeStramp == 0x00ffffff) { Skip4Bytes = true; if (availableBytes < 11) { ReadCompleted = false; return true; } TimeStramp = reader.ReadUInt32(); ReadCompleted = true; return true; } Skip4Bytes = false; ReadCompleted = true; return true; case HT_SAME_LENGTH_AND_STREAM: IsAbsolute = false; if (availableBytes < 3) { ReadCompleted = false; return true; } TimeStramp = reader.ReadU24(); //buffer.Read(temp, 1, 3); //hf.datac = temp; //ts = (uint)IPAddress.NetworkToHostOrder((int)ts) & 0x00ffffff; if (TimeStramp == 0x00ffffff) { Skip4Bytes = true; if (availableBytes < 7) { ReadCompleted = false; return true; } TimeStramp = reader.ReadUInt32(); ReadCompleted = true; return true; } Skip4Bytes = false; ReadCompleted = true; return true; case HT_CONTINUATION: IsAbsolute = false; ReadCompleted = !Skip4Bytes || availableBytes >= 4; return true; default: Logger.FATAL("Invalid header type"); return false; } }
public void Send(ClusterMessageType type, InputStream message) { Send(type, output => message.CopyDataTo(output.BaseStream)); }
//public virtual void SignalInterProtocolEvent(Variant e) => NearProtocol?.SignalInterProtocolEvent(e); public virtual bool SignalInputData(InputStream inputStream, IPEndPoint address) { Logger.WARN("This should be overridden. Protocol type is {0}", Type.TagToString()); return false; }