1
****************************************************************************
3
| Copyright (c) 2007 Novell, Inc.
6
| This program is free software; you can redistribute it and/or
7
| modify it under the terms of version 2 of the GNU General Public License as
8
| published by the Free Software Foundation.
10
| This program is distributed in the hope that it will be useful,
11
| but WITHOUT ANY WARRANTY; without even the implied warranty of
12
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
| GNU General Public License for more details.
15
| You should have received a copy of the GNU General Public License
16
| along with this program; if not, contact Novell, Inc.
18
| To contact Novell about this file by physical or electronic mail,
19
| you may find current contact information at www.novell.com
22
| Gonzalo Paniagua Javier (gonzalo@ximian.com)
23
| Lluis Sanchez Gual (lluis@ximian.com)
24
|***************************************************************************/
29
using System.Net.Sockets;
36
// XSPWebSource: Provides methods to get objects and types specific
39
public class XSPWebSource: IWebSource
41
IPEndPoint bindAddress;
43
public XSPWebSource (IPAddress address, int port)
45
SetListenAddress (address, port);
48
public void SetListenAddress (int port)
50
SetListenAddress (IPAddress.Any, port);
53
public void SetListenAddress (IPAddress address, int port)
55
SetListenAddress (new IPEndPoint (address, port));
58
public void SetListenAddress (IPEndPoint bindAddress)
60
if (bindAddress == null)
61
throw new ArgumentNullException ("bindAddress");
63
this.bindAddress = bindAddress;
66
public Socket CreateSocket ()
68
Socket listen_socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
69
listen_socket.Bind (bindAddress);
73
public IWorker CreateWorker (Socket client, ApplicationServer server)
75
return new XSPWorker (client, client.LocalEndPoint, server);
78
public Type GetApplicationHostType ()
80
return typeof (XSPApplicationHost);
83
public IRequestBroker CreateRequestBroker ()
85
return new XSPRequestBroker ();
90
// XSPRequestBroker: The request broker for XSP. Provides some
91
// additional methods to the BaseRequestBroker from which inherits.
93
public class XSPRequestBroker: BaseRequestBroker
95
public bool IsConnected (int requestId)
97
return ((XSPWorker)GetWorker (requestId)).IsConnected ();
102
// XSPApplicationHost: The application host for XSP.
104
public class XSPApplicationHost : BaseApplicationHost
106
public void ProcessRequest (int reqId, string localEPAddr, int localEPPort, string remoteEPAdds,
107
int remoteEPPort, string verb, string path, string pathInfo,
108
string queryString, string protocol, byte [] inputBuffer, string redirect)
110
XSPRequestBroker broker = (XSPRequestBroker) RequestBroker;
111
IPEndPoint localEP = new IPEndPoint (IPAddress.Parse (localEPAddr), localEPPort);
112
IPEndPoint remoteEP = new IPEndPoint (IPAddress.Parse (remoteEPAdds), remoteEPPort);
113
XSPWorkerRequest mwr = new XSPWorkerRequest (reqId, broker, this, localEP, remoteEP, verb, path,
114
pathInfo, queryString, protocol, inputBuffer);
116
if (redirect != null) {
117
Redirect (mwr, redirect);
121
ProcessRequest (mwr);
124
static string content301 = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" +
125
"<html><head>\n<title>301 Moved Permanently</title>\n</head><body>\n" +
126
"<h1>Moved Permanently</h1>\n" +
127
"<p>The document has moved to <a href='http://{0}{1}'>http://{0}{1}</a>.</p>\n" +
130
static void Redirect (XSPWorkerRequest wr, string location)
132
string host = wr.GetKnownRequestHeader (HttpWorkerRequest.HeaderHost);
133
wr.SendStatus (301, "Moved Permanently");
134
wr.SendUnknownResponseHeader ("Connection", "close");
135
wr.SendUnknownResponseHeader ("Date", DateTime.Now.ToUniversalTime ().ToString ("r"));
136
wr.SendUnknownResponseHeader ("Location", String.Format ("http://{0}{1}", host, location));
137
Encoding enc = Encoding.ASCII;
138
wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName);
139
string content = String.Format (content301, host, location);
140
byte [] contentBytes = enc.GetBytes (content);
141
wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ());
142
wr.SendResponseFromMemory (contentBytes, contentBytes.Length);
143
wr.FlushResponse (true);
144
wr.CloseConnection ();
147
static string GetValueFromHeader (string header, string attr)
149
int where = header.IndexOf (attr + '=');
153
where += attr.Length + 1;
154
int max = header.Length;
158
char ending = header [where];
162
int end = header.Substring (where + 1).IndexOf (ending);
164
return (ending == '"') ? null : header.Substring (where);
166
return header.Substring (where, end);
171
// XSPWorker: The worker that do the initial processing of XSP
174
internal class XSPWorker: IWorker
176
ApplicationServer server;
177
LingeringNetworkStream stream;
182
public XSPWorker (Socket client, EndPoint localEP, ApplicationServer server)
184
stream = new LingeringNetworkStream (client, true);
185
this.server = server;
188
remoteEP = (IPEndPoint) client.RemoteEndPoint;
190
this.localEP = (IPEndPoint) localEP;
193
public void Run (object state)
196
XSPRequestBroker broker = null;
199
if (remoteEP == null)
202
InitialWorkerRequest ir = new InitialWorkerRequest (stream);
203
ir.ReadRequestData ();
204
RequestData rdata = ir.RequestData;
205
string vhost = null; // TODO: read the headers in InitialWorkerRequest
206
int port = ((IPEndPoint) localEP).Port;
208
VPathToHost vapp = server.GetApplicationForPath (vhost, port, rdata.Path, true);
209
XSPApplicationHost host = null;
211
host = (XSPApplicationHost) vapp.AppHost;
214
byte [] nf = HttpErrors.NotFound (rdata.Path);
215
stream.Write (nf, 0, nf.Length);
220
broker = (XSPRequestBroker) vapp.RequestBroker;
221
requestId = broker.RegisterRequest (this);
224
vapp.Redirect (rdata.Path, out redirect);
225
host.ProcessRequest (requestId, localEP.Address.ToString(), localEP.Port,
226
remoteEP.Address.ToString(), remoteEP.Port, rdata.Verb,
227
rdata.Path, rdata.PathInfo, rdata.QueryString,
228
rdata.Protocol, rdata.InputBuffer, redirect);
229
} catch (Exception e) {
230
Console.WriteLine (e);
232
if (!(e is IOException)) {
233
byte [] error = HttpErrors.ServerError ();
234
stream.Write (error, 0, error.Length);
240
broker.UnregisterRequest (requestId);
244
public int Read (byte[] buffer, int position, int size)
246
return stream.Read (buffer, position, size);
249
public void Write (byte[] buffer, int position, int size)
251
stream.Write (buffer, position, size);
259
public bool IsConnected ()
261
return stream.Connected;