### Navigation

- index
- modules |
- gevent-socketio 0.3.1 documentation »
- Module code »
- socketio »

# Source code for socketio.packet

    from socketio.defaultjson import default_json_dumps, default_json_loads

    MSG_TYPES = {
        'disconnect': 0,
        'connect': 1,
        'heartbeat': 2,
        'message': 3,
        'json': 4,
        'event': 5,
        'ack': 6,
        'error': 7,
        'noop': 8,
        }

    MSG_VALUES = dict((v, k) for k, v in MSG_TYPES.iteritems())

    ERROR_REASONS = {
        'transport not supported': 0,
        'client not handshaken': 1,
        'unauthorized': 2
        }

    REASONS_VALUES = dict((v, k) for k, v in ERROR_REASONS.iteritems())

    ERROR_ADVICES = {
        'reconnect': 0,
        }

    ADVICES_VALUES = dict((v, k) for k, v in ERROR_ADVICES.iteritems())

    socketio_packet_attributes = ['type', 'name', 'data', 'endpoint', 'args',
                                  'ackId', 'reason', 'advice', 'qs', 'id']

    def encode(data, json_dumps=default_json_dumps):
        """
        Encode an attribute dict into a byte string.
        """
        payload = ''
        msg = str(MSG_TYPES[data['type']])

        if msg in ['0', '1']:
            # '1::' [path] [query]
            msg += '::' + data['endpoint']
            if 'qs' in data and data['qs'] != '':
                msg += ':' + data['qs']

        elif msg == '2':
            # heartbeat
            msg += '::'

        elif msg in ['3', '4', '5']:
            # '3:' [id ('+')] ':' [endpoint] ':' [data]
            # '4:' [id ('+')] ':' [endpoint] ':' [json]
            # '5:' [id ('+')] ':' [endpoint] ':' [json encoded event]
            # The message id is an incremental integer, required for ACKs.
            # If the message id is followed by a +, the ACK is not handled by
            # socket.io, but by the user instead.
            if msg == '3':
                payload = data['data']
            if msg == '4':
                payload = json_dumps(data['data'])
            if msg == '5':
                d = {}
                d['name'] = data['name']
                if 'args' in data and data['args'] != []:
                    d['args'] = data['args']
                payload = json_dumps(d)
            if 'id' in data:
                msg += ':' + str(data['id'])
                if data['ack'] == 'data':
                    msg += '+'
                msg += ':'
            else:
                msg += '::'
            if 'endpoint' not in data:
                data['endpoint'] = ''
            if payload != '':
                msg += data['endpoint'] + ':' + payload
            else:
                msg += data['endpoint']

        elif msg == '6':
            # '6:::' [id] '+' [data]
            msg += '::' + data.get('endpoint', '') + ':' + str(data['ackId'])
            if 'args' in data and data['args'] != []:
                msg += '+' + json_dumps(data['args'])

        elif msg == '7':
            # '7::' [endpoint] ':' [reason] '+' [advice]
            msg += ':::'
            if 'reason' in data and data['reason'] != '':
                msg += str(ERROR_REASONS[data['reason']])
            if 'advice' in data and data['advice'] != '':
                msg += '+' + str(ERROR_ADVICES[data['advice']])
            msg += data['endpoint']

        # NoOp, used to close a poll after the polling duration time
        elif msg == '8':
            msg += '::'

        return msg

    def decode(rawstr, json_loads=default_json_loads):
        """
        Decode a rawstr packet arriving from the socket into a dict.
        """
        decoded_msg = {}
        split_data = rawstr.split(":", 3)
        msg_type = split_data[0]
        msg_id = split_data[1]
        endpoint = split_data[2]

        data = ''

        if msg_id != '':
            if "+" in msg_id:
                msg_id = msg_id.split('+')[0]
                decoded_msg['id'] = int(msg_id)
                decoded_msg['ack'] = 'data'
            else:
                decoded_msg['id'] = int(msg_id)
                decoded_msg['ack'] = True

        # common to every message
        msg_type_id = int(msg_type)
        if msg_type_id in MSG_VALUES:
            decoded_msg['type'] = MSG_VALUES[int(msg_type)]
        else:
            raise Exception("Unknown message type: %s" % msg_type)

        decoded_msg['endpoint'] = endpoint

        if len(split_data) > 3:
            data = split_data[3]

        if msg_type == "0":  # disconnect
            pass

        elif msg_type == "1":  # connect
            decoded_msg['qs'] = data

        elif msg_type == "2":  # heartbeat
            pass

        elif msg_type == "3":  # message
            decoded_msg['data'] = data

        elif msg_type == "4":  # json msg
            decoded_msg['data'] = json_loads(data)

        elif msg_type == "5":  # event
            try:
                data = json_loads(data)
            except ValueError, e:
                print("Invalid JSON event message", data)
                decoded_msg['args'] = []
            else:
                decoded_msg['name'] = data.pop('name')
                if 'args' in data:
                    decoded_msg['args'] = data['args']
                else:
                    decoded_msg['args'] = []

        elif msg_type == "6":  # ack
            if '+' in data:
                ackId, data = data.split('+')
                decoded_msg['ackId'] = int(ackId)
                decoded_msg['args'] = json_loads(data)
            else:
                decoded_msg['ackId'] = int(data)
                decoded_msg['args'] = []

        elif msg_type == "7":  # error
            if '+' in data:
                reason, advice = data.split('+')
                decoded_msg['reason'] = REASONS_VALUES[int(reason)]
                decoded_msg['advice'] = ADVICES_VALUES[int(advice)]
            else:
                decoded_msg['advice'] = ''
                if data != '':
                    decoded_msg['reason'] = REASONS_VALUES[int(data)]
                else:
                    decoded_msg['reason'] = ''
        elif msg_type == "8":  # noop
            pass

        return decoded_msg

### Navigation

- index
- modules |
- gevent-socketio 0.3.1 documentation »
- Module code »
- socketio »