Exemplo n.º 1
0
 def __init__(self, channel, symbols):
     self.channel = channel
     self.symbols = symbols
     self.memory = Memory()
     self.specializer = MessageSpecializer(memory=self.memory)
     self.parser = MessageParser(memory=self.memory)
     self.flow_parser = FlowParser(memory=self.memory)
Exemplo n.º 2
0
 def __init__(self, channel, symbols):
     self.channel = channel
     self.symbols = symbols
     self.memory = Memory()
     self.specializer = MessageSpecializer(memory=self.memory)
     self.parser = MessageParser(memory=self.memory)
     self.flow_parser = FlowParser(memory=self.memory)
Exemplo n.º 3
0
    def execute(self):
        """Execute the alignment of data following specified field
        """
        if self.data is None:
            raise TypeError("Data cannot be None")
        if self.field is None:
            raise TypeError("Field cannot be None")

        # Aligned messages are stored in a MatrixList for better display
        result = MatrixList()

        # We retrieve all the leaf fields of the root of the provided field
        rootLeafFields = self.__root.getLeafFields(depth=self.depth)

        # if self.__root != self.field:
        #     targetedFieldLeafFields = self.field.getLeafFields(depth=self.depth)
        # else:
        targetedFieldLeafFields = rootLeafFields

        result.headers = [str(field.name) for field in targetedFieldLeafFields]
        from netzob.Model.Vocabulary.Domain.Parser.MessageParser import MessageParser
        for d in self.data:
            mp = MessageParser()
            # alignedMsg = mp.parseRaw(TypeConverter.convert(d, HexaString, Raw), targetedFieldLeafFields)
            alignedMsg = next(mp.parseRaw(d, targetedFieldLeafFields))

            alignedEncodedMsg = []
            for ifield, currentField in enumerate(targetedFieldLeafFields):

                # now we apply encoding and mathematic functions
                fieldValue = alignedMsg[ifield]

                if self.encoded and len(
                        list(currentField.encodingFunctions.values())) > 0:
                    for encodingFunction in list(
                            currentField.encodingFunctions.values()):
                        fieldValue = encodingFunction.encode(fieldValue)
                else:
                    fieldValue = TypeConverter.convert(fieldValue, BitArray,
                                                       Raw)

                if currentField in self.field.getLeafFields(depth=self.depth):
                    alignedEncodedMsg.append(fieldValue)

            result.append(alignedEncodedMsg)

        return result
Exemplo n.º 4
0
    def _parseFlow_internal(self, data_to_parse_bitarray, symbols, memory):
        """Parses the specified data"""

        if data_to_parse_bitarray is None or len(data_to_parse_bitarray) == 0:
            raise Exception("Nothing to parse")

        for symbol in symbols:
            self._logger.debug("Parsing '{}' with Symbol '{}'".format(
                data_to_parse_bitarray, symbol.name))
            flow_parsing_results = []
            try:
                mp = MessageParser(memory=memory)
                results = mp.parseBitarray(
                    data_to_parse_bitarray.copy(),
                    symbol.getLeafFields(),
                    must_consume_everything=False)

                for parse_result in results:
                    parse_result_len = sum(
                        [len(value) for value in parse_result])

                    remainings_bitarray = data_to_parse_bitarray[
                        parse_result_len:]

                    if len(remainings_bitarray) > 0:
                        self._logger.debug(
                            "Try to parse the remaining data '{}' with another symbol".
                            format(remainings_bitarray))
                        try:
                            child_flow_parsings = self._parseFlow_internal(
                                remainings_bitarray, symbols,
                                memory.duplicate())
                            for child_flow_parsing in child_flow_parsings:
                                flow_parsing_results = [(symbol, parse_result)
                                                        ] + child_flow_parsing

                                yield flow_parsing_results
                        except InvalidParsingPathException:
                            pass
                    else:
                        flow_parsing_results = [(symbol, parse_result)]

                        yield flow_parsing_results

            except InvalidParsingPathException:
                pass
Exemplo n.º 5
0
    def _parseFlow_internal(self, data_to_parse_bitarray, symbols, memory):
        """Parses the specified data"""

        if data_to_parse_bitarray is None or len(data_to_parse_bitarray) == 0:
            raise Exception("Nothing to parse")

        for symbol in symbols:
            self._logger.debug("Parsing '{}' with Symbol '{}'".format(
                data_to_parse_bitarray, symbol.name))
            flow_parsing_results = []
            try:
                mp = MessageParser(memory=memory)
                results = mp.parseBitarray(
                    data_to_parse_bitarray.copy(),
                    symbol._getLeafFields(),
                    must_consume_everything=False)

                for parse_result in results:
                    parse_result_len = sum(
                        [len(value) for value in parse_result])

                    remainings_bitarray = data_to_parse_bitarray[
                        parse_result_len:]

                    if len(remainings_bitarray) > 0:
                        self._logger.debug(
                            "Try to parse the remaining data '{}' with another symbol".
                            format(remainings_bitarray))
                        try:
                            child_flow_parsings = self._parseFlow_internal(
                                remainings_bitarray, symbols,
                                memory.duplicate())
                            for child_flow_parsing in child_flow_parsings:
                                flow_parsing_results = [(symbol, parse_result)
                                                        ] + child_flow_parsing

                                yield flow_parsing_results
                        except InvalidParsingPathException:
                            pass
                    else:
                        flow_parsing_results = [(symbol, parse_result)]

                        yield flow_parsing_results

            except InvalidParsingPathException:
                pass
Exemplo n.º 6
0
class AbstractionLayer(object):
    """An abstraction layer specializes a symbol into a message before
    emitting it and on the other way, abstracts a received message
    into a symbol.

    >>> from netzob.all import *
    >>> symbol = Symbol([Field(b"Hello Zoby !")], name = "Symbol_Hello")
    >>> channelIn = UDPServer(localIP="127.0.0.1", localPort=8889)
    >>> abstractionLayerIn = AbstractionLayer(channelIn, [symbol])
    >>> abstractionLayerIn.openChannel()
    >>> channelOut = UDPClient(remoteIP="127.0.0.1", remotePort=8889)
    >>> abstractionLayerOut = AbstractionLayer(channelOut, [symbol])
    >>> abstractionLayerOut.openChannel()
    >>> abstractionLayerOut.writeSymbol(symbol)
    >>> (receivedSymbol, receivedMessage) = abstractionLayerIn.readSymbol()
    >>> print(receivedSymbol.name)
    Symbol_Hello
    >>> print(receivedMessage)
    b'Hello Zoby !'

    The abstraction layer can also handle a message flow.

    >>> symbolflow = Symbol([Field(b"Hello Zoby !Whats up ?")], name = "Symbol Flow")
    >>> symbol1 = Symbol([Field(b"Hello Zoby !")], name = "Symbol_Hello")
    >>> symbol2 = Symbol([Field(b"Whats up ?")], name = "Symbol_WUP")
    >>> channelIn = UDPServer(localIP="127.0.0.1", localPort=8889)
    >>> abstractionLayerIn = AbstractionLayer(channelIn, [symbol1, symbol2])
    >>> abstractionLayerIn.openChannel()
    >>> channelOut = UDPClient(remoteIP="127.0.0.1", remotePort=8889)
    >>> abstractionLayerOut = AbstractionLayer(channelOut, [symbolflow])
    >>> abstractionLayerOut.openChannel()
    >>> abstractionLayerOut.writeSymbol(symbolflow)
    >>> (receivedSymbols, receivedMessage) = abstractionLayerIn.readSymbols()
    >>> print(receivedSymbols)
    [Symbol_Hello, Symbol_WUP]

    """
    def __init__(self, channel, symbols):
        self.channel = channel
        self.symbols = symbols
        self.memory = Memory()
        self.specializer = MessageSpecializer(memory=self.memory)
        self.parser = MessageParser(memory=self.memory)
        self.flow_parser = FlowParser(memory=self.memory)

    @typeCheck(Symbol)
    def writeSymbol(self, symbol):
        """Write the specified symbol on the communication channel
        after specializing it into a contextualized message.

        :param symbol: the symbol to write on the channel
        :type symbol: :class:`netzob.Model.Vocabulary.Symbol.Symbol`
        :raise TypeError if parameter is not valid and Exception if an exception occurs.
        """
        if symbol is None:
            raise TypeError(
                "The symbol to write on the channel cannot be None")

        self._logger.debug("Specializing symbol '{0}' (id={1}).".format(
            symbol.name, symbol.id))

        dataBin = self.specializer.specializeSymbol(symbol).generatedContent

        self.memory = self.specializer.memory
        self.parser.memory = self.memory
        data = TypeConverter.convert(dataBin, BitArray, Raw)

        self.channel.write(data)
        self._logger.debug("Writing to commnunication channel done..")

    @typeCheck(int)
    def readSymbols(self, timeout=EmptySymbol.defaultReceptionTimeout()):
        """Read from the abstraction layer a flow and abstract it with one or more consecutive symbols
        
        The timeout parameter represents the amount of time (in millisecond) above which
        no reception of a message triggers the reception of an  :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None
        or to a negative value means it always wait for the reception of a message.

        :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`
        :type timeout: :class:`int`
        :raise TypeError if the parameter is not valid and Exception if an error occurs.
        """

        self._logger.debug("Reading data from communication channel...")
        data = self.channel.read(timeout=timeout)
        self._logger.debug("Received : {}".format(repr(data)))

        symbols = []

        # if we read some bytes, we try to abstract them
        if len(data) > 0:
            try:
                symbols_and_data = self.flow_parser.parseFlow(
                    RawMessage(data), self.symbols)
                for (symbol, alignment) in symbols_and_data:
                    symbols.append(symbol)
            except Exception as e:
                self._logger.error(e)

            if len(symbols) > 0:
                self.memory = self.flow_parser.memory
                self.specializer.memory = self.memory
        else:
            symbols.append(EmptySymbol())

        if len(symbols) == 0 and len(data) > 0:
            msg = RawMessage(data)
            symbols.append(UnknownSymbol(message=msg))

        return (symbols, data)

    @typeCheck(int)
    def readSymbol(self, timeout=EmptySymbol.defaultReceptionTimeout()):
        """Read from the abstraction layer a message and abstract it
        into a message.
        The timeout parameter represents the amount of time (in millisecond) above which
        no reception of a message triggers the reception of an  :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None
        or to a negative value means it always wait for the reception of a message.

        :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`
        :type timeout: :class:`int`
        :raise TypeError if the parameter is not valid and Exception if an error occurs.
        """

        self._logger.debug("Reading data from communication channel...")
        data = self.channel.read(timeout=timeout)
        self._logger.debug("Received : {}".format(repr(data)))

        symbol = None

        # if we read some bytes, we try to abstract them
        if len(data) > 0:
            for potential in self.symbols:
                try:
                    self.parser.parseMessage(RawMessage(data), potential)
                    symbol = potential
                    self.memory = self.parser.memory
                    self.specializer.memory = self.memory
                    break
                except Exception:
                    symbol = None

        if symbol is None and len(data) > 0:
            msg = RawMessage(data)
            symbol = UnknownSymbol(message=msg)
        elif symbol is None and len(data) == 0:
            symbol = EmptySymbol()

        return (symbol, data)

    def openChannel(self):
        self.channel.open()
        self._logger.debug("Communication channel opened.")

    def closeChannel(self):
        self.channel.close()
        self._logger.debug("Communication channel close.")

    def reset(self):
        self._logger.debug("Reseting abstraction layer")
        self.memory = Memory()
        self.specializer = MessageSpecializer(memory=self.memory)
        self.parser = MessageParser(memory=self.memory)
        self.flow_parser = FlowParser(memory=self.memory)
Exemplo n.º 7
0
 def reset(self):
     self._logger.debug("Reseting abstraction layer")
     self.memory = Memory()
     self.specializer = MessageSpecializer(memory=self.memory)
     self.parser = MessageParser(memory=self.memory)
     self.flow_parser = FlowParser(memory=self.memory)
Exemplo n.º 8
0
class AbstractionLayer(object):
    """An abstraction layer specializes a symbol into a message before
    emitting it and on the other way, abstracts a received message
    into a symbol.

    >>> from netzob.all import *
    >>> symbol = Symbol([Field(b"Hello Zoby !")], name = "Symbol_Hello")
    >>> channelIn = UDPServer(localIP="127.0.0.1", localPort=8889)
    >>> abstractionLayerIn = AbstractionLayer(channelIn, [symbol])
    >>> abstractionLayerIn.openChannel()
    >>> channelOut = UDPClient(remoteIP="127.0.0.1", remotePort=8889)
    >>> abstractionLayerOut = AbstractionLayer(channelOut, [symbol])
    >>> abstractionLayerOut.openChannel()
    >>> abstractionLayerOut.writeSymbol(symbol)
    12
    >>> (receivedSymbol, receivedMessage) = abstractionLayerIn.readSymbol()
    >>> print(receivedSymbol.name)
    Symbol_Hello
    >>> print(receivedMessage)
    b'Hello Zoby !'

    The abstraction layer can also handle a message flow.

    >>> symbolflow = Symbol([Field(b"Hello Zoby !Whats up ?")], name = "Symbol Flow")
    >>> symbol1 = Symbol([Field(b"Hello Zoby !")], name = "Symbol_Hello")
    >>> symbol2 = Symbol([Field(b"Whats up ?")], name = "Symbol_WUP")
    >>> channelIn = UDPServer(localIP="127.0.0.1", localPort=8889)
    >>> abstractionLayerIn = AbstractionLayer(channelIn, [symbol1, symbol2])
    >>> abstractionLayerIn.openChannel()
    >>> channelOut = UDPClient(remoteIP="127.0.0.1", remotePort=8889)
    >>> abstractionLayerOut = AbstractionLayer(channelOut, [symbolflow])
    >>> abstractionLayerOut.openChannel()
    >>> abstractionLayerOut.writeSymbol(symbolflow)
    22
    >>> (receivedSymbols, receivedMessage) = abstractionLayerIn.readSymbols()
    >>> print(receivedSymbols)
    [Symbol_Hello, Symbol_WUP]

    """

    def __init__(self, channel, symbols):
        self.channel = channel
        self.symbols = symbols
        self.memory = Memory()
        self.specializer = MessageSpecializer(memory=self.memory)
        self.parser = MessageParser(memory=self.memory)
        self.flow_parser = FlowParser(memory=self.memory)

    @typeCheck(Symbol)
    def writeSymbol(self, symbol, rate=None, duration=None, presets=None):
        """Write the specified symbol on the communication channel
        after specializing it into a contextualized message.

        :param symbol: the symbol to write on the channel
        :type symbol: :class:`netzob.Model.Vocabulary.Symbol.Symbol`

        :param rate: specifies the bandwidth in octets to respect durring traffic emission (should be used with duration= parameter)
        :type rate: int

        :param duration: tells how much seconds the symbol is continuously written on the channel
        :type duration: int

        :param presets: specifies how to parameterize the emitted symbol
        :type presets: dict

        :raise TypeError if parameter is not valid and Exception if an exception occurs.

        """

        if symbol is None:
            raise TypeError(
                "The symbol to write on the channel cannot be None")

        len_data = 0
        if duration is None:
            len_data = self._writeSymbol(symbol, presets=presets)
        else:

            t_start = time.time()
            t_elapsed = 0
            t_delta = 0
            while True:

                t_elapsed = time.time() - t_start
                if t_elapsed > duration:
                    break

                # Specialize the symbol and send it over the channel
                len_data += self._writeSymbol(symbol, presets=presets)

                if rate is None:
                    t_tmp = t_elapsed
                    t_elapsed = time.time() - t_start
                    t_delta += t_elapsed - t_tmp
                else:
                    # Wait some time to that we follow a specific rate
                    while True:
                        t_tmp = t_elapsed
                        t_elapsed = time.time() - t_start
                        t_delta += t_elapsed - t_tmp

                        if (len_data / t_elapsed) > rate:
                            time.sleep(0.001)
                        else:
                            break

                # Show some log every seconds
                if t_delta > 1:
                    t_delta = 0
                    self._logger.debug("Rate rule: {} ko/s, current rate: {} ko/s, sent data: {} ko, nb seconds elapsed: {}".format(round(rate / 1024, 2),
                                                                                                                                    round((len_data / t_elapsed) / 1024, 2),
                                                                                                                                    round(len_data / 1024, 2),
                                                                                                                                    round(t_elapsed, 2)))
        return len_data

    def _writeSymbol(self, symbol, presets=None):
        """Write the specified symbol on the communication channel after
        specializing it into a contextualized message.

        :param symbol: the symbol to write on the channel
        :type symbol: :class:`netzob.Model.Vocabulary.Symbol.Symbol`

        :param presets: specifies how to parameterize the emitted symbol
        :type presets: dict

        :raise TypeError if parameter is not valid and Exception if an exception occurs.

        """

        self._logger.debug("Specializing symbol '{0}' (id={1}).".format(
            symbol.name, symbol.id))

        self.specializer.presets = presets
        dataBin = self.specializer.specializeSymbol(symbol).generatedContent
        self.specializer.presets = None

        self.memory = self.specializer.memory
        self.parser.memory = self.memory
        data = TypeConverter.convert(dataBin, BitArray, Raw)

        len_data = self.channel.write(data)
        self._logger.debug("Writing {} octets to commnunication channel done..".format(len_data))
        return len_data

    @typeCheck(int)
    def readSymbols(self, timeout=EmptySymbol.defaultReceptionTimeout()):
        """Read from the abstraction layer a flow and abstract it with one or more consecutive symbols
        
        The timeout parameter represents the amount of time (in millisecond) above which
        no reception of a message triggers the reception of an  :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None
        or to a negative value means it always wait for the reception of a message.

        :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`
        :type timeout: :class:`int`
        :raise TypeError if the parameter is not valid and Exception if an error occurs.
        """

        self._logger.debug("Reading data from communication channel...")
        data = self.channel.read(timeout=timeout)
        self._logger.debug("Received : {}".format(repr(data)))

        symbols = []

        # if we read some bytes, we try to abstract them
        if len(data) > 0:
            try:
                symbols_and_data = self.flow_parser.parseFlow(
                    RawMessage(data), self.symbols)
                for (symbol, alignment) in symbols_and_data:
                    symbols.append(symbol)
            except Exception as e:
                self._logger.error(e)

            if len(symbols) > 0:
                self.memory = self.flow_parser.memory
                self.specializer.memory = self.memory
        else:
            symbols.append(EmptySymbol())

        if len(symbols) == 0 and len(data) > 0:
            msg = RawMessage(data)
            symbols.append(UnknownSymbol(message=msg))

        return (symbols, data)

    @typeCheck(int)
    def readSymbol(self, timeout=EmptySymbol.defaultReceptionTimeout()):
        """Read from the abstraction layer a message and abstract it
        into a message.
        The timeout parameter represents the amount of time (in millisecond) above which
        no reception of a message triggers the reception of an  :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None
        or to a negative value means it always wait for the reception of a message.

        :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`
        :type timeout: :class:`int`
        :raise TypeError if the parameter is not valid and Exception if an error occurs.
        """

        self._logger.debug("Reading data from communication channel...")
        data = self.channel.read(timeout=timeout)
        self._logger.debug("Received : {}".format(repr(data)))

        symbol = None

        # if we read some bytes, we try to abstract them
        if len(data) > 0:
            for potential in self.symbols:
                try:
                    self.parser.parseMessage(RawMessage(data), potential)
                    symbol = potential
                    self.memory = self.parser.memory
                    self.specializer.memory = self.memory
                    break
                except Exception:
                    symbol = None

        if symbol is None and len(data) > 0:
            msg = RawMessage(data)
            symbol = UnknownSymbol(message=msg)
        elif symbol is None and len(data) == 0:
            symbol = EmptySymbol()

        return (symbol, data)

    def openChannel(self):
        self.channel.open()
        self._logger.debug("Communication channel opened.")

    def closeChannel(self):
        self.channel.close()
        self._logger.debug("Communication channel close.")

    def reset(self):
        self._logger.debug("Reseting abstraction layer")
        self.memory = Memory()
        self.specializer = MessageSpecializer(memory=self.memory)
        self.parser = MessageParser(memory=self.memory)
        self.flow_parser = FlowParser(memory=self.memory)
Exemplo n.º 9
0
 def reset(self):
     self._logger.debug("Reseting abstraction layer")
     self.memory = Memory()
     self.specializer = MessageSpecializer(memory=self.memory)
     self.parser = MessageParser(memory=self.memory)
     self.flow_parser = FlowParser(memory=self.memory)
Exemplo n.º 10
0
class AbstractionLayer(object):
    """An abstraction layer specializes a symbol into a message before
    emitting it and on the other way, abstracts a received message
    into a symbol.

    >>> from netzob.all import *
    >>> symbol = Symbol([Field(b"Hello Zoby !")], name = "Symbol_Hello")
    >>> channelIn = UDPServer(localIP="127.0.0.1", localPort=8889)
    >>> abstractionLayerIn = AbstractionLayer(channelIn, [symbol])
    >>> abstractionLayerIn.openChannel()
    >>> channelOut = UDPClient(remoteIP="127.0.0.1", remotePort=8889)
    >>> abstractionLayerOut = AbstractionLayer(channelOut, [symbol])
    >>> abstractionLayerOut.openChannel()
    >>> abstractionLayerOut.writeSymbol(symbol)
    12
    >>> (receivedSymbol, receivedMessage) = abstractionLayerIn.readSymbol()
    >>> print(receivedSymbol.name)
    Symbol_Hello
    >>> print(receivedMessage)
    b'Hello Zoby !'

    The abstraction layer can also handle a message flow.

    >>> symbolflow = Symbol([Field(b"Hello Zoby !Whats up ?")], name = "Symbol Flow")
    >>> symbol1 = Symbol([Field(b"Hello Zoby !")], name = "Symbol_Hello")
    >>> symbol2 = Symbol([Field(b"Whats up ?")], name = "Symbol_WUP")
    >>> channelIn = UDPServer(localIP="127.0.0.1", localPort=8889)
    >>> abstractionLayerIn = AbstractionLayer(channelIn, [symbol1, symbol2])
    >>> abstractionLayerIn.openChannel()
    >>> channelOut = UDPClient(remoteIP="127.0.0.1", remotePort=8889)
    >>> abstractionLayerOut = AbstractionLayer(channelOut, [symbolflow])
    >>> abstractionLayerOut.openChannel()
    >>> abstractionLayerOut.writeSymbol(symbolflow)
    22
    >>> (receivedSymbols, receivedMessage) = abstractionLayerIn.readSymbols()
    >>> print(receivedSymbols)
    [Symbol_Hello, Symbol_WUP]

    """
    def __init__(self, channel, symbols):
        self.channel = channel
        self.symbols = symbols
        self.memory = Memory()
        self.specializer = MessageSpecializer(memory=self.memory)
        self.parser = MessageParser(memory=self.memory)
        self.flow_parser = FlowParser(memory=self.memory)

    @typeCheck(Symbol)
    def writeSymbol(self, symbol, rate=None, duration=None, presets=None):
        """Write the specified symbol on the communication channel
        after specializing it into a contextualized message.

        :param symbol: the symbol to write on the channel
        :type symbol: :class:`netzob.Model.Vocabulary.Symbol.Symbol`

        :param rate: specifies the bandwidth in octets to respect durring traffic emission (should be used with duration= parameter)
        :type rate: int

        :param duration: tells how much seconds the symbol is continuously written on the channel
        :type duration: int

        :param presets: specifies how to parameterize the emitted symbol
        :type presets: dict

        :raise TypeError if parameter is not valid and Exception if an exception occurs.

        """

        if symbol is None:
            raise TypeError(
                "The symbol to write on the channel cannot be None")

        len_data = 0
        if duration is None:
            len_data = self._writeSymbol(symbol, presets=presets)
        else:

            t_start = time.time()
            t_elapsed = 0
            t_delta = 0
            while True:

                t_elapsed = time.time() - t_start
                if t_elapsed > duration:
                    break

                # Specialize the symbol and send it over the channel
                len_data += self._writeSymbol(symbol, presets=presets)

                if rate is None:
                    t_tmp = t_elapsed
                    t_elapsed = time.time() - t_start
                    t_delta += t_elapsed - t_tmp
                else:
                    # Wait some time to that we follow a specific rate
                    while True:
                        t_tmp = t_elapsed
                        t_elapsed = time.time() - t_start
                        t_delta += t_elapsed - t_tmp

                        if (len_data / t_elapsed) > rate:
                            time.sleep(0.001)
                        else:
                            break

                # Show some log every seconds
                if t_delta > 1:
                    t_delta = 0
                    self._logger.debug(
                        "Rate rule: {} ko/s, current rate: {} ko/s, sent data: {} ko, nb seconds elapsed: {}"
                        .format(round(rate / 1024, 2),
                                round((len_data / t_elapsed) / 1024, 2),
                                round(len_data / 1024, 2), round(t_elapsed,
                                                                 2)))
        return len_data

    def _writeSymbol(self, symbol, presets=None):
        """Write the specified symbol on the communication channel after
        specializing it into a contextualized message.

        :param symbol: the symbol to write on the channel
        :type symbol: :class:`netzob.Model.Vocabulary.Symbol.Symbol`

        :param presets: specifies how to parameterize the emitted symbol
        :type presets: dict

        :raise TypeError if parameter is not valid and Exception if an exception occurs.

        """

        self._logger.debug("Specializing symbol '{0}' (id={1}).".format(
            symbol.name, symbol.id))

        self.specializer.presets = presets
        dataBin = self.specializer.specializeSymbol(symbol).generatedContent
        self.specializer.presets = None

        self.memory = self.specializer.memory
        self.parser.memory = self.memory
        data = TypeConverter.convert(dataBin, BitArray, Raw)

        len_data = self.channel.write(data)
        self._logger.debug(
            "Writing {} octets to commnunication channel done..".format(
                len_data))
        return len_data

    @typeCheck(int)
    def readSymbols(self, timeout=EmptySymbol.defaultReceptionTimeout()):
        """Read from the abstraction layer a flow and abstract it with one or more consecutive symbols
        
        The timeout parameter represents the amount of time (in millisecond) above which
        no reception of a message triggers the reception of an  :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None
        or to a negative value means it always wait for the reception of a message.

        :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`
        :type timeout: :class:`int`
        :raise TypeError if the parameter is not valid and Exception if an error occurs.
        """

        self._logger.debug("Reading data from communication channel...")
        data = self.channel.read(timeout=timeout)
        self._logger.debug("Received : {}".format(repr(data)))

        symbols = []

        # if we read some bytes, we try to abstract them
        if len(data) > 0:
            try:
                symbols_and_data = self.flow_parser.parseFlow(
                    RawMessage(data), self.symbols)
                for (symbol, alignment) in symbols_and_data:
                    symbols.append(symbol)
            except Exception as e:
                self._logger.error(e)

            if len(symbols) > 0:
                self.memory = self.flow_parser.memory
                self.specializer.memory = self.memory
        else:
            symbols.append(EmptySymbol())

        if len(symbols) == 0 and len(data) > 0:
            msg = RawMessage(data)
            symbols.append(UnknownSymbol(message=msg))

        return (symbols, data)

    @typeCheck(int)
    def readSymbol(self, timeout=EmptySymbol.defaultReceptionTimeout()):
        """Read from the abstraction layer a message and abstract it
        into a message.
        The timeout parameter represents the amount of time (in millisecond) above which
        no reception of a message triggers the reception of an  :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`. If timeout set to None
        or to a negative value means it always wait for the reception of a message.

        :keyword timeout: the time above which no reception of message triggers the reception of an :class:`netzob.Model.Vocabulary.EmptySymbol.EmptySymbol`
        :type timeout: :class:`int`
        :raise TypeError if the parameter is not valid and Exception if an error occurs.
        """

        self._logger.debug("Reading data from communication channel...")
        data = self.channel.read(timeout=timeout)
        self._logger.debug("Received : {}".format(repr(data)))

        symbol = None

        # if we read some bytes, we try to abstract them
        if len(data) > 0:
            for potential in self.symbols:
                try:
                    self.parser.parseMessage(RawMessage(data), potential)
                    symbol = potential
                    self.memory = self.parser.memory
                    self.specializer.memory = self.memory
                    break
                except Exception:
                    symbol = None

        if symbol is None and len(data) > 0:
            msg = RawMessage(data)
            symbol = UnknownSymbol(message=msg)
        elif symbol is None and len(data) == 0:
            symbol = EmptySymbol()

        return (symbol, data)

    def openChannel(self):
        self.channel.open()
        self._logger.debug("Communication channel opened.")

    def closeChannel(self):
        self.channel.close()
        self._logger.debug("Communication channel close.")

    def reset(self):
        self._logger.debug("Reseting abstraction layer")
        self.memory = Memory()
        self.specializer = MessageSpecializer(memory=self.memory)
        self.parser = MessageParser(memory=self.memory)
        self.flow_parser = FlowParser(memory=self.memory)