using System; using System.IO; using System.Net; #if XAMCORE_2_0 using CoreFoundation; using Foundation; using ObjCRuntime; #elif MONOMAC using MonoMac.CoreFoundation; using MonoMac.Foundation; using MonoMac.ObjCRuntime; #else using MonoTouch.CoreFoundation; using MonoTouch.Foundation; using MonoTouch.ObjCRuntime; #endif #if SYSTEM_NET_HTTP && !MONOMAC namespace System.Net.Http { public partial class HttpClient { public HttpClient () : this (GetDefaultHandler (), true) { } // note: the linker will re-write this to only reference the selected handler // but we want this to work "as expected" even if the application is not being linked static HttpMessageHandler GetDefaultHandler () { #if MONOTOUCH_WATCH // There's only one valid handler type for watchOS return new NSUrlSessionHandler (); #else return RuntimeOptions.GetHttpMessageHandler (); #endif } } #else // due to historical reasons (around CFNetwork) Xamarin.Mac includes this inside it's profile assembly // and not a custom System.Net.Http assembly namespace Foundation { #endif partial class NSUrlSessionHandler { bool allowAutoRedirect; ICredentials credentials; bool sentRequest; public bool AllowAutoRedirect { get { return allowAutoRedirect; } set { EnsureModifiability (); allowAutoRedirect = value; } } public ICredentials Credentials { get { return credentials; } set { EnsureModifiability (); credentials = value; } } internal void EnsureModifiability () { if (sentRequest) throw new InvalidOperationException ( "This instance has already started one or more requests. " + "Properties can only be modified before sending the first request."); } // almost identical to ModernHttpClient version but it uses the constants from monotouch.dll | Xamarin.[iOS|WatchOS|TVOS].dll static Exception createExceptionForNSError(NSError error) { var webExceptionStatus = WebExceptionStatus.UnknownError; var innerException = new NSErrorException(error); // errors that exists in both share the same error code, so we can use a single switch/case // this also ease watchOS integration as if does not expose CFNetwork but (I would not be // surprised if it)could return some of it's error codes #if MONOTOUCH_WATCH if (error.Domain == NSError.NSUrlErrorDomain) { #else if ((error.Domain == NSError.NSUrlErrorDomain) || (error.Domain == NSError.CFNetworkErrorDomain)) { #endif // Parse the enum into a web exception status or exception. Some // of these values don't necessarily translate completely to // what WebExceptionStatus supports, so made some best guesses // here. For your reading pleasure, compare these: // // Apple docs: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/index.html#//apple_ref/doc/constant_group/URL_Loading_System_Error_Codes // .NET docs: http://msdn.microsoft.com/en-us/library/system.net.webexceptionstatus(v=vs.110).aspx switch ((NSUrlError) (long) error.Code) { case NSUrlError.Cancelled: case NSUrlError.UserCancelledAuthentication: #if !MONOTOUCH_WATCH case (NSUrlError) NSNetServicesStatus.CancelledError: #endif // No more processing is required so just return. return new OperationCanceledException(error.LocalizedDescription, innerException); case NSUrlError.BadURL: case NSUrlError.UnsupportedURL: case NSUrlError.CannotConnectToHost: case NSUrlError.ResourceUnavailable: case NSUrlError.NotConnectedToInternet: case NSUrlError.UserAuthenticationRequired: case NSUrlError.InternationalRoamingOff: case NSUrlError.CallIsActive: case NSUrlError.DataNotAllowed: #if !MONOTOUCH_WATCH case (NSUrlError) CFNetworkErrors.Socks5BadCredentials: case (NSUrlError) CFNetworkErrors.Socks5UnsupportedNegotiationMethod: case (NSUrlError) CFNetworkErrors.Socks5NoAcceptableMethod: case (NSUrlError) CFNetworkErrors.HttpAuthenticationTypeUnsupported: case (NSUrlError) CFNetworkErrors.HttpBadCredentials: case (NSUrlError) CFNetworkErrors.HttpBadURL: #endif webExceptionStatus = WebExceptionStatus.ConnectFailure; break; case NSUrlError.TimedOut: #if !MONOTOUCH_WATCH case (NSUrlError) CFNetworkErrors.NetServiceTimeout: #endif webExceptionStatus = WebExceptionStatus.Timeout; break; case NSUrlError.CannotFindHost: case NSUrlError.DNSLookupFailed: #if !MONOTOUCH_WATCH case (NSUrlError) CFNetworkErrors.HostNotFound: case (NSUrlError) CFNetworkErrors.NetServiceDnsServiceFailure: #endif webExceptionStatus = WebExceptionStatus.NameResolutionFailure; break; case NSUrlError.DataLengthExceedsMaximum: webExceptionStatus = WebExceptionStatus.MessageLengthLimitExceeded; break; case NSUrlError.NetworkConnectionLost: #if !MONOTOUCH_WATCH case (NSUrlError) CFNetworkErrors.HttpConnectionLost: #endif webExceptionStatus = WebExceptionStatus.ConnectionClosed; break; case NSUrlError.HTTPTooManyRedirects: case NSUrlError.RedirectToNonExistentLocation: #if !MONOTOUCH_WATCH case (NSUrlError) CFNetworkErrors.HttpRedirectionLoopDetected: #endif webExceptionStatus = WebExceptionStatus.ProtocolError; break; case NSUrlError.RequestBodyStreamExhausted: #if !MONOTOUCH_WATCH case (NSUrlError) CFNetworkErrors.SocksUnknownClientVersion: case (NSUrlError) CFNetworkErrors.SocksUnsupportedServerVersion: case (NSUrlError) CFNetworkErrors.HttpParseFailure: #endif webExceptionStatus = WebExceptionStatus.SendFailure; break; case NSUrlError.BadServerResponse: case NSUrlError.ZeroByteResource: case NSUrlError.CannotDecodeRawData: case NSUrlError.CannotDecodeContentData: case NSUrlError.CannotParseResponse: case NSUrlError.FileDoesNotExist: case NSUrlError.FileIsDirectory: case NSUrlError.NoPermissionsToReadFile: case NSUrlError.CannotLoadFromNetwork: case NSUrlError.CannotCreateFile: case NSUrlError.CannotOpenFile: case NSUrlError.CannotCloseFile: case NSUrlError.CannotWriteToFile: case NSUrlError.CannotRemoveFile: case NSUrlError.CannotMoveFile: case NSUrlError.DownloadDecodingFailedMidStream: case NSUrlError.DownloadDecodingFailedToComplete: #if !MONOTOUCH_WATCH case (NSUrlError) CFNetworkErrors.Socks4RequestFailed: case (NSUrlError) CFNetworkErrors.Socks4IdentdFailed: case (NSUrlError) CFNetworkErrors.Socks4IdConflict: case (NSUrlError) CFNetworkErrors.Socks4UnknownStatusCode: case (NSUrlError) CFNetworkErrors.Socks5BadState: case (NSUrlError) CFNetworkErrors.Socks5BadResponseAddr: case (NSUrlError) CFNetworkErrors.CannotParseCookieFile: case (NSUrlError) CFNetworkErrors.NetServiceUnknown: case (NSUrlError) CFNetworkErrors.NetServiceCollision: case (NSUrlError) CFNetworkErrors.NetServiceNotFound: case (NSUrlError) CFNetworkErrors.NetServiceInProgress: case (NSUrlError) CFNetworkErrors.NetServiceBadArgument: case (NSUrlError) CFNetworkErrors.NetServiceInvalid: #endif webExceptionStatus = WebExceptionStatus.ReceiveFailure; break; case NSUrlError.SecureConnectionFailed: webExceptionStatus = WebExceptionStatus.SecureChannelFailure; break; case NSUrlError.ServerCertificateHasBadDate: case NSUrlError.ServerCertificateHasUnknownRoot: case NSUrlError.ServerCertificateNotYetValid: case NSUrlError.ServerCertificateUntrusted: case NSUrlError.ClientCertificateRejected: case NSUrlError.ClientCertificateRequired: webExceptionStatus = WebExceptionStatus.TrustFailure; break; #if !MONOTOUCH_WATCH case (NSUrlError) CFNetworkErrors.HttpProxyConnectionFailure: case (NSUrlError) CFNetworkErrors.HttpBadProxyCredentials: case (NSUrlError) CFNetworkErrors.PacFileError: case (NSUrlError) CFNetworkErrors.PacFileAuth: case (NSUrlError) CFNetworkErrors.HttpsProxyConnectionFailure: case (NSUrlError) CFNetworkErrors.HttpsProxyFailureUnexpectedResponseToConnectMethod: webExceptionStatus = WebExceptionStatus.RequestProhibitedByProxy; break; #endif } } // Always create a WebException so that it can be handled by the client. return new WebException(error.LocalizedDescription, innerException); //, webExceptionStatus, response: null); } } }