//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All Rights Reserved. //------------------------------------------------------------------------------ namespace Microsoft.Singularity.WebServer { using System; using System.Collections; using System.Globalization; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Web; // Singularity using Microsoft.SingSharp; using Microsoft.SingSharp.Runtime; using Microsoft.Singularity.Channels; // internal sealed class Connection { private Listener! listener; private Socket socket; public Connection(Listener! listener, Socket! socket) { this.listener = listener; this.socket = socket; base(); } public bool Connected { get { return socket.Connected; } } public bool IsLocal { get { string remoteIP = RemoteIP; if (remoteIP.Equals("127.0.0.1")) { return true; } if (listener.ClientIP.Equals(remoteIP)) { return true; } //return false; return true; } } public string! LocalIP { get { IPEndPoint endPoint = (IPEndPoint)socket.LocalEndPoint; if ((endPoint != null) && (endPoint.Address != null)) { return (!)endPoint.Address.ToString(); } else { return "127.0.0.1"; } } } public string! RemoteIP { get { IPEndPoint endPoint = (IPEndPoint)socket.RemoteEndPoint; if ((endPoint != null) && (endPoint.Address != null)) { return (!)endPoint.Address.ToString(); } else { // REVIEW: Is this correct? If RemoteEndPoint is not // set, we end up returning 127.0.0.1 which is // treated as localhost, and may not be what // we want. return "127.0.0.1"; } } } public int ListenerPort { get { return listener.Port; } } public void Close() { try { if (socket != null) // ROTORTODO { socket.Shutdown(SocketShutdown.Both); socket.Close(); } } catch { } finally { socket = null; } } private static String! MakeResponseHeaders(int statusCode, String moreHeaders, int contentLength, bool keepAlive) { StringBuilder sb = new StringBuilder(); sb.Append("HTTP/1.1 " + statusCode + " " + HttpWorkerRequest.GetStatusDescription(statusCode) + "\r\n"); sb.Append("Server: Microsoft VisualStudio .NET WebServer/" + Messages.VersionString + "\r\n"); sb.Append("Date: " + DateTime.Now.ToUniversalTime().ToString("R") + "\r\n"); if (contentLength >= 0) sb.Append("Content-Length: " + contentLength + "\r\n"); if (moreHeaders != null) sb.Append(moreHeaders); if (!keepAlive) sb.Append("Connection: Close\r\n"); sb.Append("\r\n"); return sb.ToString(); } public byte[] ReadRequestBytes(int maxBytes) { try { if (WaitForRequestBytes() == 0) { return null; } int numBytes = socket.Available; if (numBytes > maxBytes) numBytes = maxBytes; int numReceived = 0; byte[] buffer = new byte[numBytes]; if (numBytes > 0) { numReceived = socket.Receive(buffer, 0, numBytes, SocketFlags.None); } if (numReceived < numBytes) { byte[] tempBuffer = new byte[numReceived]; if (numReceived > 0) { Buffer.BlockCopy(buffer, 0, tempBuffer, 0, numReceived); } buffer = tempBuffer; } return buffer; } catch { return null; } } public void Write100Continue() { WriteEntireResponseFromString(100, null, null, true); } public void WriteBody(byte[] data, int offset, int length) { socket.Send(data, offset, length, SocketFlags.None); } public void WriteBody([Claims] byte[]! in ExHeap data) { socket.Send(data, SocketFlags.None); } public void WriteEntireResponseFromString(int statusCode, String extraHeaders, String body, bool keepAlive) { try { int bodyLength = (body != null) ? Encoding.UTF8.GetByteCount(body) : 0; string headers = MakeResponseHeaders(statusCode, extraHeaders, bodyLength, keepAlive); socket.Send(Encoding.UTF8.GetBytes(headers + body)); } catch (SocketException) { } finally { if (!keepAlive) { Close(); } } } public void WriteErrorAndClose(int statusCode, string message) { string body = Messages.FormatErrorMessageBody(statusCode); if (message != null && message.Length > 0) { body += "\r\n"; } WriteEntireResponseFromString(statusCode, null, body, false); } public void WriteErrorAndClose(int statusCode) { WriteErrorAndClose(statusCode, null); } public int WaitForRequestBytes() { int availBytes = 0; try { if (socket.Available == 0) { // poll until there is data socket.Poll(100000 /* 100ms */, SelectMode.SelectRead); if (socket.Available == 0 && socket.Connected) { socket.Poll(10000000 /* 10sec */, SelectMode.SelectRead); } } availBytes = socket.Available; } catch { } return availBytes; } public void WriteHeaders(int statusCode, String extraHeaders) { string headers = MakeResponseHeaders(statusCode, extraHeaders, -1, false); try { socket.Send(Encoding.UTF8.GetBytes(headers)); } catch (SocketException) { } } } }