Author: gonzalo
Date: 2006-04-24 16:11:24 -0400 (Mon, 24 Apr 2006)
New Revision: 59826
Modified:
branches/gonzalo/xsp-async/src/ModMonoApplicationHost.cs
branches/gonzalo/xsp-async/src/Mono.WebServer/ApplicationServer.cs
branches/gonzalo/xsp-async/src/Mono.WebServer/BaseRequestBroker.cs
branches/gonzalo/xsp-async/src/Mono.WebServer/IWebSource.cs
branches/gonzalo/xsp-async/src/Mono.WebServer/MonoWorkerRequest.cs
branches/gonzalo/xsp-async/src/Mono.WebServer/XSPApplicationHost.cs
branches/gonzalo/xsp-async/src/Mono.WebServer/XSPWorkerRequest.cs
branches/gonzalo/xsp-async/src/server.cs
Log:
ongoing work
Modified: branches/gonzalo/xsp-async/src/ModMonoApplicationHost.cs
===================================================================
--- branches/gonzalo/xsp-async/src/ModMonoApplicationHost.cs 2006-04-24
20:08:54 UTC (rev 59825)
+++ branches/gonzalo/xsp-async/src/ModMonoApplicationHost.cs 2006-04-24
20:11:24 UTC (rev 59826)
@@ -39,7 +39,7 @@
// ModMonoWebSource: Provides methods to get objects and types specific
// to mod_mono.
//
- public class ModMonoWebSource: IWebSource, IDisposable
+ public class ModMonoWebSource: WebSource
{
string filename;
bool file_bound;
@@ -94,7 +94,7 @@
return result;
}
- public virtual Socket CreateSocket ()
+ public override Socket CreateSocket ()
{
if (filename == null)
throw new InvalidOperationException ("filename
not set");
@@ -106,7 +106,7 @@
conn.Connect (ep);
conn.Close ();
throw new InvalidOperationException
("There's already a server listening on " + filename);
- } catch (SocketException se) {
+ } catch (SocketException) {
}
File.Delete (filename);
}
@@ -117,28 +117,23 @@
return listen_socket;
}
- public IWorker CreateWorker (Socket client, ApplicationServer
server)
+ public override Worker CreateWorker (Socket client,
ApplicationServer server)
{
return new ModMonoWorker (client, server);
}
- public Type GetApplicationHostType ()
+ public override Type GetApplicationHostType ()
{
return typeof (ModMonoApplicationHost);
}
- public IRequestBroker CreateRequestBroker ()
+ public override IRequestBroker CreateRequestBroker ()
{
return new ModMonoRequestBroker ();
}
- public void Dispose ()
+ protected override void Dispose (bool expl)
{
- Dispose (true);
- }
-
- protected virtual void Dispose (bool expl)
- {
if (filename != null) {
string f = filename;
filename = null;
@@ -209,7 +204,7 @@
// ModMonoWorker: The worker that do the initial processing of mod_mono
// requests.
//
- internal class ModMonoWorker: IWorker
+ internal class ModMonoWorker: Worker
{
ApplicationServer server;
public LingeringNetworkStream Stream;
@@ -226,12 +221,11 @@
int requestId = -1;
ModMonoRequestBroker broker = null;
- public void Run (object state)
+ public override void Run (object state)
{
try {
InnerRun (state);
- } catch (Exception e) {
- //Console.WriteLine ("In ModMonoWorker.Run:
{0}", e.Message);
+ } catch (Exception) {
try {
// Closing is enough for mod_mono. the
module will return a 50x
Stream.Close ();
@@ -372,17 +366,17 @@
modRequest.GetAllHeaderValues());
}
- public int Read (byte[] buffer, int position, int size)
+ public override int Read (byte[] buffer, int position, int size)
{
return modRequest.GetClientBlock (buffer, position,
size);
}
- public void Write (byte[] buffer, int position, int size)
+ public override void Write (byte[] buffer, int position, int
size)
{
modRequest.SendResponseFromMemory (buffer, position,
size);
}
- public void Close ()
+ public override void Close ()
{
if (closed)
return;
@@ -399,12 +393,12 @@
} catch {}
}
- public void Flush ()
+ public override void Flush ()
{
//modRequest.Flush (); No-op
}
- public bool IsConnected ()
+ public override bool IsConnected ()
{
return modRequest.IsConnected ();
}
@@ -430,3 +424,4 @@
}
}
}
+
Modified: branches/gonzalo/xsp-async/src/Mono.WebServer/ApplicationServer.cs
===================================================================
--- branches/gonzalo/xsp-async/src/Mono.WebServer/ApplicationServer.cs
2006-04-24 20:08:54 UTC (rev 59825)
+++ branches/gonzalo/xsp-async/src/Mono.WebServer/ApplicationServer.cs
2006-04-24 20:11:24 UTC (rev 59826)
@@ -45,8 +45,8 @@
{
// ApplicationServer runs the main server thread, which accepts client
// connections and forwards the requests to the correct web application.
- // ApplicationServer takes an IWebSource object as parameter in the
- // constructor. IWebSource provides methods for getting some objects
+ // ApplicationServer takes an WebSource object as parameter in the
+ // constructor. WebSource provides methods for getting some objects
// whose behavior is specific to XSP or mod_mono.
// Each web application lives in its own application domain, and
incoming
@@ -66,24 +66,24 @@
// The complete sequence of servicing a request is the following:
//
// 1) The listener accepts an incoming connection.
- // 2) An IWorker object is created (through the IWebSource), and it is
+ // 2) An Worker object is created (through the WebSource), and it is
// queued in the thread pool.
- // 3) When the IWorker's run method is called, it registers itself in
+ // 3) When the Worker's run method is called, it registers itself in
// the application's request broker, and gets a request id. All this
is
// done in the main domain.
- // 4) The IWorker starts the request processing by making a cross-app
domain
+ // 4) The Worker starts the request processing by making a cross-app
domain
// call to the application host. It passes as parameters the request
id
// and other information already read from the request.
// 5) The application host executes the request. When it needs to read
or
// write request data, it performs remote calls to the request
broker,
- // passing the request id provided by the IWorker.
+ // passing the request id provided by the Worker.
// 6) When the request broker receives a call from the application host,
- // it locates the IWorker registered with the provided request id and
+ // it locates the Worker registered with the provided request id and
// forwards the call to it.
public class ApplicationServer : MarshalByRefObject
{
- IWebSource webSource;
+ WebSource webSource;
bool started;
bool stop;
bool verbose;
@@ -94,7 +94,7 @@
// This is much faster than hashtable for typical cases.
ArrayList vpathToHost = new ArrayList ();
- public ApplicationServer (IWebSource source)
+ public ApplicationServer (WebSource source)
{
webSource = source;
}
@@ -307,46 +307,40 @@
#endif
}
- SocketPool spool = new SocketPool ();
+ AsyncCallback accept_cb;
void RunServer ()
{
- spool.AddReadSocket (listen_socket);
started = true;
- Socket client;
- int w;
- while (!stop){
- ArrayList wSockets = spool.SelectRead ();
- w = wSockets.Count;
- for (int i = 0; i < w; i++) {
- Socket s = (Socket) wSockets [i];
- if (s == listen_socket) {
- try {
- client = s.Accept ();
- client.Blocking = true;
- } catch (Exception e) {
- continue;
- }
- SetSocketOptions (client);
- spool.AddReadSocket (client,
DateTime.UtcNow);
- continue;
- }
+ accept_cb = new AsyncCallback (OnAccept);
+ listen_socket.BeginAccept (accept_cb, null);
+ //TODO: wait or let it go, depending on IsBackground
+ }
- spool.RemoveReadSocket (s);
- IWorker worker = null;
- try {
- // This might happen when
reusing and the client closes.
- worker = webSource.CreateWorker
(s, this);
- } catch (Exception) {
- try { s.Close (); } catch {}
- continue;
- }
+ void OnAccept (IAsyncResult ares)
+ {
+ Socket accepted = null;
+ try {
+ accepted = listen_socket.EndAccept (ares);
+ } catch {
+ } finally {
+ listen_socket.BeginAccept (accept_cb, null);
+ }
+ if (accepted == null)
+ return;
+ accepted.Blocking = true;
+ SetSocketOptions (accepted);
+ Worker worker = null;
+ try {
+ worker = webSource.CreateWorker (accepted,
this);
+ if (false == worker.IsAsync)
ThreadPool.QueueUserWorkItem (new
WaitCallback (worker.Run));
- }
+ else
+ worker.Run (null);
+ } catch {
+ try { accepted.Close (); } catch {}
}
-
- started = false;
}
public VPathToHost GetApplicationForPath (string vhost, int
port, string path,
@@ -401,131 +395,31 @@
public int GetAvailableReuses (Socket sock)
{
+ /*
int res = spool.GetReuseCount (sock);
if (res == -1 || res >= 100)
return -1;
return 100 - res;
+ */
+ return 0;
}
public void ReuseSocket (Socket sock)
{
- IWorker worker = webSource.CreateWorker (sock, this);
+ /*
+ Worker worker = webSource.CreateWorker (sock, this);
spool.IncrementReuseCount (sock);
ThreadPool.QueueUserWorkItem (new WaitCallback
(worker.Run));
+ */
}
public void CloseSocket (Socket sock)
{
- spool.RemoveReadSocket (sock);
+ //spool.RemoveReadSocket (sock);
}
}
- class SocketPool {
- ArrayList readSockets = new ArrayList ();
- Hashtable timeouts = new Hashtable ();
- Hashtable uses = new Hashtable ();
- object locker = new object ();
-
- public ArrayList SelectRead ()
- {
- if (readSockets.Count == 0)
- throw new InvalidOperationException ("There are
no sockets.");
-
- ArrayList wSockets = new ArrayList (readSockets);
- // A bug on MS (or is it just me?) makes the following
select return immediately
- // when there's only one socket (the listen socket) in
the array:
- // Socket.Select (wSockets, null, null, (w == 1) ? -1
: 1000 * 1000); // 1s
- // so i have to do this for the MS runtime not to hung
all the CPU.
- if (wSockets.Count > 1) {
- Socket.Select (wSockets, null, null, 1000 *
1000); // 1s
- } else {
- Socket sock = (Socket) wSockets [0];
- sock.Poll (-1, SelectMode.SelectRead);
- // wSockets already contains listen_socket.
- }
-
- lock (locker)
- CheckTimeouts (wSockets);
-
- return wSockets;
- }
-
- void CheckTimeouts (ArrayList wSockets)
- {
- int w = timeouts.Count;
- if (w > 0) {
- Socket [] socks_timeout = new Socket [w];
- timeouts.Keys.CopyTo (socks_timeout, 0);
- DateTime now = DateTime.UtcNow;
- foreach (Socket k in socks_timeout) {
- if (wSockets.Contains (k))
- continue;
-
- DateTime atime = (DateTime) timeouts
[k];
- TimeSpan diff = now - atime;
- if (diff.TotalMilliseconds > 15 * 1000)
{
- RemoveReadSocket (k);
- wSockets.Remove (k);
- k.Close ();
- continue;
- }
- }
- }
- }
-
- public void IncrementReuseCount (Socket sock)
- {
- lock (locker) {
- if (uses.ContainsKey (sock)) {
- int n = (int) uses [sock];
- uses [sock] = n + 1;
- } else {
- uses [sock] = 1;
- }
- }
- }
-
- public int GetReuseCount (Socket sock)
- {
- lock (locker) {
- if (uses.ContainsKey (sock))
- return (int) uses [sock];
-
- uses [sock] = 1;
- return 1;
- }
- }
-
- public void AddReadSocket (Socket sock)
- {
- lock (locker)
- readSockets.Add (sock);
- }
-
- public void AddReadSocket (Socket sock, DateTime time)
- {
- lock (locker) {
- if (readSockets.Contains (sock)) {
- timeouts [sock] = time;
- return;
- }
-
- readSockets.Add (sock);
- timeouts [sock] = time;
- }
- }
-
- public void RemoveReadSocket (Socket sock)
- {
- lock (locker) {
- readSockets.Remove (sock);
- timeouts.Remove (sock);
- uses.Remove (sock);
- }
- }
- }
-
public class VPathToHost
{
public readonly string vhost;
@@ -628,7 +522,7 @@
return (vpath.StartsWith (this.vpath));
}
- public void CreateHost (ApplicationServer server, IWebSource
webSource)
+ public void CreateHost (ApplicationServer server, WebSource
webSource)
{
string v = vpath;
if (v != "/" && v.EndsWith ("/")) {
Modified: branches/gonzalo/xsp-async/src/Mono.WebServer/BaseRequestBroker.cs
===================================================================
--- branches/gonzalo/xsp-async/src/Mono.WebServer/BaseRequestBroker.cs
2006-04-24 20:08:54 UTC (rev 59825)
+++ branches/gonzalo/xsp-async/src/Mono.WebServer/BaseRequestBroker.cs
2006-04-24 20:11:24 UTC (rev 59826)
@@ -52,7 +52,7 @@
stk.Push (buffer);
}
- public int RegisterRequest (IWorker worker)
+ public int RegisterRequest (Worker worker)
{
int result = worker.GetHashCode ();
lock (requests) {
@@ -79,9 +79,9 @@
} else {
buffer = new byte[size];
}
- IWorker w;
+ Worker w;
lock (requests) {
- w = (IWorker) requests [requestId];
+ w = (Worker) requests [requestId];
}
int nread = 0;
@@ -91,30 +91,30 @@
return nread;
}
- public IWorker GetWorker (int requestId)
+ public Worker GetWorker (int requestId)
{
lock (requests) {
- return (IWorker) requests [requestId];
+ return (Worker) requests [requestId];
}
}
public void Write (int requestId, byte[] buffer, int position,
int size)
{
- IWorker worker = GetWorker (requestId);
+ Worker worker = GetWorker (requestId);
if (worker != null)
worker.Write (buffer, position, size);
}
public void Close (int requestId)
{
- IWorker worker = GetWorker (requestId);
+ Worker worker = GetWorker (requestId);
if (worker != null)
worker.Close ();
}
public void Flush (int requestId)
{
- IWorker worker = GetWorker (requestId);
+ Worker worker = GetWorker (requestId);
if (worker != null)
worker.Flush ();
}
Modified: branches/gonzalo/xsp-async/src/Mono.WebServer/IWebSource.cs
===================================================================
--- branches/gonzalo/xsp-async/src/Mono.WebServer/IWebSource.cs 2006-04-24
20:08:54 UTC (rev 59825)
+++ branches/gonzalo/xsp-async/src/Mono.WebServer/IWebSource.cs 2006-04-24
20:11:24 UTC (rev 59826)
@@ -27,29 +27,42 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-
-
using System;
+using System.IO;
using System.Net.Sockets;
-namespace Mono.WebServer
-{
- public interface IWebSource : IDisposable
+namespace Mono.WebServer {
+
+ public abstract class WebSource : IDisposable
{
- Socket CreateSocket ();
- IWorker CreateWorker (Socket client, ApplicationServer server);
- Type GetApplicationHostType ();
- IRequestBroker CreateRequestBroker ();
+ public abstract Socket CreateSocket ();
+ public abstract Worker CreateWorker (Socket client,
ApplicationServer server);
+ public abstract Type GetApplicationHostType ();
+ public abstract IRequestBroker CreateRequestBroker ();
+
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ }
}
- public interface IWorker
+ public abstract class Worker
{
- void Run (object state);
- int Read (byte[] buffer, int position, int size);
- void Write (byte[] buffer, int position, int size);
- void Close ();
- void Flush ();
- bool IsConnected ();
+ public virtual bool IsAsync {
+ get { return false; }
+ }
+
+ public abstract void Run (object state);
+ public abstract int Read (byte [] buffer, int position, int
size);
+ public abstract void Write (byte [] buffer, int position, int
size);
+ public abstract void Close ();
+ public abstract void Flush ();
+ public abstract bool IsConnected ();
}
}
Modified: branches/gonzalo/xsp-async/src/Mono.WebServer/MonoWorkerRequest.cs
===================================================================
--- branches/gonzalo/xsp-async/src/Mono.WebServer/MonoWorkerRequest.cs
2006-04-24 20:08:54 UTC (rev 59825)
+++ branches/gonzalo/xsp-async/src/Mono.WebServer/MonoWorkerRequest.cs
2006-04-24 20:11:24 UTC (rev 59826)
@@ -223,10 +223,14 @@
if (path.StartsWith (HostVPath) && (path.Length == len
|| path [len] == '/'))
path = path.Substring (len + 1);
- if (path.Length > 0 && path [0] == '/')
+ while (path.Length > 0 && path [0] == '/') {
path = path.Substring (1);
+ }
- return Path.Combine (HostPath, path.Replace ('/',
Path.DirectorySeparatorChar));
+ if (Path.DirectorySeparatorChar != '/')
+ path = path.Replace ('/',
Path.DirectorySeparatorChar);
+
+ return Path.Combine (HostPath, path);
}
protected abstract bool GetRequestData ();
Modified: branches/gonzalo/xsp-async/src/Mono.WebServer/XSPApplicationHost.cs
===================================================================
--- branches/gonzalo/xsp-async/src/Mono.WebServer/XSPApplicationHost.cs
2006-04-24 20:08:54 UTC (rev 59825)
+++ branches/gonzalo/xsp-async/src/Mono.WebServer/XSPApplicationHost.cs
2006-04-24 20:11:24 UTC (rev 59826)
@@ -47,7 +47,7 @@
// XSPWebSource: Provides methods to get objects and types specific
// to XSP.
//
- public class XSPWebSource: IWebSource
+ public class XSPWebSource: WebSource
{
IPEndPoint bindAddress;
bool secureConnection;
@@ -93,32 +93,28 @@
this.bindAddress = bindAddress;
}
- public Socket CreateSocket ()
+ public override Socket CreateSocket ()
{
Socket listen_socket = new Socket
(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
listen_socket.Bind (bindAddress);
return listen_socket;
}
- public IWorker CreateWorker (Socket client, ApplicationServer
server)
+ public override Worker CreateWorker (Socket client,
ApplicationServer server)
{
return new XSPWorker (client, client.LocalEndPoint,
server,
secureConnection, SecurityProtocol, cert,
keyCB, allowClientCert, requireClientCert);
}
- public Type GetApplicationHostType ()
+ public override Type GetApplicationHostType ()
{
return typeof (XSPApplicationHost);
}
- public IRequestBroker CreateRequestBroker ()
+ public override IRequestBroker CreateRequestBroker ()
{
return new XSPRequestBroker ();
}
-
- public void Dispose ()
- {
- }
}
//
@@ -288,7 +284,7 @@
// XSPWorker: The worker that do the initial processing of XSP
// requests.
//
- internal class XSPWorker: IWorker
+ internal class XSPWorker: Worker
{
ApplicationServer server;
LingeringNetworkStream netStream;
@@ -328,14 +324,19 @@
this.localEP = (IPEndPoint) localEP;
}
+ public override bool IsAsync {
+ get { return true; }
+ }
+
public int GetReuseCount ()
{
- return server.GetAvailableReuses (sock);
+ //FIXME
+ return 0;
}
int requestId = -1;
XSPRequestBroker broker = null;
- public void Run (object state)
+ public override void Run (object state)
{
try {
InnerRun (state);
@@ -414,23 +415,23 @@
rdata.Protocol, rdata.InputBuffer,
redirect, sock.Handle, ssl);
}
- public int Read (byte[] buffer, int position, int size)
+ public override int Read (byte[] buffer, int position, int size)
{
int n = stream.Read (buffer, position, size);
return (n >= 0) ? n : -1;
}
- public void Write (byte[] buffer, int position, int size)
+ public override void Write (byte[] buffer, int position, int
size)
{
try {
stream.Write (buffer, position, size);
- } catch (Exception e) {
+ } catch (Exception) {
Close ();
throw;
}
}
- public void Close ()
+ public override void Close ()
{
Close (false);
}
@@ -454,18 +455,18 @@
server.ReuseSocket (sock);
}
- public bool IsConnected ()
+ public override bool IsConnected ()
{
return netStream.Connected;
}
- public void Flush ()
+ public override void Flush ()
{
if (stream != netStream)
stream.Flush ();
}
- private bool ClientCertificateValidation (X509Certificate
certificate, int[] certificateErrors)
+ bool ClientCertificateValidation (X509Certificate certificate,
int [] certificateErrors)
{
if (certificate != null)
ssl.RawClientCertificate =
certificate.GetRawCertData (); // to avoid serialization
@@ -473,8 +474,8 @@
// right now we're accepting any client certificate -
i.e. it's up to the
// web application to check if the certificate is valid
(HttpClientCertificate.IsValid)
ssl.ClientCertificateValid = (certificateErrors.Length
== 0);
-
return ssl.RequireClientCertificate ? (certificate !=
null) : true;
}
}
}
+
Modified: branches/gonzalo/xsp-async/src/Mono.WebServer/XSPWorkerRequest.cs
===================================================================
--- branches/gonzalo/xsp-async/src/Mono.WebServer/XSPWorkerRequest.cs
2006-04-24 20:08:54 UTC (rev 59825)
+++ branches/gonzalo/xsp-async/src/Mono.WebServer/XSPWorkerRequest.cs
2006-04-24 20:11:24 UTC (rev 59826)
@@ -121,10 +121,11 @@
bool is_linux = false;
try {
- Stream st = File.OpenRead
("/proc/sys/kernel/ostype");
- StreamReader sr = new StreamReader (st);
- string os = sr.ReadToEnd ();
- sr.Close ();
+ string os = "";
+ using (Stream st = File.OpenRead
("/proc/sys/kernel/ostype")) {
+ StreamReader sr = new StreamReader (st);
+ os = sr.ReadToEnd ();
+ }
is_linux = os.StartsWith ("Linux");
} catch {
}
@@ -282,7 +283,7 @@
string value = line.Substring (colon +
1).Trim ();
headers [key] = value;
}
- } catch (IOException ioe) {
+ } catch (IOException) {
throw;
} catch (Exception e) {
throw new Exception ("Error reading headers.",
e);
@@ -341,7 +342,7 @@
if (finalFlush)
CloseConnection ();
- } catch (Exception e) {
+ } catch (Exception) {
CloseConnection ();
}
}
Modified: branches/gonzalo/xsp-async/src/server.cs
===================================================================
--- branches/gonzalo/xsp-async/src/server.cs 2006-04-24 20:08:54 UTC (rev
59825)
+++ branches/gonzalo/xsp-async/src/server.cs 2006-04-24 20:11:24 UTC (rev
59826)
@@ -405,7 +405,7 @@
rootDir = Directory.GetCurrentDirectory ();
- IWebSource webSource;
+ WebSource webSource;
#if MODMONO_SERVER
if (useTCP) {
webSource = new ModMonoTCPWebSource (ipaddr,
port, lockfile);
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches