Пример #1
0
    def _test_dreply(self, gen_dreply, good, diff_ips_test=False):
        for i in range(self.NLISTENERS):
            print >> sys.stderr, "test: waiting for #", i, "listenport", self.mylistenport[
                i]
            conn, addr = self.myss[i].accept()
            s = OLConnection(self.mykeypairs[i], '', 0, conn,
                             self.mylistenport[i])
            while True:
                msg = s.recv()
                self.assert_(len(msg) > 0)
                print >> sys.stderr, "test: Received overlay message", getMessageName(
                    msg[0])
                if msg[0] == DIALBACK_REQUEST:
                    break
            self.assert_(msg[0] == DIALBACK_REQUEST)
            self.check_drequest(msg[1:])

            # Proper behaviour is to try to send a reply using a new return connection
            s2 = BTConnection('localhost',
                              self.hisport,
                              mylistenport=self.mylistenport[i],
                              user_infohash=dialback_infohash)
            s2.read_handshake_medium_rare(close_ok=True)
            if gen_dreply is not None:
                resp = gen_dreply(i)
                print >> sys.stderr, "test: sending DIALBACK_REPLY #", i
                s2.send(resp)
            time.sleep(2)
            # the other side should always close the
            # connection, either because we're done or he didn't like our
            # bad DIALBACK_REPLY message
            msg = s2.recv()
            if len(msg) > 0:
                print >> sys.stderr, "test: Received unexpected data", getMessageName(
                    msg[0])
            self.assert_(len(msg) == 0)
            s2.close()

            # Not really necessary, but helps with test_dialback_active2
            s.close()

        ext_ip = self.session.get_external_ip()
        print >> sys.stderr, "test: External IP address after test is", ext_ip

        if diff_ips_test:
            if self.config.sessconfig['dialback_trust_superpeers'] == 1:
                good = True
            else:
                good = False

        if good:
            self.assert_(ext_ip == REPLY_IP)
        else:
            self.assert_(ext_ip == self.myoriginalip)
    def _test_dreply(self,gen_dreply,good,diff_ips_test=False):
        for i in range(self.NLISTENERS):
            print >> sys.stderr,"test: waiting for #",i,"listenport",self.mylistenport[i]
            conn, addr = self.myss[i].accept()
            s = OLConnection(self.mykeypairs[i],'',0,conn,self.mylistenport[i])
            while True:
                msg = s.recv()
                self.assert_(len(msg) > 0)
                print >> sys.stderr,"test: Received overlay message",getMessageName(msg[0])
                if msg[0] == DIALBACK_REQUEST:
                    break
            self.assert_(msg[0] == DIALBACK_REQUEST)
            self.check_drequest(msg[1:])
            
            # Proper behaviour is to try to send a reply using a new return connection
            s2 = BTConnection('localhost',self.hisport,mylistenport=self.mylistenport[i],user_infohash=dialback_infohash)
            s2.read_handshake_medium_rare(close_ok = True)
            if gen_dreply is not None:
                resp = gen_dreply(i)
                print >> sys.stderr,"test: sending DIALBACK_REPLY #",i
                s2.send(resp)
            time.sleep(2)
            # the other side should always close the 
            # connection, either because we're done or he didn't like our
            # bad DIALBACK_REPLY message
            msg = s2.recv()
            if len(msg) > 0:
                print >> sys.stderr,"test: Received unexpected data",getMessageName(msg[0])
            self.assert_(len(msg)==0)
            s2.close()

            # Not really necessary, but helps with test_dialback_active2
            s.close()


        ext_ip = self.session.get_external_ip()
        print >>sys.stderr,"test: External IP address after test is",ext_ip
        
        if diff_ips_test:
            if self.config.sessconfig['dialback_trust_superpeers'] == 1:
                good = True
            else:
                good = False
                
        if good:
            self.assert_(ext_ip == REPLY_IP)
        else:
            self.assert_(ext_ip == self.myoriginalip)
Пример #3
0
    def receive_crawler_reply(self, sock, message_id, channel_id):
        # Sending a reply from a Tribler peer to a Crawler
        #     SIZE    INDEX
        #     1 byte: 0      CRAWLER_REPLY (from Tribler.Core.BitTornado.BT1.MessageID)
        #     1 byte: 1      --MESSAGE-SPECIFIC-ID--
        #     1 byte: 2      Channel id
        #     1 byte: 3      Parts left
        #     1 byte: 4      Indicating success (0) or failure (non 0)
        #     n byte: 5...   Reply payload

        if DEBUG:
            print >>sys.stderr, "test_crawler: receive_crawler_reply: waiting for channel",channel_id

        parts = []
        while True:
            response  = sock.recv()
            if response:
                if response[0] == CRAWLER_REPLY and response[1] == message_id and ord(response[2]) == channel_id:
                    parts.append(response[5:])
                    if DEBUG:
                        print >>sys.stderr, "test_crawler: received", getMessageName(response[0:2]), "channel", channel_id, "length", sum([len(part) for part in parts]), "parts left", ord(response[3])

                    if ord(response[3]):
                        # there are parts left
                        continue

                    return ord(response[4]), "".join(parts)

            return -1, ""
Пример #4
0
        def olbridge_handle_msg_func():
            # Called by OverlayThread

            if DEBUG:
                print >> sys.stderr, "olbridge: handle_msg_func", show_permid_short(
                    permid), selversion, getMessageName(
                        message[0]), currentThread().getName()

            try:
                if self.olappsmsghandler is None:
                    ret = True
                else:
                    ret = self.olappsmsghandler(permid, selversion, message)
            except:
                print_exc()
                ret = False
            if ret == False:
                if DEBUG:
                    print >> sys.stderr, "olbridge: olbridge_handle_msg_func closing!", show_permid_short(
                        permid), selversion, getMessageName(
                            message[0]), currentThread().getName()
                self.close(permid)
Пример #5
0
    def _send_request(self,
                      permid,
                      message_id,
                      channel_id,
                      payload,
                      frequency=3600,
                      callback=None):
        """
        Send a CRAWLER_REQUEST message to permid. This method assumes
        that connection exists to the permid.

        @param permid The destination peer
        @param message_id The message id
        @param payload The message content
        @param frequency Destination peer will return a frequency-error when this message_id has been received within the last frequency seconds
        @param callback Callable function/method is called when request is send with 2 paramaters (exc, permid)
        @return The message channel-id > 0 on success, and 0 on failure
        """

        # Sending a request from a Crawler to a Tribler peer
        #     SIZE    INDEX
        #     1 byte: 0      CRAWLER_REQUEST (from Tribler.Core.BitTornado.BT1.MessageID)
        #     1 byte: 1      --MESSAGE-SPECIFIC-ID--
        #     1 byte: 2      Channel id
        #     2 byte: 3+4    Frequency
        #     n byte: 5...   Request payload
        def _after_send_request(exc, permid):
            if DEBUG:
                if exc:
                    print >> sys.stderr, "crawler: could not send request to", show_permid_short(
                        permid), exc
            if exc:
                self._release_channel_id(permid, channel_id)

            # call the optional callback supplied with send_request
            if callback:
                callback(exc, permid)

        if DEBUG:
            print >> sys.stderr, "crawler: sending", getMessageName(
                CRAWLER_REQUEST + message_id), "with", len(
                    payload), "bytes payload to", show_permid_short(permid)
        self._overlay_bridge.send(
            permid, "".join(
                (CRAWLER_REQUEST, message_id, chr(channel_id & 0xFF),
                 chr((frequency >> 8) & 0xFF) + chr(frequency & 0xFF),
                 str(payload))), _after_send_request)
        return channel_id
Пример #6
0
 def got_message(self,dns,message):
     """ received message from peer, pass to upper layer """
     if DEBUG:
         print >> sys.stderr,"dlbreturn: got_message",getMessageName(message[0])
     if self.usermsghandler is None:
         if DEBUG:
             print >> sys.stderr,"dlbreturn: User receive callback not set"
         return
     try:
         ret = self.usermsghandler(dns,message)
         if ret is None:
             if DEBUG:
                 print >> sys.stderr,"dlbreturn: INTERNAL ERROR:", \
                     "User receive callback returned None, not True or False"
             ret = False
         return ret
     except:
         # Catch all
         print_exc(file=sys.stderr)
         return False
Пример #7
0
    def handleMessage(self, permid, selversion, message):
        """ Called by NetworkThread """
        #ProxyService_
        #
        # DEBUG
        #print "### olbridge: handleMessage", show_permid_short(permid), selversion, getMessageName(message[0]), currentThread().getName()
        #
        #_ProxyService

        if DEBUG:
            print >> sys.stderr, "olbridge: handleMessage", show_permid_short(
                permid), selversion, getMessageName(
                    message[0]), currentThread().getName()

        def olbridge_handle_msg_func():
            # Called by OverlayThread

            if DEBUG:
                print >> sys.stderr, "olbridge: handle_msg_func", show_permid_short(
                    permid), selversion, getMessageName(
                        message[0]), currentThread().getName()

            try:
                if self.olappsmsghandler is None:
                    ret = True
                else:
                    ret = self.olappsmsghandler(permid, selversion, message)
            except:
                print_exc()
                ret = False
            if ret == False:
                if DEBUG:
                    print >> sys.stderr, "olbridge: olbridge_handle_msg_func closing!", show_permid_short(
                        permid), selversion, getMessageName(
                            message[0]), currentThread().getName()
                self.close(permid)

        self.tqueue.add_task(olbridge_handle_msg_func, 0)
        return True
Пример #8
0
    def test_good_get_metadata_url(self):

        # 1. Establish overlay connection to Tribler
        s = OLConnection(self.my_keypair,'localhost',self.hisport)

        for tdef in [self.tdef1,self.tdef2]:
            msg = self.create_good_get_metadata(tdef.get_infohash())
            s.send(msg)
        
            try:
                s.b.s.settimeout(10.0)
                resp = s.recv()
                self.assert_(len(resp) > 0)
                print >>sys.stderr,"test: Got reply",getMessageName(resp[0])
                self.assert_(resp[0] == METADATA)
                self.check_metadata(resp[1:],tdef)

            except socket.timeout:
                print >> sys.stderr,"test: Timeout, bad, peer didn't reply with METADATA message"
                self.assert_(False)

        s.close()
Пример #9
0
    def subtest_invalid_messageid(self):
        """
        Send an invalid message-id from a registered crawler peer
        """
        print >>sys.stderr, "-"*80, "\ntest: invalid_messageid"

        # make sure that the OLConnection IS in the crawler_db
        crawler_db = CrawlerDBHandler.getInstance()
        crawler_db.temporarilyAddCrawler(self.my_permid)

        # We are a registered crawler, start sending invalid messages
        messages = [CRAWLER_REQUEST,
                    CRAWLER_REQUEST + chr(0),
                    CRAWLER_REPLY,
                    CRAWLER_REPLY + chr(0)]
        for msg in messages:
            s = OLConnection(self.my_keypair, "localhost", self.hisport)
            s.send(msg)
            response  = s.recv()
            assert response == "", "response type is %s" % getMessageName(response[0])

        time.sleep(1)
        s.close()
    def _test_qreply(self,gen_qreply,good):
        print >> sys.stderr,"test: waiting for reply"
        s = self.openconn

        msg = s.recv()
        self.assert_(len(msg) > 0)
        print >> sys.stderr,"test: Received overlay message",getMessageName(msg[0])
        self.assert_(msg[0] == QUERY)
        id = self.check_rquery(msg[1:])
        
        resp = gen_qreply(id)
        print >> sys.stderr,"test: sending QUERY_REPLY"
        s.send(resp)
        if good:
            time.sleep(10)
            # the other side should not have closed the connection, as
            # this is all valid, so this should not throw an exception:
            s.send('bla')
            s.close()
        else:
            # the other side should not like this and close the connection
            self.assert_(len(s.recv())==0)
            s.close()
Пример #11
0
    def _send_request(self, permid, message_id, channel_id, payload, frequency=3600, callback=None):
        """
        Send a CRAWLER_REQUEST message to permid. This method assumes
        that connection exists to the permid.

        @param permid The destination peer
        @param message_id The message id
        @param payload The message content
        @param frequency Destination peer will return a frequency-error when this message_id has been received within the last frequency seconds
        @param callback Callable function/method is called when request is send with 2 paramaters (exc, permid)
        @return The message channel-id > 0 on success, and 0 on failure
        """
        # Sending a request from a Crawler to a Tribler peer
        #     SIZE    INDEX
        #     1 byte: 0      CRAWLER_REQUEST (from Tribler.Core.BitTornado.BT1.MessageID)
        #     1 byte: 1      --MESSAGE-SPECIFIC-ID--
        #     1 byte: 2      Channel id
        #     2 byte: 3+4    Frequency
        #     n byte: 5...   Request payload
        def _after_send_request(exc, permid):
            if DEBUG:
                if exc:
                    print >> sys.stderr, time.asctime(),'-', "crawler: could not send request to", show_permid_short(permid), exc
            if exc:
                self._release_channel_id(permid, channel_id)

            # call the optional callback supplied with send_request
            if callback:
                callback(exc, permid)

        if DEBUG: print >> sys.stderr, time.asctime(),'-', "crawler: sending", getMessageName(CRAWLER_REQUEST+message_id), "with", len(payload), "bytes payload to", show_permid_short(permid)
        self._overlay_bridge.send(permid, "".join((CRAWLER_REQUEST,
                                                   message_id,
                                                   chr(channel_id & 0xFF),
                                                   chr((frequency >> 8) & 0xFF) + chr(frequency & 0xFF),
                                                   str(payload))), _after_send_request)
        return channel_id
Пример #12
0
    def subtest_invalid_permid(self):
        """
        Send crawler messages from a non-crawler peer
        """
        print >>sys.stderr, "-"*80, "\ntest: invalid_permid"

        # make sure that the OLConnection is NOT in the crawler_db
        crawler_db = CrawlerDBHandler.getInstance()
        assert not self.my_permid in crawler_db.getCrawlers()

        # We are not a registered crawler, any request from us should
        # be denied
        messages = [CRAWLER_REQUEST,
                    CRAWLER_REQUEST + CRAWLER_DATABASE_QUERY,
                    CRAWLER_REQUEST + CRAWLER_DATABASE_QUERY,
                    CRAWLER_REQUEST + chr(0)]
        for msg in messages:
            s = OLConnection(self.my_keypair, "localhost", self.hisport)
            s.send(msg)
            response  = s.recv()
            assert response == "", "response type is %s" % getMessageName(response[0])

        time.sleep(1)
        s.close()
    def _test_qreply(self, gen_qreply, good):
        print >> sys.stderr, "test: waiting for reply"
        s = self.openconn

        msg = s.recv()
        self.assert_(len(msg) > 0)
        print >> sys.stderr, "test: Received overlay message", getMessageName(
            msg[0])
        self.assert_(msg[0] == QUERY)
        id = self.check_rquery(msg[1:])

        resp = gen_qreply(id)
        print >> sys.stderr, "test: sending QUERY_REPLY"
        s.send(resp)
        if good:
            time.sleep(10)
            # the other side should not have closed the connection, as
            # this is all valid, so this should not throw an exception:
            s.send('bla')
            s.close()
        else:
            # the other side should not like this and close the connection
            self.assert_(len(s.recv()) == 0)
            s.close()
Пример #14
0
    def _send_reply(self,
                    permid,
                    message_id,
                    channel_id,
                    payload,
                    error=0,
                    callback=None):
        """
        Send a CRAWLER_REPLY message to permid. This method assumes
        that connection exists to the permid.
        
        @param permid The destination peer
        @param message_id The message id
        @param channel_id The channel id. Used to match replies to requests
        @param payload The message content
        @param error The error code. (0: no-error, 253: unknown-message, 254: frequency-error, 255: reserved)
        @param callback Callable function/method is called when request is send with 2 paramaters (exc, permid)
        @return The message channel-id > 0 on success, and 0 on failure
        """
        # Sending a reply from a Tribler peer to a Crawler
        #     SIZE    INDEX
        #     1 byte: 0      CRAWLER_REPLY (from Tribler.Core.BitTornado.BT1.MessageID)
        #     1 byte: 1      --MESSAGE-SPECIFIC-ID--
        #     1 byte: 2      Channel id
        #     1 byte: 3      Parts left
        #     1 byte: 4      Indicating success (0) or failure (non 0)
        #     n byte: 5...   Reply payload
        if len(payload) > MAX_PAYLOAD_LENGTH:
            remaining_payload = payload[MAX_PAYLOAD_LENGTH:]

            def _after_send_reply(exc, permid):
                """
                Called after the overlay attempted to send a reply message
                """
                if DEBUG:
                    print >> sys.stderr, "crawler: _after_send_reply", show_permid_short(
                        permid), exc
                if not exc:
                    self.send_reply(permid,
                                    message_id,
                                    channel_id,
                                    remaining_payload,
                                    error=error)
                # call the optional callback supplied with send_request
                if callback:
                    callback(exc, permid)

            # 03/06/09 boudewijn: parts_left may be no larger than 255
            # because we only use one byte to store the 'parts
            # left'. This does not mean that there can't be more than
            # 255 parts!
            parts_left = min(255, int(len(payload) / MAX_PAYLOAD_LENGTH))
            payload = payload[:MAX_PAYLOAD_LENGTH]

        else:

            def _after_send_reply(exc, permid):
                if DEBUG:
                    if exc:
                        print >> sys.stderr, "crawler: could not send request", show_permid_short(
                            permid), exc
                # call the optional callback supplied with send_request
                if callback:
                    callback(exc, permid)

            parts_left = 0

            # remove from self._channels if it is still there (could
            # have been remove during periodic timeout check)
            if permid in self._channels and channel_id in self._channels[
                    permid]:
                del self._channels[permid][channel_id]
                if not self._channels[permid]:
                    del self._channels[permid]

        if DEBUG:
            print >> sys.stderr, "crawler: sending", getMessageName(
                CRAWLER_REPLY + message_id), "with", len(
                    payload), "bytes payload to", show_permid_short(permid)
        self._overlay_bridge.send(
            permid, "".join(
                (CRAWLER_REPLY, message_id, chr(channel_id & 0xFF),
                 chr(parts_left & 0xFF), chr(error & 0xFF), str(payload))),
            _after_send_reply)
        return channel_id
Пример #15
0
    def handle_reply(self, permid, selversion, message):
        """
        Received CRAWLER_REPLY message from OverlayApps
        """
        if selversion >= OLPROTO_VER_SEVENTH and len(message) >= 5 and message[1] in self._message_handlers:
            
            message_id = message[1]
            channel_id = ord(message[2])
            parts_left = ord(message[3])
            error = ord(message[4])

            # A request must exist in self._channels, otherwise we did
            # not request this reply
            if permid in self._channels and channel_id in self._channels[permid]:

                # add part to buffer
                self._channels[permid][channel_id][1] += message[5:]

                if parts_left:
                    # todo: register some event to remove the buffer
                    # after a time (in case connection is lost before
                    # all parts are received)

                    if DEBUG: print >> sys.stderr, time.asctime(),'-', "crawler: received", getMessageName(CRAWLER_REPLY+message_id), "with", len(message), "bytes payload from", show_permid_short(permid), "with", parts_left, "parts left"
                    # Can't do anything until all parts have been received
                    return True
                else:
                    timestamp, payload, channel_data = self._channels[permid].pop(channel_id)
                    if DEBUG:
                        if error == 253:
                            # unknown message error (probably because
                            # the crawler is newer than the peer)
                            print >> sys.stderr, time.asctime(),'-', "crawler: received", getMessageName(CRAWLER_REPLY+message_id), "with", len(message), "bytes payload from", show_permid_short(permid), "indicating an unknown message error"
                        if error == 254:
                            # frequency error (we did this request recently)
                            print >> sys.stderr, time.asctime(),'-', "crawler: received", getMessageName(CRAWLER_REPLY+message_id), "with", len(message), "bytes payload from", show_permid_short(permid), "indicating a frequency error"
                        else:
                            print >> sys.stderr, time.asctime(),'-', "crawler: received", getMessageName(CRAWLER_REPLY+message_id), "with", len(payload), "bytes payload from", show_permid_short(permid)
                    if not self._channels[permid]:
                        del self._channels[permid]

                    def send_request_helper(message_id, payload, frequency=3600, callback=None, channel_data=None):
                        return self.send_request(permid, message_id, payload, frequency=frequency, callback=callback, channel_data=channel_data)

                    # 20/10/08. Boudewijn: We will no longer
                    # disconnect based on the return value from the
                    # message handler
                    try:
                        self._message_handlers[message_id][1](permid, selversion, channel_id, channel_data, error, payload, send_request_helper)
                    except:
                        print_exc()
                    return True
            else:
                # reply from unknown permid or channel
                if DEBUG: print >> sys.stderr, time.asctime(),'-', "crawler: received", getMessageName(CRAWLER_REPLY+message_id), "with", len(payload), "bytes payload from", show_permid_short(permid), "from unknown peer or unused channel"
                
        if DEBUG:
            if len(message) >= 2:
                message_id = message[1]
            else:
                message_id = ""
            print >> sys.stderr, time.asctime(),'-', "crawler: received", getMessageName(CRAWLER_REPLY+message_id), "with", len(message), "bytes from", show_permid_short(permid), "from unknown peer or unused channel"
        return False
Пример #16
0
    def _send_reply(self, permid, message_id, channel_id, payload, error=0, callback=None):
        """
        Send a CRAWLER_REPLY message to permid. This method assumes
        that connection exists to the permid.
        
        @param permid The destination peer
        @param message_id The message id
        @param channel_id The channel id. Used to match replies to requests
        @param payload The message content
        @param error The error code. (0: no-error, 253: unknown-message, 254: frequency-error, 255: reserved)
        @param callback Callable function/method is called when request is send with 2 paramaters (exc, permid)
        @return The message channel-id > 0 on success, and 0 on failure
        """
        # Sending a reply from a Tribler peer to a Crawler
        #     SIZE    INDEX
        #     1 byte: 0      CRAWLER_REPLY (from Tribler.Core.BitTornado.BT1.MessageID)
        #     1 byte: 1      --MESSAGE-SPECIFIC-ID--
        #     1 byte: 2      Channel id
        #     1 byte: 3      Parts left
        #     1 byte: 4      Indicating success (0) or failure (non 0)
        #     n byte: 5...   Reply payload
        if len(payload) > MAX_PAYLOAD_LENGTH:
            remaining_payload = payload[MAX_PAYLOAD_LENGTH:]

            def _after_send_reply(exc, permid):
                """
                Called after the overlay attempted to send a reply message
                """
                if DEBUG:
                    print >> sys.stderr, time.asctime(),'-', "crawler: _after_send_reply", show_permid_short(permid), exc
                if not exc:
                    self.send_reply(permid, message_id, channel_id, remaining_payload, error=error)
                # call the optional callback supplied with send_request
                if callback:
                    callback(exc, permid)

            # 03/06/09 boudewijn: parts_left may be no larger than 255
            # because we only use one byte to store the 'parts
            # left'. This does not mean that there can't be more than
            # 255 parts!
            parts_left = min(255, int(len(payload) / MAX_PAYLOAD_LENGTH))
            payload = payload[:MAX_PAYLOAD_LENGTH]

        else:
            def _after_send_reply(exc, permid):
                if DEBUG:
                    if exc:
                        print >> sys.stderr, time.asctime(),'-', "crawler: could not send request", show_permid_short(permid), exc
                # call the optional callback supplied with send_request
                if callback:
                    callback(exc, permid)

            parts_left = 0

            # remove from self._channels if it is still there (could
            # have been remove during periodic timeout check)
            if permid in self._channels and channel_id in self._channels[permid]:
                del self._channels[permid][channel_id]
                if not self._channels[permid]:
                    del self._channels[permid]

        if DEBUG: print >> sys.stderr, time.asctime(),'-', "crawler: sending", getMessageName(CRAWLER_REPLY+message_id), "with", len(payload), "bytes payload to", show_permid_short(permid)
        self._overlay_bridge.send(permid, "".join((CRAWLER_REPLY,
                                                   message_id,
                                                   chr(channel_id & 0xFF),
                                                   chr(parts_left & 0xFF),
                                                   chr(error & 0xFF),
                                                   str(payload))), _after_send_reply)
        return channel_id
Пример #17
0
 def olbridge_handle_msg_func():
     # Called by OverlayThread
     
     if DEBUG:
         print >>sys.stderr,time.asctime(),'-', "olbridge: handle_msg_func",show_permid_short(permid),selversion,getMessageName(message[0]),currentThread().getName()
      
     try:
         if self.olappsmsghandler is None:
             ret = True
         else:
             ret = self.olappsmsghandler(permid,selversion,message)
     except:
         print_exc()
         ret = False
     if ret == False:
         self.close(permid)
Пример #18
0
    def handle_reply(self, permid, selversion, message):
        """
        Received CRAWLER_REPLY message from OverlayApps
        """
        if selversion >= OLPROTO_VER_SEVENTH and len(
                message) >= 5 and message[1] in self._message_handlers:

            message_id = message[1]
            channel_id = ord(message[2])
            parts_left = ord(message[3])
            error = ord(message[4])

            # A request must exist in self._channels, otherwise we did
            # not request this reply
            if permid in self._channels and channel_id in self._channels[
                    permid]:

                # add part to buffer
                self._channels[permid][channel_id][1] += message[5:]

                if parts_left:
                    # todo: register some event to remove the buffer
                    # after a time (in case connection is lost before
                    # all parts are received)

                    if DEBUG:
                        print >> sys.stderr, "crawler: received", getMessageName(
                            CRAWLER_REPLY + message_id), "with", len(
                                message
                            ), "bytes payload from", show_permid_short(
                                permid), "with", parts_left, "parts left"
                    # Can't do anything until all parts have been received
                    return True
                else:
                    timestamp, payload, channel_data = self._channels[
                        permid].pop(channel_id)
                    if DEBUG:
                        if error == 253:
                            # unknown message error (probably because
                            # the crawler is newer than the peer)
                            print >> sys.stderr, "crawler: received", getMessageName(
                                CRAWLER_REPLY + message_id), "with", len(
                                    message
                                ), "bytes payload from", show_permid_short(
                                    permid
                                ), "indicating an unknown message error"
                        if error == 254:
                            # frequency error (we did this request recently)
                            print >> sys.stderr, "crawler: received", getMessageName(
                                CRAWLER_REPLY + message_id), "with", len(
                                    message
                                ), "bytes payload from", show_permid_short(
                                    permid), "indicating a frequency error"
                        else:
                            print >> sys.stderr, "crawler: received", getMessageName(
                                CRAWLER_REPLY + message_id), "with", len(
                                    payload
                                ), "bytes payload from", show_permid_short(
                                    permid)
                    if not self._channels[permid]:
                        del self._channels[permid]

                    def send_request_helper(message_id,
                                            payload,
                                            frequency=3600,
                                            callback=None,
                                            channel_data=None):
                        return self.send_request(permid,
                                                 message_id,
                                                 payload,
                                                 frequency=frequency,
                                                 callback=callback,
                                                 channel_data=channel_data)

                    # 20/10/08. Boudewijn: We will no longer
                    # disconnect based on the return value from the
                    # message handler
                    try:
                        self._message_handlers[message_id][1](
                            permid, selversion, channel_id, channel_data,
                            error, payload, send_request_helper)
                    except:
                        print_exc()
                    return True
            else:
                # reply from unknown permid or channel
                if DEBUG:
                    print >> sys.stderr, "crawler: received", getMessageName(
                        CRAWLER_REPLY + message_id), "with", len(
                            payload), "bytes payload from", show_permid_short(
                                permid), "from unknown peer or unused channel"

        if DEBUG:
            if len(message) >= 2:
                message_id = message[1]
            else:
                message_id = ""
            print >> sys.stderr, "crawler: received", getMessageName(
                CRAWLER_REPLY + message_id), "with", len(
                    message), "bytes from", show_permid_short(
                        permid), "from unknown peer or unused channel"
        return False
 def handleMessage(self,permid,selversion,message):
     """ Called by NetworkThread """
     #ProxyService_
     #
     # DEBUG
     #print "### olbridge: handleMessage", show_permid_short(permid), selversion, getMessageName(message[0]), currentThread().getName()
     #
     #_ProxyService
     
     if DEBUG:
         print >>sys.stderr,"olbridge: handleMessage",show_permid_short(permid),selversion,getMessageName(message[0]),currentThread().getName()
     
     def olbridge_handle_msg_func():
         # Called by OverlayThread
         
         if DEBUG:
             print >>sys.stderr,"olbridge: handle_msg_func",show_permid_short(permid),selversion,getMessageName(message[0]),currentThread().getName()
          
         try:
             if self.olappsmsghandler is None:
                 ret = True
             else:
                 ret = self.olappsmsghandler(permid,selversion,message)
         except:
             print_exc()
             ret = False
         if ret == False:
             if DEBUG:
                 print >>sys.stderr,"olbridge: olbridge_handle_msg_func closing!",show_permid_short(permid),selversion,getMessageName(message[0]),currentThread().getName()
             self.close(permid)
             
     self.tqueue.add_task(olbridge_handle_msg_func,0)
     return True