예제 #1
0
        private bool ParseMessage(MessageID id, byte[] payload)
        {
            switch (id)
            {
            //Parse control messages 1-7
            case MessageID.SetChunkSize:
                options.ChunkSize = ArrayUtil.BigIndianInt(payload, 0, 4);
                break;

            case MessageID.WindowAcknowledge:
                options.WindowSize = ArrayUtil.BigIndianInt(payload, 0, 4);
                break;

            // Parse commands like connect
            case MessageID.CommandAMF0:
                var command = ArrayUtil.AMF0String(payload, 0);
                switch (command.ToLower())
                {
                case "connect":
                    var cmdConnect = new CmdConnect(payload);
                    if (OnConnect != null)
                    {
                        OnConnect(this, new ConnectData(cmdConnect));
                    }
                    break;

                case "releasestream":
                    if (OnReleaseStream != null)
                    {
                        OnReleaseStream(this, new AMFCallData(payload));
                    }
                    break;

                case "fcpublish":
                    if (OnFCPublish != null)
                    {
                        OnFCPublish(this, new AMFCallData(payload));
                    }
                    break;

                case "createstream":
                    if (OnCreateStream != null)
                    {
                        OnCreateStream(this, new AMFCallData(payload));
                    }
                    break;

                case "publish":
                    if (OnPublish != null)
                    {
                        OnPublish(this, new AMFCallData(payload));
                    }
                    break;

                default:
                    return(false);
                }
                break;

            default:
                return(false);
            }
            return(true);
        }
예제 #2
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);
        }
예제 #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);
            }
        }