Example #1
0
    def __init__(self,
                 incoming_message: Message,
                 received_over_multicast: bool,
                 received_over_tcp: bool = False,
                 allow_rapid_commit: bool = False,
                 marks: Iterable[str] = None):

        self.incoming_message = incoming_message
        """The incoming message including the relay chain"""

        self.received_over_multicast = received_over_multicast
        """A flag indicating whether the client used multicast to contact the server"""

        self.received_over_tcp = received_over_tcp
        """A flag indicating whether the client used TCP to contact the server"""

        self.allow_unicast = False
        """Allow the client use unicast to contact the server. Set to True by handlers"""

        self.allow_rapid_commit = allow_rapid_commit
        """Allow rapid commit? May be set to True on creation, may be set to False by handlers, not vice versa"""

        # Convenience properties for easy access to the request and chain without having to walk the chain every time
        self.request = None
        """The incoming request without the relay messages"""

        self.incoming_relay_messages = []
        """The chain of relay messages starting with the one closest to the client"""

        self.request, self.incoming_relay_messages = split_relay_chain(
            incoming_message)

        # Check that TCP connections don't include any further relay messages
        if self.received_over_tcp and len(self.incoming_relay_messages) > 1:
            raise ValueError("Relayed message on TCP connection, ignoring")

        self.responses = MessagesList()
        """This is where we keep our responses, potentially more than one"""

        self.outgoing_relay_messages = None
        """This is where the user puts the reply relay chain by calling :meth:`create_outgoing_relay_messages`"""

        # Extra state to track handling of the message
        self.handled_options = []
        """A list of options from the request that have been handled, only applies to IA type options"""

        self.marks = set(marks or [])
        """A set of marks that have been applied to this message"""

        self.handler_data = {}
        """A place for handlers to store data related to this transaction"""
    def __init__(self, incoming_message: Message, received_over_multicast: bool, received_over_tcp: bool = False,
                 allow_rapid_commit: bool = False, marks: Iterable[str] = None):

        self.incoming_message = incoming_message
        """The incoming message including the relay chain"""

        self.received_over_multicast = received_over_multicast
        """A flag indicating whether the client used multicast to contact the server"""

        self.received_over_tcp = received_over_tcp
        """A flag indicating whether the client used TCP to contact the server"""

        self.allow_unicast = False
        """Allow the client use unicast to contact the server. Set to True by handlers"""

        self.allow_rapid_commit = allow_rapid_commit
        """Allow rapid commit? May be set to True on creation, may be set to False by handlers, not vice versa"""

        # Convenience properties for easy access to the request and chain without having to walk the chain every time
        self.request = None
        """The incoming request without the relay messages"""

        self.incoming_relay_messages = []
        """The chain of relay messages starting with the one closest to the client"""

        self.request, self.incoming_relay_messages = split_relay_chain(incoming_message)

        # Check that TCP connections don't include any further relay messages
        if self.received_over_tcp and len(self.incoming_relay_messages) > 1:
            raise ValueError("Relayed message on TCP connection, ignoring")

        self.responses = MessagesList()
        """This is where we keep our responses, potentially more than one"""

        self.outgoing_relay_messages = None
        """This is where the user puts the reply relay chain by calling :meth:`create_outgoing_relay_messages`"""

        # Extra state to track handling of the message
        self.handled_options = []
        """A list of options from the request that have been handled, only applies to IA type options"""

        self.marks = set(marks or [])
        """A set of marks that have been applied to this message"""

        self.handler_data = {}
        """A place for handlers to store data related to this transaction"""
Example #3
0
    def __init__(self,
                 incoming_message: Message,
                 received_over_multicast: bool,
                 allow_rapid_commit: bool = False,
                 marks: Iterable[str] = None):

        self.incoming_message = incoming_message
        """The incoming message including the relay chain"""

        self.received_over_multicast = received_over_multicast
        """A flag indicating whether the client used multicast to contact the server"""

        self.allow_unicast = False
        """Allow the client use unicast to contact the server. Set to True by handlers"""

        self.allow_rapid_commit = allow_rapid_commit
        """Allow rapid commit? May be set to True on creation, may be set to False by handlers, not vice versa"""

        # Convenience properties for easy access to the request and chain without having to walk the chain every time
        self.request = None
        """The incoming request without the relay messages"""

        self.incoming_relay_messages = []
        """The chain of relay messages starting with the one closest to the client"""

        self.request, self.incoming_relay_messages = split_relay_chain(
            incoming_message)

        self.response = None
        """This is where the user puts the response :class:`.ClientServerMessage`"""

        self.outgoing_relay_messages = None
        """This is where the user puts the reply relay chain by calling :meth:`create_outgoing_relay_messages`"""

        # Extra state to track handling of the message
        self.handled_options = []
        """A list of options from the request that have been handled, only applies to IA type options"""

        self.marks = set(marks or [])
        """A set of marks that have been applied to this message"""

        self.handler_data = {}
        """A place for handlers to store data related to this transaction"""
    def get_transaction_info(message: DHCPKafkaMessage) -> Dict[str, object]:
        """
        Extract interesting data from the incoming message

        :param message: The Kafka DHCP message
        :return: A dictionary of stuff
        """
        # Split the message into usable blocks
        request, incoming_relay_messages = split_relay_chain(message.message_in)

        # Get the DUID and create representations for in the database
        duid_obj = request.get_option_of_type(ClientIdOption).duid
        duid = '0x' + codecs.encode(duid_obj.save(), 'hex').decode('ascii')

        # Get the link-local address of the client
        link_local = str(incoming_relay_messages[0].peer_address)

        # Get the Interface ID and create representation for in the database
        interface_id_obj = incoming_relay_messages[0].get_option_of_type(InterfaceIdOption)
        if interface_id_obj:
            try:
                interface_id = interface_id_obj.interface_id.decode('ascii')
            except ValueError:
                interface_id = '0x' + codecs.encode(interface_id_obj.interface_id, 'hex').decode('ascii')
        else:
            interface_id = ''

        # Get the Remote ID and create representation for in the database
        remote_id_obj = incoming_relay_messages[0].get_option_of_type(RemoteIdOption)
        if remote_id_obj:
            try:
                remote_id = '{}:{}'.format(remote_id_obj.enterprise_number, remote_id_obj.remote_id.decode('ascii'))
            except ValueError:
                remote_id = '{}:0x{}'.format(remote_id_obj.enterprise_number,
                                             codecs.encode(remote_id_obj.remote_id, 'hex').decode('ascii'))
        else:
            remote_id = ''

        # Get the request type
        request_type = request.__class__.__name__
        if request_type.endswith('Message'):
            request_type = request_type[:-7]

        # Get the response type
        response = message.message_out
        while isinstance(response, RelayReplyMessage):
            response = response.relayed_message

        if isinstance(response, ClientServerMessage):
            response_type = response.__class__.__name__
        else:
            response_type = None

        return {
            'duid': duid,
            'interface_id': interface_id,
            'remote_id': remote_id,
            'link_local': link_local,
            'request_type': request_type,
            'response_type': response_type,
        }