Ejemplo n.º 1
0
class CSpaceAcceptor(object):
    def __init__(self, sock, connectionId, reactor, callback):
        self.stream = TCPStream(sock, reactor)
        self.stream.setCloseCallback(self._onClose)
        self.stream.setErrorCallback(self._onError)
        self.stream.setInputCallback(self._onInput)
        self.stream.initiateRead(1)
        self.stream.writeData('ACCEPT %s\r\n' % connectionId)
        self.response = ''
        self.op = AsyncOp(callback, self.stream.close)

    def getOp(self):
        return self.op

    def _onClose(self):
        self.stream.close()
        self.op.notify(-1, None)

    def _onError(self, err, errMsg):
        self._onClose()

    def _onInput(self, data):
        self.response += data
        if self.response.endswith('\n'):
            if not self.response.startswith('OK'):
                self._onClose()
                return
            self.stream.shutdown()
            sock = self.stream.getSock()
            self.op.notify(0, sock)
Ejemplo n.º 2
0
class CSpaceAcceptor( object ) :
    def __init__( self, sock, connectionId, reactor, callback ) :
        self.stream = TCPStream( sock, reactor )
        self.stream.setCloseCallback( self._onClose )
        self.stream.setErrorCallback( self._onError )
        self.stream.setInputCallback( self._onInput )
        self.stream.initiateRead( 1 )
        self.stream.writeData( 'ACCEPT %s\r\n' % connectionId )
        self.response = ''
        self.op = AsyncOp( callback, self.stream.close )

    def getOp( self ) : return self.op

    def _onClose( self ) :
        self.stream.close()
        self.op.notify( -1, None )

    def _onError( self, err, errMsg ) :
        self._onClose()

    def _onInput( self, data ) :
        self.response += data
        if self.response.endswith('\n') :
            if not self.response.startswith('OK') :
                self._onClose()
                return
            self.stream.shutdown()
            sock = self.stream.getSock()
            self.op.notify( 0, sock )
Ejemplo n.º 3
0
 def __init__(self, reactor, callback=None):
     assert env.isContactAction or env.isIncoming
     self.reactor = reactor
     self.op = AsyncOp(callback, self._doCancel)
     self.state = self.CONNECTING
     self.connectOp = tcpConnect(('127.0.0.1', env.port), self.reactor,
                                 self._onConnect)
     self.stream = None
Ejemplo n.º 4
0
 def __init__(self, curlHandle, reactor, callback=None):
     self.reactor = reactor
     self.cm = pycurl.CurlMulti()
     self.c = curlHandle
     self.cm.add_handle(self.c)
     self.fdsets = ([], [], [])
     self.timerOp = self.reactor.callLater(0, self._onInitialTimer)
     self.op = AsyncOp(callback, self._doCancel)
Ejemplo n.º 5
0
class _Lookup( object ) :
    def __init__( self, clientObj, destId, startNodes, callback=None ) :
        assert startNodes
        self.clientObj = clientObj
        self.destId = destId
        self.destNumId = idToNum( destId )
        self.seen = {}
        self.closest = []
        self.pending = []
        self.calling = {}
        for nodeAddr in startNodes :
            self._newNode( nodeAddr )
        self._callPending()
        self.op = AsyncOp( callback, self._doCancel )

    def getOp( self ) : return self.op

    def _doCancel( self ) :
        for op in self.calling.values() :
            op.cancel()
        self.calling.clear()

    def _newNode( self, nodeAddr ) :
        if nodeAddr in self.seen : return
        info = _LookupNodeInfo( nodeAddr, self.destNumId )
        self.seen[nodeAddr] = info
        self._addPending( info )

    def _addPending( self, info ) :
        insort( self.pending, info )
        del self.pending[DHT_K*3/2:]

    def _callPending( self ) :
        count = DHT_PARALLEL - len(self.calling)
        nodeInfoList = self.pending[:count]
        del self.pending[:count]
        for info in nodeInfoList :
            self._callNode( info )

    def _callNode( self, info ) :
        assert len(self.calling) < DHT_PARALLEL
        def onResult( err, payload ) :
            self._onResult( info, err, payload )
        op = self.clientObj.callFindNodes( self.destId, info.nodeAddr,
                onResult, timeout=3, retries=0, backoff=1 )
        self.calling[info.nodeAddr] = op

    def _onResult( self, info, err, payload ) :
        del self.calling[info.nodeAddr]
        if err >= 0 :
            insort( self.closest, info )
            del self.closest[DHT_K:]
            for nodeAddr in payload :
                self._newNode( nodeAddr )
        self._callPending()
        if not self.calling :
            assert len(self.pending) == 0
            self.op.notify( [ni.nodeAddr for ni in self.closest] )
Ejemplo n.º 6
0
class _Lookup( object ) :
    def __init__( self, clientObj, destId, startNodes, callback=None ) :
        assert startNodes
        self.clientObj = clientObj
        self.destId = destId
        self.destNumId = idToNum( destId )
        self.seen = {}
        self.closest = []
        self.pending = []
        self.calling = {}
        for nodeAddr in startNodes :
            self._newNode( nodeAddr )
        self._callPending()
        self.op = AsyncOp( callback, self._doCancel )

    def getOp( self ) : return self.op

    def _doCancel( self ) :
        for op in self.calling.values() :
            op.cancel()
        self.calling.clear()

    def _newNode( self, nodeAddr ) :
        if nodeAddr in self.seen : return
        info = _LookupNodeInfo( nodeAddr, self.destNumId )
        self.seen[nodeAddr] = info
        self._addPending( info )

    def _addPending( self, info ) :
        insort( self.pending, info )
        del self.pending[DHT_K*3/2:]

    def _callPending( self ) :
        count = DHT_PARALLEL - len(self.calling)
        nodeInfoList = self.pending[:count]
        del self.pending[:count]
        for info in nodeInfoList :
            self._callNode( info )

    def _callNode( self, info ) :
        assert len(self.calling) < DHT_PARALLEL
        def onResult( err, payload ) :
            self._onResult( info, err, payload )
        op = self.clientObj.callFindNodes( self.destId, info.nodeAddr,
                onResult, timeout=3, retries=0, backoff=1 )
        self.calling[info.nodeAddr] = op

    def _onResult( self, info, err, payload ) :
        del self.calling[info.nodeAddr]
        if err >= 0 :
            insort( self.closest, info )
            del self.closest[DHT_K:]
            for nodeAddr in payload :
                self._newNode( nodeAddr )
        self._callPending()
        if not self.calling :
            assert len(self.pending) == 0
            self.op.notify( [ni.nodeAddr for ni in self.closest] )
Ejemplo n.º 7
0
 def __init__(self, sock, connectionId, reactor, callback):
     self.stream = TCPStream(sock, reactor)
     self.stream.setCloseCallback(self._onClose)
     self.stream.setErrorCallback(self._onError)
     self.stream.setInputCallback(self._onInput)
     self.stream.initiateRead(1)
     self.stream.writeData('ACCEPT %s\r\n' % connectionId)
     self.response = ''
     self.op = AsyncOp(callback, self.stream.close)
Ejemplo n.º 8
0
 def __init__(self, sock, remoteUser, remoteService, reactor, callback):
     self.stream = TCPStream(sock, reactor)
     self.stream.setCloseCallback(self._onClose)
     self.stream.setErrorCallback(self._onError)
     self.stream.setInputCallback(self._onInput)
     self.stream.initiateRead(1)
     self.stream.writeData('CONNECT %s %s\r\n' %
                           (remoteUser, remoteService))
     self.response = ''
     self.op = AsyncOp(callback, self.stream.close)
Ejemplo n.º 9
0
 def __init__(self, fileClient, remotePath, localPath, callback=None):
     self.fileClient = fileClient
     self.remotePath = remotePath
     self.localPath = localPath
     self.out = file(localPath, 'w+b')
     self.sizeOp = self.fileClient.callGetSize(remotePath, self._onGetSize)
     self.fileSize = -1
     self.op = AsyncOp(callback, self._doCancel)
     self.blockSize = 16384
     self.requestedSize = 0
     self.receivedSize = 0
     self.fetchOps = {}
Ejemplo n.º 10
0
Archivo: tcp.py Proyecto: hj91/cspace
class TCPCloser( TCPWriter ) :
    def __init__( self, sock, pendingWrite, reactor, callback=None ) :
        TCPWriter.__init__( self, sock, pendingWrite, reactor )
        self.op = AsyncOp( callback, self.shutdown )

    def getOp( self ) : return self.op

    def _notify( self ) :
        self.sock.close()
        self.op.notify()
    def onWriteComplete( self ) : self._notify()
    def onError( self, err, errMsg ) : self._notify()
    def onTimeout( self ) : self._notify()
Ejemplo n.º 11
0
 def __init__( self, clientObj, destId, startNodes, callback=None ) :
     assert startNodes
     self.clientObj = clientObj
     self.destId = destId
     self.destNumId = idToNum( destId )
     self.seen = {}
     self.closest = []
     self.pending = []
     self.calling = {}
     for nodeAddr in startNodes :
         self._newNode( nodeAddr )
     self._callPending()
     self.op = AsyncOp( callback, self._doCancel )
Ejemplo n.º 12
0
def _serviceConnect( sslConn, serviceName, reactor, callback=None ) :
    def doCancel() :
        ms.shutdown()
        sslAbort( sslConn )
    def onClose( *args ) :
        doCancel()
        op.notify( None )
    def onInput( data ) :
        try :
            result = decode( data )
            assert type(result) is int
            assert result == 0
        except :
            doCancel()
            op.notify( None )
            return
        ms.shutdown()
        op.notify( sslConn )
    ms = SSLMessageStream( sslConn, reactor )
    ms.setCloseCallback( onClose )
    ms.setErrorCallback( onClose )
    ms.setInvalidMessageCallback( onClose )
    ms.setInputCallback( onInput )
    ms.sendMessage( encode(serviceName) )
    ms.enableRead( True )
    op = AsyncOp( callback, doCancel )
    return op
Ejemplo n.º 13
0
Archivo: node.py Proyecto: hj91/cspace
    def _initNodeRefresher(self):
        obj = Dummy()

        def doWait():
            timeout = REFRESH_NODES_INTERVAL
            obj.op = self.reactor.callLater(timeout, doRefresh)

        def onLookup(nodes):
            doWait()

        def doRefresh():
            bucket = choice(self.ktable.table)
            destNumId = randint(bucket.start, bucket.end - 1)
            destId = numToId(destNumId)
            startNodes = self.ktable.getClosestNodes(destNumId)
            if not startNodes:
                doWait()
                return
            obj.op = self.client.lookup(destId, startNodes, onLookup)

        def doCancel():
            obj.op.cancel()

        obj.op = self.reactor.callLater(0, doRefresh)
        op = AsyncOp(None, doCancel)
        self.otherOps.add(op)
Ejemplo n.º 14
0
    def refreshUser(self, publicKey, callback=None):
        pubKeyData = publicKey.toDER_PublicKey()
        entry = self.d.get(pubKeyData)
        if entry is None:
            entry = _Entry(publicKey)
            self.d[pubKeyData] = entry
        assert entry.state != ES_NOTIFYING
        if entry.state == ES_DEFAULT:
            assert entry.lookupOp is None
            assert entry.notifyOps is None

            def onLookupUser(location):
                self._onLookupUser(entry, location)

            entry.lookupOp = lookupUser(
                publicKey, self.dhtClient, self.nodeTable,
                lambda loc: self._onLookupUser(entry, loc))
            entry.state = ES_LOOKINGUP
            entry.notifyOps = set()

        def doCancel():
            entry.notifyOps.remove(op)

        op = AsyncOp(callback, doCancel)
        entry.notifyOps.add(op)
        return op
Ejemplo n.º 15
0
def acceptIncoming(acceptFlag, sslConn, reactor, callback=None):
    def doCancel():
        stream.close()

    def onError(*args):
        doCancel()
        op.notify(None)

    def onWriteComplete():
        stream.shutdown()
        op.notify(sslConn)

    stream = SSLMessageStream(sslConn, reactor)
    stream.setCloseCallback(onError)
    stream.setErrorCallback(onError)
    stream.setInvalidMessageCallback(onError)
    stream.setInputCallback(onError)
    stream.setWriteCompleteCallback(onWriteComplete)
    if acceptFlag:
        data = 0
    else:
        data = -1
    stream.sendMessage(encode(data))
    op = AsyncOp(callback, doCancel)
    return op
Ejemplo n.º 16
0
def routerAccept( routerAddr, connectionId, reactor, callback=None ) :
    obj = Dummy()
    def doCancel() :
        if obj.op : obj.op.cancel()
        if obj.rpcConn : obj.rpcConn.close()
    def onError() :
        doCancel()
        op.notify( None )
    def onRouterAccept( err, result ) :
        obj.op = None
        if err < 0 :
            onError()
            return
        sock = obj.rpcConn.getSock()
        obj.rpcConn.shutdown()
        op.notify( sock )
    def onTCPConnect( connector ) :
        obj.op = None
        if connector.getError() != 0 :
            onError()
            return
        obj.rpcConn = RPCConnection( connector.getSock(), reactor )
        obj.rpcConn.setCloseCallback( onError )
        obj.op = _doRPCCall( obj.rpcConn, 'Accept', [connectionId],
                onRouterAccept )
    obj.op = tcpConnect( routerAddr, reactor, onTCPConnect )
    op = AsyncOp( callback, doCancel )
    obj.rpcConn = None
    return op
Ejemplo n.º 17
0
    def probeUserOnline(self, publicKey, callback=None):
        assert self.sm.current() == self.ONLINE

        def onStateChange():
            lookupOp.cancel()
            op.notify(False)

        def doCancel():
            lookupOp.cancel()
            self.sm.removeCallback(callbackId)

        def onLookup(location):
            self.sm.removeCallback(callbackId)
            if location is None:
                op.notify(False)
                return
            if (not location.directLocations) and (
                    not location.routedLocations):
                op.notify(False)
                return
            op.notify(True)

        lookupOp = self.locationCache.refreshUser(publicKey, onLookup)
        callbackId = self.sm.insertCallback(onStateChange,
                                            src=self.ONLINE,
                                            single=True)
        op = AsyncOp(callback, doCancel)
        return op
Ejemplo n.º 18
0
    def _promptIncoming(self,
                        sslConn,
                        serviceName,
                        peerKey,
                        contactName,
                        incomingName,
                        callback=None):
        def doCancel():
            promptOp.cancel()
            sslAbort(sslConn)

        def onPromptResult(promptResult):
            if not promptResult:
                rejectOp = self._rejectIncoming(sslConn, op.notify)
                op.setCanceler(rejectOp.cancel)
            else:
                acceptOp = self._acceptIncoming(sslConn, serviceName, peerKey,
                                                contactName, incomingName,
                                                op.notify)
                op.setCanceler(acceptOp.cancel)

        promptName = contactName
        if not promptName:
            promptName = '(Unknown %s)' % incomingName
        promptOp = IncomingPromptWindow(promptName, serviceName, self.reactor,
                                        onPromptResult).getOp()
        op = AsyncOp(callback, doCancel)
        return op
Ejemplo n.º 19
0
def _sslHandshake(sock, sslContext, reactor, callback=None):
    def doCancel():
        acceptOp.cancel()
        sslAbort(sslConn)

    def onSSLAccept(err):
        if err is not None:
            sslAbort(sslConn)
            op.notify(None)
            return
        try:
            peerCert = sslConn.getPeerCertificate()
            peerKey = peerCert.getPublicKey()
            peerName = peerCert.getSubject().lookupEntry('commonName')
        except (SSLError, X509Error):
            sslAbort(sslConn)
            op.notify(None)
            return
        data = (sslConn, peerKey, peerName)
        op.notify(data)

    sslConn = SSLConnection(sslContext, sock)
    acceptOp = sslAccept(sslConn, reactor, onSSLAccept)
    op = AsyncOp(callback, doCancel)
    return op
Ejemplo n.º 20
0
    def _registerKey(self, callback=None):
        data = 'username:%s' % self.userName
        digestType = DigestType('SHA1')
        digest = Digest(digestType).digest(data)
        signature = self.rsaKey.sign(digest, digestType)

        form = dict(username=self.userName,
                    public_key=self.rsaKey.toDER_PublicKey(),
                    signature=signature)
        postData = urllib.urlencode(form)

        request = HttpRequest(self.reactor)

        def onResponse(returnCode, data):
            if returnCode != 200:
                op.notify(-1)
                return
            try:
                keyId = int(data)
                op.notify(keyId)
            except ValueError:
                op.notify(-1)

        httpOp = request.post('http://cspace.in/addkey', postData, onResponse)
        op = AsyncOp(callback, httpOp.cancel)
        return op
Ejemplo n.º 21
0
    def connectTo(self, publicKey, serviceName, callback=None):
        assert self.sm.current() == self.ONLINE

        def onStateChange():
            connectOp.cancel()
            op.notify(-1, None)

        def doCancel():
            connectOp.cancel()
            self.sm.removeCallback(callbackId)

        def onConnect(sslConn):
            self.sm.removeCallback(callbackId)
            if sslConn is None:
                op.notify(-1, None)
                return
            op.notify(0, sslConn)

        connectOp = userServiceConnect(self.profile.name, self.profile.rsaKey,
                                       self.listener.getPublicIP(), publicKey,
                                       serviceName, self.locationCache,
                                       self.reactor, onConnect)
        callbackId = self.sm.insertCallback(onStateChange,
                                            src=self.ONLINE,
                                            single=True)
        op = AsyncOp(callback, doCancel)
        return op
Ejemplo n.º 22
0
 def __init__( self, reactor, callback=None ) :
     assert env.isContactAction or env.isIncoming
     self.reactor = reactor
     self.op = AsyncOp( callback, self._doCancel )
     self.state = self.CONNECTING
     self.connectOp = tcpConnect( ('127.0.0.1',env.port), self.reactor, self._onConnect )
     self.stream = None
Ejemplo n.º 23
0
 def __init__( self, curlHandle, reactor, callback=None ) :
     self.reactor = reactor
     self.cm = pycurl.CurlMulti()
     self.c = curlHandle
     self.cm.add_handle( self.c )
     self.fdsets = ( [], [], [] )
     self.timerOp = self.reactor.callLater( 0, self._onInitialTimer )
     self.op = AsyncOp( callback, self._doCancel )
Ejemplo n.º 24
0
 def lookup( self, destId, startNodes, callback=None ) :
     def hookCallback( *args, **kwargs ) :
         print 'done lookup %s' % str(id(lop))
         op.notify( *args, **kwargs )
     lop = _Lookup( self, destId, startNodes, hookCallback ).getOp()
     print 'starting lookup... %s' % str(id(lop))
     op = AsyncOp( callback, lop.cancel )
     return op
Ejemplo n.º 25
0
 def __init__( self, sock, connectionId, reactor, callback ) :
     self.stream = TCPStream( sock, reactor )
     self.stream.setCloseCallback( self._onClose )
     self.stream.setErrorCallback( self._onError )
     self.stream.setInputCallback( self._onInput )
     self.stream.initiateRead( 1 )
     self.stream.writeData( 'ACCEPT %s\r\n' % connectionId )
     self.response = ''
     self.op = AsyncOp( callback, self.stream.close )
Ejemplo n.º 26
0
 def __init__( self, sock, remoteUser, remoteService, reactor, callback ) :
     self.stream = TCPStream( sock, reactor )
     self.stream.setCloseCallback( self._onClose )
     self.stream.setErrorCallback( self._onError )
     self.stream.setInputCallback( self._onInput )
     self.stream.initiateRead( 1 )
     self.stream.writeData( 'CONNECT %s %s\r\n' % (remoteUser,remoteService) )
     self.response = ''
     self.op = AsyncOp( callback, self.stream.close )
Ejemplo n.º 27
0
 def __init__( self, sslConn, reactor, callback=None, timeout=30 ) :
     self.sslConn = sslConn
     self.reactor = reactor
     self.timeout = timeout
     self.sock = sslConn.sock
     self.want = self.WANT_NONE
     self.timerOp = self.reactor.callLater( 0, self._onAction )
     self.timeoutOp = self.reactor.callLater( self.timeout, self._onTimeout )
     self.op = AsyncOp( callback, self._close )
Ejemplo n.º 28
0
def _findLiveNodes(count, nodeTable, dhtClient, reactor, callback=None):
    obj = Dummy()

    def doCancel():
        for pingOp in obj.pingOps:
            pingOp.cancel()
        obj.pingOps.clear()
        obj.timerOp.cancel()
        obj.timerOp = None

    def doNotify():
        doCancel()
        op.notify()

    def onPing(pingOp, err, payload):
        obj.pingOps.remove(pingOp)
        if err >= 0:
            obj.success += 1
        if obj.success >= count:
            doNotify()
        elif (not obj.nodes) and (not obj.pingOps):
            doNotify()

    def doPing(nodeAddr):
        pingOp = dhtClient.callPing(nodeAddr,
                                    lambda e, p: onPing(pingOp, e, p))
        obj.pingOps.add(pingOp)

    def doPingNodes(count):
        current = obj.nodes[:count]
        del obj.nodes[:count]
        for nodeAddr in current:
            doPing(nodeAddr)

    def onTimer():
        obj.timerCount += 1
        if not obj.pingedSeed:
            if (not obj.nodes) or (obj.timerCount == \
                    FIND_LIVE_NODES_TIMEOUT_COUNT ) :
                for nodeAddr in nodeTable.getSeedNodes():
                    doPing(nodeAddr)
                obj.pingedSeed = True
                return
        if not obj.nodes:
            return
        doPingNodes(10)

    obj.success = 0
    obj.pingOps = set()
    obj.nodes = nodeTable.getAllNodes()
    doPingNodes(10)
    obj.timerCount = 0
    obj.pingedSeed = False
    obj.timerOp = reactor.addTimer(FIND_LIVE_NODES_TIMEOUT, onTimer)
    op = AsyncOp(callback, doCancel)
    return op
Ejemplo n.º 29
0
Archivo: upnp.py Proyecto: hj91/cspace
 def callAction( self, name, params, reactor, callback=None ) :
     payload = self.getActionPayload( name, params )
     http = HttpRequest( reactor )
     http.addHeader( 'Content-Type: text/xml; charset="utf-8"' )
     http.addHeader( 'SOAPACTION: "%s#%s"' % (self.service,name) )
     def onResponse( result, data ) :
         self._onActionResponse( op, name, result, data )
     httpOp = http.post( self.controlUrl, payload, onResponse )
     op = AsyncOp( callback, httpOp.cancel )
     return op
Ejemplo n.º 30
0
def _findNewNodes(nodeTable, dhtClient, reactor, callback=None):
    destId = numToId(randint(0, DHT_ID_MAX - 1))
    startNodes = nodeTable.getLiveNodes()

    def onLookup(nodes):
        op.notify()

    lookupOp = dhtClient.lookup(destId, startNodes, onLookup)
    op = AsyncOp(callback, lookupOp.cancel)
    return op
Ejemplo n.º 31
0
def initNodeTable(nodeTable, dhtClient, reactor, callback=None):
    def onFindLive():
        print 'done finding live nodes'
        findNewOp = _findNewNodes(nodeTable, dhtClient, reactor, op.notify)
        op.setCanceler(findNewOp.cancel)

    print 'finding live nodes...'
    findLiveOp = _findLiveNodes(5, nodeTable, dhtClient, reactor, onFindLive)
    op = AsyncOp(callback, findLiveOp.cancel)
    return op
Ejemplo n.º 32
0
Archivo: upnp.py Proyecto: hj91/cspace
 def listAllMappings( device, reactor, callback=None ) :
     mappings = []
     def onResponse( mapping ) :
         if mapping is not None :
             mappings.append( mapping )
             return
         op.notify( mappings )
     listOp = UPnpActions.listMappings( device, reactor, onResponse )
     op = AsyncOp( callback, listOp.cancel )
     return op
Ejemplo n.º 33
0
    def _rejectIncoming(self, sslConn, callback=None):
        def onReject(sslConn):
            if sslConn is None:
                op.notify(False)
                return
            sslAbort(sslConn)
            op.notify(True)

        rejectOp = acceptIncoming(False, sslConn, self.reactor, onReject)
        op = AsyncOp(callback, rejectOp.cancel)
        return op
Ejemplo n.º 34
0
Archivo: upnp.py Proyecto: hj91/cspace
 def delMapping( device, externalPort, protocol, reactor, callback=None ) :
     assert protocol in ('TCP','UDP')
     params = {
         'NewRemoteHost' : '',
         'NewExternalPort' : externalPort,
         'NewProtocol' : protocol }
     def onResponse( result, data ) :
         op.notify( result == 0 )
     actionOp = device.callAction( 'DeletePortMapping', params, reactor, onResponse )
     op = AsyncOp( callback, actionOp.cancel )
     return op
Ejemplo n.º 35
0
Archivo: upnp.py Proyecto: hj91/cspace
 def getExternalIP( device, reactor, callback=None ) :
     def onResponse( result, data ) :
         if result < 0 :
             op.notify( None )
             return
         externalIP = dict(data).get('NewExternalIPAddress',None)
         op.notify( externalIP )
     actionOp = device.callAction( 'GetExternalIPAddress', {},
             reactor, onResponse )
     op = AsyncOp( callback, actionOp.cancel )
     return op
Ejemplo n.º 36
0
 def __init__(self, fileClient, remotePath, localPath, callback=None):
     self.fileClient = fileClient
     self.remotePath = remotePath
     self.localPath = localPath
     self.out = file(localPath, "w+b")
     self.sizeOp = self.fileClient.callGetSize(remotePath, self._onGetSize)
     self.fileSize = -1
     self.op = AsyncOp(callback, self._doCancel)
     self.blockSize = 16384
     self.requestedSize = 0
     self.receivedSize = 0
     self.fetchOps = {}
Ejemplo n.º 37
0
def _directConnect( sslContext, remotePublicKey, directLocation,
        reactor, callback=None ) :
    def onConnect( connector ) :
        if connector.getError() != 0 :
            op.notify( None )
            return
        authOp = _authenticateUser( connector.getSock(), sslContext,
                remotePublicKey, reactor, op.notify )
        op.setCanceler( authOp.cancel )
    connectOp = tcpConnect( directLocation.addr, reactor, onConnect )
    op = AsyncOp( callback, connectOp.cancel )
    return op
Ejemplo n.º 38
0
 def add(self, cname, keyid):
     # Lookup the contact info and call _doAddContact
     if self.status != self.ONLINE:
         return self._error("Can't lookup buddy while not online.")
     httpOp = HttpRequest(self.reactor).get(
         # 'http://cspace.in/pubkey/%s' % keyid,
         "http://identity.datahaven.net/cspacekeys/%s" % keyid,
         self._onLookupResponse,
     )
     self._addOp = AsyncOp(self._onAddContact, httpOp.cancel)
     self._addOp.cname = cname
     return True
Ejemplo n.º 39
0
def cspaceConnect(cspaceAddr, remoteUser, remoteService, reactor, callback):
    def onTCPConnect(connector):
        if connector.getError() != 0:
            op.notify(-1, None)
            return
        connectOp = CSpaceConnector(connector.getSock(), remoteUser,
                                    remoteService, reactor, op.notify).getOp()
        op.setCanceler(connectOp.cancel)

    tcpOp = tcpConnect(cspaceAddr, reactor, onTCPConnect)
    op = AsyncOp(callback, tcpOp.cancel)
    return op
Ejemplo n.º 40
0
 def __init__(self, clientObj, destId, startNodes, callback=None):
     assert startNodes
     self.clientObj = clientObj
     self.destId = destId
     self.destNumId = idToNum(destId)
     self.seen = {}
     self.closest = []
     self.pending = []
     self.calling = {}
     for nodeAddr in startNodes:
         self._newNode(nodeAddr)
     self._callPending()
     self.op = AsyncOp(callback, self._doCancel)
Ejemplo n.º 41
0
 def __init__( self, sslConn, initiateCode, reactor, callback=None ) :
     self.sslConn = sslConn
     self.reactor = reactor
     if initiateCode == self.ACCEPT :
         self.sslFunc = self.sslConn.accept
     else :
         assert initiateCode == self.CONNECT 
         self.sslFunc = self.sslConn.connect
     self.sock = self.sslConn.sock
     self.sock.setblocking( 0 )
     timerOp = self.reactor.callLater( 0, self._doAction )
     self.op = AsyncOp( callback, timerOp.cancel )
     self.want = self.WANT_NONE
Ejemplo n.º 42
0
class SSLInitiator( object ) :
    ACCEPT = 0
    CONNECT = 1

    WANT_NONE = 0
    WANT_READ = 1
    WANT_WRITE = 2

    def __init__( self, sslConn, initiateCode, reactor, callback=None ) :
        self.sslConn = sslConn
        self.reactor = reactor
        if initiateCode == self.ACCEPT :
            self.sslFunc = self.sslConn.accept
        else :
            assert initiateCode == self.CONNECT 
            self.sslFunc = self.sslConn.connect
        self.sock = self.sslConn.sock
        self.sock.setblocking( 0 )
        timerOp = self.reactor.callLater( 0, self._doAction )
        self.op = AsyncOp( callback, timerOp.cancel )
        self.want = self.WANT_NONE

    def getOp( self ) : return self.op

    def _removeRead( self ) :
        self.reactor.removeReadCallback( self.sock.fileno() )
        self.want = self.WANT_NONE

    def _removeWrite( self ) :
        self.reactor.removeWriteCallback( self.sock.fileno() )
        self.want = self.WANT_NONE

    def _doAction( self ) :
        try :
            self.sslFunc()
        except SSLWantReadError :
            if self.want != self.WANT_READ :
                if self.want == self.WANT_WRITE : self._removeWrite()
                self.reactor.addReadCallback( self.sock.fileno(), self._doAction )
                self.want = self.WANT_READ
                self.op.setCanceler( self._removeRead )
            return
        except SSLWantWriteError :
            if self.want != self.WANT_WRITE :
                if self.want == self.WANT_READ : self._removeRead()
                self.reactor.addWriteCallback( self.sock.fileno(), self._doAction )
                self.want = self.WANT_WRITE
                self.op.setCanceler( self._removeWrite )
            return
        except SSLError, e :
            if self.want == self.WANT_READ : self._removeRead()
            elif self.want == self.WANT_WRITE : self._removeWrite()
            self.op.notify( e )
            return
        except:
Ejemplo n.º 43
0
 def __init__( self, requestId, callback=None, canceler=None ) :
     AsyncOp.__init__( self, callback, canceler )
     self.requestId = requestId
Ejemplo n.º 44
0
class CurlPerformer( object ) :
    def __init__( self, curlHandle, reactor, callback=None ) :
        self.reactor = reactor
        self.cm = pycurl.CurlMulti()
        self.c = curlHandle
        self.cm.add_handle( self.c )
        self.fdsets = ( [], [], [] )
        self.timerOp = self.reactor.callLater( 0, self._onInitialTimer )
        self.op = AsyncOp( callback, self._doCancel )

    def getOp( self ) : return self.op

    def _onInitialTimer( self ) :
        self.timerOp = self.reactor.addTimer( 1, self._onProcess )
        self._onProcess()

    def _addEvents( self ) :
        self.fdsets = self.cm.fdset()
        r = self.reactor
        for fd in self.fdsets[0] :
            r.addReadCallback( fd, self._onProcess )
        for fd in self.fdsets[1] :
            r.addWriteCallback( fd, self._onProcess )
        for fd in self.fdsets[2] :
            r.addExceptionCallback( fd, self._onProcess )

    def _removeEvents( self ) :
        r = self.reactor
        for fd in self.fdsets[0] :
            r.removeReadCallback( fd )
        for fd in self.fdsets[1] :
            r.removeWriteCallback( fd )
        for fd in self.fdsets[2] :
            r.removeExceptionCallback( fd )

    def _doCancel( self ) :
        self.timerOp.cancel()
        self.timerOp = None
        self._removeEvents()
        self.cm.remove_handle( self.c )
        self.cm.close()

    def _doNotify( self, errCode ) :
        self.timerOp.cancel()
        self.timerOp = None
        self.cm.remove_handle( self.c )
        self.cm.close()
        self.op.notify( errCode )

    def _onProcess( self ) :
        self._removeEvents()
        while 1 :
            ret,numHandles = self.cm.perform()
            if ret != pycurl.E_CALL_MULTI_PERFORM :
                break
        numQ, okList, errList = self.cm.info_read()
        assert numQ == 0
        assert len(okList)+len(errList) <= 1
        if len(okList) > 0 :
            self._doNotify( 0 )
        elif len(errList) > 0 :
            c,err,errMsg = errList[0]
            self._doNotify( err )
        else :
            self._addEvents()
Ejemplo n.º 45
0
class SSLCloser( object ) :
    WANT_NONE = 0
    WANT_READ = 1
    WANT_WRITE = 2
    def __init__( self, sslConn, reactor, callback=None, timeout=30 ) :
        self.sslConn = sslConn
        self.reactor = reactor
        self.timeout = timeout
        self.sock = sslConn.sock
        self.want = self.WANT_NONE
        self.timerOp = self.reactor.callLater( 0, self._onAction )
        self.timeoutOp = self.reactor.callLater( self.timeout, self._onTimeout )
        self.op = AsyncOp( callback, self._close )

    def getOp( self ) : return self.op

    def _close( self ) :
        if self.timerOp : self.timerOp.cancel()
        if self.timeoutOp : self.timeoutOp.cancel()
        if self.want == self.WANT_READ : self._removeRead()
        elif self.want == self.WANT_WRITE : self._removeWrite()
        self.sock.close()

    def _closeNotify( self ) :
        self._close()
        self.op.notify()

    def _removeRead( self ) :
        assert self.want == self.WANT_READ
        self.reactor.removeReadCallback( self.sock.fileno() )
        self.want = self.WANT_NONE

    def _removeWrite( self ) :
        assert self.want == self.WANT_WRITE
        self.reactor.removeWriteCallback( self.sock.fileno() )
        self.want = self.WANT_NONE

    def _onAction( self ) :
        self.timerOp = None
        self._doAction()

    def _doAction( self ) :
        try :
            result = self.sslConn.shutdown()
            if result == 0 :
                result = self.sslConn.shutdown()
        except SSLWantReadError :
            if self.want != self.WANT_READ :
                if self.want == self.WANT_WRITE : self._removeWrite()
                self.reactor.addReadCallback( self.sock.fileno(), self._doAction )
                self.want = self.WANT_READ
            return
        except SSLWantWriteError :
            if self.want != self.WANT_WRITE :
                if self.want == self.WANT_READ : self._removeRead()
                self.reactor.addWriteCallback( self.sock.fileno(), self._doAction )
                self.want = self.WANT_WRITE
            return
        except SSLError, e :
            self._closeNotify()
            return
        self._closeNotify()
Ejemplo n.º 46
0
class CSpaceService:
    OFFLINE = UserSession.OFFLINE
    CONNECTING = UserSession.CONNECTING
    ONLINE = UserSession.ONLINE
    DISCONNECTING = UserSession.DISCONNECTING
    UNKNOWN = -1

    STATII = {
        OFFLINE: "Offline",
        CONNECTING: "Connecting",
        ONLINE: "Online",
        DISCONNECTING: "Disconnecting",
        UNKNOWN: "Unknown",
    }

    ##########
    ## Service initialization
    ##
    def __init__(self, seedNodes, settings=None, reactor=None):
        global logger
        logger.info("CSpaceService init")
        if reactor is None:
            reactor = SelectReactor()

        if settings is None:
            settings = localSettings()

        self.reactor = reactor
        self.settings = settings
        self.dispatcher = Eventer()
        self.seedNodes = seedNodes

        # Session Manager
        self.session = UserSession(self.seedNodes, reactor)

        # Our user profile
        self.profile = None

        # Session status State Machine
        self.sm = self.session.sm
        # Make sure we handle the edges/state transitions
        self.sm.insertCallback(self._onStateChange)
        # Manage actions
        self.actionManager = ActionManager()
        # Loads applets in subprocesses
        self.appletServer = AppletServer(self.session, self.actionManager, self.reactor)

        # Our contacts' statii
        self.statusProbe = ContactStatusChecker(self, reactor)

        # Our current status
        self.status = self.sm.current()
        self.statusmsg = self.STATII[self.status]
        self.exitAfterOffline = False

        self.reactor.callLater(0, self._onStarted)

    def _onStarted(self):
        self.dispatcher.trigger("service.start")

    def _error(self, msg):
        logger.error(msg)
        self.dispatcher.trigger("error", msg)
        return (False, msg)

    def run(self):
        self.reactor.run()
        try:
            self.appletServer.bridgeThread.reactor.stop()
        except AttributeError:
            pass

    def svcstatus(self):
        return self.statusmsg

    def stop(self):
        # offline first
        if self.status != self.OFFLINE:
            self.exitAfterOffline = True
            return self.offline()

        for reactor in (self.appletServer.bridgeThread.reactor, self.reactor):
            reactor.stop()

        self.dispatcher.trigger("service.stop")
        return True

    ##########
    ## Go online and offline, change profiles
    ##
    def switch(self, profile, password):
        if self.status is not self.OFFLINE:
            return self._error("Not currently offline.")

        st = self.settings
        logger.debug("Changing profile...")
        profiles = [userName for userName, keyId, entry in listProfiles()]
        if not st.getInt("Settings/RememberKey", 0):
            return self._error("No key found.")

        if not profile in entries:
            return self._error("No profile %s found.")

        profile = loadProfile(profile, password)
        if not profile:
            return self._error("Profile couldn't be loaded.")

        st.setString("Settings/SavedProfile", profile.name)
        st.setString("Settings/SavedPassword", password)
        saveLocalSettings()

        self.dispatcher.trigger("profile.switch", profile)
        return True

    def online(self):
        global logger
        if self.status is not self.OFFLINE:
            return self._error("Not currently offline.")

        st = self.settings
        logger.debug("Going online...")
        entries = [entry for userName, keyId, entry in listProfiles()]
        if not st.getInt("Settings/RememberKey", 0):
            return self._error("No key found.")

        entry = st.getString("Settings/SavedProfile")
        password = st.getString("Settings/SavedPassword")
        if not (entry and password and (entry in entries)):
            return self._error("No profile or password.")

        profile = loadProfile(entry, password)
        if not profile:
            return self._error("Profile couldn't be loaded.")

        self.profile = profile
        logger.debug("Going online as %s keyID=%s ..." % (profile.name, profile.keyId))
        self.session.goOnline(self.profile)
        self.reconnector = Reconnector(self.profile, self._onReconnectTimer, self.reactor)

        return True

    def _onReconnectTimer(self):
        assert self.reconnector
        if self.reconnector.timeLeft > 0:
            return
        self.profile = self.reconnector.profile
        self.reconnector.shutdown()
        if self.session.sm.current() == 0:
            self.session.goOnline(self.profile)
            self.reconnector = Reconnector(self.profile, self._onReconnectTimer, self.reactor)
            self.dispatcher.trigger("profile.reconnecting", self.profile)

    def offline(self):
        if self.status is not self.ONLINE:
            return self._error("Not currently online.")
        self.session.goOffline()
        self.profile = None
        self.reconnector.shutdown()
        self.reconnector = None
        return True

    def _onStateChange(self):
        """ Respond to connecting/online/disconnecting/offline notices """

        self.status = self.sm.current()
        self.statusmsg = None

        # No longer online
        if self.sm.previous() == self.ONLINE:
            # Stop checking contact statii
            self.statusProbe.stopProbing()
            # Clean up any open applets
            self.appletServer.clearConnections()

        # Now offline
        if self.sm.current() == self.OFFLINE:
            profile = self.profile
            self.profile = None
            if self.reconnector:
                if self.sm.previous() == self.CONNECTING:
                    msg = "Connect failed."
                else:
                    msg = "Disconnected."
                self.reconnector.startReconnectTimer(msg)
                self.statusmsg = msg
            self.dispatcher.trigger("profile.offline", profile)
            if self.exitAfterOffline:
                self.stop()

        # Now online
        elif self.sm.current() == self.ONLINE:
            # Restart checking contact statii
            self.dispatcher.trigger("profile.online", self.profile)
            self.statusProbe.startProbing()

        # Now connecting
        elif self.sm.current() == self.CONNECTING:
            self.dispatcher.trigger("profile.connecting", self.profile)
        elif self.sm.current() == self.DISCONNECTING:
            self.dispatcher.trigger("profile.disconnecting", self.profile)

        if not self.statusmsg:
            self.statusmsg = self.STATII[self.status]

        logger.info("STATUS: " + self.statusmsg)

    ##########
    ## List, add and remove contacts
    ##
    def list(self):
        if self.status != self.ONLINE:
            return self._error("Not connected.")

        contactsByName = self.profile.contactNames
        statii = []
        STATII = CSpaceService.STATII
        for key in contactsByName:
            contact = contactsByName[key]
            if hasattr(contact, "status"):
                buddystatus = (key, contact.status, STATII[contact.status])
            else:
                buddystatus = (key, -1, STATII[-1])
            statii.append(buddystatus)

        statii.sort()
        return statii

    def add(self, cname, keyid):
        # Lookup the contact info and call _doAddContact
        if self.status != self.ONLINE:
            return self._error("Can't lookup buddy while not online.")
        httpOp = HttpRequest(self.reactor).get(
            # 'http://cspace.in/pubkey/%s' % keyid,
            "http://identity.datahaven.net/cspacekeys/%s" % keyid,
            self._onLookupResponse,
        )
        self._addOp = AsyncOp(self._onAddContact, httpOp.cancel)
        self._addOp.cname = cname
        return True

    def addKey(self, cname, key):
        if cname and not isValidUserName(cname):
            return self._error("Bad username.")

        k = RSAKey()
        try:
            k.fromPEM_PublicKey(pemPublicKey)
        except RSAError:
            return self._error("Bad PEM-encoded key.")

        contact = Contact(k, cname)
        self._onAddContact(contact)

    def _onLookupResponse(self, responseCode, data):
        if responseCode != 200:
            self._addOp.notify(None)
            return
        inp = StringIO.StringIO(data)
        name = inp.readline().strip()
        pemPublicKey = inp.read()
        if name and not isValidUserName(name):
            self._addOp.notify(None)
            return

        k = RSAKey()
        try:
            k.fromPEM_PublicKey(pemPublicKey)
        except RSAError:
            self._addOp.notify(None)

        contact = Contact(k, self._addOp.cname)
        self._addOp.notify(contact)

    def _onAddContact(self, contact):
        del self._addOp
        if contact == None:
            # Contact lookup failed.
            return

        self.profile.addContact(contact)
        saveProfileContacts(self.profile)
        self.dispatcher.trigger("contact.add", contact)

    def remove(self, cname=None):
        if self.status != self.ONLINE:
            return self._error("Can't modify contact list while not online.")
        # Lookup the contact in profile and remove it
        contact = self.profile.getContactByName(cname)
        if contact is None:
            return self._error("No such contact.")
        self.profile.removeContact(contact)
        saveProfileContacts(self.profile)
        self.dispatcher.trigger("contact.remove", contact)
        return True

    #########
    ## Perform contact action
    ##
    def action(self, buddy, action):
        if self.status != self.ONLINE:
            return False

        actionManager = self.actionManager
        if buddy not in self.profile.contactNames:
            return self._error("Bad buddy name: %s" % buddy)

        for actionItem in actionManager.actions:
            if actionItem[4] == action:
                logger.info("Running action %s on %s" % (action, buddy))
                retVal = actionManager.execAction(action, buddy)
                self.dispatcher.trigger("contact.action", self.profile.contactNames[buddy], action, retVal)
                return retVal
            else:
                logger.info("Not action %s" % actionItem[4])

        return self._error("Bad action name: %s" % action)

    def probe(self, buddy):
        if self.status != self.ONLINE:
            return self._error("Not online.")

        if buddy not in self.profile.contactNames:
            return self._error("Bad buddy name: %s" % buddy)

        self.statusProbe.probeContactStatus(buddy)
        return True

    def contactinfo(self, buddy):
        if self.status != self.ONLINE:
            return self._error("Not online.")

        if buddy not in self.profile.contactNames:
            return self._error("Bad buddy name: %s" % buddy)

        contact = self.profile.contactNames[buddy]
        contactKey = hexEncode(contact.publicKeyData)
        if hasattr(contact, "status"):
            contactStatus = contact.status
        else:
            contactStatus = -1
        return [contact.name, contactKey, self.STATII[contactStatus]]
Ejemplo n.º 47
0
 def __init__( self, opId, callback=None, canceler=None ) :
     AsyncOp.__init__( self, callback, canceler )
     self.opId = opId
Ejemplo n.º 48
0
 def __init__( self, sock, pendingWrite, reactor, callback=None ) :
     TCPWriter.__init__( self, sock, pendingWrite, reactor )
     self.op = AsyncOp( callback, self.shutdown )
Ejemplo n.º 49
0
class IMInitializer( object ) :
    CONNECTING = 0
    GETTINGKEY = 1
    NOTIFYING = 2
    REGISTERING = 3
    REGISTERED = 4
    CLOSED = 5
    def __init__( self, reactor, callback=None ) :
        assert env.isContactAction or env.isIncoming
        self.reactor = reactor
        self.op = AsyncOp( callback, self._doCancel )
        self.state = self.CONNECTING
        self.connectOp = tcpConnect( ('127.0.0.1',env.port), self.reactor, self._onConnect )
        self.stream = None

    def getOp( self ) : return self.op

    def _doCancel( self ) :
        if self.connectOp : self.connectOp.cancel()
        if self.stream : self.stream.close( deferred=True )
        self.state = self.CLOSED

    def _onConnect( self, connector ) :
        self.connectOp = None
        if connector.getError() != 0 :
            self.op.notify( -1, None )
            return
        self.stream = TCPLineStream( connector.getSock(), self.reactor )
        self.stream.setCloseCallback( self._onClose )
        self.stream.setErrorCallback( self._onError )
        self.stream.setInputCallback( self._onInput )
        self.stream.enableRead( True )
        if env.isContactAction :
            self.stream.writeData( 'GETPUBKEY %s\r\n' % env.contactName )
        else :
            self.stream.writeData( 'GETINCOMINGPUBKEY %s\r\n' % env.connectionId )
        self.state = self.GETTINGKEY

    def _onClose( self ) :
        self._doCancel()
        self.op.notify( -1, None )

    def _onError( self, err, errMsg ) :
        self._onClose()

    def _onInput( self, line ) :
        if self.state == self.GETTINGKEY :
            if not line.startswith('OK') :
                self._doCancel()
                self.op.notify( -1, None )
                return
            self.pubKey = line.split()[1]
            self.state = self.REGISTERING
            self.listenerName = 'CSpaceIM-%s' % self.pubKey
            self.stream.writeData( 'REGISTERLISTENER %s\r\n' % self.listenerName )
        elif self.state == self.REGISTERING :
            if not line.startswith('OK') :
                self.state = self.NOTIFYING
                if env.isContactAction :
                    msg = 'CONTACTACTION'
                else :
                    msg = 'INCOMING %s' % env.connectionId
                self.stream.writeData( 'SENDLISTENER %s %s\r\n' %
                        (self.listenerName,msg) )
                return
            self.state = self.REGISTERED
            self.stream.setCloseCallback( None )
            self.stream.setErrorCallback( None )
            self.stream.setInputCallback( None )
            self.op.notify( 1, self )
        elif self.state == self.NOTIFYING :
            if not line.startswith('OK') :
                self._doCancel()
                self.op.notify( -1, None )
                return
            self._doCancel()
            self.op.notify( 0, self )
        else :
            assert False
Ejemplo n.º 50
0
class FileFetcher(object):
    def __init__(self, fileClient, remotePath, localPath, callback=None):
        self.fileClient = fileClient
        self.remotePath = remotePath
        self.localPath = localPath
        self.out = file(localPath, "w+b")
        self.sizeOp = self.fileClient.callGetSize(remotePath, self._onGetSize)
        self.fileSize = -1
        self.op = AsyncOp(callback, self._doCancel)
        self.blockSize = 16384
        self.requestedSize = 0
        self.receivedSize = 0
        self.fetchOps = {}

    def getOp(self):
        return self.op

    def _doCancel(self):
        if self.sizeOp:
            self.sizeOp.cancel()
        for fop in self.fetchOps.keys():
            fop.cancel()
        self.out.close()

    def _notifyError(self):
        self._doCancel()
        self.op.notify(-1, self.fileSize)

    def _onGetSize(self, err, size):
        self.sizeOp = None
        if err != 0:
            self._notifyError()
            return
        self.fileSize = size
        self._fetchMore()

    def _fetchMore(self):
        while (self.requestedSize < self.fileSize) and (len(self.fetchOps) < 5):
            self._fetchBlock()
        if self.receivedSize == self.fileSize:
            assert len(self.fetchOps) == 0
            self.out.close()
            self.op.notify(self.receivedSize, self.fileSize)
            return
        self.op.notify(self.receivedSize, self.fileSize)

    def _fetchBlock(self):
        size = min(self.fileSize - self.requestedSize, self.blockSize)
        assert size > 0
        offset = self.requestedSize

        def onResponse(err, data):
            del self.fetchOps[rpcOp]
            if err != 0:
                self._notifyError()
                return
            if len(data) != size:
                self._notifyError()
                return
            try:
                self.out.write(data)
            except (IOError, OSError), e:
                self._notifyError()
                return
            self.receivedSize += size
            self._fetchMore()

        rpcOp = self.fileClient.callRead(self.remotePath, offset, size, onResponse)
        self.requestedSize += size
        self.fetchOps[rpcOp] = 1