All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.jsync.sockjs.impl.WebSocketTransport Maven / Gradle / Ivy

There is a newer version: 1.10.13
Show newest version
/*
 * Copyright (c) 2011-2013 The original author or authors
 * ------------------------------------------------------
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution.
 *
 *     The Eclipse Public License is available at
 *     http://www.eclipse.org/legal/epl-v10.html
 *
 *     The Apache License v2.0 is available at
 *     http://www.opensource.org/licenses/apache2.0.php
 *
 * You may elect to redistribute this code under either of these licenses.
 */

package io.jsync.sockjs.impl;

import io.jsync.Handler;
import io.jsync.VoidHandler;
import io.jsync.buffer.Buffer;
import io.jsync.http.HttpServerRequest;
import io.jsync.http.RouteMatcher;
import io.jsync.http.ServerWebSocket;
import io.jsync.http.impl.WebSocketMatcher;
import io.jsync.impl.AsyncInternal;
import io.jsync.json.JsonObject;
import io.jsync.logging.Logger;
import io.jsync.logging.impl.LoggerFactory;
import io.jsync.sockjs.SockJSSocket;

import java.util.Map;

/**
 * @author Tim Fox
 */
class WebSocketTransport extends BaseTransport {

    private static final Logger log = LoggerFactory.getLogger(WebSocketTransport.class);

    WebSocketTransport(final AsyncInternal async, WebSocketMatcher wsMatcher,
                       RouteMatcher rm, String basePath, final Map sessions,
                       final JsonObject config,
                       final Handler sockHandler) {
        super(async, sessions, config);
        String wsRE = basePath + COMMON_PATH_ELEMENT_RE + "websocket";

        wsMatcher.addRegEx(wsRE, new Handler() {

            public void handle(final WebSocketMatcher.Match match) {
                if (log.isTraceEnabled()) log.trace("WS, handler");
                final Session session = new Session(async, sessions, config.getLong("heartbeat_period"), sockHandler);
                session.setInfo(match.ws.localAddress(), match.ws.remoteAddress(), match.ws.uri(), match.ws.headers());
                session.register(new WebSocketListener(match.ws, session));
            }
        });

        rm.getWithRegEx(wsRE, new Handler() {
            public void handle(HttpServerRequest request) {
                if (log.isTraceEnabled()) log.trace("WS, get: " + request.uri());
                request.response().setStatusCode(400);
                request.response().end("Can \"Upgrade\" only to \"WebSocket\".");
            }
        });

        rm.allWithRegEx(wsRE, new Handler() {
            public void handle(HttpServerRequest request) {
                if (log.isTraceEnabled()) log.trace("WS, all: " + request.uri());
                request.response().headers().set("Allow", "GET");
                request.response().setStatusCode(405);
                request.response().end();
            }
        });
    }

    private static class WebSocketListener implements TransportListener {

        final ServerWebSocket ws;
        final Session session;
        boolean closed;

        WebSocketListener(final ServerWebSocket ws, final Session session) {
            this.ws = ws;
            this.session = session;
            ws.dataHandler(new Handler() {
                public void handle(Buffer data) {
                    if (!session.isClosed()) {
                        String msgs = data.toString();
                        if (msgs.equals("")) {
                            //Ignore empty frames
                        } else if ((msgs.startsWith("[\"") && msgs.endsWith("\"]")) ||
                                (msgs.startsWith("\"") && msgs.endsWith("\""))) {
                            session.handleMessages(msgs);
                        } else {
                            //Invalid JSON - we close the connection
                            close();
                        }
                    }
                }
            });
            ws.closeHandler(new VoidHandler() {
                public void handle() {
                    closed = true;
                    session.shutdown();
                }
            });
            ws.exceptionHandler(new Handler() {
                public void handle(Throwable t) {
                    closed = true;
                    session.shutdown();
                    session.handleException(t);
                }
            });
        }

        public void sendFrame(final String body) {
            if (log.isTraceEnabled()) log.trace("WS, sending frame");
            if (!closed) {
                ws.writeTextFrame(body);
            }
        }

        public void close() {
            if (!closed) {
                ws.close();
                session.shutdown();
                closed = true;
            }
        }

        public void sessionClosed() {
            session.writeClosed(this);
            closed = true;
            ws.close();
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy