Esempio n. 1
0
    def __disconnect(session_id: int, address: tuple) -> bytes:
        """
        Closes session

        :param session_id: id of session to close
        :param address: address of the client
        :return: answer for the client
        """
        answer = Datagram(Status.OK, Mode.DISCONNECT, session_id)
        utils.log('removed session: ' + str(session_id) + ' : ' + str(address))
        return answer.get_bytes()
Esempio n. 2
0
    def __operation(self, session_id: int, operation: int, num_a: float,
                    num_b: float) -> bytes:
        """
        Makes requested calculations

        :param session_id:
        :param operation: id of rewuested operation
        :param num_a: number a
        :param num_b: number b
        :return: answer for the client
        """

        utils.log('received call for ' + Operation.name_from_code(operation) +
                  ' from session: ' + str(session_id))

        answer = Datagram(Status.OK, Mode.OPERATION, session_id, operation,
                          num_a, num_b)
        answer.result_id = self.next_result_id
        result: float

        try:
            if operation == Operation.POWER:
                result = num_a**num_b
            elif operation == Operation.LOG:
                result = log(num_b) / log(num_a)
            elif operation == Operation.GEO_MEAN:
                if num_a * num_b < 0:
                    return self.__error(5, Mode.OPERATION, session_id,
                                        operation)
                result = sqrt(num_a * num_b)
            elif operation == Operation.BIN_COE:
                if num_b > num_a or num_a < 0 or num_b < 0:
                    return self.__error(5, Mode.OPERATION, session_id,
                                        operation)
                result = factorial(num_a) / (factorial(num_a - num_b) *
                                             factorial(num_b))
        except OverflowError:
            return self.__error(Error.MAX_VALUE_EXCEEDED, Mode.OPERATION,
                                session_id, operation)

        if result == float('inf'):
            return self.__error(Error.MAX_VALUE_EXCEEDED, Mode.OPERATION,
                                session_id, operation)

        self.results_storage[session_id][self.next_result_id] = \
            (operation, num_a, num_b, session_id, result, self.next_result_id)

        self.next_result_id += 1

        answer.result = result
        return answer.get_bytes()
Esempio n. 3
0
    def __is_alive(self, session_id: int, handler: Thread) -> bytes:
        """
        Handles is alive request

        If session was closed on server, sends information about it to the client

        :param session_id: id of session to close
        :param handler: session handler
        :return: answer for the client
        """

        if self.sessions[handler]:
            answer = Datagram(Status.OK, Mode.IS_ALIVE, session_id)
        else:
            answer = Datagram(Status.REFUSED, Mode.IS_ALIVE, session_id)
        return answer.get_bytes()
Esempio n. 4
0
    def __connect(self, address: tuple) -> (bytes, int):
        """
        Establish new session

        :param address: client address
        :return: (answer to the client , given session_id)
        """

        # get id
        self.next_id_lock.acquire()
        given_id = self.next_id
        self.next_id += 1
        self.next_id_lock.release()
        # prepare answer
        answer = Datagram(Status.OK, Mode.CONNECT, given_id)
        utils.log('new session: ' + str(given_id) + ' : ' + str(address[0]))
        return answer.get_bytes(), given_id
Esempio n. 5
0
    def __error(code: int,
                mode: int = Mode.ERROR,
                session_id: int = 0,
                operation: int = 0) -> bytes:
        """
        Returns error answer

        :param code: error code
        :param mode: mode in which error occurred
        :param session_id: session id in which error occurred
        :param operation: operation in which error occurred
        :return: error answer for the client
        """
        utils.log(
            Error.name_from_code(code) + ' on session: ' + str(session_id) +
            ' mode: ' + Mode.name_from_code(mode), True)
        error = Datagram(Status.ERROR, mode, session_id, operation, a=code)
        return error.get_bytes()
Esempio n. 6
0
    def __send_datagram(self, datagram: Datagram) -> List[Datagram]:
        """
        Sends data to the server

        :param datagram: data to send
        :return: list of answers
        """
        self.socket.sendall(datagram.get_bytes())
        answer = list()
        last = False

        # receive data until last flag is send to true
        while last is False:
            # get data
            answer_bin = self.socket.recv(DATAGRAM_SIZE)
            try:
                # decode data
                answer_data = Datagram.from_bytes(answer_bin)
            except (bitstring.ReadError, ValueError, TypeError) as e:
                # if data was unreadable
                utils.log('error reading datagram: ' + str(e), True)
                print('error reading datagram')
            else:
                # check last flag
                if answer_data.last:
                    last = True

                # proceed received errors
                if answer_data.status == Status.ERROR:
                    print('error on server: ' +
                          Mode.name_from_code(answer_data.mode) + ' - ' +
                          Error.name_from_code(answer_data.a))
                elif answer_data.status == Status.REFUSED:
                    print('server refused to ' +
                          Mode.name_from_code(answer_data.mode) + ' reason: ' +
                          Error.name_from_code(answer_data.a))

                # add received data to answers
                answer.append(answer_data)

        return answer
Esempio n. 7
0
    def __query_by_result_id(self, session_id: int, given_session_id: int,
                             result_id: int) -> bytes:
        """
        Gets one result

        :param session_id: id of session to look for
        :param given_session_id: id of session requesting query
        :param result_id: id of result to look for
        :return: answer for the client
        """
        utils.log('querying by result id: ' + str(result_id) + 'for ' +
                  str(given_session_id))

        if session_id != given_session_id:
            return self.__error(Error.UNAUTHORISED, Mode.QUERY_BY_SESSION_ID,
                                session_id)

        if session_id not in self.results_storage:
            return self.__error(Error.NOT_EXISTING_DATA,
                                Mode.QUERY_BY_SESSION_ID_CMD)

        session_results = self.results_storage[session_id]

        if result_id not in session_results:
            return self.__error(Error.UNAUTHORISED, Mode.QUERY_BY_RESULT_ID,
                                session_id)

        answer = Datagram(
            Status.OK,
            Mode.QUERY_BY_RESULT_ID,
            session_id,
            operation=self.results_storage[session_id][result_id][0],
            a=self.results_storage[session_id][result_id][1],
            b=self.results_storage[session_id][result_id][2],
            result=self.results_storage[session_id][result_id][4],
            result_id=result_id,
        )

        return answer.get_bytes()