Пример #1
0
    def set_packet(self, packet_bbuf):
        super().set_packet(packet_bbuf)
        self.all_tiles = TileList(self.rule, packet_bbuf, self.l2word)
        # XXX
        # check whether the size of the last tile is less than L2 word
        # AND the tile number is zero
        # because draft-17 doesn't specify how to handle it.
        a = self.all_tiles.get_all_tiles()

        if (a[-1]["t-num"] == 0
                and a[-1]["tile"].count_added_bits() < self.l2word):
            raise ValueError(
                "The size {} of the last tile with the tile number 0 must be equal to or greater than L2 word size {}."
                .format(a[-1]["tile"].count_added_bits(), self.l2word))
        # make the bitmap
        #self.bit_list = make_bit_list(self.all_tiles.get_all_tiles(),
        #                              self.rule["FCNSize"],
        #                              frag_msg.get_fcn_all_1(self.rule))
        dprint(
            "----------------------- Fragmentation process -----------------------"
        )
        self.bit_list = make_bit_list(
            self.all_tiles.get_all_tiles(),
            self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN],
            self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_W])
        dprint("bit_list:", self.bit_list)
        for tile in self.all_tiles.get_all_tiles():
            dprint("w: {}, t: {}, sent: {}".format(tile['w-num'],
                                                   tile['t-num'],
                                                   tile['sent']))
        self.all1_send = False
        self.num_of_windows = 0
        for pos in self.bit_list:
            dprint("bitmap: {}, length:{}".format(self.bit_list[pos],
                                                  len(self.bit_list[pos])))
            if len(self.bit_list[pos]) != 0:
                self.num_of_windows += 1
        dprint("number of windows = {}".format(self.num_of_windows))
Пример #2
0
def frag_generic(rule, packet):
    # General configuration
    l2_mtu = 72  # bits
    data_size = 14  # bytes
    SF = 12

    simul_config = {
        "log": True,
    }
    devaddr = b"\xaa\xbb\xcc\xdd"

    set_debug_output(True)
    rm0 = RuleManager()
    rm0.Add(devaddr, dev_info=rule)

    # Message
    packet_bbuf = BitBuffer(packet)
    tiles = TileList(rm0.FindFragmentationRule(devaddr), packet_bbuf)

    for t in tiles.get_all_tiles():
        print(t)

    set_debug_output(False)
    return True
Пример #3
0
    def send_frag(self):
        if self.state == self.ACK_SUCCESS:
            dprint(
                "-----------------------------------------------------------------------"
            )
            return
        dprint(
            "----------------------- Preparing to send a message -----------------------"
        )
        scheduler = self.protocol.system.get_scheduler()
        dprint("{} send_frag!!!!!!!!!!!!!!!!!".format(
            scheduler.get_clock()))  # utime.time()
        dprint("all1_send-> {}, resend -> {}, state -> {}".format(
            self.all1_send, self.resend, self.state))
        dprint("all tiles unsend -> {}".format(self.all_tiles.get_all_tiles()))
        for tile in self.all_tiles.get_all_tiles():
            dprint("w: {}, t: {}, sent: {}".format(tile['w-num'],
                                                   tile['t-num'],
                                                   tile['sent']))
        dprint("")
        # if self.state == self.ACK_FAILURE and self.num_of_windows != 1 and self.number_of_ack_waits <= self.num_of_windows:
        #     #waiting for the acks of the others windows
        #     self.number_of_ack_waits += 1 #wait depends on the number of windows
        #     #set ack_time_out_timer
        #     dprint("waiting for more acks: {}".format(self.number_of_ack_waits))
        #     return

        # get contiguous tiles as many as possible fit in MTU.
        mtu_size = self.protocol.layer2.get_mtu_size()
        window_tiles, nb_remaining_tiles, remaining_size = self.all_tiles.get_tiles(
            mtu_size)
        dprint(
            "----window tiles to send: {}, nb_remaining_tiles: {}, remaining_size: {}"
            .format(window_tiles, nb_remaining_tiles, remaining_size))

        if window_tiles is None and self.resend:
            dprint("no more tiles to resend")
            # how to identify that all tiles are resend and that the ack timeout should be set
            # to wait for tha last ok. It should be set after retransmission of the last fragment
            if self.state == self.ACK_FAILURE and self.event_id_ack_wait_timer is None:
                win = self.last_window_tiles[0][
                    "w-num"] if self.last_window_tiles[0][
                        "w-num"] is not None else 0
                if self.last_window_tiles[0]["t-num"] == 0:
                    win += 1
                schc_frag = frag_msg.frag_sender_tx(self.rule,
                                                    dtag=self.dtag,
                                                    win=win,
                                                    fcn=frag_msg.get_fcn_all_1(
                                                        self.rule),
                                                    mic=self.mic_sent)
                # set ack waiting timer
                args = (
                    schc_frag,
                    win,
                )
                self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                    self.ack_wait_timer, self.ack_timeout, args)
                dprint("*******event id {}".format(
                    self.event_id_ack_wait_timer))
                # if self.all1_send and self.state == self.ACK_FAILURE:
            #     #case when with the bitmap is not possible to identify the missing tile,
            #     #resend ALL-1 messages
            #     # send a SCHC fragment
            #     args = (self.schc_all_1.packet.get_content(), self._session_id[0],
            #     self.event_sent_frag)
            #     dprint("frag sent:", self.schc_all_1.__dict__)
            #     if enable_statsct:
            #         Statsct.set_msg_type("SCHC_ALL_1")
            #         Statsct.set_header_size(frag_msg.get_sender_header_size(self.rule) +
            #             frag_msg.get_mic_size(self.rule))
            #     self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
            #                                     args)
            #     dprint("Sending all-1 beacuse there is an ACK FaILURE but cannot find the missing tiles")
            #     input("")

            # win = self.last_window_tiles[0]["w-num"] if self.last_window_tiles[0]["w-num"] is not None else 0
            # if self.last_window_tiles[0]["t-num"] == 0:
            #     win += 1
            # schc_frag = frag_msg.frag_sender_tx(
            #         self.rule, dtag=self.dtag, win=win,
            #         fcn=frag_msg.get_fcn_all_1(self.rule),
            #         mic=self.mic_sent)
            # set ack waiting timer
            # args = (schc_frag, win,)
            # self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
            #        self.ack_wait_timer, self.ack_timeout, args)
            # dprint("*******event id {}".format(self.event_id_ack_wait_timer))

        # if window_tiles is not None and not self.all1_send and not self.resend:

        if window_tiles is not None:

            dprint("window_tiles is not None -> {}, resend -> {}".format(
                self.all1_send, self.resend))
            dprint("")
            # even when mic is sent, it comes here in the retransmission.
            if self.all1_send and self.state != self.ACK_FAILURE:
                # when there is a retransmission, the all-1 is send again and is send before
                # the ACK-OK is received. One option is not set the timer after the last
                # retransmission, but i don´t know how to idenfy that all missing fragments
                # have been send. Also the ALL-1 is not retransmisted (dont know if this should
                # be like this. For example, if the ALL-1s is lost, the receiver timer expires
                # and a receiver abort is send. If it arrives, there is not need to retransmit
                # the message after the retransmission of the missing fragments)
                # FIX, all-1 is resend
                dprint('All-1 ones already send')
                # cancel timer when there is success
                # if self.event_id_ack_wait_timer and self.state == self.ACK_SUCCESS:
                #     self.cancel_ack_wait_timer()
                # else:
                #    dprint("how to add a timer without sending a message")
                # fcn = frag_msg.get_fcn_all_1(self.rule)
                # args = (schc_frag, window_tiles[0]["w-num"],)
                # elf.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                # self.ack_wait_timer, self.ack_timeout, args)
                # fcn = frag_msg.get_fcn_all_1(self.rule)
                return
            elif (nb_remaining_tiles == 0 and len(window_tiles) == 1
                  and remaining_size >= frag_msg.get_mic_size(self.rule)):
                dprint("MESSSAGE TYPE ----> ALL-1 prepared")

                # make the All-1 frag with this tile.
                # the All-1 fragment can carry only one tile of which the size
                # is less than L2 word size.
                fcn = frag_msg.get_fcn_all_1(self.rule)
                last_frag_base_size = (
                    frag_msg.get_sender_header_size(self.rule) +
                    frag_msg.get_mic_size(self.rule) +
                    TileList.get_tile_size(window_tiles))
                # check if mic exists, no need no created again
                if self.mic_sent is None:
                    mic = self.get_mic(self.mic_base, last_frag_base_size)
                    # store the mic in order to know all-1 has been sent.
                    self.mic_sent = mic
                else:
                    mic = self.mic_sent
                dprint("mic_sent -> {}".format(self.mic_sent))
                if enable_statsct:
                    Statsct.set_msg_type("SCHC_ALL_1")
                    Statsct.set_header_size(
                        frag_msg.get_sender_header_size(self.rule) +
                        frag_msg.get_mic_size(self.rule))
                self.all1_send = True
                self.state = self.SEND_ALL_1
            else:
                dprint("MESSSAGE TYPE ----> regular SCHC frag")
                dprint("")
                # regular fragment.
                fcn = window_tiles[0]["t-num"]
                mic = None

                if enable_statsct:
                    Statsct.set_msg_type("SCHC_FRAG")
                    Statsct.set_header_size(
                        frag_msg.get_sender_header_size(self.rule))

            schc_frag = frag_msg.frag_sender_tx(
                self.rule,
                dtag=self.dtag,
                win=window_tiles[0]["w-num"],
                fcn=fcn,
                mic=mic,
                payload=TileList.concat(window_tiles))

            if mic is not None:
                dprint("mic is not None")
                # set ack waiting timer
                if enable_statsct:
                    Statsct.set_msg_type("SCHC_FRAG")
                    Statsct.set_header_size(
                        frag_msg.get_sender_header_size(self.rule))
                args = (
                    schc_frag,
                    window_tiles[0]["w-num"],
                )
                dprint("all ones")
                self.schc_all_1 = schc_frag
                self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                    self.ack_wait_timer, self.ack_timeout, args)
                dprint("*******event id {}".format(
                    self.event_id_ack_wait_timer))
            # save the last window tiles.
            self.last_window_tiles = window_tiles
            dprint("self.last_window_tiles -> {}".format(
                self.last_window_tiles))
        elif self.mic_sent is not None or self.all1_send:
            dprint("self.mic_sent is not None state -> {}".format(self.state))
            # it looks that all fragments have been sent.
            dprint(
                "----------------------- all tiles have been sent -----------------------",
                window_tiles, nb_remaining_tiles, remaining_size)
            schc_frag = None
            self.all1_send = True
            if self.event_id_ack_wait_timer and self.state == self.ACK_SUCCESS:
                self.cancel_ack_wait_timer()
            return
        else:
            dprint("only mic all tiles send")
            # Here, only MIC will be sent since all tiles has been sent.
            assert self.last_window_tiles is not None
            # As the MTU would be changed anytime AND the size of the
            # significant padding bits would be changed, therefore the MIC
            # calculation may be needed again.
            # XXX maybe it's better to check whether the size of MTU is change
            # or not when the previous MIC was calculated..
            last_frag_base_size = (
                frag_msg.get_sender_header_size(self.rule) +
                TileList.get_tile_size(self.last_window_tiles))
            self.mic_sent = self.get_mic(self.mic_base, last_frag_base_size)
            # check the win number.
            # XXX if the last tile number is zero, here window number has to be
            # incremented.
            win = self.last_window_tiles[0]["w-num"]
            if self.last_window_tiles[0]["t-num"] == 0:
                win += 1
            schc_frag = frag_msg.frag_sender_tx(self.rule,
                                                dtag=self.dtag,
                                                win=win,
                                                fcn=frag_msg.get_fcn_all_1(
                                                    self.rule),
                                                mic=self.mic_sent)
            # set ack waiting timer
            args = (
                schc_frag,
                win,
            )
            if enable_statsct:
                Statsct.set_msg_type("SCHC_ALL_1")
                Statsct.set_header_size(
                    frag_msg.get_sender_header_size(self.rule) +
                    frag_msg.get_mic_size(self.rule))
            self.schc_all_1 = schc_frag
            self.state = self.SEND_ALL_1
            self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                self.ack_wait_timer, self.ack_timeout, args)
            dprint("*******event id {}".format(self.event_id_ack_wait_timer))

        # send a SCHC fragment
        args = (schc_frag.packet.get_content(), self._session_id[0],
                self.event_sent_frag)
        dprint("frag sent:", schc_frag.__dict__)
        self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
                                          args)
Пример #4
0
class FragmentAckOnError(FragmentBase):
    def set_packet(self, packet_bbuf):
        super().set_packet(packet_bbuf)
        self.all_tiles = TileList(self.rule, packet_bbuf, self.l2word)
        # XXX
        # check whether the size of the last tile is less than L2 word
        # AND the tile number is zero
        # because draft-17 doesn't specify how to handle it.
        a = self.all_tiles.get_all_tiles()

        if (a[-1]["t-num"] == 0
                and a[-1]["tile"].count_added_bits() < self.l2word):
            raise ValueError(
                "The size {} of the last tile with the tile number 0 must be equal to or greater than L2 word size {}."
                .format(a[-1]["tile"].count_added_bits(), self.l2word))
        # make the bitmap
        #self.bit_list = make_bit_list(self.all_tiles.get_all_tiles(),
        #                              self.rule["FCNSize"],
        #                              frag_msg.get_fcn_all_1(self.rule))
        dprint(
            "----------------------- Fragmentation process -----------------------"
        )
        self.bit_list = make_bit_list(
            self.all_tiles.get_all_tiles(),
            self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN],
            self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_W])
        dprint("bit_list:", self.bit_list)
        for tile in self.all_tiles.get_all_tiles():
            dprint("w: {}, t: {}, sent: {}".format(tile['w-num'],
                                                   tile['t-num'],
                                                   tile['sent']))
        self.all1_send = False
        self.num_of_windows = 0
        for pos in self.bit_list:
            dprint("bitmap: {}, length:{}".format(self.bit_list[pos],
                                                  len(self.bit_list[pos])))
            if len(self.bit_list[pos]) != 0:
                self.num_of_windows += 1
        dprint("number of windows = {}".format(self.num_of_windows))
        #input("")

    def send_frag(self):
        if self.state == self.ACK_SUCCESS:
            dprint(
                "-----------------------------------------------------------------------"
            )
            return
        dprint(
            "----------------------- Preparing to send a message -----------------------"
        )
        scheduler = self.protocol.system.get_scheduler()
        dprint("{} send_frag!!!!!!!!!!!!!!!!!".format(
            scheduler.get_clock()))  # utime.time()
        dprint("all1_send-> {}, resend -> {}, state -> {}".format(
            self.all1_send, self.resend, self.state))
        dprint("all tiles unsend -> {}".format(self.all_tiles.get_all_tiles()))
        for tile in self.all_tiles.get_all_tiles():
            dprint("w: {}, t: {}, sent: {}".format(tile['w-num'],
                                                   tile['t-num'],
                                                   tile['sent']))
        dprint("")
        # if self.state == self.ACK_FAILURE and self.num_of_windows != 1 and self.number_of_ack_waits <= self.num_of_windows:
        #     #waiting for the acks of the others windows
        #     self.number_of_ack_waits += 1 #wait depends on the number of windows
        #     #set ack_time_out_timer
        #     dprint("waiting for more acks: {}".format(self.number_of_ack_waits))
        #     return

        # get contiguous tiles as many as possible fit in MTU.
        mtu_size = self.protocol.layer2.get_mtu_size()
        window_tiles, nb_remaining_tiles, remaining_size = self.all_tiles.get_tiles(
            mtu_size)
        dprint(
            "----window tiles to send: {}, nb_remaining_tiles: {}, remaining_size: {}"
            .format(window_tiles, nb_remaining_tiles, remaining_size))

        if window_tiles is None and self.resend:
            dprint("no more tiles to resend")
            # how to identify that all tiles are resend and that the ack timeout should be set
            # to wait for tha last ok. It should be set after retransmission of the last fragment
            if self.state == self.ACK_FAILURE and self.event_id_ack_wait_timer is None:
                win = self.last_window_tiles[0][
                    "w-num"] if self.last_window_tiles[0][
                        "w-num"] is not None else 0
                if self.last_window_tiles[0]["t-num"] == 0:
                    win += 1
                schc_frag = frag_msg.frag_sender_tx(self.rule,
                                                    dtag=self.dtag,
                                                    win=win,
                                                    fcn=frag_msg.get_fcn_all_1(
                                                        self.rule),
                                                    mic=self.mic_sent)
                # set ack waiting timer
                args = (
                    schc_frag,
                    win,
                )
                self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                    self.ack_wait_timer, self.ack_timeout, args)
                dprint("*******event id {}".format(
                    self.event_id_ack_wait_timer))
                # if self.all1_send and self.state == self.ACK_FAILURE:
            #     #case when with the bitmap is not possible to identify the missing tile,
            #     #resend ALL-1 messages
            #     # send a SCHC fragment
            #     args = (self.schc_all_1.packet.get_content(), self._session_id[0],
            #     self.event_sent_frag)
            #     dprint("frag sent:", self.schc_all_1.__dict__)
            #     if enable_statsct:
            #         Statsct.set_msg_type("SCHC_ALL_1")
            #         Statsct.set_header_size(frag_msg.get_sender_header_size(self.rule) +
            #             frag_msg.get_mic_size(self.rule))
            #     self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
            #                                     args)
            #     dprint("Sending all-1 beacuse there is an ACK FaILURE but cannot find the missing tiles")
            #     input("")

            # win = self.last_window_tiles[0]["w-num"] if self.last_window_tiles[0]["w-num"] is not None else 0
            # if self.last_window_tiles[0]["t-num"] == 0:
            #     win += 1
            # schc_frag = frag_msg.frag_sender_tx(
            #         self.rule, dtag=self.dtag, win=win,
            #         fcn=frag_msg.get_fcn_all_1(self.rule),
            #         mic=self.mic_sent)
            # set ack waiting timer
            # args = (schc_frag, win,)
            # self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
            #        self.ack_wait_timer, self.ack_timeout, args)
            # dprint("*******event id {}".format(self.event_id_ack_wait_timer))

        # if window_tiles is not None and not self.all1_send and not self.resend:

        if window_tiles is not None:

            dprint("window_tiles is not None -> {}, resend -> {}".format(
                self.all1_send, self.resend))
            dprint("")
            # even when mic is sent, it comes here in the retransmission.
            if self.all1_send and self.state != self.ACK_FAILURE:
                # when there is a retransmission, the all-1 is send again and is send before
                # the ACK-OK is received. One option is not set the timer after the last
                # retransmission, but i don´t know how to idenfy that all missing fragments
                # have been send. Also the ALL-1 is not retransmisted (dont know if this should
                # be like this. For example, if the ALL-1s is lost, the receiver timer expires
                # and a receiver abort is send. If it arrives, there is not need to retransmit
                # the message after the retransmission of the missing fragments)
                # FIX, all-1 is resend
                dprint('All-1 ones already send')
                # cancel timer when there is success
                # if self.event_id_ack_wait_timer and self.state == self.ACK_SUCCESS:
                #     self.cancel_ack_wait_timer()
                # else:
                #    dprint("how to add a timer without sending a message")
                # fcn = frag_msg.get_fcn_all_1(self.rule)
                # args = (schc_frag, window_tiles[0]["w-num"],)
                # elf.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                # self.ack_wait_timer, self.ack_timeout, args)
                # fcn = frag_msg.get_fcn_all_1(self.rule)
                return
            elif (nb_remaining_tiles == 0 and len(window_tiles) == 1
                  and remaining_size >= frag_msg.get_mic_size(self.rule)):
                dprint("MESSSAGE TYPE ----> ALL-1 prepared")

                # make the All-1 frag with this tile.
                # the All-1 fragment can carry only one tile of which the size
                # is less than L2 word size.
                fcn = frag_msg.get_fcn_all_1(self.rule)
                last_frag_base_size = (
                    frag_msg.get_sender_header_size(self.rule) +
                    frag_msg.get_mic_size(self.rule) +
                    TileList.get_tile_size(window_tiles))
                # check if mic exists, no need no created again
                if self.mic_sent is None:
                    mic = self.get_mic(self.mic_base, last_frag_base_size)
                    # store the mic in order to know all-1 has been sent.
                    self.mic_sent = mic
                else:
                    mic = self.mic_sent
                dprint("mic_sent -> {}".format(self.mic_sent))
                if enable_statsct:
                    Statsct.set_msg_type("SCHC_ALL_1")
                    Statsct.set_header_size(
                        frag_msg.get_sender_header_size(self.rule) +
                        frag_msg.get_mic_size(self.rule))
                self.all1_send = True
                self.state = self.SEND_ALL_1
            else:
                dprint("MESSSAGE TYPE ----> regular SCHC frag")
                dprint("")
                # regular fragment.
                fcn = window_tiles[0]["t-num"]
                mic = None

                if enable_statsct:
                    Statsct.set_msg_type("SCHC_FRAG")
                    Statsct.set_header_size(
                        frag_msg.get_sender_header_size(self.rule))

            schc_frag = frag_msg.frag_sender_tx(
                self.rule,
                dtag=self.dtag,
                win=window_tiles[0]["w-num"],
                fcn=fcn,
                mic=mic,
                payload=TileList.concat(window_tiles))

            if mic is not None:
                dprint("mic is not None")
                # set ack waiting timer
                if enable_statsct:
                    Statsct.set_msg_type("SCHC_FRAG")
                    Statsct.set_header_size(
                        frag_msg.get_sender_header_size(self.rule))
                args = (
                    schc_frag,
                    window_tiles[0]["w-num"],
                )
                dprint("all ones")
                self.schc_all_1 = schc_frag
                self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                    self.ack_wait_timer, self.ack_timeout, args)
                dprint("*******event id {}".format(
                    self.event_id_ack_wait_timer))
            # save the last window tiles.
            self.last_window_tiles = window_tiles
            dprint("self.last_window_tiles -> {}".format(
                self.last_window_tiles))
        elif self.mic_sent is not None or self.all1_send:
            dprint("self.mic_sent is not None state -> {}".format(self.state))
            # it looks that all fragments have been sent.
            dprint(
                "----------------------- all tiles have been sent -----------------------",
                window_tiles, nb_remaining_tiles, remaining_size)
            schc_frag = None
            self.all1_send = True
            if self.event_id_ack_wait_timer and self.state == self.ACK_SUCCESS:
                self.cancel_ack_wait_timer()
            return
        else:
            dprint("only mic all tiles send")
            # Here, only MIC will be sent since all tiles has been sent.
            assert self.last_window_tiles is not None
            # As the MTU would be changed anytime AND the size of the
            # significant padding bits would be changed, therefore the MIC
            # calculation may be needed again.
            # XXX maybe it's better to check whether the size of MTU is change
            # or not when the previous MIC was calculated..
            last_frag_base_size = (
                frag_msg.get_sender_header_size(self.rule) +
                TileList.get_tile_size(self.last_window_tiles))
            self.mic_sent = self.get_mic(self.mic_base, last_frag_base_size)
            # check the win number.
            # XXX if the last tile number is zero, here window number has to be
            # incremented.
            win = self.last_window_tiles[0]["w-num"]
            if self.last_window_tiles[0]["t-num"] == 0:
                win += 1
            schc_frag = frag_msg.frag_sender_tx(self.rule,
                                                dtag=self.dtag,
                                                win=win,
                                                fcn=frag_msg.get_fcn_all_1(
                                                    self.rule),
                                                mic=self.mic_sent)
            # set ack waiting timer
            args = (
                schc_frag,
                win,
            )
            if enable_statsct:
                Statsct.set_msg_type("SCHC_ALL_1")
                Statsct.set_header_size(
                    frag_msg.get_sender_header_size(self.rule) +
                    frag_msg.get_mic_size(self.rule))
            self.schc_all_1 = schc_frag
            self.state = self.SEND_ALL_1
            self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                self.ack_wait_timer, self.ack_timeout, args)
            dprint("*******event id {}".format(self.event_id_ack_wait_timer))

        # send a SCHC fragment
        args = (schc_frag.packet.get_content(), self._session_id[0],
                self.event_sent_frag)
        dprint("frag sent:", schc_frag.__dict__)
        self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
                                          args)

    def cancel_ack_wait_timer(self):
        # don't assert here because the receiver sends ACK back anytime.
        #assert self.event_id_ack_wait_timer is not None
        dprint(
            '----------------------- cancel_ack_wait_timer -----------------------'
        )
        self.protocol.scheduler.cancel_event(self.event_id_ack_wait_timer)
        self.event_id_ack_wait_timer = None

    def ack_timeout(self, *args):
        self.cancel_ack_wait_timer()
        dprint("----------------------- ACK timeout -----------------------  ")
        self.state = self.ACK_TIMEOUT
        assert len(args) == 2
        assert isinstance(args[0], frag_msg.frag_sender_tx)
        assert isinstance(args[1], int)
        schc_frag = args[0]
        win = args[1]
        self.ack_requests_counter += 1
        dprint("ack_requests_counter -> {}".format(self.ack_requests_counter))
        if self.ack_requests_counter > max_ack_requests:
            # sending sender abort.
            schc_frag = frag_msg.frag_sender_tx_abort(self.rule, self.dtag)
            args = (schc_frag.packet.get_content(), self._session_id[0])
            dprint("MESSSAGE TYPE ----> Sent Sender-Abort.",
                   schc_frag.__dict__)
            if enable_statsct:
                Statsct.set_msg_type("SCHC_SENDER_ABORT")
                Statsct.set_header_size(
                    frag_msg.get_sender_header_size(self.rule))

            self.protocol.scheduler.add_event(0,
                                              self.protocol.layer2.send_packet,
                                              args)
            return
        # set ack waiting timer
        self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
            self.ack_wait_timer, self.ack_timeout, args)
        dprint("*******event id {}".format(self.event_id_ack_wait_timer))
        schc_frag = frag_msg.frag_sender_ack_req(self.rule, self.dtag, win)
        if enable_statsct:
            Statsct.set_msg_type("SCHC_ACK_REQ")
        # # retransmit MIC.
        args = (schc_frag.packet.get_content(), self._session_id[0],
                self.event_sent_frag)

        dprint("MESSSAGE TYPE ----> SCHC ACK REQ frag:", schc_frag.__dict__)
        self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
                                          args)
        """ waits for all the acks before sending the ack request

        self.number_of_ack_waits += 1
        dprint("number_of_ack_waits -> {}".format(self.number_of_ack_waits))
        if self.number_of_ack_waits > self.num_of_windows:
            schc_frag = frag_msg.frag_sender_ack_req(self.rule, self.dtag, win)
            if enable_statsct:
                    Statsct.set_msg_type("SCHC_ACK_REQ")
            # # retransmit MIC.
            args = (schc_frag.packet.get_content(), self._session_id[0],
                    self.event_sent_frag)
            dprint("SCHC ACK REQ frag:", schc_frag.__dict__)
            # if enable_statsct:
            #     Statsct.set_msg_type("SCHC_FRAG")
            #     Statsct.set_header_size(frag_msg.get_sender_header_size(self.rule))
            self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
                                            args)
            self.number_of_ack_waits = 0

        else:
            dprint("Do no send ACK REQ, waiting for more ACKS")        #the idea is that if the ack did not arrive, to send a SCHC ACK REQ
        """

    def event_sent_frag(self, status):  # status == nb actually sent (for now)
        dprint("EVENT SEND FRAG")
        self.send_frag()

    def receive_frag(self, bbuf, dtag):
        # the ack timer can be cancelled here, because it's been done whether
        # both rule_id and dtag in the fragment are matched to this session
        # at process_received_packet().
        self.cancel_ack_wait_timer(
        )  # the timeout is canceled but has to be set
        # when an ack should be received
        self.resend = False
        #
        schc_frag = frag_msg.frag_sender_rx(self.rule, bbuf)
        dprint(
            "-----------------------  Sender Frag Received -----------------------"
        )
        dprint("fragment received -> {}".format(schc_frag.__dict__))
        if ((self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_W] is None
             or schc_frag.win == frag_msg.get_win_all_1(self.rule))
                and schc_frag.cbit == 1
                and schc_frag.remaining.allones() == True):
            dprint(
                "-----------------------  Receiver Abort rid={} dtag={} -----------------------"
                .format(self.rule[T_RULEID], self.dtag))
            #self.resend = False
            self.state = self.RECEIVER_ABORT

            return
        if schc_frag.cbit == 1:
            dprint(
                "----------------------- ACK Success rid={} dtag={} -----------------------"
                .format(self.rule[T_RULEID], self.dtag))
            #self.resend = False
            self.state = self.ACK_SUCCESS

            # XXX needs to be reviewed.  at least, no one need this log.
            # try:
            #     f = open("client_server_simulation.txt", "r+")
            # except IOError:
            #     f = open("client_server_simulation.txt", "w+")
            #     f = open("client_server_simulation.txt", "r+")
            # content = f.read()
            # seconds = time. time()
            # f.seek(0, 0)
            # f.write(str(int(seconds)) + '\n' + content)
            # f.close()

            return
        if schc_frag.cbit == 0:
            dprint(
                "----------------------- ACK Failure rid={} dtag={} -----------------------"
                .format(self.rule[T_RULEID], self.dtag))
            #self.resend = False
            #self.all1_send = False
            self.state = self.ACK_FAILURE
            self.resend_frag(schc_frag)
            return

    def resend_frag(self, schc_frag):
        self.resend = True
        dprint("recv bitmap:", (schc_frag.win, schc_frag.bitmap.to_bit_list()))
        dprint("sent bitmap:", (schc_frag.win, self.bit_list[schc_frag.win]))
        self.all_tiles.unset_sent_flag(schc_frag.win,
                                       schc_frag.bitmap.to_bit_list())
        self.send_frag()

    def tiles_send(self):
        for tile in self.all_tiles.get_all_tiles():
            if not tile['sent']:
                self.number_tiles_send += 1
        self.number_tiles_send = math.ceil(
            self.number_tiles_send /
            (self.protocol.layer2.get_mtu_size() //
             self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_TILE]))
        dprint("----------- ", self.number_tiles_send, "tiles to send")

    def current_number_tiles_sent(self):
        if self.number_tiles_send > 0:
            self.number_tiles_send -= 1
        dprint("----------- ", self.number_tiles_send, "tiles to send")
        return self.number_tiles_send

    def get_state(self, **kw):
        result = {
            "type": "ack-on-error",
            "state": self.state,
            "mic-sent": self.mic_sent,
            "resend": self.resend,
            "all1-send": self.all1_send,
            "sent-tiles": self.number_tiles_send,
            "ack-req-counter": self.ack_requests_counter,
            "tiles": self.all_tiles.get_state(**kw),
            "state": "XXX - need to be added"
        }
        return result