singrdk/base/Applications/cassini/Connection.cs

224 lines
7.1 KiB
C#
Raw Permalink 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
//------------------------------------------------------------------------------
2008-11-17 18:29:00 -05:00
namespace Microsoft.VisualStudio.WebHost
{
2008-03-05 09:52:00 -05:00
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 Server _server;
private Socket _socket;
private static string _localServerIP;
private static string _clientIP;
public Connection(Server server, Socket socket, string clientIP) {
_server = server;
_socket = socket;
_clientIP = clientIP;
}
public bool Connected {
get {
return _socket.Connected;
}
}
public bool IsLocal {
get {
string remoteIP = RemoteIP;
if (remoteIP.Equals("127.0.0.1")) {
return true;
}
if (_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 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, _server.VirtualPath);
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) {
}
}
}
}