X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Runtime.Remoting%2FSystem.Runtime.Remoting.Channels.Http%2FHttpServer.cs;h=3c60866951857254dbd97cae7c37c7cc5496bbd5;hb=95cc3b326085efb22d9192b0bf95f510e9139e5d;hp=e4d2c2c5f84c0a3d5a08e445ed64d02f460f72ac;hpb=eaac7d77453725a4b6019f31100d0b48efc713b6;p=mono.git diff --git a/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Http/HttpServer.cs b/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Http/HttpServer.cs index e4d2c2c5f84..3c608669518 100644 --- a/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Http/HttpServer.cs +++ b/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Http/HttpServer.cs @@ -14,6 +14,27 @@ // Hussein Mehanna hussein_mehanna@hotmail.com // //========================================================================== + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// using System; using System.Net.Sockets; using System.Text; @@ -28,203 +49,166 @@ using System.Runtime.Remoting.Messaging; namespace System.Runtime.Remoting.Channels.Http { - class RequestArguments + internal class RequestArguments { - public RequestArguments(Socket SOCKET, HttpServerTransportSink SNK) + public RequestArguments (Socket socket, HttpServerTransportSink sink) { - socket = SOCKET; - snk = SNK; + NetworkStream ns = new NetworkStream (socket); + InputStream = ns; + OutputStream = ns; + Sink = sink; } - public Socket socket; - public HttpServerTransportSink snk; + + public Stream InputStream; + public Stream OutputStream; + public HttpServerTransportSink Sink; } internal sealed class HttpServer { - public int port; - private TcpListener listener=null; - private const int nTimeOut = 1000; - - public HttpServer(int port) + public static void ProcessRequest (object reqInfo) { - try - { - listener = new TcpListener(port); - } - catch(NullReferenceException) - { - Console.WriteLine("The port is bound to another application"); - } - } - - - public static void ProcessRequest(object Object) - { - - if(Object as RequestArguments == null) + if(reqInfo as RequestArguments == null) return; - - Socket socket; - HttpServerTransportSink snk; - - RequestArguments reqArg = (RequestArguments)Object; + RequestArguments reqArg = (RequestArguments)reqInfo; - socket = reqArg.socket; - snk = reqArg.snk; - - if(!socket.Connected) - return; - - //Step (1) Start Reciceve the header - ArrayList Headers = RecieveHeader(socket); - + //Step (1) Start Reciceve the header + ArrayList Headers = RecieveHeader (reqArg); - //Step (2) Start Parse the header - IDictionary HeaderFields = new Hashtable(); - IDictionary CustomHeaders = new Hashtable(); - if(!ParseHeader(socket,Headers,HeaderFields,CustomHeaders)) - return; - - + //Step (2) Start Parse the header + IDictionary HeaderFields = new Hashtable(); + IDictionary CustomHeaders = new Hashtable(); + if (!ParseHeader (reqArg, Headers, HeaderFields, CustomHeaders)) + return; + //Step (3) + if (!CheckRequest (reqArg, HeaderFields, CustomHeaders)) + return; - //Step (3) - if(!CheckRequest(socket,HeaderFields,CustomHeaders)) + //Step (4) Recieve the entity body + + byte[] buffer; + object len = HeaderFields["content-length"]; + if (len != null) + { + buffer = new byte [(int)len]; + if (!RecieveEntityBody (reqArg, buffer)) return; - - - //Step (4) Recieve the entity body - byte [] buffer =new byte[(int)HeaderFields["content-length"]]; - if(!RecieveEntityBody(socket,buffer)) - return ; - + } + else + buffer = new byte [0]; - - //Step (5) - - if(! SendRequestForChannel(socket,snk,HeaderFields,CustomHeaders,buffer)) - return ; - - + //Step (5) + SendRequestForChannel (reqArg, HeaderFields, CustomHeaders, buffer); } - private static ArrayList RecieveHeader(Socket socket) + private static ArrayList RecieveHeader (RequestArguments reqArg) { bool bLastLine = false; bool bEndOfLine = false; byte[] buffer = new byte[1024]; ArrayList Headers = new ArrayList(); - - + + Stream ist = reqArg.InputStream; int index =0; - while(!bLastLine) + while (!bLastLine) { //recieve line by line index = 0; bEndOfLine = false; //Step (1) is it an empty line? - socket.Receive(buffer,index,1,SocketFlags.None); + ist.Read (buffer, index, 1); if(buffer[index++]==13) { - socket.Receive(buffer,index,1,SocketFlags.None); + ist.Read (buffer, index, 1); bLastLine=true; bEndOfLine = true; } //Step (2) recieve line bytes - while(!bEndOfLine) + while (!bEndOfLine) { - socket.Receive(buffer,index,1,SocketFlags.None); + ist.Read (buffer, index, 1); - if(buffer[index++]==13) + if(buffer [index++]==13) { bEndOfLine = true; - socket.Receive(buffer,index,1,SocketFlags.None); + ist.Read (buffer,index,1); } - } //Step (3) convert bytes to a string - if(bLastLine) + if (bLastLine) continue; - Headers.Add( Encoding.ASCII.GetString(buffer,0,index)); - - + + Headers.Add (Encoding.ASCII.GetString (buffer,0,index)); }//end while loop return Headers; } - private static bool ParseHeader(Socket socket, ArrayList Headers,IDictionary HeaderFields, IDictionary CustomHeaders) + private static bool ParseHeader (RequestArguments reqArg, ArrayList Headers, IDictionary HeaderFields, IDictionary CustomHeaders) { - - for(int i=0;i - break; + throw e; } return false; @@ -233,37 +217,29 @@ namespace System.Runtime.Remoting.Channels.Http return true; } - private static bool SendRequestForChannel(Socket socket ,HttpServerTransportSink snk ,IDictionary HeaderFields , IDictionary CustomHeaders, byte[]buffer) + private static bool SendRequestForChannel (RequestArguments reqArg, IDictionary HeaderFields, IDictionary CustomHeaders, byte[] buffer) { - - TransportHeaders THeaders = new TransportHeaders(); - Stream stream = new MemoryStream(buffer); - if(stream.Position !=0) stream.Seek(0,SeekOrigin.Begin); - //These two headers are sent to the Soap Formatter - //IF the Soap formatter on mono will need them , then uncomment them. - //THeaders["__ConnectionId"] = Int64.Parse("1"); - //THeaders["__IPAddress"]= ((IPEndPoint)socket.RemoteEndPoint).Address; - - THeaders["__RequestUri"] =FixURI((string)HeaderFields["request-url"]); - THeaders["Content-Type"]=HeaderFields["content-type"]; - THeaders["__RequestVerb"]=HeaderFields["method"]; - THeaders["__HttpVersion"] = HeaderFields["http-version"]; - THeaders["User-Agent"] = HeaderFields["user-agent"]; - THeaders["Host"] = HeaderFields["host"]; + THeaders[CommonTransportKeys.RequestUri] = FixURI((string)HeaderFields["request-url"]); + THeaders[CommonTransportKeys.ContentType]= HeaderFields["content-type"]; + THeaders[CommonTransportKeys.RequestVerb]= HeaderFields["method"]; + THeaders[CommonTransportKeys.HttpVersion] = HeaderFields["http-version"]; + THeaders[CommonTransportKeys.UserAgent] = HeaderFields["user-agent"]; + THeaders[CommonTransportKeys.Host] = HeaderFields["host"]; + THeaders[CommonTransportKeys.SoapAction] = HeaderFields["SOAPAction"]; foreach(DictionaryEntry DictEntry in CustomHeaders) { THeaders[DictEntry.Key.ToString()] = DictEntry.Value.ToString(); } - snk.ServiceRequest(socket,stream,THeaders); + reqArg.Sink.ServiceRequest (reqArg, stream, THeaders); return true; } @@ -277,73 +253,66 @@ namespace System.Runtime.Remoting.Channels.Http } - public static bool SendResponse(Socket socket, int HttpStatusCode, ITransportHeaders headers , Stream responseStream) + public static void SendResponse (RequestArguments reqArg, int httpStatusCode, ITransportHeaders headers, Stream responseStream) { byte [] headersBuffer = null; byte [] entityBuffer = null; - StringBuilder ResponseStr ; - String Reason = GetReasonPhrase(HttpStatusCode); + StringBuilder responseStr; + String reason = null; + if (headers != null && headers[CommonTransportKeys.HttpStatusCode] != null) { + // The formatter can override the result code + httpStatusCode = int.Parse ((string)headers [CommonTransportKeys.HttpStatusCode]); + reason = (string) headers [CommonTransportKeys.HttpReasonPhrase]; + } + + if (reason == null) + reason = GetReasonPhrase (httpStatusCode); //Response Line - ResponseStr = new StringBuilder( "HTTP/1.1 " + HttpStatusCode.ToString() + " " + Reason + "\r\n" ); - if(headers!=null) - foreach(DictionaryEntry entry in headers) + responseStr = new StringBuilder ("HTTP/1.0 " + httpStatusCode + " " + reason + "\r\n" ); + + if (headers != null) + { + foreach (DictionaryEntry entry in headers) { - ResponseStr.Append(entry.Key.ToString()+": "+entry.Value.ToString()+"\r\n"); + string key = entry.Key.ToString(); + if (key != CommonTransportKeys.HttpStatusCode && key != CommonTransportKeys.HttpReasonPhrase) + responseStr.Append(key + ": " + entry.Value.ToString() + "\r\n"); } + } - ResponseStr.Append("Server: MS .NET Remoting, MS .NET CLR 1.0.3705.0\r\n"); + responseStr.Append("Server: Mono Remoting, Mono CLR " + System.Environment.Version.ToString() + "\r\n"); - if(responseStream != null) - if(responseStream.Length!=0) + if(responseStream != null && responseStream.Length!=0) { - ResponseStr.Append("Content-Length: "+responseStream.Length.ToString()+"\r\n"); + responseStr.Append("Content-Length: "+responseStream.Length.ToString()+"\r\n"); entityBuffer = new byte[responseStream.Length]; responseStream.Seek(0 , SeekOrigin.Begin); - responseStream.Read(entityBuffer,0,entityBuffer.Length); + responseStream.Read(entityBuffer,0,entityBuffer.Length); } + else + responseStr.Append("Content-Length: 0\r\n"); - ResponseStr.Append("\r\n"); + responseStr.Append("X-Powered-By: Mono\r\n"); + responseStr.Append("Connection: close\r\n"); + responseStr.Append("\r\n"); - headersBuffer = Encoding.ASCII.GetBytes(ResponseStr.ToString()); - - try - { - - //send headersBuffer - if(socket.Send(headersBuffer,0,headersBuffer.Length,SocketFlags.None) != headersBuffer.Length) - return false; - - + headersBuffer = Encoding.ASCII.GetBytes (responseStr.ToString()); - if(entityBuffer != null) - if(socket.Send(entityBuffer,0,entityBuffer.Length,SocketFlags.None) != entityBuffer.Length) - return false; + //send headersBuffer + reqArg.OutputStream.Write (headersBuffer, 0, headersBuffer.Length); - } - catch (SocketException ) - { - // - //may be its the client's fault so just return with false - return false; - } - - return true; - } - - public static bool SendResponse(Socket socket , int HttpStatusCode ,string ReasonPhrase, ITransportHeaders headers , Stream responseStream ) - { - - return true; + if (entityBuffer != null) + reqArg.OutputStream.Write (entityBuffer, 0, entityBuffer.Length); } - private static string GetReasonPhrase(int HttpStatusCode) + internal static string GetReasonPhrase (int HttpStatusCode) { switch (HttpStatusCode) { - case 100 : return " Continue" ; + case 100 : return "Continue" ; case 101 :return "Switching Protocols"; case 200 :return "OK"; case 201 :return "Created"; @@ -394,39 +363,34 @@ namespace System.Runtime.Remoting.Channels.Http } - internal sealed class ReqMessageParser + internal sealed class ReqMessageParser { - private const int nCountReq = 14; - private const int nCountEntity = 15; - - private static bool bInitialized = false; - - private static String [] ReqRegExpString = new String [nCountReq ]; - private static String [] EntityRegExpString = new String[nCountEntity]; - - private static Regex [] ReqRegExp = new Regex[nCountReq]; - private static Regex [] EntityRegExp = new Regex[nCountEntity]; + private const int nCountReq = 14; + private const int nCountEntity = 15; + + private static bool bInitialized = false; + + private static String [] ReqRegExpString = new String [nCountReq ]; + private static String [] EntityRegExpString = new String[nCountEntity]; + + private static Regex [] ReqRegExp = new Regex[nCountReq]; + private static Regex [] EntityRegExp = new Regex[nCountEntity]; - public ReqMessageParser() + public ReqMessageParser () { - - } - public static bool ParseHeaderField(string buffer,IDictionary headers) + public static bool ParseHeaderField(string buffer,IDictionary headers) { - try { - if(!bInitialized) { Initialize(); bInitialized =true; } - if(IsRequestField(buffer,headers)) return true; @@ -437,16 +401,12 @@ namespace System.Runtime.Remoting.Channels.Http catch(Exception ) { // - } //Exception return false; - } - - private static bool Initialize() {