public static byte[] Serialize(this ITftpPacket packet)
        {
            MemoryStream bytes = new MemoryStream();

            bytes.Write(EndianBitConverter.Big.GetBytes((ushort)packet.Op), 0, sizeof(ushort));
            switch (packet.Op)
            {
            case TftpOperation.ReadRequest:
                RrqPacket rrq = (RrqPacket)packet;
                StringToNetascii(rrq.FileName, bytes);
                StringToNetascii(rrq.Mode.ToString(), bytes);
                break;

            case TftpOperation.WriteRequest:
                WrqPacket wrq = (WrqPacket)packet;
                StringToNetascii(wrq.FileName, bytes);
                StringToNetascii(wrq.Mode.ToString(), bytes);
                break;

            case TftpOperation.Data:
                DataPacket data = (DataPacket)packet;
                bytes.Write(EndianBitConverter.Big.GetBytes((ushort)data.BlockNumber), 0, sizeof(ushort));
                bytes.Write(data.Data, 0, data.Data.Length);
                break;

            case TftpOperation.Ack:
                AckPacket ack = (AckPacket)packet;
                bytes.Write(EndianBitConverter.Big.GetBytes((ushort)ack.BlockNumber), 0, sizeof(ushort));
                break;

            case TftpOperation.Error:
                ErrorPacket error = (ErrorPacket)packet;
                bytes.Write(EndianBitConverter.Big.GetBytes((ushort)error.Error), 0, sizeof(ushort));
                StringToNetascii(error.Message, bytes);
                break;

            default:
                throw new Exception("Operation not recognized.");
            }
            return(bytes.ToArray());
        }
Exemple #2
0
        public void Write(IPEndPoint server, string fileName, string inputPath, CancellationToken cancellationToken)
        {
            Console.WriteLine("Writing local file '{0}' to file '{1}' on server {2}", inputPath, fileName, server);

            // Read the file from the local file system.
            byte[] file = File.ReadAllBytes(inputPath);

            // Create a connection with the server.
            IPEndPoint receivedFromEP = new IPEndPoint(IPAddress.Any, 0);

            using (RemoteEndPointReservation clientReservation = new RemoteEndPointReservation(server))
                using (TftpConnection connection = new TftpConnection())
                {
                    RemoteEndPointReservation remoteEPReservation = null;
                    try
                    {
                        // Read the file contents to the remote endpoint in chunks.
                        ushort currentBlockNumber = 0;
                        int    currentFileIndex   = 0;
                        bool   done = false;
                        while (!done)
                        {
                            Func <ITftpPacket, bool> receiveFilter = (ITftpPacket packet) =>
                            {
                                if (packet.Op == TftpOperation.Ack)
                                {
                                    AckPacket ack = (AckPacket)packet;
                                    if (ack.BlockNumber == currentBlockNumber)
                                    {
                                        Console.WriteLine("ACK received for block {0}", ack.BlockNumber);
                                        return(true);
                                    }
                                    else
                                    {
                                        Console.WriteLine("Incorrect ACK block number {0}", ack.BlockNumber);
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Incorrect operation. Expected ACK.");
                                }
                                return(false);
                            };
                            ITftpPacket sendPacket;
                            // To initialize the transfer, send WRQ and wait for an ACK of block 0.
                            if (currentBlockNumber == 0)
                            {
                                Console.WriteLine("Sending WRQ");
                                // NOTE: the server only supports octet mode by design.
                                sendPacket = new WrqPacket(fileName, TftpMode.octet);
                                IPEndPoint remoteEP;
                                connection.SendAndWaitForResponse(sendPacket, server, receiveFilter, out remoteEP, cancellationToken);
                                remoteEPReservation = new RemoteEndPointReservation(remoteEP);
                                connection.Connect(remoteEP);
                            }
                            else
                            {
                                // Extract the current block from the file contents and put it in a DATA packet.
                                Console.WriteLine("Sending block {0}", currentBlockNumber);
                                int remainingBytes = file.Length - currentFileIndex;
                                int blockSize;
                                if (remainingBytes < DataPacket.MaxBlockSize)
                                {
                                    blockSize = remainingBytes;
                                    done      = true;
                                }
                                else
                                {
                                    blockSize = DataPacket.MaxBlockSize;
                                }
                                byte[] block = new byte[blockSize];
                                Buffer.BlockCopy(file, currentFileIndex, block, 0, blockSize);
                                currentFileIndex += block.Length;
                                sendPacket        = new DataPacket(blockNumber: currentBlockNumber, data: block);

                                // Send the DATA packet and wait for the corresponding ACK.
                                connection.SendAndWaitForResponse(sendPacket, receiveFilter, cancellationToken);
                            }

                            // Move to the next block.
                            currentBlockNumber++;
                        }
                    }
                    finally
                    {
                        if (remoteEPReservation != null)
                        {
                            remoteEPReservation.Dispose();
                        }
                    }
                }
        }