def handle_STOP(self, timestamp, message): match = Handler.re_m_STOP.match(message) if not match: raise HTTPErrorResponse( 400, "Malformed STOP message {0}".format(message)) # Make sure the matchid is correct matchid = match.group(1) if self._matchid != matchid: self._on_ABORT() self._matchid = None raise HTTPErrorResponse(400, ("PLAY message has wrong matchid: " "{0} {1}").format(matchid, self._matchid)) # Extract the actions and match to the correct roles tmpstr = match.group(2) # GGP 1 and GGP 2 are handled differently if self._protocol_version == Handler.GGP1: # GDL-I: a list of actions actions = parse_actions_sexp(tmpstr) if len(actions) != len(self._roles): raise HTTPErrorResponse( 400, "Malformed STOP message {0}".format(message)) timeout = Timeout(timestamp, self._playclock) self._on_STOP(timeout.clone(), dict(zip(self._roles, actions))) else: # GDL-II: a list of observations (turn, action, observations) = _parse_gdl2_playstop_component( "STOP", message, tmpstr) if turn != self._gdl2_turn: raise HTTPErrorResponse(400, ("STOP message has wrong turn number: " "{0} {1}").format( turn, self._gdl2_turn)) self._gdl2_turn += 1 timeout = Timeout(timestamp, self._playclock) self._on_STOP2(timeout.clone(), action, observations) remaining = timeout.remaining() if remaining <= 0: g_logger.error( _fmt("STOP messsage handler late response by {0}s", remaining)) else: g_logger.debug(_fmt("STOP response with {0}s remaining", remaining)) # Now return the DONE response return self._response("DONE")
def _app_normal(self, environ, start_response, timestamp, post_message): try: response_body = self._handle_POST(timestamp, post_message) response_headers = _get_response_headers(environ, response_body) start_response('200 OK', response_headers) return response_body except HTTPErrorResponse as er: g_logger.info(_fmt("HTTPErrorResponse: {0}", er)) response_headers = _get_response_headers(environ, "") start_response(str(er), response_headers) return "" except Exception as e: g_logger.error(_fmt("Unknown Exception: {0}", e)) response_headers = _get_response_headers(environ, "") start_response('500 Internal Server Error', response_headers) raise return ""
def _app_bad(self, environ, start_response): try: # Return an error response_headers = _get_response_headers(environ, "") start_response('400 Invalid GGP message', response_headers) return "" except Exception as e: g_logger.error(_fmt("Unknown Exception: {0}", e)) response_headers = _get_response_headers(environ, "") start_response('500 Internal Server Error', response_headers) return ""
def handle_START(self, timestamp, message): self._set_case(message, "START") match = Handler.re_m_START.match(message) if not match: raise HTTPErrorResponse( 400, "Malformed START message {0}".format(message)) self._matchid = match.group(1) role = match.group(2) gdl = match.group(3) self._startclock = int(match.group(4)) self._playclock = int(match.group(5)) if self._protocol_version == Handler.GGP2: self._gdl2_turn = 0 # Hack: need to process the GDL to extract the order of roles as they appear # in the GDL file so that we can get around the brokeness of the PLAY/STOP # messages, which require a player to know the order of roles to match # to the correct actions. try: self._roles_in_correct_order(gdl) except Exception as e: g_logger.error(_fmt("GDL error. Will ignore this game: {0}", e)) self._matchid = None return timeout = Timeout(timestamp, self._startclock) self._on_START(timeout.clone(), self._matchid, role, gdl, self._playclock) remaining = timeout.remaining() if remaining <= 0: g_logger.error( _fmt("START messsage handler late response by {0}s", remaining)) else: g_logger.debug( _fmt("START response with {0}s remaining", remaining)) # Now return the READY response return self._response("READY")
def _get_http_post(environ): try: if environ.get('REQUEST_METHOD') != "POST": raise HTTPErrorResponse(405, 'Non-POST method not supported') request_body_size = int(environ.get('CONTENT_LENGTH')) if request_body_size <= 5: raise HTTPErrorResponse( 400, 'Message content too short to be meaningful') return environ['wsgi.input'].read(request_body_size) except HTTPErrorResponse: raise except Exception as e: g_logger.warning(_fmt("HTTP POST exception: {0}", e)) raise HTTPErrorResponse(400, 'Invalid content')
def handle_PLAY(self, timestamp, message): match = Handler.re_m_PLAY.match(message) if not match: raise HTTPErrorResponse( 400, "Malformed PLAY message {0}".format(message)) matchid = match.group(1) if self._matchid != matchid: self._on_ABORT() self._matchid = None raise HTTPErrorResponse(400, ("PLAY message has wrong matchid: " "{0} {1}").format(matchid, self._matchid)) tmpstr = match.group(2) action = None actionstr = "" # GGP 1 and GGP 2 are handled differently if self._protocol_version == Handler.GGP1: # GDL-I: a list of actions if not re.match(r'^\s*\(.*\)\s*$', tmpstr) and \ not re.match(r'^\s*NIL\s*$', tmpstr, re.I): raise HTTPErrorResponse( 400, "Malformed PLAY message {0}".format(message)) actions = parse_actions_sexp(tmpstr) if len(actions) != 0 and len(actions) != len(self._roles): raise HTTPErrorResponse( 400, "Malformed PLAY message {0}".format(message)) timeout = Timeout(timestamp, self._playclock) action = self._on_PLAY(timeout.clone(), dict(zip(self._roles, actions))) else: # GDL-II: a list of observations (turn, action, observations) = _parse_gdl2_playstop_component( "PLAY", message, tmpstr) timeout = Timeout(timestamp, self._playclock) action = self._on_PLAY2(timeout.clone(), action, observations) if turn != self._gdl2_turn: raise HTTPErrorResponse(400, ("PLAY message has wrong turn number: " "{0} {1}").format( turn, self._gdl2_turn)) self._gdl2_turn += 1 # Handle the return action actionstr = "{0}".format(action) # Make sure the action is a valid s-expression try: exp = parse_simple_sexp(actionstr.strip()) except: actionstr = "({0})".format(actionstr) g_logger.critical( _fmt(("Invalid action '{0}'. Will try to recover to " "and send {1}"), action, actionstr)) remaining = timeout.remaining() if remaining <= 0: g_logger.error( _fmt("PLAY messsage handler late response by {0}s", remaining)) else: g_logger.info( _fmt("PLAY response with {0}s remaining: {1}", remaining, action)) # Returns the action as the response return actionstr