예제 #1
0
        private TFTPPacket ReceivePacket(int timeout)
        {
            if (timeout <= 0)
            {
                return(null);
            }

            try
            {
                m_Socket.ReceiveTimeout = timeout;
                EndPoint responseEndPoint = new IPEndPoint(m_ServerEndPoint.Address, m_ServerEndPoint.Port);
                int      len    = m_Socket.ReceiveFrom(m_ReceiveBuffer, ref responseEndPoint);
                var      result = TFTPPacket.Deserialize(new MemoryStream(m_ReceiveBuffer, 0, len, false, true));
                result.EndPoint = (IPEndPoint)responseEndPoint;
                Trace(() => string.Format("<- [{0}] {1}", result.EndPoint, result.ToString()));
                return(result);
            }
            catch (SocketException e)
            {
                if (e.SocketErrorCode == SocketError.TimedOut)
                {
                    return(null);
                }
                else
                {
                    throw;
                }
            }
        }
예제 #2
0
        public void Upload(string filename, Stream stream)
        {
            m_IsUpload = true;
            Init(filename, stream);

            try
            {
                m_TransferSize = stream.Length;

                if (m_TransferSize >= 0)
                {
                    m_RequestedOptions.Add(Option_TransferSize, m_TransferSize.ToString(CultureInfo.InvariantCulture));
                }
                else
                {
                    m_TransferSize = -1;
                }
            }
            catch
            {
                m_TransferSize = -1;
            }

            m_BlockNumber = 0;
            m_Request     = new TFTPPacket_WriteRequest()
            {
                EndPoint = m_ServerEndPoint, Filename = filename, Options = m_RequestedOptions
            };
            Progress(true);
            PumpPackets(p => FilterPacket(p, DoUpload));
            Progress(true);
            Trace(() => "Upload complete");
        }
예제 #3
0
        private Instruction DoDownload(TFTPPacket packet)
        {
            Instruction result = Instruction.Drop;

            switch (packet.Code)
            {
            case Opcode.OptionsAck:
                if (m_Init)
                {
                    HandleOptionsAck((TFTPPacket_OptionsAck)packet);
                    // If the transfer was initiated with a Read Request, then an ACK (with the data block number set to 0) is sent by the client to confirm
                    // the values in the server's OACK packet.
                    m_Request = new TFTPPacket_Ack()
                    {
                        EndPoint = packet.EndPoint, BlockNumber = 0
                    };
                    result = Instruction.SendNew;
                    Progress(true);
                }
                else
                {
                    // received another optionsack, probably the server resent it because our ack(0) was lost. drop it.
                    result = Instruction.Drop;
                }
                break;

            case Opcode.Data:
            {
                var responseData = (TFTPPacket_Data)packet;
                // did we receive the expected blocknumber ?
                if (responseData.BlockNumber == m_BlockNumber)
                {
                    m_Request = new TFTPPacket_Ack {
                        EndPoint = packet.EndPoint, BlockNumber = m_BlockNumber
                    };
                    m_Stream.Write(responseData.Data.Array, responseData.Data.Offset, responseData.Data.Count);
                    m_BlockNumber++;
                    result         = (responseData.Data.Count < m_BlockSize) ? Instruction.SendFinal : Instruction.SendNew;
                    m_Transferred += responseData.Data.Count;
                    Progress(false);
                }
                else
                {
                    // not the correct block, drop it (maybe the next one will be ok)
                    result = Instruction.Drop;
                }
            }
            break;

            case Opcode.Error:
                HandleError((TFTPPacket_Error)packet);
                break;

            default:
                throw new TFTPException("Illegal server response");
            }
            return(result);
        }
예제 #4
0
        private void SendPacket(TFTPPacket msg)
        {
            Trace(() => $"-> [{msg.EndPoint}] {msg.ToString()}");
            var ms = new MemoryStream();

            msg.Serialize(ms);
            byte[] buffer = ms.ToArray();
            _socket.SendTo(buffer, 0, buffer.Length, SocketFlags.None, msg.EndPoint);
        }
예제 #5
0
        private void SendPacket(TFTPPacket msg)
        {
            Trace(() => string.Format("-> [{0}] {1}", msg.EndPoint, msg.ToString()));
            var ms = new MemoryStream();

            msg.Serialize(ms);
            byte[] buffer = ms.ToArray();
            m_Socket.SendTo(buffer, 0, buffer.Length, SocketFlags.None, msg.EndPoint);
        }
예제 #6
0
 public void Download(string filename, Stream stream)
 {
     m_IsUpload = false;
     Init(filename, stream);
     m_RequestedOptions.Add(Option_TransferSize, "0");
     m_BlockNumber = 1;
     m_Request     = new TFTPPacket_ReadRequest()
     {
         EndPoint = m_ServerEndPoint, Filename = filename, Options = m_RequestedOptions
     };
     Progress(true);
     PumpPackets(p => FilterPacket(p, DoDownload));
     Progress(true);
     Trace(() => "Download complete");
 }
예제 #7
0
            public static TFTPPacket Deserialize(Stream s)
            {
                TFTPPacket result = null;

                long   startPosition = s.Position;
                Opcode c             = (Opcode)ReadUInt16(s);

                s.Position = startPosition;

                switch (c)
                {
                case Opcode.Ack:
                    result = new TFTPPacket_Ack(s);
                    break;

                case Opcode.Data:
                    result = new TFTPPacket_Data(s);
                    break;

                case Opcode.Error:
                    result = new TFTPPacket_Error(s);
                    break;

                case Opcode.OptionsAck:
                    result = new TFTPPacket_OptionsAck(s);
                    break;

                case Opcode.ReadRequest:
                    result = new TFTPPacket_ReadRequest(s);
                    break;

                case Opcode.WriteRequest:
                    result = new TFTPPacket_WriteRequest(s);
                    break;

                default:
                    result = new TFTPPacket_Unknown(s);
                    break;
                }

                return(result);
            }
예제 #8
0
        /// <summary>
        /// This method does the first level of response interpretation (see: PumpPackets). It takes care of the following tasks:
        /// - on timeout receiving the response : retry sending the request
        /// - drop responses that aren't from the expected sender
        /// - everything else: forward them to the next level of response interpretation by way of calling the lambda function.
        /// </summary>
        /// <param name="packet">the incoming response packet, or null on timeout</param>
        /// <param name="step">the nested packet interpretation function</param>
        /// <returns></returns>
        private Instruction FilterPacket(TFTPPacket packet, Func <TFTPPacket, Instruction> step)
        {
            // on timeout receiving the response : retry sending the request
            if (packet == null)
            {
                return(Instruction.Retry);
            }

            /// packet isn't coming from the expected address: drop
            if (!packet.EndPoint.Address.Equals(m_PeerEndPoint.Address))
            {
                Trace(() => string.Format("Got response from {0}, but {1} expected, dropping packet", packet.EndPoint, m_PeerEndPoint));
                return(Instruction.Drop);
            }

            if (!m_Init)
            {
                /// packet isn't coming from the expected port: drop
                if (packet.EndPoint.Port != m_PeerEndPoint.Port)
                {
                    Trace(() => string.Format("Got response from {0}, but {1} expected, dropping packet", packet.EndPoint, m_PeerEndPoint));
                    return(Instruction.Drop);
                }
            }

            // packet checks out ok, let the nested function interpret it
            var result = step(packet);

            // if the nested function accepted the packet, it's safe to assume that the packet endpoint is
            // the peer endpoint that we should check for from now on.
            if (result != Instruction.Drop && result != Instruction.Retry)
            {
                m_PeerEndPoint = packet.EndPoint;
                m_Init         = false;
            }

            return(result);
        }
예제 #9
0
        private Instruction DoUpload(TFTPPacket packet)
        {
            Instruction result = Instruction.Drop;

            switch (packet.Code)
            {
            case Opcode.OptionsAck:
                if (m_Init)
                {
                    HandleOptionsAck((TFTPPacket_OptionsAck)packet);
                    Progress(true);
                    // If the transfer was initiated with a Write Request, then the client begins the transfer with the first DATA packet (blocknr=1), using the negotiated values.
                    // If the client rejects the OACK, then it sends an ERROR packet, with error code 8, to the server and the transfer is terminated.
                    m_BlockNumber++;
                    m_Request = new TFTPPacket_Data()
                    {
                        EndPoint = packet.EndPoint, BlockNumber = m_BlockNumber, Data = ReadData(m_Stream, m_BlockSize)
                    };
                    result         = Instruction.SendNew;
                    m_Transferred += ((TFTPPacket_Data)m_Request).Data.Count;
                }
                else
                {
                    // received another optionsack, probably the server resent it because our first datapacket was lost. drop it.
                    result = Instruction.Drop;
                }
                break;

            case Opcode.Ack:
            {
                var responseData = (TFTPPacket_Ack)packet;
                m_PeerEndPoint = packet.EndPoint;
                // did we receive the expected blocknumber ?
                if (responseData.BlockNumber == m_BlockNumber)
                {
                    Progress(false);
                    // was the outstanding request a data packet, and the last one?
                    if (m_Request is TFTPPacket_Data && ((TFTPPacket_Data)m_Request).Data.Count < m_BlockSize)
                    {
                        // that was the ack for the last packet, we're done
                        result = Instruction.Done;
                    }
                    else
                    {
                        m_BlockNumber++;
                        m_Request = new TFTPPacket_Data()
                        {
                            EndPoint = packet.EndPoint, BlockNumber = m_BlockNumber, Data = ReadData(m_Stream, m_BlockSize)
                        };
                        result         = Instruction.SendNew;
                        m_Transferred += ((TFTPPacket_Data)m_Request).Data.Count;
                    }
                }
                else
                {
                    // not the correct block, drop it (maybe the next one will be ok)
                    result = Instruction.Drop;
                }
            }
            break;

            case Opcode.Error:
                HandleError((TFTPPacket_Error)packet);
                break;

            default:
                throw new TFTPException("Illegal server response");
            }
            return(result);
        }
예제 #10
0
 private void SendPacket(TFTPPacket msg)
 {
     Trace(() => string.Format("-> [{0}] {1}", msg.EndPoint, msg.ToString()));
     var ms = new MemoryStream();
     msg.Serialize(ms);
     byte[] buffer = ms.ToArray();
     m_Socket.SendTo(buffer, 0, buffer.Length, SocketFlags.None, msg.EndPoint);
 }
예제 #11
0
        /// <summary>
        /// This method does the first level of response interpretation (see: PumpPackets). It takes care of the following tasks:
        /// - on timeout receiving the response : retry sending the request
        /// - drop responses that aren't from the expected sender
        /// - everything else: forward them to the next level of response interpretation by way of calling the lambda function.
        /// </summary>
        /// <param name="packet">the incoming response packet, or null on timeout</param>
        /// <param name="step">the nested packet interpretation function</param>
        /// <returns></returns>
        private Instruction FilterPacket(TFTPPacket packet, Func<TFTPPacket, Instruction> step)
        {
            // on timeout receiving the response : retry sending the request
            if (packet == null) return Instruction.Retry;

            /// packet isn't coming from the expected address: drop
            if (!packet.EndPoint.Address.Equals(m_PeerEndPoint.Address))
            {
                Trace(() => string.Format("Got response from {0}, but {1} expected, dropping packet", packet.EndPoint, m_PeerEndPoint));
                return Instruction.Drop;
            }

            if (!m_Init)
            {
                /// packet isn't coming from the expected port: drop
                if (packet.EndPoint.Port != m_PeerEndPoint.Port)
                {
                    Trace(() => string.Format("Got response from {0}, but {1} expected, dropping packet", packet.EndPoint, m_PeerEndPoint));
                    return Instruction.Drop;
                }
            }

            // packet checks out ok, let the nested function interpret it
            var result = step(packet);

            // if the nested function accepted the packet, it's safe to assume that the packet endpoint is
            // the peer endpoint that we should check for from now on.
            if (result != Instruction.Drop && result != Instruction.Retry)
            {
                m_PeerEndPoint = packet.EndPoint;
                m_Init = false;
            }

            return result;
        }
예제 #12
0
        private Instruction DoUpload(TFTPPacket packet)
        {
            Instruction result = Instruction.Drop;

            switch (packet.Code)
            {
                case Opcode.OptionsAck:
                    if (m_Init)
                    {
                        HandleOptionsAck((TFTPPacket_OptionsAck)packet);
                        Progress(true);
                        // If the transfer was initiated with a Write Request, then the client begins the transfer with the first DATA packet (blocknr=1), using the negotiated values.
                        // If the client rejects the OACK, then it sends an ERROR packet, with error code 8, to the server and the transfer is terminated.
                        m_BlockNumber++;
                        m_Request = new TFTPPacket_Data() { EndPoint = packet.EndPoint, BlockNumber = m_BlockNumber, Data = ReadData(m_Stream, m_BlockSize) };
                        result = Instruction.SendNew;
                        m_Transferred += ((TFTPPacket_Data)m_Request).Data.Count;
                    }
                    else
                    {
                        // received another optionsack, probably the server resent it because our first datapacket was lost. drop it.
                        result = Instruction.Drop;
                    }
                    break;

                case Opcode.Ack:
                    {
                        var responseData = (TFTPPacket_Ack)packet;
                        m_PeerEndPoint = packet.EndPoint;
                        // did we receive the expected blocknumber ?
                        if (responseData.BlockNumber == m_BlockNumber)
                        {
                            Progress(false);
                            // was the outstanding request a data packet, and the last one?
                            if (m_Request is TFTPPacket_Data && ((TFTPPacket_Data)m_Request).Data.Count < m_BlockSize)
                            {
                                // that was the ack for the last packet, we're done
                                result = Instruction.Done;
                            }
                            else
                            {
                                m_BlockNumber++;
                                m_Request = new TFTPPacket_Data() { EndPoint = packet.EndPoint, BlockNumber = m_BlockNumber, Data = ReadData(m_Stream, m_BlockSize) };
                                result = Instruction.SendNew;
                                m_Transferred += ((TFTPPacket_Data)m_Request).Data.Count;
                            }
                        }
                        else
                        {
                            // not the correct block, drop it (maybe the next one will be ok)
                            result = Instruction.Drop;
                        }
                    }
                    break;

                case Opcode.Error:
                    HandleError((TFTPPacket_Error)packet);
                    break;

                default:
                    throw new TFTPException("Illegal server response");
            }
            return result;
        }
예제 #13
0
        private Instruction DoDownload(TFTPPacket packet)
        {
            Instruction result = Instruction.Drop;

            switch (packet.Code)
            {
                case Opcode.OptionsAck:
                    if (m_Init)
                    {
                        HandleOptionsAck((TFTPPacket_OptionsAck)packet);
                        // If the transfer was initiated with a Read Request, then an ACK (with the data block number set to 0) is sent by the client to confirm
                        // the values in the server's OACK packet.
                        m_Request = new TFTPPacket_Ack() { EndPoint = packet.EndPoint, BlockNumber = 0 };
                        result = Instruction.SendNew;
                        Progress(true);
                    }
                    else
                    {
                        // received another optionsack, probably the server resent it because our ack(0) was lost. drop it.
                        result = Instruction.Drop;
                    }
                    break;

                case Opcode.Data:
                    {
                        var responseData = (TFTPPacket_Data)packet;
                        // did we receive the expected blocknumber ?
                        if (responseData.BlockNumber == m_BlockNumber)
                        {
                            m_Request = new TFTPPacket_Ack { EndPoint = packet.EndPoint, BlockNumber = m_BlockNumber };
                            m_Stream.Write(responseData.Data.Array, responseData.Data.Offset, responseData.Data.Count);
                            m_BlockNumber++;
                            result = (responseData.Data.Count < m_BlockSize) ? Instruction.SendFinal : Instruction.SendNew;
                            m_Transferred += responseData.Data.Count;
                            Progress(false);
                        }
                        else
                        {
                            // not the correct block, drop it (maybe the next one will be ok)
                            result = Instruction.Drop;
                        }
                    }
                    break;

                case Opcode.Error:
                    HandleError((TFTPPacket_Error)packet);
                    break;

                default:
                    throw new TFTPException("Illegal server response");
            }
            return result;
        }
예제 #14
0
        public void Upload(string filename, Stream stream)
        {
            m_IsUpload = true;
            Init(filename, stream);

            try
            {
                m_TransferSize = stream.Length;

                if (m_TransferSize >= 0)
                {
                    m_RequestedOptions.Add(Option_TransferSize, m_TransferSize.ToString(CultureInfo.InvariantCulture));
                }
                else
                {
                    m_TransferSize = -1;
                }
            }
            catch
            {
                m_TransferSize = -1;
            }

            m_BlockNumber = 0;
            m_Request = new TFTPPacket_WriteRequest() { EndPoint = m_ServerEndPoint, Filename = filename, Options = m_RequestedOptions };
            Progress(true);
            PumpPackets(p => FilterPacket(p, DoUpload));
            Progress(true);
            Trace(() => "Upload complete");
        }
예제 #15
0
 public void Download(string filename, Stream stream)
 {
     m_IsUpload = false;
     Init(filename, stream);
     m_RequestedOptions.Add(Option_TransferSize, "0");
     m_BlockNumber = 1;
     m_Request = new TFTPPacket_ReadRequest() { EndPoint = m_ServerEndPoint, Filename = filename, Options = m_RequestedOptions };
     Progress(true);
     PumpPackets(p => FilterPacket(p, DoDownload));
     Progress(true);
     Trace(() => "Download complete");
 }