1919import static com .linecorp .armeria .common .SessionProtocol .httpAndHttpsValues ;
2020
2121import java .lang .reflect .Array ;
22- import java .net .InetSocketAddress ;
2322import java .net .SocketAddress ;
23+ import java .util .Objects ;
2424import java .util .Set ;
2525
2626import com .linecorp .armeria .common .SerializationFormat ;
2727import com .linecorp .armeria .common .SessionProtocol ;
2828import com .linecorp .armeria .common .annotation .Nullable ;
2929import com .linecorp .armeria .internal .common .SslContextFactory ;
30- import com .linecorp .armeria .internal .common .SslContextFactory .SslContextMode ;
3130
3231import io .netty .bootstrap .Bootstrap ;
3332import io .netty .channel .Channel ;
3938final class Bootstraps {
4039
4140 private final EventLoop eventLoop ;
42- private final SslContext sslCtxHttp1Only ;
43- private final SslContext sslCtxHttp1Or2 ;
44- @ Nullable
4541 private final SslContextFactory sslContextFactory ;
4642
4743 private final HttpClientFactory clientFactory ;
4844 private final Bootstrap inetBaseBootstrap ;
45+ private final DefaultSslContexts defaultSslContexts ;
4946 @ Nullable
5047 private final Bootstrap unixBaseBootstrap ;
5148 private final Bootstrap [][] inetBootstraps ;
5249 private final Bootstrap @ Nullable [][] unixBootstraps ;
5350
5451 Bootstraps (HttpClientFactory clientFactory , EventLoop eventLoop ,
55- SslContext sslCtxHttp1Or2 , SslContext sslCtxHttp1Only ,
56- @ Nullable SslContextFactory sslContextFactory ) {
52+ SslContextFactory sslContextFactory , DefaultSslContexts defaultSslContexts ) {
5753 this .eventLoop = eventLoop ;
58- this .sslCtxHttp1Or2 = sslCtxHttp1Or2 ;
59- this .sslCtxHttp1Only = sslCtxHttp1Only ;
6054 this .sslContextFactory = sslContextFactory ;
6155 this .clientFactory = clientFactory ;
6256
6357 inetBaseBootstrap = clientFactory .newInetBootstrap ();
58+ this .defaultSslContexts = defaultSslContexts ;
6459 inetBaseBootstrap .group (eventLoop );
6560 inetBootstraps = staticBootstrapMap (inetBaseBootstrap );
6661
@@ -80,20 +75,13 @@ private Bootstrap[][] staticBootstrapMap(Bootstrap baseBootstrap) {
8075 // Attempting to access the array with an unallowed protocol will trigger NPE,
8176 // which will help us find a bug.
8277 for (SessionProtocol p : sessionProtocols ) {
83- final SslContext sslCtx = determineSslContext ( p ) ;
78+ final SslContext sslCtx = p . isTls () ? defaultSslContexts . getSslContext ( p ) : null ;
8479 createAndSetBootstrap (baseBootstrap , maps , p , sslCtx , true );
8580 createAndSetBootstrap (baseBootstrap , maps , p , sslCtx , false );
8681 }
8782 return maps ;
8883 }
8984
90- /**
91- * Determine {@link SslContext} by the specified {@link SessionProtocol}.
92- */
93- SslContext determineSslContext (SessionProtocol desiredProtocol ) {
94- return desiredProtocol .isExplicitHttp1 () ? sslCtxHttp1Only : sslCtxHttp1Or2 ;
95- }
96-
9785 private Bootstrap select (boolean isDomainSocket , SessionProtocol desiredProtocol ,
9886 SerializationFormat serializationFormat ) {
9987 final Bootstrap [][] bootstraps = isDomainSocket ? unixBootstraps : inetBootstraps ;
@@ -102,7 +90,7 @@ private Bootstrap select(boolean isDomainSocket, SessionProtocol desiredProtocol
10290 }
10391
10492 private void createAndSetBootstrap (Bootstrap baseBootstrap , Bootstrap [][] maps ,
105- SessionProtocol desiredProtocol , SslContext sslContext ,
93+ SessionProtocol desiredProtocol , @ Nullable SslContext sslContext ,
10694 boolean webSocket ) {
10795 maps [desiredProtocol .ordinal ()][toIndex (webSocket )] = newBootstrap (baseBootstrap , desiredProtocol ,
10896 sslContext , webSocket , false );
@@ -121,7 +109,7 @@ private static int toIndex(SerializationFormat serializationFormat) {
121109 * {@link SessionProtocol} and {@link SerializationFormat}.
122110 */
123111 Bootstrap getOrCreate (SocketAddress remoteAddress , SessionProtocol desiredProtocol ,
124- SerializationFormat serializationFormat ) {
112+ SerializationFormat serializationFormat , ClientTlsSpec tlsSpec ) {
125113 if (!httpAndHttpsValues ().contains (desiredProtocol )) {
126114 throw new IllegalArgumentException ("Unsupported session protocol: " + desiredProtocol );
127115 }
@@ -132,71 +120,50 @@ Bootstrap getOrCreate(SocketAddress remoteAddress, SessionProtocol desiredProtoc
132120 eventLoop .getClass ().getName ());
133121 }
134122
135- if (sslContextFactory == null || !desiredProtocol .isTls ()) {
123+ if (!desiredProtocol .isTls ()) {
124+ return select (isDomainSocket , desiredProtocol , serializationFormat );
125+ }
126+ final ClientTlsSpec defaultTlsSpec = defaultSslContexts .getClientTlsSpec (desiredProtocol );
127+ if (Objects .equals (defaultTlsSpec , tlsSpec )) {
136128 return select (isDomainSocket , desiredProtocol , serializationFormat );
137129 }
138130
139131 final Bootstrap baseBootstrap = isDomainSocket ? unixBaseBootstrap : inetBaseBootstrap ;
140132 assert baseBootstrap != null ;
141- return newBootstrap (baseBootstrap , remoteAddress , desiredProtocol , serializationFormat );
133+ return newBootstrap (baseBootstrap , desiredProtocol , serializationFormat , tlsSpec );
142134 }
143135
144- private Bootstrap newBootstrap (Bootstrap baseBootstrap , SocketAddress remoteAddress ,
136+ private Bootstrap newBootstrap (Bootstrap baseBootstrap ,
145137 SessionProtocol desiredProtocol ,
146- SerializationFormat serializationFormat ) {
138+ SerializationFormat serializationFormat , ClientTlsSpec tlsSpec ) {
147139 final boolean webSocket = serializationFormat == SerializationFormat .WS ;
148- final SslContext sslContext = newSslContext ( remoteAddress , desiredProtocol );
140+ final SslContext sslContext = sslContextFactory . getOrCreate ( tlsSpec );
149141 return newBootstrap (baseBootstrap , desiredProtocol , sslContext , webSocket , true );
150142 }
151143
152144 private Bootstrap newBootstrap (Bootstrap baseBootstrap , SessionProtocol desiredProtocol ,
153- SslContext sslContext , boolean webSocket , boolean closeSslContext ) {
145+ @ Nullable SslContext sslContext , boolean webSocket ,
146+ boolean closeSslContext ) {
154147 final Bootstrap bootstrap = baseBootstrap .clone ();
155148 bootstrap .handler (clientChannelInitializer (desiredProtocol , sslContext , webSocket , closeSslContext ));
156149 return bootstrap ;
157150 }
158151
159- SslContext getOrCreateSslContext (SocketAddress remoteAddress , SessionProtocol desiredProtocol ) {
160- if (sslContextFactory == null ) {
161- return determineSslContext (desiredProtocol );
162- } else {
163- return newSslContext (remoteAddress , desiredProtocol );
164- }
152+ SslContext getOrCreateSslContext (ClientTlsSpec tlsSpec ) {
153+ return sslContextFactory .getOrCreate (tlsSpec );
165154 }
166155
167- private SslContext newSslContext (SocketAddress remoteAddress , SessionProtocol desiredProtocol ) {
168- final String hostname ;
169- if (remoteAddress instanceof InetSocketAddress ) {
170- hostname = ((InetSocketAddress ) remoteAddress ).getHostString ();
171- } else {
172- assert remoteAddress instanceof DomainSocketAddress ;
173- hostname = "unix:" + ((DomainSocketAddress ) remoteAddress ).path ();
174- }
175-
176- final SslContextMode sslContextMode =
177- desiredProtocol .isExplicitHttp1 () ? SslContextFactory .SslContextMode .CLIENT_HTTP1_ONLY
178- : SslContextFactory .SslContextMode .CLIENT ;
179- assert sslContextFactory != null ;
180- return sslContextFactory .getOrCreate (sslContextMode , hostname );
181- }
182-
183- boolean shouldReleaseSslContext (SslContext sslContext ) {
184- return sslContext != sslCtxHttp1Only && sslContext != sslCtxHttp1Or2 ;
185- }
186-
187- void releaseSslContext (SslContext sslContext ) {
188- if (sslContextFactory != null ) {
189- sslContextFactory .release (sslContext );
190- }
156+ void release (SslContext sslContext ) {
157+ sslContextFactory .release (sslContext );
191158 }
192159
193- private ChannelInitializer <Channel > clientChannelInitializer (SessionProtocol p , SslContext sslCtx ,
160+ private ChannelInitializer <Channel > clientChannelInitializer (SessionProtocol p , @ Nullable SslContext sslCtx ,
194161 boolean webSocket , boolean closeSslContext ) {
195162 return new ChannelInitializer <Channel >() {
196163 @ Override
197164 protected void initChannel (Channel ch ) throws Exception {
198- if (closeSslContext ) {
199- ch .closeFuture ().addListener (unused -> releaseSslContext (sslCtx ));
165+ if (closeSslContext && sslCtx != null ) {
166+ ch .closeFuture ().addListener (unused -> release (sslCtx ));
200167 }
201168 ch .pipeline ().addLast (new HttpClientPipelineConfigurator (
202169 clientFactory , webSocket , p , sslCtx ));
0 commit comments