def start(self):
        '''
        Main loop.
        continue receiving messages from Clients and processing it
        '''
        threads = {} #Dictionary for multi-threading

        #Main loop
        while True:
            receiveMessage, address = self.sock.recvfrom(4096)
            messageType, sequenceNumber, breakMessage, _ = util.parse_packet(receiveMessage.decode("utf-8"))
            sendSequence = int(sequenceNumber) + 1

            #If the checksum of the received packet is valid
            if util.validate_checksum(receiveMessage.decode("utf-8")):
                #If we get a start packet initialize a new queue for that respective client and make a thread of process_handler for it and send ack packet to client
                if messageType == "start":
                    self.receive_start(address, sendSequence, threads)

                #If we get a data packet send ack packet to client and wait for next packet
                elif messageType == "data":
                    self.receive_data(address, sendSequence, breakMessage)

                #If we get a end packet we will delete the thread from the dictionary
                elif messageType == "end":
                    self.receive_end(address, sendSequence, threads)

                #If we receive ack message from client we will update acknowledged and send the next packet to the client in send function
                elif messageType == "ack":
                    self.receive_ack(address, sendSequence)
예제 #2
0
 def construct_message(self, all_packets):
     '''
      leave out end and start packets and make complete message from the packets recieved
     '''
     packets_to_use = len(all_packets) - 1
     msg = ""
     for i in range(1, packets_to_use):
         p_type, seqno, data, checksum = util.parse_packet(all_packets[i])
         msg = msg + data
     return msg
예제 #3
0
def listener(thread_quit, port):
    '''
    Fungsi utama yang mendengarkan semua pesan masuk
    Exclusive access ke port yang diatur

    Args:
        thread_quit (threading.Event) : Signaling untuk memberitahu jika thread selesai
        port (int) : Port number untuk dibind
    '''

    # Setup socket
    listener_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    listener_socket.setblocking(False)
    listener_socket.bind(("", port))

    while (not thread_quit.is_set()):
        try:
            data, addr = listener_socket.recvfrom(MAX_LENGTH_DATA +
                                                  LENGTH_TYPE_ID +
                                                  LENGTH_CHECKSUM +
                                                  LENGTH_LENGTH +
                                                  LENGTH_SEQUENCE)

            packet_data = parse_packet(data)
            data_type = packet_data["type"]

            if data_type != PacketType.INVALID:
                source_address = addr[0]
                data_ID = packet_data["id"]

                # Jika Data atau FIN buat thread listener, jika tidak passing ke thread sender
                if data_type == PacketType.DATA or data_type == PacketType.FIN:
                    if thread_pool_listener.get(source_address) == None:
                        thread_pool_listener[source_address] = [None] * 16

                    if thread_pool_listener[source_address][data_ID] == None:
                        handler = Queue()
                        thread_pool_listener[source_address][data_ID] = handler
                        threading.Thread(target=receive_thread,
                                         args=((source_address, port),
                                               handler)).start()
                        handler.put(packet_data)
                    else:
                        thread_pool_listener[source_address][data_ID].put(
                            packet_data)
                else:
                    if (thread_pool_sender[source_address][data_ID] != None):
                        thread_pool_sender[source_address][data_ID].put(
                            packet_data)

        except socket.error:
            pass

    listener_socket.close()
    def receive_handler(self):
        '''
        Waits for a message from server and process it accordingly
        '''
        global stop  #To stop the main loop

        #Main loop
        while not stop:
            revieveMessage, address = self.sock.recvfrom(self.server_port)
            _, _, breakMessage, _ = util.parse_packet(
                revieveMessage.decode("utf-8"))
            breakMessage = breakMessage.split()

            #If the clients request to join has been rejected
            if breakMessage[0].strip() == "join":
                print(breakMessage[2])

            #If the clients request for active user list has been processed
            elif breakMessage[0].strip() == "response_users_list":
                print("list:", " ".join(breakMessage[2:]))

            #If someone has send a message
            elif breakMessage[0].strip() == "forward_message":
                print("msg:", " ".join(breakMessage[2:]))

            #If someone has send a file
            elif breakMessage[0].strip() == "forward_file":
                fileName = breakMessage[3]
                fileData = " ".join(breakMessage[4:])
                print("file:", breakMessage[2] + ":", fileName)
                fileName = self.name + "_" + fileName
                fileHandle = open(fileName, "w")
                fileHandle.write(fileData)
                fileHandle.close()

            #If the server is full
            elif breakMessage[0].strip() == "err_server_full":
                print("disconnected: server full")
                stop = True
                self.sock.close()

            #If the username is already taken
            elif breakMessage[0].strip() == "err_username_unavailable":
                print("disconnected: username not available")
                stop = True
                self.sock.close()

            #If the client send an unknown message format
            elif breakMessage[0].strip() == "err_unknown_message":
                print("disconnected: server received an unknown command")
                stop = True
                self.sock.close()
예제 #5
0
    def start(self):
        '''
        Main loop.
        continue receiving messages from Clients and processing it
        '''
        global transfer
        global acknowledged
        global nextSeqNumber
        global acknowledgedAddress
        threads = {}  #Dictionary for multi-threading

        #Main loop
        while True:
            receiveMessage, address = self.sock.recvfrom(4094)
            messageType, sequenceNumber, breakMessage, _ = util.parse_packet(
                receiveMessage.decode("utf-8"))
            sendSequence = int(sequenceNumber) + 1

            #If we get a start packet initialize a new queue for that respective client and make a thread of process_handler for it and send ack packet to client
            if messageType == "start":
                transfer[address] = queue.Queue()
                threads[address] = Thread(target=self.process_handler,
                                          args=(address, ))
                threads[address].daemon = True
                threads[address].start()
                sendPacket = util.make_packet(
                    "ack",
                    sendSequence,
                )
                self.sock.sendto(sendPacket.encode("utf-8"), address)

            #If we get a data packet send ack packet to client and wait for next packet
            elif messageType == "data":
                transfer[address].put(breakMessage)
                sendPacket = util.make_packet(
                    "ack",
                    sendSequence,
                )
                self.sock.sendto(sendPacket.encode("utf-8"), address)

            #If we get a end packet we will delete the thread from the dictionary
            elif messageType == "end":
                transfer[address].put(messageType)
                del threads[address]

            #If we receive ack message from client we will update acknowledged and send the next packet to the client in send function
            elif messageType == "ack":
                nextSeqNumber = int(sequenceNumber)
                acknowledgedAddress = address
                acknowledged = True
예제 #6
0
    def start(self):
        '''
        Main loop.
        continue receiving messages from Clients and processing it
        '''
        while True:

            packet, addr = self.sock.recvfrom(4096)

            #initialize buffers for every new request
            if addr not in self.ack_buffer or addr not in self.ack_queue:
                self.ack_buffer[addr] = -1
                self.ack_queue[addr] = queue.Queue(maxsize=1)

            p_type, seqno, message, checksum = util.parse_packet(
                packet.decode("utf-8"))
            #if the packet is ack store in buffer
            if p_type == "ack":
                self.ack_buffer[addr] = int(seqno)
                q = self.ack_queue[addr]
                q.put(int(seqno))

            #create a buffer for the incoming address
            if addr not in self.packet_buff:
                self.packet_buff[addr] = {}

            #store the packets in the buffer
            if p_type != "ack":
                self.packet_buff[addr][int(seqno)] = packet.decode("utf-8")

            ##checks whether complete packets were recieved or not

            tmp = message.split()
            #dont send acknowledgment for acknowledgment
            if p_type != "ack":
                self.send_ack(packet, addr)

            if (p_type == "end"):
                # every time and end packet is received
                # it means that all data has bess received
                # hence to process that data a new thread is made so that
                # main thread never gets blocked

                processDataThread = Thread(target=self.processAndServe,
                                           args=(addr, ))
                processDataThread.daemon = True
                processDataThread.start()
예제 #7
0
    def receive_handler(self):
        '''
        Waits for a message from server and process it accordingly
        
        '''
        while True:

            packet = self.sock.recv(util.CHUNK_SIZE)
            packet = packet.decode('utf-8')
            message = util.parse_packet(packet)[2]
            msg = message.split(' ')

            if 'ERR_SERVER_FULL' in msg[0]:
                print(msg[2])
                self.sock.close()
                os._exit(1)
            elif 'ERR_USERNAME_UNAVAILABLE' in msg[0]:
                print(msg[2])
                self.sock.close()
                os._exit(1)

            elif 'response_list' in msg[0]:
                msg1 = msg[2].replace('$', " ")
                print(f"list: {msg1}")

            elif 'FORWARD' in msg[0]:
                msg1 = ' '.join(msg[2:])
                msg1 = msg1.replace('  ', ' ')
                print(msg1)

            elif 'DISCONNECT' in msg[0]:
                print('disconnected: server received a unknown command')
                self.sock.close()
                os._exit(1)

            elif 'forward_file' in msg[0]:

                client = msg[2]
                file = msg[3]
                data = msg[4].replace('[s]', ' ').replace('[nl]', '\n')
                with open(f'{client}_{file}', 'w+') as f:
                    f.write(data)
                    f.close()
                print(f'file: {client}: {file}')
예제 #8
0
    def waitAndreSend(self, packet, addr):
        '''
         in the case of single packet transmission, send the packet and then wait for its acknowledgemtn
         if the ack is recieved within 0.5 ms then good, otherwise resend packer

         '''
        msg_type, seqno, message, checksum = util.parse_packet(packet)

        pack_n = int(seqno) + 1
        sent = False
        resend = 5
        while sent == False and resend > 0:
            try:
                ackbuf = self.ack_queue[addr]
                ack = ackbuf.get(timeout=0.5)
                sent = True
            except:
                resend = resend - 1
                self.send_res(packet, addr)
    def start(self):
        '''
        Main loop.
        continue receiving messages from Clients and processing it
        '''
        clientUsername = []  #Will store the usernames of the clients
        clientData = {
        }  #Will store the address of the clients with usernames as the key
        usernameExists = False  #Boolian variable to check if the username is already taken or not
        clientConnected = 0  #Variable to track the number of clients connected
        sendMessage = ""  #The message that will be made
        sendPacket = ""  #The packer that will be send

        #Main loop
        while True:

            #Recieve the message, parse it and break into list
            revieveMessage, address = self.sock.recvfrom(4096)
            _, _, breakMessage, _ = util.parse_packet(
                revieveMessage.decode("utf-8"))
            breakMessage = breakMessage.split()

            #Check if the client has sent the join message
            if breakMessage[0].strip() == "join":
                #Check if the maximum client limit has been reached
                if clientConnected == util.MAX_NUM_CLIENTS:
                    self.send(address, "err_server_full", 2)
                    print("disconnected: server full")
                #If the client limit has not been reached
                else:
                    #Traverse the client username list to check if the username is already taken
                    for username in clientUsername:
                        #If the username already exits
                        if breakMessage[2].strip() == username.strip():
                            self.send(address, "err_server_full", 2)
                            usernameExists = True
                            print("disconnected: username not available")
                            break
                    #If the username does not exist
                    if not usernameExists:
                        clientUsername.append(breakMessage[2])
                        clientUsername.sort(key=str.casefold)
                        clientData[breakMessage[2]] = address
                        clientConnected += 1
                        print("join:", breakMessage[2])
                    usernameExists = False

            #Check if the client has requested the active users list
            elif breakMessage[0].strip() == "request_users_list":
                print("request_users_list:", util.get_key(clientData, address))
                listCompile = ""
                #Traverse the client username list
                for username in clientUsername:
                    listCompile += username + " "
                self.send(address, "response_users_list", 3, listCompile)

            #Check if the client wants to send the message
            elif breakMessage[0].strip() == "send_message":
                #Check if the message does not contain a character on <numberOfClients> part
                if not breakMessage[3].isdigit():
                    self.send(address, "err_unknown_message", 2)
                    print("disconnected:", util.get_key(clientData, address))
                #Check if the number of usernames enters is not less than specified in the message
                elif len(breakMessage) - 4 <= int(breakMessage[3]):
                    self.send(address, "err_unknown_message", 2)
                    print("disconnected:", util.get_key(clientData, address))
                #If no format error
                else:
                    print("msg:", util.get_key(clientData, address))
                    end = int(breakMessage[3]) + 4
                    #Traverse through the usernames to which client wants to send the message to
                    for i in range(4, end):
                        #The destination username exits
                        if clientData.get(breakMessage[i]) is not None:
                            message = util.get_key(clientData,
                                                   address) + ": " + " ".join(
                                                       breakMessage[end:])
                            destinationAddress = ((clientData.get(
                                breakMessage[i]))[0], (clientData.get(
                                    breakMessage[i]))[1])
                            self.send(destinationAddress, "forward_message", 4,
                                      message)
                        #The destination username does not exits
                        else:
                            print("msg:", util.get_key(clientData, address),
                                  "to non-existent user", breakMessage[i])

            #Check if the client wants to send a file
            elif breakMessage[0].strip() == "send_file":
                #Check if the message does not contain a character on <numberOfClients> part
                if not breakMessage[3].isdigit():
                    self.send(address, "err_unknown_message", 2)
                    print("disconnected:", util.get_key(clientData, address))
                #If there is no format error
                else:
                    print("file:", util.get_key(clientData, address))
                    end = int(breakMessage[3]) + 4
                    #Traverse through the usernames to which client wants to send the message to
                    for i in range(4, end):
                        #The destination username exits
                        if clientData.get(breakMessage[i]) is not None:
                            message = util.get_key(clientData,
                                                   address) + " " + " ".join(
                                                       breakMessage[end:])
                            destinationAddress = ((clientData.get(
                                breakMessage[i]))[0], (clientData.get(
                                    breakMessage[i]))[1])
                            self.send(destinationAddress, "forward_file", 4,
                                      message)
                        #The destination username does not exits
                        else:
                            print("file:", util.get_key(clientData, address),
                                  "to non-existent user", breakMessage[i])

            #Check if the client wants to disconnet
            elif breakMessage[0].strip() == "disconnect":
                clientUsername.remove(breakMessage[2])
                clientData.pop(breakMessage[2])
                clientConnected -= 1
                print("disconnected:", breakMessage[2])

            #If the format recieved is something unknown
            else:
                print("disconnected:", util.get_key(clientData, address),
                      "sent unknown command")
                self.send(address, "err_unknown_message", 2)
예제 #10
0
    def receive_handler(self):
        '''
        Waits for a message from server and process it accordingly
        '''

        while True:
            start = False
            end = False

            # loop from start packet to end packet
            while (start == False or end == False):
                packet = self.sock.recv(4096)
                p_type, seqno, res, checksum = util.parse_packet(
                    packet.decode("utf-8"))
                if (p_type == "ack"):  # store ack in ack buffer
                    self.ack_buffer = int(seqno)
                    self.ack_queue.put(int(seqno), block=True)
                if p_type != "ack":  # if not ack buffer the packer
                    self.packet_buff[int(seqno)] = packet.decode("utf-8")
                if p_type == "start":
                    start = True
                if p_type == "end":
                    end = True
                if p_type != "ack":  #send ack for every packet received
                    self.send_ack(packet)

            #get packets from buffer
            all_packets = self.getPacketsFromBuffer()

            # construct full message frm the packets
            res = self.construct_message(all_packets)

            #process data here
            res_unsplit = res
            res = res.split()
            res_type = res[0]

            # max number of client reached
            if res_type == "err_server_full":
                # print("disconnected: server full")
                os._exit(1)
            # username is already taken or unavailable
            elif res_type == "err_username_unavailable":
                # print("disconnected: username not available")
                os._exit(1)
            elif res_type == "response_users_list":
                total_clients = res[2]
                total_clients = int(total_clients)
                out = "list:"
                for i in range(3, total_clients + 3):
                    out = out + " " + res[i]
                print(out)
            elif res_type == "forward_message":
                sender = res[3]
                recieved_text = ''
                for i in range(4, len(res)):
                    recieved_text = recieved_text + " " + res[i]
                recieved_text = recieved_text.strip()

                print("msg:", sender + ":", recieved_text)
            elif res_type == "forward_file":
                sender = res[3]
                file_recieved = res[4]

                d = res_unsplit.split("<delimtter>")
                text = d[1]
                print("file:", sender + ":", file_recieved)
                f = open(self.name + "_" + file_recieved, 'w')
                f.write(text)
                f.close()
            elif res_type == "err_unknown_message":
                os._exit(1)
            self.resetBuffer()
            self.reset_ack_queue()
예제 #11
0
    def receive_handler(self):
        '''
        Waits for a message from server and process it accordingly
        '''
        global stop
        global acknowledged
        global nextSeqNumber
        chunks = []

        #Main loop
        while not stop:
            receiveMessage, address = self.sock.recvfrom(self.server_port)
            messageType, sequenceNumber, message, _ = util.parse_packet(
                receiveMessage.decode("utf-8"))

            #If client recieved the ack packet it will update acknowledged and send the next packet using the send function
            if messageType == "ack":
                nextSeqNumber = int(sequenceNumber)
                acknowledged = True

            #If client recieves the start packet then it will send ack packet and wait for next packet from the server
            elif messageType == "start":
                sendPacket = util.make_packet(
                    "ack",
                    int(sequenceNumber) + 1,
                )
                self.sock.sendto(sendPacket.encode("utf-8"),
                                 (self.server_addr, self.server_port))

            #If client recieves the data packet it will send ack packet and wait for the next packet from the server
            elif messageType == "data":
                chunks.append(message)
                sendPacket = util.make_packet(
                    "ack",
                    int(sequenceNumber) + 1,
                )
                self.sock.sendto(sendPacket.encode("utf-8"),
                                 (self.server_addr, self.server_port))

            #If client recieves the end packet it will join all the chunks together and process the message
            elif messageType == "end":
                extractMessage = ""
                #For each chunk recieved concatinate it into message
                for chunk in chunks:
                    extractMessage += chunk
                breakMessage = extractMessage.split()

                #If the clients request to join has been rejected
                if breakMessage[0].strip() == "join":
                    print(breakMessage[2])

                #If the clients request for active user list has been processed
                elif breakMessage[0].strip() == "response_users_list":
                    print("list:", " ".join(breakMessage[2:]))

                #If someone has send a message
                elif breakMessage[0].strip() == "forward_message":
                    print("msg:", " ".join(breakMessage[2:]))

                #If someone has send a file
                elif breakMessage[0].strip() == "forward_file":
                    fileName = breakMessage[3]
                    fileData = " ".join(breakMessage[4:])
                    print("file:", breakMessage[2] + ":", fileName)
                    fileName = self.name + "_" + fileName
                    fileHandle = open(fileName, "w")
                    fileHandle.write(fileData)
                    fileHandle.close()

                #If the server is full
                elif breakMessage[0].strip() == "err_server_full":
                    print("disconnected: server full")
                    stop = True
                    self.sock.close()

                #If the username is already taken
                elif breakMessage[0].strip() == "err_username_unavailable":
                    print("disconnected: username not available")
                    stop = True
                    self.sock.close()

                #If the client send an unknown message format
                elif breakMessage[0].strip() == "err_unknown_message":
                    print("disconnected: server received an unknown command")
                    stop = True
                    self.sock.close()

                chunks = []
예제 #12
0
    def receive_handler(self):
        '''
        Waits for a message from server and process it accordingly
        '''
        new_msg = ''

        while True:
            catch_packet = self.sock.recv(4096).decode("utf-8")
            msg_type, seq_no, msg, checksum = util.parse_packet(catch_packet)
            self.seq_no = seq_no

            print(catch_packet)

            if msg_type == 'ack':
                is_ack = True
                self.q.put(is_ack)
                print('received an ack put it into the client queue')
            elif msg_type == 'data':
                new_msg += msg
                print('new_msg concatenated')
            elif msg_type == 'end':
                msg_list = new_msg.split(' ')
                new_msg = ''
                if msg_list[0] == "response_users_list":
                    my_list = []
                    my_list = msg_list[3:]
                    my_list.sort()
                    str_out = ' '.join(my_list)
                    print('list:', str_out[2:])

                elif msg_list[0] == "disconnect":
                    print('disconnected')
                    self.sock.close()
                    sys.exit()
                    return

                elif msg_list[0] == 'forward_message':
                    print('msg:', msg_list[2] + ':', ' '.join(msg_list[3:]))

                elif msg_list[0] == 'err_username_unavailable':
                    print('disconnected: username not available')
                    self.sock.close()
                    sys.exit()
                    return
                elif msg_list[0] == 'err_server_full':
                    print('disconnected: server full')
                    self.sock.close()
                    sys.exit()
                    return
                elif msg_list[0] == 'err_unknown_message':
                    print('disconnected: server recieved an unknown command')
                    self.sock.close()
                    sys.exit()
                    return
                elif msg_list[0] == 'forward_file':
                    new_file_name = self.name + '_' + msg_list[3]
                    print('file:', msg_list[2] + ':', msg_list[3])
                    f = open(new_file_name, "x")
                    f.write(' '.join(msg_list[4:]))
                    f.close()
                else:
                    if len(new_msg) != 0:
                        print(new_msg)
    def receive_handler(self):
        '''
        Waits for a message from server and process it accordingly
        '''
        global STOP
        chunks = []

        #Main loop
        while not STOP:
            receiveMessage, _ = self.sock.recvfrom(self.server_port)
            messageType, sequenceNumber, message, _ = util.parse_packet(
                receiveMessage.decode("utf-8"))

            #If the checksum of the received packet is valid
            if util.validate_checksum(receiveMessage.decode("utf-8")):
                #If client recieved the ack packet it will update ACKNOWLEDGED and send the next packet using the send function
                if messageType == "ack":
                    self.receive_ack(sequenceNumber)

                #If client recieves the start packet then it will send ack packet and wait for next packet from the server
                elif messageType == "start":
                    self.receive_start(sequenceNumber, chunks)

                #If client recieves the data packet it will send ack packet and wait for the next packet from the server
                elif messageType == "data":
                    self.receive_data(sequenceNumber, chunks, message)

                #If client recieves the end packet it will join all the chunks together and process the message
                elif messageType == "end":
                    breakMessage = []
                    #For each chunk recieved concatinate it into message
                    breakMessage = self.receive_end(sequenceNumber, chunks)

                    #If the list is not empty
                    if breakMessage:
                        #If clients asks to join the server
                        if breakMessage[0].strip() == "join":
                            print(breakMessage[2])

                        #If the clients request for active user list has been processed
                        elif breakMessage[0].strip() == "response_users_list":
                            print("list:", " ".join(breakMessage[2:]))

                        #If someone has send a message
                        elif breakMessage[0].strip() == "forward_message":
                            print("msg:", " ".join(breakMessage[2:]))

                        #If someone has send a file
                        elif breakMessage[0].strip() == "forward_file":
                            fileName = breakMessage[3]
                            fileData = " ".join(breakMessage[4:])
                            print("file:", breakMessage[2] + ":", fileName)
                            fileName = self.name + "_" + fileName
                            fileHandle = open(fileName, "w")
                            fileHandle.write(fileData)
                            fileHandle.close()

                        #If the server is full
                        elif breakMessage[0].strip() == "err_server_full":
                            print("disconnected: server full")
                            STOP = True
                            self.sock.close()

                        #If the username is already taken
                        elif breakMessage[0].strip(
                        ) == "err_username_unavailable":
                            print("disconnected: username not available")
                            STOP = True
                            self.sock.close()

                        #If the client send an unknown message format
                        elif breakMessage[0].strip() == "err_unknown_message":
                            print(
                                "disconnected: server received an unknown command"
                            )
                            STOP = True
                            self.sock.close()

                        chunks = []