Package org.atmosphere.socketio.transport

Source Code of org.atmosphere.socketio.transport.SocketIOPacketImpl

/*
* Copyright 2014 Sebastien Dionne
*
* 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.atmosphere.socketio.transport;

import org.atmosphere.socketio.SocketIOException;
import org.atmosphere.socketio.SocketIOPacket;

import java.util.ArrayList;
import java.util.List;

/**
* @author Sebastien Dionne  : sebastien.dionne@gmail.com
*/
public class SocketIOPacketImpl implements SocketIOPacket {

    public static final char SOCKETIO_MSG_DELIMITER = '\ufffd';

    public final static String POST_RESPONSE = "1";
    private final PacketType packetType;

    private final String id;
    private final String endpoint;
    private final String data;
    private boolean padding = false;

    public SocketIOPacketImpl(PacketType frameType) {
        this(frameType, null, null, null, false);
    }

    public SocketIOPacketImpl(PacketType frameType, String data) {
        this(frameType, null, null, data, false);
    }

    public SocketIOPacketImpl(PacketType frameType, String data, boolean padding) {
        this(frameType, null, null, data, padding);
    }

    public SocketIOPacketImpl(PacketType frameType, String id, String endpoint, String data) {
        this(frameType, id, endpoint, data, false);
    }

    public SocketIOPacketImpl(PacketType frameType, String id, String endpoint, String data, boolean padding) {
        this.packetType = frameType;
        this.id = id;
        this.endpoint = endpoint;
        this.data = data;
        this.padding = padding;
    }

    public PacketType getFrameType() {
        return packetType;
    }

    public String getData() {
        return data;
    }

    public void setPadding(boolean padding) {
        this.padding = padding;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();

        //[message type] ':' [message id ('+')] ':' [message endpoint] (':' [message data])
        sb.append(packetType.value).append(":");

        if (id != null) {
            sb.append(id);
        }

        sb.append(":");

        if (endpoint != null) {
            sb.append(endpoint);
        }

        if (data != null) {
            sb.append(":");
            sb.append(data);
        }

        String msg = sb.toString();

        if (padding) {
            sb = new StringBuilder();
            sb.append(SOCKETIO_MSG_DELIMITER).append(msg.length()).append(SOCKETIO_MSG_DELIMITER).append(msg);
            msg = sb.toString();
        }


        return msg;
    }


    public enum PacketType {
        UNKNOWN(-1),
        DISCONNECT(0),
        CONNECT(1),
        HEARTBEAT(2),
        MESSAGE(3),
        JSON(4),
        EVENT(5),
        ACK(6),
        ERROR(7),
        NOOP(8);

        private int value;

        PacketType(int value) {
            this.value = value;
        }

        public int value() {
            return value;
        }

        public static PacketType fromInt(int val) {
            switch (val) {
                case 0:
                    return DISCONNECT;
                case 1:
                    return CONNECT;
                case 2:
                    return HEARTBEAT;
                case 3:
                    return MESSAGE;
                case 4:
                    return JSON;
                case 5:
                    return EVENT;
                case 6:
                    return ACK;
                case 7:
                    return ERROR;
                case 8:
                    return NOOP;
                default:
                    return UNKNOWN;
            }
        }
    }

    private static SocketIOPacketImpl parse2(String data) throws SocketIOException {

        try {
            String array[] = data.split(":");

            if (array.length < 1) {
                System.err.println("Message invalide=" + data);
                return null;
            }

            String type = null;
            String id = null;
            String endpoint = null;
            String message = null;

            //[message type] ':' [message id ('+')] ':' [message endpoint] (':' [message data])

            // 0::/test
            // 1::/test?my=param
            // 2::
            // 3:1::blabla
            // 4:1::{"a":"b"}
            // 5:::{"args":["user1","user2 ecrit coucou"],"name":"user message"}
            // 6:::4+["A","B"]  ou 6:::4
            // '7::' [endpoint] ':' [reason] '+' [advice]
            // 8 ..

            if (array.length == 1) {
                type = array[0];
            } else if (array.length == 2) {
                type = array[0];
                id = array[1];
            } else if (array.length == 3) {
                type = array[0];
                id = array[1];
                endpoint = array[2];
            } else {

                type = array[0];
                id = array[1];
                endpoint = array[2];

                // skip the first 3 ":"

                int start = data.indexOf(":");

                start = data.indexOf(":", ++start);
                start = data.indexOf(":", ++start);

                if (start > -1) {
                    message = data.substring(start + 1);
                }
            }

            return new SocketIOPacketImpl(PacketType.fromInt(Integer.parseInt(type)), id, endpoint, message);
        } catch (Exception e) {
            throw new SocketIOException("Invalid message = " + data, e);
        }
    }

    public static List<SocketIOPacketImpl> parse(String data) throws SocketIOException {
        List<SocketIOPacketImpl> messages = new ArrayList<SocketIOPacketImpl>();

        if (data == null || data.length() == 0) {
            return messages;
        }


        try {
            // look for delimiter
            if (data.charAt(0) == SocketIOPacketImpl.SOCKETIO_MSG_DELIMITER) {

                int size = data.length();
                int previousDelimiterIndex = 1;
                int nextDelimiterIndex = -1;

                // find next delimiter
                for (int i = 1; i < size; i++) {
                    for (; i < size; i++) {
                        if (data.charAt(i) == SocketIOPacketImpl.SOCKETIO_MSG_DELIMITER) {
                            nextDelimiterIndex = i;
                            break;
                        }
                    }

                    if (nextDelimiterIndex > previousDelimiterIndex) {
                        int length = Integer.parseInt(data.substring(previousDelimiterIndex, nextDelimiterIndex));

                        i = ++nextDelimiterIndex + length;
                        previousDelimiterIndex = i + 1;

                        SocketIOPacketImpl msg = parse2(data.substring(nextDelimiterIndex, i));

                        if (msg != null) {
                            messages.add(msg);
                        }

                    }
                }

            } else {

                SocketIOPacketImpl msg = parse2(data);

                if (msg != null) {
                    messages.add(msg);
                }
            }

            return messages;
        } catch (Exception e) {
            throw new SocketIOException("Invalid message=" + data, e);
        }
    }

}
TOP

Related Classes of org.atmosphere.socketio.transport.SocketIOPacketImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.