EIOSocket.java 6.26 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  org.apache.sling.commons.json.JSONArray
 *  org.apache.sling.commons.json.JSONException
 *  org.apache.sling.commons.json.JSONObject
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.granite.socketio.impl.engine;

import com.adobe.granite.socketio.impl.engine.EIOPacket;
import com.adobe.granite.socketio.impl.engine.EIOPacketType;
import com.adobe.granite.socketio.impl.engine.EIOServiceImpl;
import com.adobe.granite.socketio.impl.engine.EIOSocketListener;
import com.adobe.granite.socketio.impl.engine.EIOTransport;
import com.adobe.granite.socketio.impl.engine.EIOTransportListener;
import java.security.Principal;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EIOSocket
implements EIOTransportListener {
    private static final Logger log = LoggerFactory.getLogger(EIOSocket.class);
    private final String id;
    private State state = State.OPENING;
    private EIOTransport transport;
    private EIOSocketListener listener = EIOSocketListener.NOP;
    private ScheduledFuture<?> pingHandle;
    private final EIOServiceImpl service;
    private final Principal userPrincipal;
    private final Runnable pingTimeoutHandler;

    public EIOSocket(String id, EIOServiceImpl service, EIOTransport transport, Principal userPrincipal) {
        this.pingTimeoutHandler = new Runnable(){

            @Override
            public void run() {
                log.debug("ping timeout reached for socket {}. closing.", (Object)EIOSocket.this.id);
                EIOSocket.this.onClose("ping timeout");
            }
        };
        this.id = id;
        this.service = service;
        this.userPrincipal = userPrincipal;
        this.setTransport(transport);
    }

    public String getId() {
        return this.id;
    }

    public boolean isOpen() {
        return this.state == State.OPEN;
    }

    public void setListener(EIOSocketListener listener) {
        this.listener = listener;
    }

    @Override
    public void onOpen() {
        String str;
        log.trace("[{}] onOpen()", (Object)this.id);
        this.state = State.OPEN;
        try {
            JSONObject obj = new JSONObject();
            obj.put("sid", (Object)this.id);
            obj.put("upgrades", (Object)new JSONArray(this.transport.getUpgrades()));
            obj.put("pingInterval", this.service.getPingInterval());
            obj.put("pingTimeout", this.service.getPingTimeout());
            str = obj.toString();
        }
        catch (JSONException e) {
            throw new IllegalStateException((Throwable)e);
        }
        this.sendPacket(EIOPacketType.OPEN, str);
        this.service.onConnect(this);
        this.listener.onOpen();
        this.schedulePingTimeout();
    }

    private void schedulePingTimeout() {
        this.cancelPingTimeout();
        this.pingHandle = this.service.schedulePingTimeout(this.pingTimeoutHandler);
        log.debug("[{}] scheduled pingTimeout.", (Object)this.id);
    }

    private void cancelPingTimeout() {
        if (this.pingHandle != null) {
            boolean ret = this.pingHandle.cancel(false);
            this.pingHandle = null;
            log.debug("[{}] cancelPingTimeout. ret={}", (Object)this.id, (Object)ret);
        }
    }

    @Override
    public void onPacket(EIOPacket packet) {
        if (this.state == State.OPEN) {
            log.trace("[{}] onPacket: {}", (Object)this.id, (Object)packet);
            this.listener.onPacket(packet);
            this.schedulePingTimeout();
            switch (packet.type) {
                case PING: {
                    log.debug("[{}] got ping", (Object)this.id);
                    this.sendPacket(EIOPacketType.PONG, null);
                    this.listener.onHeartbeat();
                    break;
                }
                case PARSE_ERROR: {
                    this.onClose("parse error");
                    break;
                }
                case MESSAGE: {
                    this.listener.onMessage(packet.data);
                    break;
                }
                default: {
                    log.warn("[{}] Unexpected packet type: {}", (Object)this.id, (Object)packet.type);
                    break;
                }
            }
        } else {
            log.error("[{}] packet received with closed socket", (Object)this.id);
        }
    }

    @Override
    public void onError(String err) {
        log.debug("[{}] transport error: {}", (Object)this.id, (Object)err);
        this.onClose("transport error: " + err);
    }

    public void setTransport(EIOTransport transport) {
        this.transport = transport;
        transport.setListener(this);
    }

    public EIOTransport getTransport() {
        return this.transport;
    }

    @Override
    public void onClose() {
        this.onClose("transport close");
    }

    public void onClose(String reason) {
        if (this.state != State.CLOSED) {
            this.cancelPingTimeout();
            this.state = State.CLOSED;
            this.listener.onClose(reason);
            this.service.onDisconnect(this);
        }
    }

    public EIOSocket send(String data) {
        this.sendPacket(EIOPacketType.MESSAGE, data);
        return this;
    }

    private void sendPacket(EIOPacketType type, String data) {
        if (this.state != State.CLOSING) {
            log.trace("[{}] sending packet {} \"{}\"", new Object[]{this.id, type, data});
            this.transport.send(new EIOPacket(type, data));
        } else {
            log.error("[{}] Trying to send packet on non-oen socket with state {}", (Object)this.id, (Object)type);
        }
    }

    public void close() {
        if (this.state == State.OPEN) {
            this.state = State.CLOSING;
            this.transport.close();
            this.onClose("forced closed");
        }
    }

    public Principal getUserPrincipal() {
        return this.userPrincipal;
    }

    private static enum State {
        OPENING,
        OPEN,
        CLOSING,
        CLOSED;
        

        private State() {
        }
    }

}