public TFTPSession(TFTPServer parent, UDPSocket socket, IPEndPoint remoteEndPoint, Dictionary <string, string> requestedOptions, string filename, UDPSocket.OnReceiveDelegate onReceive, int socketDisposeDelay) { m_Parent = parent; m_CurrentBlockSize = TFTPServer.DefaultBlockSize; m_ResponseTimeout = m_Parent.m_ResponseTimeout; m_RemoteEndPoint = remoteEndPoint; m_Timer = new Timer(new System.Threading.TimerCallback(OnTimer), this, Timeout.Infinite, Timeout.Infinite); m_RequestedOptions = requestedOptions; m_Filename = filename; m_SocketDisposeDelay = socketDisposeDelay; m_Length = 0; m_LastBlock = false; m_BlockNumber = 0; m_BlockRetry = 0; foreach (var kvp in m_RequestedOptions) { switch (kvp.Key) { case TFTPServer.Option_Multicast: // not supported break; case TFTPServer.Option_Timeout: //Console.WriteLine("Timeout of {0}", kvp.Value); int requestedTimeout = int.Parse(kvp.Value); // rfc2349 : valid values range between "1" and "255" seconds if (requestedTimeout >= 1 && requestedTimeout <= 255) { m_ResponseTimeout = requestedTimeout * 1000; m_AcceptedOptions.Add(TFTPServer.Option_Timeout, kvp.Value); } break; case TFTPServer.Option_TransferSize: // handled in inherited classes break; case TFTPServer.Option_BlockSize: //Console.WriteLine("Blocksize of {0}", kvp.Value); int requestedBlockSize = int.Parse(kvp.Value); // rfc2348 : valid values range between "8" and "65464" octets, inclusive if (requestedBlockSize >= 8 && requestedBlockSize <= 65464) { m_CurrentBlockSize = Math.Min(TFTPServer.MaxBlockSize, requestedBlockSize); m_AcceptedOptions.Add(TFTPServer.Option_BlockSize, m_CurrentBlockSize.ToString()); } break; } } if (socket != null) { m_OwnSocket = false; m_Socket = socket; } else { m_OwnSocket = true; m_Socket = new UDPSocket( new IPEndPoint(m_Parent.m_ServerEndPoint.Address, 0), m_CurrentBlockSize + 4, m_Parent.m_DontFragment, m_Parent.m_Ttl, onReceive, (sender, reason) => { Stop(true, reason); }); } m_LocalEndPoint = (IPEndPoint)m_Socket.LocalEndPoint; }
public UploadSession(TFTPServer parent, UDPSocket socket, IPEndPoint remoteEndPoint, Dictionary <string, string> requestedOptions, string filename, UDPSocket.OnReceiveDelegate onReceive) : base(parent, socket, remoteEndPoint, requestedOptions, filename, onReceive, 1000) { }
internal static void SendError(UDPSocket socket, IPEndPoint endPoint, ErrorCode code, string message) { SendError(socket, endPoint, (ushort)code, message); }
internal static void Send(UDPSocket socket, IPEndPoint endPoint, MemoryStream ms) { socket.Send(endPoint, new ArraySegment <byte>(ms.ToArray())); }
internal static void Send(UDPSocket socket, IPEndPoint endPoint, ArraySegment <byte> data) { socket.Send(endPoint, data); }
private void OnUDPStop(UDPSocket sender, Exception reason) { Stop(reason); }
private void OnUDPReceive(UDPSocket sender, IPEndPoint endPoint, ArraySegment <byte> data) { bool notify = false; int packetSize = data.Count; MemoryStream ms = new MemoryStream(data.Array, data.Offset, data.Count, false, true); ITFTPSession session; bool found; ushort opCode = ReadUInt16(ms); lock (m_Sessions) { found = m_Sessions.TryGetValue(endPoint, out session); } // is there a session in progress for that endpoint? if (found) { // yes. switch ((Opcode)opCode) { case Opcode.ReadRequest: // session already exists, and we're getting a new readrequest? SendError(sender, endPoint, ErrorCode.IllegalOperation, "Read session already in progress"); break; case Opcode.WriteRequest: // session already exists, and we're getting a new writerequest? SendError(sender, endPoint, ErrorCode.IllegalOperation, "Write session already in progress"); break; case Opcode.Data: session.ProcessData(ReadUInt16(ms), new ArraySegment <byte>(data.Array, (int)(data.Offset + ms.Position), (int)(data.Count - ms.Position))); break; case Opcode.Ack: session.ProcessAck(ReadUInt16(ms)); break; case Opcode.Error: ushort code = ReadUInt16(ms); string msg = ReadZString(ms); session.ProcessError(code, msg); break; case Opcode.OptionsAck: break; default: SendError(sender, endPoint, ErrorCode.IllegalOperation, "Unknown opcode"); break; } } else // session==null { // no session in progress for the endpoint that sent the packet switch ((Opcode)opCode) { case Opcode.ReadRequest: { string filename = ReadZString(ms); if (m_ConvertPathSeparator) { filename = filename.Replace('/', '\\'); } Mode mode = ReadMode(ms); var requestedOptions = ReadOptions(ms); ushort windowSize = GetWindowSize(filename); ITFTPSession newSession = new DownloadSession(this, m_UseSinglePort ? m_Socket : null, endPoint, requestedOptions, filename, windowSize, OnUDPReceive); lock (m_Sessions) { m_Sessions.Add(newSession.RemoteEndPoint, newSession); } notify = true; Trace(string.Format("Starting transfer of file '{0}' from local '{1}' to remote '{2}', send window size {3}", newSession.Filename, newSession.LocalEndPoint, newSession.RemoteEndPoint, windowSize)); newSession.Start(); } break; case Opcode.WriteRequest: { string filename = ReadZString(ms); if (m_ConvertPathSeparator) { filename = filename.Replace('/', '\\'); } Mode mode = ReadMode(ms); var requestedOptions = ReadOptions(ms); ITFTPSession newSession = new UploadSession(this, m_UseSinglePort ? m_Socket : null, endPoint, requestedOptions, filename, OnUDPReceive); lock (m_Sessions) { m_Sessions.Add(newSession.RemoteEndPoint, newSession); } notify = true; Trace(string.Format("Starting transfer of file '{0}' from remote '{1}' to local '{2}'", newSession.Filename, newSession.RemoteEndPoint, newSession.LocalEndPoint)); newSession.Start(); } break; default: SendError(m_Socket, endPoint, (ushort)ErrorCode.UnknownTransferID, "Unknown transfer ID"); break; } } if (notify) { OnStatusChange(this, null); } }