|
@@ -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);
|
|
|
|