Recycle() public method

public Recycle ( bool force = false ) : void
force bool
return void
 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;
 }
Esempio n. 2
0
        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;
        }