File: channels\http\httpsocketmanager.cs
Project: ndp\clr\src\managedlibraries\remoting\System.Runtime.Remoting.csproj (System.Runtime.Remoting)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
//==========================================================================
//  File:       HttpSocketManager.cs
//
//  Summary:    Provides a base for the client and server http socket 
//              managers.
//
//==========================================================================
 
 
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
 
 
namespace System.Runtime.Remoting.Channels.Http
{
 
    // A client socket manager instance should encapsulate the socket
    //   for the purpose of reading a response
    internal abstract class HttpSocketHandler : SocketHandler
    {            
        private static byte[] s_httpVersion = Encoding.ASCII.GetBytes("HTTP/1.1");
        private static byte[] s_httpVersionAndSpace = Encoding.ASCII.GetBytes("HTTP/1.1 ");
        private static byte[] s_headerSeparator = new byte[]{(byte)':',(byte)' '};
        private static byte[] s_endOfLine = new byte[]{(byte)'\r',(byte)'\n'};
 
    
        public HttpSocketHandler(Socket socket, RequestQueue requestQueue, Stream stream) : base(socket, requestQueue, stream)
        {          
        } // HttpSocketHandler
 
 
        protected void ReadToEndOfHeaders(BaseTransportHeaders headers, 
                                          out bool bChunked,
                                          out int contentLength,
                                          ref bool bKeepAlive,
                                          ref bool bSendContinue)
        {
            bChunked = false;
            contentLength = 0;
        
            // read and process headers
            for (;;)
            {
                String header = ReadToEndOfLine();
 
                // stop reading headers at first blank line
                if (header.Length == 0)
                    break;
                
                int sep = header.IndexOf(":");
                String headerName = header.Substring(0,sep);
                String headerValue = header.Substring(sep+1+1); // skip semi-colon and space
 
                if (String.Compare(headerName, "Transfer-Encoding", StringComparison.OrdinalIgnoreCase) == 0)          
                {
                    if (String.Compare(headerValue, "chunked", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        bChunked = true;
                    }
                }
                else
                if (String.Compare(headerName, "Connection", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (String.Compare(headerValue, "Keep-Alive", StringComparison.OrdinalIgnoreCase) == 0)
                        bKeepAlive = true;
                    else
                    if (String.Compare(headerValue, "Close", StringComparison.OrdinalIgnoreCase) == 0)
                        bKeepAlive = false;
                }
                else
                if (String.Compare(headerName, "Expect", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (String.Compare(headerValue, "100-continue", StringComparison.OrdinalIgnoreCase) == 0)
                        bSendContinue = true;
                }
                else
                if (String.Compare(headerName, "Content-Length", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    contentLength = Int32.Parse(headerValue, CultureInfo.InvariantCulture);
                }
                else
                {                
                    headers[headerName] = headerValue;
                }
            }
        } // ReadToEndOfHeaders
 
 
        protected void WriteHeaders(ITransportHeaders headers, Stream outputStream)
        {
            if (headers == null)
                return;
        
            foreach (DictionaryEntry header in headers)
            {
                String headerName = (String)header.Key;
 
                if (!headerName.StartsWith("__", StringComparison.Ordinal)) // exclude special headers
                {
                    WriteHeader(headerName, (String)header.Value, outputStream);
                }
            }
 
            // write end of headers "\r\n"
            outputStream.Write(s_endOfLine, 0, s_endOfLine.Length);
        } // WriteHeaders
 
        private void WriteHeader(String name, String value, Stream outputStream)
        {
            byte[] nameBytes = Encoding.ASCII.GetBytes(name); 
            byte[] valueBytes = Encoding.ASCII.GetBytes(value); 
            
            outputStream.Write(nameBytes, 0, nameBytes.Length);
            outputStream.Write(s_headerSeparator, 0, s_headerSeparator.Length);
            outputStream.Write(valueBytes, 0, valueBytes.Length);
            outputStream.Write(s_endOfLine, 0, s_endOfLine.Length);            
        } // WriteHeader
 
        protected void WriteResponseFirstLine(String statusCode, String reasonPhrase, Stream outputStream)
        {
            byte[] statusCodeBytes = Encoding.ASCII.GetBytes(statusCode); 
            byte[] reasonPhraseBytes = Encoding.ASCII.GetBytes(reasonPhrase); 
        
            outputStream.Write(s_httpVersionAndSpace, 0, s_httpVersionAndSpace.Length);
            outputStream.Write(statusCodeBytes, 0, statusCodeBytes.Length);
            outputStream.WriteByte((byte)' ');
            outputStream.Write(reasonPhraseBytes, 0, reasonPhraseBytes.Length);
            outputStream.Write(s_endOfLine, 0, s_endOfLine.Length);
        } // WriteResponseFirstLine        
 
 
    } // class HttpSocketHandler
 
 
} // namespace System.Runtime.Remoting.Channels.Tcp