Beispiel #1
0
        /// <summary>
        /// Used to initialize the file transfer sequence.
        /// <para>Sends a file request with the file id, name, and size.</para>
        /// </summary>
        /// 
        /// <param name="FilePath">The full path to the file to send</param>
        public void SendFile(string FilePath)
        {
            // store file length
            long len = new FileInfo(FilePath).Length;
            // increment file id
            _fileCounter++;
            // get an open port
            int port = _clientSocket.NextOpenPort();
            // create the file info header
            byte[] btInfo = new DtmFileInfo(Path.GetFileName(FilePath), len, port).ToBytes();

            // create a new symmetric key
            KeyParams fileKey = GenerateSymmetricKey(_srvIdentity.Session);
            MemoryStream keyStrm = (MemoryStream)KeyParams.Serialize(fileKey);
            // add the key
            btInfo = ArrayUtils.Concat(btInfo, keyStrm.ToArray());

            // wrap the request
            btInfo = WrapMessage(btInfo, _dtmParameters.MaxMessageAppend, _dtmParameters.MaxMessagePrePend);
            // encrypt with master
            btInfo = SymmetricTransform(_srvSymProcessor, btInfo);

            // initialize the files unique crypto processor
            ICipherMode fileSymProcessor = SymmetricInit(_srvIdentity.Session, fileKey);
            // tune for parallel processing
            int blockSize = ((int)MessageBufferSize - DtmPacket.GetHeaderSize()) - ((int)MessageBufferSize - DtmPacket.GetHeaderSize()) % ((CTR)fileSymProcessor).ParallelMinimumSize;
            ((CTR)fileSymProcessor).ParallelBlockSize = blockSize;

            // build the file transfer instance
            DtmFileTransfer fileTransfer = new DtmFileTransfer(fileSymProcessor, _fileCounter, 1024, (int)FileBufferSize);
            fileTransfer.FileTransferred += new DtmFileTransfer.FileTransferredDelegate(OnFileSent);
            fileTransfer.ProgressPercent += new DtmFileTransfer.ProgressDelegate(OnFileSentProgress);
            // add to dictionary
            _transQueue.TryAdd(_fileCounter, fileTransfer);

            // send header to the remote host in a file request
            Transmit(DtmPacketTypes.Transfer, (short)DtmTransferFlags.Request, _fileCounter, new MemoryStream(btInfo));

            // initiate with non-blocking listen
            fileTransfer.StartSend(_clientSocket.LocalAddress, port, FilePath);

            if (fileTransfer.IsConnected)
            {
                try
                {
                    // start on a new thread
                    Task socketTask = Task.Factory.StartNew(() =>
                    {
                        fileTransfer.SendFile();
                    });
                    socketTask.Wait(10);
                }
                catch (AggregateException ae)
                {
                    if (SessionError != null)
                        SessionError(this, new DtmErrorEventArgs(ae.GetBaseException(), DtmErrorSeverity.Warning));
                }
            }
            else
            {
                // remove from pending and dispose
                CloseTransfer(_fileCounter);

                // alert app
                DtmErrorEventArgs args = new DtmErrorEventArgs(new SocketException((int)SocketError.ConnectionAborted), DtmErrorSeverity.Connection);
                if (SessionError != null)
                    SessionError(this, args);

                if (args.Cancel == true)
                    Disconnect();
            }
        }
Beispiel #2
0
        /// <summary>
        /// Used Post-Exchange to setup a file transfer from the remote host
        /// </summary>
        /// 
        /// <param name="PacketStream">The stream containing the file transfer request</param>
        private void ReceiveFile(Stream PacketStream)
        {
            // asynchronous transfer by sending a file key and info, and running the entire transfer on another socket..
            if (!_isEstablished)
                throw new CryptoProcessingException("DtmKex:ReceiveFile", "The VPN has not been established!", new InvalidOperationException());
            if (FileRequest == null)
                throw new CryptoProcessingException("DtmKex:ReceiveFile", "The FileRequest and FileReceived must be connected to perform a file transfer, read the documentation!", new InvalidOperationException());
            if (FileReceived == null)
                throw new CryptoProcessingException("DtmKex:ReceiveFile", "The FileRequest and FileReceived must be connected to perform a file transfer, read the documentation!", new InvalidOperationException());

            // get the header
            DtmPacket pktHdr = new DtmPacket(PacketStream);
            // read the packet
            byte[] enc = new byte[pktHdr.PayloadLength];
            // get the encrypted data
            PacketStream.Read(enc, 0, enc.Length);
            // decrypt it using client crypto processor
            byte[] dec = SymmetricTransform(_cltSymProcessor, enc);
            // remove padding
            dec = UnwrapMessage(dec);
            MemoryStream pktStm = new MemoryStream(dec);

            // get file info header
            DtmFileInfo pktFi = new DtmFileInfo(pktStm);
            // get the key
            KeyParams fileKey = KeyParams.DeSerialize(pktStm);

            // forward request to app
            DtmFileRequestEventArgs args = new DtmFileRequestEventArgs(pktFi.FileName);
            FileRequest(this, args);

            // accept file or refuse and exit; app must send back a valid path or cancel; if cancel, send a refuse notice which will signal the end of the transfer, otherwise store file path and port
            if (args.Cancel || string.IsNullOrEmpty(args.FilePath) || args.FilePath.Equals(pktFi.FileName) || !Directory.Exists(Path.GetDirectoryName(args.FilePath)))
            {
                // send refuse and exit
                Transmit(DtmPacketTypes.Transfer, (short)DtmTransferFlags.Refused, pktHdr.OptionFlag);
            }
            else
            {
                // create the files crypto processor
                ICipherMode fileSymProcessor = SymmetricInit(_cltIdentity.Session, fileKey);
                // enable parallel decryption
                int blockSize = ((int)MessageBufferSize - DtmPacket.GetHeaderSize()) - ((int)MessageBufferSize - DtmPacket.GetHeaderSize()) % ((CTR)fileSymProcessor).ParallelMinimumSize;
                ((CTR)fileSymProcessor).ParallelBlockSize = blockSize;

                // init the file transfer host
                DtmFileTransfer fileTransfer = new DtmFileTransfer(fileSymProcessor, pktHdr.OptionFlag, 1024, (int)FileBufferSize);
                fileTransfer.FileTransferred += new DtmFileTransfer.FileTransferredDelegate(OnFileReceived);
                fileTransfer.ProgressPercent += new DtmFileTransfer.ProgressDelegate(OnFileReceivedProgress);
                // add to dictionary
                _transQueue.TryAdd(pktHdr.OptionFlag, fileTransfer);

                try
                {
                    // start the transfer on a new thread
                    Task socketTask = Task.Factory.StartNew(() =>
                    {
                        fileTransfer.StartReceive(_clientSocket.RemoteAddress, (int)pktFi.OptionsFlag, args.FilePath);
                    });
                    socketTask.Wait(10);
                }
                catch (AggregateException ae)
                {
                    if (SessionError != null)
                        SessionError(this, new DtmErrorEventArgs(ae.GetBaseException(), DtmErrorSeverity.Warning));
                }
            }
        }
Beispiel #3
0
        public void SendFile()
        {
            int bytesRead = 0;
            long len = new FileInfo(_filePath).Length;
            DtmFileInfo flHdr = new DtmFileInfo(_filePath, len, 0);
            int ckSize = _clientSocket.SendBufferSize - (flHdr.GetHeaderSize() + DtmPacket.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(DtmPacketTypes.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 DtmPacketEventArgs((short)DtmTransferFlags.Sent, _fileId));
            }
            catch (Exception ex)
            {
                throw new CryptoFileTransferException("DtmFileTransfer:SendFile", "The file transfer did not complete!", ex);
            }
            finally
            {
                // flush
                SendFlush();
            }
        }
Beispiel #4
0
        private void Receive(Stream PacketStream)
        {
            // get the packet header
            DtmPacket prcPacket = new DtmPacket(PacketStream);
            // read the packet
            byte[] enc = new byte[prcPacket.PayloadLength];
            // get the encrypted data
            PacketStream.Read(enc, 0, enc.Length);
            // decrypt it using file crypto processor
            byte[] dec = SymmetricTransform(_fileSymProcessor, enc);
            // get file info header
            DtmFileInfo pktFi = new DtmFileInfo(dec);
            // store file name and size
            string fileName = pktFi.FileName;
            long fileSize = pktFi.FileSize;
            long streamLen = 0;

            try
            {
                using (FileStream outStream = new FileStream(_tempPath, FileMode.Append, FileAccess.Write, FileShare.Read))
                {
                    // calculate offsets
                    int hdrSize = pktFi.GetHeaderSize();
                    int len = dec.Length - hdrSize;
                    // write to file
                    outStream.Write(ArrayUtils.GetRange(dec, hdrSize, len), 0, len);
                    // store length
                    streamLen = outStream.Length;

                    // progress
                    if (ProgressPercent != null)
                    {
                        double progress = 100.0 * (double)pktFi.OptionsFlag / fileSize;
                        ProgressPercent(this, new System.ComponentModel.ProgressChangedEventArgs((int)progress, (object)fileSize));
                    }
                }

                // transfer completed
                if (streamLen == fileSize)
                {
                    // reset attributes
                    File.SetAttributes(_tempPath, File.GetAttributes(_tempPath) & ~FileAttributes.Hidden);
                    // rename the file
                    File.Move(_tempPath, VTDev.Libraries.CEXEngine.Tools.FileTools.GetUniqueName(_filePath));

                    // notify app
                    if (FileTransferred != null)
                        FileTransferred(this, new DtmPacketEventArgs((short)DtmTransferFlags.Received, prcPacket.OptionFlag));

                    // flush and close
                    ReceiveClose();
                }
            }
            catch (Exception ex)
            {
                throw new CryptoFileTransferException("DtmFileTransfer:Receive", "The file transfer did not complete!", ex);
            }
        }
Beispiel #5
0
 /// <summary>
 /// Serialize an DtmFileInfo structure
 /// </summary>
 /// 
 /// <param name="FileInfo">A DtmFileInfo structure</param>
 /// 
 /// <returns>A stream containing the DtmFileInfo data</returns>
 public static Stream Serialize(DtmFileInfo FileInfo)
 {
     return FileInfo.ToStream();
 }