Пример #1
0
    def _recv_command(self, decrypt=True):
        """
        .. todo:: rewrite
        """

        recv_size = self._recv_to_buff()
        if len(
                self._recv_buff
        ) < 5 and not self._decrypted_header:  # all packets are terminated by 0x00
            return None, None

        if not self._decrypted_header:  # decrypt header
            if decrypt:
                first4 = self._crypto.decrypt(self._recv_buff[:4])
            else:
                first4 = self._recv_buff[:4]
            headerbuff = bytebuff(first4)
            self._recv_buff = self._recv_buff[4:]
            size_1 = headerbuff.get(">B")
            if size_1 & 0x80 and self._ver >= EXPANSION_WOTLK:  #big packet
                if decrypt:
                    headerbuff += self._crypto.decrypt(self._recv_buff[:1])
                else:
                    headerbuff += self._recv_buff[:1]
                self._recv_buff = self._recv_buff[1:]
                size_2 = headerbuff.get(">H")
                size = ((size_1 ^ 0x80) << 16) + size_2 - 2
            else:  # little packet
                size_2 = headerbuff.get(">B")
                size = (size_1 << 8) + size_2 - 2
            cmd = headerbuff.get("H")
            self._decrypted_header = (size, cmd)

        if self._decrypted_header:
            size = self._decrypted_header[0]
            cmd = self._decrypted_header[1]
            if len(self._recv_buff) < size:
                return None, None
            data = self._recv_buff[:size]
            self._recv_buff = self._recv_buff[size:]
            if self._ver >= EXPANSION_CATA and cmd & COMPRESSED_OPCODE_MASK:
                cmd ^= COMPRESSED_OPCODE_MASK
                data = self._zlib_stream.decompress(data[4:])
                buff = bytebuff(data)
            else:
                buff = bytebuff(data)
            self._decrypted_header = ()
            logging.getLogger("tclib").debug("WORLD: recv cmd: %s; data: %s",
                                             hex(cmd), buff)
            return cmd, buff

        return None, None
Пример #2
0
    def _worker(self):
        self._connect()
        # SMSG_AUTH_CHALLENGE
        if self._ver >= EXPANSION_CATA:  #rewrite
            self._connection.recv(50, socket.MSG_WAITALL)
            if self._ver == EXPANSION_CATA:
                self._send(
                    "\x00\x2fWORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER")
            else:
                self._send(
                    "\x30\x00WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER\00"
                )
            buff = bytebuff(self._connection.recv(41, socket.MSG_WAITALL))
        elif self._ver == EXPANSION_WOTLK:
            buff = bytebuff(self._connection.recv(44, socket.MSG_WAITALL))
        else:
            buff = bytebuff(self._connection.recv(8, socket.MSG_WAITALL))
        print len(buff.data)
        size = buff.get(">H")  # wotlk - 42, cata - 39; tbc - 6
        cmd = buff.get("H")
        print cmd
        if self._ver == EXPANSION_CATA:
            cmd = opcode_translate_cata_wotlk(cmd)
        elif self._ver == EXPANSION_PANDA:
            cmd = opcode_translate_panda_wotlk(cmd)
        print cmd
        if cmd != SMSG_AUTH_CHALLENGE:
            raise StreamBrokenError()
        buff.cut()
        self._world._handle_auth_challange(cmd, buff)
        # CMSG_AUTH_SESSION
        cmd, buff = self._send_queue.get()
        self._send_command(cmd, buff, False)

        self._connection.setblocking(0)
        while 1:
            time.sleep(NETWORK_LOOP_SLEEP)
            while 1:
                cmd, buff = self._recv_command()
                if cmd == None:
                    break
                elif cmd == SMSG_NAME_QUERY_RESPONSE or cmd == CATA_SMSG_NAME_QUERY_RESPONSE:  # little hack, world threat is now probably blocked
                    self._world._handle_name_query_response(cmd, buff)
                self._recv_queue.put((cmd, buff))
            while 1:
                try:
                    cmd, buff = self._send_queue.get_nowait()
                    self._send_command(cmd, buff)
                except Queue.Empty:
                    break
Пример #3
0
 def _recv_command(self, decrypt = True):
     """
     .. todo:: rewrite
     """
     
     recv_size = self._recv_to_buff()
     if len(self._recv_buff) < 5 and not self._decrypted_header: # all packets are terminated by 0x00
         return None, None
     
     if not self._decrypted_header: # decrypt header
         if decrypt:
             first4 = self._crypto.decrypt(self._recv_buff[:4])
         else:
             first4 = self._recv_buff[:4]
         headerbuff = bytebuff(first4)
         self._recv_buff = self._recv_buff[4:]
         size_1 = headerbuff.get(">B")
         if size_1 & 0x80 and self._ver >= EXPANSION_WOTLK: #big packet
             if decrypt:
                 headerbuff += self._crypto.decrypt(self._recv_buff[:1])
             else:
                 headerbuff += self._recv_buff[:1]
             self._recv_buff = self._recv_buff[1:]
             size_2 = headerbuff.get(">H")
             size = ((size_1 ^ 0x80) << 16) + size_2 - 2
         else: # little packet
             size_2 = headerbuff.get(">B")
             size = (size_1 << 8) + size_2 - 2
         cmd = headerbuff.get("H")
         self._decrypted_header = (size, cmd)
     
     if self._decrypted_header:
         size = self._decrypted_header[0]
         cmd = self._decrypted_header[1]
         if len(self._recv_buff) < size:
             return None, None
         data = self._recv_buff[:size]
         self._recv_buff = self._recv_buff[size:]
         if self._ver >= EXPANSION_CATA and cmd & COMPRESSED_OPCODE_MASK:
             cmd ^= COMPRESSED_OPCODE_MASK
             data = self._zlib_stream.decompress(data[4:])
             buff = bytebuff(data)
         else:
             buff = bytebuff(data)
         self._decrypted_header = ()
         logging.getLogger("tclib").debug("WORLD: recv cmd: %s; data: %s", hex(cmd), buff)
         return cmd, buff
     
     return None, None
Пример #4
0
 def send_channel_list(self, name = None):
     """
     CMSG_CHANNEL_LIST (CMSG_CHANNEL_DISPLAY_LIST)
     
     Parameters
     ----------
     name : str
         channel name; if None send for all joined channels
     """
     
     if name == None:
         for channel in self.get_all_channels():
             assert(channel.name != None)
             self.send_channel_list(channel.name)
         return
     
     assert(self._ver < EXPANSION_CATA or len(name) < 2**8)
     buff = bytebuff()
     name = name.lower()
     
     if self._ver >= EXPANSION_CATA:
         buff.add("<B", len(name))
         buff.add_raw(name)
     else:
         buff.add("S", name)
     
     self._send(CMSG_CHANNEL_LIST, buff)
Пример #5
0
    def send_join_channel(self, name, password = ""):
        """
        CMSG_JOIN_CHANNEL
        
        Parameters
        ----------
        name : str
        password : str
        """

        name = name.lower()
        
        buff = bytebuff()
        if self._ver >= EXPANSION_CATA:
            buff.add("I", 0)
            buff.add_bit(0) # unknown
            buff.add_bit(0) # unknown
            buff.add("8t", len(name))
            buff.add("8t", len(password))
            buff.fill_byte()
            buff.add("k", name)
            buff.add("k", password)
        elif self._ver >= EXPANSION_TBC:
            buff.add_zeros(6)
            buff.add("S", name.lower())
            buff.add("S", password)
        else:
            buff.add("S", name.lower())
            buff.add("S", password)
        
        self._send(CMSG_JOIN_CHANNEL, buff)
Пример #6
0
    def _handle_guild_query(self, cmd, buff):
        """
        SMSG_GUILD_QUERY_RESPONSE
        
        Returns
        ----------
        guild_id     : int
        player_guild : bool
        guild_name   : str
        rank_names   : list of str
        """

        if self._ver >= EXPANSION_CATA:
            return  # TODO: implement

        buff = bytebuff()
        guild_id = buff.get("I")
        guild_name = buff.get("S")
        player_guild = False
        if guild_id == self._my_player.guild_id:
            player_guild = True

        rank_names = []
        guild_ranks_max_count = 10
        for i in range(guild_ranks_max_count):
            rank_name = buff.get("S")
            if not rank_name:
                break

            rank_names.append()

        return guild_id, player_guild, guild_name, rank_names
Пример #7
0
 def _handle_guild_query(self, cmd, buff):
     """
     SMSG_GUILD_QUERY_RESPONSE
     
     Returns
     ----------
     guild_id     : int
     player_guild : bool
     guild_name   : str
     rank_names   : list of str
     """
     
     if self._ver >= EXPANSION_CATA:
         return # TODO: implement
     
     buff = bytebuff()
     guild_id = buff.get("I")
     guild_name = buff.get("S")
     player_guild = False
     if guild_id == self._my_player.guild_id:
         player_guild = True
     
     rank_names = []
     guild_ranks_max_count = 10
     for i in range(guild_ranks_max_count):
         rank_name = buff.get("S")
         if not rank_name:
             break
         
         rank_names.append()
         
     return guild_id, player_guild, guild_name, rank_names
         
Пример #8
0
 def _worker(self):
     self._connect()
     # SMSG_AUTH_CHALLENGE
     if self._ver >= EXPANSION_CATA: #rewrite
         self._connection.recv(50, socket.MSG_WAITALL)
         if self._ver == EXPANSION_CATA:
             self._send("\x00\x2fWORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER")
         else:
             self._send("\x30\x00WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER\00")
         buff = bytebuff(self._connection.recv(41, socket.MSG_WAITALL))
     elif self._ver == EXPANSION_WOTLK:
         buff = bytebuff(self._connection.recv(44, socket.MSG_WAITALL))
     else:
         buff = bytebuff(self._connection.recv(8, socket.MSG_WAITALL))
     print len(buff.data)
     size = buff.get(">H") # wotlk - 42, cata - 39; tbc - 6
     cmd = buff.get("H")
     print cmd
     if self._ver == EXPANSION_CATA:
         cmd = opcode_translate_cata_wotlk(cmd)
     elif self._ver == EXPANSION_PANDA:
         cmd = opcode_translate_panda_wotlk(cmd)
     print cmd
     if cmd != SMSG_AUTH_CHALLENGE:
         raise StreamBrokenError()
     buff.cut()
     self._world._handle_auth_challange(cmd, buff)
     # CMSG_AUTH_SESSION
     cmd, buff = self._send_queue.get()
     self._send_command(cmd, buff, False)
     
     self._connection.setblocking(0)
     while 1:
         time.sleep(NETWORK_LOOP_SLEEP)
         while 1:
             cmd, buff = self._recv_command()
             if cmd == None:
                 break
             elif cmd == SMSG_NAME_QUERY_RESPONSE or cmd == CATA_SMSG_NAME_QUERY_RESPONSE: # little hack, world threat is now probably blocked
                 self._world._handle_name_query_response(cmd, buff)
             self._recv_queue.put((cmd, buff))
         while 1:
             try:
                 cmd, buff = self._send_queue.get_nowait()
                 self._send_command(cmd, buff)
             except Queue.Empty:
                 break
Пример #9
0
 def send_contact_list(self):
     """
     CMSG_CONTACT_LIST
     """
     
     buff = bytebuff()
     buff.add("I", 1) #unknown, always 1
     self._send(CMSG_CONTACT_LIST, buff)
Пример #10
0
    def send_auction_list_items(self,
                                listfrom,
                                searchedname = AUCTION_SEARCHEDNAME_ALL,
                                levelmin = AUCTION_LEVELMIN_ALL,
                                levelmax = AUCTION_LEVELMAX_ALL,
                                auction_slot_id = AUCTION_FILTERS_ALL,
                                auction_main_category = AUCTION_FILTERS_ALL,
                                auction_sub_category = AUCTION_FILTERS_ALL,
                                quality = AUCTION_FILTERS_ALL,
                                only_usable = False,
                                get_all = False):
        """
        CMSG_AUCTION_LIST_ITEMS

        Send auction list items.

        listfrom : int
            Page number
        searchedname : string
            AUCTION_SEARCHEDNAME_ALL for all
        levelmin : int
            AUCTION_LEVELMIN_ALL for all
        levelmax : int
            AUCTION_LEVELMAX_ALL for all
        auction_slot_id : int
            AUCTION_FILTERS_ALL for all
        auction_main_category : int
            AUCTION_FILTERS_ALL for all
        auction_sub_category : int
            AUCTION_FILTERS_ALL for all
        quality : int
            AUCTION_FILTERS_ALL for all
        only_usable : bool
        get_all : bool
        """

        if self._ver != EXPANSION_WOTLK:
            raise NotImplementedError # TODO: implement
        if not self._auction_ready:
            raise SendAuctionHelloFirst

        buff = bytebuff()
        buff.add("Q", self._auctioneer_guid)
        buff.add("I", listfrom)
        buff.add("S", searchedname)
        buff.add("B", levelmin)
        buff.add("B", levelmax)
        buff.add("I", auction_slot_id)
        buff.add("I", auction_main_category)
        buff.add("I", auction_sub_category)
        buff.add("I", quality)
        buff.add("B", int(only_usable))
        buff.add("B", int(get_all))
        buff.add("B", 0) # unknown
        self._send(CMSG_AUCTION_LIST_ITEMS, buff)
Пример #11
0
 def send_played_time(self, show = True):
     """
     CMSG_PLAYED_TIME
     
     Parameters
     ----------
     show : bool
     """
     
     buff = bytebuff()
     buff.add("B", int(show))
     self._send(CMSG_PLAYED_TIME, buff)
Пример #12
0
 def send_add_ignore(self, player_name):
     """
     CMSG_ADD_IGNORE
     
     Parameters
     ----------
     player_name : str
     """
     
     buff = bytebuff()
     buff.add("S", player_name)
     self._send(CMSG_ADD_IGNORE, buff)
Пример #13
0
 def _send_command(self, cmd, buff, encrypt = True):
     data = buff.data
     assert(len(data) < 2**16-7)
     logging.getLogger("tclib").debug("WORLD: sending cmd: %s; data: %s", hex(cmd), buff)
     
     headerbuff = bytebuff()
     headerbuff.add(">H", len(data) + 4)
     headerbuff.add("H", cmd)
     headerbuff.add_zeros(2)
     
     header = headerbuff.data
     if encrypt:
         header = self._crypto.encrypt(header)
     self._send(header + data)
Пример #14
0
    def _send_command(self, cmd, buff, encrypt=True):
        data = buff.data
        assert (len(data) < 2**16 - 7)
        logging.getLogger("tclib").debug("WORLD: sending cmd: %s; data: %s",
                                         hex(cmd), buff)

        headerbuff = bytebuff()
        headerbuff.add(">H", len(data) + 4)
        headerbuff.add("H", cmd)
        headerbuff.add_zeros(2)

        header = headerbuff.data
        if encrypt:
            header = self._crypto.encrypt(header)
        self._send(header + data)
Пример #15
0
    def send_auction_hello(self, auctioneer_guid):
        """
        MSG_AUCTION_HELLO

        Send auction hello.

        Parameters
        ----------
        auctioneer_guid : int
        """

        if self._ver != EXPANSION_WOTLK:
            raise NotImplementedError # TODO: implement

        buff = bytebuff()
        buff.add("Q", auctioneer_guid)
        self._send(MSG_AUCTION_HELLO, buff)
Пример #16
0
    def send_guild_query(self, guild_id=None):
        """
        CMSG_GUILD_QUERY
        
        Parameters
        ----------
        guild_id : int
        """

        if self._ver >= EXPANSION_CATA:
            raise NotImplementedError  # TODO: implement

        if guild_id == None:
            guild_id = self._my_player.guild_id

        buff = bytebuff()
        buff.add("I", guild_id)
        self._send(CMSG_GUILD_QUERY, buff)
Пример #17
0
 def send_guild_query(self, guild_id = None):
     """
     CMSG_GUILD_QUERY
     
     Parameters
     ----------
     guild_id : int
     """
     
     if self._ver >= EXPANSION_CATA:
         raise NotImplementedError # TODO: implement
     
     if guild_id == None:
         guild_id = self._my_player.guild_id
     
     buff = bytebuff()
     buff.add("I", guild_id)
     self._send(CMSG_GUILD_QUERY, buff)
Пример #18
0
 def send_leave_channel(self, name):
     """
     CMSG_LEAVE_CHANNEL
     
     Parameters
     ----------
     name : str
     """
     
     name = name.lower()
     
     buff = bytebuff()
     if self._ver >= EXPANSION_CATA:
         buff.add("I", 0) # unknown
         buff.add("8t", len(name))
         buff.add("k", name)
     else:
         buff.add_zeros(4)
         buff.add("S", name)
     
     self._send(CMSG_LEAVE_CHANNEL, buff)
Пример #19
0
    def send_who(self, minlevel = 0, maxlevel = 100, racemask = 0xFFFFFFFF, classmask = 0xFFFFFFFF, player_name = "", guild_name = "", user_strings = None, zones = None):
        """
        CMSG_WHO
    
        Parameters
        ----------
        minlevel : int
        maxlevel : int
        racemask : int
        classmask : int
        player_name : str
        guild_name : str
        user_strings : list of strs
        zones : list of ints
        """

        if user_strings == None:
            user_strings = ()
        if zones == None:
            zones = ()
            
        assert(len(user_strings) <= 4)
        assert(len(zones) <= 10)
        
        buff = bytebuff()
        buff.add("I", minlevel)
        buff.add("I", maxlevel)
        buff.add("S", player_name)
        buff.add("S", guild_name)
        buff.add("I", racemask)
        buff.add("I", classmask)
        buff.add("I", len(zones))
        for i in zones:
            buff.add("I", i)
        buff.add("I", len(user_strings))
        for string in user_strings:
            buff.add("S", string)
            
        self._send(CMSG_WHO, buff)
Пример #20
0
    def send_message_chat(self, msg_type, msg, to = ""):
        """
        CMSG_MESSAGECHAT
        
        Send chat message.
        
        Parameters
        ----------
        msg_type : int
            Implemented: CHAT_MSG_WHISPER,
                         CHAT_MSG_CHANNEL,
                         CHAT_MSG_SAY,
                         CHAT_MSG_PARTY,
                         CHAT_MSG_RAID,
                         CHAT_MSG_GUILD,
                         CHAT_MSG_OFFICER,
                         CHAT_MSG_YELL,
                         CHAT_MSG_WHISPER,
                         CHAT_MSG_CHANNEL
        msg : str
            msg must be less than 256 characters
        to : str
            Required if msg_type is CHAT_MSG_WHISPER or CHAT_MSG_CHANNEL
            
        Raises
        ----------
        NotImplementedError
            If msg_type is not implemented.
        MessageIsTooLong
            If len(msg) > 255
        """
        
        if len(msg) > 255:
            raise MessageIsTooLong()
        
        if msg_type == CHAT_MSG_WHISPER and self._ver < EXPANSION_CATA:
            lang = LANG_GLOBAL
        else:
            lang = self._my_player.default_lang
        buff = bytebuff()
        if msg_type in (CHAT_MSG_WHISPER, CHAT_MSG_CHANNEL):
            assert(to)
            if self._ver >= EXPANSION_CATA:
                buff.add("I", lang)
                buff.add("10t", len(to))
                buff.add("9t", len(msg))
                buff.fill_byte()
                if msg_type == CHAT_MSG_WHISPER:
                    buff.add_raw(to)
                    buff.add_raw(msg)
                if msg_type == CHAT_MSG_CHANNEL:
                    buff.add_raw(msg)
                    buff.add_raw(to)
                cmd = msg_type_translate_wotlk_cata(msg_type)
                self._send(cmd, buff, False)
            else:
                if self._ver == EXPANSION_VANILLA:
                    msg_type = msg_type_translate_wotlk_vanilla(msg_type)
                buff.add("I", msg_type)
                buff.add("I", lang)
                buff.add("S", to)
                buff.add("S", msg)
                self._send(CMSG_MESSAGECHAT, buff)
            return

        if msg_type in (CHAT_MSG_SAY,
                        CHAT_MSG_PARTY,
                        CHAT_MSG_RAID,
                        CHAT_MSG_GUILD,
                        CHAT_MSG_OFFICER,
                        CHAT_MSG_YELL):
            if self._ver >= EXPANSION_CATA:
                buff.add("I", lang)
                buff.add("9t", len(msg))
                buff.fill_byte()
                buff.add_raw(msg)
                cmd = msg_type_translate_wotlk_cata(msg_type)
                self._send(cmd, buff, False)
            else:
                if self._ver == EXPANSION_VANILLA:
                    msg_type = msg_type_translate_wotlk_vanilla(msg_type)
                buff.add("I", msg_type)
                buff.add("I", lang)
                buff.add("S", msg)
                self._send(CMSG_MESSAGECHAT, buff)
            return
        
        raise NotImplementedError()