/** * Builds Config with the previously set values. * * @return {@link SockJsConfig} the configuration for the SockJS service. */ public SockJsConfig build() { if (tls && (keyStore == null || keyStorePassword == null)) { throw new IllegalStateException("keyStore and keyStorePassword must be specified if 'tls' is enabled"); } return new SockJsConfig(this); } }
private static String infoContent(final SockJsConfig config) { final StringBuilder sb = new StringBuilder("{\"websocket\": ").append(config.isWebSocketEnabled()); sb.append(", \"origins\": [\"*:*\"]"); sb.append(", \"cookie_needed\": ").append(config.areCookiesNeeded()); sb.append(", \"entropy\": ").append(RANDOM.nextInt(Integer.MAX_VALUE) + 1); sb.append('}'); return sb.toString(); } }
private void startHeartbeatTimer(final ChannelHandlerContext ctx, final SockJsSession session) { heartbeatFuture = ctx.executor().scheduleAtFixedRate(new Runnable() { @Override public void run() { if (ctx.channel().isActive() && ctx.channel().isRegistered()) { if (logger.isDebugEnabled()) { logger.debug("Sending heartbeat for {}", session); } ctx.channel().writeAndFlush(new HeartbeatFrame()); } } }, session.config().heartbeatInterval(), session.config().heartbeatInterval(), TimeUnit.MILLISECONDS); }
@SuppressWarnings("resource") private KeyStore loadKeyStore() throws Exception { InputStream fin = null; try { fin = this.getClass().getResourceAsStream(sockJsConfig.keyStore()); if (fin == null) { throw new IllegalStateException("Could not locate keystore [" + sockJsConfig.keyStore() + "]"); } final KeyStore ks = KeyStore.getInstance("JKS"); ks.load(fin, sockJsConfig.keyStorePassword().toCharArray()); return ks; } finally { safeClose(fin); } }
@Override protected void initChannel(final SocketChannel socketChannel) throws Exception { final ChannelPipeline pipeline = socketChannel.pipeline(); if (sockjsConfig.isTls()) { final SSLEngine engine = sslContext.createSSLEngine(); engine.setUseClientMode(false); pipeline.addLast(new SslHandler(engine)); } pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(65536)); final DefaultSimplePushServer simplePushServer = new DefaultSimplePushServer(datastore, simplePushConfig, privateKey); pipeline.addLast(new NotificationHandler(simplePushServer)); pipeline.addLast(new CorsInboundHandler()); pipeline.addLast(new SockJsHandler(new SimplePushServiceFactory(sockjsConfig, simplePushServer))); pipeline.addLast(backgroundGroup, new UserAgentReaperHandler(simplePushServer)); pipeline.addLast(new CorsOutboundHandler()); }
final String wsUrl = getWebSocketLocation(config.isTls(), req, Transports.Type.WEBSOCKET.path()); final WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(wsUrl, config.webSocketProtocolCSV(), false); handshaker = wsFactory.newHandshaker(req); if (handshaker == null) {
private boolean maxBytesLimit(final int bytesWritten) { bytesSent.addAndGet(bytesWritten); return bytesSent.get() >= config.maxStreamingBytesSize(); }
/** * Sole constructor which takes one or more {@code SockJSServiceFactory}. These factories will * later be used by the server to create the SockJS services that will be exposed by this server * * @param factories one or more {@link SockJsServiceFactory}s. */ public SockJsHandler(final SockJsServiceFactory... factories) { for (SockJsServiceFactory factory : factories) { this.factories.put(factory.config().prefix(), factory); } }
/** * Sets the Http response header SET_COOKIE if {@link SockJsConfig#areCookiesNeeded()} is true. * * @param response the Http Response. * @param config the SockJS configuration. * @param request the Http request which will be inspected for the existence of a JSESSIONID cookie. */ public static void setSessionIdCookie(final FullHttpResponse response, final SockJsConfig config, final HttpRequest request) { if (config.areCookiesNeeded()) { response.headers().set(SET_COOKIE, encodeSessionIdCookie(request)); } }
private void startSessionTimer(final ChannelHandlerContext ctx, final SockJsSession session) { if (sessionTimer == null) { sessionTimer = ctx.executor().scheduleAtFixedRate(new Runnable() { @Override public void run() { final long now = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); if (isInUse()) { return; } if (session.timestamp() + session.config().sessionTimeout() < now) { final SockJsSession removed = sessions.remove(session.sessionId()); session.connectionContext().close(); sessionTimer.cancel(true); heartbeatFuture.cancel(true); if (logger.isDebugEnabled()) { logger.debug("Removed {} from map[{}]", removed.sessionId(), sessions.size()); } } } }, session.config().sessionTimeout(), session.config().sessionTimeout(), TimeUnit.MILLISECONDS); } }
private KeyManagerFactory keyManagerFactory(final KeyStore ks) throws Exception { final KeyManagerFactory kmf = KeyManagerFactory.getInstance(getKeyManagerAlgorithm()); kmf.init(ks, sockJsConfig.keyStorePassword().toCharArray()); return kmf; }
@Override protected void initChannel(final SocketChannel socketChannel) throws Exception { final ChannelPipeline pipeline = socketChannel.pipeline(); if (sockjsConfig.isTls()) { final SSLEngine engine = sslContext.createSSLEngine(); engine.setUseClientMode(false); pipeline.addLast(new SslHandler(engine)); } pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(65536)); final DefaultSimplePushServer simplePushServer = new DefaultSimplePushServer(datastore, simplePushConfig, privateKey); pipeline.addLast(new NotificationHandler(simplePushServer)); pipeline.addLast(new CorsInboundHandler()); pipeline.addLast(new SockJsHandler(new SimplePushServiceFactory(sockjsConfig, simplePushServer))); pipeline.addLast(backgroundGroup, new UserAgentReaperHandler(simplePushServer)); pipeline.addLast(new CorsOutboundHandler()); }
final String wsUrl = getWebSocketLocation(config.isTls(), req, Transports.Type.WEBSOCKET.path()); final WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(wsUrl, config.webSocketProtocolCSV(), false); handshaker = wsFactory.newHandshaker(req); if (handshaker == null) {
private boolean maxBytesLimit(final int bytesWritten) { bytesSent.addAndGet(bytesWritten); return bytesSent.get() >= config.maxStreamingBytesSize(); }
@SuppressWarnings("resource") private KeyStore loadKeyStore() throws Exception { InputStream fin = null; try { fin = this.getClass().getResourceAsStream(sockJsConfig.keyStore()); if (fin == null) { throw new IllegalStateException("Could not locate keystore [" + sockJsConfig.keyStore() + "]"); } final KeyStore ks = KeyStore.getInstance("JKS"); ks.load(fin, sockJsConfig.keyStorePassword().toCharArray()); return ks; } finally { safeClose(fin); } }
/** * Sole constructor which takes one or more {@code SockJSServiceFactory}. These factories will * later be used by the server to create the SockJS services that will be exposed by this server * * @param factories one or more {@link SockJsServiceFactory}s. */ public SockJsHandler(final SockJsServiceFactory... factories) { for (SockJsServiceFactory factory : factories) { this.factories.put(factory.config().prefix(), factory); } }
/** * Sets the Http response header SET_COOKIE if {@link SockJsConfig#areCookiesNeeded()} is true. * * @param response the Http Response. * @param config the SockJS configuration. * @param request the Http request which will be inspected for the existence of a JSESSIONID cookie. */ public static void setSessionIdCookie(final FullHttpResponse response, final SockJsConfig config, final HttpRequest request) { if (config.areCookiesNeeded()) { response.headers().set(SET_COOKIE, encodeSessionIdCookie(request)); } }
private void startSessionTimer(final ChannelHandlerContext ctx, final SockJsSession session) { if (sessionTimer == null) { sessionTimer = ctx.executor().scheduleAtFixedRate(new Runnable() { @Override public void run() { final long now = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); if (isInUse()) { return; } if (session.timestamp() + session.config().sessionTimeout() < now) { final SockJsSession removed = sessions.remove(session.sessionId()); session.connectionContext().close(); sessionTimer.cancel(true); heartbeatFuture.cancel(true); if (logger.isDebugEnabled()) { logger.debug("Removed {} from map[{}]", removed.sessionId(), sessions.size()); } } } }, session.config().sessionTimeout(), session.config().sessionTimeout(), TimeUnit.MILLISECONDS); } }
private KeyManagerFactory keyManagerFactory(final KeyStore ks) throws Exception { final KeyManagerFactory kmf = KeyManagerFactory.getInstance(getKeyManagerAlgorithm()); kmf.init(ks, sockJsConfig.keyStorePassword().toCharArray()); return kmf; }
/** * Sole constructor. * * @param simplePushConfig the {@link SimplePushServerConfig} configuration. * @param datastore the {@link DataStore} to be passed to the {@link SimplePushServiceFactory}. * @param sockjsConfig the SockJS {@link SimplePushServerConfig}. * @param backgroundGroup an {@link EventExecutorGroup} to be used for the {@link UserAgentReaperHandler}. */ public SockJSChannelInitializer(final SimplePushServerConfig simplePushConfig, final DataStore datastore, final SockJsConfig sockjsConfig, final EventExecutorGroup backgroundGroup) { this.simplePushConfig = simplePushConfig; this.datastore = datastore; this.sockjsConfig = sockjsConfig; this.backgroundGroup = backgroundGroup; privateKey = DefaultSimplePushServer.generateAndStorePrivateKey(datastore, simplePushConfig); if (sockjsConfig.isTls()) { sslContext = new WebSocketSslServerSslContext(sockjsConfig).sslContext(); } }