Mercurial > hg > ucis.core
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 { |