예제 #1
0
        private byte[] getPreBuffer()
        {
            // get md5 hash
            ChecksumCalc checksum = new ChecksumCalc();

            byte[] md5 = checksum.GetMD5Checksum(filePath);

            FileInfo f = new FileInfo(filePath);

            // Using windows 1252 encoding
            Encoding encoding1252 = Encoding.GetEncoding(1252);

            //byte[] fileName = Encoding.ASCII.GetBytes(f.Name);
            byte[] fileName = encoding1252.GetBytes(f.Name);
            byte[] filenameSizePlusFilename = new byte[fileName.Length + 1];

            // copy byte representing the size of the filename
            // to the beginning of the first packet sent
            int  length  = fileName.Length;
            byte lengthB = (byte)length;

            new byte[] { lengthB }.CopyTo(filenameSizePlusFilename, 0);

            // copies file name in ASCII format from index 1 to length of filename
            Array.Copy(fileName, 0, filenameSizePlusFilename, 1, fileName.Length);

            // get file size and convert to 8 bytes
            long fileSize = f.Length;

            byte[] fileSizeB = BitConverter.GetBytes(fileSize);

            // preBuffer has size:
            // file name +
            // 1 byte for file name size +
            // 8 bytes is the size of the file +
            // 16 bytes is the md5 hash of the file
            byte[] preBuffer = new byte[fileName.Length + 1 + 8 + 16];

            // copy file name size and file name to preBuffer
            filenameSizePlusFilename.CopyTo(preBuffer, 0);

            // copy fileSizeB to end of preBuffer
            Array.Copy(fileSizeB, 0, preBuffer, fileName.Length + 1, 8);

            // copy md5 hash to preBuffer
            Array.Copy(md5, 0, preBuffer, fileName.Length + 1 + 8, 16);

            // format the transfer like this:
            // byte = filename size
            // file name
            // long = file size in bytes, ulong is 64 bit so filesize could be limitless
            // 16 bytes md5 hash of file
            // file content

            return(preBuffer);
        }
예제 #2
0
        public void startSending()
        {
            try
            {
                // Create a TCP socket.
                sendingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //sendingSocket.SendBufferSize = 8192;
                sendingSocket.SendBufferSize = 32768;
                //sendingSocket.SendBufferSize = 65536;

                // Don't allow another socket to bind to this port.
                // Should perhaps consider this one
                //listener.ExclusiveAddressUse = true;

                // Connect the socket to the remote endpoint.
                sendingSocket.Connect(endPoint);

                // TODO:
                // look at SocketFlags http://msdn.microsoft.com/en-us/library/system.net.sockets.socketflags%28v=vs.110%29.aspx

                // get md5 hash
                ChecksumCalc checksum = new ChecksumCalc();
                byte[]       md5      = checksum.GetMD5Checksum(filePath);

                FileInfo f = new FileInfo(filePath);

                // TODO:
                // fix error with files like xyzæøå.txt
                // Replace ASIC2 with Windows 1252 encoding
                //Encoding encoding = Encoding.GetEncoding(1252);

                byte[] fileName = Encoding.ASCII.GetBytes(f.Name);
                byte[] filenameSizePlusFilename = new byte[fileName.Length + 1];

                // copy byte representing the size of the filename
                // to the beginning of the first packet sent
                int  length  = fileName.Length;
                byte lengthB = (byte)length;
                new byte[] { lengthB }.CopyTo(filenameSizePlusFilename, 0);

                // copies file name in ASCII format from index 1 to length of filename
                Array.Copy(fileName, 0, filenameSizePlusFilename, 1, fileName.Length);

                // get file size and convert to 8 bytes
                long   fileSize  = f.Length;
                byte[] fileSizeB = BitConverter.GetBytes(fileSize);

                // preBuffer has size:
                // file name +
                // 1 byte for file name size +
                // 8 bytes is the size of the file +
                // 16 bytes is the md5 hash of the file
                byte[] preBuffer = new byte[fileName.Length + 1 + 8 + 16];

                // copy file name size and file name to preBuffer
                filenameSizePlusFilename.CopyTo(preBuffer, 0);

                // copy fileSizeB to end of preBuffer
                Array.Copy(fileSizeB, 0, preBuffer, fileName.Length + 1, 8);

                // copy md5 hash to preBuffer
                Array.Copy(md5, 0, preBuffer, fileName.Length + 1 + 8, 16);

                // format the transfer like this:
                // byte = filename size
                // file name
                // long = file size in bytes, ulong is 64 bit so filesize could be limitless
                // 16 bytes md5 hash of file
                // file content

                // sends size of filename (0-255) + filename
                // plus file size and md5 hash of file
                // and then disconnect after file has been queued for transmission
                sendingSocket.BeginSendFile(filePath, preBuffer, null, TransmitFileOptions.Disconnect, new AsyncCallback(FileSendCallback), sendingSocket);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                // this method starts a new  AsyncCallback(ReadCallback)
                // and this method is ReadCallback so it works as a recursive method
                //handler.BeginReceive(tempState.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), tempState);

                //Thread.CurrentThread.Interrupt();
            }
        }
예제 #3
0
        public void ReadCallback(IAsyncResult ar)
        {
            //int fileNameLen = 1;
            //String content = String.Empty;
            StateObject tempState = (StateObject)ar.AsyncState;
            Socket      handler   = tempState.workSocket;
            int         bytesRead = handler.EndReceive(ar);

            if (bytesRead <= 0)
            {
                return;
            }

            counter.AddBytes((uint)bytesRead);

            if (isFirstPacket)
            {
                try
                {
                    // gets the first byte
                    byte[] firstByte = new byte[1];
                    firstByte = tempState.buffer.Take(1).ToArray();

                    // first byte has a value 0 - 255
                    fileNameLength = Convert.ToInt32(firstByte[0]);

                    // a fileName cannot be more then 255 characters because a byte cannot have have a higher value...
                    if (fileNameLength > 255)
                    {
                        // filename is not valid...
                        // this should not happen, should somehow at least validate the first packet to ensure
                        // it contain the right information...
                        return;
                        //fileNameLength = 255;
                    }

                    // TODO:
                    // check if fileName is valid
                    // if file already exist (conflict)

                    // Windows 1252 encoding
                    Encoding encoding1252 = Encoding.GetEncoding(1252);
                    fileName = encoding1252.GetString(tempState.buffer, 1, fileNameLength);

                    // after the file name comes the size of the file
                    // should be a long
                    // that is 64 bit = 8 byte
                    byte[] fileSizeB = tempState.buffer.Skip(1 + fileNameLength).Take(8).ToArray();
                    fileSize = BitConverter.ToInt64(fileSizeB, 0);

                    // get md5 hash
                    // md5 hash is 16 bytes = 128 bit
                    md5 = tempState.buffer.Skip(1 + fileNameLength + 8).Take(16).ToArray();

                    // set total to be received
                    totalBytesToBeReceived = fileNameLength + fileSize + 9 + 16;

                    // TODO:
                    // get FileInfo object

                    // TODO:
                    // start download counter, datetime, total filesize to download etc
                    // get MD5 hash or other hash of file
                    // make sure all meta data and other stuff is actually sent
                    // calculate hash of when file has been received and written to a file here
                    // close socket and stop thread when entire file has been written

                    // start timer that will execute an event every 1 sec
                    // that shows mb/s kb/s etc
                    timer = new System.Timers.Timer()
                    {
                        Interval = 1000, Enabled = true
                    };
                    timer.Elapsed += timer_Elapsed;
                    timer.Start();
                }
                catch (InvalidCastException castError)
                {
                    // was not able to find file size
                    Console.WriteLine(castError.Message);
                    return;
                }
                catch (Exception error)
                {
                    Console.WriteLine(error.Message);
                    return;
                }
            }

            BinaryWriter writer = null;

            try
            {
                // TODO:
                // double check that file path is correct

                // TODO:
                // only open file while it is not in use
                // wait until file is ready to be written to

                if (isFirstPacket)
                {
                    // old way
                    //writer = new BinaryWriter(File.Open(savePathAndFileName, FileMode.Append));

                    string savePathAndFileName = receivePath + "\\" + fileName;

                    // creates a thread pool using BlockingCollection
                    // this will allow a queue of max 200 threads waiting to write to the file
                    // if more than 200 threads are created, they are blocked and wait until the '
                    // queue is free
                    fileWriter = new ParallelFileWriter(savePathAndFileName, 200);

                    // the first packet contain information that should not be written to the file itself so
                    // if first packet then increase the index to size of fileName + one byte
                    // since we increase the index, we need to reduce the count by the same amount

                    // + 1 byte for size of fileName byte
                    // + 8 bytes for 64 bit long with file size
                    // + 16 bytes for md5 hash
                    // shift = 9 bytes + fileName
                    int shift = fileNameLength + 9 + 16;
                    //writer.Write(tempState.buffer, shift, bytesRead - shift);

                    byte[] data = new byte[bytesRead - shift];
                    Array.Copy(tempState.buffer, shift, data, 0, bytesRead - shift);

                    fileWriter.Write(data);

                    isFirstPacket = false;

                    // set fileName, but do not trigger event
                    FileTransferEvents.filename = fileName;
                }
                else
                {
                    byte[] data = new byte[bytesRead];
                    Array.Copy(tempState.buffer, 0, data, 0, bytesRead);

                    fileWriter.Write(data);

                    //writer.Write(tempState.buffer, 0, bytesRead);
                }

                // add to written files
                totalBytesReceived += bytesRead;

                // check if all bytes has been read and transfer is complete
                if (totalBytesReceived == totalBytesToBeReceived)
                {
                    // trigger file received event
                    FileTransferEvents.FileReceived = fileName;

                    // get file location
                    string savePathAndFileName = receivePath + "\\" + fileName;

                    // reset connection
                    // set everything back to default and wait for new file
                    resetConnection();

                    // close file writer so we can access file again
                    if (writer != null)
                    {
                        writer.Close();
                    }

                    // complete writing tasks and threads
                    fileWriter.Dispose();

                    Console.WriteLine("Calculating md5 hash of received file...");

                    // get md5 hash
                    ChecksumCalc checksum         = new ChecksumCalc();
                    byte[]       md5AfterTransfer = checksum.GetMD5Checksum(savePathAndFileName);

                    // check if md5 received is identical to md5 calculated after transfer
                    bool isIdentical = checksum.checkIfHashisIdentical(md5, md5AfterTransfer);

                    if (isIdentical)
                    {
                        // the hash received before the file transfer is identical to the
                        // hash calculated with the new file
                        Console.WriteLine("SUCCESS: md5 hash match the md5 of received file");
                    }
                    else
                    {
                        // delete file?
                        Console.WriteLine("ERROR: File is corrupt, md5 hash does NOT match the md5 of the file received");
                    }
                }
            }
            catch (Exception error)
            {
                Console.WriteLine(error.Message);
                Thread.Sleep(30);
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }

                // triggers event with long of bytes written
                //FileTransferEvents.BytesReceived = written;

                // this method starts a new  AsyncCallback(ReadCallback)
                // and this method is ReadCallback so it works as a recursive method
                handler.BeginReceive(tempState.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), tempState);

                //Thread.CurrentThread.Interrupt();
            }
        }
예제 #4
0
        public void sendFileInfo(string filePath)
        {
            // check if file exists
            if (File.Exists(filePath) == false)
            {
                return;
            }

            // get md5 hash
            ChecksumCalc checksum = new ChecksumCalc();

            byte[] md5 = checksum.GetMD5Checksum(filePath);

            FileInfo f = new FileInfo(filePath);

            // Using windows 1252 encoding
            Encoding encoding1252 = Encoding.GetEncoding(1252);

            //byte[] fileName = Encoding.ASCII.GetBytes(f.Name);
            byte[] fileName = encoding1252.GetBytes(f.Name);
            byte[] filenameSizePlusFilename = new byte[fileName.Length + 1];

            // copy byte representing the size of the filename
            // to the beginning of the first packet sent
            int  length  = fileName.Length;
            byte lengthB = (byte)length;

            new byte[] { lengthB }.CopyTo(filenameSizePlusFilename, 0);

            // copies file name in ASCII format from index 1 to length of filename
            Array.Copy(fileName, 0, filenameSizePlusFilename, 1, fileName.Length);

            // get file size and convert to 8 bytes
            long fileSize = f.Length;

            byte[] fileSizeB = BitConverter.GetBytes(fileSize);

            // preBuffer has size:
            // file name +
            // 1 byte for file name size +
            // 8 bytes is the size of the file +
            // 16 bytes is the md5 hash of the file
            byte[] preBuffer = new byte[fileName.Length + 1 + 8 + 16];

            // copy file name size and file name to preBuffer
            filenameSizePlusFilename.CopyTo(preBuffer, 0);

            // copy fileSizeB to end of preBuffer
            Array.Copy(fileSizeB, 0, preBuffer, fileName.Length + 1, 8);

            // copy md5 hash to preBuffer
            Array.Copy(md5, 0, preBuffer, fileName.Length + 1 + 8, 16);

            // format the transfer like this:
            // byte = filename size
            // file name
            // long = file size in bytes, ulong is 64 bit so filesize could be limitless
            // 16 bytes md5 hash of file
            // file content

            // byte indicating what type of packet it is
            byte[] commandByte = new byte[] { 9 };

            // byte array with port
            byte[] listenPortByteArray = BitConverter.GetBytes(listenPort);

            // Creating buffer to send
            byte[] sendBuffer = combineBytes(commandByte, listenPortByteArray, preBuffer);

            // Sending UPD packet
            socket.SendTo(sendBuffer, endPoint);
            Console.WriteLine("\nUDP Responder");
            Console.WriteLine(String.Format("Sending file info to {0}, file: \"{1}\"", endPoint.ToString(), f.Name));
        }