|
//------------------------------------------------------------------------------
// <copyright file="StateWorkerRequest.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* StateHttpWorkerRequest
*
* Copyright (c) 1998-1999, Microsoft Corporation
*
*/
namespace System.Web.SessionState {
using System.Text;
using System.Configuration.Assemblies;
using System.Runtime.InteropServices;
using System.Collections;
using System.Web;
using System.Web.Util;
using System.Globalization;
class StateHttpWorkerRequest : HttpWorkerRequest {
/* long enough to hold the string representation of an IPv4 or IPv6 address; keep in sync with tracker.cxx */
private const int ADDRESS_LENGTH_MAX = 64;
IntPtr _tracker;
string _uri;
UnsafeNativeMethods.StateProtocolExclusive _exclusive;
int _extraFlags;
int _timeout;
int _lockCookie;
bool _lockCookieExists;
int _contentLength;
byte[] _content;
UnsafeNativeMethods.StateProtocolVerb _methodIndex;
string _method;
string _remoteAddress;
int _remotePort;
string _localAddress;
int _localPort;
StringBuilder _status;
int _statusCode;
StringBuilder _headers;
IntPtr _unmanagedState;
bool _sent;
internal StateHttpWorkerRequest(
IntPtr tracker,
UnsafeNativeMethods.StateProtocolVerb methodIndex,
string uri,
UnsafeNativeMethods.StateProtocolExclusive exclusive,
int extraFlags,
int timeout,
int lockCookieExists,
int lockCookie,
int contentLength,
IntPtr content
) {
_tracker = tracker;
_methodIndex = methodIndex;
switch (_methodIndex) {
case UnsafeNativeMethods.StateProtocolVerb.GET:
_method = "GET";
break;
case UnsafeNativeMethods.StateProtocolVerb.PUT:
_method = "PUT";
break;
case UnsafeNativeMethods.StateProtocolVerb.HEAD:
_method = "HEAD";
break;
case UnsafeNativeMethods.StateProtocolVerb.DELETE:
_method = "DELETE";
break;
default:
Debug.Assert(false, "Shouldn't get here!");
break;
}
_uri = uri;
// Handle the ASP1.1 case which prepends an extra / to the URI
if (_uri.StartsWith("//", StringComparison.Ordinal)) {
_uri = _uri.Substring(1);
}
_exclusive = exclusive;
_extraFlags = extraFlags;
_timeout = timeout;
_lockCookie = lockCookie;
_lockCookieExists = lockCookieExists != 0;
_contentLength = contentLength;
if (contentLength != 0) {
Debug.Assert(_contentLength == IntPtr.Size);
// Need to convert 'content', which is a ptr to native StateItem,
// into a byte array because that's what GetPreloadedEntityBody
// must return, and GetPreloadedEntityBody is what the pipeline uses
// to read the body of the request, which in our case is just a pointer
// to a native StateItem object.
#if WIN64
ulong p = (ulong) content;
_content = new byte[8]
{
(byte) ((p & 0x00000000000000ff)),
(byte) ((p & 0x000000000000ff00) >> 8),
(byte) ((p & 0x0000000000ff0000) >> 16),
(byte) ((p & 0x00000000ff000000) >> 24),
(byte) ((p & 0x000000ff00000000) >> 32),
(byte) ((p & 0x0000ff0000000000) >> 40),
(byte) ((p & 0x00ff000000000000) >> 48),
(byte) ((p & 0xff00000000000000) >> 56),
};
#else
uint p = (uint) content;
_content = new byte[4]
{
(byte) ((p & 0x000000ff)),
(byte) ((p & 0x0000ff00) >> 8),
(byte) ((p & 0x00ff0000) >> 16),
(byte) ((p & 0xff000000) >> 24),
};
#endif
}
_status = new StringBuilder(256);
_headers = new StringBuilder(256);
}
public override string GetUriPath() {
return HttpUtility.UrlDecode(_uri);
}
// The file path is used as the path for configuration.
// This path should always be null, in order to retrieve
// the machine configuration.
public override string GetFilePath() {
return null;
}
public override string GetQueryString() {
return null;
}
public override string GetRawUrl() {
return _uri;
}
public override string GetHttpVerbName() {
return _method;
}
public override string GetHttpVersion() {
return "HTTP/1.0";
}
public override string GetRemoteAddress() {
StringBuilder buf;
if (_remoteAddress == null) {
buf = new StringBuilder(ADDRESS_LENGTH_MAX);
UnsafeNativeMethods.STWNDGetRemoteAddress(_tracker, buf);
_remoteAddress = buf.ToString();
}
return _remoteAddress;
}
public override int GetRemotePort() {
if (_remotePort == 0) {
_remotePort = UnsafeNativeMethods.STWNDGetRemotePort(_tracker);
}
return _remotePort;
}
public override string GetLocalAddress() {
StringBuilder buf;
if (_localAddress == null) {
buf = new StringBuilder(ADDRESS_LENGTH_MAX);
UnsafeNativeMethods.STWNDGetLocalAddress(_tracker, buf);
_localAddress = buf.ToString();
}
return _localAddress;
}
public override int GetLocalPort() {
if (_localPort == 0) {
_localPort = UnsafeNativeMethods.STWNDGetLocalPort(_tracker);
}
return _localPort;
}
public override byte[] GetPreloadedEntityBody() {
return _content;
}
public override bool IsEntireEntityBodyIsPreloaded() {
/* Request is always preloaded */
return true;
}
public override string MapPath(string virtualPath) {
/*
* Physical and virtual are identical to state server.
*/
return virtualPath;
}
public override int ReadEntityBody(byte[] buffer, int size) {
/* pretend everything is preloaded */
return 0;
}
public override long GetBytesRead() {
/* State web doesn't support partial reads */
throw new NotSupportedException(SR.GetString(SR.Not_supported));
}
public override string GetKnownRequestHeader(int index) {
string s = null;
switch (index) {
/* special case important ones */
case HeaderContentLength:
s = (_contentLength).ToString(CultureInfo.InvariantCulture);
break;
}
return s;
}
public override string GetUnknownRequestHeader(string name) {
string s = null;
if (name.Equals(StateHeaders.EXCLUSIVE_NAME)) {
switch (_exclusive) {
case UnsafeNativeMethods.StateProtocolExclusive.ACQUIRE:
s = StateHeaders.EXCLUSIVE_VALUE_ACQUIRE;
break;
case UnsafeNativeMethods.StateProtocolExclusive.RELEASE:
s = StateHeaders.EXCLUSIVE_VALUE_RELEASE;
break;
}
}
else if (name.Equals(StateHeaders.TIMEOUT_NAME)) {
if (_timeout != -1) {
s = (_timeout).ToString(CultureInfo.InvariantCulture);
}
}
else if (name.Equals(StateHeaders.LOCKCOOKIE_NAME)) {
if (_lockCookieExists) {
s = (_lockCookie).ToString(CultureInfo.InvariantCulture);
}
}
else if (name.Equals(StateHeaders.EXTRAFLAGS_NAME)) {
if (_extraFlags != -1) {
s = (_extraFlags).ToString(CultureInfo.InvariantCulture);
}
}
return s;
}
public override string[][] GetUnknownRequestHeaders() {
string [][] ret;
int c, i;
c = 0;
if (_exclusive != (UnsafeNativeMethods.StateProtocolExclusive) (-1)) {
c++;
}
if (_extraFlags != -1) {
c++;
}
if (_timeout != -1) {
c++;
}
if (_lockCookieExists) {
c++;
}
if (c == 0)
return null;
ret = new string[c][];
i = 0;
if (_exclusive != (UnsafeNativeMethods.StateProtocolExclusive) (-1)) {
ret[0] = new string[2];
ret[0][0] = StateHeaders.EXCLUSIVE_NAME;
if (_exclusive == UnsafeNativeMethods.StateProtocolExclusive.ACQUIRE) {
ret[0][1] = StateHeaders.EXCLUSIVE_VALUE_ACQUIRE;
}
else {
Debug.Assert(_exclusive == UnsafeNativeMethods.StateProtocolExclusive.RELEASE, "_exclusive == UnsafeNativeMethods.StateProtocolExclusive.RELEASE");
ret[0][1] = StateHeaders.EXCLUSIVE_VALUE_RELEASE;
}
i++;
}
if (_timeout != -1) {
ret[i] = new string[2];
ret[i][0] = StateHeaders.TIMEOUT_NAME;
ret[i][1] = (_timeout).ToString(CultureInfo.InvariantCulture);
i++;
}
if (_lockCookieExists) {
ret[i] = new string[2];
ret[i][0] = StateHeaders.LOCKCOOKIE_NAME;
ret[i][1] = (_lockCookie).ToString(CultureInfo.InvariantCulture);
i++;
}
if (_extraFlags != -1) {
ret[i] = new string[2];
ret[i][0] = StateHeaders.EXTRAFLAGS_NAME;
ret[i][1] = (_extraFlags).ToString(CultureInfo.InvariantCulture);
i++;
}
return ret;
}
public override void SendStatus(int statusCode, string statusDescription) {
Debug.Assert(!_sent);
_statusCode = statusCode;
_status.Append((statusCode).ToString(CultureInfo.InvariantCulture) + " " + statusDescription + "\r\n");
}
public override void SendKnownResponseHeader(int index, string value) {
Debug.Assert(!_sent);
_headers.Append(GetKnownResponseHeaderName(index));
_headers.Append(": ");
_headers.Append(value);
_headers.Append("\r\n");
}
public override void SendUnknownResponseHeader(string name, string value) {
Debug.Assert(!_sent);
_headers.Append(name);
_headers.Append(": ");
_headers.Append(value);
_headers.Append("\r\n");
}
public override void SendCalculatedContentLength(int contentLength) {
Debug.Assert(!_sent);
/*
* Do nothing - we append the content-length in STWNDSendResponse.
*/
}
public override bool HeadersSent() {
return _sent;
}
public override bool IsClientConnected() {
return UnsafeNativeMethods.STWNDIsClientConnected(_tracker);
}
public override void CloseConnection() {
UnsafeNativeMethods.STWNDCloseConnection(_tracker);
}
private void SendResponse() {
if (!_sent) {
_sent = true;
UnsafeNativeMethods.STWNDSendResponse(
_tracker,
_status,
_status.Length,
_headers,
_headers.Length,
_unmanagedState);
}
}
public override void SendResponseFromMemory(byte[] data, int length) {
/*
* The only content besides error message text is the pointer
* to the state item in unmanaged memory.
*/
if (_statusCode == 200) {
Debug.Assert(_unmanagedState == IntPtr.Zero, "_unmanagedState == 0");
Debug.Assert(length == IntPtr.Size, "length == IntPtr.Size");
Debug.Assert(_methodIndex == UnsafeNativeMethods.StateProtocolVerb.GET, "verb == GET");
Debug.Assert(_exclusive != UnsafeNativeMethods.StateProtocolExclusive.RELEASE,
"correct exclusive method");
if (IntPtr.Size == 4) {
_unmanagedState = (IntPtr)
(((int)data[0]) |
((int)data[1] << 8) |
((int)data[2] << 16) |
((int)data[3] << 24));
}
else {
_unmanagedState = (IntPtr)
(((long)data[0]) |
((long)data[1] << 8) |
((long)data[2] << 16) |
((long)data[3] << 24) |
((long)data[4] << 32) |
((long)data[5] << 40) |
((long)data[6] << 48) |
((long)data[7] << 56));
}
Debug.Assert(_unmanagedState != IntPtr.Zero, "_unmanagedState != 0");
}
SendResponse();
}
public override void SendResponseFromFile(string filename, long offset, long length) {
/* Not needed by state application */
throw new NotSupportedException(SR.GetString(SR.Not_supported));
}
public override void SendResponseFromFile(IntPtr handle, long offset, long length) {
/* Not needed by state application */
throw new NotSupportedException(SR.GetString(SR.Not_supported));
}
public override void FlushResponse(bool finalFlush) {
SendResponse();
}
public override void EndOfRequest() {
SendResponse();
UnsafeNativeMethods.STWNDEndOfRequest(_tracker);
}
}
}
|