Example #1
0
        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());
        }
Example #2
0
 public void Read(IPEndPoint server, string fileName, string outputPath, CancellationToken cancellationToken)
 {
     Console.WriteLine("Reading to local file '{0}' from file '{1}' on server {2}", outputPath, fileName, server);
     using (FileStream outputFileStream = new FileStream(outputPath, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
         using (TftpConnection connection = new TftpConnection())
         {
             RemoteEndPointReservation remoteEPReservation = null;
             try
             {
                 bool       initialized        = false;
                 ushort     currentBlockNumber = 1;
                 DataPacket currentDataPacket;
                 AckPacket  ackPacket = null;
                 while (true)
                 {
                     Func <ITftpPacket, bool> receiveFilter = (ITftpPacket packet) =>
                     {
                         if (packet.Op == TftpOperation.Data)
                         {
                             DataPacket d = (DataPacket)packet;
                             if (d.BlockNumber == currentBlockNumber)
                             {
                                 return(true);
                             }
                             else
                             {
                                 Console.WriteLine("Incorrect DATA block number.");
                             }
                         }
                         else
                         {
                             Console.WriteLine("Incorrect operation. Expected DATA.");
                         }
                         return(false);
                     };
                     // To initialize the transfer, send RRQ and wait for the first data block.
                     if (!initialized)
                     {
                         Console.WriteLine("Sending RRQ");
                         // NOTE: the server only supports octet mode by design.
                         RrqPacket  requestPacket = new RrqPacket(fileName, TftpMode.octet);
                         IPEndPoint remoteEP;
                         currentDataPacket   = (DataPacket)connection.SendAndWaitForResponse(requestPacket, server, receiveFilter, out remoteEP, cancellationToken);
                         remoteEPReservation = new RemoteEndPointReservation(remoteEP);
                         connection.Connect(remoteEP);
                         initialized = true;
                     }
                     else
                     {
                         Console.WriteLine("Sending ack for block number {0}", ackPacket.BlockNumber);
                         currentDataPacket = (DataPacket)connection.SendAndWaitForResponse(ackPacket, receiveFilter, cancellationToken);
                     }
                     Console.WriteLine("DATA packet containing block {0} received", currentDataPacket.BlockNumber);
                     outputFileStream.Write(currentDataPacket.Data, 0, currentDataPacket.Data.Length);
                     ackPacket = new AckPacket(currentBlockNumber);
                     // When the received DATA packet is less than the maximum length, send a final ack and terminate.
                     if (currentDataPacket.Data.Length < DataPacket.MaxBlockSize)
                     {
                         connection.Send(ackPacket);
                         break;
                     }
                     ++currentBlockNumber;
                 }
             }
             finally
             {
                 if (remoteEPReservation != null)
                 {
                     remoteEPReservation.Dispose();
                 }
             }
         }
 }