コード例 #1
0
ファイル: community.py プロジェクト: proximate/proximate
class Hello_Server:
    def __init__(self, address, sock, data):
        self.q = TCP_Queue(self.msghandler)
        self.q.set_timeout(TP_CONNECT_TIMEOUT)
        self.address = address
        self.q.append_input(data)
        self.q.initialize(sock)

    def msghandler(self, q, benhello, ctx):
        community.got_rpc_msg(benhello, self.address)
        self.q.write(bencode(community.gen_rpc_hello()))
        self.q.close_after_send()
        return True
コード例 #2
0
ファイル: community.py プロジェクト: proximate/proximate
class Hello_Client:
    def __init__(self, address, benhello):
        self.address = address
        self.q = TCP_Queue(self.msghandler)
        if not self.q.connect(address, TP_CONNECT_TIMEOUT):
            return
        prefix = TP_HELLO + '\n'
        self.q.write(prefix, writelength=False)
        self.q.write(benhello)
        self.q.set_timeout(TP_CONNECT_TIMEOUT)

    def msghandler(self, q, data, ctx):
        community.got_rpc_msg(data, self.address)
        return False
コード例 #3
0
ファイル: tcpfetcher.py プロジェクト: proximate/proximate
class Fetch_Queue:
    def __init__(self, user=None, sock=None, address=None, data=None):
        self.q = TCP_Queue(self.fetchhandler, closehandler=self.queue_closed)
        self.user = user
        self.openingconnection = (user != None)
        self.reqs = {}
        if self.openingconnection:
            # It's an outgoing queue
            self.add_connection(user)
        else:
            # It's an incoming queue
            self.q.set_timeout(TP_FETCH_TIMEOUT)
            self.q.remote = address
            self.q.append_input(data)
            self.q.initialize(sock)

    def add(self, req):
        # fetch master: start connection process, if necessary
        if self.q.status == TCPQ_NO_CONNECTION and not self.connect():
            return False
        if req.rid >= 0:
            self.reqs[req.rid] = req
        self.q.write(req.payload)
        return True

    def add_connection(self, user):
        queuelist = fetchqueues.setdefault(user, [])
        queuelist.append(self)
        return queuelist

    def cleanup(self, msg):
        if self.user == None:
            return
        queuelist = fetchqueues.get(self.user)
        try:
            queuelist.remove(self)
        except ValueError:
            pass
        debug('fetcher: connection to %s closed: %s\n' % (self.user.tag(), msg))

    def close(self, msg):
        self.q.close(msg=msg)

    def connect(self):
        ip = self.user.get('ip')
        port = self.user.get('port')

        if not community.get_network_state(community.IP_NETWORK):
            # Act as if we were missing the IP network
            warning('fetcher: IP network disabled\n')
            ip = None

        if ip == None or port == None:
            warning('fetcher: No ip/port to open %s\n' % (self.user.tag()))
            return False

        debug('fetcher: open from %s: %s:%s\n' % (self.user.tag(), ip, port))

        if self.openingconnection == False or self.q.connect((ip, port), TP_CONNECT_TIMEOUT) == False:
            return False

        # The first write is seen by opposite side's RPC hander, not TCP_Queue
        prefix = '%s\n' %(TP_FETCH_RECORDS)
        self.q.write(prefix, writelength=False)

        self.q.write(fetcher.encode(firstmsg, -1, ''))

        # Close queue that is idle for a period of time. This is also the
        # maximum processing time for pending requests. Requests taking
        # longer than this must use other state tracking mechanisms.
        self.q.set_timeout(TP_FETCH_TIMEOUT)
        return True

    def fetchhandler(self, q, msg, parameter):
        d = fetcher.decode(msg)
        if d == None:
            warning('fetch master: spurious msg\n')
            return False

        if self.user == None:
            uid = d.get('uid')
            if uid == None or type(uid) != str:
                warning('fetch slave: no uid in fetch connection\n')
                return False
            self.user = community.safe_get_user(uid, q.remote[0])
            if self.user == None:
                warning('fetch slave: Invalid uid from master: %s\n' % (uid))
                return False
            queuelist = self.add_connection(self.user)
            if len(queuelist) > MAX_QUEUES_PER_USER:
                warning('Not allowing too many connections from the same user: %s\n' % (self.user.tag()))
                return False
            debug('fetcher: connection from %s\n' % (self.user.tag()))
            return True

        if len(d['rt']) == 0:
            self.reqs.pop(d['rid'], None)  # Remove pending req (master side)

        fetcher.handle_msg(self.user, d)
        return True

    def queue_closed(self, q, parameter, msg):
        """ Master side: this is called from TCP_Queue close() """

        if self.user == None:
            self.cleanup('No user context -> nothing to retry')
            return

        pendingreqs = []
        for req in self.reqs.values():
            if req.userreplies.has_key(self.user) == False:
                pendingreqs.append(req)

        if len(pendingreqs) == 0:
            self.cleanup('Nothing to retry')
            return

        # First, remove this queue by calling cleanup()
        self.cleanup('Migrate requests')

        # Check requests that can still be resent. Put resendable requests
        # into other queues. Note, this queue is already removed by cleanup().
        q = select_queue(self.user)
        for req in pendingreqs:
            if not req.retry() or not q.add(req):
                req.call(self.user, None)

    def send_reply(self, payload):
        # fetch slave: reply, but connect first, if necessary
        if self.q.status == TCPQ_NO_CONNECTION and not self.connect():
            return False
        self.q.write(payload)
        return True