We need you! We're working hard on the next version of Developer Fusion - Let us know what you think we should be up to!

The Labs \ Source Viewer \ SSCLI \ System.Net \ Booleans

  1. //------------------------------------------------------------------------------
  2. // <copyright file="HttpWebRequest.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net
  16. {
  17.     using System.Collections;
  18.     using System.Collections.Specialized;
  19.     using System.Globalization;
  20.     using System.IO;
  21.     using System.IO.Compression;
  22.     using System.Net.Cache;
  23.     using System.Net.Configuration;
  24.     using System.Runtime.Serialization;
  25.     using System.Security;
  26.     using System.Security.Cryptography.X509Certificates;
  27.     using System.Security.Permissions;
  28.     using System.Text;
  29.     using System.Text.RegularExpressions;
  30.     using System.Threading;
  31.     using System.Net.Security;
  32.     using System.Reflection;
  33.     using System.ComponentModel;
  34.    
  35.     /// <devdoc>
  36.     /// <para>
  37.     /// <see cref='System.Net.HttpWebRequest'/> is an HTTP-specific implementation of the <see cref='System.Net.WebRequest'/> class.
  38.     ///
  39.     /// Performs the major body of HTTP request processing. Handles
  40.     /// everything between issuing the HTTP header request to parsing the
  41.     /// the HTTP response. At that point, we hand off the request to the response
  42.     /// object, where the programmer can query for headers or continue reading, usw.
  43.     /// </para>
  44.     /// </devdoc>
  45.    
  46.    
  47.     [Flags()]
  48.     public enum DecompressionMethods
  49.     {
  50.         None = 0,
  51.         GZip = 1,
  52.         Deflate = 2
  53.     }
  54.    
  55.    
  56.     [Serializable()]
  57.     public class HttpWebRequest : WebRequest, ISerializable
  58.     {
  59.        
  60.         //these could have race conditions
  61.         bool m_Saw100Continue;
  62.         bool m_KeepAlive = true;
  63.         bool m_LockConnection;
  64.         bool m_NtlmKeepAlive;
  65.         bool m_PreAuthenticate;
  66.         DecompressionMethods m_AutomaticDecompression;
  67.        
  68.         private static class AbortState
  69.         {
  70.             public const int Public = 1;
  71.             public const int Internal = 2;
  72.         }
  73.         // interlocked
  74.         private int m_Aborted;
  75.        
  76.         //
  77.         // This is set on failure of the request before reattempting a retransmit,
  78.         // we do this on write/read failures so that we can recover from certain failures
  79.         // that may be caused by intermittent server/network failures.
  80.         // Returns: true, if we have seen some kind of failure.
  81.         //
  82.         // set to true if this request failed during a connect
  83.        
  84.         bool m_OnceFailed;
  85.        
  86.         bool m_Pipelined = true;
  87.         bool m_Retry = true;
  88.         bool m_HeadersCompleted;
  89.         bool m_IsCurrentAuthenticationStateProxy;
  90.         bool m_SawInitialResponse;
  91.         bool m_BodyStarted;
  92.         bool m_RequestSubmitted;
  93.         bool m_OriginallyBuffered;
  94.         bool m_Extra401Retry;
  95.        
  96.         //these should be safe.
  97.         [Flags()]
  98.         private enum Booleans : uint
  99.         {
  100.             AllowAutoRedirect = 1,
  101.             AllowWriteStreamBuffering = 2,
  102.             ExpectContinue = 4,
  103.            
  104.             ProxySet = 16,
  105.            
  106.             UnsafeAuthenticatedConnectionSharing = 64,
  107.             IsVersionHttp10 = 128,
  108.             SendChunked = 256,
  109.             EnableDecompression = 512,
  110.             IsTunnelRequest = 1024,
  111.             Default = AllowAutoRedirect | AllowWriteStreamBuffering | ExpectContinue
  112.         }
  113.        
  114.        
  115.         internal const HttpStatusCode MaxOkStatus = (HttpStatusCode)299;
  116.         private const HttpStatusCode MaxRedirectionStatus = (HttpStatusCode)399;
  117.         private const int RequestLineConstantSize = 12;
  118.         private const string ContinueHeader = "100-continue";
  119.         internal const string ChunkedHeader = "chunked";
  120.         internal const string GZipHeader = "gzip";
  121.         internal const string DeflateHeader = "deflate";
  122.        
  123.        
  124.         // default delay on the Stream.Read and Stream.Write operations
  125.         private const int DefaultReadWriteTimeout = 5 * 60 * 1000;
  126.         // 5 minutes
  127.         // time delay that we would wait for continue
  128.         internal const int DefaultContinueTimeout = 350;
  129.         // ms
  130.         // Size of ' HTTP/x.x\r\n'
  131.         // which are the
  132.         // unchanging pieces of the
  133.         // request line.
  134.         private static readonly byte[] HttpBytes = new byte[] {(byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/'};
  135.        
  136.         // Statics used in the 100 Continue timeout mechanism.
  137.         private static readonly WaitCallback s_EndWriteHeaders_Part2Callback = new WaitCallback(EndWriteHeaders_Part2Wrapper);
  138.         private static readonly TimerThread.Callback s_ContinueTimeoutCallback = new TimerThread.Callback(ContinueTimeoutCallback);
  139.         private static readonly TimerThread.Queue s_ContinueTimerQueue = TimerThread.GetOrCreateQueue(DefaultContinueTimeout);
  140.         private static readonly TimerThread.Callback s_TimeoutCallback = new TimerThread.Callback(TimeoutCallback);
  141.         private static readonly WaitCallback s_AbortWrapper = new WaitCallback(AbortWrapper);
  142.        
  143.         private static int s_UniqueGroupId;
  144.        
  145.         private Booleans _Booleans = Booleans.Default;
  146.        
  147.         private DateTime _CachedIfModifedSince = DateTime.MinValue;
  148.        
  149.         // Used in the 100 Continue timeout mechanism.
  150.         private TimerThread.Timer m_ContinueTimer;
  151.         private InterlockedGate m_ContinueGate;
  152.        
  153.         // Holds a WriteStream result to be processed by GetResponse.
  154.         private object m_PendingReturnResult;
  155.        
  156.         // Read and Write async results - corspond to BeginGetResponse(read), and BeginGetRequestStream(write)
  157.         private LazyAsyncResult _WriteAResult;
  158.         private LazyAsyncResult _ReadAResult;
  159.        
  160.         // Used by our Connection to block the Request on getting a Connection
  161.         private LazyAsyncResult _ConnectionAResult;
  162.         // Used by our Connection to block on being able to Read from our Connection
  163.         private LazyAsyncResult _ConnectionReaderAResult;
  164.        
  165.         // Once set, the Request either works Async or Sync internally
  166.         private TriState _RequestIsAsync;
  167.        
  168.         // Delegate that can be called on Continue Response
  169.         private HttpContinueDelegate _ContinueDelegate;
  170.        
  171.         // Link back to the server point used for this request.
  172.         internal ServicePoint _ServicePoint;
  173.        
  174.         // this is generated by SetResponse
  175.         internal HttpWebResponse _HttpResponse;
  176.        
  177.        
  178.         // set by Connection code upon completion (can be either CoreResponseData or an Exception)
  179.         private object _CoreResponse;
  180.         private int _NestedWriteSideCheck;
  181.         //To keep track nested responses for Sync case
  182.         // request values
  183.         private KnownHttpVerb _Verb;
  184.         // the actual verb set by caller or default
  185.         private KnownHttpVerb _OriginVerb;
  186.        
  187.         // our HTTP header response, request, parsing and storage objects
  188.         private WebHeaderCollection _HttpRequestHeaders;
  189.        
  190.         // send buffer for output request with headers.
  191.         private byte[] _WriteBuffer;
  192.        
  193.         // Property to set whether writes can be handled
  194.         private HttpWriteMode _HttpWriteMode;
  195.        
  196.         // the host, port, and path
  197.         private Uri _Uri;
  198.         // the origin Uri host, port and path that never changes
  199.         private Uri _OriginUri;
  200.        
  201.         // for which response ContentType we will look for and parse the CharacterSet
  202.         private string _MediaType;
  203.        
  204.         // content length
  205.         private long _ContentLength;
  206.        
  207.         // proxy that we are using...
  208.         private IWebProxy _Proxy;
  209.         private ProxyChain _ProxyChain;
  210.        
  211.         private string _ConnectionGroupName;
  212.         private bool m_InternalConnectionGroup;
  213.        
  214.         private AuthenticationState _ProxyAuthenticationState;
  215.         private AuthenticationState _ServerAuthenticationState;
  216.        
  217.         private ICredentials _AuthInfo;
  218.         private HttpAbortDelegate _AbortDelegate;
  219.        
  220.         //
  221.         // used to prevent Write Buffering,
  222.         // used otherwise for reposting POST, and PUTs in redirects
  223.         //
  224.         private ConnectStream _SubmitWriteStream;
  225.         private ConnectStream _OldSubmitWriteStream;
  226.         private int _MaximumAllowedRedirections;
  227.         private int _AutoRedirects;
  228.        
  229.         //
  230.         // generic version of _AutoRedirects above
  231.         // used to count the number of requests made off this WebRequest
  232.         //
  233.         private int _RerequestCount;
  234.        
  235.         //
  236.         // Timeout in milliseconds, if a synchronous request takes longer
  237.         // than timeout, a WebException is thrown
  238.         //
  239.         private int _Timeout;
  240.        
  241.         //
  242.         // Used to track relative time out across the use of the request
  243.         //
  244.         private TimerThread.Timer _Timer;
  245.        
  246.         //
  247.         // Timer factory, tied to the _Timeout time.
  248.         //
  249.         private TimerThread.Queue _TimerQueue;
  250.        
  251.         private int _RequestContinueCount;
  252.        
  253.         //
  254.         // Timeout for Read & Write on the Stream that we return through
  255.         // GetResponse().GetResponseStream() && GetRequestStream()
  256.         //
  257.         private int _ReadWriteTimeout;
  258.        
  259.         private CookieContainer _CookieContainer;
  260.        
  261.         private int _MaximumResponseHeadersLength;
  262.        
  263.         private UnlockConnectionDelegate _UnlockDelegate;
  264.        
  265.        
  266.        
  267.         // size of post data, that needs to be greater, before we wait for a continue response
  268.         // private static int DefaultRequireWaitForContinueSize = 2048; // bytes
  269.        
  270.        
  271.        
  272.         //
  273.         // Properties
  274.         //
  275.        
  276.         internal TimerThread.Timer RequestTimer {
  277.             get { return _Timer; }
  278.         }
  279.        
  280.         internal bool Aborted {
  281.             get { return m_Aborted != 0; }
  282.         }
  283.        
  284.        
  285.         /// <devdoc>
  286.         /// <para>
  287.         /// Enables or disables automatically following redirection responses.
  288.         /// </para>
  289.         /// </devdoc>
  290.         public bool AllowAutoRedirect {
  291.             get { return (_Booleans & Booleans.AllowAutoRedirect) != 0; }
  292.             set {
  293.                 if (value) {
  294.                     _Booleans |= Booleans.AllowAutoRedirect;
  295.                 }
  296.                 else {
  297.                     _Booleans &= ~Booleans.AllowAutoRedirect;
  298.                 }
  299.             }
  300.         }
  301.        
  302.         /// <devdoc>
  303.         /// <para>
  304.         /// Enables or disables buffering the data stream sent to the server.
  305.         /// </para>
  306.         /// </devdoc>
  307.         public bool AllowWriteStreamBuffering {
  308.             get { return (_Booleans & Booleans.AllowWriteStreamBuffering) != 0; }
  309.             set {
  310.                 if (value) {
  311.                     _Booleans |= Booleans.AllowWriteStreamBuffering;
  312.                 }
  313.                 else {
  314.                     _Booleans &= ~Booleans.AllowWriteStreamBuffering;
  315.                 }
  316.             }
  317.         }
  318.        
  319.         private bool ExpectContinue {
  320.             get { return (_Booleans & Booleans.ExpectContinue) != 0; }
  321.             set {
  322.                 if (value) {
  323.                     _Booleans |= Booleans.ExpectContinue;
  324.                 }
  325.                 else {
  326.                     _Booleans &= ~Booleans.ExpectContinue;
  327.                 }
  328.             }
  329.         }
  330.        
  331.         /// <devdoc>
  332.         /// <para>
  333.         /// Returns <see langword='true'/> if a response has been received from the
  334.         /// server.
  335.         /// </para>
  336.         /// </devdoc>
  337.         public bool HaveResponse {
  338.             get { return _ReadAResult != null && _ReadAResult.InternalPeekCompleted; }
  339.         }
  340.        
  341.         // this overrides the public KeepAlive setting.
  342.         // we use this override for NTLM only
  343.         internal bool NtlmKeepAlive {
  344.             get { return m_NtlmKeepAlive; }
  345.             set { m_NtlmKeepAlive = value; }
  346.         }
  347.        
  348.        
  349.        
  350.         internal bool SawInitialResponse {
  351.             get {
  352.                 GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SawInitialResponse_get() :" + m_SawInitialResponse);
  353.                 return m_SawInitialResponse;
  354.             }
  355.             set {
  356.                 GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SawInitialResponse_set() :" + value);
  357.                 m_SawInitialResponse = value;
  358.             }
  359.         }
  360.        
  361.         internal bool BodyStarted {
  362.             get { return m_BodyStarted; }
  363.         }
  364.        
  365. /*
  366.             Accessor:  KeepAlive
  367.             To the app, this means "I want to use a persistent connection if
  368.             available" if set to true, or "I don't want to use a persistent
  369.             connection", if set to false.
  370.             This accessor allows the application simply to register its
  371.             desires so far as persistence is concerned. We will act on this
  372.             and the pipelined requirement (below) at the point that we come
  373.             to choose or create a connection on the application's behalf
  374.             Read:      returns the sense of the keep-alive request switch
  375.             Write:      set the sense of the keep-alive request switch
  376.         */       
  377.        
  378.         /// <devdoc>
  379.         /// <para>
  380.         /// Gets or sets the value of the Keep-Alive header.
  381.         /// </para>
  382.         /// </devdoc>
  383.         public bool KeepAlive {
  384.             get { return m_KeepAlive; }
  385.             set { m_KeepAlive = value; }
  386.         }
  387.        
  388.         //
  389.         // LockConnection - set to true when the
  390.         // request needs exclusive access to the Connection
  391.         //
  392.         internal bool LockConnection {
  393.             get { return m_LockConnection; }
  394.             set { m_LockConnection = value; }
  395.         }
  396.        
  397.        
  398. /*
  399.             Accessor:  Pipelined
  400.             To the app, this means "I want to use pipelining if available" if
  401.             set to true, or "I don't want to use pipelining", if set to false.
  402.             We could infer the state of the keep-alive flag from this setting
  403.             too, but we will decide that only at connection-initiation time.
  404.             If the application sets pipelining but resets keep-alive then we
  405.             will generate a non-pipelined, non-keep-alive request
  406.             Read:      returns the sense of the pipelined request switch
  407.             Write:      sets the sense of the pipelined request switch
  408.         */       
  409.        
  410.         /// <devdoc>
  411.         /// <para>
  412.         /// Gets or sets the value of Pipelined property.
  413.         /// </para>
  414.         /// </devdoc>
  415.         public bool Pipelined {
  416.             get { return m_Pipelined; }
  417.             set { m_Pipelined = value; }
  418.         }
  419.        
  420.         /// <devdoc>
  421.         /// <para>
  422.         /// Enables or disables pre-authentication.
  423.         /// </para>
  424.         /// </devdoc>
  425.         public override bool PreAuthenticate {
  426.             get { return m_PreAuthenticate; }
  427.             set { m_PreAuthenticate = value; }
  428.         }
  429.        
  430.         private bool ProxySet {
  431.             get { return (_Booleans & Booleans.ProxySet) != 0; }
  432.             set {
  433.                 if (value) {
  434.                     _Booleans |= Booleans.ProxySet;
  435.                 }
  436.                 else {
  437.                     _Booleans &= ~Booleans.ProxySet;
  438.                 }
  439.             }
  440.         }
  441.        
  442.         private bool RequestSubmitted {
  443.             get { return m_RequestSubmitted; }
  444.         }
  445.        
  446.         // Call under lock.
  447.         private bool SetRequestSubmitted()
  448.         {
  449.             bool ret = RequestSubmitted;
  450.             m_RequestSubmitted = true;
  451.             GlobalLog.Print("HttpWebRequest#" + ValidationHelper.HashString(this) + "::SetRequestSubmitted() returning:" + ret.ToString());
  452.             return ret;
  453.         }
  454.        
  455.        
  456.         //
  457.         // if the 100 Continue comes in around 350ms there might be race conditions
  458.         // that make us set Understands100Continue to true when parsing the 100 response
  459.         // in the Connection object and later make us set it to false if the
  460.         // thread that is waiting comes in later than 350ms. to solve this we save info
  461.         // on wether we did actually see the 100 continue. In that case, even if there's a
  462.         // timeout, we won't set it to false.
  463.         //
  464.         internal bool Saw100Continue {
  465.             get { return m_Saw100Continue; }
  466.             set { m_Saw100Continue = value; }
  467.         }
  468.        
  469.         /// <devdoc>
  470.         /// <para>Allows hi-speed NTLM connection sharing with keep-alive</para>
  471.         /// </devdoc>
  472.         public bool UnsafeAuthenticatedConnectionSharing {
  473.             get { return (_Booleans & Booleans.UnsafeAuthenticatedConnectionSharing) != 0; }
  474.             set {
  475.                 ExceptionHelper.WebPermissionUnrestricted.Demand();
  476.                 if (value) {
  477.                     _Booleans |= Booleans.UnsafeAuthenticatedConnectionSharing;
  478.                 }
  479.                 else {
  480.                     _Booleans &= ~Booleans.UnsafeAuthenticatedConnectionSharing;
  481.                 }
  482.             }
  483.         }
  484.         //
  485.         // When authenticating TO THE proxy we create a shared connection
  486.         //
  487.         internal bool UnsafeOrProxyAuthenticatedConnectionSharing {
  488.             get { return m_IsCurrentAuthenticationStateProxy || UnsafeAuthenticatedConnectionSharing; }
  489.         }
  490.        
  491.        
  492.         // HTTP version of the request
  493.         private bool IsVersionHttp10 {
  494.             get { return (_Booleans & Booleans.IsVersionHttp10) != 0; }
  495.             set {
  496.                 if (value) {
  497.                     _Booleans |= Booleans.IsVersionHttp10;
  498.                 }
  499.                 else {
  500.                     _Booleans &= ~Booleans.IsVersionHttp10;
  501.                 }
  502.             }
  503.         }
  504.        
  505.         //
  506.         // SendChunked - set/gets the state of chunk transfer send mode,
  507.         // if true, we will attempt to upload/write bits using chunked property
  508.         //
  509.        
  510.         /// <devdoc>
  511.         /// <para>
  512.         /// Enable and disable sending chunked data to the server.
  513.         /// </para>
  514.         /// </devdoc>
  515.         public bool SendChunked {
  516.             get { return (_Booleans & Booleans.SendChunked) != 0; }
  517.             set {
  518.                 if (RequestSubmitted) {
  519.                     throw new InvalidOperationException(SR.GetString(SR.net_writestarted));
  520.                 }
  521.                 if (value) {
  522.                     _Booleans |= Booleans.SendChunked;
  523.                 }
  524.                 else {
  525.                     _Booleans &= ~Booleans.SendChunked;
  526.                 }
  527.             }
  528.         }
  529.        
  530.         public DecompressionMethods AutomaticDecompression {
  531.             get { return m_AutomaticDecompression; }
  532.             set {
  533.                 if (RequestSubmitted) {
  534.                     throw new InvalidOperationException(SR.GetString(SR.net_writestarted));
  535.                 }
  536.                 m_AutomaticDecompression = value;
  537.             }
  538.         }
  539.        
  540.        
  541. /*
  542.         //                         
  543.         internal DecompressionMethods DecompressionMethod{
  544.             get{
  545.                 DecompressionMethods method = DecompressionMethods.None;
  546.                 string acceptEncoding = Headers[HttpKnownHeaderNames.AcceptEncoding];
  547.                 if (acceptEncoding != null){
  548.                     if((AutomaticDecompression & DecompressionMethods.GZip) != 0){
  549.                         method = DecompressionMethods.GZip;
  550.                     }
  551.                     //was it set directly?
  552.                     else if(acceptEncoding.IndexOf(HttpWebRequest.GZipHeader) != -1) {
  553.                         method=DecompressionMethods.GZip;
  554.                     }
  555.                     if (acceptEncoding.IndexOf(HttpWebRequest.DeflateHeader) != -1){
  556.                         method |= DecompressionMethods.Deflate;
  557.                     }
  558.                 }
  559.                 return method;
  560.             }
  561.         }
  562.         */       
  563.        
  564.        
  565.         // This property holds our actual behaviour.
  566.         // In some cases we might have to disable chunking even if the user has requested it.
  567.         // In this case SendChunked returns true, but HttpWriteMode is != HttpWriteMode.Chunked
  568.         internal HttpWriteMode HttpWriteMode {
  569.             get { return _HttpWriteMode; }
  570.             set { _HttpWriteMode = value; }
  571.         }
  572.        
  573.        
  574.         internal string AuthHeader(HttpResponseHeader header)
  575.         {
  576.             if (_HttpResponse == null) {
  577.                 return null;
  578.             }
  579.             // currently if'd out in HttpWebRequest.cs
  580.             return _HttpResponse.Headers[(int)header];
  581.         }
  582.        
  583.         // This is a shortcut that would set the default policy for HTTP/HTTPS.
  584.         // The default policy is overridden by any prefix-registered policy.
  585.         // Will demand permission for set{}
  586.         public