示例#1
0
        public RTMPEndpoint(TCPSocket socket)
        {
            previousPacket = null;
            Socket = socket;
            Version = versionNumber;
            currentData = emptyArray;
            Socket.OnDataReceived += OnData;
            CurrentState = RTMPState.Unitialized;

            options = new RTMPEndpointOptions();
        }
示例#2
0
        public RTMPEndpoint(TCPSocket socket)
        {
            previousPacket         = null;
            Socket                 = socket;
            Version                = versionNumber;
            currentData            = emptyArray;
            Socket.OnDataReceived += OnData;
            CurrentState           = RTMPState.Unitialized;

            options = new RTMPEndpointOptions();
        }
示例#3
0
        public bool InitWith( byte[] data, RTMPPacket previousPacket = null)
        {
            if (data == null)
                throw new Exception("Can't create packet with null payload");

            var dataLength = data.Length;
            if (dataLength < 1 )
                return false;

            RawLength = 0;

            switch (Type)
            {
                case PacketType.VersionNumber:
                    {
                        RawData = new byte[1] { data[0] }; //RTMP protocol version. Normally == 3
                        RawLength = 1;
                    }
                    break;
                case PacketType.Handshake:
                    {
                        if (dataLength < handshakeLength)
                            return false;

                        if (dataLength == handshakeLength)
                        {
                            RawData = data;
                        }
                        else
                        {
                            RawData = new byte[handshakeLength];  //First 8 bytes should be timestamp[4] & zero[4] by Adobe's specs. It seems XSplit doesn't care about specs. So do I :D
                            Buffer.BlockCopy(data, 0, RawData, 0, handshakeLength);
                        }
                        RawLength = handshakeLength;
                    }
                    break;
                case PacketType.Chunk:
                    {
                        // Fill message/basic header lengths and Chunk Type
                        ParseChunkType(data[0]);

                        var chunkLength = BasicHeaderLength + MessageHeaderLength;
                        // Incomplete packet ?
                        if (dataLength < chunkLength)
                            return false;

                        if (ChunkType == rtmpproxy.ChunkType.Undefined)
                            throw new Exception("Packet with unknown RTMP header received!");

                        switch( ChunkType )
                        {
                            // If header is empty - init this packet with properties from the previous packet
                            case rtmpproxy.ChunkType.Header0:
                            {
                                if (previousPacket == null)
                                    throw new Exception("Can't calculate RTMP chunk length. Previous packet is null");

                                MessageLength = previousPacket.MessageLength;
                                ChunkStreamId = previousPacket.ChunkStreamId;
                            }
                            break;
                            default:
                            {
                                RawBasicHeader = ArrayUtil.Mid(data, 0, BasicHeaderLength);
                                RawMessageHeader = ArrayUtil.Mid(data, BasicHeaderLength, MessageHeaderLength);

                                ParseBasicHeader();
                                ParseMessageHeader();

                                if (ExtendedTimestamp >= 0x00ffffff)
                                {
                                    RawExtendedTimeStamp = ArrayUtil.Mid(data, BasicHeaderLength + MessageHeaderLength, 4);
                                    ExtendedTimeStampLength = 4;
                                }
                                else
                                {
                                    ExtendedTimeStampLength = 0;
                                }
                                chunkLength += (ExtendedTimeStampLength + MessageLength);
                                if (chunkLength <= dataLength)
                                {
                                    RawLength = chunkLength;
                                    RawData = new byte[RawLength];
                                    Buffer.BlockCopy(data, 0, RawData, 0, RawLength);

                                    MessageData = new byte[MessageLength];
                                    Buffer.BlockCopy(data, RawLength - MessageLength, MessageData, 0, MessageLength);
                                }
                            }
                            break;
                        }
                    }
                    break;
            }

            if (RawLength > 0)
                return true;
            else
                return false;
        }
示例#4
0
        private int ParseReceivedData()
        {
            if (currentData.Length <= 0)
                return 0;

            RTMPPacket packet = new RTMPPacket(PacketType.Unknown);

            switch (CurrentState)
            {

                case RTMPState.Unitialized:
                    {
                        packet = new RTMPPacket(PacketType.VersionNumber);
                        if (packet.InitWith(currentData))
                            CurrentState = RTMPState.VersionReceived;
                    }
                    break;
                case RTMPState.VersionReceived:
                    {
                        packet = new RTMPPacket(PacketType.Handshake);
                        if (packet.InitWith(currentData))
                        {
                            var sendData = ArrayUtil.ConcatArrays(new byte[1]{versionNumber},packet.RawData);
                            sendData = ArrayUtil.ConcatArrays(sendData,packet.RawData);
                            Socket.Send(sendData);
                            CurrentState = RTMPState.VersionSent;
                        }
                    }
                    break;
                case RTMPState.VersionSent:
                    packet = new RTMPPacket(PacketType.Handshake);
                    if (packet.InitWith(currentData))
                    {
                        CurrentState = RTMPState.HandshakeDone;
                    }
                    break;
                case RTMPState.HandshakeDone:
                    {
                        if (previousPacket == null)
                        {
                            previousPacket = new RTMPPacket(PacketType.Chunk);
                            if( !previousPacket.InitWith(currentData) )
                                return 0;
                            packet = previousPacket;
                        }
                        else
                        {
                            packet = new RTMPPacket(PacketType.Chunk);
                            if (!packet.InitWith(currentData, previousPacket))
                                return 0;
                            else
                                previousPacket = packet;

                        }
                        if (packet.MessageLength > 0 && packet.MessageLength < packet.MessageData.Length)
                            return 0;

                        Debug.Print(String.Format("Received RTMP chunk {0} bytes, Msg Id: {1} : {2}", packet.RawData.Length, packet.MessageTypeId, BitConverter.ToString(packet.RawData)));
                        Debug.Print(String.Format("Chunk payload: {0}", BitConverter.ToString(packet.MessageData)));

                        var msgID = packet.MessageTypeId;
                        if (!ParseMessage((MessageID)msgID, packet.MessageData))
                                Debug.Print("Failed to parse control message");
                    }
                    break;
                default:

                    break;
            }
            return packet.RawLength;
        }
示例#5
0
        private int ParseReceivedData()
        {
            if (currentData.Length <= 0)
            {
                return(0);
            }

            RTMPPacket packet = new RTMPPacket(PacketType.Unknown);

            switch (CurrentState)
            {
            case RTMPState.Unitialized:
            {
                packet = new RTMPPacket(PacketType.VersionNumber);
                if (packet.InitWith(currentData))
                {
                    CurrentState = RTMPState.VersionReceived;
                }
            }
            break;

            case RTMPState.VersionReceived:
            {
                packet = new RTMPPacket(PacketType.Handshake);
                if (packet.InitWith(currentData))
                {
                    var sendData = ArrayUtil.ConcatArrays(new byte[1] {
                            versionNumber
                        }, packet.RawData);
                    sendData = ArrayUtil.ConcatArrays(sendData, packet.RawData);
                    Socket.Send(sendData);
                    CurrentState = RTMPState.VersionSent;
                }
            }
            break;

            case RTMPState.VersionSent:
                packet = new RTMPPacket(PacketType.Handshake);
                if (packet.InitWith(currentData))
                {
                    CurrentState = RTMPState.HandshakeDone;
                }
                break;

            case RTMPState.HandshakeDone:
            {
                if (previousPacket == null)
                {
                    previousPacket = new RTMPPacket(PacketType.Chunk);
                    if (!previousPacket.InitWith(currentData))
                    {
                        return(0);
                    }
                    packet = previousPacket;
                }
                else
                {
                    packet = new RTMPPacket(PacketType.Chunk);
                    if (!packet.InitWith(currentData, previousPacket))
                    {
                        return(0);
                    }
                    else
                    {
                        previousPacket = packet;
                    }
                }
                if (packet.MessageLength > 0 && packet.MessageLength < packet.MessageData.Length)
                {
                    return(0);
                }

                Debug.Print(String.Format("Received RTMP chunk {0} bytes, Msg Id: {1} : {2}", packet.RawData.Length, packet.MessageTypeId, BitConverter.ToString(packet.RawData)));
                Debug.Print(String.Format("Chunk payload: {0}", BitConverter.ToString(packet.MessageData)));

                var msgID = packet.MessageTypeId;
                if (!ParseMessage((MessageID)msgID, packet.MessageData))
                {
                    Debug.Print("Failed to parse control message");
                }
            }
            break;

            default:

                break;
            }
            return(packet.RawLength);
        }
示例#6
0
        public bool InitWith(byte[] data, RTMPPacket previousPacket = null)
        {
            if (data == null)
            {
                throw new Exception("Can't create packet with null payload");
            }

            var dataLength = data.Length;

            if (dataLength < 1)
            {
                return(false);
            }

            RawLength = 0;

            switch (Type)
            {
            case PacketType.VersionNumber:
            {
                RawData = new byte[1] {
                    data[0]
                };                                         //RTMP protocol version. Normally == 3
                RawLength = 1;
            }
            break;

            case PacketType.Handshake:
            {
                if (dataLength < handshakeLength)
                {
                    return(false);
                }

                if (dataLength == handshakeLength)
                {
                    RawData = data;
                }
                else
                {
                    RawData = new byte[handshakeLength];          //First 8 bytes should be timestamp[4] & zero[4] by Adobe's specs. It seems XSplit doesn't care about specs. So do I :D
                    Buffer.BlockCopy(data, 0, RawData, 0, handshakeLength);
                }
                RawLength = handshakeLength;
            }
            break;

            case PacketType.Chunk:
            {
                // Fill message/basic header lengths and Chunk Type
                ParseChunkType(data[0]);

                var chunkLength = BasicHeaderLength + MessageHeaderLength;
                // Incomplete packet ?
                if (dataLength < chunkLength)
                {
                    return(false);
                }

                if (ChunkType == rtmpproxy.ChunkType.Undefined)
                {
                    throw new Exception("Packet with unknown RTMP header received!");
                }

                switch (ChunkType)
                {
                // If header is empty - init this packet with properties from the previous packet
                case rtmpproxy.ChunkType.Header0:
                {
                    if (previousPacket == null)
                    {
                        throw new Exception("Can't calculate RTMP chunk length. Previous packet is null");
                    }

                    MessageLength = previousPacket.MessageLength;
                    ChunkStreamId = previousPacket.ChunkStreamId;
                }
                break;

                default:
                {
                    RawBasicHeader   = ArrayUtil.Mid(data, 0, BasicHeaderLength);
                    RawMessageHeader = ArrayUtil.Mid(data, BasicHeaderLength, MessageHeaderLength);

                    ParseBasicHeader();
                    ParseMessageHeader();

                    if (ExtendedTimestamp >= 0x00ffffff)
                    {
                        RawExtendedTimeStamp    = ArrayUtil.Mid(data, BasicHeaderLength + MessageHeaderLength, 4);
                        ExtendedTimeStampLength = 4;
                    }
                    else
                    {
                        ExtendedTimeStampLength = 0;
                    }
                    chunkLength += (ExtendedTimeStampLength + MessageLength);
                    if (chunkLength <= dataLength)
                    {
                        RawLength = chunkLength;
                        RawData   = new byte[RawLength];
                        Buffer.BlockCopy(data, 0, RawData, 0, RawLength);

                        MessageData = new byte[MessageLength];
                        Buffer.BlockCopy(data, RawLength - MessageLength, MessageData, 0, MessageLength);
                    }
                }
                break;
                }
            }
            break;
            }

            if (RawLength > 0)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }