Source

ppenet / ppenet / protocol.py

Full commit
import socket
from structtype import structtype

MINIMUM_MTU = 576
MAXIMUM_MTU = 4096
MAXIMUM_PACKET_COMMANDS = 32
MINIMUM_WINDOW_SIZE = 4096
MAXIMUM_WINDOW_SIZE = 32768
MINIMUM_CHANNEL_COUNT = 1
MAXIMUM_CHANNEL_COUNT = 255
MAXIMUM_PEER_ID = 0xFFF
MAXIMUM_PACKET_SIZE = 1024 * 1024 * 1024
MAXIMUM_FRAGMENT_COUNT = 1024 * 1024

COMMAND_MASK = 0x0F


class Command:
    (NONE,
    ACKNOWLEDGE,
    CONNECT,
    VERIFY_CONNECT,
    DISCONNECT,
    PING,
    SEND_RELIABLE,
    SEND_UNRELIABLE,
    SEND_FRAGMENT,
    SEND_UNSEQUENCED,
    BANDWIDTH_LIMIT,
    THROTTLE_CONFIGURE,
    SEND_UNRELIABLE_FRAGMENT,
    COUNT) = range(14)


class Flag:
    COMMAND_ACKNOWLEDGE = 1 << 7
    COMMAND_UNSEQUENCED = 1 << 6

    HEADER_COMPRESSED = 1 << 14
    HEADER_SENT_TIME = 1 << 15
    HEADER_MASK = HEADER_COMPRESSED | HEADER_SENT_TIME
    HEADER_SESSION_MASK = 3 << 12
    HEADER_SESSION_SHIFT = 12


Header = structtype('Header', (
    'peer_id',
    'sent_time',
), '!HH', default=0)

CommandHeader = structtype('CommandHeader', (
    'command',
    'channel_id',
    'reliable_seq_num', # no idea why it's here
), '!BBH', default=0)

Acknowledge = structtype('Acknowledge', CommandHeader.field_names + (
    'received_reliable_seq_num',
    'received_sent_time'
), CommandHeader.format + 'HH', default=0, field_defaults={
    'command': Command.ACKNOWLEDGE
})

Connect = structtype('Connect', CommandHeader.field_names + (
    'outgoing_peer_id',
    'incoming_session_id',
    'outgoing_session_id',
    'mtu',
    'window_size',
    'channel_count',
    'incoming_bandwidth',
    'outgoing_bandwidth',
    'packet_throttle_interval',
    'packet_throttle_acceleration',
    'packet_throttle_deceleration',
    'connect_id',
    'data',
), CommandHeader.format + 'HBB10I', default=0, field_defaults={
    'command': Command.CONNECT | Flag.COMMAND_ACKNOWLEDGE
})

VerifyConnect = structtype('VerifyConnect', CommandHeader.field_names + (
    'outgoing_peer_id',
    'incoming_session_id',
    'outgoing_session_id',
    'mtu',
    'window_size',
    'channel_count',
    'incoming_bandwidth',
    'outgoing_bandwidth',
    'packet_throttle_interval',
    'packet_throttle_acceleration',
    'packet_throttle_deceleration',
    'connect_id',
), CommandHeader.format + 'HBB9I', default=0, field_defaults={
    'command': Command.VERIFY_CONNECT
})

BandwidthLimit = structtype('BandwidthLimit', CommandHeader.field_names + (
    'incoming_bandwidth',
    'outgoing_bandwidth',
), CommandHeader.format + 'II', default=0, field_defaults={
    'command': Command.BANDWIDTH_LIMIT
})

ThrottleConfigure = structtype('ThrottleConfigure', CommandHeader.field_names + (
    'packet_throttle_interval',
    'packet_throttle_acceleration',
    'packet_throttle_deceleration',
), CommandHeader.format + '3I', default=0, field_defaults={
    'command': Command.THROTTLE_CONFIGURE
})

Disconnect = structtype('Disconnect', CommandHeader.field_names + (
    'data',
), CommandHeader.format + 'I', default=0, field_defaults={
    'command': Command.DISCONNECT
})

Ping = structtype('Ping', CommandHeader.field_names,
                  CommandHeader.format, default=0,
                  field_defaults={'command': Command.PING})

SendReliable = structtype('SendReliable', CommandHeader.field_names + (
    'data_length',
), CommandHeader.format + 'H', default=0, field_defaults={
    'command': Command.SEND_RELIABLE | Flag.COMMAND_ACKNOWLEDGE
})

SendUnreliable = structtype('SendUnreliable', CommandHeader.field_names + (
    'unreliable_seq_num',
    'data_length',
), CommandHeader.format + 'HH', default=0, field_defaults={
    'command': Command.SEND_UNRELIABLE
})

SendUnsequenced = structtype('SendUnsequenced', CommandHeader.field_names + (
    'unsequenced_group',
    'data_length',
), CommandHeader.format + 'HH', default=0, field_defaults={
    'command': Command.SEND_UNSEQUENCED | Flag.COMMAND_UNSEQUENCED
})

SendFragment = structtype('SendFragment', CommandHeader.field_names + (
    'start_seq_num',
    'data_length',
    'fragment_count',
    'fragment_number',
    'total_length',
    'fragment_offset',
), CommandHeader.format + 'HH4I', default=0, field_defaults={
    'command': Command.SEND_FRAGMENT
})