-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathHttpServer2.cs
124 lines (114 loc) · 3.01 KB
/
HttpServer2.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
using System;
using System.IO;
using System.Net.Sockets;
using static WebOne.Program;
namespace WebOne
{
/// <summary>
/// HTTP/1.1 Listener and Server (TcpClient-based).
/// </summary>
class HttpServer2 : HttpServer
{
/* This is the new version of HTTP Listener/Server, made for WebOne 0.16+.
* Pluses: almost full HTTP 0.9/1.0/1.1 support, including CONNECT method and GET to ftp:// addresses
* Minuses: ...time will show...
* https://www.codeproject.com/Articles/93301/Implementing-a-Multithreaded-HTTP-HTTPS-Debugging
*/
private int Port;
private static TcpListener Listener;
private LogWriter Log = new();
/// <summary>
/// Status of this HTTP Server.
/// </summary>
public override bool Working { get; set; }
/// <summary>
/// Initizlize a HTTP Listener & Server (TcpClient-based).
/// </summary>
/// <param name="port">TCP Port to listen on.</param>
public HttpServer2(int port) : base(port)
{
Port = port;
Working = false;
Listener = new(System.Net.IPAddress.Any, Port);
}
/// <summary>
/// Start this HTTP Server.
/// </summary>
public override void Start()
{
Listener.Start();
Listener.BeginAcceptTcpClient(ProcessConnection, null);
Working = true;
Log.WriteLine(true, false, "Supported protocols: HTTP{0}, FTP via Web browser.", (ConfigFile.SslEnable ? ", HTTPS" : " (plain)"));
UpdateStatistics();
}
/// <summary>
/// Gracefully stop this HTTP Server.
/// </summary>
public override void Stop()
{
Working = false;
Log.BeginTime = DateTime.Now;
if (Listener != null)
{
Listener.Stop();
}
Log.WriteLine(true, true, "HTTP/HTTPS/CERN Server stopped.");
}
/// <summary>
/// Process a HTTP request (callback for TcpListener).
/// </summary>
/// <param name="ar">Something from TcpListener.</param>
private void ProcessConnection(IAsyncResult ar)
{
if (!Working) return;
Load++;
UpdateStatistics();
LogWriter Logger = new();
#if DEBUG
Logger.WriteLine("Got a connection.");
#endif
TcpClient Client = null;
try
{
Client = Listener.EndAcceptTcpClient(ar);
Listener.BeginAcceptTcpClient(ProcessConnection, null);
}
catch
{
Logger.WriteLine("Connection unexpectedly lost.");
Load--;
UpdateStatistics();
return;
}
try
{
new HttpRequestProcessor().ProcessClientRequest(Client, Logger);
}
catch (IOException)
{
/*Timeouts, unexpected socket close, etc*/
#if DEBUG
Logger.WriteLine("Connection closed.");
#endif
}
catch (Exception ex)
{
Logger.WriteLine("Oops: {0}.", ex.Message);
try { Client.Close(); } catch { }
}
Load--;
UpdateStatistics();
}
/// <summary>
/// Display count of open requests in app's titlebar.
/// </summary>
private void UpdateStatistics()
{
if (DaemonMode)
Console.Title = string.Format("WebOne (silent) @ {0}:{1} [{2}]", ConfigFile.DefaultHostName, Port, Load);
else
Console.Title = string.Format("WebOne @ {0}:{1} [{2}]", ConfigFile.DefaultHostName, Port, Load);
}
}
}