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)
Beispiel #5
0
    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
Beispiel #10
0
    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")