def rdt_rcv(sock): data = extract(sock) if data == 0: return None # parse packets ACK = data[0:4] rec_seq = data[4:20] rec_cksum = rdt_utils.parse_checksum(data[20:]) # Handle error possibilities if rdt_utils.has_ack_bit_err( ) and rdt_utils.random_channel() < config.percent_corrupt: corruptData = rdt_utils.corrupt_bits(ACK) calc = corruptData + rec_seq elif rdt_utils.has_ack_packet_loss( ) and rdt_utils.random_channel() < config.percent_corrupt: rdt_utils.debug_print(f"ACK Packet #{int(rec_seq, 2)} Dropped !") return None else: calc = ACK + rec_seq checksum = rdt_utils.calc_checksum(calc) if rec_cksum != checksum: rdt_utils.debug_print( f"Bit error encountered in ACK #{int(rec_seq, 2)}!") return None rdt_utils.debug_print( f'ACK Packet #{int(rec_seq, 2)} successfully received') return int(rec_seq, 2)
def rdt_rcv(sock, seqNum): data = extract(sock) if data == 0: return 0 # parse packets ACK = data[0:4] recSeq = data[4:5] rec_cksum = rdt_utils.parse_checksum(data[5:]) if rdt_utils.has_ack_bit_err( ) and rdt_utils.random_channel() < config.percent_corrupt: if config.debug: print("Bit error encountered in ACK!") corruptData = rdt_utils.corrupt_bits(ACK) calc = corruptData + recSeq elif rdt_utils.has_ack_packet_loss( ) and rdt_utils.random_channel() < config.percent_corrupt: if config.debug: print("ACK Packet Dropped!") return 0 else: calc = ACK + recSeq checksum = rdt_utils.calc_checksum(calc) return ACK == b'1111' and recSeq == seqNum and rec_cksum == checksum
def rdt_rcv(fname, sock): expected_seq_num = 0 expected_seq_num_b = rdt_utils.seq_num_to_bin(expected_seq_num) ACK = bin(15)[2:].encode('utf-8') oncethru = False endpoint = None # Endpoint starts off unitialized, get it from first received packet f = None # Don't open file until know that we received message sndpkt = None while True: pkt, addr = extract(sock) # Initialize endpoint with actual addr received if not endpoint and addr: endpoint = addr # Got actual message if pkt and addr: # Open file if not opened if not f: f = open(fname, 'wb') #parse packet rec_seq = pkt[0:16] rec_ck = rdt_utils.parse_checksum(pkt[16:18]) data = pkt[18:] if rdt_utils.has_data_bit_err( ) and rdt_utils.random_channel() < config.percent_corrupt: if config.debug: print("Bit error encountered in Data!") corruptData = rdt_utils.corrupt_bits(data) calc = rec_seq + corruptData else: calc = rec_seq + data chksum = rdt_utils.calc_checksum(calc) # correct sequence number if (not config.loss_recovery or expected_seq_num_b == rec_seq) and chksum == rec_ck: deliver_data(f, data) sndpkt = make_pkt(ACK, rec_seq) udt_send(sndpkt, endpoint, sock) expected_seq_num += 1 expected_seq_num_b = rdt_utils.seq_num_to_bin(expected_seq_num) else: # didn't receive right pkt, either seqnum wrong or cksum if config.debug: print("Bad data received, sending prev ACK") if oncethru and sndpkt: udt_send(sndpkt, endpoint, sock) else: # Close file if opened if f: f.close() break oncethru = True return endpoint
def rdt_rcv(file, endpoint, sock): oncethru = 0 seqNum = 0 seq = bin(seqNum)[2:].encode("utf-8") ACK = bin(15)[2:].encode('utf-8') while True: pkt = extract(sock) if pkt: #parse packet recSeq = pkt[0:1] rec_ck = rdt_utils.parse_checksum(pkt[1:3]) data = pkt[3:] if rdt_utils.has_data_bit_err( ) and rdt_utils.random_channel() < config.percent_corrupt: if config.debug: print("Bit error encountered in Data!") corruptData = rdt_utils.corrupt_bits(data) calc = recSeq + corruptData else: calc = recSeq + data chksum = rdt_utils.calc_checksum(calc) # correct sequence number if seq == recSeq and chksum == rec_ck: deliver_data(file, data) sndpkt = make_pkt(ACK, recSeq, chksum) udt_send(sndpkt, endpoint, sock) # switch sequence number if seqNum == 0: seqNum = 1 else: seqNum = 0 seq = bin(seqNum)[2:].encode("utf-8") oncethru = 1 else: # didn't receive right pkt, either seqnum wrong or cksum if oncethru == 1: if config.debug: print("Bad data received, sending prev ACK") udt_send(sndpkt, endpoint, sock) else: if config.debug: print("Bad data received in first packet") else: file.close() break
def rdt_send(file, endpoint, sock): timer = rdt_utils.RDTTimer(config.timeout) # Returns callback function for when timeout reached def timeout_func(packet, endpoint, sock): def ret_func(): if config.debug: print("Timeout for ACK exceeded, resending packet") udt_send(packet, endpoint, sock) # Forget last timer and start new one timer.start(timeout_func(packet, endpoint, sock)) return ret_func seqNum = 0 seq = bin(seqNum)[2:].encode("utf-8") packet = make_pkt(file, seq) while packet != 0: if rdt_utils.has_data_packet_loss( ) and rdt_utils.random_channel() < config.percent_corrupt: if config.debug: print("DATA Packet Dropped!") else: udt_send(packet, endpoint, sock) timer.start(timeout_func(packet, endpoint, sock)) while not rdt_rcv(sock, seq): pass timer.cancel() if seqNum == 0: # switch sequence numbers seqNum = 1 else: seqNum = 0 seq = bin(seqNum)[2:].encode("utf-8") packet = make_pkt(file, seq) time.sleep(0.005)
def udt_send(packet, endpoint, sock, packet_num): if rdt_utils.has_data_packet_loss( ) and rdt_utils.random_channel() < config.percent_corrupt: rdt_utils.debug_print(f'DATA Packet #{packet_num} Dropped!') return return sock.sendto(packet, endpoint)
def udt_send(packet, endpoint, sock): if rdt_utils.has_data_packet_loss() and rdt_utils.random_channel() < config.percent_corrupt: if config.debug: print("DATA Packet Dropped!") return return sock.sendto(packet, endpoint)
def rdt_rcv(fname, sock): rcv_buf = rdt_utils.RCVPacketBuffer(config.max_buf_size, config.window_size) ACK = bin(15)[2:].encode('utf-8') endpoint = None # Endpoint starts off unitialized, get it from first received packet f = None # Don't open file until know that we received message sndpkt = None while True: pkt, addr = extract(sock) # Initialize endpoint with actual addr received if not endpoint and addr: endpoint = addr # Got actual message if pkt and addr: # Open file if not opened if not f: f = open(fname, 'wb') #parse packet rec_seq = pkt[0:16] rec_ck = rdt_utils.parse_checksum(pkt[16:18]) data = pkt[18:] if rdt_utils.has_data_bit_err( ) and rdt_utils.random_channel() < config.percent_corrupt: corruptData = rdt_utils.corrupt_bits(data) calc = rec_seq + corruptData else: calc = rec_seq + data chksum = rdt_utils.calc_checksum(calc) rec_seq_int = int(rec_seq, 2) if chksum == rec_ck: sndpkt = make_pkt(ACK, rec_seq) if rcv_buf.includes(rec_seq_int): udt_send(sndpkt, endpoint, sock) rcv_buf.buf[rec_seq_int] = data rdt_utils.debug_print( f'Data packet #{int(rec_seq, 2)} added to receive buffer' ) # Inorder if rec_seq_int == rcv_buf.base: while rcv_buf.buf[rcv_buf.base] is not None: deliver_data(f, rcv_buf.buf[rcv_buf.base]) rdt_utils.debug_print( f'Data {rcv_buf.base} delivered to file') rcv_buf.base += 1 elif rec_seq_int < rcv_buf.base: udt_send(sndpkt, endpoint, sock) else: # didn't receive right pkt, wrong cksum rdt_utils.debug_print( f'Bit error encountered in data packet #{int(rec_seq, 2)}, doing nothing' ) else: # Close file if opened if f: f.close() break return endpoint