Adding it to an app¶
An app needs the C# side and two files beside default.xex:
Silverlight360.Https.dll, the C# side,HttpsClientand the drop-in, withSilverlight360.Https.xmlbeside it for IntelliSense: a reference to the release's DLL, or aProjectReferenceto the repository'scsharp/Silverlight360.Https.csproj.https360.xexandcacert.pem, asContent.
The C# side uses NativeBuffer from Silverlight360's common library, Silverlight360.Common, for the memory the DLL reads and writes. An app built with Silverlight360 references that library already, and its build puts Silverlight360.Common.dll in the package.
In the app's project, as sample/HttpsSample.csproj has them:
<ItemGroup>
<ProjectReference Include="..\Silverlight360.Https\csharp\Silverlight360.Https.csproj" />
<!-- or, from a release: <Reference Include="Silverlight360.Https"><HintPath>..\Silverlight360.Https\Silverlight360.Https.dll</HintPath></Reference> -->
</ItemGroup>
<ItemGroup>
<Content Include="..\Silverlight360.Https\https360.xex"><Link>https360.xex</Link></Content>
<Content Include="..\Silverlight360.Https\cacert.pem"><Link>cacert.pem</Link></Content>
</ItemGroup>
Ship the release's licenses folder and THIRD-PARTY-NOTICES.md with them too: curl's and Mbed TLS's licenses ask for their notices to go with the binary. Silverlight360.Https's own license asks for a visible reference to https://github.com/Digiex/Silverlight360.Https in the app's documentation, credits or "about" information (see Licenses).
The drop-in¶
To leave an app's WebClient and HttpWebRequest code as it is, register the drop-in, in Silverlight360.Https.dll, once, at the start:
HttpsRequestCreator.Register();
var web = new WebClient();
web.DownloadStringCompleted += (s, e) => Show(e.Error == null ? e.Result : e.Error.Message);
web.DownloadStringAsync(new Uri("https://example.com/"));
From then on every https:// request the app makes through the platform goes through Silverlight360.Https, with TLS 1.3 and Mozilla's roots; Register(true) takes http:// too. On a console the platform's own stack fails for example.com and github.com, and Silverlight360.Https's doesn't. See API.
What each one has¶
HttpsClient |
HttpsWebRequest |
The platform's HttpWebRequest |
|
|---|---|---|---|
| TLS 1.3, Mozilla's current roots | yes | yes | no: the console's own TLS and roots, which fail for example.com and github.com |
| Works off the UI thread | blocks, on any thread | Begin/End, on the thread pool |
yes |
WebClient |
no | yes | yes |
| Request body | byte[] |
a stream | a stream |
| Response body | in memory, or a file of any size | in memory | in memory, or read as it comes |
| Response headers | lines as they came, Header(name) |
WebHeaderCollection |
WebHeaderCollection |
| Cookies | no | CookieContainer |
CookieContainer |
| Progress, cancelling | BytesReceived, Cancel() |
Abort() |
WebClient's progress events, Abort() |
| Downloads to a file, resumed | yes | no | no |
Credentials (ICredentials) |
no | no | yes |
| Compressed responses | no | no | not checked |
Making requests¶
Requests block until the response is in, so make them on a thread of their own, never the UI's:
ThreadPool.QueueUserWorkItem(delegate
{
try
{
using (var client = new HttpsClient { TimeoutSeconds = 30 })
{
HttpsResponse response = client.Get("https://api.github.com/");
string text = response.Status == 200 ? response.Text : null;
Deployment.Current.Dispatcher.BeginInvoke(() => Show(text));
}
}
catch (HttpsException e)
{
// No response came: e.Code is curl's, such as HttpsException.BadCertificate.
}
});
- One request at a time per client. A client keeps its connections open, so the next request to the same host skips the handshake: 7 ms against 260 ms for the first in xenia-edge. Use one client per thread for requests at the same time.
- Statuses aren't errors. Any HTTP response comes back as an
HttpsResponse, 404 included.HttpsExceptionmeans no response came. - The first client starts the DLL with a heap of
DefaultHeapBytes(96 MB, reserved and committed as it's used). CallHttpsClient.Start(bytes)before the first client for another size;HeapPeaksays what the requests needed. Silverdash360 gives it 16 MB, and its requests have peaked under 2 MB. - The DLL loads at
0x8D000000. In a Silverlight app's process on the console,0x8A000000,0x8C000000and0x8E000000are taken, so another DLL of the app's can't be at this base. A DllImport of a module that can't load turns into a call through null, which can power the console off, so check a new build loads first (see Testing).
Certificates¶
Servers are checked against game:\cacert.pem, and against the console's clock, which has to be right. Pass another PEM file to new HttpsClient(path) to trust other roots. Insecure turns the checks off, for a test server only.
See API for everything a client has.