singrdk/base/Applications/cassini/Main.cs

267 lines
9.6 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
//------------------------------------------------------------------------------
2008-11-17 18:29:00 -05:00
// Copyright (c) Microsoft Corporation. All Rights Reserved.
2008-03-05 09:52:00 -05:00
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using Microsoft.VisualStudio.WebHost;
using System.Globalization;
using Microsoft.Singularity;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Configuration;
using Microsoft.Singularity.Channels;
2008-11-17 18:29:00 -05:00
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.WebApps.Contracts;
2008-03-05 09:52:00 -05:00
using Microsoft.Contracts;
using Microsoft.SingSharp.Reflection;
using Microsoft.Singularity.Applications;
[assembly: Transform(typeof(ApplicationResourceTransform))]
2008-11-17 18:29:00 -05:00
namespace Microsoft.VisualStudio.WebServer
{
2008-03-05 09:52:00 -05:00
[ConsoleCategory(HelpMessage="cassini [options] A web server",
DefaultAction=true)]
internal sealed class Parameters
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
2008-11-17 18:29:00 -05:00
[Endpoint]
public readonly TRef<DirectoryServiceContract.Imp:Start> nsRef;
[BoolParameter("v", Default=false, HelpMessage="Verbose")]
2008-03-05 09:52:00 -05:00
internal bool verbose;
2008-11-17 18:29:00 -05:00
[BoolParameter("s", Default=false, HelpMessage="Silent")]
2008-03-05 09:52:00 -05:00
internal bool silent;
2008-11-17 18:29:00 -05:00
[BoolParameter("quitURL", Default=false, HelpMessage="Allow special URL to terminate")]
2008-03-05 09:52:00 -05:00
internal bool quitURL;
2008-11-17 18:29:00 -05:00
[StringParameter("port", Default=null, HelpMessage="Port ID to listen to")]
2008-03-05 09:52:00 -05:00
internal string portString;
2008-11-17 18:29:00 -05:00
[StringParameter("vpath", Default="", HelpMessage="Root of Virtual Path")]
2008-03-05 09:52:00 -05:00
internal string virtualPath;
2008-11-17 18:29:00 -05:00
[StringParameter("client", Default="", HelpMessage="Client IP")]
2008-03-05 09:52:00 -05:00
internal string client;
2008-11-17 18:29:00 -05:00
[StringParameter("apparg", Default="", HelpMessage="Arg to pass to client app")]
2008-03-05 09:52:00 -05:00
internal string appArg;
2008-11-17 18:29:00 -05:00
[StringParameter("app", Mandatory=true, Default="", HelpMessage="Name of the app to run")]
2008-03-05 09:52:00 -05:00
internal string app;
2008-11-17 18:29:00 -05:00
[StringParameter("nspath", Mandatory=false, Default=null, HelpMessage="NS path to app to run")]
internal string nsPath;
[LongParameter("load", Mandatory=false, Default=1000, HelpMessage="Overload timeout threshold (in ms)")]
internal long load;
2008-03-05 09:52:00 -05:00
reflective internal Parameters();
internal int AppMain() {
return WebServerApp.AppMain(this);
}
}
public sealed class WebServerApp {
internal static int AppMain(Parameters! config) {
bool verbose = config.verbose;
bool silent = config.silent;
string virtualPath = config.virtualPath;
if (virtualPath != null) {
virtualPath = virtualPath.Trim();
}
if ((virtualPath == null) || (virtualPath.Length == 0)) {
virtualPath = "/";
}
else {
if (virtualPath.StartsWith("/") == false) {
if (!silent) {
ShowUsage();
}
return -1;
}
}
string physicalPath = "\\";
2008-11-17 18:29:00 -05:00
//
//TODO: HACKHACK FIXME: the file system is not wired up
//in Singularity; avoid using it!
//
//string physicalPath = (string)commandLine.Options["path"];
//if (physicalPath != null) {
// physicalPath = physicalPath.Trim();
//}
//if ((physicalPath == null) || (physicalPath.Length == 0)) {
// if (!silent) {
// ShowUsage();
// }
// return -1;
//}
//else {
// if (Directory.Exists(physicalPath) == false) {
// if (!silent) {
// ShowMessage("The physical path '"+ physicalPath + "' does not exist!");
// }
// return -2;
// }
//
// // added this to resolve paths like "."
// physicalPath = Path.GetFullPath(physicalPath);
//}
//
2008-03-05 09:52:00 -05:00
int port = 0;
string portText = config.portString;
if (portText != null) {
portText = portText.Trim();
}
if ((portText != null) && (portText.Length != 0)) {
try {
port = Int32.Parse(portText);
if ((port < 1) || (port > 65535)) {
if (!silent) {
ShowUsage();
}
return -1;
}
}
catch {
if (!silent) {
ShowMessage("Invalid port '" + portText + "'");
}
return -3;
}
}
else {
port = 80;
}
// clientIP was added so that we could test using Cassini remotely on
// lab machines. This now allows the client to be localhost or clientIP.
string clientIP = config.client;
if (clientIP != null) {
clientIP = clientIP.Trim();
}
if ((clientIP == null) || (clientIP.Length == 0)) {
clientIP = "localhost";
}
//
// Singularity-specific initialization
//
string webApp = config.app;
bool quitURL = config.quitURL;
// FIXME: should generalize this so more than one arg can be passed to
// the webapp!
string[] appArgs = null;
if (config.appArg != null) {
appArgs = new string[1];
appArgs[0] = config.appArg;
}
if ((webApp == null) || (webApp.Length == 0)) {
2008-11-17 18:29:00 -05:00
webApp = "HelloWebApp";
2008-03-05 09:52:00 -05:00
}
webApp.Trim();
2008-11-17 18:29:00 -05:00
// If a nsPath was provide, then connect to the client.
if (config.nsPath != null) {
Console.WriteLine("Cassini: Connecting to {0}.", config.nsPath);
DirectoryServiceContract.Imp! dsImp = config.nsRef.Acquire();
dsImp.RecvSuccess();
WebAppContract.Imp! waImp;
WebAppContract.Exp! waExp;
WebAppContract.NewChannel(out waImp, out waExp);
ErrorCode error;
if (!SdsUtils.Bind(config.nsPath, dsImp, waExp, out error)) {
DebugStub.WriteLine("Failed to bind to webapp store...error {0}\n",
__arglist(SdsUtils.ErrorCodeToString(error)));
Console.WriteLine("Failed to bind to webapp store...error {0}\n",
SdsUtils.ErrorCodeToString(error));
delete dsImp;
delete waImp;
return -1;
}
delete dsImp;
waImp.RecvWebAppReady();
Dispatcher.BalanceConnection(waImp, config.load);
}
if (!Dispatcher.Initialize(webApp, appArgs, verbose, quitURL)) {
2008-03-05 09:52:00 -05:00
if (!silent) {
ShowMessage("Invalid web application name \"" + webApp + "\"");
return -5;
}
}
// ====================
// Actually start the server below
// ===================
try {
Server server = new Server(port, virtualPath, physicalPath, clientIP);
server.Start();
2008-11-17 18:29:00 -05:00
Console.WriteLine();
Console.WriteLine("Running Web Server on port {0}.", port);
Console.WriteLine("Application '{0}' is mapped to '{1}'.", virtualPath, physicalPath);
Console.WriteLine("http://localhost:{0}{1}", port, virtualPath);
2008-03-05 09:52:00 -05:00
// Currently no console-read support in Singularity. Run forever!
//Console.WriteLine("Hit Enter to stop the server");
//Console.ReadLine();
//server.Stop();
}
catch (Exception ex) {
if (!silent) {
ShowMessage("Error opening port " + port + ": " + ex.Message);
}
return -5;
}
return 0;
}
private static void ShowUsage() {
string usageString;
usageString = "Invalid usage.\n\n";
usageString += "cassini [options]\n";
usageString += "Options:\n";
usageString += " -app:<application> run application.\n";
usageString += " -apparg:<argument> supply argument to application.\n";
usageString += " -path:<physicalpath>\n";
usageString += " -port:<port>\n";
usageString += " -quitURL quit if URL ending in \"quit\" is received.\n";
usageString += " [-silent]\n";
usageString += " [-verbose] show files served\n";
usageString += " [-vpath:<virtualpath>]\n";
usageString += " [-client:<clientIP>]\n";
ShowMessage(usageString);
}
private static void ShowMessage(String msg) {
Console.WriteLine("Visual Web Developer Web Server:\n" + msg);
}
}
}