33using System . Net . Security ;
44using System . Security . Authentication ;
55using System . Security . Cryptography . X509Certificates ;
6+ using System . Text ;
67using System . Threading ;
78using System . Threading . Tasks ;
89using Titanium . Web . Proxy . StreamExtended ;
10+ using Titanium . Web . Proxy . StreamExtended . Models ;
911
1012namespace Titanium . Web . Proxy . Extensions
1113{
@@ -31,24 +33,24 @@ internal static class SslExtensions
3133 {
3234 if ( clientHelloInfo . Extensions != null && clientHelloInfo . Extensions . TryGetValue ( "ALPN" , out var alpnExtension ) )
3335 {
34- var alpn = alpnExtension . Data . Split ( ',' ) ;
35- if ( alpn . Length != 0 )
36+ var alpn = alpnExtension . Alpns ;
37+ if ( alpn . Count != 0 )
3638 {
37- var result = new List < SslApplicationProtocol > ( alpn . Length ) ;
38- foreach ( string p in alpn )
39- {
40- string protocol = p . Trim ( ) ;
41- if ( protocol . Equals ( "http/1.1" ) )
42- {
43- result . Add ( SslApplicationProtocol . Http11 ) ;
44- }
45- else if ( protocol . Equals ( "h2" ) )
46- {
47- result . Add ( SslApplicationProtocol . Http2 ) ;
48- }
49- }
50- 51- return result ;
39+ return alpn ;
40+ }
41+ }
42+ 43+ return null ;
44+ }
45+ 46+ internal static List < string > ? GetSslProtocols ( this ClientHelloInfo clientHelloInfo )
47+ {
48+ if ( clientHelloInfo . Extensions != null && clientHelloInfo . Extensions . TryGetValue ( "supported_versions" , out var versions ) )
49+ {
50+ var protocols = versions . Protocols ;
51+ if ( protocols . Count != 0 )
52+ {
53+ return protocols ;
5254 }
5355 }
5456
@@ -80,10 +82,54 @@ internal static Task AuthenticateAsServerAsync(this SslStream sslStream, SslServ
8082#if ! NET6_0_OR_GREATER
8183namespace System . Net . Security
8284{
83- internal enum SslApplicationProtocol
85+ internal struct SslApplicationProtocol
8486 {
85- Http11 ,
86- Http2
87+ public static readonly SslApplicationProtocol Http11 = new SslApplicationProtocol ( SslExtension . Http11Utf8 ) ;
88+ 89+ public static readonly SslApplicationProtocol Http2 = new SslApplicationProtocol ( SslExtension . Http2Utf8 ) ;
90+ 91+ public static readonly SslApplicationProtocol Http3 = new SslApplicationProtocol ( SslExtension . Http3Utf8 ) ;
92+ 93+ private readonly byte [ ] readOnlyProtocol ;
94+ 95+ public ReadOnlyMemory < byte > Protocol => readOnlyProtocol ;
96+ 97+ public SslApplicationProtocol ( byte [ ] protocol )
98+ {
99+ readOnlyProtocol = protocol ;
100+ }
101+ 102+ public bool Equals ( SslApplicationProtocol other ) => Protocol . Span . SequenceEqual ( other . Protocol . Span ) ;
103+ 104+ public override bool Equals ( object ? obj ) => obj is SslApplicationProtocol protocol && Equals ( protocol ) ;
105+ 106+ public override int GetHashCode ( )
107+ {
108+ var arr = Protocol ;
109+ if ( arr . Length == 0 )
110+ {
111+ return 0 ;
112+ }
113+ 114+ int hash = 0 ;
115+ for ( int i = 0 ; i < arr . Length ; i ++ )
116+ {
117+ hash = ( ( hash << 5 ) + hash ) ^ arr . Span [ i ] ;
118+ }
119+ 120+ return hash ;
121+ }
122+ 123+ public override string ToString ( )
124+ {
125+ return Encoding . UTF8 . GetString ( readOnlyProtocol ) ;
126+ }
127+ 128+ public static bool operator == ( SslApplicationProtocol left , SslApplicationProtocol right ) =>
129+ left . Equals ( right ) ;
130+ 131+ public static bool operator != ( SslApplicationProtocol left , SslApplicationProtocol right ) =>
132+ ! ( left == right ) ;
87133 }
88134
89135 [ SuppressMessage ( "StyleCop.CSharp.MaintainabilityRules" , "SA1402:FileMayOnlyContainASingleType" , Justification =
0 commit comments