public FragmentHandler ( ulong stage, ulong deltaNAck, Stream fragment, byte flags ) : void | ||
stage | ulong | |
deltaNAck | ulong | |
fragment | Stream | |
flags | byte | |
return | void |
public void FragmentHandler(ulong stage, ulong deltaNAck, Stream fragment, byte flags)
{
//Logger.Debug("Stage {0} on flow {1} received", stage, Id);
if (Completed) return;
var nextStage = Stage + 1;
if (stage < nextStage)
{
Logger.Debug("Stage {0} on flow {1} has already been received",stage,Id);
return;
}
if (deltaNAck > stage)
{
Logger.WARN("DeltaNAck {0} superior to stage {1} on flow {2}",deltaNAck,stage,Id);
deltaNAck = stage;
}
if (Stage < stage - deltaNAck)
{
foreach (var it in _fragments.OrderBy(x=>x.Stage).TakeWhile(it => it.Stage <= stage).ToList())
{
FragmentSortedHandler(it.Stage, it.Data, it.Flags);
if ((it.Flags & FlowWriter.MESSAGE_END)!=0)
{
Complete();
return;
}
it.Data.Dispose();
_fragments.Remove(it);
}
nextStage = stage;
}
if (stage > nextStage)
{
if (_fragments.All(x => x.Stage != stage))
{
_fragments.Add(new Fragment(fragment, flags,stage));
if (_fragments.Count > 100)
{
Logger.Debug("_fragments.Count={0}", _fragments.Count);
}
else
{
//Logger.Debug("nextStage{0},now receive {1}", nextStage,stage);
}
}
else
{
Logger.Debug("Stage {0} on flow {1} has already been received",stage,Id);
}
}
else
{
FragmentSortedHandler(nextStage++, fragment, flags);
if ((flags & FlowWriter.MESSAGE_END) != 0) Complete();
if(_fragments.Count>0)
foreach (var fragment1 in _fragments.OrderBy(x => x.Stage).ToList())
{
if (fragment1.Stage > nextStage) break;
FragmentSortedHandler(nextStage++, fragment1.Data, fragment1.Flags);
if ((fragment1.Flags & FlowWriter.MESSAGE_END) != 0)
{
Complete();
return;
}
fragment1.Data.Dispose();
_fragments.Remove(fragment1);
}
}
}
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); }