1 module hunt.net.secure.conscrypt.ApplicationProtocolSelectorAdapter;
2 
3 // dfmt off
4 version(WITH_HUNT_SECURITY):
5 // dfmt on
6 
7 import hunt.net.secure.conscrypt.ApplicationProtocolSelector;
8 import hunt.net.secure.conscrypt.SSLUtils;
9 
10 import hunt.net.ssl.SSLEngine;
11 
12 
13 import hunt.text.Common;
14 import std.array;
15 
16 
17 /**
18  * An adapter to bridge between the native code and the {@link ApplicationProtocolSelector} API.
19  */
20 final class ApplicationProtocolSelectorAdapter {
21     private enum int NO_PROTOCOL_SELECTED = -1;
22 
23     private SSLEngine engine;
24     // private SSLSocket socket;
25     private ApplicationProtocolSelector selector;
26 
27     this(SSLEngine engine, ApplicationProtocolSelector selector) {
28         this.engine = engine;
29         // this.socket = null;
30         this.selector = selector;
31     }
32 
33     // this(SSLSocket socket, ApplicationProtocolSelector selector) {
34     //     this.engine = null;
35     //     this.socket = socket;
36     //     this.selector = selector;
37     // }
38 
39     /**
40      * Performs the ALPN protocol selection from the given list of length-delimited peer protocols.
41      * @param encodedProtocols the peer protocols in length-delimited form.
42      * @return If successful, returns the offset into the {@code lenghPrefixedList} array of the
43      * selected protocol (i.e. points to the length prefix). Otherwise, returns
44      * {@link #NO_PROTOCOL_SELECTED}.
45      */
46     int selectApplicationProtocol(ubyte[] encodedProtocols) {
47         if (encodedProtocols.length == 0) {
48             return NO_PROTOCOL_SELECTED;
49         }
50 
51         // Decode the protocols.
52         string[] protocols = SSLUtils.decodeProtocols(encodedProtocols);
53 
54         // Select the protocol.
55         string selected;
56 
57         selected = selector.selectApplicationProtocol(engine, protocols);
58         if (selected.empty()) {
59             return NO_PROTOCOL_SELECTED;
60         }
61 
62         int offset = 0;
63         foreach (string protocol ; protocols) {
64             if (selected.equals(protocol)) {
65                 // Found the selected protocol. Return the index position of the beginning of
66                 // the protocol.
67                 return offset;
68             }
69 
70             // Add 1 byte for the length prefix.
71             offset += 1 + cast(int)protocol.length;
72         }
73 
74         return NO_PROTOCOL_SELECTED;
75     }
76 }
77