You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
588 lines
17 KiB
588 lines
17 KiB
7 years ago
|
/**
|
||
6 years ago
|
* Copyright (c) 2012-2019 Nikita Koksharov
|
||
7 years ago
|
*
|
||
|
* 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 com.fr.third.socketio;
|
||
|
|
||
6 years ago
|
import java.io.InputStream;
|
||
|
import java.util.Arrays;
|
||
|
import java.util.List;
|
||
|
|
||
7 years ago
|
import com.fr.third.socketio.handler.SuccessAuthorizationListener;
|
||
|
import com.fr.third.socketio.listener.DefaultExceptionListener;
|
||
|
import com.fr.third.socketio.listener.ExceptionListener;
|
||
|
import com.fr.third.socketio.protocol.JsonSupport;
|
||
|
import com.fr.third.socketio.store.MemoryStoreFactory;
|
||
6 years ago
|
import com.fr.third.socketio.store.RedissonStoreFactory;
|
||
7 years ago
|
import com.fr.third.socketio.store.StoreFactory;
|
||
|
|
||
|
import javax.net.ssl.KeyManagerFactory;
|
||
|
|
||
|
public class Configuration {
|
||
|
|
||
|
private ExceptionListener exceptionListener = new DefaultExceptionListener();
|
||
|
|
||
|
private String context = "/socket.io";
|
||
|
|
||
|
private List<Transport> transports = Arrays.asList(Transport.WEBSOCKET, Transport.POLLING);
|
||
|
|
||
|
private int bossThreads = 0; // 0 = current_processors_amount * 2
|
||
|
private int workerThreads = 0; // 0 = current_processors_amount * 2
|
||
|
private boolean useLinuxNativeEpoll;
|
||
|
|
||
|
private boolean allowCustomRequests = false;
|
||
|
|
||
|
private int upgradeTimeout = 10000;
|
||
|
private int pingTimeout = 60000;
|
||
|
private int pingInterval = 25000;
|
||
|
private int firstDataTimeout = 5000;
|
||
|
|
||
|
private int maxHttpContentLength = 64 * 1024;
|
||
|
private int maxFramePayloadLength = 64 * 1024;
|
||
|
|
||
|
private String packagePrefix;
|
||
|
private String hostname;
|
||
|
private int port = -1;
|
||
|
|
||
|
private String sslProtocol = "TLSv1";
|
||
|
|
||
|
private String keyStoreFormat = "JKS";
|
||
|
private InputStream keyStore;
|
||
|
private String keyStorePassword;
|
||
|
|
||
|
private String trustStoreFormat = "JKS";
|
||
|
private InputStream trustStore;
|
||
|
private String trustStorePassword;
|
||
|
|
||
|
private String keyManagerFactoryAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
|
||
|
|
||
|
private boolean preferDirectBuffer = true;
|
||
|
|
||
|
private SocketConfig socketConfig = new SocketConfig();
|
||
|
|
||
|
private StoreFactory storeFactory = new MemoryStoreFactory();
|
||
|
|
||
|
private JsonSupport jsonSupport;
|
||
|
|
||
|
private AuthorizationListener authorizationListener = new SuccessAuthorizationListener();
|
||
|
|
||
|
private AckMode ackMode = AckMode.AUTO_SUCCESS_ONLY;
|
||
|
|
||
|
private boolean addVersionHeader = true;
|
||
|
|
||
|
private String origin;
|
||
|
|
||
|
private boolean httpCompression = true;
|
||
|
|
||
|
private boolean websocketCompression = true;
|
||
|
|
||
6 years ago
|
private boolean randomSession = false;
|
||
|
|
||
7 years ago
|
public Configuration() {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Defend from further modifications by cloning
|
||
|
*
|
||
|
* @param conf - Configuration object to clone
|
||
|
*/
|
||
|
Configuration(Configuration conf) {
|
||
|
setBossThreads(conf.getBossThreads());
|
||
|
setWorkerThreads(conf.getWorkerThreads());
|
||
|
setUseLinuxNativeEpoll(conf.isUseLinuxNativeEpoll());
|
||
|
|
||
|
setPingInterval(conf.getPingInterval());
|
||
|
setPingTimeout(conf.getPingTimeout());
|
||
|
|
||
|
setHostname(conf.getHostname());
|
||
|
setPort(conf.getPort());
|
||
|
|
||
|
if (conf.getJsonSupport() == null) {
|
||
|
try {
|
||
7 years ago
|
getClass().getClassLoader().loadClass("com.fr.third.fasterxml.jackson.databind.ObjectMapper");
|
||
7 years ago
|
try {
|
||
|
Class<?> jjs = getClass().getClassLoader().loadClass("com.fr.third.socketio.protocol.JacksonJsonSupport");
|
||
|
JsonSupport js = (JsonSupport) jjs.getConstructor().newInstance();
|
||
|
conf.setJsonSupport(js);
|
||
|
} catch (Exception e) {
|
||
|
throw new IllegalArgumentException(e);
|
||
|
}
|
||
|
} catch (ClassNotFoundException e) {
|
||
|
throw new IllegalArgumentException("Can't find jackson lib in classpath", e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
setJsonSupport(new JsonSupportWrapper(conf.getJsonSupport()));
|
||
|
setContext(conf.getContext());
|
||
|
setAllowCustomRequests(conf.isAllowCustomRequests());
|
||
|
|
||
|
setKeyStorePassword(conf.getKeyStorePassword());
|
||
|
setKeyStore(conf.getKeyStore());
|
||
|
setKeyStoreFormat(conf.getKeyStoreFormat());
|
||
|
setTrustStore(conf.getTrustStore());
|
||
|
setTrustStoreFormat(conf.getTrustStoreFormat());
|
||
|
setTrustStorePassword(conf.getTrustStorePassword());
|
||
|
setKeyManagerFactoryAlgorithm(conf.getKeyManagerFactoryAlgorithm());
|
||
|
|
||
|
setTransports(conf.getTransports().toArray(new Transport[conf.getTransports().size()]));
|
||
|
setMaxHttpContentLength(conf.getMaxHttpContentLength());
|
||
|
setPackagePrefix(conf.getPackagePrefix());
|
||
|
|
||
|
setPreferDirectBuffer(conf.isPreferDirectBuffer());
|
||
|
setStoreFactory(conf.getStoreFactory());
|
||
|
setAuthorizationListener(conf.getAuthorizationListener());
|
||
|
setExceptionListener(conf.getExceptionListener());
|
||
|
setSocketConfig(conf.getSocketConfig());
|
||
|
setAckMode(conf.getAckMode());
|
||
|
setMaxFramePayloadLength(conf.getMaxFramePayloadLength());
|
||
|
setUpgradeTimeout(conf.getUpgradeTimeout());
|
||
|
|
||
|
setAddVersionHeader(conf.isAddVersionHeader());
|
||
|
setOrigin(conf.getOrigin());
|
||
|
setSSLProtocol(conf.getSSLProtocol());
|
||
|
|
||
|
setHttpCompression(conf.isHttpCompression());
|
||
|
setWebsocketCompression(conf.isWebsocketCompression());
|
||
6 years ago
|
setRandomSession(conf.randomSession);
|
||
7 years ago
|
}
|
||
|
|
||
|
public JsonSupport getJsonSupport() {
|
||
|
return jsonSupport;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Allows to setup custom implementation of
|
||
|
* JSON serialization/deserialization
|
||
|
*
|
||
|
* @param jsonSupport - json mapper
|
||
|
*
|
||
|
* @see JsonSupport
|
||
|
*/
|
||
|
public void setJsonSupport(JsonSupport jsonSupport) {
|
||
|
this.jsonSupport = jsonSupport;
|
||
|
}
|
||
|
|
||
|
public String getHostname() {
|
||
|
return hostname;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Optional parameter. If not set then bind address
|
||
|
* will be 0.0.0.0 or ::0
|
||
|
*
|
||
|
* @param hostname - name of host
|
||
|
*/
|
||
|
public void setHostname(String hostname) {
|
||
|
this.hostname = hostname;
|
||
|
}
|
||
|
|
||
|
public int getPort() {
|
||
|
return port;
|
||
|
}
|
||
|
public void setPort(int port) {
|
||
|
this.port = port;
|
||
|
}
|
||
|
|
||
|
public int getBossThreads() {
|
||
|
return bossThreads;
|
||
|
}
|
||
|
public void setBossThreads(int bossThreads) {
|
||
|
this.bossThreads = bossThreads;
|
||
|
}
|
||
|
|
||
|
public int getWorkerThreads() {
|
||
|
return workerThreads;
|
||
|
}
|
||
|
public void setWorkerThreads(int workerThreads) {
|
||
|
this.workerThreads = workerThreads;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Ping interval
|
||
|
*
|
||
|
* @param heartbeatIntervalSecs - time in milliseconds
|
||
|
*/
|
||
|
public void setPingInterval(int heartbeatIntervalSecs) {
|
||
|
this.pingInterval = heartbeatIntervalSecs;
|
||
|
}
|
||
|
public int getPingInterval() {
|
||
|
return pingInterval;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Ping timeout
|
||
|
* Use <code>0</code> to disable it
|
||
|
*
|
||
|
* @param heartbeatTimeoutSecs - time in milliseconds
|
||
|
*/
|
||
|
public void setPingTimeout(int heartbeatTimeoutSecs) {
|
||
|
this.pingTimeout = heartbeatTimeoutSecs;
|
||
|
}
|
||
|
public int getPingTimeout() {
|
||
|
return pingTimeout;
|
||
|
}
|
||
|
public boolean isHeartbeatsEnabled() {
|
||
|
return pingTimeout > 0;
|
||
|
}
|
||
|
|
||
|
public String getContext() {
|
||
|
return context;
|
||
|
}
|
||
|
public void setContext(String context) {
|
||
|
this.context = context;
|
||
|
}
|
||
|
|
||
|
public boolean isAllowCustomRequests() {
|
||
|
return allowCustomRequests;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Allow to service custom requests differs from socket.io protocol.
|
||
|
* In this case it's necessary to add own handler which handle them
|
||
|
* to avoid hang connections.
|
||
|
* Default is {@code false}
|
||
|
*
|
||
|
* @param allowCustomRequests - {@code true} to allow
|
||
|
*/
|
||
|
public void setAllowCustomRequests(boolean allowCustomRequests) {
|
||
|
this.allowCustomRequests = allowCustomRequests;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* SSL key store password
|
||
|
*
|
||
|
* @param keyStorePassword - password of key store
|
||
|
*/
|
||
|
public void setKeyStorePassword(String keyStorePassword) {
|
||
|
this.keyStorePassword = keyStorePassword;
|
||
|
}
|
||
|
public String getKeyStorePassword() {
|
||
|
return keyStorePassword;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* SSL key store stream, maybe appointed to any source
|
||
|
*
|
||
|
* @param keyStore - key store input stream
|
||
|
*/
|
||
|
public void setKeyStore(InputStream keyStore) {
|
||
|
this.keyStore = keyStore;
|
||
|
}
|
||
|
public InputStream getKeyStore() {
|
||
|
return keyStore;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Key store format
|
||
|
*
|
||
|
* @param keyStoreFormat - key store format
|
||
|
*/
|
||
|
public void setKeyStoreFormat(String keyStoreFormat) {
|
||
|
this.keyStoreFormat = keyStoreFormat;
|
||
|
}
|
||
|
public String getKeyStoreFormat() {
|
||
|
return keyStoreFormat;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set maximum http content length limit
|
||
|
*
|
||
|
* @param value
|
||
|
* the maximum length of the aggregated http content.
|
||
|
*/
|
||
|
public void setMaxHttpContentLength(int value) {
|
||
|
this.maxHttpContentLength = value;
|
||
|
}
|
||
|
public int getMaxHttpContentLength() {
|
||
|
return maxHttpContentLength;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Transports supported by server
|
||
|
*
|
||
|
* @param transports - list of transports
|
||
|
*/
|
||
|
public void setTransports(Transport ... transports) {
|
||
|
if (transports.length == 0) {
|
||
|
throw new IllegalArgumentException("Transports list can't be empty");
|
||
|
}
|
||
|
this.transports = Arrays.asList(transports);
|
||
|
}
|
||
|
public List<Transport> getTransports() {
|
||
|
return transports;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Package prefix for sending json-object from client
|
||
|
* without full class name.
|
||
|
*
|
||
|
* With defined package prefix socket.io client
|
||
|
* just need to define '@class: 'SomeType'' in json object
|
||
|
* instead of '@class: 'com.full.package.name.SomeType''
|
||
|
*
|
||
|
* @param packagePrefix - prefix string
|
||
|
*
|
||
|
*/
|
||
|
public void setPackagePrefix(String packagePrefix) {
|
||
|
this.packagePrefix = packagePrefix;
|
||
|
}
|
||
|
public String getPackagePrefix() {
|
||
|
return packagePrefix;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Buffer allocation method used during packet encoding.
|
||
|
* Default is {@code true}
|
||
|
*
|
||
|
* @param preferDirectBuffer {@code true} if a direct buffer should be tried to be used as target for
|
||
|
* the encoded messages. If {@code false} is used it will allocate a heap
|
||
|
* buffer, which is backed by an byte array.
|
||
|
*/
|
||
|
public void setPreferDirectBuffer(boolean preferDirectBuffer) {
|
||
|
this.preferDirectBuffer = preferDirectBuffer;
|
||
|
}
|
||
|
public boolean isPreferDirectBuffer() {
|
||
|
return preferDirectBuffer;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Data store - used to store session data and implements distributed pubsub.
|
||
|
* Default is {@code MemoryStoreFactory}
|
||
|
*
|
||
|
* @param clientStoreFactory - implements StoreFactory
|
||
|
*
|
||
|
* @see MemoryStoreFactory
|
||
6 years ago
|
* @see RedissonStoreFactory
|
||
7 years ago
|
*/
|
||
|
public void setStoreFactory(StoreFactory clientStoreFactory) {
|
||
|
this.storeFactory = clientStoreFactory;
|
||
|
}
|
||
|
public StoreFactory getStoreFactory() {
|
||
|
return storeFactory;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Authorization listener invoked on every handshake.
|
||
|
* Accepts or denies a client by {@code AuthorizationListener.isAuthorized} method.
|
||
|
* <b>Accepts</b> all clients by default.
|
||
|
*
|
||
|
* @param authorizationListener - authorization listener itself
|
||
|
*
|
||
|
* @see AuthorizationListener
|
||
|
*/
|
||
|
public void setAuthorizationListener(AuthorizationListener authorizationListener) {
|
||
|
this.authorizationListener = authorizationListener;
|
||
|
}
|
||
|
public AuthorizationListener getAuthorizationListener() {
|
||
|
return authorizationListener;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Exception listener invoked on any exception in
|
||
|
* SocketIO listener
|
||
|
*
|
||
|
* @param exceptionListener - listener
|
||
|
*
|
||
|
* @see ExceptionListener
|
||
|
*/
|
||
|
public void setExceptionListener(ExceptionListener exceptionListener) {
|
||
|
this.exceptionListener = exceptionListener;
|
||
|
}
|
||
|
public ExceptionListener getExceptionListener() {
|
||
|
return exceptionListener;
|
||
|
}
|
||
|
|
||
|
public SocketConfig getSocketConfig() {
|
||
|
return socketConfig;
|
||
|
}
|
||
|
/**
|
||
|
* TCP socket configuration
|
||
|
*
|
||
|
* @param socketConfig - config
|
||
|
*/
|
||
|
public void setSocketConfig(SocketConfig socketConfig) {
|
||
|
this.socketConfig = socketConfig;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Auto ack-response mode
|
||
|
* Default is {@code AckMode.AUTO_SUCCESS_ONLY}
|
||
|
*
|
||
|
* @see AckMode
|
||
|
*
|
||
|
* @param ackMode - ack mode
|
||
|
*/
|
||
|
public void setAckMode(AckMode ackMode) {
|
||
|
this.ackMode = ackMode;
|
||
|
}
|
||
|
public AckMode getAckMode() {
|
||
|
return ackMode;
|
||
|
}
|
||
|
|
||
|
|
||
|
public String getTrustStoreFormat() {
|
||
|
return trustStoreFormat;
|
||
|
}
|
||
|
public void setTrustStoreFormat(String trustStoreFormat) {
|
||
|
this.trustStoreFormat = trustStoreFormat;
|
||
|
}
|
||
|
|
||
|
public InputStream getTrustStore() {
|
||
|
return trustStore;
|
||
|
}
|
||
|
public void setTrustStore(InputStream trustStore) {
|
||
|
this.trustStore = trustStore;
|
||
|
}
|
||
|
|
||
|
public String getTrustStorePassword() {
|
||
|
return trustStorePassword;
|
||
|
}
|
||
|
public void setTrustStorePassword(String trustStorePassword) {
|
||
|
this.trustStorePassword = trustStorePassword;
|
||
|
}
|
||
|
|
||
|
public String getKeyManagerFactoryAlgorithm() {
|
||
|
return keyManagerFactoryAlgorithm;
|
||
|
}
|
||
|
public void setKeyManagerFactoryAlgorithm(String keyManagerFactoryAlgorithm) {
|
||
|
this.keyManagerFactoryAlgorithm = keyManagerFactoryAlgorithm;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Set maximum websocket frame content length limit
|
||
|
*
|
||
|
* @param maxFramePayloadLength - length
|
||
|
*/
|
||
|
public void setMaxFramePayloadLength(int maxFramePayloadLength) {
|
||
|
this.maxFramePayloadLength = maxFramePayloadLength;
|
||
|
}
|
||
|
public int getMaxFramePayloadLength() {
|
||
|
return maxFramePayloadLength;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Transport upgrade timeout in milliseconds
|
||
|
*
|
||
|
* @param upgradeTimeout - upgrade timeout
|
||
|
*/
|
||
|
public void setUpgradeTimeout(int upgradeTimeout) {
|
||
|
this.upgradeTimeout = upgradeTimeout;
|
||
|
}
|
||
|
public int getUpgradeTimeout() {
|
||
|
return upgradeTimeout;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds <b>Server</b> header with lib version to http response.
|
||
|
* <p>
|
||
|
* Default is <code>true</code>
|
||
|
*
|
||
|
* @param addVersionHeader - <code>true</code> to add header
|
||
|
*/
|
||
|
public void setAddVersionHeader(boolean addVersionHeader) {
|
||
|
this.addVersionHeader = addVersionHeader;
|
||
|
}
|
||
|
public boolean isAddVersionHeader() {
|
||
|
return addVersionHeader;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set <b>Access-Control-Allow-Origin</b> header value for http each
|
||
|
* response.
|
||
|
* Default is <code>null</code>
|
||
|
*
|
||
|
* If value is <code>null</code> then request <b>ORIGIN</b> header value used.
|
||
|
*
|
||
|
* @param origin - origin
|
||
|
*/
|
||
|
public void setOrigin(String origin) {
|
||
|
this.origin = origin;
|
||
|
}
|
||
|
public String getOrigin() {
|
||
|
return origin;
|
||
|
}
|
||
|
|
||
|
public boolean isUseLinuxNativeEpoll() {
|
||
|
return useLinuxNativeEpoll;
|
||
|
}
|
||
|
public void setUseLinuxNativeEpoll(boolean useLinuxNativeEpoll) {
|
||
|
this.useLinuxNativeEpoll = useLinuxNativeEpoll;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the name of the requested SSL protocol
|
||
|
*
|
||
|
* @param sslProtocol - name of protocol
|
||
|
*/
|
||
|
public void setSSLProtocol(String sslProtocol) {
|
||
|
this.sslProtocol = sslProtocol;
|
||
|
}
|
||
|
public String getSSLProtocol() {
|
||
|
return sslProtocol;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Timeout between channel opening and first data transfer
|
||
|
* Helps to avoid 'silent channel' attack and prevents
|
||
|
* 'Too many open files' problem in this case
|
||
|
*
|
||
|
* @param firstDataTimeout - timeout value
|
||
|
*/
|
||
|
public void setFirstDataTimeout(int firstDataTimeout) {
|
||
|
this.firstDataTimeout = firstDataTimeout;
|
||
|
}
|
||
|
public int getFirstDataTimeout() {
|
||
|
return firstDataTimeout;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Activate http protocol compression. Uses {@code gzip} or
|
||
|
* {@code deflate} encoding choice depends on the {@code "Accept-Encoding"} header value.
|
||
|
* <p>
|
||
|
* Default is <code>true</code>
|
||
|
*
|
||
|
* @param httpCompression - <code>true</code> to use http compression
|
||
|
*/
|
||
|
public void setHttpCompression(boolean httpCompression) {
|
||
|
this.httpCompression = httpCompression;
|
||
|
}
|
||
|
public boolean isHttpCompression() {
|
||
|
return httpCompression;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Activate websocket protocol compression.
|
||
|
* Uses {@code permessage-deflate} encoding only.
|
||
|
* <p>
|
||
|
* Default is <code>true</code>
|
||
|
*
|
||
|
* @param websocketCompression - <code>true</code> to use websocket compression
|
||
|
*/
|
||
|
public void setWebsocketCompression(boolean websocketCompression) {
|
||
|
this.websocketCompression = websocketCompression;
|
||
|
}
|
||
|
public boolean isWebsocketCompression() {
|
||
|
return websocketCompression;
|
||
|
}
|
||
|
|
||
6 years ago
|
public boolean isRandomSession() {
|
||
|
return randomSession;
|
||
|
}
|
||
|
|
||
|
public void setRandomSession(boolean randomSession) {
|
||
|
this.randomSession = randomSession;
|
||
|
}
|
||
7 years ago
|
}
|