Skip to content

Commit e7d678c

Browse files
committed
fix issue Dispatcher thread stuck in SSL Handshake, httpserver not anymore responsive robaho#23
1 parent 0043b0a commit e7d678c

File tree

1 file changed

+68
-66
lines changed

1 file changed

+68
-66
lines changed

src/main/java/robaho/net/httpserver/ServerImpl.java

Lines changed: 68 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -342,82 +342,84 @@ public void run() {
342342
while (true) {
343343
try {
344344
Socket s = socket.accept();
345-
if(logger.isLoggable(Level.TRACE)) {
346-
logger.log(Level.TRACE, "accepted connection: " + s.toString());
347-
}
348-
stats.connectionCount.incrementAndGet();
349-
if (MAX_CONNECTIONS > 0 && allConnections.size() >= MAX_CONNECTIONS) {
350-
// we've hit max limit of current open connections, so we go
351-
// ahead and close this connection without processing it
345+
executor.execute(() -> {
352346
try {
353-
stats.maxConnectionsExceededCount.incrementAndGet();
354-
logger.log(Level.WARNING, "closing accepted connection due to too many connections");
355-
s.close();
356-
} catch (IOException ignore) {
347+
acceptConnection(s);
348+
} catch (IOException t) {
349+
logger.log(Level.ERROR, "Dispatcher Exception", t);
357350
}
358-
continue;
359-
}
360-
361-
if (ServerConfig.noDelay()) {
362-
s.setTcpNoDelay(true);
351+
});
352+
} catch (IOException e) {
353+
if (!isFinishing()) {
354+
logger.log(Level.ERROR, "Dispatcher Exception, terminating", e);
363355
}
356+
return;
357+
}
358+
}
359+
}
360+
private void acceptConnection(Socket s) throws IOException {
361+
if(logger.isLoggable(Level.TRACE)) {
362+
logger.log(Level.TRACE, "accepted connection: " + s.toString());
363+
}
364+
stats.connectionCount.incrementAndGet();
365+
if (MAX_CONNECTIONS > 0 && allConnections.size() >= MAX_CONNECTIONS) {
366+
// we've hit max limit of current open connections, so we go
367+
// ahead and close this connection without processing it
368+
try {
369+
stats.maxConnectionsExceededCount.incrementAndGet();
370+
logger.log(Level.WARNING, "closing accepted connection due to too many connections");
371+
s.close();
372+
} catch (IOException ignore) {
373+
}
374+
return;
375+
}
364376

365-
boolean http2 = false;
377+
if (ServerConfig.noDelay()) {
378+
s.setTcpNoDelay(true);
379+
}
366380

367-
if (https) {
368-
// for some reason, creating an SSLServerSocket and setting the default parameters would
369-
// not work, so upgrade to a SSLSocket after connection
370-
SSLSocketFactory ssf = httpsConfig.getSSLContext().getSocketFactory();
371-
SSLSocket sslSocket = (SSLSocket) ssf.createSocket(s, null, false);
372-
SSLConfigurator.configure(sslSocket,httpsConfig);
381+
boolean http2 = false;
373382

374-
sslSocket.setHandshakeApplicationProtocolSelector((_sslSocket, protocols) -> {
375-
if (protocols.contains("h2") && ServerConfig.http2OverSSL()) {
376-
return "h2";
377-
} else {
378-
return "http/1.1";
379-
}
380-
});
381-
// the following forces the SSL handshake to complete in order to determine the negotiated protocol
382-
var session = sslSocket.getSession();
383-
if ("h2".equals(sslSocket.getApplicationProtocol())) {
384-
logger.log(Level.DEBUG, () -> "http2 connection "+sslSocket.toString());
385-
http2 = true;
386-
} else {
387-
logger.log(Level.DEBUG, () -> "http/1.1 connection "+sslSocket.toString());
388-
}
389-
s = sslSocket;
383+
if (https) {
384+
// for some reason, creating an SSLServerSocket and setting the default parameters would
385+
// not work, so upgrade to a SSLSocket after connection
386+
SSLSocketFactory ssf = httpsConfig.getSSLContext().getSocketFactory();
387+
SSLSocket sslSocket = (SSLSocket) ssf.createSocket(s, null, false);
388+
SSLConfigurator.configure(sslSocket,httpsConfig);
389+
390+
sslSocket.setHandshakeApplicationProtocolSelector((_sslSocket, protocols) -> {
391+
if (protocols.contains("h2") && ServerConfig.http2OverSSL()) {
392+
return "h2";
393+
} else {
394+
return "http/1.1";
390395
}
396+
});
397+
// the following forces the SSL handshake to complete in order to determine the negotiated protocol
398+
var session = sslSocket.getSession();
399+
if ("h2".equals(sslSocket.getApplicationProtocol())) {
400+
logger.log(Level.DEBUG, () -> "http2 connection "+sslSocket.toString());
401+
http2 = true;
402+
} else {
403+
logger.log(Level.DEBUG, () -> "http/1.1 connection "+sslSocket.toString());
404+
}
405+
s = sslSocket;
406+
}
391407

392-
HttpConnection c;
393-
try {
394-
c = new HttpConnection(s);
395-
} catch (IOException e) {
396-
logger.log(Level.WARNING, "Failed to create HttpConnection", e);
397-
continue;
398-
}
399-
try {
400-
allConnections.add(c);
401-
402-
if (http2) {
403-
Http2Exchange t = new Http2Exchange(protocol, c);
404-
executor.execute(t);
405-
} else {
406-
Exchange t = new Exchange(protocol, c);
407-
executor.execute(t);
408-
}
408+
HttpConnection c = new HttpConnection(s);
409+
try {
410+
allConnections.add(c);
409411

410-
} catch (Exception e) {
411-
logger.log(Level.TRACE, "Dispatcher Exception", e);
412-
stats.handleExceptionCount.incrementAndGet();
413-
closeConnection(c);
414-
}
415-
} catch (IOException e) {
416-
if (!isFinishing()) {
417-
logger.log(Level.ERROR, "Dispatcher Exception, terminating", e);
418-
}
419-
return;
412+
if (http2) {
413+
Http2Exchange t = new Http2Exchange(protocol, c);
414+
executor.execute(t);
415+
} else {
416+
Exchange t = new Exchange(protocol, c);
417+
executor.execute(t);
420418
}
419+
} catch (Exception e) {
420+
logger.log(Level.TRACE, "Dispatcher Exception", e);
421+
stats.handleExceptionCount.incrementAndGet();
422+
closeConnection(c);
421423
}
422424
}
423425
}

0 commit comments

Comments
 (0)