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

org.jboss.aerogear.simplepush.vertx.SimplePushServerHandler Maven / Gradle / Ivy

The newest version!
/**
 * JBoss, Home of Professional Open Source
 * Copyright Red Hat, Inc., and individual contributors.
 *
 * 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 org.jboss.aerogear.simplepush.vertx;

import static org.jboss.aerogear.simplepush.protocol.impl.json.JsonUtil.fromJson;
import static org.jboss.aerogear.simplepush.protocol.impl.json.JsonUtil.toJson;

import java.util.Set;
import java.util.concurrent.ConcurrentMap;

import org.jboss.aerogear.simplepush.protocol.AckMessage;
import org.jboss.aerogear.simplepush.protocol.HelloMessage;
import org.jboss.aerogear.simplepush.protocol.HelloResponse;
import org.jboss.aerogear.simplepush.protocol.MessageType;
import org.jboss.aerogear.simplepush.protocol.RegisterResponse;
import org.jboss.aerogear.simplepush.protocol.UnregisterMessage;
import org.jboss.aerogear.simplepush.protocol.UnregisterResponse;
import org.jboss.aerogear.simplepush.protocol.Ack;
import org.jboss.aerogear.simplepush.protocol.impl.AckMessageImpl;
import org.jboss.aerogear.simplepush.protocol.impl.HelloMessageImpl;
import org.jboss.aerogear.simplepush.protocol.impl.NotificationMessageImpl;
import org.jboss.aerogear.simplepush.protocol.impl.PingMessageImpl;
import org.jboss.aerogear.simplepush.protocol.impl.RegisterMessageImpl;
import org.jboss.aerogear.simplepush.protocol.impl.UnregisterMessageImpl;
import org.jboss.aerogear.simplepush.protocol.impl.json.JsonUtil;
import org.jboss.aerogear.simplepush.server.SimplePushServer;
import org.jboss.aerogear.simplepush.util.UUIDUtil;
import org.vertx.java.core.Handler;
import org.vertx.java.core.Vertx;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.logging.Logger;
import org.vertx.java.core.sockjs.SockJSSocket;
import org.vertx.java.platform.Container;

/**
 * Vert.x SimplePush Server implementation.
 */
public class SimplePushServerHandler implements Handler {

    private final SimplePushServer simplePushServer;
    private final Logger logger;
    private final ConcurrentMap writeHandlerMap;
    private final ConcurrentMap lastAccessedMap;
    private final Vertx vertx;
    private final Container container;
    private String uaid;

    public SimplePushServerHandler(final SimplePushServer simplePushServer, final Vertx vertx, final Container container) {
        this.simplePushServer = simplePushServer;
        this.container = container;
        logger = container.logger();
        this.vertx = vertx;
        writeHandlerMap = vertx.sharedData().getMap(VertxSimplePushServer.WRITE_HANDLER_MAP);
        lastAccessedMap = vertx.sharedData().getMap(VertxSimplePushServer.LAST_ACCESSED_MAP);
    }

    @Override
    public void handle(final SockJSSocket sock) {
        sock.dataHandler(new Handler() {
            @Override
            public void handle(final Buffer buffer) {
                final MessageType messageType = JsonUtil.parseFrame(buffer.toString());
                switch (messageType.getMessageType()) {
                    case HELLO:
                        HelloMessage handshakeMessage = fromJson(buffer.toString(), HelloMessageImpl.class);
                        if (!writeHandlerMap.containsKey(handshakeMessage.getUAID())) {
                            handshakeMessage = new HelloMessageImpl(UUIDUtil.newUAID());
                        }
                        final HelloResponse helloResponse = simplePushServer.handleHandshake(handshakeMessage);
                        sock.write(new Buffer(toJson(helloResponse)));
                        uaid = helloResponse.getUAID();
                        writeHandlerMap.put(uaid.toString(), sock.writeHandlerID());
                        lastAccessedMap.put(uaid.toString(), System.currentTimeMillis());
                        logger.info("UserAgent [" + uaid + "] handshake done");
                        break;
                    case REGISTER:
                        if (checkHandshakeCompleted(uaid)) {
                            final RegisterResponse response = simplePushServer.handleRegister(fromJson(buffer.toString(), RegisterMessageImpl.class), uaid);
                            sock.write(new Buffer(toJson(response)));
                            logger.info("UserAgent [" + uaid + "] Registered[" + response + "]");
                        }
                        break;
                    case UNREGISTER:
                        if (checkHandshakeCompleted(uaid)) {
                            final UnregisterMessage unregister = fromJson(buffer.toString(), UnregisterMessageImpl.class);
                            final UnregisterResponse response = simplePushServer.handleUnregister(unregister, uaid);
                            sock.write(new Buffer(toJson(response)));
                            logger.info("UserAgent [" + uaid + "] Unregistered[" + response.getChannelId() + "]");
                        }
                        break;
                    case ACK:
                        if (checkHandshakeCompleted(uaid)) {
                            final AckMessage ack = fromJson(buffer.toString(), AckMessageImpl.class);
                            simplePushServer.handleAcknowledgement(ack, uaid);
                            processUnacked(uaid);
                        }
                        break;
                    case PING:
                        sock.write(new Buffer(PingMessageImpl.JSON));
                        break;
                    default:
                        break;
                }
                updateAccessedTime(uaid);
            }
        });
    }

    private boolean checkHandshakeCompleted(final String uaid) {
        if (uaid == null) {
            logger.debug("Hello frame has not been sent");
            return false;
        }
        return true;
    }

    private void updateAccessedTime(final String uaid) {
        if (uaid != null) {
            lastAccessedMap.put(uaid, System.currentTimeMillis());
        }
    }

    private void processUnacked(final String uaid) {
        final Set unacked = simplePushServer.getUnacknowledged(uaid);
        if (!unacked.isEmpty()) {
            final Long interval = container.config().getLong("ackInterval", 60000);
            vertx.setPeriodic(interval, new Handler() {
                public void handle(final Long timerID) {
                    final Set unacked = simplePushServer.getUnacknowledged(uaid);
                    if (unacked.isEmpty()) {
                        logger.info("Nothing to ack. Stopping periodic task");
                        vertx.cancelTimer(timerID);
                    } else {
                        logger.info("Resending " + unacked);
                        final Buffer buf = new Buffer(toJson(new NotificationMessageImpl(unacked)));
                        vertx.eventBus().send(writeHandlerMap.get(uaid.toString()), buf);
                    }
                }
            });
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy