|
|
@ -18,6 +18,7 @@ package org.springframework.boot.web.embedded.netty;
|
|
|
|
|
|
|
|
|
|
|
|
import java.time.Duration;
|
|
|
|
import java.time.Duration;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import io.netty.channel.unix.Errors.NativeIoException;
|
|
|
|
import org.apache.commons.logging.Log;
|
|
|
|
import org.apache.commons.logging.Log;
|
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
import reactor.netty.ChannelBindException;
|
|
|
|
import reactor.netty.ChannelBindException;
|
|
|
@ -42,6 +43,11 @@ import org.springframework.util.Assert;
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public class NettyWebServer implements WebServer {
|
|
|
|
public class NettyWebServer implements WebServer {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Permission denied error code from {@code errno.h}.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private static final int ERROR_NO_EACCES = -13;
|
|
|
|
|
|
|
|
|
|
|
|
private static final Log logger = LogFactory.getLog(NettyWebServer.class);
|
|
|
|
private static final Log logger = LogFactory.getLog(NettyWebServer.class);
|
|
|
|
|
|
|
|
|
|
|
|
private final HttpServer httpServer;
|
|
|
|
private final HttpServer httpServer;
|
|
|
@ -68,7 +74,7 @@ public class NettyWebServer implements WebServer {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception ex) {
|
|
|
|
catch (Exception ex) {
|
|
|
|
ChannelBindException bindException = findBindException(ex);
|
|
|
|
ChannelBindException bindException = findBindException(ex);
|
|
|
|
if (bindException != null) {
|
|
|
|
if (bindException != null && !isPermissionDenied(bindException.getCause())) {
|
|
|
|
throw new PortInUseException(bindException.localPort(), ex);
|
|
|
|
throw new PortInUseException(bindException.localPort(), ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new WebServerException("Unable to start Netty", ex);
|
|
|
|
throw new WebServerException("Unable to start Netty", ex);
|
|
|
@ -78,6 +84,17 @@ public class NettyWebServer implements WebServer {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean isPermissionDenied(Throwable bindExceptionCause) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
if (bindExceptionCause instanceof NativeIoException) {
|
|
|
|
|
|
|
|
return ((NativeIoException) bindExceptionCause).expectedErr() == ERROR_NO_EACCES;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Throwable ex) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private DisposableServer startHttpServer() {
|
|
|
|
private DisposableServer startHttpServer() {
|
|
|
|
if (this.lifecycleTimeout != null) {
|
|
|
|
if (this.lifecycleTimeout != null) {
|
|
|
|
return this.httpServer.handle(this.handlerAdapter).bindNow(this.lifecycleTimeout);
|
|
|
|
return this.httpServer.handle(this.handlerAdapter).bindNow(this.lifecycleTimeout);
|
|
|
|