Skip to content
This repository has been archived by the owner on Nov 19, 2022. It is now read-only.

Commit

Permalink
2004-06-14 Gonzalo Paniagua Javier <gonzalo@ximian.com>
Browse files Browse the repository at this point in the history
	* server/XSPApplicationHost.cs: allow wilcard for vhosts, fixed matching
	of /xxx when we have a vhost for /xxx/, matching moved to VPathToHost
	class and improved. When creating a new host, lock on the VPathToHost
	object, not the entire array of vhosts.

	* server/server.cs: don't allow duplicated options passed in the command
	line. No need to wait on a handle when --nonstop. Just make the runner
	thread have IsBackGround to false and finish the main one.

svn path=/trunk/xsp/; revision=29539
  • Loading branch information
gonzalop committed Jun 14, 2004
1 parent e55d88e commit 4b5395b
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 60 deletions.
11 changes: 11 additions & 0 deletions ChangeLog
@@ -1,3 +1,14 @@
2004-06-14 Gonzalo Paniagua Javier <gonzalo@ximian.com>

* server/XSPApplicationHost.cs: allow wilcard for vhosts, fixed matching
of /xxx when we have a vhost for /xxx/, matching moved to VPathToHost
class and improved. When creating a new host, lock on the VPathToHost
object, not the entire array of vhosts.

* server/server.cs: don't allow duplicated options passed in the command
line. No need to wait on a handle when --nonstop. Just make the runner
thread have IsBackGround to false and finish the main one.

2004-06-12 Gonzalo Paniagua Javier <gonzalo@ximian.com>

* test/dbpage1.aspx:
Expand Down
121 changes: 82 additions & 39 deletions server/XSPApplicationHost.cs
Expand Up @@ -9,6 +9,7 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
Expand Down Expand Up @@ -245,23 +246,66 @@ public class VPathToHost
public readonly int vport;
public readonly string vpath;
public readonly string realPath;
public readonly bool haveWildcard;

public IApplicationHost appHost;

public VPathToHost (string vhost, int vport, string vpath, string realPath)
{
this.vhost = vhost;
this.vhost = (vhost != null) ? vhost.ToLower (CultureInfo.InvariantCulture) : null;
this.vport = vport;
this.vpath = vpath;
if (vpath == null || vpath == "" || vpath [0] != '/')
throw new ArgumentException ("Virtual path must begin with '/': " + vpath,
"vpath");

this.realPath = realPath;
this.appHost = null;
if (vhost != null && vhost.Length != 0 && vhost [0] == '*') {
haveWildcard = true;
if (vhost.Length > 2 && vhost [1] == '.')
vhost = vhost.Substring (2);
}
}

public void ClearHost ()
{
this.appHost = null;
}

public bool Match (string vhost, int vport, string vpath)
{
if (vport != -1 && vport != this.vport)
return false;

if (vhost != null && this.vhost != null) {
int length = this.vhost.Length;
if (haveWildcard) {
if (this.vhost == "*")
return true;

length = vhost.Length;
}

if (length != vhost.Length ||
!this.vhost.EndsWith (vhost.ToLower (CultureInfo.InvariantCulture))) {
return false;
}
}

int local = vpath.Length;
int vlength = this.vpath.Length;
if (vlength > local) {
// Check for /xxx requests to be redirected to /xxx/
if (this.vpath [vlength - 1] != '/')
return false;

return (vlength - 1 == local && this.vpath.Substring (0, vlength - 1) == vpath);
}

return (vpath.StartsWith (this.vpath));
}

public void CreateHost ()
{
string v = vpath;
Expand All @@ -287,10 +331,8 @@ public class XSPApplicationServer
#endif
Thread runner;

// a sorted list of mappings. This is much faster than hashtable for typical cases.
// This is much faster than hashtable for typical cases.
ArrayList vpathToHost = new ArrayList ();

object marker = new object ();

#if MODMONO_SERVER
string filename;
Expand Down Expand Up @@ -341,6 +383,10 @@ public void SetListenAddress (IPEndPoint bindAddress)

private void AddApplication (string vhost, int vport, string vpath, string fullPath)
{
// TODO - check for duplicates, sort, optimize, etc.
if (started)
throw new InvalidOperationException ("The server is already started.");

if (verbose) {
Console.WriteLine("Registering application:");
Console.WriteLine(" Host: {0}", (vhost != null) ? vhost : "any");
Expand Down Expand Up @@ -373,11 +419,16 @@ public void AddApplicationsFromConfigFile (string fileName)
Console.WriteLine ("Adding applications from config file '{0}'", fileName);
}

XmlDocument doc = new XmlDocument ();
doc.Load (fileName);
try {
XmlDocument doc = new XmlDocument ();
doc.Load (fileName);

foreach (XmlElement el in doc.SelectNodes ("//web-application")) {
AddApplicationFromElement (el);
foreach (XmlElement el in doc.SelectNodes ("//web-application")) {
AddApplicationFromElement (el);
}
} catch {
Console.WriteLine ("Error loading '{0}'", fileName);
throw;
}
}

Expand Down Expand Up @@ -462,16 +513,18 @@ public void AddApplicationsFromCommandLine (string applications)
string fullPath = System.IO.Path.GetFullPath (realpath);
AddApplication (vhost, vport, vpath, fullPath);
}
// TODO - check for duplicates, sort, optimize, etc.
}

public bool Start ()
public bool Start (bool bgThread)
{
if (started)
throw new InvalidOperationException ("The server is already started.");

if (vpathToHost == null)
throw new InvalidOperationException ("SetApplications must be called first");
throw new InvalidOperationException ("SetApplications must be called first.");

if (vpathToHost.Count == 0)
throw new InvalidOperationException ("No applications defined.");

#if MODMONO_SERVER
if (filename == null)
Expand All @@ -487,7 +540,7 @@ public bool Start ()
#endif
listen_socket.Listen (5);
runner = new Thread (new ThreadStart (RunServer));
runner.IsBackground = true;
runner.IsBackground = bgThread;
runner.Start ();
stop = false;
WebTrace.WriteLine ("Server started.");
Expand Down Expand Up @@ -531,42 +584,32 @@ private void RunServer ()

// Console.WriteLine("GetApplicationForPath({0},{1},{2},{3})", vhost, port,
// path, defaultToRoot);
foreach (VPathToHost v in vpathToHost) {
if (v.vport != -1 && v.vport != port) {
// ports don't match - ignore
for (int i = vpathToHost.Count - 1; i >= 0; i--) {
VPathToHost v = (VPathToHost) vpathToHost [i];
int matchLength = v.vpath.Length;
if (matchLength <= bestMatchLength || !v.Match (vhost, port, path))
continue;
}

if (vhost != null && v.vhost != null &&
0 != String.CompareOrdinal(vhost, v.vhost)) {
// vhosts don't match - ignore
continue;
}

if (path.StartsWith (v.vpath)) {
int matchLength = v.vpath.Length;
if (matchLength > bestMatchLength) {
bestMatchLength = matchLength;
bestMatch = v;
}
}
bestMatchLength = matchLength;
bestMatch = v;
}

if (bestMatch != null) {
if (bestMatch.appHost == null) {
lock (vpathToHost) {
if (bestMatch.appHost == null) {
bestMatch.CreateHost();
}
}
lock (bestMatch) {
if (bestMatch.appHost == null)
bestMatch.CreateHost ();
}

return bestMatch.appHost;
} else if (defaultToRoot) {
}

if (defaultToRoot)
return GetApplicationForPath (vhost, port, "/", false);
} else {

if (verbose)
Console.WriteLine ("No application defined for: {0}:{1}{2}", vhost, port, path);
return null;
}

return null;
}
}
}
Expand Down
65 changes: 44 additions & 21 deletions server/server.cs
Expand Up @@ -14,7 +14,6 @@
using System.IO;
using System.Net;
using System.Reflection;
using System.Threading;
using System.Web.Hosting;

namespace Mono.ASPNET
Expand Down Expand Up @@ -109,6 +108,31 @@ static void ShowHelp ()

Console.WriteLine ();
}

[Flags]
enum Options {
NonStop = 1,
Verbose = 1 << 1,
Applications = 1 << 2,
AppConfigDir = 1 << 3,
AppConfigFile = 1 << 4,
Root = 1 << 5,
FileName = 1 << 6,
Address = 1 << 7,
Port = 1 << 8
}

static void CheckAndSetOptions (string name, Options value, ref Options options)
{
if ((options & value) != 0) {
ShowHelp ();
Console.WriteLine ();
Console.WriteLine ("ERROR: Option '{0}' duplicated.", name);
Environment.Exit (1);
}

options |= value;
}

public static int Main (string [] args)
{
Expand All @@ -133,32 +157,40 @@ public static int Main (string [] args)
oport = 8080;

#endif
Options options = 0;
for (int i = 0; i < args.Length; i++){
string a = args [i];

switch (a){
#if MODMONO_SERVER
case "--filename":
CheckAndSetOptions (a, Options.FileName, ref options);
filename = args [++i];
break;
#else
case "--port":
CheckAndSetOptions (a, Options.Port, ref options);
oport = args [++i];
break;
case "--address":
CheckAndSetOptions (a, Options.Address, ref options);
ip = args [++i];
break;
#endif
case "--root":
CheckAndSetOptions (a, Options.Root, ref options);
rootDir = args [++i];
break;
case "--applications":
CheckAndSetOptions (a, Options.Applications, ref options);
apps = args [++i];
break;
case "--appconfigfile":
CheckAndSetOptions (a, Options.AppConfigFile, ref options);
appConfigFile = args [++i];
break;
case "--appconfigdir":
CheckAndSetOptions (a, Options.AppConfigDir, ref options);
appConfigDir = args [++i];
break;
case "--nonstop":
Expand Down Expand Up @@ -210,17 +242,20 @@ public static int Main (string [] args)

rootDir = Directory.GetCurrentDirectory ();

XSPApplicationServer server = new XSPApplicationServer ();
if (verbose)
server.Verbose = true;
XSPApplicationServer server = new XSPApplicationServer ();
server.Verbose = verbose;

if (apps != null)
server.AddApplicationsFromCommandLine(apps);
server.AddApplicationsFromCommandLine (apps);

if (appConfigFile != null)
server.AddApplicationsFromConfigFile(appConfigFile);
server.AddApplicationsFromConfigFile (appConfigFile);

if (appConfigDir != null)
server.AddApplicationsFromConfigDirectory(appConfigDir);
server.AddApplicationsFromConfigDirectory (appConfigDir);

if (apps == null && appConfigDir == null && appConfigFile == null)
server.AddApplicationsFromCommandLine("/:.");
server.AddApplicationsFromCommandLine ("/:.");
#if MODMONO_SERVER
server.SetListenFile (filename);
Console.WriteLine ("Listening on: {0}", filename);
Expand All @@ -232,31 +267,19 @@ public static int Main (string [] args)

Console.WriteLine ("Root directory: {0}", rootDir);

ManualResetEvent evt = null;
try {
if (server.Start () == false)
if (server.Start (!nonstop) == false)
return 2;

if (!nonstop) {
Console.WriteLine ("Hit Return to stop the server.");
Console.ReadLine ();
} else {
evt = new ManualResetEvent (false);
evt.WaitOne ();
}
} catch (Exception e) {
Console.WriteLine ("Error: {0}", e.Message);
if (evt != null)
evt.Set ();

Environment.Exit (1); // Temp. workaround for errors finishing
return 1;
}

if (evt != null)
evt.Set ();

Environment.Exit (0); // Temp. workaround for errors finishing
return 0;
}
}
Expand Down

0 comments on commit 4b5395b

Please sign in to comment.