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()
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()
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()
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
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()
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
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()