Dont index style nodes.
[beagle.git] / beagled / WebServices / WebServer / XSPApplicationHost.cs
blob4e2e320bbe36d23b9393c6e76343199d4ff0f889
1 //
2 // Mono.ASPNET.XSPApplicationHost
3 //
4 // Authors:
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // (C) Copyright 2004 Novell, Inc. (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System;
31 using System.IO;
32 using System.Net;
33 using System.Net.Sockets;
34 using System.Text;
35 using System.Web;
37 namespace Mono.ASPNET
40 // XSPWebSource: Provides methods to get objects and types specific
41 // to XSP.
43 public class XSPWebSource: IWebSource
45 IPEndPoint bindAddress;
47 public XSPWebSource (IPAddress address, int port)
49 SetListenAddress (address, port);
52 public void SetListenAddress (int port)
54 SetListenAddress (IPAddress.Any, port);
57 public void SetListenAddress (IPAddress address, int port)
59 SetListenAddress (new IPEndPoint (address, port));
62 public void SetListenAddress (IPEndPoint bindAddress)
64 if (bindAddress == null)
65 throw new ArgumentNullException ("bindAddress");
67 this.bindAddress = bindAddress;
70 public Socket CreateSocket ()
72 Socket listen_socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
73 listen_socket.Bind (bindAddress);
74 return listen_socket;
77 public IWorker CreateWorker (Socket client, ApplicationServer server)
79 return new XSPWorker (client, client.LocalEndPoint, server);
82 public Type GetApplicationHostType ()
84 return typeof (XSPApplicationHost);
87 public IRequestBroker CreateRequestBroker ()
89 return new XSPRequestBroker ();
92 public void Dispose ()
98 // XSPRequestBroker: The request broker for XSP. Provides some
99 // additional methods to the BaseRequestBroker from which inherits.
101 public class XSPRequestBroker: BaseRequestBroker
103 public bool IsConnected (int requestId)
105 return ((XSPWorker)GetWorker (requestId)).IsConnected ();
108 public int GetReuseCount (int requestId)
110 XSPWorker worker = (XSPWorker) GetWorker (requestId);
111 return worker.GetReuseCount ();
114 public void Close (int requestId, bool keepAlive)
116 XSPWorker worker = (XSPWorker) GetWorker (requestId);
117 if (worker != null) {
118 try {
119 worker.Close (keepAlive);
120 } catch {}
126 // XSPApplicationHost: The application host for XSP.
128 public class XSPApplicationHost : BaseApplicationHost
130 public void ProcessRequest (int reqId, long localEPAddr, int localEPPort, long remoteEPAdds,
131 int remoteEPPort, string verb, string path,
132 string queryString, string protocol, byte [] inputBuffer, string redirect)
134 XSPRequestBroker broker = (XSPRequestBroker) RequestBroker;
135 IPEndPoint localEP = new IPEndPoint (localEPAddr, localEPPort);
136 IPEndPoint remoteEP = new IPEndPoint (remoteEPAdds, remoteEPPort);
137 XSPWorkerRequest mwr = new XSPWorkerRequest (reqId, broker, this, localEP, remoteEP, verb, path,
138 queryString, protocol, inputBuffer);
140 string translated = mwr.GetFilePathTranslated ();
141 if (path [path.Length - 1] != '/' && Directory.Exists (translated))
142 redirect = path + '/';
144 if (redirect != null) {
145 Redirect (mwr, redirect);
146 broker.UnregisterRequest (reqId);
147 return;
150 ProcessRequest (mwr);
153 static string content301 = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" +
154 "<html><head>\n<title>301 Moved Permanently</title>\n</head><body>\n" +
155 "<h1>Moved Permanently</h1>\n" +
156 "<p>The document has moved to <a href='http://{0}{1}'>http://{0}{1}</a>.</p>\n" +
157 "</body></html>\n";
159 static void Redirect (XSPWorkerRequest wr, string location)
161 string host = wr.GetKnownRequestHeader (HttpWorkerRequest.HeaderHost);
162 wr.SendStatus (301, "Moved Permanently");
163 wr.SendUnknownResponseHeader ("Connection", "close");
164 wr.SendUnknownResponseHeader ("Date", DateTime.Now.ToUniversalTime ().ToString ("r"));
165 wr.SendUnknownResponseHeader ("Location", String.Format ("http://{0}{1}", host, location));
166 Encoding enc = Encoding.ASCII;
167 wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName);
168 string content = String.Format (content301, host, location);
169 byte [] contentBytes = enc.GetBytes (content);
170 wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ());
171 wr.SendResponseFromMemory (contentBytes, contentBytes.Length);
172 wr.FlushResponse (true);
173 wr.CloseConnection ();
178 // XSPWorker: The worker that do the initial processing of XSP
179 // requests.
181 internal class XSPWorker: IWorker
183 ApplicationServer server;
184 LingeringNetworkStream stream;
185 IPEndPoint remoteEP;
186 IPEndPoint localEP;
187 Socket sock;
189 public XSPWorker (Socket client, EndPoint localEP, ApplicationServer server)
191 stream = new LingeringNetworkStream (client, false);
192 sock = client;
193 this.server = server;
195 try {
196 remoteEP = (IPEndPoint) client.RemoteEndPoint;
197 } catch { }
198 this.localEP = (IPEndPoint) localEP;
201 public int GetReuseCount ()
203 return server.GetAvailableReuses (sock);
206 public void Run (object state)
208 int requestId = -1;
209 XSPRequestBroker broker = null;
211 try {
212 if (remoteEP == null)
213 return;
215 InitialWorkerRequest ir = new InitialWorkerRequest (stream);
216 try {
217 ir.ReadRequestData ();
218 } catch (Exception ex) {
219 if (ir.GotSomeInput) {
220 byte [] badReq = HttpErrors.BadRequest ();
221 Write (badReq, 0, badReq.Length);
224 throw ex;
227 RequestData rdata = ir.RequestData;
228 string vhost = null; // TODO: read the headers in InitialWorkerRequest
229 int port = ((IPEndPoint) localEP).Port;
231 VPathToHost vapp = server.GetApplicationForPath (vhost, port, rdata.Path, true);
232 XSPApplicationHost host = null;
233 if (vapp != null)
234 host = (XSPApplicationHost) vapp.AppHost;
236 if (host == null) {
237 byte [] nf = HttpErrors.NotFound (rdata.Path);
238 Write (nf, 0, nf.Length);
239 Close ();
240 return;
243 broker = (XSPRequestBroker) vapp.RequestBroker;
244 requestId = broker.RegisterRequest (this);
246 string redirect;
247 vapp.Redirect (rdata.Path, out redirect);
248 host.ProcessRequest (requestId, localEP.Address.Address, localEP.Port,
249 remoteEP.Address.Address, remoteEP.Port, rdata.Verb,
250 rdata.Path, rdata.QueryString,
251 rdata.Protocol, rdata.InputBuffer, redirect);
252 } catch (Exception e) {
253 bool ignore = ((e is RequestLineException) || (e is IOException));
254 if (!ignore)
255 Console.WriteLine (e);
257 try {
258 if (!ignore) {
259 byte [] error = HttpErrors.ServerError ();
260 Write (error, 0, error.Length);
262 } catch {}
263 try {
264 Close ();
265 } catch {}
267 if (broker != null && requestId != -1)
268 broker.UnregisterRequest (requestId);
272 public int Read (byte[] buffer, int position, int size)
274 return stream.Read (buffer, position, size);
277 public void Write (byte[] buffer, int position, int size)
279 try {
280 stream.Write (buffer, position, size);
281 } catch (Exception e) {
282 Close ();
283 throw;
287 public void Close ()
289 Close (false);
292 public void Close (bool keepAlive)
294 if (!keepAlive || !IsConnected ()) {
295 stream.Close ();
296 server.CloseSocket (sock);
297 return;
300 stream.EnableLingering = false;
301 stream.Close ();
302 server.ReuseSocket (sock);
305 public bool IsConnected ()
307 return stream.Connected;
310 public void Flush ()
312 stream.Flush ();