/** * Create a new client mode SSL engine, configured from an option map. * * @param sslContext the SSL context * @param optionMap the SSL options * @param peerAddress the peer address of the connection * @return the configured SSL engine */ public static SSLEngine createSSLEngine( SSLContext sslContext, OptionMap optionMap, InetSocketAddress peerAddress) { final SSLEngine engine = sslContext.createSSLEngine( optionMap.get(Options.SSL_PEER_HOST_NAME, getHostNameNoResolve(peerAddress)), optionMap.get(Options.SSL_PEER_PORT, peerAddress.getPort())); engine.setUseClientMode(true); engine.setEnableSessionCreation(optionMap.get(Options.SSL_ENABLE_SESSION_CREATION, true)); final Sequence<String> cipherSuites = optionMap.get(Options.SSL_ENABLED_CIPHER_SUITES); if (cipherSuites != null) { final Set<String> supported = new HashSet<String>(Arrays.asList(engine.getSupportedCipherSuites())); final List<String> finalList = new ArrayList<String>(); for (String name : cipherSuites) { if (supported.contains(name)) { finalList.add(name); } } engine.setEnabledCipherSuites(finalList.toArray(new String[finalList.size()])); } final Sequence<String> protocols = optionMap.get(Options.SSL_ENABLED_PROTOCOLS); if (protocols != null) { final Set<String> supported = new HashSet<String>(Arrays.asList(engine.getSupportedProtocols())); final List<String> finalList = new ArrayList<String>(); for (String name : protocols) { if (supported.contains(name)) { finalList.add(name); } } engine.setEnabledProtocols(finalList.toArray(new String[finalList.size()])); } return engine; }
ClientConnectionOpenListener( final RemoteConnection connection, final CallbackHandler callbackHandler, final AccessControlContext accessControlContext, final OptionMap optionMap) { this.connection = connection; this.callbackHandler = callbackHandler; this.accessControlContext = accessControlContext; this.optionMap = optionMap; final Sequence<String> allowedMechs = optionMap.get(Options.SASL_MECHANISMS); final Sequence<String> disallowedMechs = optionMap.get(Options.SASL_DISALLOWED_MECHANISMS); this.allowedMechs = allowedMechs == null ? null : new HashSet<String>(allowedMechs); this.disallowedMechs = disallowedMechs == null ? Collections.<String>emptySet() : new HashSet<String>(disallowedMechs); }
@Override public void handleEvent(StreamConnection channel) { // set read and write timeouts try { Integer readTimeout = channel.getOption(Options.READ_TIMEOUT); Integer idleTimeout = undertowOptions.get(UndertowOptions.IDLE_TIMEOUT); if ((readTimeout == null || readTimeout <= 0) && idleTimeout != null) { readTimeout = idleTimeout; } else if (readTimeout != null && idleTimeout != null && idleTimeout > 0) { readTimeout = Math.min(readTimeout, idleTimeout); } if (readTimeout != null && readTimeout > 0) { channel .getSourceChannel() .setConduit( new ReadTimeoutStreamSourceConduit( channel.getSourceChannel().getConduit(), channel, this)); } Integer writeTimeout = channel.getOption(Options.WRITE_TIMEOUT); if ((writeTimeout == null || writeTimeout <= 0) && idleTimeout != null) { writeTimeout = idleTimeout; } else if (writeTimeout != null && idleTimeout != null && idleTimeout > 0) { writeTimeout = Math.min(writeTimeout, idleTimeout); } if (writeTimeout != null && writeTimeout > 0) { channel .getSinkChannel() .setConduit( new WriteTimeoutStreamSinkConduit( channel.getSinkChannel().getConduit(), channel, this)); } } catch (IOException e) { IoUtils.safeClose(channel); UndertowLogger.REQUEST_IO_LOGGER.ioException(e); } final PortForwardServerConnection connection = new PortForwardServerConnection(channel, bufferPool, undertowOptions, bufferSize); connection .getWorker() .execute( new Runnable() { @Override public void run() { try { connection.startForwarding( masterPortForwardConnection, urlPath, targetPort, requestId.getAndIncrement()); } catch (IOException e) { } finally { IoUtils.safeClose(connection); } } }); }
ClientConnectionOpenListener( final URI uri, final RemoteConnection connection, final ConnectionProviderContext connectionProviderContext, final AuthenticationContext authenticationContext, final SaslClientFactory saslClientFactory, final OptionMap optionMap) { this.uri = uri; this.connection = connection; this.connectionProviderContext = connectionProviderContext; this.authenticationContext = authenticationContext; this.saslClientFactory = saslClientFactory; this.optionMap = optionMap; final Sequence<String> allowedMechs = optionMap.get(Options.SASL_MECHANISMS); final Sequence<String> disallowedMechs = optionMap.get(Options.SASL_DISALLOWED_MECHANISMS); this.allowedMechs = allowedMechs == null ? null : new HashSet<String>(allowedMechs); this.disallowedMechs = disallowedMechs == null ? Collections.<String>emptySet() : new HashSet<String>(disallowedMechs); }
/** * Create a new SSL context, configured from an option map and the given parameters. * * @param keyManagers the key managers to use, or {@code null} to configure from the option map * @param trustManagers the trust managers to use, or {@code null} to configure from the option * map * @param secureRandom the secure RNG to use, or {@code null} to choose a system default * @param optionMap the SSL context options * @return a new context * @throws NoSuchProviderException if there is no matching provider * @throws NoSuchAlgorithmException if there is no matching algorithm * @throws KeyManagementException if the context initialization fails */ public static SSLContext createSSLContext( KeyManager[] keyManagers, TrustManager[] trustManagers, SecureRandom secureRandom, OptionMap optionMap) throws NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException { final String provider = optionMap.get(Options.SSL_PROVIDER); final String protocol = optionMap.get(Options.SSL_PROTOCOL); final SSLContext sslContext; if (protocol == null) { // Default context is initialized automatically return SSLContext.getDefault(); } else if (provider == null) { sslContext = SSLContext.getInstance(protocol); } else { sslContext = SSLContext.getInstance(protocol, provider); } if (keyManagers == null) { final Sequence<Class<? extends KeyManager>> keyManagerClasses = optionMap.get(Options.SSL_JSSE_KEY_MANAGER_CLASSES); if (keyManagerClasses != null) { final int size = keyManagerClasses.size(); keyManagers = new KeyManager[size]; for (int i = 0; i < size; i++) { keyManagers[i] = instantiate(keyManagerClasses.get(i)); } } } if (trustManagers == null) { final Sequence<Class<? extends TrustManager>> trustManagerClasses = optionMap.get(Options.SSL_JSSE_TRUST_MANAGER_CLASSES); if (trustManagerClasses != null) { final int size = trustManagerClasses.size(); trustManagers = new TrustManager[size]; for (int i = 0; i < size; i++) { trustManagers[i] = instantiate(trustManagerClasses.get(i)); } } } sslContext.init(keyManagers, trustManagers, secureRandom); sslContext .getClientSessionContext() .setSessionCacheSize(optionMap.get(Options.SSL_CLIENT_SESSION_CACHE_SIZE, 0)); sslContext .getClientSessionContext() .setSessionTimeout(optionMap.get(Options.SSL_CLIENT_SESSION_TIMEOUT, 0)); sslContext .getServerSessionContext() .setSessionCacheSize(optionMap.get(Options.SSL_SERVER_SESSION_CACHE_SIZE, 0)); sslContext .getServerSessionContext() .setSessionTimeout(optionMap.get(Options.SSL_SERVER_SESSION_TIMEOUT, 0)); return sslContext; }
void sendCapRequest(final String remoteServerName) { client.trace("Client sending capabilities request"); // Prepare the request message body final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate(); boolean ok = false; try { final ByteBuffer sendBuffer = pooledSendBuffer.getResource(); sendBuffer.put(Protocol.CAPABILITIES); ProtocolUtils.writeByte(sendBuffer, Protocol.CAP_VERSION, Protocol.VERSION); final String localEndpointName = connectionProviderContext.getEndpoint().getName(); if (localEndpointName != null) { ProtocolUtils.writeString(sendBuffer, Protocol.CAP_ENDPOINT_NAME, localEndpointName); } ProtocolUtils.writeEmpty(sendBuffer, Protocol.CAP_MESSAGE_CLOSE); ProtocolUtils.writeString( sendBuffer, Protocol.CAP_VERSION_STRING, Version.getVersionString()); ProtocolUtils.writeInt( sendBuffer, Protocol.CAP_CHANNELS_IN, optionMap.get( RemotingOptions.MAX_INBOUND_CHANNELS, RemotingOptions.DEFAULT_MAX_INBOUND_CHANNELS)); ProtocolUtils.writeInt( sendBuffer, Protocol.CAP_CHANNELS_OUT, optionMap.get( RemotingOptions.MAX_OUTBOUND_CHANNELS, RemotingOptions.DEFAULT_MAX_OUTBOUND_CHANNELS)); sendBuffer.flip(); connection.setReadListener(new Capabilities(remoteServerName, uri), true); connection.send(pooledSendBuffer); ok = true; // all set return; } finally { if (!ok) { pooledSendBuffer.free(); } } }
public void handleEvent(final ConnectedMessageChannel channel) { final Pooled<ByteBuffer> pooledReceiveBuffer = connection.allocate(); try { final ByteBuffer receiveBuffer = pooledReceiveBuffer.getResource(); int res = 0; try { res = channel.receive(receiveBuffer); } catch (IOException e) { connection.handleException(e); return; } if (res == -1) { connection.handleException(client.abruptClose(connection)); return; } if (res == 0) { return; } receiveBuffer.flip(); boolean starttls = false; final Set<String> saslMechs = new LinkedHashSet<String>(); final byte msgType = receiveBuffer.get(); switch (msgType) { case Protocol.CONNECTION_ALIVE: { client.trace("Client received connection alive"); return; } case Protocol.CONNECTION_CLOSE: { client.trace("Client received connection close request"); connection.handleIncomingCloseRequest(); return; } case Protocol.CAPABILITIES: { client.trace("Client received capabilities response"); while (receiveBuffer.hasRemaining()) { final byte type = receiveBuffer.get(); final int len = receiveBuffer.get() & 0xff; final ByteBuffer data = Buffers.slice(receiveBuffer, len); switch (type) { case Protocol.CAP_VERSION: { final byte version = data.get(); client.tracef( "Client received capability: version %d", Integer.valueOf(version & 0xff)); // We only support version zero, so knowing the other side's version is not // useful presently break; } case Protocol.CAP_SASL_MECH: { final String mechName = Buffers.getModifiedUtf8(data); client.tracef("Client received capability: SASL mechanism %s", mechName); if (!failedMechs.contains(mechName) && !disallowedMechs.contains(mechName) && (allowedMechs == null || allowedMechs.contains(mechName))) { client.tracef("SASL mechanism %s added to allowed set", mechName); saslMechs.add(mechName); } break; } case Protocol.CAP_STARTTLS: { client.trace("Client received capability: STARTTLS"); starttls = true; break; } default: { client.tracef( "Client received unknown capability %02x", Integer.valueOf(type & 0xff)); // unknown, skip it for forward compatibility. break; } } } if (starttls) { // only initiate starttls if not forbidden by config if (optionMap.get(Options.SSL_STARTTLS, true)) { // Prepare the request message body final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate(); final ByteBuffer sendBuffer = pooledSendBuffer.getResource(); sendBuffer.put(Protocol.STARTTLS); sendBuffer.flip(); connection.setReadListener(new StartTls(serverName)); connection.send(pooledSendBuffer); // all set return; } } if (saslMechs.isEmpty()) { connection.handleException( new SaslException("No more authentication mechanisms to try")); return; } // OK now send our authentication request final OptionMap optionMap = connection.getOptionMap(); final String userName = optionMap.get(RemotingOptions.AUTHORIZE_ID); final Map<String, ?> propertyMap = SaslUtils.createPropertyMap( optionMap, Channels.getOption(channel, Options.SECURE, false)); final SaslClient saslClient; try { saslClient = AccessController.doPrivileged( new PrivilegedExceptionAction<SaslClient>() { public SaslClient run() throws SaslException { return Sasl.createSaslClient( saslMechs.toArray(new String[saslMechs.size()]), userName, "remote", serverName, propertyMap, callbackHandler); } }, accessControlContext); } catch (PrivilegedActionException e) { final SaslException se = (SaslException) e.getCause(); connection.handleException(se); return; } final String mechanismName = saslClient.getMechanismName(); client.tracef("Client initiating authentication using mechanism %s", mechanismName); // Prepare the request message body final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate(); final ByteBuffer sendBuffer = pooledSendBuffer.getResource(); sendBuffer.put(Protocol.AUTH_REQUEST); Buffers.putModifiedUtf8(sendBuffer, mechanismName); sendBuffer.flip(); connection.send(pooledSendBuffer); connection.setReadListener(new Authentication(saslClient, serverName)); return; } default: { client.unknownProtocolId(msgType); connection.handleException(client.invalidMessage(connection)); return; } } } catch (BufferUnderflowException e) { connection.handleException(client.invalidMessage(connection)); return; } catch (BufferOverflowException e) { connection.handleException(client.invalidMessage(connection)); return; } finally { pooledReceiveBuffer.free(); } }
public void handleEvent(final ConnectedMessageChannel channel) { int res; SaslWrapper saslWrapper = connection.getSaslWrapper(); try { Pooled<ByteBuffer> pooled = connection.allocate(); ByteBuffer buffer = pooled.getResource(); try { for (; ; ) try { res = channel.receive(buffer); if (res == -1) { log.trace("Received connection end-of-stream"); try { channel.shutdownReads(); } finally { handler.handleConnectionClose(); } return; } else if (res == 0) { log.trace("No message ready; returning"); return; } buffer.flip(); if (saslWrapper != null) { final ByteBuffer source = buffer.duplicate(); buffer.clear(); saslWrapper.unwrap(buffer, source); buffer.flip(); } final byte protoId = buffer.get(); try { switch (protoId) { case Protocol.CONNECTION_ALIVE: { log.trace("Received connection alive"); connection.sendAliveResponse(); return; } case Protocol.CONNECTION_ALIVE_ACK: { log.trace("Received connection alive ack"); return; } case Protocol.CONNECTION_CLOSE: { log.trace("Received connection close request"); handler.receiveCloseRequest(); return; } case Protocol.CHANNEL_OPEN_REQUEST: { log.trace("Received channel open request"); int channelId = buffer.getInt() ^ 0x80000000; int inboundWindow = Integer.MAX_VALUE; int inboundMessages = 0xffff; int outboundWindow = Integer.MAX_VALUE; int outboundMessages = 0xffff; long inboundMessageSize = Long.MAX_VALUE; long outboundMessageSize = Long.MAX_VALUE; // parse out request int b; String serviceType = null; OUT: for (; ; ) { b = buffer.get() & 0xff; switch (b) { case Protocol.O_END: break OUT; case Protocol.O_SERVICE_NAME: { serviceType = ProtocolUtils.readString(buffer); break; } case Protocol.O_MAX_INBOUND_MSG_WINDOW_SIZE: { outboundWindow = Math.min(outboundWindow, ProtocolUtils.readInt(buffer)); break; } case Protocol.O_MAX_INBOUND_MSG_COUNT: { outboundMessages = Math.min(outboundMessages, ProtocolUtils.readUnsignedShort(buffer)); break; } case Protocol.O_MAX_OUTBOUND_MSG_WINDOW_SIZE: { inboundWindow = Math.min(inboundWindow, ProtocolUtils.readInt(buffer)); break; } case Protocol.O_MAX_OUTBOUND_MSG_COUNT: { inboundMessages = Math.min(inboundMessages, ProtocolUtils.readUnsignedShort(buffer)); break; } case Protocol.O_MAX_INBOUND_MSG_SIZE: { outboundMessageSize = Math.min(outboundMessageSize, ProtocolUtils.readLong(buffer)); break; } case Protocol.O_MAX_OUTBOUND_MSG_SIZE: { inboundMessageSize = Math.min(inboundMessageSize, ProtocolUtils.readLong(buffer)); break; } default: { Buffers.skip(buffer, buffer.get() & 0xff); break; } } } if ((channelId & 0x80000000) != 0) { // invalid channel ID, original should have had MSB=1 and thus the complement // should be MSB=0 refuseService(channelId, "Invalid channel ID"); break; } if (serviceType == null) { // invalid service reply refuseService(channelId, "Missing service name"); break; } final RegisteredService registeredService = handler.getConnectionContext().getRegisteredService(serviceType); if (registeredService == null) { refuseService(channelId, "Unknown service name"); break; } final OptionMap serviceOptionMap = registeredService.getOptionMap(); outboundWindow = Math.min( outboundWindow, serviceOptionMap.get( RemotingOptions.TRANSMIT_WINDOW_SIZE, Protocol.DEFAULT_WINDOW_SIZE)); outboundMessages = Math.min( outboundMessages, serviceOptionMap.get( RemotingOptions.MAX_OUTBOUND_MESSAGES, Protocol.DEFAULT_MESSAGE_COUNT)); inboundWindow = Math.min( inboundWindow, serviceOptionMap.get( RemotingOptions.RECEIVE_WINDOW_SIZE, Protocol.DEFAULT_WINDOW_SIZE)); inboundMessages = Math.min( inboundMessages, serviceOptionMap.get( RemotingOptions.MAX_INBOUND_MESSAGES, Protocol.DEFAULT_MESSAGE_COUNT)); outboundMessageSize = Math.min( outboundMessageSize, serviceOptionMap.get( RemotingOptions.MAX_OUTBOUND_MESSAGE_SIZE, Long.MAX_VALUE)); inboundMessageSize = Math.min( inboundMessageSize, serviceOptionMap.get( RemotingOptions.MAX_INBOUND_MESSAGE_SIZE, Long.MAX_VALUE)); final OpenListener openListener = registeredService.getOpenListener(); if (!handler.handleInboundChannelOpen()) { // refuse refuseService(channelId, "Channel refused"); break; } boolean ok1 = false; try { // construct the channel RemoteConnectionChannel connectionChannel = new RemoteConnectionChannel( handler, connection, channelId, outboundWindow, inboundWindow, outboundMessages, inboundMessages, outboundMessageSize, inboundMessageSize); RemoteConnectionChannel existing = handler.addChannel(connectionChannel); if (existing != null) { log.tracef("Encountered open request for duplicate %s", existing); // the channel already exists, which means the remote side "forgot" about it // or we somehow missed the close message. // the only safe thing to do is to terminate the existing channel. try { refuseService(channelId, "Duplicate ID"); } finally { existing.handleRemoteClose(); } break; } // construct reply Pooled<ByteBuffer> pooledReply = connection.allocate(); boolean ok2 = false; try { ByteBuffer replyBuffer = pooledReply.getResource(); replyBuffer.clear(); replyBuffer.put(Protocol.CHANNEL_OPEN_ACK); replyBuffer.putInt(channelId); ProtocolUtils.writeInt( replyBuffer, Protocol.O_MAX_INBOUND_MSG_WINDOW_SIZE, inboundWindow); ProtocolUtils.writeShort( replyBuffer, Protocol.O_MAX_INBOUND_MSG_COUNT, inboundMessages); if (inboundMessageSize != Long.MAX_VALUE) { ProtocolUtils.writeLong( replyBuffer, Protocol.O_MAX_INBOUND_MSG_SIZE, inboundMessageSize); } ProtocolUtils.writeInt( replyBuffer, Protocol.O_MAX_OUTBOUND_MSG_WINDOW_SIZE, outboundWindow); ProtocolUtils.writeShort( replyBuffer, Protocol.O_MAX_OUTBOUND_MSG_COUNT, outboundMessages); if (outboundMessageSize != Long.MAX_VALUE) { ProtocolUtils.writeLong( replyBuffer, Protocol.O_MAX_OUTBOUND_MSG_SIZE, outboundMessageSize); } replyBuffer.put((byte) 0); replyBuffer.flip(); ok2 = true; // send takes ownership of the buffer connection.send(pooledReply); } finally { if (!ok2) pooledReply.free(); } ok1 = true; // Call the service open listener connection .getExecutor() .execute(SpiUtils.getServiceOpenTask(connectionChannel, openListener)); break; } finally { // the inbound channel wasn't open so don't leak the ref count if (!ok1) handler.handleInboundChannelClosed(); } } case Protocol.MESSAGE_DATA: { log.trace("Received message data"); int channelId = buffer.getInt() ^ 0x80000000; RemoteConnectionChannel connectionChannel = handler.getChannel(channelId); if (connectionChannel == null) { // ignore the data log.tracef("Ignoring message data for expired channel"); break; } connectionChannel.handleMessageData(pooled); // need a new buffer now pooled = connection.allocate(); buffer = pooled.getResource(); break; } case Protocol.MESSAGE_WINDOW_OPEN: { log.trace("Received message window open"); int channelId = buffer.getInt() ^ 0x80000000; RemoteConnectionChannel connectionChannel = handler.getChannel(channelId); if (connectionChannel == null) { // ignore log.tracef("Ignoring window open for expired channel"); break; } connectionChannel.handleWindowOpen(pooled); break; } case Protocol.MESSAGE_CLOSE: { log.trace("Received message async close"); int channelId = buffer.getInt() ^ 0x80000000; RemoteConnectionChannel connectionChannel = handler.getChannel(channelId); if (connectionChannel == null) { break; } connectionChannel.handleAsyncClose(pooled); break; } case Protocol.CHANNEL_CLOSED: { log.trace("Received channel closed"); int channelId = buffer.getInt() ^ 0x80000000; RemoteConnectionChannel connectionChannel = handler.getChannel(channelId); if (connectionChannel == null) { break; } connectionChannel.handleRemoteClose(); break; } case Protocol.CHANNEL_SHUTDOWN_WRITE: { log.trace("Received channel shutdown write"); int channelId = buffer.getInt() ^ 0x80000000; RemoteConnectionChannel connectionChannel = handler.getChannel(channelId); if (connectionChannel == null) { break; } connectionChannel.handleIncomingWriteShutdown(); break; } case Protocol.CHANNEL_OPEN_ACK: { log.trace("Received channel open ack"); int channelId = buffer.getInt() ^ 0x80000000; if ((channelId & 0x80000000) == 0) { // invalid break; } PendingChannel pendingChannel = handler.removePendingChannel(channelId); if (pendingChannel == null) { // invalid break; } int outboundWindow = pendingChannel.getOutboundWindowSize(); int inboundWindow = pendingChannel.getInboundWindowSize(); int outboundMessageCount = pendingChannel.getOutboundMessageCount(); int inboundMessageCount = pendingChannel.getInboundMessageCount(); long outboundMessageSize = pendingChannel.getOutboundMessageSize(); long inboundMessageSize = pendingChannel.getInboundMessageSize(); OUT: for (; ; ) { switch (buffer.get() & 0xff) { case Protocol.O_MAX_INBOUND_MSG_WINDOW_SIZE: { outboundWindow = Math.min(outboundWindow, ProtocolUtils.readInt(buffer)); break; } case Protocol.O_MAX_INBOUND_MSG_COUNT: { outboundMessageCount = Math.min( outboundMessageCount, ProtocolUtils.readUnsignedShort(buffer)); break; } case Protocol.O_MAX_OUTBOUND_MSG_WINDOW_SIZE: { inboundWindow = Math.min(inboundWindow, ProtocolUtils.readInt(buffer)); break; } case Protocol.O_MAX_OUTBOUND_MSG_COUNT: { inboundMessageCount = Math.min( inboundMessageCount, ProtocolUtils.readUnsignedShort(buffer)); break; } case Protocol.O_MAX_INBOUND_MSG_SIZE: { outboundMessageSize = Math.min(outboundMessageSize, ProtocolUtils.readLong(buffer)); break; } case Protocol.O_MAX_OUTBOUND_MSG_SIZE: { inboundMessageSize = Math.min(inboundMessageSize, ProtocolUtils.readLong(buffer)); break; } case Protocol.O_END: { break OUT; } default: { // ignore unknown parameter Buffers.skip(buffer, buffer.get() & 0xff); break; } } } RemoteConnectionChannel newChannel = new RemoteConnectionChannel( handler, connection, channelId, outboundWindow, inboundWindow, outboundMessageCount, inboundMessageCount, outboundMessageSize, inboundMessageSize); handler.putChannel(newChannel); pendingChannel.getResult().setResult(newChannel); break; } case Protocol.SERVICE_ERROR: { log.trace("Received service error"); int channelId = buffer.getInt() ^ 0x80000000; PendingChannel pendingChannel = handler.removePendingChannel(channelId); if (pendingChannel == null) { // invalid break; } String reason = new String(Buffers.take(buffer), Protocol.UTF_8); pendingChannel.getResult().setException(new IOException(reason)); break; } default: { log.unknownProtocolId(protoId); break; } } } catch (BufferUnderflowException e) { log.bufferUnderflow(protoId); } } catch (BufferUnderflowException e) { log.bufferUnderflowRaw(); } finally { buffer.clear(); } } finally { pooled.free(); } } catch (IOException e) { connection.handleException(e); handler.handleConnectionClose(); } }
public synchronized void start() { xnio = Xnio.getInstance(Undertow.class.getClassLoader()); channels = new ArrayList<>(); try { worker = xnio.createWorker( OptionMap.builder() .set(Options.WORKER_IO_THREADS, ioThreads) .set(Options.CONNECTION_HIGH_WATER, 1000000) .set(Options.CONNECTION_LOW_WATER, 1000000) .set(Options.WORKER_TASK_CORE_THREADS, workerThreads) .set(Options.WORKER_TASK_MAX_THREADS, workerThreads) .set(Options.TCP_NODELAY, true) .set(Options.CORK, true) .addAll(workerOptions) .getMap()); OptionMap socketOptions = OptionMap.builder() .set(Options.WORKER_IO_THREADS, ioThreads) .set(Options.TCP_NODELAY, true) .set(Options.REUSE_ADDRESSES, true) .set(Options.BALANCING_TOKENS, 1) .set(Options.BALANCING_CONNECTIONS, 2) .set(Options.BACKLOG, 1000) .addAll(this.socketOptions) .getMap(); Pool<ByteBuffer> buffers = new ByteBufferSlicePool( directBuffers ? BufferAllocator.DIRECT_BYTE_BUFFER_ALLOCATOR : BufferAllocator.BYTE_BUFFER_ALLOCATOR, bufferSize, bufferSize * buffersPerRegion); for (ListenerConfig listener : listeners) { final HttpHandler rootHandler = listener.rootHandler != null ? listener.rootHandler : this.rootHandler; if (listener.type == ListenerType.AJP) { AjpOpenListener openListener = new AjpOpenListener(buffers, serverOptions); openListener.setRootHandler(rootHandler); ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener); AcceptingChannel<? extends StreamConnection> server = worker.createStreamConnectionServer( new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), acceptListener, socketOptions); server.resumeAccepts(); channels.add(server); } else { OptionMap undertowOptions = OptionMap.builder() .set(UndertowOptions.BUFFER_PIPELINED_DATA, true) .addAll(serverOptions) .getMap(); if (listener.type == ListenerType.HTTP) { HttpOpenListener openListener = new HttpOpenListener(buffers, undertowOptions); openListener.setRootHandler(rootHandler); ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener); AcceptingChannel<? extends StreamConnection> server = worker.createStreamConnectionServer( new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), acceptListener, socketOptions); server.resumeAccepts(); channels.add(server); } else if (listener.type == ListenerType.HTTPS) { ChannelListener<StreamConnection> openListener; HttpOpenListener httpOpenListener = new HttpOpenListener(buffers, undertowOptions); httpOpenListener.setRootHandler(rootHandler); boolean spdy = serverOptions.get(UndertowOptions.ENABLE_SPDY, false); boolean http2 = serverOptions.get(UndertowOptions.ENABLE_HTTP2, false); if (spdy || http2) { AlpnOpenListener alpn = new AlpnOpenListener(buffers, undertowOptions, httpOpenListener); if (spdy) { SpdyOpenListener spdyListener = new SpdyOpenListener( buffers, new ByteBufferSlicePool(BufferAllocator.BYTE_BUFFER_ALLOCATOR, 1024, 1024), undertowOptions); spdyListener.setRootHandler(rootHandler); alpn.addProtocol(SpdyOpenListener.SPDY_3_1, spdyListener, 5); } if (http2) { Http2OpenListener http2Listener = new Http2OpenListener(buffers, undertowOptions); http2Listener.setRootHandler(rootHandler); alpn.addProtocol(Http2OpenListener.HTTP2, http2Listener, 10); alpn.addProtocol(Http2OpenListener.HTTP2_14, http2Listener, 7); } openListener = alpn; } else { openListener = httpOpenListener; } ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener); XnioSsl xnioSsl; if (listener.sslContext != null) { xnioSsl = new UndertowXnioSsl( xnio, OptionMap.create(Options.USE_DIRECT_BUFFERS, true), listener.sslContext); } else { xnioSsl = xnio.getSslProvider( listener.keyManagers, listener.trustManagers, OptionMap.create(Options.USE_DIRECT_BUFFERS, true)); } AcceptingChannel<SslConnection> sslServer = xnioSsl.createSslConnectionServer( worker, new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), (ChannelListener) acceptListener, socketOptions); sslServer.resumeAccepts(); channels.add(sslServer); } } } } catch (Exception e) { throw new RuntimeException(e); } }