diff --git a/src/System.Net.Http/CFContentStream.cs b/src/System.Net.Http/CFContentStream.cs
index 4e4985cac8dc..b2acefdbcd9b 100644
--- a/src/System.Net.Http/CFContentStream.cs
+++ b/src/System.Net.Http/CFContentStream.cs
@@ -35,22 +35,21 @@
using CFNetwork;
using CoreFoundation;
-// Disable until we get around to enable + fix any issues.
-#nullable disable
+#nullable enable
namespace System.Net.Http {
class BufferData {
- public byte [] Buffer;
+ public required byte [] Buffer;
public int Length;
}
class CFContentStream : HttpContent {
readonly CFHTTPStream http_stream;
- BufferData data;
+ BufferData? data;
Mutex data_mutex;
AutoResetEvent data_event;
AutoResetEvent data_read_event;
- ExceptionDispatchInfo http_exception;
+ ExceptionDispatchInfo? http_exception;
// The requirements are:
// * We must read at least one byte from the stream every time
@@ -83,13 +82,18 @@ public CFContentStream (CFHTTPStream stream)
data_mutex = new Mutex ();
}
- void HandleErrorEvent (object sender, CFStream.StreamEventArgs e)
+ void HandleErrorEvent (object? sender, CFStream.StreamEventArgs e)
{
+ if (sender is null)
+ return;
var gotMutex = data_mutex.WaitOne ();
if (gotMutex) {
var stream = (CFHTTPStream) sender;
- if (e.EventType == CFStreamEventType.ErrorOccurred)
- Volatile.Write (ref http_exception, ExceptionDispatchInfo.Capture (stream.GetError ()));
+ if (e.EventType == CFStreamEventType.ErrorOccurred) {
+ var error = stream.GetError ();
+ if (error is not null)
+ Volatile.Write (ref http_exception, ExceptionDispatchInfo.Capture (error));
+ }
data_mutex.ReleaseMutex ();
}
}
@@ -99,7 +103,8 @@ public void ReadStreamData ()
data_read_event.WaitOne (); // make sure there's no pending data.
data_mutex.WaitOne ();
- data.Length = (int) http_stream.Read (data.Buffer, 0, data.Buffer.Length);
+ if (data is not null)
+ data.Length = (int) http_stream.Read (data.Buffer, 0, data.Buffer.Length);
data_mutex.ReleaseMutex ();
data_event.Set ();
@@ -117,7 +122,7 @@ public void Close ()
data_event.Set ();
}
- protected override async Task SerializeToStreamAsync (Stream stream, TransportContext context)
+ protected override async Task SerializeToStreamAsync (Stream stream, TransportContext? context)
{
while (data_event.WaitOne ()) {
data_mutex.WaitOne ();
diff --git a/src/System.Net.Http/CFNetworkHandler.cs b/src/System.Net.Http/CFNetworkHandler.cs
index fbe5115091ce..ca3c03af3bda 100644
--- a/src/System.Net.Http/CFNetworkHandler.cs
+++ b/src/System.Net.Http/CFNetworkHandler.cs
@@ -37,8 +37,7 @@
using CoreFoundation;
using CF = CoreFoundation;
-// Disable until we get around to enable + fix any issues.
-#nullable disable
+#nullable enable
namespace System.Net.Http {
/// To be added.
@@ -53,10 +52,10 @@ namespace System.Net.Http {
[ObsoletedOSPlatform ("tvos", "Use 'NSUrlSessionHandler' instead.")]
public class CFNetworkHandler : HttpMessageHandler {
class StreamBucket {
- public TaskCompletionSource Response;
- public HttpRequestMessage Request;
+ public required TaskCompletionSource Response;
+ public required HttpRequestMessage Request;
public CancellationTokenRegistration CancellationTokenRegistration;
- public CFContentStream ContentStream;
+ public CFContentStream? ContentStream;
public bool StreamCanBeDisposed;
public void Close ()
@@ -92,7 +91,7 @@ public void Close ()
bool allowAutoRedirect;
bool sentRequest;
bool useSystemProxy;
- CookieContainer cookies;
+ CookieContainer? cookies;
Dictionary streamBuckets;
@@ -165,7 +164,8 @@ protected override void Dispose (bool disposing)
CFHTTPMessage CreateWebRequestAsync (HttpRequestMessage request)
{
- var req = CFHTTPMessage.CreateRequest (request.RequestUri, request.Method.Method, request.Version);
+ var requestUri = request.RequestUri ?? throw new InvalidOperationException ("The request URI must not be null.");
+ var req = CFHTTPMessage.CreateRequest (requestUri, request.Method.Method, request.Version);
// TODO:
/*
@@ -186,7 +186,7 @@ CFHTTPMessage CreateWebRequestAsync (HttpRequestMessage request)
}
*/
if (cookies is not null) {
- string cookieHeader = cookies.GetCookieHeader (request.RequestUri);
+ string cookieHeader = cookies.GetCookieHeader (requestUri);
if (cookieHeader != "")
req.SetHeaderFieldValue ("Cookie", cookieHeader);
}
@@ -234,7 +234,7 @@ internal async Task SendAsync (HttpRequestMessage request,
if (useSystemProxy) {
var proxies = CF.CFNetwork.GetSystemProxySettings ();
- if (proxies.HTTPEnable) {
+ if (proxies is not null && proxies.HTTPEnable) {
stream.SetProxy (proxies);
}
}
@@ -268,8 +268,7 @@ internal async Task SendAsync (HttpRequestMessage request,
stream.Open ();
bucket.CancellationTokenRegistration = cancellationToken.Register (() => {
- StreamBucket bucket2;
- if (!streamBuckets.TryGetValue (stream.Handle, out bucket2))
+ if (!streamBuckets.TryGetValue (stream.Handle, out var bucket2))
return;
bucket2.Response.TrySetCanceled ();
@@ -305,21 +304,27 @@ static bool IsRedirect (HttpStatusCode status)
status == HttpStatusCode.RedirectKeepVerb; // 307
}
- void HandleErrorEvent (object sender, CFStream.StreamEventArgs e)
+ void HandleErrorEvent (object? sender, CFStream.StreamEventArgs e)
{
+ if (sender is null)
+ return;
var stream = (CFHTTPStream) sender;
- StreamBucket bucket;
- if (!streamBuckets.TryGetValue (stream.Handle, out bucket))
+ if (!streamBuckets.TryGetValue (stream.Handle, out var bucket))
return;
var ex = stream.GetError ();
- bucket.Response.TrySetException (new HttpRequestException (ex.FailureReason, ex));
+ if (ex is not null)
+ bucket.Response.TrySetException (new HttpRequestException (ex.FailureReason, ex));
+ else
+ bucket.Response.TrySetException (new HttpRequestException ("Unknown error"));
CloseStream (stream);
}
- void HandleClosedEvent (object sender, CFStream.StreamEventArgs e)
+ void HandleClosedEvent (object? sender, CFStream.StreamEventArgs e)
{
+ if (sender is null)
+ return;
var stream = (CFHTTPStream) sender;
// might not have been called (e.g. no data) but initialize critical data
HandleHasBytesAvailableEvent (sender, e);
@@ -339,21 +344,25 @@ void CloseStream (CFHTTPStream stream)
stream.Close ();
}
- void HandleHasBytesAvailableEvent (object sender, CFStream.StreamEventArgs e)
+ void HandleHasBytesAvailableEvent (object? sender, CFStream.StreamEventArgs e)
{
+ if (sender is null)
+ return;
var stream = (CFHTTPStream) sender;
- StreamBucket bucket;
- if (!streamBuckets.TryGetValue (stream.Handle, out bucket))
+ if (!streamBuckets.TryGetValue (stream.Handle, out var bucket))
return;
if (bucket.Response.Task.IsCompleted) {
- bucket.ContentStream.ReadStreamData ();
+ bucket.ContentStream?.ReadStreamData ();
return;
}
var header = stream.GetResponseHeader ();
+ if (header is null)
+ throw new InvalidOperationException ("Failed to get response header.");
+
// Is this possible?
if (!header.IsHeaderComplete)
throw new NotImplementedException ();
@@ -372,14 +381,16 @@ void HandleHasBytesAvailableEvent (object sender, CFStream.StreamEventArgs e)
continue;
var key = entry.Key.ToString ();
- var value = entry.Value is null ? string.Empty : entry.Value.ToString ();
+ if (key is null)
+ continue;
+ var value = entry.Value is null ? string.Empty : entry.Value.ToString () ?? string.Empty;
HttpHeaders item_headers;
if (IsContentHeader (key)) {
item_headers = response_msg.Content.Headers;
} else {
item_headers = response_msg.Headers;
- if (cookies is not null && (key == "Set-Cookie" || key == "Set-Cookie2"))
+ if (cookies is not null && (key == "Set-Cookie" || key == "Set-Cookie2") && bucket.Request.RequestUri is not null)
AddCookie (value, bucket.Request.RequestUri, key);
}
@@ -391,14 +402,14 @@ void HandleHasBytesAvailableEvent (object sender, CFStream.StreamEventArgs e)
if (!bucket.Response.Task.IsCanceled) {
bucket.Response.TrySetResult (response_msg);
- bucket.ContentStream.ReadStreamData ();
+ bucket.ContentStream?.ReadStreamData ();
}
}
void AddCookie (string value, Uri uri, string header)
{
try {
- cookies.SetCookies (uri, value);
+ cookies?.SetCookies (uri, value);
} catch {
}
}
diff --git a/tests/cecil-tests/ObsoleteTest.cs b/tests/cecil-tests/ObsoleteTest.cs
index a562ec57c284..6f77488294aa 100644
--- a/tests/cecil-tests/ObsoleteTest.cs
+++ b/tests/cecil-tests/ObsoleteTest.cs
@@ -44,6 +44,10 @@ public void GetAllObsoletedThings (AssemblyInfo info)
bool FilterMember (ICustomAttributeProvider provider)
{
+ // We don't care about APIs that aren't public
+ if (provider is MemberReference mr && !mr.IsPubliclyVisible ())
+ return false;
+
// If an API isn't obsolete, it's not under scrutiny from this test.
if (!provider.IsObsolete ())
return false;