Ejemplo n.º 1
0
        public virtual void PacketHandler(N2HBinaryReader reader)
        {
            if (IsEnqueueForDelete)
            {
                return;
            }
            RecTimestamp.Restart();
            var marker = reader.ReadByte() | 0xF0;

            TimeSent = reader.ReadUInt16();
            if (marker == (Target == null?0xFD:0xFE))
            {
                var time     = RtmfpUtils.TimeNow();
                var timeEcho = reader.ReadUInt16();
                if (timeEcho > time)
                {
                    if (timeEcho - time < 30)
                    {
                        time = 0;
                    }
                    else
                    {
                        time += (ushort)(0xFFFF - timeEcho);
                    }
                    timeEcho = 0;
                }
                Peer.Ping = (ushort)((time - timeEcho) * Defines.RTMFP_TIMESTAMP_SCALE);
            }
            else if (marker != (Target == null ? 0xF9 : 0xFA))
            {
                Logger.WARN("Packet marker unknown:{0}", marker);
                return;
            }
            byte  flags     = 0;
            Flow  flow      = null;
            ulong stage     = 0;
            ulong deltaNAck = 0;
            var   type      = reader.BaseStream.GetAvaliableByteCounts() > 0 ? reader.ReadByte() : (byte)0xFF;

            //Debug.WriteLine("rec:{0:x}",type);
            while (type != 0xFF)
            {
                var  size         = reader.ReadUInt16();
                long nextPos      = reader.BaseStream.Position + size;
                var  oldPublished = (reader.BaseStream as InputStream).Published;
                (reader.BaseStream as InputStream).Published = (uint)nextPos;
                switch (type)
                {
                case 0x0c:
                    Fail("failed on client side");
                    break;

                case 0x4c:
                    _failed = true;
                    EnqueueForDelete();
                    return;

                case 0x01:
                    if (!Peer.Connected)
                    {
                        Fail("Timeout connection client");
                    }
                    else
                    {
                        WriteMessage(0x41, 0);
                    }
                    goto case 0x41;

                case 0x41:
                    Logger.INFO("keepAlive!");
                    _timesKeepalive = 0;
                    break;

                case 0x5e:
                    var idFlow = reader.Read7BitLongValue();
                    if (!FlowWriters.ContainsKey(idFlow))
                    {
                        Logger.WARN("FlowWriter {0} unfound for acknowledgment on session {1}", idFlow, Id);
                    }
                    else
                    {
                        var flowWriter = FlowWriters[idFlow];
                        flowWriter.Fail("flowWriter rejected on session " + Id);
                    }
                    break;

                case 0x18:
                    Fail("ack negative from server");
                    break;

                case 0x51:
                    //Acknowledgment
                    idFlow = reader.Read7BitLongValue();
                    if (FlowWriters.ContainsKey(idFlow))
                    {
                        FlowWriters[idFlow].Acknowledgment(reader);
                    }
                    else
                    {
                        Logger.WARN("FlowWriter {0} unfound for acknowledgment on session {1}", idFlow, Id);
                    }
                    break;

                case 0x10:
                    flags     = reader.ReadByte();
                    idFlow    = reader.Read7BitLongValue();
                    stage     = reader.Read7BitLongValue() - 1;
                    deltaNAck = reader.Read7BitLongValue() - 1;
                    //Debug.WriteLine("10:{0},{1},{2}",idFlow,stage,deltaNAck);
                    if (_failed)
                    {
                        break;
                    }
                    if (Flows.ContainsKey(idFlow))
                    {
                        flow = Flows[idFlow];
                    }
                    if ((flags & FlowWriter.MESSAGE_HEADER) != 0)
                    {
                        var   signature   = reader.ReadString8();
                        ulong assocFlowId = 0;
                        if (reader.ReadByte() > 0)
                        {
                            if (reader.ReadByte() != 0x0A)
                            {
                                Logger.WARN("Unknown fullduplex header part for the flow {0}", idFlow);
                            }
                            else
                            {
                                assocFlowId = reader.Read7BitLongValue();
                            }
                            var length = reader.ReadByte();
                            while (length > 0 && reader.BaseStream.GetAvaliableByteCounts() > 0)
                            {
                                Logger.WARN("Unknown message part on flow {0}", idFlow);
                                reader.BaseStream.Position += length;
                                length = reader.ReadByte();
                            }
                            if (length > 0)
                            {
                                Logger.FATAL("Bad header message part, finished before scheduled");
                            }
                        }
                        if (flow == null)
                        {
                            flow = CreateFlow(idFlow, signature, assocFlowId);
                        }
                    }
                    if (flow == null)
                    {
                    }
                    goto case 0x11;

                case 0x11:
                    ++stage;
                    ++deltaNAck;
                    if (type == 0x11)
                    {
                        flags = reader.ReadByte();
                    }
                    if (flow != null)
                    {
                        flow.FragmentHandler(stage, deltaNAck, reader.BaseStream, flags);
                        if (!string.IsNullOrEmpty(flow.Error))
                        {
                            Fail(flow.Error);
                            flow = null;
                        }
                    }
                    break;

                default:
                    Logger.FATAL("Message type {0} unknown", type);
                    break;
                }

                reader.BaseStream.Position = nextPos;
                (reader.BaseStream as InputStream).Published = oldPublished;
                type = (byte)(reader.BaseStream.GetAvaliableByteCounts() > 0 ? reader.ReadByte() : 0xFF);
                if (flow != null && type != 0x11)
                {
                    flow.Commit();
                    if (flow.Completed)
                    {
                        Flows.Remove(flow.Id);
                        flow.Dispose();
                    }
                    flow = null;
                }
                //else
                //{
                //    Debug.WriteLine("no commit:{0},{1:X}",flow?.Id.ToString() ?? "no flow",type);
                //}
            }
            SFlush(true);
        }