Skip to content

Commit ebf7573

Browse files
rzikmliveansantonfirsov
authored
Add example for ALPN usage. (#8487)
* Add example for ALPN usage. * Fix compilation * Apply suggestions from code review Co-authored-by: Ahmet Ibrahim AKSOY <[email protected]> * Apply suggestions from code review Co-authored-by: Anton Firszov <[email protected]> Co-authored-by: Ahmet Ibrahim AKSOY <[email protected]> Co-authored-by: Anton Firszov <[email protected]>
1 parent 24aba1e commit ebf7573

File tree

5 files changed

+170
-0
lines changed

5 files changed

+170
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFrameworks>net6.0</TargetFrameworks>
6+
</PropertyGroup>
7+
8+
</Project>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System.Collections.Generic;
2+
using System.Net;
3+
using System.Net.Security;
4+
using System.Net.Sockets;
5+
using System.Security.Cryptography.X509Certificates;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
async Task RunServer()
10+
{
11+
using X509Certificate2 serverCertificate = new("contoso.com.pfx", "testcertificate");
12+
13+
14+
var listener = new TcpListener(IPAddress.Loopback, 5004);
15+
listener.Start();
16+
using var server = await listener.AcceptTcpClientAsync();
17+
listener.Stop();
18+
19+
await Server(server.GetStream(), serverCertificate);
20+
}
21+
22+
async Task RunClient()
23+
{
24+
using var client = new TcpClient();
25+
26+
await client.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 5004));
27+
28+
await Client(client.GetStream(), "testserver.contoso.com");
29+
}
30+
31+
//<snippet>
32+
async Task Server(NetworkStream stream, X509Certificate2 serverCertificate)
33+
{
34+
using var server = new SslStream(stream);
35+
36+
await server.AuthenticateAsServerAsync(new SslServerAuthenticationOptions
37+
{
38+
ServerCertificate = serverCertificate,
39+
ApplicationProtocols = new()
40+
{
41+
new("protocol1"),
42+
new("protocol2"),
43+
}
44+
});
45+
46+
string protocol = Encoding.ASCII.GetString(server.NegotiatedApplicationProtocol.Protocol.Span);
47+
System.Console.WriteLine($"Server - negotiated protocol: {protocol}");
48+
}
49+
50+
async Task Client(NetworkStream stream, string hostName)
51+
{
52+
using var client = new SslStream(stream);
53+
54+
await client.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
55+
{
56+
// the host name must match the name on the certificate used on the server side
57+
TargetHost = hostName,
58+
ApplicationProtocols = new()
59+
{
60+
new("protocol2"),
61+
new("protocol3")
62+
}
63+
});
64+
65+
string protocol = Encoding.ASCII.GetString(client.NegotiatedApplicationProtocol.Protocol.Span);
66+
System.Console.WriteLine($"Client - negotiated protocol: {protocol}");
67+
}
68+
69+
// possible output:
70+
// Server - negotiated protocol: protocol2
71+
// Client - negotiated protocol: protocol2
72+
//</snippet>
73+
74+
await Task.WhenAll(RunClient(), RunServer());
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFrameworks>net6.0</TargetFrameworks>
6+
</PropertyGroup>
7+
8+
</Project>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
Imports System.Net
2+
Imports System.Net.Security
3+
Imports System.Net.Sockets
4+
Imports System.Security.Cryptography.X509Certificates
5+
Imports System.Text
6+
7+
Module MainModule
8+
Async Function RunServer() As Task
9+
Using serverCertificate As X509Certificate2 = New X509Certificate2("contoso.com.pfx", "testcertificate")
10+
Dim listener as New TcpListener(IPAddress.Loopback, 5004)
11+
listener.Start()
12+
Using tcpServer As TcpClient = Await listener.AcceptTcpClientAsync()
13+
listener.Stop()
14+
Await Server(tcpServer.GetStream(), serverCertificate)
15+
End Using
16+
End Using
17+
End Function
18+
19+
Async Function RunClient() As Task
20+
Using tcpClient as TcpClient = New TcpClient()
21+
Await tcpClient.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 5004))
22+
Await Client(tcpClient.GetStream(), "testserver.contoso.com")
23+
End Using
24+
End Function
25+
26+
'<snippet>
27+
Async Function Server(stream As NetworkStream, serverCertificate As X509Certificate2) As Task
28+
Using serverStream As SslStream = new SslStream(stream)
29+
Dim options as New SslServerAuthenticationOptions() With
30+
{
31+
.ServerCertificate = serverCertificate,
32+
.ApplicationProtocols = New List(Of SslApplicationProtocol) From
33+
{
34+
New SslApplicationProtocol("protocol1"),
35+
New SslApplicationProtocol("protocol2")
36+
}
37+
}
38+
Await serverStream.AuthenticateAsServerAsync(options)
39+
40+
Dim protocol As String = Encoding.ASCII.GetString(
41+
serverStream.NegotiatedApplicationProtocol.Protocol.Span)
42+
System.Console.WriteLine($"Server - negotiated protocol: {protocol}")
43+
End Using
44+
End Function
45+
46+
Async Function Client(stream As NetworkStream, hostName As String ) As Task
47+
Using clientStream As SslStream = new SslStream(stream)
48+
Dim options as New SslClientAuthenticationOptions() With
49+
{
50+
.TargetHost = hostName,
51+
.ApplicationProtocols = New List(Of SslApplicationProtocol) From
52+
{
53+
New SslApplicationProtocol("protocol2"),
54+
New SslApplicationProtocol("protocol3")
55+
}
56+
}
57+
Await clientStream.AuthenticateAsClientAsync(options)
58+
59+
Dim protocol As String = Encoding.ASCII.GetString(
60+
clientStream.NegotiatedApplicationProtocol.Protocol.Span)
61+
System.Console.WriteLine($"Client - negotiated protocol: {protocol}")
62+
End Using
63+
End Function
64+
65+
' possible output:
66+
' Server - negotiated protocol: protocol2
67+
' Client - negotiated protocol: protocol2
68+
'</snippet>
69+
70+
Sub Main()
71+
Task.WhenAll(RunClient(), RunServer()).GetAwaiter().GetResult()
72+
End Sub
73+
End Module

xml/System.Net.Security/SslApplicationProtocol.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ This type contains static fields with predefined <xref:System.Net.Security.SslAp
4848
During the handshake, the client sends a list of available ALPN protocols and the server chooses the best match from that list.
4949
5050
For a complete list of supported protocols, see [TLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids).
51+
52+
## Examples
53+
54+
The following code example demonstrates negotiation of the application-level protocol on <xref:System.Net.Security.SslStream>. The server advertises support for `protocol1` and `protocol2`. The client advertises support for `protocol2` and `protocol3`. The commonly supported protocol (`protocol2`) gets negotiated during the handshake.
55+
56+
:::code language="csharp" source="~/snippets/csharp/System.Net.Security/ALPN/alpn.cs" id="snippet":::
57+
:::code language="vb" source="~/snippets/visualbasic/System.Net.Security/ALPN/alpn.vb" id="snippet":::
5158
5259
]]></format>
5360
</remarks>

0 commit comments

Comments
 (0)