コード例 #1
0
def write_msg_to(socket, msg):
    if not isinstance(msg, Message):
        debug_print('BAD. attempting to write_msg_to:', msg)
    else:
        debug_print('out --> msg', msg, 'to socket', socket)
    '''
    send the given msg into the socket
    returns True if writing completes
    '''
    my_file = StringIO()
    packer = msgpack.Packer()
    my_file.write(packer.pack(msg.serialize()))
    my_file = StringIO(my_file.getvalue())
    # debug_print(vars(my_file))
    tot_bytes = len(my_file.buf)
    sent_now = 1
    to_send = tot_bytes
    while sent_now != 0:  # 0 means send done
        try:
            sent_now = socket.send(my_file.read(to_send))
            to_send -= sent_now
            if to_send == 0:
                return True
        except:
            return False
    return True
コード例 #2
0
 def header_matches_string(self, string):
     try:
         assert string in header2int
         return header2int[string] == self.msg_header
     except Exception as e:
         debug_print('header_matches_string FAILED')
         raise RuntimeError(e)
コード例 #3
0
 def __repr__(self):
     try:
         assert 0 <= self.msg_header < len(int2header)
         return 'Message::' + int2header[self.msg_header] + ' from ' \
             + str(self.sender) + ' with args:' + str(self.args)
     except Exception as e:
         debug_print('Msg REPR FAILED')
         raise RuntimeError(e)
コード例 #4
0
 def main_loop(self):
     # split thread into outgoing and incoming
     debug_print('main loop!')
     incoming_thread = threading.Thread(
         target=self.main_incoming_loop,
         args=(),
     )
     incoming_thread.daemon = True
     incoming_thread.start()
     self.main_outgoing_loop()
コード例 #5
0
def read_msg_from(sock, timeout=None):
    assert timeout is None or isinstance(timeout, float)
    '''
    attempts to read exactly ONE message from the given socket
    may return Message
    may return MessageError.CRASH
    if timeout is not None:
        may return MessageError.TIMEOUT
    '''
    unpacker = msgpack.Unpacker()
    while True:
        try:
            sock.settimeout(timeout)
            x = sock.recv(1)
            if x == '':
                debug_print('socket dead!')
                return MessageError.CRASH
                # connection closed
            unpacker.feed(x)
            for package in unpacker:
                x = Message.deserialize(package)
                debug_print('     ::read msg', x)
                return x
        except socket.timeout:
            debug_print("timeout error")
            return MessageError.TIMEOUT
        except Exception as e:
            debug_print("sth else occurred: ", e)
            return MessageError.CRASH
コード例 #6
0
 def measure_rtt_to(ip, port):
     debug_print('rtt to...', ip, port, 'is...')
     start_time = time.time()
     result = Client.sock_client(
         ip, port, timeout=das_game_settings.client_ping_max_time)
     rtt = (time.time() - start_time if result is not None else
            das_game_settings.client_ping_max_time)
     if result is not None:
         result.close()
     debug_print('rtt', rtt)
     logging.info(
         ('Rtt to {ip} {port} was measured to be {rtt} sec').format(
             ip=ip, port=port, rtt=rtt))
     return rtt
コード例 #7
0
 def __init__(self, msg_header, sender, args):
     # print('init', msg_header, sender, args)
     try:
         assert isinstance(msg_header, int) and \
                msg_header in range(0, len(int2header))
         assert isinstance(sender, int) or isinstance(
             sender, list) or isinstance(sender, tuple)
         assert isinstance(args, list)
         self.msg_header = msg_header
         if isinstance(sender, int):
             self.sender = sender
         else:
             self.sender = tuple(sender)
         self.args = args
         # print('WENT OK', self.msg_header, self.sender, self.args)
     except Exception as e:
         print('MESSAGE INIT FAILED!', msg_header, sender, args)
         # print('went bad!')
         debug_print('MESSAGE INIT FAILED', msg_header, sender, args)
         raise e
コード例 #8
0
    def __init__(self, player):
        # TODO player reconnect after crash
        # TODO handle S2C_REFUSE
        self._name = generate_name()
        log_filename = 'client_{name}.log'.format(name=self._name)
        logging.basicConfig(filename=log_filename,
                            filemode='a',
                            level=das_game_settings.logging_level,
                            format='%(asctime)s.%(msecs)03d <client:' +
                            self._name + '> %(message)s',
                            datefmt='%a %H:%M:%S')
        logging.info(
            "Client `{name}` started logging! :D".format(name=self._name))

        assert isinstance(player, client_player.Player)
        self._player = player
        # in order of descending 'quality
        self.sorted_server_ids = Client._ordered_server_list()
        debug_print('self.sorted_server_ids', self.sorted_server_ids)
        self._connect_to_a_server()
コード例 #9
0
def generate_messages_from(sock, timeout=True):
    debug_print('ITSYABOI, GENERATOR')
    assert timeout is None or isinstance(timeout, float)
    '''
    Generator object. will read and yield messages from new_socket
    if timeout==True, may yield None objects. This allows the caller to regularly
    if
    '''
    unpacker = msgpack.Unpacker()
    sock.settimeout(timeout)
    try:
        while True:
            try:
                x = sock.recv(1)
                if x == '':
                    debug_print('socket dead!')
                    return
                unpacker.feed(x)
                for package in unpacker:
                    yield Message.deserialize(package)
            except socket.timeout:
                if timeout:
                    yield MessageError.TIMEOUT
    except GeneratorExit:
        debug_print('generator dieded')
        return
    except Exception:
        yield MessageError.CRASH
        return
コード例 #10
0
def write_many_msgs_to(socket, msg_iterable):
    packer = msgpack.Packer()
    all_went_perfectly = True
    try:
        for msg in msg_iterable:
            if not isinstance(msg, Message):
                debug_print('BAD. attempting to write_msg_to:', msg)
            else:
                debug_print('try out --> msg', msg, 'to socket', socket)
            my_file = StringIO()
            my_file.write(packer.pack(msg.serialize()))
            my_file = StringIO(my_file.getvalue())
            # tot_bytes = len(my_file.buf)
            sent_now = 1
            while sent_now != 0:  # 0 means send done
                try:
                    sent_now = socket.send(my_file.read(256))
                except:
                    all_went_perfectly = False
    except:
        all_went_perfectly = False
    return all_went_perfectly
コード例 #11
0
 def main_incoming_loop(self):
     debug_print('main incoming')
     # while True:
     #     msg = messaging.read_msg_from(self._server_socket, timeout=None)
     while True:
         debug_print('Remade update generator')
         update_generator = messaging.generate_messages_from(
             self._server_socket, timeout=None)
         for msg in update_generator:
             debug_print(str(msg))
             if msg != MessageError.CRASH:
                 if msg.header_matches_string('UPDATE'):
                     new_state = DragonArena.deserialize(msg.args[1])
                     if das_game_settings.client_visualizer:
                         ascii_draw(new_state, me=self._my_id)
                     self._protected_game_state.replace_arena(new_state)
                     logging.info(
                         'Received a server update. Replaced arena')
                     debug_print('replaced arena! :D')
                     if new_state.game_over and not das_game_settings.suppress_game_over:
                         logging.info(('Latest game state is a GAME OVER '
                                       'state...'))
                         time.sleep(2.0)
                         logging.info(('Latest game state is a GAME OVER '
                                       'state...'))
                         print(('GAME OVER! {winners} win!').format(
                             winners=new_state.get_winner()))
                         logging.info(('GAME OVER! {winners} win!').format(
                             winners=new_state.get_winner()))
                         os._exit(0)
             else:
                 break
         debug_print("MY SERVER CRASHED")
         logging.info(('Incoming handler detected crash! '
                       'Re-establishing connection...'))
         self._connect_to_a_server(reconnect=True)
         logging.info('Connection back up!')
コード例 #12
0
 def main_outgoing_loop(self):
     req_generator = self._player.main_loop(self._protected_game_state,
                                            self._my_id)
     debug_print('ready?')
     for request in req_generator:
         logging.info(
             'Player yielded request: {request}'.format(request=request))
         assert isinstance(request, Message)
         debug_print('forwarding', request)
         if not messaging.write_msg_to(self._server_socket, request):
             logging.info("Forwarding the player request has failed! "
                          "Incoming handler should fix this eventually..")
     debug_print('no more requests. Player closed down I guess')
コード例 #13
0
 def main_loop(protected_dragon_arena, my_id):
     assert isinstance(protected_dragon_arena,
                       protected.ProtectedDragonArena)
     debug_print('bot player main loop')
     debug_print('my id', my_id)
     # has self._game_state_copy
     st = das_game_settings.bot_action_period
     try:
         while True:  # TODO: while game.playing    # Roy: And I'm not dead?
             time.sleep(random.uniform(st * 0.8, st / 0.8))
             with protected_dragon_arena as da:
                 try:
                     choice = BotPlayer._choose_action_return_message(
                         da, my_id)
                 except Exception as e:
                     choice = None
                     debug_print("BOT CRASHED WHEN DECIDING", e)
             # `with` expired. dragon arena unlocked
             if choice is not None:
                 yield choice
     except GeneratorExit:
         # clean up generator
         return
コード例 #14
0
    def _connect_to_a_server(self, reconnect=False):
        logging.info("Connecting to server...")
        backoff = 0.01
        while True:
            for serv_id in self.sorted_server_ids:
                try:
                    ip, port = das_game_settings.server_addresses[serv_id]
                    debug_print('Trying server at', ip, port)
                    logging.info(
                        "Trying server (id={serv_id}) at {ip} {port}".format(
                            serv_id=serv_id, ip=ip, port=port))
                    '''1. get socket'''
                    self._server_socket = Client.sock_client(ip, port)
                    if self._server_socket is None:
                        logging.info("No dice.")
                        continue
                    logging.info("Got a socket! Sending HELLO")
                    debug_print('self._server_socket', self._server_socket)
                    '''2. send hello'''
                    if not reconnect:
                        self._random_salt = random.randint(0, 999999)
                        logging.info(("This is a fresh connection. "
                                      "my salt is {salt}").format(
                                          salt=self._random_salt))
                        hello_msg = messaging.M_C2S_HELLO(self._random_salt)
                    else:
                        logging.info("(This is a RE-connection. "
                                     "my salt is still {salt})".format(
                                         salt=self._random_salt))
                        hello_msg = messaging.M_C2S_HELLO_AGAIN(
                            self._random_salt, self._my_id, self._secret)

                    debug_print('about to send msg', str(hello_msg))
                    messaging.write_msg_to(self._server_socket, hello_msg)
                    '''2. get reply (expect welcome)'''
                    reply_msg = messaging.read_msg_from(
                        self._server_socket,
                        timeout=das_game_settings.client_handshake_timeout)
                    if messaging.is_message_with_header_string(
                            reply_msg, 'REFUSE'):
                        debug_print(
                            'got refused by server_id {serv_id}'.format(
                                serv_id=serv_id))
                        logging.info("Refused!")
                        continue
                    if not messaging.is_message_with_header_string(
                            reply_msg, 'S2C_WELCOME'):
                        logging.info(
                            ('CRASH or TIMEOUT for '
                             'server_id {serv_id}').format(serv_id=serv_id))
                        raise RuntimeError('crash or timeout')
                    '''3. get my knight's ID'''
                    self._my_id = tuple(reply_msg.args[0])
                    self._secret = reply_msg.args[1]
                    logging.info(('Successful connection to Server_id '
                                  '{serv_id}. My knight ID is {kid}').format(
                                      serv_id=serv_id, kid=self._my_id))
                    '''4. wait for 1st game update'''
                    first_update =\
                        messaging.read_msg_from(
                            self._server_socket,
                            timeout=max(das_game_settings.max_done_wait,
                                        das_game_settings.
                                        client_handshake_timeout))
                    if not messaging.is_message_with_header_string(
                            first_update, 'UPDATE'):
                        logging.info(('Got {msg} but I expected my first '
                                      'update').format(msg=first_update))
                        raise RuntimeError('got' + str(first_update) +
                                           'instead of first update')

                    logging.info('Got my first update!')
                    '''5. try deserialize and extract game state'''
                    self._protected_game_state = protected.ProtectedDragonArena(
                        DragonArena.deserialize(first_update.args[1]))
                    logging.info(
                        ('Successfully deserialized game state. '
                         'Hash is {h}').format(h=self._protected_game_state.
                                               _dragon_arena.get_hash()))
                    return  # exit the loop
                except Exception as e:
                    debug_print('CONNECTION WENT AWRY :(', e)
                    logging.info(('Connection went wrong! Reason: {e}').format(
                        e=str(e)))
            debug_print('failed to connect to everyone! D:')
            time.sleep(backoff)
            logging.info(('Backing off. Sleeping {sec}').format(sec=backoff))
            debug_print('backing off...', backoff)
            backoff = sqrt(backoff * 1.7)