def recv_process(self): while True: UDPsocket.setblocking(self, 0) try: reply = UDPsocket.recvfrom(self, bufsize=4096) if reply is not None: result = payload_resolver(reply[0]) if not result.jug: continue else: continue except: time.sleep(0.5) continue try: pack = self.datas[0] address = reply[1] except IndexError: continue if address not in self.seq.keys(): self.seq[address] = 0 self.seq_ack[address] = 0 if result.seq_ack is self.seq[address] + pack[0].len: print('\"' + str(pack[0].payload) + '\"' + 'send successfully!') self.seq[address] += pack[0].len self.datas.remove(pack) continue elif result.seq is self.seq_ack[address] and result.syn is 1: print('\"' + str(result.payload) + '\"' + 'receive successfully!') self.seq_ack[address] += result.len continue else: time.sleep(0.5) continue
def __init__(self): # udt self.udpsocket = UDPsocket() # FSM variables self.window_size = Config.RFT_WINDOW_SIZE self.unacked_queue = queue.Queue(self.window_size) self.unsent_queue = queue.Queue() self.base_seq_num = 0 self.ack_num = 0 # the expecting seq_num # timer self.timer = timeoutMonitor(self, Config.RDT_TIMEOUT, Config.RDT_TIMROUT_CHECKING_TIME) self.timer.start() # destination self.addr = None # receive thread self.receive_queue = queue.Queue() # flag self.SYN_blocked_queue = queue.Queue() # coding self.encoding = Config.DEFAULT_CODING # threads self.recv_thread = recv_thread(self) self.send_thread = send_thread(self) self.retransmit_on = False
def send(self, data, ADDR): address = ADDR print('send to ', address) packets = [] seq_num = 0 #data = data.encode(encoding='utf-8') #self.pkt_num = int(len(data)/PACKET_SIZE)+ 1 self.set_pkt_num(int(len(data) / PACKET_SIZE) + 1) ''' slice the data into packets and put them into the buffer ''' for i in range(0, self.pkt_num): data_slice = data[i * PACKET_SIZE:(i + 1) * PACKET_SIZE] seq_bytes = seq_num.to_bytes(4, byteorder='little', signed=True) check_sum = socket._get_checksum(self, seq_bytes + data_slice) packets.append(make_pkt(seq_num, data_slice, check_sum)) seq_num += 1 next_seq = 0 print(self.pkt_num) # start sender receive thread #_thread.start_new_thread(socket._sender_recv, (self,)) #t.start() while (self.base < self.pkt_num): #print(base) #lock.acquire() #print(next_seq) # send all pkts in the window while next_seq < self.base + WINDOW_SIZE and next_seq < self.pkt_num: print('sending pkt ', next_seq) UDPsocket.send(UDPsocket, packets[next_seq], address) # if next sequence number is equal to base, start timer next_seq += 1 if not send_timer.running(): print('start timer') send_timer.start() # wait for ack or timeout. we now release the lock and _sender_recv thread can do modification while send_timer.running() and not send_timer.timeout(): #lock.release() print("Waiting...") socket._sender_recv(self) #time.sleep(SLEEP_INTERVAL) #lock.acquire() # handle timeout if send_timer.timeout(): print("Time out") send_timer.stop() # resend every packet from base next_seq = self.base #lock.release() print('======finish send========') for i in range(0, 5): time.sleep(SLEEP_INTERVAL) UDPsocket.send(UDPsocket, make_pkt(0, b'', 0), address) print('=======sender send empty packet==========') #socket.set_flag() self.base = 0
def _close_connection(self, conn) -> None: if self.connection: # client UDPsocket.close(self) elif self.connections: # server del self.connections[conn.client] if self.state == State.CLOSED and len(self.connections) == 0: UDPsocket.close(self) else: raise Exception("Illegal state")
def recv(self, ADDR): expected_num = 0 address = ADDR global data_buffer while True: # get the next packet from sender ''' print(socket.send_finish) if socket.send_finish == 1: socket.clear_flag() break ''' #time.sleep(1) pkt = UDPsocket.recv(self, BUFFER_SIZE) if pkt is None: continue #print('recv ', len(pkt)) seq_num, data, checksum = unpack(pkt) if checksum == 0 and seq_num == 0: print('recv empty packet finish recv') break print("recv packet ", seq_num) #print('original checksum ', checksum) pkt_checksum = socket._get_checksum(self, pkt[0:-2]) #print('recv checksum ', pkt_checksum) is_corrupt = not (checksum == pkt_checksum) print('is corrupt ', is_corrupt) # send an ack if seq_num == expected_num and not is_corrupt: print("Got expected pkt ", seq_num) print('Sending ACK', expected_num, 'TO', address) data_buffer += pkt[4:-2] _data = expected_num.to_bytes(4, byteorder='little', signed=True) UDPsocket.send( UDPsocket, make_pkt(expected_num, b'', socket._get_checksum(self, _data)), address) expected_num += 1 elif seq_num > 0: # send ack on previous acked packet pre_expected_num = expected_num - 1 _data = pre_expected_num.to_bytes(4, byteorder='little', signed=True) print('Sending dup ACK', expected_num - 1) UDPsocket.send( UDPsocket, make_pkt(pre_expected_num, b'', socket._get_checksum(self, _data)), address) print('==========recv finished===========') return data_buffer
def recvfrom(self): while True: UDPsocket.setblocking(self, 5) result = UDPsocket.recvfrom(self, bufsize=4096) if result is None: continue else: try: data = payload_resolver(result[0]) except: continue address = result[1] if data.jug: if address not in self.seq.keys(): self.seq[address] = 0 self.seq_ack[address] = 0 if data.seq is not self.seq_ack[address]: re = payload(seq_ack=self.seq_ack[address]) UDPsocket.sendto(self, re.to_ascii(), address) continue else: self.seq_ack[address] = data.seq + data.len re = payload(seq_ack=self.seq_ack[address]) UDPsocket.sendto(self, re.to_ascii(), address) break else: if address not in self.seq.keys(): self.seq[address] = 0 self.seq_ack[address] = 0 re = payload(seq_ack=self.seq_ack[address]) UDPsocket.sendto(self, re.to_ascii(), address) continue # print('Inside function: '+str(data.payload)) return data.payload, address
def _sender_recv(self): print('start recv') #global base global send_timer pkt = None #global lock sleep_time = random.random() time.sleep(sleep_time) signal.signal(signal.SIGALRM, recv_timeout_handler) try: signal.alarm(2) pkt = UDPsocket.recv(self, BUFFER_SIZE) if pkt: signal.alarm(0) except RuntimeError as e: print("recv time out") signal.alarm(0) if pkt is None: return ack, _data, checksum = unpack(pkt) print('recv ack ', ack) pkt_checksum = socket._get_checksum(self, pkt[0:-2]) is_corrupt = not (checksum == pkt_checksum) print('is_corrupt ', is_corrupt) #print('base', self.base) if not is_corrupt and ack >= self.base and checksum != 0: #lock.acquire() self.base = ack + 1 print('base update ', self.base) #print('pkt num ', self.pkt_num) if self.base == self.pkt_num: return send_timer.stop()
def send(self, data): message = data[0] address = data[1] bytes = message.to_ascii() UDPsocket.sendto(self, bytes, address)
class socket(): # init def __init__(self): # udt self.udpsocket = UDPsocket() # FSM variables self.window_size = Config.RFT_WINDOW_SIZE self.unacked_queue = queue.Queue(self.window_size) self.unsent_queue = queue.Queue() self.base_seq_num = 0 self.ack_num = 0 # the expecting seq_num # timer self.timer = timeoutMonitor(self, Config.RDT_TIMEOUT, Config.RDT_TIMROUT_CHECKING_TIME) self.timer.start() # destination self.addr = None # receive thread self.receive_queue = queue.Queue() # flag self.SYN_blocked_queue = queue.Queue() # coding self.encoding = Config.DEFAULT_CODING # threads self.recv_thread = recv_thread(self) self.send_thread = send_thread(self) self.retransmit_on = False # callable method def set_encoding(self, encoding): self.encoding = encoding def bind(self, ip_and_port): self.addr = ip_and_port self.udpsocket.bind(ip_and_port) self.recv_thread.start() def _get_base_seq_num(self): rtn = self.base_seq_num return rtn def accpet(self): Debug.verbose_print("accept : Waiting for new connection on {}".format( self.addr)) # Wait for a connecting request packet, addr = self.recv_packet() self.addr = addr self.send_thread.start() Debug.verbose_print("accept : Accept connection from {}".format(addr)) #Send SYN_ACK_PACKET self.send_packet( Encoder.SYN_ACK_PACKET(), addr) # SEQ_NUM=self._get_base_seq_num(), ACK_NUM=self.ack_num self.SYN_blocked_queue.get() Debug.verbose_print("accept : Successfully finish handshaking") self.ack_num = 1 def close(self): self.recv_thread.terminate() self.send_thread.terminate() def connect(self, addr): self.addr = addr Debug.verbose_print("connect : Try to connect {}".format(addr)) # Send SYN self.send_packet( Encoder.SYN_PACKET(), addr) #SEQ_NUM=self._get_base_seq_num(), ACK_NUM=self.ack_num self.send_thread.start() # Receive SYN ACK data, addr = self.recv_packet() Debug.verbose_print("connect : Successfully finish handshaking") self.ack_num = 1 def recv(self): packet, addr = self.recv_packet() if packet.SEG == 0: return packet.payload.decode(self.encoding) else: # packet.SEG == 1 rtn_payload = packet.payload while packet.SEG != 0: packet, addr = self.recv_packet() rtn_payload += packet.payload # return rtn_payload.decode(self.encoding) def send(self, data: str): segment_size = Config.SEGMENT_SIZE total_len = len(data) if total_len < segment_size: self.send_packet(self._make_packet(data), self.addr) else: ptr = 0 next_ptr = segment_size # data_list = list(data) seq_num = self._get_base_seq_num() while ptr < total_len: seg = 1 if next_ptr >= total_len: # This is the last packet next_ptr = total_len seg = 0 self.send_packet( self._make_packet(data[ptr:next_ptr], seq_num=seq_num, seg=seg), self.addr) seq_num += 1 ptr = next_ptr next_ptr += segment_size def recv_packet(self): receive_bytes = self.receive_queue.get() return receive_bytes def recv_packet_toQueue(self): while True: # Keep receiving until the packet is in order and not corrupted recv = self.udpsocket.recvfrom(Config.BUFSIZE) # 1. Packet loss -> receive again if recv == None: Debug.debug_print("recv_packet : Loss. receive again.") continue data, addr = recv # 2. Corrputed -> discard -> receive again if Encoder._isCorrupted(data): Debug.debug_print("recv_packet : corrupted, discard.") continue # 3. Out of order -> discard -> receive again packet = Decoder.Packet(data) Debug.debug_print( "recv_packet : (s:{}, a:{}) payload:{}, SYN={}, ACK={}".format( packet.seq_num, packet.ack_num, packet.payload, packet.SYN, packet.ACK)) if packet.seq_num != 0xFFFF and packet.seq_num > self.ack_num: Debug.debug_print( "recv_packet : s:{}. expecting {}, discard".format( packet.seq_num, self.ack_num)) # 4. already receive before -> send pure ack -> receive again elif packet.seq_num < self.ack_num: # Debug.debug_print( "recv_packet : s:{} is already received. expecting {}, discard" .format(packet.seq_num, self.ack_num)) if (packet.SYN == 0 and packet.ACK == 0) or (packet.SYN == 1 and packet.ACK == 1): self.send_pure_ack() # successfully receive the right packet else: break Debug.debug_print( "recv_packet : successfully receive reilable packet. seq_num:{}". format(packet.seq_num)) # ack an unacked packet if (ack_num - 1 equals to smallest base_seq_num) if packet.ack_num > self.base_seq_num: # if retransmission is going on, wait until it finishes. while True: time.sleep(0.01) if self.retransmit_on: continue else: break while self.base_seq_num != packet.ack_num: Debug.debug_print( "recv_packet : base_seq_num:{}. received ack_num:{}, move window." .format(self.base_seq_num, packet.ack_num)) self.timer.start_timer() self._move_window() # pure ack if packet.ACK == 1 and packet.SYN == 0: if packet.ack_num == 1 and packet.seq_num == 0xFFFF: # Only for handshaking sessions self.SYN_blocked_queue.put(0) Debug.debug_print("recv_packet : pure ack") return None # Do not forward ack # If the packet is not an ACK and not a SYN packet. Send ACK to this packet # assert packet.seq_num == self.ack_num if (packet.SYN == 0 and packet.ACK == 0) or (packet.SYN == 1 and packet.ACK == 1): # expecting the next self.ack_num += 1 self.send_pure_ack() Debug.debug_print("recv_packet : forward to upper layer.") return packet, addr # deliver to the upper layer def _move_window(self): self.base_seq_num += 1 if not self.unacked_queue.empty(): pkt = Decoder.Packet(self.unacked_queue.get()) Debug.debug_print("ack and dequeue seq_num:{}".format(pkt.seq_num)) if not self.unsent_queue.empty(): sending_pkt_byte = self.unsent_queue.get() self.unacked_queue.put(sending_pkt_byte) self.udpsocket.sendto(sending_pkt_byte, self.addr) # packet = Decoder.Packet(sending_pkt_byte) Debug.debug_print("send_packet : (s:{}, a:{}) payload:{}".format( packet.seq_num, packet.ack_num, packet.payload)) def send_packet(self, packet_byte: bytes, addr): Debug.debug_print("Append s:{} to unsent_queue".format( Decoder.Packet(packet_byte).seq_num)) self.unsent_queue.put(packet_byte) def send_packet_fromQueue(self): if self.unacked_queue.empty() and (not self.retransmit_on): while (not self.unacked_queue.full()) and ( not self.unsent_queue.empty()): sending_pkt_byte = self.unsent_queue.get() self.unacked_queue.put(sending_pkt_byte) self.udpsocket.sendto(sending_pkt_byte, self.addr) # packet = Decoder.Packet(sending_pkt_byte) Debug.debug_print( "send_packet : (s:{}, a:{}) payload:{}".format( packet.seq_num, packet.ack_num, packet.payload)) def send_pure_ack(self): Debug.debug_print("direct send ACK, ack_num : {}".format(self.ack_num)) self.udpsocket.sendto( Encoder.ACK_PACKET(SEQ_NUM=0xFFFF, ACK_NUM=self.ack_num), self.addr) def _retransmit(self): self.timer.start_timer() if self.unacked_queue.qsize() == 0: return None Debug.debug_print( "_retransmit : timeout. expecting:{}. {} unacked packet still in queue" .format(self.base_seq_num, self.unacked_queue.qsize())) cnt = self.unacked_queue.qsize() self.retransmit_on = True for _ in range(cnt): packet_bytes = self.unacked_queue.get() self.unacked_queue.put(packet_bytes) packet = Decoder.Packet(packet_bytes) Debug.debug_print("_retransmit : s:{}, a:{}".format( packet.seq_num, packet.ack_num)) self.udpsocket.sendto(packet_bytes, self.addr) self.retransmit_on = False def _make_packet(self, data: str, seq_num=-1, seg=0): if seq_num == -1: seq_num = self._get_base_seq_num() Debug.debug_print("_make_packet : make new packet s:{}, a:{}".format( seq_num, self.ack_num)) return Encoder.MAKE_PACKET(ACK=0, SYN=0, SEQ_NUM=seq_num, ACK_NUM=self.ack_num, payload=data, SEG=seg)