Пример #1
0
        public void Queue(RtmpEvent message, int streamId, int messageStreamId)
        {
            var header = new RtmpHeader();
            var packet = new RtmpPacket(header, message);

            header.StreamId        = 0;
            header.Timestamp       = message.Timestamp;
            header.MessageStreamId = messageStreamId;
            header.MessageType     = message.MessageType;
            queuedPackets.Enqueue(packet);
            packetAvailableEvent.Set();
        }
Пример #2
0
        private RtmpEvent ParsePacket(RtmpPacket packet, Func <AmfReader, RtmpEvent> handler)
        {
            AmfReader  amfReader  = new AmfReader((Stream) new MemoryStream(packet.Buffer, false), this._reader.SerializationContext);
            RtmpHeader header     = packet.Header;
            RtmpEvent  rtmpEvent  = handler(amfReader);
            RtmpHeader rtmpHeader = header;

            rtmpEvent.Header = rtmpHeader;
            int timestamp = header.Timestamp;

            rtmpEvent.Timestamp = timestamp;
            return(rtmpEvent);
        }
Пример #3
0
        private void WriteData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding)
        {
            Command command = o as Command;

            if (command.MethodCall == null)
            {
                this.WriteCommandOrData(writer, o, encoding);
            }
            else
            {
                writer.WriteBytes(command.Buffer);
            }
        }
Пример #4
0
        byte[] GetMessageBytes(FlvTagHeader header, RtmpEvent message)
        {
            switch (header.TagType)
            {
            case MessageType.Audio:
            case MessageType.Video:
                return(GetMessageBytes(message, (w, o) => w.WriteBytes(((ByteData)o).Data)));

            case MessageType.DataAmf0:
                return(GetMessageBytes(message, (w, o) => WriteCommandOrData(w, o, ObjectEncoding.Amf0)));

            default:
                throw new ArgumentOutOfRangeException("Unknown RTMP message type: " + (int)header.TagType);
            }
        }
Пример #5
0
        public void Queue(RtmpEvent message, int streamId, int messageStreamId)
        {
            RtmpHeader header     = new RtmpHeader();
            RtmpPacket rtmpPacket = new RtmpPacket(header, message);

            header.StreamId        = streamId;
            header.Timestamp       = message.Timestamp;
            header.MessageStreamId = messageStreamId;
            header.MessageType     = message.MessageType;
            if (message.Header != null)
            {
                header.IsTimerRelative = message.Header.IsTimerRelative;
            }
            this._queuedPackets.Enqueue(rtmpPacket);
            this._packetAvailableEvent.Set();
        }
Пример #6
0
        private void WriteCommandOrData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding)
        {
            var command    = o as Command;
            var methodCall = command.MethodCall;
            var isInvoke   = command is Invoke;

            // write the method name or result type (first section)
            var isRequest = methodCall.CallStatus == CallStatus.Request;
            var isResult  = methodCall.CallStatus == CallStatus.Result;

            if (isRequest)
            {
                writer.WriteAmfItem(ObjectEncoding.Amf0, methodCall.Name);
            }
            else
            {
                writer.WriteAmfItem(ObjectEncoding.Amf0, methodCall.IsSuccess ? "_result" : "_error");
            }

            if (isInvoke)
            {
                writer.WriteAmfItem(ObjectEncoding.Amf0, command.InvokeId);
                writer.WriteAmfItem(encoding, command.ConnectionParameters);
            }

            if (isRequest || isResult)
            {
                // write arguments
                foreach (var arg in methodCall.Parameters)
                {
                    writer.WriteAmfItem(encoding, arg);
                }
            }
            else if (isInvoke)
            {
                // write the result
                if (!methodCall.IsSuccess)
                {
                    methodCall.Parameters = new object[]
                    { new StatusAsObject(StatusCode.CallFailed, "error", "Call failed.") }
                }
                ;
                writer.WriteAmfItem(encoding, methodCall.Parameters);
            }
        }
    }
Пример #7
0
        private void WriteCommandOrData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding)
        {
            Command command    = o as Command;
            Method  methodCall = command.MethodCall;
            bool    flag1      = command is Invoke;
            bool    flag2      = methodCall.CallStatus == CallStatus.Request;
            bool    flag3      = methodCall.CallStatus == CallStatus.Result;

            if (flag2)
            {
                writer.WriteAmfItem(ObjectEncoding.Amf0, (object)methodCall.Name);
            }
            else
            {
                writer.WriteAmfItem(ObjectEncoding.Amf0, methodCall.IsSuccess ? (object)"_result" : (object)"_error");
            }
            if (flag1)
            {
                writer.WriteAmfItem(ObjectEncoding.Amf0, (object)command.InvokeId);
                writer.WriteAmfItem(encoding, command.ConnectionParameters);
            }
            if (flag2 | flag3)
            {
                foreach (object parameter in methodCall.Parameters)
                {
                    writer.WriteAmfItem(encoding, parameter);
                }
            }
            else
            {
                if (!flag1)
                {
                    return;
                }
                if (!methodCall.IsSuccess)
                {
                    methodCall.Parameters = new object[1]
                    {
                        (object)new StatusAsObject("NetConnection.Call.Failed", "error", "Call failed.")
                    }
                }
                ;
                writer.WriteAmfItem(encoding, (object)methodCall.Parameters);
            }
        }
    }
        public void Queue(RtmpEvent message, int streamId, int messageStreamId)
        {
            var header = new RtmpHeader();
            var packet = new RtmpPacket(header, message);

            header.StreamId        = streamId;
            header.Timestamp       = message.Timestamp;
            header.MessageStreamId = messageStreamId;
            header.MessageType     = message.MessageType;
            if (message.Header != null)
            {
                header.IsTimerRelative = message.Header.IsTimerRelative;
            }
            queuedPackets.Enqueue(packet);
            // packetAvailableEvent.Set();
            Interlocked.Exchange(ref packetAvailable, 1);
        }
Пример #9
0
        void WriteCommandOrData(AmfWriter writer, RtmpEvent o, ObjectEncoding encoding)
        {
            var command    = o as Command;
            var methodCall = command.MethodCall;
            var isInvoke   = command is Invoke;

            // write the method name or result type (first section)
            if (methodCall.Name == "@setDataFrame")
            {
                writer.WriteAmfItem(encoding, command.ConnectionParameters);
            }

            // write arguments
            foreach (var arg in methodCall.Parameters)
            {
                writer.WriteAmfItem(encoding, arg);
            }
        }
Пример #10
0
 public void ReadLoop()
 {
     try
     {
         while (this.Continue)
         {
             RtmpHeader header = this.ReadHeader();
             this._rtmpHeaders[header.StreamId] = header;
             RtmpPacket packet1;
             if (!this._rtmpPackets.TryGetValue(header.StreamId, out packet1) || packet1 == null)
             {
                 packet1 = new RtmpPacket(header);
                 this._rtmpPackets[header.StreamId] = packet1;
             }
             byte[] bytes = this._reader.ReadBytes(Math.Min(packet1.Length + (header.Timestamp >= 16777215 ? 4 : 0) - packet1.CurrentLength, this._readChunkSize));
             packet1.AddBytes(bytes);
             if (packet1.IsComplete)
             {
                 this._rtmpPackets.Remove(header.StreamId);
                 RtmpEvent packet2 = this.ParsePacket(packet1);
                 this.OnEventReceived(new EventReceivedEventArgs(packet2));
                 ChunkSize chunkSize = packet2 as ChunkSize;
                 if (chunkSize != null)
                 {
                     this._readChunkSize = chunkSize.Size;
                 }
                 Abort abort = packet2 as Abort;
                 if (abort != null)
                 {
                     this._rtmpPackets.Remove(abort.StreamId);
                 }
             }
         }
     }
     catch (Exception ex)
     {
         this.OnDisconnected(new ExceptionalEventArgs("rtmp-packet-reader", ex));
     }
 }
Пример #11
0
        private void WritePacket(RtmpPacket packet)
        {
            RtmpHeader header   = packet.Header;
            int        streamId = header.StreamId;
            RtmpEvent  body     = packet.Body;

            byte[] messageBytes = this.GetMessageBytes(header, body);
            header.PacketLength = messageBytes.Length;
            RtmpHeader previousHeader;

            this._rtmpHeaders.TryGetValue(streamId, out previousHeader);
            this._rtmpHeaders[streamId] = header;
            this._rtmpPackets[streamId] = packet;
            this.WriteMessageHeader(header, previousHeader);
            bool flag  = true;
            int  index = 0;

            while (index < header.PacketLength)
            {
                if (!flag)
                {
                    this.WriteBasicHeader(ChunkMessageHeaderType.Continuation, header.StreamId);
                }
                int count = index + this._writeChunkSize > header.PacketLength ? header.PacketLength - index : this._writeChunkSize;
                this._writer.Write(messageBytes, index, count);
                flag   = false;
                index += this._writeChunkSize;
            }
            ChunkSize chunkSize = body as ChunkSize;

            if (chunkSize == null)
            {
                return;
            }
            this._writeChunkSize = chunkSize.Size;
        }
Пример #12
0
        byte[] GetMessageBytes(RtmpHeader header, RtmpEvent message)
        {
            switch (header.MessageType)
            {
            case MessageType.SetChunkSize:
                return(GetMessageBytes(message, (w, o) => w.WriteInt32(((ChunkSize)o).Size)));

            case MessageType.AbortMessage:
                return(GetMessageBytes(message, (w, o) => w.WriteInt32(((Abort)o).StreamId)));

            case MessageType.Acknowledgement:
                return(GetMessageBytes(message, (w, o) => w.WriteInt32(((Acknowledgement)o).BytesRead)));

            case MessageType.UserControlMessage:
                return(GetMessageBytes(message, (w, o) =>
                {
                    var m = (UserControlMessage)o;
                    w.WriteUInt16((ushort)m.EventType);
                    foreach (var v in m.Values)
                    {
                        w.WriteInt32(v);
                    }
                }));

            case MessageType.WindowAcknowledgementSize:
                return(GetMessageBytes(message, (w, o) => w.WriteInt32(((WindowAcknowledgementSize)o).Count)));

            case MessageType.SetPeerBandwith:
                return(GetMessageBytes(message, (w, o) =>
                {
                    var m = (PeerBandwidth)o;
                    w.WriteInt32(m.AcknowledgementWindowSize);
                    w.WriteByte((byte)m.LimitType);
                }));

            case MessageType.Audio:
            case MessageType.Video:
                return(GetMessageBytes(message, (w, o) => WriteData(w, o, ObjectEncoding.Amf0)));


            case MessageType.DataAmf0:
                return(GetMessageBytes(message, (w, o) => WriteCommandOrData(w, o, ObjectEncoding.Amf0)));

            case MessageType.SharedObjectAmf0:
                return(new byte[0]);    // todo: `SharedObject`s

            case MessageType.CommandAmf0:
                return(GetMessageBytes(message, (w, o) => WriteCommandOrData(w, o, ObjectEncoding.Amf0)));


            case MessageType.DataAmf3:
                return(GetMessageBytes(message, (w, o) => WriteData(w, o, ObjectEncoding.Amf3)));

            case MessageType.SharedObjectAmf3:
                return(new byte[0]);    // todo: `SharedObject`s

            case MessageType.CommandAmf3:
                return(GetMessageBytes(message, (w, o) =>
                {
                    w.WriteByte(0);
                    WriteCommandOrData(w, o, ObjectEncoding.Amf3);
                }));

            case MessageType.Aggregate:
                // todo: Aggregate messages
                System.Diagnostics.Debugger.Break();
                return(new byte[0]);    // todo: `Aggregate`

            default:
                throw new ArgumentOutOfRangeException("Unknown RTMP message type: " + (int)header.MessageType);
            }
        }
Пример #13
0
 public FlvPacket(FlvTagHeader header, RtmpEvent body) : this(header)
 {
     Body   = body;
     Length = header.DataSize;
 }
Пример #14
0
 public FlvPacket(RtmpEvent body)
 {
     Body = body;
 }
Пример #15
0
 void WriteProtocolControlMessage(RtmpEvent @event)
 {
     writer.Queue(@event, 2, 0);
 }
Пример #16
0
 public EventReceivedEventArgs(RtmpEvent @event)
 {
     this.Event = @event;
 }
Пример #17
0
 public RtmpPacket(RtmpHeader header, RtmpEvent body) : this(header)
 {
     Body   = body;
     Length = header.PacketLength;
 }
Пример #18
0
 private void WriteProtocolControlMessage(RtmpEvent @event)
 {
     this._writer.Queue(@event, 2, 0);
 }
Пример #19
0
 public RtmpPacket(RtmpEvent body)
 {
     Body = body;
 }
Пример #20
0
 public void SendAmf0Data(RtmpEvent e)
 {
     //var timestamp = (int)(DateTime.UtcNow - connectTime).TotalMilliseconds;
     //e.Timestamp = timestamp;
     writer.Queue(e, StreamId, random.Next());
 }
Пример #21
0
        private byte[] GetMessageBytes(RtmpHeader header, RtmpEvent message)
        {
            switch (header.MessageType)
            {
            case MessageType.SetChunkSize:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteInt32(((ChunkSize)o).Size))));

            case MessageType.AbortMessage:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteInt32(((Abort)o).StreamId))));

            case MessageType.Acknowledgement:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteInt32(((Acknowledgement)o).BytesRead))));

            case MessageType.UserControlMessage:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) =>
                {
                    UserControlMessage userControlMessage = (UserControlMessage)o;
                    w.WriteUInt16((ushort)userControlMessage.EventType);
                    foreach (int num in userControlMessage.Values)
                    {
                        w.WriteInt32(num);
                    }
                })));

            case MessageType.WindowAcknowledgementSize:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteInt32(((WindowAcknowledgementSize)o).Count))));

            case MessageType.SetPeerBandwidth:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) =>
                {
                    PeerBandwidth peerBandwidth = (PeerBandwidth)o;
                    w.WriteInt32(peerBandwidth.AcknowledgementWindowSize);
                    w.WriteByte((byte)peerBandwidth.LimitType);
                })));

            case MessageType.Audio:
            case MessageType.Video:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => w.WriteBytes(((ByteData)o).Data))));

            case MessageType.DataAmf3:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => this.WriteData(w, o, ObjectEncoding.Amf3))));

            case MessageType.SharedObjectAmf3:
                return(new byte[0]);

            case MessageType.CommandAmf3:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) =>
                {
                    w.WriteByte((byte)0);
                    this.WriteCommandOrData(w, o, ObjectEncoding.Amf3);
                })));

            case MessageType.DataAmf0:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => this.WriteData(w, o, ObjectEncoding.Amf0))));

            case MessageType.SharedObjectAmf0:
                return(new byte[0]);

            case MessageType.CommandAmf0:
                return(this.GetMessageBytes(message, (Action <AmfWriter, RtmpEvent>)((w, o) => this.WriteCommandOrData(w, o, ObjectEncoding.Amf0))));

            case MessageType.Aggregate:
                Debugger.Break();
                return(new byte[0]);

            default:
                throw new ArgumentOutOfRangeException("Unknown RTMP message type: " + (object)(int)header.MessageType);
            }
        }
Пример #22
0
 void WriteProtocolControlMessage(RtmpEvent @event)
 {
     writer.Queue(@event, CONTROL_CSID, 0);
 }
Пример #23
0
 public RtmpPacket(RtmpEvent body)
 {
     this.Body = body;
 }