comparison Net/HTTP.cs @ 6:5ce7a138fdba

Improvements in HTTP server
author Ivo Smits <Ivo@UCIS.nl>
date Tue, 08 Jan 2013 16:38:37 +0100
parents 9e2e6433f57a
children 4b78cc5f116b
comparison
equal deleted inserted replaced
5:2933f7750542 6:5ce7a138fdba
2 using System.Collections.Generic; 2 using System.Collections.Generic;
3 using System.IO; 3 using System.IO;
4 using System.Net; 4 using System.Net;
5 using System.Net.Sockets; 5 using System.Net.Sockets;
6 using System.Text; 6 using System.Text;
7 using UCIS.Net;
7 using UCIS.Util; 8 using UCIS.Util;
8 using HTTPHeader = System.Collections.Generic.KeyValuePair<string, string>; 9 using HTTPHeader = System.Collections.Generic.KeyValuePair<string, string>;
9 10
10 namespace UCIS.Net.HTTP { 11 namespace UCIS.Net.HTTP {
11 public class HTTPServer : TCPServer.IModule, IDisposable { 12 public class HTTPServer : TCPServer.IModule, IDisposable {
57 public String RequestQuery { get; private set; } 58 public String RequestQuery { get; private set; }
58 public int HTTPVersion { get; set; } 59 public int HTTPVersion { get; set; }
59 60
60 public Socket Socket { get; private set; } 61 public Socket Socket { get; private set; }
61 public Boolean SuppressStandardHeaders { get; set; } 62 public Boolean SuppressStandardHeaders { get; set; }
62 63 public TCPStream TCPStream { get; private set; }
63 private Stream Stream; 64
64 private StreamWriter Writer; 65 private StreamWriter Writer;
66 private PrebufferingStream Reader;
65 private List<HTTPHeader> RequestHeaders; 67 private List<HTTPHeader> RequestHeaders;
66 private HTTPConnectionState State = HTTPConnectionState.Starting; 68 private HTTPConnectionState State = HTTPConnectionState.Starting;
67 69
68 private enum HTTPConnectionState { 70 private enum HTTPConnectionState {
69 Starting = 0, 71 Starting = 0,
74 Closed = 5, 76 Closed = 5,
75 } 77 }
76 78
77 public HTTPContext(HTTPServer server, TCPStream stream) { 79 public HTTPContext(HTTPServer server, TCPStream stream) {
78 this.Server = server; 80 this.Server = server;
81 this.TCPStream = stream;
79 this.Socket = stream.Socket; 82 this.Socket = stream.Socket;
80 this.LocalEndPoint = Socket.LocalEndPoint; 83 this.LocalEndPoint = Socket.LocalEndPoint;
81 this.RemoteEndPoint = Socket.RemoteEndPoint; 84 this.RemoteEndPoint = Socket.RemoteEndPoint;
82 this.Stream = stream; 85 Init(stream);
83 Init();
84 } 86 }
85 87
86 public HTTPContext(HTTPServer server, Socket socket) { 88 public HTTPContext(HTTPServer server, Socket socket) {
87 this.Server = server; 89 this.Server = server;
90 this.TCPStream = null;
88 this.Socket = socket; 91 this.Socket = socket;
89 this.LocalEndPoint = socket.LocalEndPoint; 92 this.LocalEndPoint = socket.LocalEndPoint;
90 this.RemoteEndPoint = socket.RemoteEndPoint; 93 this.RemoteEndPoint = socket.RemoteEndPoint;
91 this.Stream = new NetworkStream(socket, true); 94 Init(new NetworkStream(socket, true));
92 Init(); 95 }
93 } 96
94 97 private void Init(Stream Stream) {
95 private void Init() {
96 Writer = new StreamWriter(Stream, Encoding.ASCII); 98 Writer = new StreamWriter(Stream, Encoding.ASCII);
97 Writer.NewLine = "\r\n"; 99 Writer.NewLine = "\r\n";
98 Writer.AutoFlush = true; 100 Writer.AutoFlush = true;
99 UCIS.ThreadPool.RunTask(ReceiveOperation, null); 101 Reader = new PrebufferingStream(Stream);
102 Reader.BeginPrebuffering(PrebufferCallback, null);
100 } 103 }
101 104
102 private String ReadLine() { 105 private String ReadLine() {
103 StringBuilder s = new StringBuilder(); 106 StringBuilder s = new StringBuilder();
104 while (true) { 107 while (true) {
105 int b = Stream.ReadByte(); 108 int b = Reader.ReadByte();
106 if (b == -1) { 109 if (b == -1) {
107 if (s.Length == 0) return null; 110 if (s.Length == 0) return null;
108 break; 111 break;
109 } else if (b == 13) { 112 } else if (b == 13) {
110 } else if (b == 10 || b == 0) { 113 } else if (b == 10 || b == 0) {
114 } 117 }
115 } 118 }
116 return s.ToString(); 119 return s.ToString();
117 } 120 }
118 121
119 private void ReceiveOperation(Object state) { 122 private void PrebufferCallback(IAsyncResult ar) {
120 State = HTTPConnectionState.ReceivingRequest; 123 State = HTTPConnectionState.ReceivingRequest;
121 try { 124 try {
125 Reader.EndPrebuffering(ar);
122 String line = ReadLine(); 126 String line = ReadLine();
123 if (line == null) { 127 if (line == null) {
124 Close(); 128 Close();
125 return; 129 return;
126 } 130 }
127 if (Server.ServeFlashPolicyFile && line[0] == '<') { //<policy-file-request/> 131 if (Server.ServeFlashPolicyFile && line[0] == '<') { //<policy-file-request/>
128 Writer.WriteLine("<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>"); 132 Writer.WriteLine("<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>");
129 Stream.WriteByte(0); 133 Reader.WriteByte(0);
130 Close(); 134 Close();
131 return; 135 return;
132 } 136 }
133 String[] request = line.Split(' '); 137 String[] request = line.Split(' ');
134 if (request.Length != 3) goto SendError400AndClose; 138 if (request.Length != 3) goto SendError400AndClose;
246 if (State == HTTPConnectionState.SendingHeaders) { 250 if (State == HTTPConnectionState.SendingHeaders) {
247 Writer.WriteLine(); 251 Writer.WriteLine();
248 State = HTTPConnectionState.SendingContent; 252 State = HTTPConnectionState.SendingContent;
249 } 253 }
250 if (State != HTTPConnectionState.SendingContent) throw new InvalidOperationException(); 254 if (State != HTTPConnectionState.SendingContent) throw new InvalidOperationException();
251 return Stream; 255 return Reader;
252 } 256 }
253 257
254 public void Close() { 258 public void Close() {
255 if (State == HTTPConnectionState.Closed) return; 259 if (State == HTTPConnectionState.Closed) return;
256 Stream.Close(); 260 Reader.Close();
257 State = HTTPConnectionState.Closed; 261 State = HTTPConnectionState.Closed;
258 } 262 }
259 } 263 }
260 264
261 public interface IHTTPContentProvider { 265 public interface IHTTPContentProvider {