def event_inactive(self): """ event_inactive // TODO : Redaction (here is frag_recv.py) """ #if the ack-ok was received, no ACK REQ will be received, #check for state == "DONE" and return, this means that the ack-ok #was send, before the system returns after sending the ack-ok, now it #waits for one inactivity timer before closing session if self.state == "DONE": return # sending sender abort. schc_frag = frag_msg.frag_receiver_tx_abort(self.rule, self.dtag) """ Changement à corriger args = (schc_frag.packet.get_content(), self.context["devL2Addr"]) """ args = (schc_frag.packet.get_content(), '*') dprint("Sent Receiver-Abort.", schc_frag.__dict__) dprint( "----------------------- SCHC RECEIVER ABORT SEND -----------------------" ) if enable_statsct: Statsct.set_msg_type("SCHC_RECEIVER_ABORT") Statsct.set_header_size(frag_msg.get_sender_header_size(self.rule)) self.state = "ABORT" self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args) # XXX needs to release all resources. return
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) """ Changement à corriger args = (schc_frag.packet.get_content(), self.context["devL2Addr"]) """ args = (schc_frag.packet.get_content(), "*") 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. """Changement à corriger args = (schc_frag.packet.get_content(), self.context["devL2Addr"], self.event_sent_frag) """ args = (schc_frag.packet.get_content(), '*', 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
def send_frag(self): print("{} send_frag!!!!!!!!!!!!!!!!!".format(utime.time())) print("all1_send-> {}, resend -> {}, state -> {}".format( self.all1_send, self.resend, self.state)) print("all tiles unsend -> {}".format(self.all_tiles)) for tile in self.all_tiles.get_all_tiles(): print("w: {}, t: {}, sent: {}".format(tile['w-num'], tile['t-num'], tile['sent'])) if self.state == self.ACK_SUCCESS: return # 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 # print("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) print("window tiles: {}, nb_remaining_tiles: {}, remaining_size: {}". format(window_tiles, nb_remaining_tiles, remaining_size)) if window_tiles is None and self.resend: print("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 = schcmsg.frag_sender_tx(self.rule, dtag=self.dtag, win=win, fcn=schcmsg.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) print("*******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.context["devL2Addr"], # self.event_sent_frag) # print("frag sent:", self.schc_all_1.__dict__) # if enable_statsct: # Statsct.set_msg_type("SCHC_ALL_1") # Statsct.set_header_size(schcmsg.get_sender_header_size(self.rule) + # schcmsg.get_mic_size(self.rule)) # self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, # args) # print("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 = schcmsg.frag_sender_tx( # self.rule, dtag=self.dtag, win=win, # fcn=schcmsg.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) #print("*******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: print("window_tiles is not None -> {}, resend -> {}".format( self.all1_send, self.resend)) # 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 print('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: # print("how to add a timer without sending a message") # fcn = schcmsg.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 = schcmsg.get_fcn_all_1(self.rule) return elif (nb_remaining_tiles == 0 and len(window_tiles) == 1 and remaining_size >= schcmsg.get_mic_size(self.rule)): print("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 = schcmsg.get_fcn_all_1(self.rule) last_frag_base_size = ( schcmsg.get_sender_header_size(self.rule) + schcmsg.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 print("mic_sent -> {}".format(self.mic_sent)) if enable_statsct: Statsct.set_msg_type("SCHC_ALL_1") Statsct.set_header_size( schcmsg.get_sender_header_size(self.rule) + schcmsg.get_mic_size(self.rule)) self.all1_send = True self.state = self.SEND_ALL_1 else: print("regular SCHC frag") # regular fragment. fcn = window_tiles[0]["t-num"] mic = None if enable_statsct: Statsct.set_msg_type("SCHC_FRAG") Statsct.set_header_size( schcmsg.get_sender_header_size(self.rule)) schc_frag = schcmsg.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: print("mic is not None") # set ack waiting timer #if enable_statsct: # Statsct.set_msg_type("SCHC_FRAG") # Statsct.set_header_size(schcmsg.get_sender_header_size(self.rule)) args = ( schc_frag, window_tiles[0]["w-num"], ) print("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) print("*******event id {}".format( self.event_id_ack_wait_timer)) # save the last window tiles. self.last_window_tiles = window_tiles print("self.last_window_tiles -> {}".format( self.last_window_tiles)) elif self.mic_sent is not None or self.all1_send: print("self.mic_sent is not None state -> {}".format(self.state)) # it looks that all fragments have been sent. print( "----------------------- 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: print("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 = ( schcmsg.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 = schcmsg.frag_sender_tx(self.rule, dtag=self.dtag, win=win, fcn=schcmsg.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( schcmsg.get_sender_header_size(self.rule) + schcmsg.get_mic_size(self.rule)) 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) print("*******event id {}".format(self.event_id_ack_wait_timer)) # send a SCHC fragment args = (schc_frag.packet.get_content(), self.context["devL2Addr"], self.event_sent_frag) print("frag sent:", schc_frag.__dict__) self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args)
def send_frag(self): # XXX # because No-ACK mode supports variable MTU, # sender can't know the fact that it can't send all fragments # before it reachs to send the last fragment (All-1). # # The All-1 fragment MUST be formed like below. # # | header | MIC | last tile | # |<- L2 word size ->| # |<- L2 Word # # if the size of header+MIC+tile doesn't fit the L2 Word, # # | header | MIC | last tile | padding | # |<- L2 word size ->|<- less than ->| # L2 word size # |<- L2 Word payload_size = (self.protocol.layer2.get_mtu_size() - schcmsg.get_sender_header_size(self.rule)) remaining_data_size = self.packet_bbuf.count_remaining_bits() if remaining_data_size >= payload_size: # put remaining_size of bits of packet into the tile. tile = self.packet_bbuf.get_bits_as_buffer(payload_size) transmit_callback = self.event_sent_frag fcn = 0 self.mic_sent = None if enable_statsct: Statsct.set_msg_type("SCHC_FRAG") Statsct.set_header_size( schcmsg.get_sender_header_size(self.rule)) elif remaining_data_size < payload_size: if remaining_data_size <= (payload_size - schcmsg.get_mic_size(self.rule)): tile = None if remaining_data_size > 0: tile = self.packet_bbuf.get_bits_as_buffer() # make All-1 frag. assert self.mic_sent is None last_frag_base_size = 0 if tile is not None: last_frag_base_size += ( schcmsg.get_sender_header_size(self.rule) + schcmsg.get_mic_size(self.rule) + remaining_data_size) self.mic_sent = self.get_mic(self.mic_base, last_frag_base_size) # callback doesn't need in No-ACK mode. transmit_callback = None fcn = schcmsg.get_fcn_all_1(self.rule) if enable_statsct: Statsct.set_msg_type("SCHC_ALL_1") Statsct.set_header_size( schcmsg.get_sender_header_size(self.rule) + schcmsg.get_mic_size(self.rule)) else: # put the size of the complements of the header to L2 Word. tile_size = (remaining_data_size - (schcmsg.get_sender_header_size(self.rule) + remaining_data_size) % self.rule["L2WordSize"]) tile = self.packet_bbuf.get_bits_as_buffer(tile_size) transmit_callback = self.event_sent_frag fcn = 0 self.mic_sent = None if enable_statsct: Statsct.set_msg_type("SCHC_FRAG") Statsct.set_header_size( schcmsg.get_sender_header_size(self.rule)) schc_frag = schcmsg.frag_sender_tx(self.rule, dtag=self.dtag, win=None, fcn=fcn, mic=self.mic_sent, payload=tile) # send a SCHC fragment args = (schc_frag.packet.get_content(), self.context["devL2Addr"], transmit_callback) print("frag sent:", schc_frag.__dict__) self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args)
def send_frag(self): # XXX # because No-ACK mode supports variable MTU, # sender can't know the fact that it can't send all fragments # before it reachs to send the last fragment (All-1). # # The All-1 fragment MUST be formed like below. # # | header | MIC | last tile | # |<- L2 word size ->| # |<- L2 Word # # if the size of header+MIC+tile doesn't fit the L2 Word, # # | header | MIC | last tile | padding | # |<- L2 word size ->|<- less than ->| # L2 word size # |<- L2 Word payload_size = (self.protocol.layer2.get_mtu_size() - frag_msg.get_sender_header_size(self.rule)) remaining_data_size = self.packet_bbuf.count_remaining_bits() if remaining_data_size >= payload_size: dprint( "----------------------- Fragmentation process -----------------------" ) # put remaining_size of bits of packet into the tile. tile = self.packet_bbuf.get_bits_as_buffer(payload_size) transmit_callback = self.event_sent_frag fcn = 0 self.mic_sent = None if enable_statsct: Statsct.set_msg_type("SCHC_FRAG") Statsct.set_header_size( frag_msg.get_sender_header_size(self.rule)) elif remaining_data_size < payload_size: dprint( "----------------------- Fragmentation process -----------------------" ) if remaining_data_size <= (payload_size - frag_msg.get_mic_size(self.rule)): tile = None if remaining_data_size > 0: tile = self.packet_bbuf.get_bits_as_buffer() # make All-1 frag. assert self.mic_sent is None last_frag_base_size = 0 if tile is not None: last_frag_base_size += ( frag_msg.get_sender_header_size(self.rule) + frag_msg.get_mic_size(self.rule) + remaining_data_size) self.mic_sent = self.get_mic(self.mic_base, last_frag_base_size) # callback doesn't need in No-ACK mode. transmit_callback = None fcn = frag_msg.get_fcn_all_1(self.rule) 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)) else: # put the size of the complements of the header to L2 Word. tile_size = (remaining_data_size - (frag_msg.get_sender_header_size(self.rule) + remaining_data_size) % self.l2word) tile = self.packet_bbuf.get_bits_as_buffer(tile_size) transmit_callback = self.event_sent_frag fcn = 0 self.mic_sent = 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=None, fcn=fcn, mic=self.mic_sent, payload=tile) # send a SCHC fragment args = (schc_frag.packet.get_content(), self._session_id[0], transmit_callback) dprint("frag sent:", schc_frag.__dict__) if self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG] == 0: w_dtag = '-' else: w_dtag = schc_frag.dtag if self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_W] == 0: w_w = '-' else: w_w = schc_frag.win all1 = 2**self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN] - 1 if schc_frag.fcn == all1: w_fcn = "All-1" elif schc_frag.fcn == 0: w_fcn = "All-0" else: w_fcn = schc_frag.fcn dtrace("r:{}/{} (noA) DTAG={} W={} FCN={}".format( self.rule[T_RULEID], self.rule[T_RULEIDLENGTH], w_dtag, w_w, w_fcn)) dtrace("|----{:3}------------->".format(len( schc_frag.packet._content))) self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args)