def handle(self):
        """
        Handle requests from the clients.
        :return:
        """
        global auth_dict, nonce_dict, crypto_service, password_hash_dict, user_addr_dict, chatting_service
        msg = self.request[0]
        sock = self.request[1]
        # get auth instance for client
        if self.client_address not in auth_dict:
            try:
                _, msg_parts = PacketOrganiser.process_packet(msg)
            except:
                return
            if msg_parts[0] != c.GREETING:
                return
            # new client, create an auth entry in the auth dictionary
            auth_dict[self.client_address] = Authentication(
                self.client_address, crypto_service, password_hash_dict)
        else:
            auth = auth_dict[self.client_address]
            if not PacketOrganiser.isValidTimeStampSeconds(
                    auth.timestamp, c.KEEP_ALIVE_TIME):
                auth_dict.pop(self.client_address)

        cur_auth = auth_dict[self.client_address]
        assert isinstance(cur_auth, Authentication)
        rep = None
        if not cur_auth.is_auth():
            rep = cur_auth.process_request(msg, user_addr_dict)

        else:
            # get decrypted msg
            dec_msg = crypto_service.sym_decrypt(cur_auth.dh_key, msg)
            n, msg_ps = PacketOrganiser.process_packet(dec_msg)
            auth_dict[
                self.
                client_address].timestamp = PacketOrganiser.get_new_timestamp(
                )  # update timestamp
            rep = chatting_service.get_response(self.client_address, msg_ps)
            if rep is not None:
                rep = PacketOrganiser.prepare_packet(rep, n)
                rep = crypto_service.sym_encrypt(cur_auth.dh_key, rep)

        try:
            if rep is not None:
                sys.stdout.flush()
                sock.sendto(rep, self.client_address)
            elif cur_auth.is_auth():
                cur_auth.loginfailures += 1
        except socket.error:
            print(c.FAIL_MSG_FWD)
            return
 def handle_list(self):
     """
     :return: Handles the list input and sends the list of active users as response.
     """
     res = ""
     for user, addr in self.user_addr_dict.iteritems():
         auth = self.auth_dict[addr]
         if not PacketOrganiser.isValidTimeStampSeconds(
                 auth.timestamp, c.KEEP_ALIVE_TIME):
             self.auth_dict.pop(addr)
             continue
         res += user + ","
     return [c.MSG_TYPE_LIST, res[:-1], ""]
    def handle(self):
        """
        Handle requests from the clients.
        :return:
        """
        global auth_dict, nonce_dict, crypto_service, password_hash_dict, user_addr_dict, chatting_service
        msg = self.request[0]
        sock = self.request[1]
        # get auth instance for client
        if self.client_address not in auth_dict:
            try:
                _, msg_parts = PacketOrganiser.process_packet(msg)
            except:
                return
            if msg_parts[0] != c.GREETING:
                return
            # new client, create an auth entry in the auth dictionary
            auth_dict[self.client_address] = Authentication(self.client_address, crypto_service,
                                                                           password_hash_dict)
        else:
            auth = auth_dict[self.client_address]
            if not PacketOrganiser.isValidTimeStampSeconds(auth.timestamp,c.KEEP_ALIVE_TIME):
                auth_dict.pop(self.client_address)

        cur_auth = auth_dict[self.client_address]
        assert isinstance(cur_auth, Authentication)
        rep = None
        if not cur_auth.is_auth():
            rep = cur_auth.process_request(msg, user_addr_dict)

        else:
            # get decrypted msg
            dec_msg = crypto_service.sym_decrypt(cur_auth.dh_key, msg)
            n, msg_ps = PacketOrganiser.process_packet(dec_msg)
            auth_dict[self.client_address].timestamp = PacketOrganiser.get_new_timestamp()  # update timestamp
            rep = chatting_service.get_response(self.client_address, msg_ps)
            if rep is not None:
                rep = PacketOrganiser.prepare_packet(rep, n)
                rep = crypto_service.sym_encrypt(cur_auth.dh_key, rep)

        try:
            if rep is not None:
                sys.stdout.flush()
                sock.sendto(rep, self.client_address)
            elif cur_auth.is_auth():
                cur_auth.loginfailures += 1
        except socket.error:
            print(c.FAIL_MSG_FWD)
            return
    def resend(self, cache):
        """
        :param cache: The parameter cache stores what message haven't acknowledged to resend them.
        :return: True if resend happened, False otherwise
        """
        global server_auth
        # first check if the cache is more than 30 seconds old
        # if it is, we will drop the cache entry, which means the other side is off line, don't resend again
        if cache[c.CACHE_TYPE_IND] == c.MSG_TYPE_MSG:
            original_ts = self.get_original_ts(cache)
            if not PacketOrganiser.isValidTimeStampSeconds(original_ts, c.RESEND_TIMEOUT):
                util.cmd_output(c.WARNING_STOP_RESENDING)
                return False

        ts = PacketOrganiser.get_new_timestamp()
        cache[c.CACHE_TS_IND] = ts
        msg = util.replace_ts_in_msg(cache[c.CACHE_MSG_IND])
        # cache[c.CACHE_MSG_IND] = msg
        enc_msg = server_auth.crypto_service.sym_encrypt(cache[c.CACHE_KEY_IND], msg)
        self.sock.sendto(enc_msg, cache[c.CACHE_ADDR_IND])
        return True
 def handle_start_new_chat(self, a_addr, b_username):
     """
     b_addr, k_ab, ttb, ts, n1
     :param a_addr: Chat requesting client address
     :param b_addr: Address of client wanting to chat with
     :return: The server sends as response the ticket to b and a symettric key to talk to b.
     """
     k_ab = self.auth_dict[a_addr].crypto_service.new_sym_key()
     a_username = self.auth_dict[a_addr].username
     b_addr = self.user_addr_dict[b_username]
     auth = self.auth_dict[b_addr]
     if not PacketOrganiser.isValidTimeStampSeconds(auth.timestamp,
                                                    c.KEEP_ALIVE_TIME):
         self.auth_dict.pop(b_addr)
         return c.ERR_CLIENT_DOWN
     k_b = self.auth_dict[b_addr].dh_key
     ttb = PacketOrganiser.prepare_packet(
         [a_username, util.addr_to_str(a_addr), k_ab])
     enc_ttb = self.crypto_service.sym_encrypt(k_b, ttb)
     signed_enc_ttb = enc_ttb + self.crypto_service.rsa_sign(enc_ttb)
     return [util.addr_to_str(b_addr), k_ab, signed_enc_ttb]
    def resend(self, cache):
        """
        :param cache: The parameter cache stores what message haven't acknowledged to resend them.
        :return: True if resend happened, False otherwise
        """
        global server_auth
        # first check if the cache is more than 30 seconds old
        # if it is, we will drop the cache entry, which means the other side is off line, don't resend again
        if cache[c.CACHE_TYPE_IND] == c.MSG_TYPE_MSG:
            original_ts = self.get_original_ts(cache)
            if not PacketOrganiser.isValidTimeStampSeconds(
                    original_ts, c.RESEND_TIMEOUT):
                util.cmd_output(c.WARNING_STOP_RESENDING)
                return False

        ts = PacketOrganiser.get_new_timestamp()
        cache[c.CACHE_TS_IND] = ts
        msg = util.replace_ts_in_msg(cache[c.CACHE_MSG_IND])
        # cache[c.CACHE_MSG_IND] = msg
        enc_msg = server_auth.crypto_service.sym_encrypt(
            cache[c.CACHE_KEY_IND], msg)
        self.sock.sendto(enc_msg, cache[c.CACHE_ADDR_IND])
        return True