def handshake_client(self): established = False server = self.host, self.port while not established: self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) logging.debug("(Starting Handshake)") syn_pkt = make_ack(SYN, 0, server) logging.debug(f'(client->{server}):{syn_pkt}:Sending SYN') self.conn.sendto(syn_pkt.to_bytes(), self.router) # TODO timeout self.conn.settimeout(TIMEOUT) try: raw_packet, router = self.conn.recvfrom(1024) except socket.timeout: logging.debug(f'(client->{server}):Timeout, either SYN dropped or SYN-ACK dropped') continue p = Packet.from_bytes(raw_packet) if p.packet_type == SYN_ACK: logging.debug(f'({server}->client):{p}:Received SYN_ACK') established = True ack_pkt = make_ack(ACK, 0, server) logging.debug(f'(client->{server}):{ack_pkt}:Send ACK') self.conn.sendto(ack_pkt.to_bytes(), router) logging.debug("(Handshake Finished)") return established
def send_response(self, client, packet, router, server): if packet.packet_type == ACK: # check if all packets have received acks self.validate_ack(client, packet, server) else: # make response into packets and send them # combine packets to data payload = [self.clients[client]["request"][p].payload for p in sorted(self.clients[client]["request"].keys())] raw_request = b''.join(payload) logging.debug(f'(request) {raw_request}') # make http response if len(raw_request) == 0: response = make_http_response([], 'Bad Request', 400) else: request = parse_http_request(raw_request) # Get a parsed HTTP request # Invoke get or post handler based on the request type request_handler = getattr(self, 'handle_%s' % request["method"]) response = request_handler(request) logging.debug(f'(response) {response.encode("utf-8")}') # send http response packets = split_data_into_packets(response, client) fin_pkt = make_ack(FIN, len(packets) + 1, client) packets.append(fin_pkt) for j in range(math.ceil(len(packets)/WINDOW)): for p in packets[WINDOW*j:WINDOW*(j+1)]: #packets logging.debug(f'({server}->{client}):{p}:Sending response packet') self.conn.sendto(p.to_bytes(), router) # store packets in dict, later use that dict for checking acks self.clients[client]["response"][p.seq_num] = p self.conn.settimeout(TIMEOUT)
def send_request(self, request): server = self.host, self.port # send request packets packets = split_data_into_packets(request, server) fin_pkt = make_ack(FIN, len(packets) + 1, server) packets.append(fin_pkt) for j in range(math.ceil(len(packets) / WINDOW)): for p in packets[WINDOW * j:WINDOW * (j + 1)]: # packets logging.debug(f'(client->{server}):{p}:Send Request Packet') self.conn.sendto(p.to_bytes(), self.router) # store packets in dict, later use that dict for checking acks self.communication["request"][p.seq_num] = p # validate acks for request packets while True: try: raw_packet, router = self.conn.recvfrom(1024) except socket.timeout: for key in self.communication["request"].keys(): logging.debug( f'(client->{server}):{self.communication["request"][key]}:Timeout, resending Request Packet') self.conn.sendto(self.communication["request"][key].to_bytes(), self.router) continue packet = Packet.from_bytes(raw_packet) if packet.packet_type == SYN_ACK: logging.debug( f'({server}->client):{packet}:Received SYN_ACK (Server didn"t receive ACK from handshake)') ack_pkt = make_ack(ACK, 0, server) logging.debug(f'(client->{server}):{ack_pkt}:Send ACK') self.conn.sendto(ack_pkt.to_bytes(), router) logging.debug("(Handshake Finished)") return False if packet.seq_num in self.communication["request"]: logging.debug(f'({server}->client):{packet}:ACK received') # remove a request packet from dict if ack is received del self.communication["request"][packet.seq_num] # if no packets in response dict, all the packets have been sent is_response_complete = len(self.communication["request"]) == 0 if is_response_complete: logging.debug(f'(client->{server}):Request Finished') # close connection return True else: logging.debug(f'({server}->client):{packet}: Duplicate ACK received, ignoring it')
def handshake_server(self, client, packet, router, server): if packet.packet_type == SYN: logging.debug(f'({client}->{server}):{packet}:Received SYN') # send syn-ack syn_ack_pkt = make_ack(SYN_ACK, packet.seq_num, client) logging.debug(f'({server}->{client}):{syn_ack_pkt}:Sending SYN-ACK') self.conn.sendto(syn_ack_pkt.to_bytes(), router) if packet.packet_type == DATA: logging.debug( f'({client}->{server}):{packet}:Received data, without handshake -> client"s ACK lost, send SYN-ACK') syn_ack_pkt = make_ack(SYN_ACK, packet.seq_num - 1, client) self.conn.sendto(syn_ack_pkt.to_bytes(), router) if packet.packet_type == ACK: # add sender to connections logging.debug(f'({server}->{client}):Received ACK, Connection Established') self.clients[client] = { "request": {}, "response": {} }
def recieve_request(self, client, packet, router, server): # receive packets ack_pkt = make_ack(ACK, packet.seq_num, client) if packet.packet_type == DATA: if packet.seq_num in self.clients[client]["request"]: # duplicate seq num detected send ack logging.debug(f'({server}->{client}):{ack_pkt}:Duplicate detected, Sending ACK') else: # add received packet to request dict and send ack self.clients[client]["request"][packet.seq_num] = packet logging.debug(f'({server}->{client}):{ack_pkt}:Received data packet, Sending ACK') if packet.packet_type == FIN: # last packet recieved, use seq num to store packets length logging.debug(f'({server}->{client}):{ack_pkt}:Received FIN, Sending ACK') self.clients[client]["request_length"] = packet.seq_num - 1 # send ack to client for the current packet self.conn.sendto(ack_pkt.to_bytes(), router)
def receive_response(self): server = self.host, self.port self.conn.settimeout(None) # receive packets while True: is_receive_complete = "response_length" in self.communication and self.communication[ "response_length"] == len( self.communication["response"]) if is_receive_complete: self.conn.settimeout(4*TIMEOUT) try: raw_packet, sender = self.conn.recvfrom(1024) except socket.timeout: logging.debug(f'(Received Response)') self.conn.settimeout(None) break packet = Packet.from_bytes(raw_packet) ack_pkt = make_ack(ACK, packet.seq_num, server) if packet.packet_type == DATA: if packet.seq_num in self.communication["response"]: # duplicate seq num detected send ack logging.debug(f'(client->{server}):{ack_pkt}:Duplicate detected, Sending ACK') else: # add received packet to request dict and send ack self.communication["response"][packet.seq_num] = packet logging.debug(f'(client->{server}):{ack_pkt}:Received data packet, Sending ACK') if packet.packet_type == FIN: # last packet recieved, use seq num to store packets length logging.debug(f'(client->{server}):{ack_pkt}:Received FIN, Sending ACK') self.communication["response_length"] = packet.seq_num - 1 # send ack to client for the current packet self.conn.sendto(ack_pkt.to_bytes(), self.router) # combine packets to data payload = [self.communication["response"][p].payload for p in sorted(self.communication["response"].keys())] raw_response = b''.join(payload) logging.debug(f'(response) {raw_response}') return raw_response