def _log_out(self): request_type = Request.Type.LOG_OUT if not self._user: return Response(request_type, success=False, message="Not logged in") self._parent.deactivate_user(self._user.name) self._user = None self._parent.users.commit() return Response(request_type)
def _log_in(self, user_name): if self._parent.user_is_activated(user_name): return Response(Request.Type.LOG_IN, success=False, message="User already online") if user_name not in self._parent.users: self._parent.users.create_user(user_name) self._user = self._parent.users[user_name] self._user.credits += self._parent.get_init_credits() self._parent.activate_user(user_name) return Response(Request.Type.LOG_IN)
def _get_item(self, item_name): if item_name not in self._cache[Request.Type.GET_ALL_ITEMS_NAMES]: ret = Response( Request.Type.GET_ITEM, success=False, message=f"No such item: {item_name}" ) else: item = next(filter( lambda item: item.name == item_name, self._cache[Request.Type.GET_ALL_ITEMS] )) ret = Response( Request.Type.GET_ITEM, data=item ) return ret
def _user_has(self, user, item_name): if not user: return self._no_user_response(Request.Type.USER_HAS) if not item_name: return Response(Request.Type.USER_HAS, success=False, message="No item") if item_name not in self._items: return self._no_item_response(Request.Type.USER_HAS, item_name) if item_name not in user.items: ret = 0 else: ret = user.items[item_name] return Response(Request.Type.USER_HAS, data=ret)
def process(self): # type: () -> Response self.logger.info('Start request processing') req = self.get() if self.queue.empty(): self.event.clear() self.logger.info('Request to process: %s' % req.__str__()) result = False if req.type is RequestType.TRANSACTION: result = self.wallet.req_transaction(req.body) response = Response(req.uid) if result is 0: response.type = ResponseType.ACK if result is 1: response.type = ResponseType.ERROR response.body = { 'code': result, 'msg': self.wallet.TRANSACTION_ERROR % self.wallet.TRANSACTION_ERROR_MIN } if result is 2: response.type = ResponseType.ERROR response.body = { 'code': result, 'msg': self.wallet.TRANSACTION_ERROR % self.wallet.TRANSACTION_ERROR_MAX } self.logger.info(response) return response
def _buy_item(self, user, item_name_and_amount): item_name, amount = item_name_and_amount request_type = Request.Type.PURCHASE_ITEM if not user: return self._no_user_response(request_type) if item_name not in self._items: return self._no_item_response(request_type, item_name) item = self._items[item_name] if item.buying_price * amount > user.credits: return Response(request_type, success=False, message="Not enough money") user.credits -= item.buying_price * amount user.items[item_name] = user.items.get(item_name, 0) + amount self._operation_count += 1 return Response(request_type, message=f"Item(s) bought: {amount} {item_name}")
def _sell_item(self, user, item_name_and_amount): item_name, amount = item_name_and_amount request_type = Request.Type.SELL_ITEM if not user: return self._no_user_response(request_type) if item_name not in self._items: return self._no_item_response(request_type, item_name) item = self._items[item_name] if user.items.get(item_name, 0) < amount: return Response(request_type, success=False, message=f"You don't have {amount} {item_name}") user.items[item_name] -= amount if user.items[item_name] == 0: user.items.pop(item_name) user.credits += item.selling_price * amount self._operation_count += 1 return Response(request_type, message=f"Item(s) sold: {amount} {item_name}")
def handle_request_from(self, user, request): """Handle request for given user.""" request_type = request.request_type if request_type in self._plain_requests: ret = Response(request_type, data=self._plain_requests[request_type]()) elif request_type in self._user_requests and not user: ret = self._no_user_response(request_type) elif request_type in self._user_requests: ret = Response(request_type, data=self._user_requests[request_type](user)) else: ret = self._complex_requests[request_type](user, request.data) if ret.success: self._operation_count = \ (self._operation_count + 1) % self._save_frequency if self._operation_count == 0: self._users.commit() return ret
def execute(self, request_type, arg=None): """Wrapps ServerHandler.execute. Update cache and use it to provide responses when possible. """ if request_type in self._updaters: ret = self._server.execute(request_type, arg) if ret.success: self._updaters[request_type](arg) elif self._cache.get(request_type, None): ret = Response(request_type, data=self._cache[request_type]) elif request_type in self._checkers: ret = self._checkers[request_type](arg) else: ret = self._server.execute(request_type, arg) return ret
def get_session_token(self, duration_seconds=None, callback=None): #logging.info('retreiving session token') s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) stream = tornado.iostream.SSLIOStream(s) stream._always_callback = True # get callbacks on stream.connect addr = (self.DefaultRegionEndpoint,443) yield gen.Task( stream.connect, addr ) if stream.error: callback(ErrorResponse('error connecting to %s to get token' % str(addr) ) ) raise StopIteration data = {'Action':'GetSessionToken'} if duration_seconds: data['DurationSeconds'] = duration_seconds request = AWSRequest('POST', self.DefaultRegionEndpoint, data) request.set_parameter('Version', self.APIVersion) request.sign_request(self.aws_key, self.aws_secret) body = request.to_postdata() request.headers['Content-Length'] = str(len(body)) towrite = request.make_request_headers() + body #logging.info('writing %s' % towrite) yield gen.Task( stream.write, towrite ) rawheaders = yield gen.Task( stream.read_until, '\r\n\r\n' ) if not rawheaders: logging.error('read until headers returned null, likely socket closed...') callback( ErrorResponse('socket closed') ) raise StopIteration code, headers = parse_headers(rawheaders) if code != 200: logging.error('get token: got error response %s, %s' % (code, headers)) callback( ErrorResponse('non 200 response %s' % code ) ) stream.close() raise StopIteration if 'Content-Length' in headers: body = yield gen.Task( stream.read_bytes, int(headers['Content-Length']) ) if not body: logging.error('conn closed reading for body?') callback( ErrorResponse('socket closed') ) raise StopIteration #logging.info('got body %s' % body) response = Response( code, headers, body ) callback( response ) else: logging.error('chunked encoding response?') callback( ErrorResponse('unable to parse chunked encoding') ) if not stream.closed(): stream.close()
def _item_exists(self, item_name): return Response( Request.Type.ITEM_EXISTS, data=(item_name in self._cache[Request.Type.GET_ALL_ITEMS_NAMES]) )
def __init__(self, items_db, users_db, min_limit, max_limit, save_frequency, simultanious_log_ins): """Create ServerCore. items_db and users_db stands for data bases with users and items respectively. min_limit and max_limit are bonds for user initialization reward. save_frequency is how many operations must take place between automatic commits. Operations from each user counts. simultanious_log_ins is binary flag, which allows or forbide multiple users log in into one account simultaniously. """ self._items = items_db self._users = users_db self._new_credits_max = max_limit self._new_credits_min = min_limit self._save_frequency = save_frequency self._operation_count = 1 self._simultanious_log_ins = simultanious_log_ins self._active_users_names = set() self._plain_requests = { Request.Type.GET_ALL_USERS: lambda: self._users.values(), Request.Type.GET_ALL_USERS_NAMES: lambda: self._users.keys(), Request.Type.GET_ALL_ITEMS: lambda: self._items.values(), Request.Type.GET_ALL_ITEMS_NAMES: lambda: self._items.keys(), Request.Type.PING: lambda: None, } self._user_requests = { Request.Type.GET_CURRENT_USER: lambda user: user, Request.Type.GET_CURRENT_USER_NAME: lambda user: user.name, Request.Type.GET_CREDITS: lambda user: user.credits, Request.Type.GET_USER_ITEMS_NAMES: lambda user: user.items, Request.Type.GET_USER_ITEMS: lambda user: {item.name: item for item in user.items} } self._complex_requests = { Request.Type.GET_USER: self._get_user, Request.Type.GET_ITEM: self._get_item, Request.Type.USER_HAS: self._user_has, Request.Type.PURCHASE_ITEM: self._buy_item, Request.Type.SELL_ITEM: self._sell_item, Request.Type.USER_EXISTS: lambda _, name: Response(Request.Type.USER_EXISTS, data=(name in self._users)), Request.Type.ITEM_EXISTS: lambda _, name: Response(Request.Type.ITEM_EXISTS, data=(name in self._items)), }
def _get_user(self, user, user_name): if user_name not in self._users: return Response(Request.Type.GET_USER, success=False, message="No such user") return Response(Request.Type.GET_USER, data=self._users[user_name])
def _get_item(self, user, item_name): if item_name not in self._items: return self._no_item_response(Request.Type.GET_ITEM, item_name) return Response(Request.Type.GET_ITEM, data=self._items[item_name])
def _no_item_response(request_type, item_name): return Response(request_type, success=False, message=f"No such item: {item_name}")
def _no_user_response(request_type): return Response(request_type, success=False, message="Not logged in")