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))
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
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)
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