File: channels\core\basetransportheaders.cs
Project: ndp\clr\src\managedlibraries\remoting\System.Runtime.Remoting.csproj (System.Runtime.Remoting)
// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
//==========================================================================
//  File:       BaseTransportHeaders.cs
//
//  Summary:    Base class for special-cased transport headers implementations.
//
//==========================================================================
 
 
using System;
using System.Collections;
using System.Globalization;
using System.Net;
 
 
namespace System.Runtime.Remoting.Channels
{
 
    [Serializable]
    internal class BaseTransportHeaders : ITransportHeaders
    {
        // IMPORTANT: If a new wellknown header is added, MapHeaderNameToIndex,
        //   GetValueFromHeaderIndex, and SetValueFromHeaderIndex methods must
        //   be updated (as well as WellknownHeaderCount)!!!
 
        internal const int WellknownHeaderCount = 4;
 
        private Object _connectionId; // 0) CommonTransportKeys.ConnectionId
        private Object _ipAddress;    // 1) CommonTransportKeys.IPAddress
    
        private String _requestUri;   // 2) CommonTransportKeys.RequestUri
        private String _contentType;  // 3) "Content-Type"
 
 
        // transport headers structure is for non well-known headers
        private ITransportHeaders _otherHeaders;
 
 
        public BaseTransportHeaders()
        {
            _otherHeaders = null;
        }
 
 
        public String RequestUri
        {
            get { return _requestUri; }
            set { _requestUri = value; }
        } // RequestUri
 
 
        public String ContentType
        {
            get { return _contentType; }
            set { _contentType = value; }
        } // ContentType
 
 
        public Object ConnectionId
        {
            set { _connectionId = value; }
        }
 
        public IPAddress IPAddress
        {
            set { _ipAddress = value; }
        }        
 
 
        //
        // ITransportHeaders implementation
        //
 
        public Object this[Object key]
        {
            get 
            {
                String strKey = key as String;
                if (strKey != null)
                {
                    int index = MapHeaderNameToIndex(strKey);
                    if (index != -1)
                        return GetValueFromHeaderIndex(index);
                }
            
                if (_otherHeaders != null)
                    return _otherHeaders[key];
 
                return null;
            } // get
 
            set
            {
                bool bSet = false;
            
                String strKey = key as String;
                if (strKey != null)
                {
                    int index = MapHeaderNameToIndex(strKey);
                    if (index != -1)     
                    {
                        SetValueFromHeaderIndex(index, value);
                        bSet = true;
                    }
                }
 
                if (!bSet)
                {
                    if (_otherHeaders == null)
                        _otherHeaders = new TransportHeaders();
                    _otherHeaders[key] = value;
                }
            } // set
        } // Object this[Object key]
 
 
        public IEnumerator GetEnumerator() 
        {
            return new BaseTransportHeadersEnumerator(this);
        } // GetEnumerator
 
 
        internal IEnumerator GetOtherHeadersEnumerator()
        {
            if (_otherHeaders == null)
                return null;
 
            return _otherHeaders.GetEnumerator();            
        } // GetOtherHeadersEnumerator
 
 
 
        internal int MapHeaderNameToIndex(String headerName)
        {
            // 0) CommonTransportKeys.ConnectionId
            // 1) CommonTransportKeys.IPAddress
            // 2) CommonTransportKeys.RequestUri
            // 3) "Content-Type"
            
            if (String.Compare(headerName, CommonTransportKeys.ConnectionId, StringComparison.OrdinalIgnoreCase) == 0)
                return 0;
            else
            if (String.Compare(headerName, CommonTransportKeys.IPAddress, StringComparison.OrdinalIgnoreCase) == 0)
                return 1;
            else
            if (String.Compare(headerName, CommonTransportKeys.RequestUri, StringComparison.OrdinalIgnoreCase) == 0)
                return 2;
            else
            if (String.Compare(headerName, "Content-Type", StringComparison.OrdinalIgnoreCase) == 0)
                return 3;
 
            return -1;
        } // MapHeaderNameToIndex
 
 
        internal String MapHeaderIndexToName(int index)
        {
            // 0) CommonTransportKeys.ConnectionId
            // 1) CommonTransportKeys.IPAddress
            // 2) CommonTransportKeys.RequestUri
            // 3) "Content-Type"
 
            switch (index)
            {
            case 0: return CommonTransportKeys.ConnectionId;
            case 1: return CommonTransportKeys.IPAddress;            
            case 2: return CommonTransportKeys.RequestUri;
            case 3: return "Content-Type";
            
            default: return null;
            }
            
        } // MapHeaderNameToIndex
 
 
        internal Object GetValueFromHeaderIndex(int index)
        {
            // NOTE: If this method returns the null, then that indicates the header has no
            //   value (i.e. isn't in the "dictionary"). For the purposes of iteration, this
            //   means that the header should be skipped.
        
            // 0) CommonTransportKeys.ConnectionId
            // 1) CommonTransportKeys.IPAddress
            // 2) CommonTransportKeys.RequestUri
            // 3) "Content-Type"
 
            switch (index)
            {
            case 0: return _connectionId;
            case 1: return _ipAddress;            
            case 2: return _requestUri;
            case 3: return _contentType;
            
            default: return null;
            }
            
        } // MapHeaderIndexToValue
 
 
        internal void SetValueFromHeaderIndex(int index, Object value)
        {
            // NOTE: If this method returns the null, then that indicates the header has no
            //   value (i.e. isn't in the "dictionary"). For the purposes of iteration, this
            //   means that the header should be skipped.
        
            // 0) CommonTransportKeys.ConnectionId
            // 1) CommonTransportKeys.IPAddress
            // 2) CommonTransportKeys.RequestUri
            // 3) "Content-Type"
 
            switch (index)
            {
            case 0: _connectionId = value; break;
            case 1: _ipAddress = value; break;        
            case 2: _requestUri = (String)value; break;
            case 3: _contentType = (String)value; break;
 
            default: 
            {
                InternalRemotingServices.RemotingAssert(false, "someone forgot to update this method"); 
                break;
            }
            
            } // switch (index)
            
        } // MapHeaderIndexToValue
        
 
    
    } // class BaseTransportHeaders
 
 
 
    internal class BaseTransportHeadersEnumerator : IEnumerator
    {
        private BaseTransportHeaders _headers;
        private bool _bStarted;
        private int _currentIndex;
        private IEnumerator _otherHeadersEnumerator;
    
        public BaseTransportHeadersEnumerator(BaseTransportHeaders headers)
        {
            _headers = headers;
            Reset();
        } // BaseTransportHeadersEnumerator
 
    
        public bool MoveNext()
        {
            if (_currentIndex != -1)
            {
                if (_bStarted)
                    _currentIndex++;
                else
                    _bStarted = true;
 
                while (_currentIndex != -1)
                {
                    if (_currentIndex >= BaseTransportHeaders.WellknownHeaderCount)
                    {
                        _otherHeadersEnumerator = _headers.GetOtherHeadersEnumerator();
                        _currentIndex = -1;
                    }
                    else
                    {
                        if (_headers.GetValueFromHeaderIndex(_currentIndex) != null)
                            return true;
                
                        _currentIndex++;
                    }
                }
            }
            
            if (_otherHeadersEnumerator != null)
            {
                if (!_otherHeadersEnumerator.MoveNext())
                {
                    _otherHeadersEnumerator = null;
                    return false;                   
                }
                else
                    return true;                    
            }
 
            return false;
        } // MoveNext
        
        public void Reset()
        {
            _bStarted = false;
            _currentIndex = 0;
            _otherHeadersEnumerator = null;
        } // Reset
 
        public Object Current  
        {
            get 
            {
                if (!_bStarted)
                    return null;
            
                if (_currentIndex != -1)
                {
                    return 
                        new DictionaryEntry(
                            _headers.MapHeaderIndexToName(_currentIndex),
                            _headers.GetValueFromHeaderIndex(_currentIndex));
                }
 
                if (_otherHeadersEnumerator != null)
                {
                    return _otherHeadersEnumerator.Current;
                }
 
                return null;
            }
        } // Current
        
    } // class BaseTransportHeadersEnumerator
 
 
 
 
} // namespace System.Runtime.Remoting.Channels