private void OnDataReceived(DataReceivedEventArgs args) { if (args.Owner.Client.Equals(_clientSocket.Client)) { // retrieve the packet ProcessAndPush(_rcvBuffer, args.Owner.Data); // check for sequenced packets in the queue if (_rcvBuffer.Count > 0) { do { // process if in sequence or break if (!_rcvBuffer.Exists(_rcvSequence)) { break; } else { Process(_rcvBuffer.Pop(_rcvSequence)); } }while (true); } } }
private void Process(MemoryStream PacketStream) { // increment rcv sequence _rcvSequence++; // get the header DtmPacketStruct pktHdr = new DtmPacketStruct(PacketStream); PacketStream.Seek(0, SeekOrigin.Begin); switch (pktHdr.PacketType) { // file transfer case DtmPacketFlags.Transfer: { switch ((DtmTransferFlags)pktHdr.PacketFlag) { case DtmTransferFlags.DataChunk: { try { lock (_rcvLock) { // received file data Receive(PacketStream); } } catch (Exception) { // packet corrupted, request a retransmission and exit Transmit(DtmPacketFlags.Service, (short)DtmServiceFlags.Resend, pktHdr.Sequence); return; } // echo the packet to remove it from remote buffer Transmit(DtmPacketFlags.Service, (short)DtmServiceFlags.Echo, pktHdr.Sequence); break; } } break; } // service messages case DtmPacketFlags.Service: { switch ((DtmServiceFlags)pktHdr.PacketFlag) { case DtmServiceFlags.Resend: { // resend the packet Resend(pktHdr); break; } case DtmServiceFlags.Echo: { // remove from local buffer if (_sndBuffer.Exists(pktHdr.OptionFlag)) { _sndBuffer.Destroy(pktHdr.OptionFlag); } break; } } break; } default: { throw new CryptoKeyExchangeException("DtmFileTransfer:Process", "The packet type is unknown!", new InvalidDataException()); } } // notify parent if (PacketReceived != null) { PacketReceived(this, new DtmPacketArgs(pktHdr.PacketFlag, pktHdr.PayloadLength)); } }