Browse Source

commit: tftp timeout added

HOME 5 years ago
parent
commit
80dc76f47b
3 changed files with 42 additions and 27 deletions
  1. 4 2
      TftpServer/App/BlockReader.cs
  2. 0 1
      TftpServer/Protocol/TftpPacket.cs
  3. 38 24
      TftpServer/TftpProgram.cs

+ 4 - 2
TftpServer/App/BlockReader.cs

@@ -5,12 +5,14 @@ namespace TftpServer
 {
     internal class BlockReader : IDisposable
     {
-        public DateTime LastActive { get; set; }
-
         private readonly FileStream _fileStream;
 
+        public string Path { get; }
+        public DateTime LastActive { get; private set; }
+
         public BlockReader(string path)
         {
+            Path = path;
             _fileStream = File.OpenRead(path);
             LastActive = DateTime.Now;
         }

+ 0 - 1
TftpServer/Protocol/TftpPacket.cs

@@ -27,7 +27,6 @@ namespace TftpServer
             get => Options.MapValue("blksize", int.Parse, () => 512);
             set => Options["blksize"] = value.ToString();
         }
-
         public int? TransferSize
         {
             get => Options.MapValue("tsize", s => int.Parse(s), () => (int?)null);

+ 38 - 24
TftpServer/TftpProgram.cs

@@ -1,24 +1,27 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Linq;
 using System.Net;
 using System.Net.Sockets;
 using System.Threading;
 
 namespace TftpServer
 {
-    internal class TftpProgram
+    internal static class TftpProgram
     {
         private static bool _isRunning;
-        private static string Root;
-        private static int TimeOutSecond = 10;
+
+        private static string _root;
+
+        private static int _timeOutSecond = 10;
 
         private static void Main(string[] args)
         {
             Console.WriteLine("Starting...");
 
-            Root = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Properties.Settings.Default.Root);
-            if (false == Directory.Exists(Root))
+            _root = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Properties.Settings.Default.Root);
+            if (false == Directory.Exists(_root))
             {
                 Console.WriteLine("Error: Root path no exist");
             }
@@ -59,10 +62,7 @@ namespace TftpServer
 
             BlockReader GetBlockReader(string path)
             {
-                if (dicBlockReaders.TryGetValue(path, out var br))
-                {
-                    return br;
-                }
+                if (dicBlockReaders.TryGetValue(path, out var br)) return br;
 
                 br = new BlockReader(path);
                 dicBlockReaders[path] = br;
@@ -78,31 +78,48 @@ namespace TftpServer
             var pollingTime = DateTime.Now;
             while (_isRunning)
             {
-                Console.CursorLeft = 0;
+                var now = DateTime.Now;
+                var timeout = false;
+                foreach (var item in dicBlockReaders.ToArray())
+                {
+                    if (!((now - item.Value.LastActive).TotalSeconds > _timeOutSecond)) continue;
+                    timeout = true;
+                    dicBlockReaders.Remove(item.Key);
+                    item.Value.Dispose();
+                    Console.WriteLine($"File closed by Timeout: {item.Value.Path}");
+                }
 
-                //TODO: Timeout
+                foreach (var item in dicSessions.ToArray())
+                {
+                    if (!((now - item.Value.LastActive).TotalSeconds > _timeOutSecond)) continue;
+                    timeout = true;
+                    dicSessions.Remove(item.Key);
+                    Console.WriteLine($"Session removed by Timeout: {item.Key}");
+                }
+
+                if (timeout) Console.WriteLine();
 
                 if (false == socket.Poll(500 * 1000, SelectMode.SelectRead))
                 {
+                    Console.CursorLeft = 0;
+                    --Console.CursorTop;
                     var polling = DateTime.Now - pollingTime;
                     var up = DateTime.Now - upTime;
-                    Console.Write($"Polling..." +
+                    Console.WriteLine($"Polling..." +
                                   $" {polling.Days:00}D {polling.Hours:00}H {polling.Minutes:00}M {polling.Seconds:00}S {polling.Milliseconds:000}" +
                                   $" / UP {up.Days:00}D {up.Hours:00}H {up.Minutes:00}M {up.Seconds:00}S {up.Milliseconds:000}");
                 }
                 else
                 {
-                    Console.WriteLine();
-
                     do
                     {
                         var bytes = socket.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref remoteEndPoint);
-                        Console.Write($"Receive {bytes} byte From {remoteEndPoint}");
+                        Console.Write($"Receive {bytes} byte From {remoteEndPoint} ");
 
                         try
                         {
                             var packet = new TftpPacket(buffer, bytes);
-                            Console.Write($" OpCode:{packet.OpCode}");
+                            Console.Write($"OpCode:{packet.OpCode}");
 
                             TftpTransferSession session;
                             switch (packet.OpCode)
@@ -110,19 +127,16 @@ namespace TftpServer
                                 default: throw new NotImplementedException();
 
                                 case TftpOpCode.Error:
-                                    Console.Write($" {packet.ErrorNumber} 0x{(short)packet.ErrorNumber:X4} {packet.ErrorMessage}");
-                                    if (dicSessions.Remove(remoteEndPoint))
-                                    {
-                                        Console.Write(" Session closed");
-                                    }
+                                    Console.Write($"{packet.ErrorNumber} 0x{(short)packet.ErrorNumber:X4} {packet.ErrorMessage} ");
+                                    if (dicSessions.Remove(remoteEndPoint)) Console.Write("Session closed");
                                     break;
 
                                 case TftpOpCode.Read:
-                                    Console.Write($" FileName:{packet.FileName} [{packet.Mode}] BlockSize:{packet.BlockSize}");
-                                    var path = Path.Combine(Root, packet.FileName.TrimStart('/'));
+                                    Console.Write($"FileName:{packet.FileName} [{packet.Mode}] BlockSize:{packet.BlockSize} ");
+                                    var path = Path.Combine(_root, packet.FileName.TrimStart('/'));
                                     if (false == File.Exists(path))
                                     {
-                                        Console.Write(" ** File Not Found");
+                                        Console.Write("** File Not Found ");
                                         var response = new TftpPacket("File Not Found", TftpErrorNumber.FileNoFound);
                                         bytes = response.WriteToBuffer(buffer);