singrdk/base/Applications/WebServer/Connection.sg

247 lines
7.4 KiB
Plaintext

//------------------------------------------------------------------------------
// <copyright company='Microsoft Corporation'>
// Copyright (c) Microsoft Corporation. All rights reserved.
// Information Contained Herein is Proprietary and Confidential.
// </copyright>
//------------------------------------------------------------------------------
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<!--\r\n" + message + "\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) {
}
}
}
}