[runtime] Replace pedump boehm dependency with sgen dependency
[mono.git] / mcs / class / referencesource / System / net / System / Net / WebRequest.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="WebRequest.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6
7 namespace System.Net {
8     using System.Collections;
9     using System.Collections.Generic;
10     using System.Configuration;
11     using System.Diagnostics.CodeAnalysis;
12     using System.Diagnostics.Contracts;
13     using System.Diagnostics.Tracing;
14     using System.Globalization;
15     using System.IO;
16     using System.Net.Cache;
17     using System.Net.Configuration;
18     using System.Reflection;
19     using System.Runtime.Serialization;
20     using System.Security.Permissions;
21     using System.Security.Principal;
22     using System.Threading;
23     using System.Threading.Tasks;
24     using System.Net.Security;
25     using System.ComponentModel;
26     using System.Security;
27     //
28     // WebRequest - the base class of all Web resource/protocol objects. Provides
29     // common methods, data and proprties for making the top level request
30     //
31
32     /// <devdoc>
33     ///    <para>A request to a Uniform Resource Identifier (Uri). This
34     ///       is an abstract class.</para>
35     /// </devdoc>
36     [Serializable]
37     public abstract class WebRequest : MarshalByRefObject, ISerializable
38     {
39 #if FEATURE_PAL // ROTORTODO - after speed ups (like real JIT and GC) remove this one
40 #if DEBUG
41         internal const int DefaultTimeout = 100000 * 10;
42 #else // DEBUG
43         internal const int DefaultTimeout = 100000 * 5;
44 #endif // DEBUG
45 #else // FEATURE_PAL
46         internal const int DefaultTimeout = 100000; // default timeout is 100 seconds (ASP .NET is 90 seconds)
47 #endif // FEATURE_PAL
48         private static volatile ArrayList s_PrefixList;
49         private static Object s_InternalSyncObject;
50         private static TimerThread.Queue s_DefaultTimerQueue = TimerThread.CreateQueue(DefaultTimeout);
51
52 #if !FEATURE_PAL
53         private  AuthenticationLevel m_AuthenticationLevel;
54         private  TokenImpersonationLevel m_ImpersonationLevel;
55 #endif
56         private RequestCachePolicy      m_CachePolicy;
57         private RequestCacheProtocol    m_CacheProtocol;
58         private RequestCacheBinding     m_CacheBinding;
59
60 #region designer support for System.Windows.dll
61         internal class DesignerWebRequestCreate : IWebRequestCreate
62         {
63             public WebRequest Create(Uri uri)
64             {
65                 return WebRequest.Create(uri);
66             }
67         }
68         private static DesignerWebRequestCreate webRequestCreate = new DesignerWebRequestCreate();
69         //introduced for supporting design-time loading of System.Windows.dll
70         [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)]
71         [EditorBrowsable(EditorBrowsableState.Never)]
72         public virtual IWebRequestCreate CreatorInstance { get { return webRequestCreate; } }
73
74         //introduced for supporting design-time loading of System.Windows.dll
75         [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)]
76         [EditorBrowsable(EditorBrowsableState.Never)]
77         public static void RegisterPortableWebRequestCreator(IWebRequestCreate creator) { }       
78 #endregion        
79
80         private static Object InternalSyncObject {
81             get {
82                 if (s_InternalSyncObject == null) {
83                     Object o = new Object();
84                     Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
85                 }
86                 return s_InternalSyncObject;
87             }
88         }
89
90         internal static TimerThread.Queue DefaultTimerQueue {
91             get {
92                 return s_DefaultTimerQueue;
93             }
94         }
95
96         /*++
97
98             Create - Create a WebRequest.
99
100             This is the main creation routine. We take a Uri object, look
101             up the Uri in the prefix match table, and invoke the appropriate
102             handler to create the object. We also have a parameter that
103             tells us whether or not to use the whole Uri or just the
104             scheme portion of it.
105
106             Input:
107
108                 RequestUri          - Uri object for request.
109                 UseUriBase          - True if we're only to look at the scheme
110                                         portion of the Uri.
111
112             Returns:
113
114                 Newly created WebRequest.
115         --*/
116
117         private static WebRequest Create(Uri requestUri, bool useUriBase) {
118             if(Logging.On)Logging.Enter(Logging.Web, "WebRequest", "Create", requestUri.ToString());
119
120             string LookupUri;
121             WebRequestPrefixElement Current = null;
122             bool Found = false;
123
124             if (!useUriBase)
125             {
126                 LookupUri = requestUri.AbsoluteUri;
127             }
128             else {
129
130                 //
131                 // schemes are registered as <schemeName>":", so add the separator
132                 // to the string returned from the Uri object
133                 //
134
135                 LookupUri = requestUri.Scheme + ':';
136             }
137
138             int LookupLength = LookupUri.Length;
139
140             // Copy the prefix list so that if it is updated it will
141             // not affect us on this thread.
142
143             ArrayList prefixList = PrefixList;
144
145             // Look for the longest matching prefix.
146
147             // Walk down the list of prefixes. The prefixes are kept longest
148             // first. When we find a prefix that is shorter or the same size
149             // as this Uri, we'll do a compare to see if they match. If they
150             // do we'll break out of the loop and call the creator.
151
152             for (int i = 0; i < prefixList.Count; i++) {
153                 Current = (WebRequestPrefixElement)prefixList[i];
154
155                 //
156                 // See if this prefix is short enough.
157                 //
158
159                 if (LookupLength >= Current.Prefix.Length) {
160
161                     //
162                     // It is. See if these match.
163                     //
164
165                     if (String.Compare(Current.Prefix,
166                                        0,
167                                        LookupUri,
168                                        0,
169                                        Current.Prefix.Length,
170                                        StringComparison.OrdinalIgnoreCase ) == 0) {
171
172                         //
173                         // These match. Remember that we found it and break
174                         // out.
175                         //
176
177                         Found = true;
178                         break;
179                     }
180                 }
181             }
182
183             WebRequest webRequest = null;
184
185             if (Found) {
186
187                 //
188                 // We found a match, so just call the creator and return what it
189                 // does.
190                 //
191
192                 webRequest = Current.Creator.Create(requestUri);
193                 if(Logging.On)Logging.Exit(Logging.Web, "WebRequest", "Create", webRequest);
194                 return webRequest;
195             }
196
197             if(Logging.On)Logging.Exit(Logging.Web, "WebRequest", "Create", null);
198
199             //
200             // Otherwise no match, throw an exception.
201             //
202
203             throw new NotSupportedException(SR.GetString(SR.net_unknown_prefix));
204         }
205
206         /*++
207
208             Create - Create a WebRequest.
209
210             An overloaded utility version of the real Create that takes a
211             string instead of an Uri object.
212
213
214             Input:
215
216                 RequestString       - Uri string to create.
217
218             Returns:
219
220                 Newly created WebRequest.
221         --*/
222
223         /// <devdoc>
224         ///    <para>
225         ///       Creates a new <see cref='System.Net.WebRequest'/>
226         ///       instance for
227         ///       the specified Uri scheme.
228         ///    </para>
229         /// </devdoc>
230         public static WebRequest Create(string requestUriString) {
231             if (requestUriString == null) {
232                 throw new ArgumentNullException("requestUriString");
233             }
234             // In .NET FX v4.0, custom IWebRequestCreate implementations can 
235             // cause this to return null.  Consider tightening this in the future.
236             //Contract.Ensures(Contract.Result<WebRequest>() != null);
237
238             return Create(new Uri(requestUriString), false);
239         }
240
241         /*++
242
243             Create - Create a WebRequest.
244
245             Another overloaded version of the Create function that doesn't
246             take the UseUriBase parameter.
247
248             Input:
249
250                 RequestUri          - Uri object for request.
251
252             Returns:
253
254                 Newly created WebRequest.
255         --*/
256
257         /// <devdoc>
258         ///    <para>
259         ///       Creates a new <see cref='System.Net.WebRequest'/> instance for the specified Uri scheme.
260         ///    </para>
261         /// </devdoc>
262         public static WebRequest Create(Uri requestUri) {
263             if (requestUri == null) {
264                 throw new ArgumentNullException("requestUri");
265             }
266             // In .NET FX v4.0, custom IWebRequestCreate implementations can 
267             // cause this to return null.  Consider tightening this in the future.
268             //Contract.Ensures(Contract.Result<WebRequest>() != null);
269
270             return Create(requestUri, false);
271         }
272
273         /*++
274
275             CreateDefault - Create a default WebRequest.
276
277             This is the creation routine that creates a default WebRequest.
278             We take a Uri object and pass it to the base create routine,
279             setting the useUriBase parameter to true.
280
281             Input:
282
283                 RequestUri          - Uri object for request.
284
285             Returns:
286
287                 Newly created WebRequest.
288         --*/
289         /// <devdoc>
290         ///    <para>[To be supplied.]</para>
291         /// </devdoc>
292         public static WebRequest CreateDefault(Uri requestUri) {
293             if (requestUri == null) {
294                 throw new ArgumentNullException("requestUri");
295             }
296             // In .NET FX v4.0, custom IWebRequestCreate implementations can 
297             // cause this to return null.  Consider tightening this in the future.
298             //Contract.Ensures(Contract.Result<WebRequest>() != null);
299
300             return Create(requestUri, true);
301         }
302         
303         // For portability
304         public static HttpWebRequest CreateHttp(string requestUriString) {
305             if (requestUriString == null) {
306                 throw new ArgumentNullException("requestUriString");
307             }
308             return CreateHttp(new Uri(requestUriString));
309         }
310
311         // For portability
312         public static HttpWebRequest CreateHttp(Uri requestUri) {
313             if (requestUri == null) {
314                 throw new ArgumentNullException("requestUri");
315             }
316             if ((requestUri.Scheme != Uri.UriSchemeHttp) && (requestUri.Scheme != Uri.UriSchemeHttps)) {
317                 throw new NotSupportedException(SR.GetString(SR.net_unknown_prefix));
318             }
319             return (HttpWebRequest)CreateDefault(requestUri);
320         }
321
322         /*++
323
324             RegisterPrefix - Register an Uri prefix for creating WebRequests.
325
326             This function registers a prefix for creating WebRequests. When an
327             user wants to create a WebRequest, we scan a table looking for a
328             longest prefix match for the Uri they're passing. We then invoke
329             the sub creator for that prefix. This function puts entries in
330             that table.
331
332             We don't allow duplicate entries, so if there is a dup this call
333             will fail.
334
335         Input:
336
337             Prefix           - Represents Uri prefix being registered.
338             Creator         - Interface for sub creator.
339
340         Returns:
341
342             True if the registration worked, false otherwise.
343
344         --*/
345         /// <devdoc>
346         ///    <para>
347         ///       Registers a <see cref='System.Net.WebRequest'/> descendent
348         ///       for a specific Uniform Resource Identifier.
349         ///    </para>
350         /// </devdoc>
351         public static bool RegisterPrefix(string prefix, IWebRequestCreate creator) {
352
353             bool Error = false;
354             int i;
355             WebRequestPrefixElement Current;
356
357             if (prefix == null) {
358                 throw new ArgumentNullException("prefix");
359             }
360             if (creator == null) {
361                 throw new ArgumentNullException("creator");
362             }
363
364             ExceptionHelper.WebPermissionUnrestricted.Demand();
365
366             // Lock this object, then walk down PrefixList looking for a place to
367             // to insert this prefix.
368
369             lock(InternalSyncObject) {
370                 //
371                 // clone the object and update the clone thus
372                 // allowing other threads to still read from it
373                 //
374
375                 ArrayList prefixList = (ArrayList)PrefixList.Clone();
376
377                 // As AbsoluteUri is used later for Create, account for formating changes 
378                 // like Unicode escaping, default ports, etc.
379                 Uri tempUri;
380                 if (Uri.TryCreate(prefix, UriKind.Absolute, out tempUri))
381                 {
382                     String cookedUri = tempUri.AbsoluteUri;
383
384                     // Special case for when a partial host matching is requested, drop the added trailing slash
385                     // IE: http://host could match host or host.domain
386                     if (!prefix.EndsWith("/", StringComparison.Ordinal) 
387                         && tempUri.GetComponents(UriComponents.PathAndQuery | UriComponents.Fragment, 
388                             UriFormat.UriEscaped)
389                             .Equals("/"))
390                         cookedUri = cookedUri.Substring(0, cookedUri.Length - 1);
391
392                     prefix = cookedUri;
393                 }
394
395                 i = 0;
396
397                 // The prefix list is sorted with longest entries at the front. We
398                 // walk down the list until we find a prefix shorter than this
399                 // one, then we insert in front of it. Along the way we check
400                 // equal length prefixes to make sure this isn't a dupe.
401
402                 while (i < prefixList.Count) {
403                     Current = (WebRequestPrefixElement)prefixList[i];
404
405                     // See if the new one is longer than the one we're looking at.
406
407                     if (prefix.Length > Current.Prefix.Length) {
408                         // It is. Break out of the loop here.
409                         break;
410                     }
411
412                     // If these are of equal length, compare them.
413
414                     if (prefix.Length == Current.Prefix.Length) {
415                         // They're the same length.
416                         if (String.Compare(Current.Prefix, prefix, StringComparison.OrdinalIgnoreCase) == 0) {
417                             // ...and the strings are identical. This is an error.
418
419                             Error = true;
420                             break;
421                         }
422                     }
423                     i++;
424                 }
425
426                 // When we get here either i contains the index to insert at or
427                 // we've had an error, in which case Error is true.
428
429                 if (!Error) {
430                     // No error, so insert.
431
432                     prefixList.Insert(i,
433                                         new WebRequestPrefixElement(prefix, creator)
434                                        );
435
436                     //
437                     // no error, assign the clone to the static object, other
438                     // threads using it will have copied the oriignal object already
439                     //
440                     PrefixList = prefixList;
441                 }
442             }
443             return !Error;
444         }
445
446         /*
447         public static bool UnregisterPrefix(string prefix) {
448             if (prefix == null) {
449                 throw new ArgumentNullException("prefix");
450             }
451             ExceptionHelper.WebPermissionUnrestricted.Demand();
452
453             // Lock this object, then walk down PrefixList looking for a place to
454             // to insert this prefix.
455
456             lock(InternalSyncObject) {
457                 //
458                 // clone the object and update the clone thus
459                 // allowing other threads to still read from it
460                 //
461
462                 ArrayList prefixList = (ArrayList) PrefixList.Clone();
463
464                 int i = 0;
465                 WebRequestPrefixElement Current;
466
467                 // The prefix list is sorted with longest entries at the front. We
468                 // walk down the list until we find a prefix shorter than this
469                 // one, then we insert in front of it. Along the way we check
470                 // equal length prefixes to make sure this isn't a dupe.
471                 while (i < prefixList.Count) {
472                     Current = (WebRequestPrefixElement)prefixList[i];
473
474                     // See if the new one is longer than the one we're looking at.
475
476                     if (prefix.Length > Current.Prefix.Length) {
477                         return fasle;
478                     }
479
480                     // If these are of equal length, compare them.
481
482                     if (prefix.Length == Current.Prefix.Length) {
483                         // They're the same length.
484                         if (String.Compare(Current.Prefix, prefix, StringComparison.OrdinalIgnoreCase ) == 0) {
485                             prefixList.RemoveAt(i);
486                             PrefixList = prefixList;
487                             return true;
488                         }
489                     }
490                     i++;
491                 }
492             }
493
494             return false;
495
496         }
497         */
498
499         /*++
500
501             PrefixList - Returns And Initialize our prefix list.
502
503
504             This is the method that initializes the prefix list. We create
505             an ArrayList for the PrefixList, then an HttpRequestCreator object,
506             and then we register the HTTP and HTTPS prefixes.
507
508             Input: Nothing
509
510             Returns: true
511
512         --*/
513         internal static ArrayList PrefixList {
514
515             get {
516                 //
517                 // GetConfig() might use us, so we have a circular dependency issue,
518                 // that causes us to nest here, we grab the lock, only
519                 // if we haven't initialized.
520                 //
521                 if (s_PrefixList == null) {
522
523                     lock (InternalSyncObject) {
524                         if (s_PrefixList == null) {
525                             GlobalLog.Print("WebRequest::Initialize(): calling ConfigurationManager.GetSection()");
526                             s_PrefixList = WebRequestModulesSectionInternal.GetSection().WebRequestModules;
527                         }
528                     }
529                 }
530
531                 return s_PrefixList;
532             }
533             set {
534                 s_PrefixList = value;
535             }
536         }
537
538         // constructors
539
540         /// <devdoc>
541         ///    <para>
542         ///       Initializes a new instance of the <see cref='System.Net.WebRequest'/>
543         ///       class.
544         ///    </para>
545         /// </devdoc>
546
547         protected WebRequest()
548         {
549 #if !FEATURE_PAL
550             // Defautl values are set as per V1.0 behavior
551             m_ImpersonationLevel = TokenImpersonationLevel.Delegation;
552             m_AuthenticationLevel= AuthenticationLevel.MutualAuthRequested;
553 #endif
554         }
555         //
556         // ISerializable constructor
557         //
558         /// <devdoc>
559         ///    <para>[To be supplied.]</para>
560         /// </devdoc>
561         protected WebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) {
562         }
563
564         //
565         // ISerializable method
566         //
567         /// <internalonly/>
568         [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Justification = "System.dll is still using pre-v4 security model and needs this demand")]
569         [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter, SerializationFormatter=true)]
570         void ISerializable.GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
571         {
572             GetObjectData(serializationInfo, streamingContext);
573         }
574
575         //
576         // FxCop: Provide a way for inherited classes to access base.GetObjectData in case they also implement ISerializable.
577         //
578         [SecurityPermission(SecurityAction.Demand, SerializationFormatter=true)]
579         protected virtual void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
580         {
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 static RequestCachePolicy DefaultCachePolicy {
587             get {
588                 return RequestCacheManager.GetBinding(string.Empty).Policy;
589             }
590             set {
591                 // This is a replacement of RequestCachePermission demand since we are not including the latest in the product.
592                 ExceptionHelper.WebPermissionUnrestricted.Demand();
593
594                 RequestCacheBinding binding = RequestCacheManager.GetBinding(string.Empty);
595                 RequestCacheManager.SetBinding(string.Empty, new RequestCacheBinding(binding.Cache, binding.Validator, value));
596             }
597         }
598
599         //
600         //
601         public virtual RequestCachePolicy CachePolicy {
602             get {
603                 return m_CachePolicy;
604             }
605             set
606             {
607                 // Delayed creation of CacheProtocol until caching is actually turned on.
608                 InternalSetCachePolicy(value);
609             }
610         }
611
612
613         void InternalSetCachePolicy(RequestCachePolicy policy){
614             // Delayed creation of CacheProtocol until caching is actually turned on.
615             if (m_CacheBinding != null &&
616                 m_CacheBinding.Cache != null &&
617                 m_CacheBinding.Validator != null &&
618                 CacheProtocol == null &&
619                 policy != null &&
620                 policy.Level != RequestCacheLevel.BypassCache)
621             {
622                 CacheProtocol = new RequestCacheProtocol(m_CacheBinding.Cache, m_CacheBinding.Validator.CreateValidator());
623             }
624
625             m_CachePolicy = policy;
626         }
627
628
629         /// <devdoc>
630         ///    <para>When overridden in a derived class, gets and
631         ///       sets
632         ///       the
633         ///       protocol method used in this request. Default value should be
634         ///       "GET".</para>
635         /// </devdoc>
636         public virtual string Method {
637             get {
638                 throw ExceptionHelper.PropertyNotImplementedException;
639             }
640             set {
641                 throw ExceptionHelper.PropertyNotImplementedException;
642             }
643         }
644
645
646         /// <devdoc>
647         /// <para>When overridden in a derived class, gets a <see cref='Uri'/>
648         /// instance representing the resource associated with
649         /// the request.</para>
650         /// </devdoc>
651         public virtual Uri RequestUri {                               // read-only
652             get {
653                 throw ExceptionHelper.PropertyNotImplementedException;
654             }
655         }
656
657         //
658         // This is a group of connections that may need to be used for
659         //  grouping connecitons.
660         //
661         /// <devdoc>
662         /// </devdoc>
663         public virtual string ConnectionGroupName {
664             get {
665                 throw ExceptionHelper.PropertyNotImplementedException;
666             }
667             set {
668                 throw ExceptionHelper.PropertyNotImplementedException;
669             }
670         }
671
672
673         /*++
674
675             Headers  - Gets any request specific headers associated
676              with this request, this is simply a name/value pair collection
677
678             Input: Nothing.
679
680             Returns: This property returns WebHeaderCollection.
681
682                     read-only
683
684         --*/
685
686         /// <devdoc>
687         ///    <para>When overridden in a derived class,
688         ///       gets
689         ///       a collection of header name-value pairs associated with this
690         ///       request.</para>
691         /// </devdoc>
692         public virtual WebHeaderCollection Headers {
693             get {
694                 Contract.Ensures(Contract.Result<WebHeaderCollection>() != null);
695                 throw ExceptionHelper.PropertyNotImplementedException;
696             }
697             set {
698                 throw ExceptionHelper.PropertyNotImplementedException;
699             }
700         }
701
702
703         /// <devdoc>
704         ///    <para>When
705         ///       overridden in a derived class, gets
706         ///       and sets
707         ///       the
708         ///       content length of request data being sent.</para>
709         /// </devdoc>
710         public virtual long ContentLength {
711             get {
712                 throw ExceptionHelper.PropertyNotImplementedException;
713             }
714             set {
715                 throw ExceptionHelper.PropertyNotImplementedException;
716             }
717         }
718
719         /// <devdoc>
720         ///    <para>When
721         ///       overridden in a derived class, gets
722         ///       and
723         ///       sets
724         ///       the content type of the request data being sent.</para>
725         /// </devdoc>
726         public virtual string ContentType {
727             get {
728                 throw ExceptionHelper.PropertyNotImplementedException;
729             }
730             set {
731                 throw ExceptionHelper.PropertyNotImplementedException;
732             }
733         }
734
735         /// <devdoc>
736         ///     <para>When overridden in a derived class, gets and sets the network
737         ///       credentials used for authentication to this Uri.</para>
738         /// </devdoc>
739         public virtual ICredentials Credentials {
740             get {
741                 throw ExceptionHelper.PropertyNotImplementedException;
742             }
743             set {
744                 throw ExceptionHelper.PropertyNotImplementedException;
745             }
746         }
747
748         /// <devdoc>
749         ///    <para>Sets Credentials to CredentialCache.DefaultCredentials</para>
750         /// </devdoc>
751         public virtual bool UseDefaultCredentials  {
752             get {
753                 throw ExceptionHelper.PropertyNotImplementedException;
754             }
755             set {
756                 throw ExceptionHelper.PropertyNotImplementedException;
757             }
758         }
759
760         /// <devdoc>
761         ///    <para>When overridden in a derived class,
762         ///       gets and set proxy info. </para>
763         /// </devdoc>
764         public virtual IWebProxy Proxy {
765             get {
766                 throw ExceptionHelper.PropertyNotImplementedException;
767             }
768             set {
769                 throw ExceptionHelper.PropertyNotImplementedException;
770             }
771         }
772
773         /// <devdoc>
774         ///    <para>When overridden in a derived class,
775         ///       enables or disables pre-authentication.</para>
776         /// </devdoc>
777         public virtual bool PreAuthenticate {
778             get {
779                 throw ExceptionHelper.PropertyNotImplementedException;
780             }
781             set {
782                 throw ExceptionHelper.PropertyNotImplementedException;
783             }
784         }
785
786         //
787         // Timeout in milliseconds, if request  takes longer
788         // than timeout, a WebException is thrown
789         //
790         //UEUE
791         /// <devdoc>
792         ///    <para>[To be supplied.]</para>
793         /// </devdoc>
794         public virtual int Timeout {
795             get {
796                 throw ExceptionHelper.PropertyNotImplementedException;
797             }
798             set {
799                 throw ExceptionHelper.PropertyNotImplementedException;
800             }
801         }
802
803
804         /// <devdoc>
805         ///    <para>When overridden in a derived class,
806         ///       returns a <see cref='System.IO.Stream'/> object that is used for writing data
807         ///       to the resource identified by <see cref='WebRequest.RequestUri'/>
808         ///       .</para>
809         /// </devdoc>
810         public virtual Stream GetRequestStream() {
811             throw ExceptionHelper.MethodNotImplementedException;
812         }
813
814         /// <devdoc>
815         ///    <para>When overridden in a derived class,
816         ///       returns the response
817         ///       to an Internet request.</para>
818         /// </devdoc>
819         public virtual WebResponse GetResponse() {
820             Contract.Ensures(Contract.Result<WebResponse>() != null);
821
822             throw ExceptionHelper.MethodNotImplementedException;
823         }
824
825         /// <devdoc>
826         ///    <para>Asynchronous version of GetResponse.</para>
827         /// </devdoc>
828         [HostProtection(ExternalThreading=true)]
829         public virtual IAsyncResult BeginGetResponse(AsyncCallback callback, object state) {
830             throw ExceptionHelper.MethodNotImplementedException;
831         }
832
833
834         /// <devdoc>
835         ///    <para>Returns a WebResponse object.</para>
836         /// </devdoc>
837         public virtual WebResponse EndGetResponse(IAsyncResult asyncResult) {
838             throw ExceptionHelper.MethodNotImplementedException;
839         }
840
841         /// <devdoc>
842         ///    <para>Asynchronous version of GetRequestStream
843         ///       method.</para>
844         /// </devdoc>
845         [HostProtection(ExternalThreading=true)]
846         public virtual IAsyncResult BeginGetRequestStream(AsyncCallback callback, Object state) {
847             throw ExceptionHelper.MethodNotImplementedException;
848         }
849
850         /// <devdoc>
851         /// <para>Returns a <see cref='System.IO.Stream'/> object that is used for writing data to the resource
852         ///    identified by <see cref='System.Net.WebRequest.RequestUri'/>
853         ///    .</para>
854         /// </devdoc>
855         public virtual Stream EndGetRequestStream(IAsyncResult asyncResult) {
856             throw ExceptionHelper.MethodNotImplementedException;
857         }
858
859         // Offload to a different thread to avoid blocking the caller durring request submission.
860         [HostProtection(ExternalThreading = true)]
861         public virtual Task<Stream> GetRequestStreamAsync()
862         {
863             IWebProxy proxy = null;
864             try { proxy = Proxy; }
865             catch (NotImplementedException) { }
866
867             // Preserve context for authentication
868             if (ExecutionContext.IsFlowSuppressed() 
869                 && (UseDefaultCredentials || Credentials != null
870                     || (proxy != null && proxy.Credentials != null)))
871             {
872                 WindowsIdentity currentUser = SafeCaptureIdenity();
873
874                 // When flow is suppressed we would lose track of the current user across this thread switch.
875                 // Flow manually so that UseDefaultCredentials will work. BeginGetRequestStream will
876                 // take over from there.
877                 return Task.Run(() =>
878                 {
879                     using (currentUser)
880                     {
881                         using (currentUser.Impersonate())
882                         {
883                             return Task<Stream>.Factory.FromAsync(this.BeginGetRequestStream,
884                                 this.EndGetRequestStream, null);
885                         }
886                     }
887                 });
888             }
889             else
890             {
891                 return Task.Run(() => Task<Stream>.Factory.FromAsync(this.BeginGetRequestStream, 
892                     this.EndGetRequestStream, null));
893             }
894         }
895
896         // Offload to a different thread to avoid blocking the caller durring request submission.
897         [HostProtection(ExternalThreading = true)]
898         public virtual Task<WebResponse> GetResponseAsync()
899         {
900             IWebProxy proxy = null;
901             try { proxy = Proxy; }
902             catch (NotImplementedException) { }
903
904             // Preserve context for authentication
905             if (ExecutionContext.IsFlowSuppressed()
906                 && (UseDefaultCredentials || Credentials != null
907                     || (proxy != null && proxy.Credentials != null)))
908             {
909                 WindowsIdentity currentUser = SafeCaptureIdenity();
910
911                 // When flow is suppressed we would lose track of the current user across this thread switch.
912                 // Flow manually so that UseDefaultCredentials will work. BeginGetResponse will
913                 // take over from there.
914                 return Task.Run(() =>
915                 {
916                     using (currentUser)
917                     {
918                         using (currentUser.Impersonate())
919                         {
920                             return Task<WebResponse>.Factory.FromAsync(this.BeginGetResponse, 
921                                 this.EndGetResponse, null);
922                         }
923                     }
924                 });
925             }
926             else
927             {
928                 return Task.Run(() => Task<WebResponse>.Factory.FromAsync(this.BeginGetResponse, 
929                     this.EndGetResponse, null));
930             }
931         }
932
933         // Security: We need an assert for a call into WindowsIdentity.GetCurrent
934         [SecuritySafeCritical]
935         [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]
936         [SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification = "Needed for identity flow.")]
937         private WindowsIdentity SafeCaptureIdenity()
938         {
939             return WindowsIdentity.GetCurrent();
940         }
941
942
943         /// <summary>
944         ///    <para>Aborts the Request</para>
945         /// </summary>
946         public virtual void Abort() {
947             throw ExceptionHelper.MethodNotImplementedException;
948         }
949
950         //
951         //
952         //
953         internal RequestCacheProtocol CacheProtocol
954         {
955             get
956             {
957                 return m_CacheProtocol;
958             }
959             set
960             {
961                 m_CacheProtocol = value;
962             }
963         }
964
965 #if !FEATURE_PAL
966         //
967         //
968         //
969         public AuthenticationLevel AuthenticationLevel {
970             get {
971                 return m_AuthenticationLevel;
972             }
973             set {
974                 m_AuthenticationLevel = value;
975             }
976         }
977
978
979         // Methods to retrieve the context of the "reading phase" and of the "writing phase" of the request.
980         // Each request type can define what goes into what phase.  Typically, the writing phase corresponds to
981         // GetRequestStream() and the reading phase to GetResponse(), but if there's no request body, both phases
982         // may happen inside GetResponse().
983         //
984         // Return null only on [....] (if we're on the [....] thread).  Otherwise throw if no context is available.
985         internal virtual ContextAwareResult GetConnectingContext()
986         {
987             throw ExceptionHelper.MethodNotImplementedException;
988         }
989
990         internal virtual ContextAwareResult GetWritingContext()
991         {
992             throw ExceptionHelper.MethodNotImplementedException;
993         }
994
995         internal virtual ContextAwareResult GetReadingContext()
996         {
997             throw ExceptionHelper.MethodNotImplementedException;
998         }
999
1000
1001         //
1002         //
1003         //
1004         public TokenImpersonationLevel ImpersonationLevel {
1005             get {
1006                 return m_ImpersonationLevel;
1007             }
1008             set {
1009                 m_ImpersonationLevel = value;
1010             }
1011         }
1012 #endif  // !FEATURE_PAL
1013
1014         /// <summary>
1015         ///    <para>Provides an abstract way of having Async code callback into the request (saves a delegate)</para>
1016         /// </summary>
1017         internal virtual void RequestCallback(object obj) {
1018             throw ExceptionHelper.MethodNotImplementedException;
1019         }
1020
1021         //
1022         // Default Web Proxy implementation.
1023         //
1024         private static volatile IWebProxy s_DefaultWebProxy;
1025         private static volatile bool s_DefaultWebProxyInitialized;
1026
1027         internal static IWebProxy InternalDefaultWebProxy
1028         {
1029             get
1030             {
1031                 if (!s_DefaultWebProxyInitialized)
1032                 {
1033                     lock (InternalSyncObject)
1034                     {
1035                         if (!s_DefaultWebProxyInitialized)
1036                         {
1037                             GlobalLog.Print("WebRequest::get_InternalDefaultWebProxy(): Getting config.");
1038                             DefaultProxySectionInternal section = DefaultProxySectionInternal.GetSection();
1039                             if (section != null)
1040                             {
1041                                 s_DefaultWebProxy = section.WebProxy;
1042                             }
1043                             s_DefaultWebProxyInitialized = true;
1044                         }
1045                     }
1046                 }
1047                 return s_DefaultWebProxy;
1048             }
1049
1050             set
1051             {
1052                 // Same lock as above.  Avoid hitting config if the proxy is set first.
1053                 if (!s_DefaultWebProxyInitialized)
1054                 {
1055                     lock (InternalSyncObject)
1056                     {
1057                         s_DefaultWebProxy = value;
1058                         s_DefaultWebProxyInitialized = true;
1059                     }
1060                 }
1061                 else
1062                 {
1063                     s_DefaultWebProxy = value;
1064                 }
1065             }
1066         }
1067
1068         //
1069         // Get and set the global default proxy.  Use this instead of the old GlobalProxySelection.
1070         //
1071         public static IWebProxy DefaultWebProxy
1072         {
1073             get
1074             {
1075                 ExceptionHelper.WebPermissionUnrestricted.Demand();
1076                 return InternalDefaultWebProxy;
1077             }
1078
1079             set
1080             {
1081                 ExceptionHelper.WebPermissionUnrestricted.Demand();
1082                 InternalDefaultWebProxy = value;
1083             }
1084         }
1085
1086         //
1087         // This returns an "IE Proxy" based on the currently impersonated user's proxy settings.
1088         //
1089         public static IWebProxy GetSystemWebProxy()
1090         {
1091             ExceptionHelper.WebPermissionUnrestricted.Demand();
1092             return InternalGetSystemWebProxy();
1093         }
1094
1095         internal static IWebProxy InternalGetSystemWebProxy()
1096         {
1097             return new WebProxyWrapperOpaque(new WebProxy(true));
1098         }
1099
1100         //
1101         // To maintain backwards-compatibility, GlobalProxySelection.Select must return a proxy castable to WebProxy.
1102         // To get away from that restriction in the future, new APIs wrap the WebProxy in an internal wrapper.
1103         // Once Select is removed, the system-proxy functionality can be factored out of the WebProxy class.
1104         //
1105
1106         //
1107         // This doesn't expose the WebProxy.  It's used by GetSystemWebProxy(), which should never be castable to WebProxy.
1108         //
1109         internal class WebProxyWrapperOpaque : IAutoWebProxy
1110         {
1111             protected readonly WebProxy webProxy;
1112
1113             internal WebProxyWrapperOpaque(WebProxy webProxy)
1114             {
1115                 this.webProxy = webProxy;
1116             }
1117
1118             public Uri GetProxy(Uri destination)
1119             {
1120                 return webProxy.GetProxy(destination);
1121             }
1122
1123             public bool IsBypassed(Uri host)
1124             {
1125                 return webProxy.IsBypassed(host);
1126             }
1127
1128             public ICredentials Credentials
1129             {
1130                 get
1131                 {
1132                     return webProxy.Credentials;
1133                 }
1134
1135                 set
1136                 {
1137                     webProxy.Credentials = value;
1138                 }
1139             }
1140
1141             public ProxyChain GetProxies(Uri destination)
1142             {
1143                 return ((IAutoWebProxy) webProxy).GetProxies(destination);
1144             }
1145         }
1146
1147         //
1148         // Select returns the WebProxy out of this one.
1149         //
1150         internal class WebProxyWrapper : WebProxyWrapperOpaque
1151         {
1152             internal WebProxyWrapper(WebProxy webProxy) :
1153                 base(webProxy)
1154             { }
1155
1156             internal WebProxy WebProxy
1157             {
1158                 get
1159                 {
1160                     return webProxy;
1161                 }
1162             }
1163         }
1164
1165
1166         //
1167         internal void SetupCacheProtocol(Uri uri)
1168         {
1169             m_CacheBinding = RequestCacheManager.GetBinding(uri.Scheme);
1170
1171             // Note if the cache is disabled it will give back a bypass policy.
1172             InternalSetCachePolicy( m_CacheBinding.Policy);
1173             if (m_CachePolicy == null)
1174             {
1175                 // If the protocol cache policy is not specifically configured, grab from the base class.
1176                 InternalSetCachePolicy(WebRequest.DefaultCachePolicy);
1177             }
1178         }
1179
1180         delegate void DelEtwFireBeginWRGet(object id, string uri, bool success, bool synchronous);
1181         delegate void DelEtwFireEndWRGet(object id, bool success, bool synchronous);
1182         delegate void DelEtwFireEndWRespGet(object id, bool success, bool synchronous, int statusCode);
1183         static DelEtwFireBeginWRGet s_EtwFireBeginGetResponse;
1184         static DelEtwFireEndWRespGet s_EtwFireEndGetResponse;
1185         static DelEtwFireBeginWRGet s_EtwFireBeginGetRequestStream;
1186         static DelEtwFireEndWRGet s_EtwFireEndGetRequestStream;
1187         static volatile bool s_TriedGetEtwDelegates;
1188
1189         private static void InitEtwMethods()
1190         {
1191             Type fest = typeof(FrameworkEventSource);
1192             var beginParamTypes = new Type[] { typeof(object), typeof(string), typeof(bool), typeof(bool) };
1193             var bindingFlags = BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public;
1194             var mi1 = fest.GetMethod("BeginGetResponse", bindingFlags, null, beginParamTypes, null);
1195             var mi2 = fest.GetMethod("EndGetResponse", bindingFlags, null, new Type[] { typeof(object), typeof(bool), typeof(bool), typeof(int) }, null);
1196             var mi3 = fest.GetMethod("BeginGetRequestStream", bindingFlags, null, beginParamTypes, null);
1197             var mi4 = fest.GetMethod("EndGetRequestStream", bindingFlags, null, new Type[] { typeof(object), typeof(bool), typeof(bool) }, null);
1198             if (mi1 != null && mi2 != null && mi3 != null && mi4 != null)
1199             {
1200                 s_EtwFireBeginGetResponse = (DelEtwFireBeginWRGet) mi1.CreateDelegate(typeof(DelEtwFireBeginWRGet), FrameworkEventSource.Log);
1201                 s_EtwFireEndGetResponse = (DelEtwFireEndWRespGet)mi2.CreateDelegate(typeof(DelEtwFireEndWRespGet), FrameworkEventSource.Log);
1202                 s_EtwFireBeginGetRequestStream = (DelEtwFireBeginWRGet) mi3.CreateDelegate(typeof(DelEtwFireBeginWRGet), FrameworkEventSource.Log);
1203                 s_EtwFireEndGetRequestStream = (DelEtwFireEndWRGet) mi4.CreateDelegate(typeof(DelEtwFireEndWRGet), FrameworkEventSource.Log);
1204             }
1205             s_TriedGetEtwDelegates = true;
1206         }
1207
1208         internal void LogBeginGetResponse(bool success, bool synchronous)
1209         {
1210             string uri = this.RequestUri.OriginalString;
1211             if (!s_TriedGetEtwDelegates) 
1212                 InitEtwMethods();
1213             if (s_EtwFireBeginGetResponse != null)
1214             {
1215                 s_EtwFireBeginGetResponse(this, uri, success, synchronous);
1216             }
1217         }
1218         internal void LogEndGetResponse(bool success, bool synchronous, int statusCode)
1219         {
1220             if (!s_TriedGetEtwDelegates) 
1221                 InitEtwMethods();
1222             if (s_EtwFireEndGetResponse != null) {
1223                 s_EtwFireEndGetResponse(this, success, synchronous, statusCode);
1224             }
1225         }
1226         internal void LogBeginGetRequestStream(bool success, bool synchronous)
1227         {
1228             string uri = this.RequestUri.OriginalString;
1229             if (!s_TriedGetEtwDelegates) 
1230                 InitEtwMethods();
1231             if (s_EtwFireBeginGetRequestStream != null)
1232             {
1233                 s_EtwFireBeginGetRequestStream(this, uri, success, synchronous);
1234             }
1235         }
1236         internal void LogEndGetRequestStream(bool success, bool synchronous)
1237         {
1238             if (!s_TriedGetEtwDelegates) 
1239                 InitEtwMethods();
1240             if (s_EtwFireEndGetRequestStream != null) {
1241
1242                 s_EtwFireEndGetRequestStream(this, success, synchronous);
1243             }
1244         }
1245     } // class WebRequest
1246 } // namespace System.Net