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; } } }
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"); }
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); }
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); }
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); }
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"); }
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); }
/// <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); }
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); }
/// <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; }
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; }
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; }