Exemple #1
0
def test_message_object_instantiation():
    mac = [0x00, 0x0B, 0xAD, 0xC0, 0xFF, 0xEE]
    Message.packno = 0
    m = Message(source=mac, destination=mac, command=commands.RESET)
    assert isinstance(m, Message)

    assert m.source == '00:0b:ad:c0:ff:ee'
    assert m.target_count == 1
    assert m.packet_number == 1
    assert m.command == commands.RESET
    assert m.destination == '00:0b:ad:c0:ff:ee'
    assert m.payload == b''

    m = Message(source=mac, destination=mac, command=commands.CHANGE_IP)
    assert m.packet_number == 2

    expected = """[header]
    [source]       = 00:0b:ad:c0:ff:ee
    [target count] = 1
    [packet no]    = 2
    [command]      = CHANGE_IP [0x6]
    [payload len]  = 0
[destination] = 00:0b:ad:c0:ff:ee
[payload] = none
[checksum] = 0x5f17f037"""
    assert str(m) == expected

    m.source = "00:de:ad:be:ef:00"
Exemple #2
0
def test_destination_check():
    with pytest.raises(ValueError):
        Message(source='00:0B:AD:C0:FF:EE',
                command=commands.RESET)

    Message(source='00:0B:AD:C0:FF:EE',
            command=commands.REQUEST_CONFIG)
Exemple #3
0
def test_message_ack_payload():
    m = Message.from_bytes(ACK_MSG)
    assert isinstance(m, Message)

    expected = """[header]
    [source]       = 00:0c:c6:69:13:2d
    [target count] = 1
    [packet no]    = 1
    [command]      = UPDATE_CONFIG_ACK [0x10]
    [payload len]  = 4
[destination] = 00:22:19:06:bf:58
[payload] = [acknowledgement]
                [to packet] = 2
                [code]      = OK [0x0]
[checksum] = 0x12ec8a45"""

    assert str(m) == expected
    assert m.to_bytes() == ACK_MSG

    p = Acknowledgement.from_bytes(ACK)
    mm = Message(source="00:0c:c6:69:13:2d",
                 packet_number=1,
                 command=commands.UPDATE_CONFIG_ACK,
                 destination="00:22:19:06:bf:58",
                 payload=p)
    assert m == mm
    def send_configuration(self, config: Configuration) -> commands:
        message = Message(source=self.mac,
                          destination=config.mac,
                          command=commands.UPDATE_CONFIG,
                          payload=config)
        pack_no = message.packet_number

        self.log.emit(f'Sending configuration:\n{str(message)}')

        self.sock.sendto(message.to_bytes(), NETWORK)

        while True:
            try:
                data, address = self.sock.recvfrom(MAX_PACKET_LENGTH)
                message = Message.from_bytes(data)

                if message.source == self.mac:
                    continue  # Skip our own messages

                self.log.emit(f'Received:\n {str(message)}')
                if message.command is commands.UPDATE_CONFIG_ACK:
                    # We purposefully do not check the payload type
                    # to crash hard if some messed up packet comes our way
                    if message.payload.packet_number == pack_no:
                        return message.payload.code
            except socket.timeout:
                return None
    def do_discovery(self) -> dict:
        """Send a requests for configurations, and return a dictionary of
        {mac address (str): Configuration}"""
        message = Message(source=self.mac,
                          command=commands.REQUEST_CONFIG,
                          payload=b'')
        self.log.emit(f'Doing discovery:\n{str(message)}')
        self.sock.sendto(message.to_bytes(), NETWORK)

        ret = dict()
        while True:
            for _ in range(255):  # TODO: Find a better way to loop
                try:
                    data, address = self.sock.recvfrom(MAX_PACKET_LENGTH)
                except socket.timeout:
                    return ret
                message = Message.from_bytes(data)

                if message.source == self.mac:
                    continue  # Skip our own messages

                self.log.emit(f'Received:\n{str(message)}')
                if message.command is commands.SEND_CONFIG:
                    ret[message.source] = message.payload
            return ret
Exemple #6
0
def test_check_payload_length():
    Message(source="00:0c:c6:69:13:2d",
            packet_number=1,
            command=commands.UPDATE_CONFIG_ACK,
            destination="00:22:19:06:bf:58",
            payload=CONFIGURATION)

    Message(source="00:0c:c6:69:13:2d",
            packet_number=1,
            command=commands.UPDATE_CONFIG_ACK,
            destination="00:22:19:06:bf:58",
            payload=ACK)

    Message(source="00:0c:c6:69:13:2d",
            packet_number=1,
            command=commands.UPDATE_CONFIG_ACK,
            destination="00:22:19:06:bf:58",
            payload=b'')

    with pytest.raises(ValueError):
        Message(source="00:0c:c6:69:13:2d",
                packet_number=1,
                command=commands.UPDATE_CONFIG_ACK,
                destination="00:22:19:06:bf:58",
                payload=b'\x00\xFF')

    with pytest.raises(AssertionError):
        Message.from_bytes(MALFORMATTED_MESSAGE)
Exemple #7
0
def test_message_config_payload():
    p = Configuration.from_bytes(CONFIGURATION)
    p.reboot = True
    source = "00:0c:c6:69:13:2d"
    destination = "00:de:ad:be:ef:00"
    command = commands.UPDATE_CONFIG

    m = Message(source=source,
                command=command,
                destination=destination,
                payload=p)

    mm = Message(source=source,
                 packet_number=1,
                 command=command,
                 destination=destination,
                 payload=CONFIGURATION)
    mm.payload.reboot = True

    mmm = Message(source=source,
                  packet_number=1,
                  command=command,
                  destination=destination,
                  payload=b'')
    mmm.payload = CONFIGURATION
    mmm.payload.reboot = True

    mmmm = Message(source=source,
                   packet_number=1,
                   command=command,
                   destination=destination,
                   payload=b'')
    mmmm.payload = p

    assert m == mm
    assert mm == mmm
    assert mmm == mmmm
Exemple #8
0
def main():
    # Create the socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF,
                    socket.inet_aton('0.0.0.0'))  # check all interfaces

    mreq = struct.pack('4sL', socket.inet_aton(MULTICAST_ADDR),
                       socket.INADDR_ANY)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

    # Bind to the server address
    sock.bind(('', MULTICAST_PORT))

    with sock:
        try:
            while True:
                print('\nWaiting for messages...')
                data, address = sock.recvfrom(MAX_PACKET_LENGTH)
                print(Message.from_bytes(data))
        except KeyboardInterrupt:
            pass
Exemple #9
0
def test_parse_reply():
    m = Message.from_bytes(REPLY)
    assert m.to_bytes() == REPLY
    assert m == REPLY

    expected = """[header]
    [source]       = 00:0c:c6:69:13:2d
    [target count] = 1
    [packet no]    = 0
    [command]      = SEND_CONFIG [0x3]
    [payload len]  = 56
[destination] = 00:22:19:06:bf:58
[payload] = [configuration]
                [target id]   = 00:0c:c6:69:13:2d
                [ip address]  = 172.24.155.222
                [broadcast]   = 172.24.155.255
                [netmask]     = 255.255.255.0
                [gateway]     = 172.24.155.99
                [mac address] = 00:0c:c6:69:13:2d
                [flags]       =
                [hostname]    = iceeu4
[checksum] = 0xd2357b3"""

    assert str(m) == expected
print(f'Working with {mac} and {hostname}, no ack: {nack}')

# Create a mock configuration to send ipassign
config = Configuration(
    target_id=mac,  # will be overwritten in due time
    ip='172.24.155.105',
    bc='172.24.155.25',
    nm='255.255.255.0',
    gw='172.24.155.99',
    mac=mac,
    hostname=hostname)

message = Message(
    source=mac,
    packet_number=0,
    destination=mac,  # will be overwritten in due time
    command=commands.SEND_CONFIG,
    payload=config)

try:
    while True:
        print('\nwaiting to receive message')
        data, address = sock.recvfrom(MAX_PACKET_LENGTH)
        m = Message.from_bytes(data)
        if m.source == mac:
            print('--- Our reply:')
            print('            ', end='')
            print('\n            '.join([line for line in str(m).split('\n')]))
            print('--------------')
        else:
            print(m)
Exemple #11
0
def test_serialisation():
    m = Message.from_bytes(PACKET)
    assert m.to_bytes() == PACKET
Exemple #12
0
def test_deserialisation():
    m = Message.from_bytes(PACKET)
    assert isinstance(m, Message)

    with pytest.raises(AssertionError):  # Invalid CRC, due to wrong MAC
        packet = b'xf' + PACKET[2:]
        Message.from_bytes(packet)

    with pytest.raises(TypeError):  # Invalid input
        Message.from_bytes("I'm a string!")

    with pytest.raises(AssertionError):  # Corrupted CRC
        packet = PACKET[:-2] + b'xf'
        Message.from_bytes(packet)

    with pytest.raises(AssertionError):  # Payload length mismatch
        packet = b'xE\xc4\xf7\x8fH\x00\x00\x01\x00\x02\x00\xff\xff\xce\x9dB\xf6'  # noqa
        Message.from_bytes(packet)

    with pytest.raises(ValueError):  # Input too short
        packet = b'xE\xc4\xf7\x8fH\x00\x00\x01\x00\x02\xff\xff\x00'
        Message.from_bytes(packet)

    with pytest.raises(ValueError):  # Input too short
        Message.from_bytes(b'xE\xc4\xf7\x8fH\x00\x00\x01\x00')

    with pytest.raises(ValueError):  # Input too long
        Message.from_bytes(b'x' * 1048)