/**
* Copyright 2012 Ronen Hamias, Anton Kharenko
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package io.scalecube.socketio;
import javax.net.ssl.SSLContext;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.JdkSslContext;
import io.netty.handler.ssl.SslContext;
/**
* Class represents different options of socket.io server
*/
public final class ServerConfiguration {
// Default configuration
public static final ServerConfiguration DEFAULT = builder().build();
// Default settings
public static final int DEFAULT_PORT = 8080;
public static final int DEFAULT_HEARTBEAT_TIMEOUT = 60;
public static final int DEFAULT_HEARTBEAT_INTERVAL = 25;
public static final int DEFAULT_CLOSE_TIMEOUT = 60;
public static final String DEFAULT_TRANSPORTS = "websocket,flashsocket,xhr-polling,jsonp-polling";
public static final boolean DEFAULT_ALWAYS_SECURE_WEB_SOCKET_LOCATION = false;
public static final String DEFAULT_REMOTE_ADDRESS_HEADER = null;
public static final boolean DEFAULT_EVENT_EXECUTOR_ENABLED = true;
public static final int DEFAULT_EVENT_EXECUTOR_THREAD_NUMBER = Runtime.getRuntime().availableProcessors() * 2;
public static final int DEFAULT_MAX_WEB_SOCKET_FRAME_SIZE = 65536;
public static final SslContext DEFAULT_SSL_CONTEXT = null;
public static final boolean DEFAULT_EPOLL_ENABLED = true;
public static final boolean DEFAULT_HTTP_COMPRESSION_ENABLED = false;
public static final boolean DEFAULT_WEBSOCKET_COMPRESSION_ENABLED = false;
private final int port;
private final int heartbeatTimeout;
private final int heartbeatInterval;
private final int closeTimeout;
private final String transports;
private final boolean alwaysSecureWebSocketLocation;
private final String remoteAddressHeader;
private final boolean eventExecutorEnabled;
private final int eventExecutorThreadNumber;
private final int maxWebSocketFrameSize;
private final SslContext sslContext;
private final boolean epollEnabled;
private final boolean httpCompressionEnabled;
private final boolean websocketCompressionEnabled;
/**
* Private constructor. Use {@link ServerConfiguration.Builder} to build configuration.
*/
private ServerConfiguration(Builder builder) {
this.port = builder.port;
this.heartbeatTimeout = builder.heartbeatTimeout;
this.heartbeatInterval = builder.heartbeatInterval;
this.closeTimeout = builder.closeTimeout;
this.transports = builder.transports;
this.alwaysSecureWebSocketLocation = builder.alwaysSecureWebSocketLocation;
this.remoteAddressHeader = builder.remoteAddressHeader;
this.eventExecutorEnabled = builder.eventExecutorEnabled;
this.eventExecutorThreadNumber = builder.eventExecutorThreadNumber;
this.maxWebSocketFrameSize = builder.maxWebSocketFrameSize;
this.sslContext = builder.sslContext;
this.epollEnabled = builder.epollEnabled;
this.httpCompressionEnabled = builder.httpCompressionEnabled;
this.websocketCompressionEnabled = builder.websocketCompressionEnabled;
}
public static Builder builder() {
return new Builder();
}
/**
* Port on which Socket.IO server will be started. Default value is 8080.
*/
public int getPort() {
return port;
}
/**
* SSL context which is used to run secure socket. If it's set to null server runs without SSL.
* Default value is null.
*/
public SslContext getSslContext() {
return sslContext;
}
/**
* The timeout in seconds for the client when it should send a new heart
* beat to the server. This value is sent to the client after a successful
* handshake. The default value is 60.
*/
public int getHeartbeatTimeout() {
return heartbeatTimeout;
}
/**
* The timeout in seconds for the client, when it closes the connection it
* still X amounts of seconds to do re open of the connection. This value is
* sent to the client after a successful handshake. Default value is 60.
*/
public int getCloseTimeout() {
return closeTimeout;
}
/**
* A string with list of allowed transport methods separated by comma.
* Default value is "websocket,flashsocket,xhr-polling,jsonp-polling".
*/
public String getTransports() {
return transports;
}
/**
* The timeout in seconds for the server, we should receive a heartbeat from
* the client within this interval. This should be less than the heartbeat
* timeout. Default value is 25.
*/
public int getHeartbeatInterval() {
return heartbeatInterval;
}
/**
* Flag which if set to true will always return secure web socket location protocol ("wss://")
* even when connection is established over plain socket. It is used as a workaround related to case
* when SSL is offloaded to Load Balancer, but it doesn't modify web socket location. By default it
* is false.
*/
public boolean isAlwaysSecureWebSocketLocation() {
return alwaysSecureWebSocketLocation;
}
/**
* The HTTP header name which is used as a session remote address. It is a workaround related to case
* when Load Balancer modify client address with its address. This header is supposed to be set by Load
* Balancer. If it is set to null then this header is not used. Default value is null.
*/
public String getRemoteAddressHeader() {
return remoteAddressHeader;
}
/**
* Flag which defines if listener will be executed, true - different thread, false - io-thread.
* Default is true.
*/
public boolean isEventExecutorEnabled() {
return eventExecutorEnabled;
}
/*
* Event executor thread number, if eventExecutorEnabled flag set to true.
* Default value is Runtime.getRuntime().availableProcessors() x 2.
*/
public int getEventExecutorThreadNumber() {
return eventExecutorThreadNumber;
}
/**
* Maximum allowable web socket frame payload length. Setting this value to your application's requirement may
* reduce denial of service attacks using long data frames. Default is 65536.
*/
public int getMaxWebSocketFrameSize() {
return maxWebSocketFrameSize;
}
/**
* Flag which defines if Linux native epoll transport will be used if available. Default is true.
*/
public boolean isEpollEnabled() {
return epollEnabled;
}
/**
* Flag which defines if HTTP compression is enabled. Default is false.
*/
public boolean isHttpCompressionEnabled() {
return httpCompressionEnabled;
}
/**
* Flag which defines if websocket compression is enabled. Default is false.
*/
public boolean isWebsocketCompressionEnabled() {
return websocketCompressionEnabled;
}
@Override
public String toString() {
return "ServerConfiguration{port=" + port +
", ssl=" + (sslContext != null) +
", heartbeatTimeout=" + heartbeatTimeout +
", heartbeatInterval=" + heartbeatInterval +
", closeTimeout=" + closeTimeout +
", transports='" + transports + '\'' +
", alwaysSecureWebSocketLocation=" + alwaysSecureWebSocketLocation +
", remoteAddressHeader=" + remoteAddressHeader +
", eventExecutorEnabled=" + eventExecutorEnabled +
", eventExecutorThreadNumber=" + eventExecutorThreadNumber +
", maxWebSocketFrameSize=" + maxWebSocketFrameSize +
", epollEnabled=" + epollEnabled +
", httpCompressionEnabled=" + httpCompressionEnabled +
", websocketCompressionEnabled=" + websocketCompressionEnabled +
'}';
}
public static class Builder {
private int port = DEFAULT_PORT;
private int heartbeatTimeout = DEFAULT_HEARTBEAT_TIMEOUT;
private int heartbeatInterval = DEFAULT_HEARTBEAT_INTERVAL;
private int closeTimeout = DEFAULT_CLOSE_TIMEOUT;
private String transports = DEFAULT_TRANSPORTS;
private boolean alwaysSecureWebSocketLocation = DEFAULT_ALWAYS_SECURE_WEB_SOCKET_LOCATION;
private String remoteAddressHeader = DEFAULT_REMOTE_ADDRESS_HEADER;
private boolean eventExecutorEnabled = DEFAULT_EVENT_EXECUTOR_ENABLED;
private int eventExecutorThreadNumber = DEFAULT_EVENT_EXECUTOR_THREAD_NUMBER;
private int maxWebSocketFrameSize = DEFAULT_MAX_WEB_SOCKET_FRAME_SIZE;
private SslContext sslContext = DEFAULT_SSL_CONTEXT;
private boolean epollEnabled = DEFAULT_EPOLL_ENABLED;
private boolean httpCompressionEnabled = DEFAULT_HTTP_COMPRESSION_ENABLED;
private boolean websocketCompressionEnabled = DEFAULT_WEBSOCKET_COMPRESSION_ENABLED;
private Builder() {}
/**
* See {@link ServerConfiguration#getPort()}
*/
public Builder port(int port) {
this.port = port;
return this;
}
/**
* See {@link ServerConfiguration#getSslContext()}
*/
public Builder sslContext(SslContext sslContext) {
this.sslContext = sslContext;
return this;
}
/**
* See {@link ServerConfiguration#getSslContext()}
*/
public Builder sslContext(SSLContext sslContext) {
this.sslContext = sslContext != null
? new JdkSslContext(sslContext, false, ClientAuth.NONE)
: null;
return this;
}
/**
* See {@link ServerConfiguration#getHeartbeatTimeout()}
*/
public Builder heartbeatTimeout(int heartbeatTimeout) {
this.heartbeatTimeout = heartbeatTimeout;
return this;
}
/**
* See {@link ServerConfiguration#getHeartbeatInterval()}
*/
public Builder heartbeatInterval(int heartbeatInterval) {
this.heartbeatInterval = heartbeatInterval;
return this;
}
/**
* See {@link ServerConfiguration#getCloseTimeout()}
*/
public Builder closeTimeout(int closeTimeout) {
this.closeTimeout = closeTimeout;
return this;
}
/**
* See {@link ServerConfiguration#getTransports()}
*/
public Builder transports(String transports) {
this.transports = transports;
return this;
}
/**
* See {@link ServerConfiguration#isAlwaysSecureWebSocketLocation()}
*/
public Builder alwaysSecureWebSocketLocation(boolean alwaysSecureWebSocketLocation) {
this.alwaysSecureWebSocketLocation = alwaysSecureWebSocketLocation;
return this;
}
/**
* See {@link ServerConfiguration#getRemoteAddressHeader()}
*/
public Builder remoteAddressHeader(String remoteAddressHeader) {
this.remoteAddressHeader = remoteAddressHeader;
return this;
}
/**
* See {@link ServerConfiguration#getMaxWebSocketFrameSize()}
*/
public Builder maxWebSocketFrameSize(int maxWebSocketFrameSize) {
this.maxWebSocketFrameSize = maxWebSocketFrameSize;
return this;
}
/**
* See {@link ServerConfiguration#isEventExecutorEnabled()}
*/
public Builder eventExecutorEnabled(boolean eventExecutorEnabled) {
this.eventExecutorEnabled = eventExecutorEnabled;
return this;
}
/**
* See {@link ServerConfiguration#getEventExecutorThreadNumber()}
*/
public Builder eventExecutorThreadNumber(int eventExecutorThreadNumber) {
this.eventExecutorThreadNumber = eventExecutorThreadNumber;
return this;
}
/**
* See {@link ServerConfiguration#isEpollEnabled()}
*/
public Builder epollEnabled(boolean epollEnabled) {
this.epollEnabled = epollEnabled;
return this;
}
/**
* See {@link ServerConfiguration#isHttpCompressionEnabled()}
*/
public Builder httpCompressionEnabled(boolean httpCompressionEnabled) {
this.httpCompressionEnabled = httpCompressionEnabled;
return this;
}
/**
* See {@link ServerConfiguration#isWebsocketCompressionEnabled()}
*/
public Builder websocketCompressionEnabled(boolean websocketCompressionEnabled) {
this.websocketCompressionEnabled = websocketCompressionEnabled;
return this;
}
/**
* Creates new instance of {@code ServerConfiguration}
*/
public ServerConfiguration build() {
return new ServerConfiguration(this);
}
}
}