예제 #1
0
        private void ProcessAndPush(PacketBuffer Buffer, MemoryStream PacketStream)
        {
            int hdrLen = DtmPacketStruct.GetHeaderSize();
            int pktLen = 0;
            // get the header
            DtmPacketStruct pktHdr = new DtmPacketStruct(PacketStream);

            PacketStream.Seek(0, SeekOrigin.Begin);

            // track high sequence number
            if (pktHdr.Sequence > _seqCounter)
            {
                _seqCounter = pktHdr.Sequence;
            }

            // out of sync, possible packet loss
            if (_seqCounter - _rcvSequence > _bufferCount / 4)
            {
                // request a retransmission
                Transmit(DtmPacketFlags.Service, (short)DtmServiceFlags.Resend, _rcvSequence + 1);
            }

            // packet aligned
            if (pktHdr.PayloadLength + hdrLen == PacketStream.Length)
            {
                // resend was already processed
                if (pktHdr.Sequence < _rcvSequence)
                {
                    return;
                }

                // push onto buffer
                Buffer.Push(pktHdr.Sequence, PacketStream);
            }
            // more than one packet
            else if (pktHdr.PayloadLength + hdrLen < PacketStream.Length)
            {
                byte[] buffer;
                long   pos = 0;

                do
                {
                    // get packet position and size
                    pos = PacketStream.Position;

                    if (PacketStream.Length - pos < DtmPacketStruct.GetHeaderSize())
                    {
                        // next packet corrupted, request a retransmission and exit
                        Transmit(DtmPacketFlags.Service, (short)DtmServiceFlags.Resend, Buffer.GetHighKey() + 1);
                        return;
                    }

                    pktHdr = new DtmPacketStruct(PacketStream);
                    pktLen = (int)(hdrLen + pktHdr.PayloadLength);

                    if (pktLen > MAXRCVBUFFER || pktLen < 0 || PacketStream.Length - pos < pktLen)
                    {
                        // packet corrupted, request a retransmission and exit
                        Transmit(DtmPacketFlags.Service, (short)DtmServiceFlags.Resend, Buffer.GetHighKey() + 1);
                        return;
                    }
                    else
                    {
                        // create the buffer
                        buffer = new byte[pktLen];
                        PacketStream.Seek(pos, SeekOrigin.Begin);
                        PacketStream.Read(buffer, 0, (int)pktLen);
                        // push onto buffer
                        Buffer.Push(pktHdr.Sequence, new MemoryStream(buffer));
                    }
                } while (PacketStream.Position < PacketStream.Length);
            }
            // malformed packet, send retransmit request
            else if (pktHdr.PayloadLength > MAXRCVBUFFER || pktHdr.PayloadLength < 0 || pktHdr.PayloadLength + hdrLen > PacketStream.Length)
            {
                // packet corrupted, request a retransmission of last in queue + 1
                Transmit(DtmPacketFlags.Service, (short)DtmServiceFlags.Resend, Buffer.GetHighKey() + 1);
            }
        }
예제 #2
0
        public void SendFile()
        {
            int              bytesRead = 0;
            long             len       = new FileInfo(_filePath).Length;
            DtmFileInfoSruct flHdr     = new DtmFileInfoSruct(_filePath, len, 0);
            int              ckSize    = _clientSocket.SendBufferSize - (flHdr.GetHeaderSize() + DtmPacketStruct.GetHeaderSize());

            byte[] inputBuffer = new byte[ckSize];

            try
            {
                using (FileStream inStream = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    // loop through file
                    while ((bytesRead = inStream.Read(inputBuffer, 0, ckSize)) > 0)
                    {
                        // wrap in a file info; option flag is used for payload length
                        flHdr.OptionsFlag = bytesRead;
                        byte[] hdrArr = flHdr.ToBytes();

                        // add data
                        if (bytesRead == ckSize)
                        {
                            hdrArr = ArrayUtils.Concat(hdrArr, inputBuffer);
                        }
                        else
                        {
                            hdrArr = ArrayUtils.Concat(hdrArr, ArrayUtils.GetRange(inputBuffer, 0, bytesRead));
                        }

                        // encrypt the header and data
                        byte[] enc = SymmetricTransform(_fileSymProcessor, hdrArr);
                        // send to the remote host
                        Transmit(DtmPacketFlags.Transfer, (short)DtmTransferFlags.DataChunk, _fileId, new MemoryStream(enc));
                        // increment counter
                        _bytesSent += bytesRead;

                        // progress
                        if (ProgressPercent != null)
                        {
                            double progress = 100.0 * (double)_bytesSent / inStream.Length;
                            ProgressPercent(this, new System.ComponentModel.ProgressChangedEventArgs((int)progress, (object)inStream.Length));
                        }
                    }
                }
                // notify app
                if (FileTransferred != null)
                {
                    FileTransferred(this, new DtmPacketArgs((short)DtmTransferFlags.Sent, _fileId));
                }
            }
            catch (Exception ex)
            {
                throw new CryptoFileTransferException("DtmFileTransfer:SendFile", "The file transfer did not complete!", ex);
            }
            finally
            {
                // flush
                SendFlush();
            }
        }