def client_receiver(data, address):
    server_log = open('server_log.txt', 'w+')
    print("Client {} Connected".format(address[1]))
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_port = new_port()
    server_new_address_port = ('localhost', server_port)
    server_socket.bind(server_new_address_port)
    state = states[1]
    last_sent_ack = None
    client_port = address[1]
    initial_sequence_number = 0
    ack_to_send = data.sequenceNumber+1
    packet = TCPHeader.TCPHeader(client_port, server_port, initial_sequence_number, ack_to_send, 1, 1, 0, 1000).get()
    server_socket.sendto(packet, address)
    last_sent_ack = ack_to_send-1
    state = states[2]
    while state == states[2]:
        data, address = server_socket.recvfrom(20)
        data = TCPHeader.make_tcp_from_bytes(data)
        if data.ackFlag and data.ackNumber == initial_sequence_number+1:
            state = states[3]
            ack_to_send, last_sent_ack = send_ack(server_socket, data, last_sent_ack, client_port, server_port, initial_sequence_number, address, ack_to_send)
    while state == states[3]:
        data, address = server_socket.recvfrom(20)
        data = TCPHeader.make_tcp_from_bytes(data)
        print("Packet {} Received".format(data.sequenceNumber), file=server_log)
        ack_to_send, last_sent_ack = send_ack(server_socket, data, last_sent_ack, client_port, server_port, initial_sequence_number, address, ack_to_send)
        if data.finFlag:
            state = states[4]
    print("Connection Closed")
def receiver():
    global state, states, server_ip, server_port, server_ip_port, client_port, udp_client_socket, establish_time, initial_sequence_number, last_acked, fin_recvd, last_received, base_time, base, window, alpha, beta, dev_rtt, estimated_rtt, timeout, dropped, fin_number, sample_log, window_log
    while not fin_recvd:
        try:
            received_packet, address = udp_client_socket.recvfrom(20)
        except:
            continue
        received_tcp = TCPHeader.make_tcp_from_bytes(received_packet)
        if received_tcp.ackFlag:
            if received_tcp.ackNumber > last_acked:
                window = min(window + (received_tcp.ackNumber - last_acked), 20)
                for i in range(last_acked, received_tcp.ackNumber):
                    if i not in dropped:
                        sent_time_set = False
                        while not sent_time_set:
                            try:
                                sample = time.time() - sent_time[str(i)]
                                sent_time_set = True
                            except KeyError:
                                sent_time_set = False
                        print(sample, file=sample_log)
                        estimated_rtt = (1-alpha) * estimated_rtt + alpha*sample
                        dev_rtt = (1 - beta) * dev_rtt + beta*(abs(sample - estimated_rtt))
                        timeout = estimated_rtt + 4 * dev_rtt
                # print("Timeout = {}".format(timeout))
                # print("Window = {}".format(window))
            last_acked = received_tcp.ackNumber
            if received_tcp.ackNumber > base:
                base_time = time.time()
                base = received_tcp.ackNumber
        if received_tcp.sequenceNumber == last_received+1 or last_received is None:
            last_received = received_tcp.sequenceNumber
    return
def main_receiver():
    global main_server_socket
    while True:
        data, address = main_server_socket.recvfrom(20)
        data = TCPHeader.make_tcp_from_bytes(data)
        if data.synFlag:
            test_file = open('test.txt', 'w+')
            thread = threading.Thread(target=client_receiver, args=(data, address))
            thread.start()
def main_receiver():
    global main_server_socket
    while True:
        data, address = main_server_socket.recvfrom(20)
        data = TCPHeader.make_tcp_from_bytes(data)
        if data.synFlag:
            print("Received in main receiver", data)
            thread = threading.Thread(target=client_receiver,
                                      args=(data, address))
            thread.start()
def handshake():
    global state, states, server_ip, server_port, server_ip_port, client_port, udp_client_socket, establish_time, initial_sequence_number, last_acked, last_sent, base_time, base, last_sent_time, last_sent, last_received
    while state != states[2]:
        if state == states[0]:
            initial_sequence_number = 1
            expected_ack = initial_sequence_number + 1
            packet = TCPHeader.TCPHeader(client_port, server_port, initial_sequence_number, 0, 0, 1, 0, 1000).get()
            udp_client_socket.sendto(packet, server_ip_port)
            last_sent = initial_sequence_number
            sent_time[str(last_sent)] = time.time()
            last_sent_time = sent_time[str(last_sent)]
            base = initial_sequence_number
            base_time = last_sent_time
            state = states[1]
        elif state == states[1]:
            if time.time() - base_time > timeout:
                packet = TCPHeader.TCPHeader(client_port, server_port, initial_sequence_number, 0, 0, 1, 0, 1000).get()
                udp_client_socket.sendto(packet, server_ip_port)
                last_sent = initial_sequence_number
                sent_time[str(last_sent)] = time.time()
                last_sent_time = sent_time[str(last_sent)]
                base = initial_sequence_number
                base_time = last_sent_time
                continue
            try:
                received_packet, address = udp_client_socket.recvfrom(20)
            except:
                continue
            server_port = address[1]
            server_ip = address[0]
            server_ip_port = (server_ip, server_port)
            received_tcp = TCPHeader.make_tcp_from_bytes(received_packet)
            if received_tcp.ackFlag and received_tcp.ackNumber == expected_ack and received_tcp.synFlag:
                last_acked = expected_ack
                establish_time = time.time()
                last_received = received_tcp.sequenceNumber
                ack_to_send = received_tcp.sequenceNumber + 1
                packet = TCPHeader.TCPHeader(client_port, server_port, expected_ack, ack_to_send, 1, 0, 0, 1000).get()
                initial_sequence_number = expected_ack
                last_sent = expected_ack
                sent_time[str(expected_ack)] = time.time()
                udp_client_socket.sendto(packet, server_ip_port)
                base = last_sent
                base_time = sent_time[str(expected_ack)]
                state = states[2]
    return True
def client_receiver(data, address):
    pprint(vars(data))
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_port = new_port()
    server_new_address_port = ('localhost', server_port)
    server_socket.bind(server_new_address_port)
    state = states[1]
    last_sent_ack = None
    client_port = address[1]
    initial_sequence_number = 0
    ack_to_send = data.sequenceNumber + 1
    packet = TCPHeader.TCPHeader(client_port, server_port,
                                 initial_sequence_number, ack_to_send, 1, 1, 0,
                                 1000).get()
    server_socket.sendto(packet, address)
    last_sent_ack = ack_to_send - 1
    state = states[2]
    tmp = 2
    while state == states[2]:
        data, address = server_socket.recvfrom(20)
        data = TCPHeader.make_tcp_from_bytes(data)
        if data.ackFlag and data.ackNumber == initial_sequence_number + 1:
            state = states[3]
            ack_to_send, last_sent_ack = send_ack(server_socket, data,
                                                  last_sent_ack, client_port,
                                                  server_port,
                                                  initial_sequence_number,
                                                  address, ack_to_send)
    fin_time = 0
    print("Y")
    # tmp = 2
    while state == states[3] or (state == states[4]
                                 and time.time() - fin_time < 1):
        # print(state, fin_time, time.time())
        # print("Z")
        data, address = server_socket.recvfrom(20)
        # print("P")
        data = TCPHeader.make_tcp_from_bytes(data)
        # if tmp == 1:
        #     pprint(vars(data))
        # if data.finFlag and tmp > 0:
        #     print("HOOOOOOOOOY", tmp)
        #     print("aCKK tO sEnD", ack_to_send)
        #     tmp -= 1
        #     continue
        ack_to_send, last_sent_ack = send_ack(server_socket, data,
                                              last_sent_ack, client_port,
                                              server_port,
                                              initial_sequence_number, address,
                                              ack_to_send)
        if data.finFlag and state != states[4]:
            # print("W")
            state = states[4]
            fin_time = time.time()

    print("X")
    tmp = 2
    state = states[5]
    initial_sequence_number += 1
    packet = TCPHeader.TCPHeader(client_port, server_port,
                                 initial_sequence_number, ack_to_send, 0, 0, 1,
                                 1000).get()
    server_socket.sendto(packet, address)
    print(initial_sequence_number + 1)
    while state == states[5]:
        data, address = server_socket.recvfrom(20)
        data = TCPHeader.make_tcp_from_bytes(data)
        print("S")
        if data.ackFlag and data.ackNumber == initial_sequence_number + 1:
            if tmp > 2:
                tmp -= 1
                continue
            state = states[6]
            print("Done")