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);
}