66
77package modelengine .fit .http .server .netty ;
88
9- import static modelengine .fitframework .inspection .Validation .greaterThan ;
9+ import static modelengine .fitframework .inspection .Validation .greaterThanOrEquals ;
1010import static modelengine .fitframework .inspection .Validation .isTrue ;
1111import static modelengine .fitframework .inspection .Validation .lessThanOrEquals ;
1212import static modelengine .fitframework .inspection .Validation .notNull ;
5252import modelengine .fitframework .value .ValueFetcher ;
5353
5454import java .io .IOException ;
55+ import java .net .InetSocketAddress ;
5556import java .security .GeneralSecurityException ;
5657import java .util .Arrays ;
5758import java .util .Collections ;
@@ -94,8 +95,10 @@ public class NettyHttpClassicServer implements HttpClassicServer {
9495 log .error ("Failed to start netty http server." , exception );
9596 }));
9697 private final ChannelGroup channelGroup = new DefaultChannelGroup (GlobalEventExecutor .INSTANCE );
97- private volatile int httpPort ;
98- private volatile int httpsPort ;
98+ private volatile int httpPort = 0 ;
99+ private volatile int httpsPort = 0 ;
100+ private volatile boolean httpBound = false ;
101+ private volatile boolean httpsBound = false ;
99102 private final boolean isGracefulExit ;
100103 private volatile boolean isStarted = false ;
101104 private final Lock lock = LockUtils .newReentrantLock ();
@@ -131,27 +134,29 @@ public HttpClassicServer bind(int port, boolean isSecure) {
131134 return this ;
132135 }
133136 if (isSecure ) {
134- this .httpsPort = greaterThan (port ,
137+ this .httpsPort = greaterThanOrEquals (port ,
135138 0 ,
136- "The port to bind to netty http server cannot be less than 1 . [port={0}, isSecure={1}]" ,
139+ "The port to bind to netty http server cannot be negative . [port={0}, isSecure={1}]" ,
137140 port ,
138141 true );
139142 this .httpsPort = lessThanOrEquals (port ,
140143 65535 ,
141144 "The port to bind to netty http server cannot be more than 65535. [port={0}, isSecure={1}]" ,
142145 port ,
143146 true );
147+ this .httpsBound = true ;
144148 } else {
145- this .httpPort = greaterThan (port ,
149+ this .httpPort = greaterThanOrEquals (port ,
146150 0 ,
147- "The port to bind to netty http server cannot be less than 1 . [port={0}, isSecure={1}]" ,
151+ "The port to bind to netty http server cannot be negative . [port={0}, isSecure={1}]" ,
148152 port ,
149153 false );
150154 this .httpPort = lessThanOrEquals (port ,
151155 65535 ,
152156 "The port to bind to netty http server cannot be more than 65535. [port={0}, isSecure={1}]" ,
153157 port ,
154158 false );
159+ this .httpBound = true ;
155160 }
156161 return this ;
157162 }
@@ -161,7 +166,7 @@ public void start() {
161166 if (this .isStarted ) {
162167 return ;
163168 }
164- isTrue (this .httpPort > 0 || this .httpsPort > 0 ,
169+ isTrue (this .httpBound || this .httpsBound ,
165170 "At least 1 port should be bound to netty http server. [httpPort={0}, httpsPort={1}]" ,
166171 this .httpPort ,
167172 this .httpsPort );
@@ -177,6 +182,22 @@ public boolean isStarted() {
177182 return this .isStarted ;
178183 }
179184
185+ @ Override
186+ public int getActualHttpPort () {
187+ if (!this .isStarted || !this .httpBound ) {
188+ return 0 ;
189+ }
190+ return Math .max (this .httpPort , 0 );
191+ }
192+
193+ @ Override
194+ public int getActualHttpsPort () {
195+ if (!this .isStarted || !this .httpsBound ) {
196+ return 0 ;
197+ }
198+ return Math .max (this .httpsPort , 0 );
199+ }
200+
180201 @ Override
181202 public void stop () {
182203 if (!this .isStarted ) {
@@ -202,27 +223,32 @@ private void startServer() {
202223 EventLoopGroup workerGroup = this .createWorkerGroup ();
203224 try {
204225 SSLContext sslContext = null ;
205- if (this .httpsPort > 0 && this .httpsConfig .isSslEnabled ()) {
226+ if (this .httpsBound && this . httpsConfig != null && this .httpsConfig .isSslEnabled ()) {
206227 sslContext = this .createSslContext ();
207228 }
208- ChannelHandler channelHandler = new ChannelInitializerHandler (this ,
209- this .getAssemblerConfig (),
210- this .httpsPort ,
211- sslContext ,
212- this .httpsConfig );
229+ ChannelHandler channelHandler =
230+ new ChannelInitializerHandler (this , this .getAssemblerConfig (), sslContext , this .httpsConfig );
213231 ServerBootstrap serverBootstrap = new ServerBootstrap ();
214232 serverBootstrap .group (bossGroup , workerGroup )
215233 .channel (NioServerSocketChannel .class )
216234 .childHandler (channelHandler );
217- this .logServerStarted ();
218- if (this .httpPort > 0 ) {
235+ if (this .httpBound ) {
219236 Channel channel = serverBootstrap .bind (this .httpPort ).sync ().channel ();
220237 this .channelGroup .add (channel );
238+ if (this .httpPort == 0 ) {
239+ this .httpPort = ((InetSocketAddress ) channel .localAddress ()).getPort ();
240+ log .info ("HTTP server bound to auto-assigned port: {}" , this .httpPort );
241+ }
221242 }
222- if (this .httpsPort > 0 ) {
243+ if (this .httpsBound ) {
223244 Channel channel = serverBootstrap .bind (this .httpsPort ).sync ().channel ();
224245 this .channelGroup .add (channel );
246+ if (this .httpsPort == 0 ) {
247+ this .httpsPort = ((InetSocketAddress ) channel .localAddress ()).getPort ();
248+ log .info ("HTTPS server bound to auto-assigned port: {}" , this .httpsPort );
249+ }
225250 }
251+ this .logServerStarted ();
226252 ChannelGroupFuture channelFutures = this .channelGroup .newCloseFuture ();
227253 this .isStarted = true ;
228254 channelFutures .sync ();
@@ -353,17 +379,17 @@ private static class ChannelInitializerHandler extends ChannelInitializer<Socket
353379 "TLS_AES_128_CCM_SHA256" ))
354380 .build ();
355381
356- private final int httpsPort ;
382+ private final NettyHttpClassicServer server ;
357383 private final SSLContext sslContext ;
358384 private final ServerConfig .Secure httpsConfig ;
359385 private final ProtocolUpgrader upgrader ;
360386 private final ProtocolUpgrader secureUpgrader ;
361387 private final HttpClassicRequestAssembler assembler ;
362388 private final HttpClassicRequestAssembler secureAssembler ;
363389
364- ChannelInitializerHandler (HttpClassicServer server , HttpClassicRequestAssembler .Config assemblerConfig ,
365- int httpsPort , SSLContext sslContext , ServerConfig .Secure httpsConfig ) {
366- this .httpsPort = httpsPort ;
390+ ChannelInitializerHandler (NettyHttpClassicServer server , HttpClassicRequestAssembler .Config assemblerConfig ,
391+ SSLContext sslContext , ServerConfig .Secure httpsConfig ) {
392+ this .server = server ;
367393 this .sslContext = sslContext ;
368394 this .httpsConfig = httpsConfig ;
369395 this .upgrader = new ProtocolUpgrader (server ,
@@ -381,7 +407,8 @@ private static class ChannelInitializerHandler extends ChannelInitializer<Socket
381407 @ Override
382408 protected void initChannel (SocketChannel ch ) {
383409 ChannelPipeline pipeline = ch .pipeline ();
384- if (ch .localAddress ().getPort () == this .httpsPort && this .sslContext != null
410+ int httpsPort = this .server .httpsPort ;
411+ if (ch .localAddress ().getPort () == httpsPort && this .sslContext != null && this .httpsConfig != null
385412 && this .httpsConfig .isSslEnabled ()) {
386413 pipeline .addLast (new SslHandler (this .buildSslEngine (this .sslContext , this .httpsConfig )));
387414 pipeline .addLast (new HttpServerCodec ());
0 commit comments