コード例 #1
0
class IMConnection(object):
    INITIAL = 0
    CONNECTING = 1
    ACCEPTING = 2
    CONNECTED = 3
    CLOSED = 4

    def __init__(self, reactor):
        self.reactor = reactor
        self.closeCallback = None
        self.inputCallback = None
        self.state = self.INITIAL
        self.connectOp = None
        self.stream = None

    def setCloseCallback(self, closeCallback):
        self.closeCallback = closeCallback

    def setInputCallback(self, inputCallback):
        self.inputCallback = inputCallback

    def shutdown(self, notify=False):
        if self.state == self.CLOSED: return
        if self.connectOp: self.connectOp.cancel()
        if self.stream: self.stream.close(deferred=True)
        self.state = self.CLOSED
        if notify and self.closeCallback: self.closeCallback()

    def connectTo(self, peerPubKey, callback=None):
        assert self.state == self.INITIAL
        self.connectCallback = callback
        self.state = self.CONNECTING
        self.peerPubKey = peerPubKey
        self.connectOp = tcpConnect(('127.0.0.1', env.port), self.reactor,
                                    self._onConnect)

    def acceptConnection(self, connectionId, callback=None):
        assert self.state == self.INITIAL
        self.connectCallback = callback
        self.state = self.ACCEPTING
        self.connectionId = connectionId
        self.connectOp = tcpConnect(('127.0.0.1', env.port), self.reactor,
                                    self._onConnect)

    def writeLine(self, line):
        self.stream.writeData(line + '\r\n')

    def _onConnect(self, connector):
        self.connectOp = None
        if connector.getError() != 0:
            self.shutdown(notity=True)
            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 self.state == self.CONNECTING:
            self.stream.writeData('CONNECTPUBKEY %s TextChat\r\n' %
                                  self.peerPubKey)
        else:
            assert self.state == self.ACCEPTING
            self.stream.writeData('ACCEPT %s\r\n' % self.connectionId)

    def _onClose(self):
        self.shutdown(notify=True)

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

    def _onInput(self, line):
        if self.state in (self.CONNECTING, self.ACCEPTING):
            if not line.startswith('OK'):
                self.shutdown(notify=True)
                return
            self.state = self.CONNECTED
            if self.connectCallback: self.connectCallback()
            return
        elif self.state == self.CONNECTED:
            self.inputCallback(line)
        else:
            self.shutdown(notify=True)
コード例 #2
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
コード例 #3
0
ファイル: cspace_testapplet.py プロジェクト: AchillesA/cspace
class MainWindow( QVBox ) :
    CONNECTING = 0
    CONNECTED = 1
    CLOSED = 2
    def __init__( self, parent, reactor ) :
        QVBox.__init__( self, parent )
        self.reactor = reactor
        self.setCaption( 'CSpace Test Applet' )
        self.chatOutputView = QTextEdit( self )
        self.chatOutputView.setReadOnly( True )
        self.chatInputEdit = QLineEdit( self )
        self.chatInputEdit.setFocus()
        self.state = self.CONNECTING
        self.chatInputEdit.setEnabled( False )
        self.isClient = (cspaceEvent == 'CONTACTACTION')
        self.chatOutputView.append( self.isClient and
            'Connecting to %s...' % cspaceContactNickName or
            'Accepting connection from %s' % cspacePeerNickName )
        addr = ('127.0.0.1',int(cspacePort))
        self.tcpConnectOp = tcpConnect( addr, self.reactor, self._onTCPConnect )
        self.stream = None

    def _onTCPConnect( self, connector ) :
        self.tcpConnectOp = None
        if connector.getError() != 0 :
            self.chatOutputView.append( 'ERROR' )
            return
        self.sock = connector.getSock()
        self.stream = TCPLineStream( self.sock, self.reactor )
        self.stream.setCloseCallback( self._onClose )
        self.stream.setErrorCallback( self._onError )
        self.stream.setInputCallback( self._onInput )
        self.stream.enableRead( True )
        if self.isClient :
            self.stream.writeData( 'CONNECT %s test\r\n' % cspaceContactNickName )
        else :
            self.stream.writeData( 'ACCEPT %s\r\n' % cspaceConnectionId )

    def shutdown( self ) :
        if self.tcpConnectOp : self.tcpConnectOp.cancel()
        if self.stream : self.stream.close()
        self.state = self.CLOSED

    def _onClose( self ) :
        self.chatOutputView.append( 'Connection closed' )
        self.shutdown()

    def _onError( self, err, errMsg ) :
        self.chatOutputView.append( 'Connection error(%d): %s' % (err,errMsg) )
        self.shutdown()

    def _onInput( self, line ) :
        if self.state == self.CONNECTING :
            if line.startswith('ERROR') :
                self.chatOutputView.append( 'Connection failed' )
                return
            if line.startswith('OK') :
                self.chatOutputView.append( 'Connected' )
                self.state = self.CONNECTED
                self.chatInputEdit.setEnabled( True )
                self.chatInputEdit.setFocus()
                self.connect( self.chatInputEdit, SIGNAL('returnPressed()'), self._onChatInputReturnPressed )
        elif self.state == self.CONNECTED :
            line = line.strip()
            self.chatOutputView.append( line )

    def _onChatInputReturnPressed( self ) :
        if self.state != self.CONNECTED : return
        s = str(self.chatInputEdit.text()).strip()
        if not s : return
        self.chatOutputView.append( s )
        self.stream.writeData( s + '\r\n' )
        self.chatInputEdit.clear()
コード例 #4
0
ファイル: IM.py プロジェクト: AchillesA/cspace
class IMConnection( object ) :
    INITIAL = 0
    CONNECTING = 1
    ACCEPTING = 2
    CONNECTED = 3
    CLOSED = 4
    def __init__( self, reactor ) :
        self.reactor = reactor
        self.closeCallback = None
        self.inputCallback = None
        self.state = self.INITIAL
        self.connectOp = None
        self.stream = None

    def setCloseCallback( self, closeCallback ) :
        self.closeCallback = closeCallback

    def setInputCallback( self, inputCallback ) :
        self.inputCallback = inputCallback

    def shutdown( self, notify=False ) :
        if self.state == self.CLOSED : return
        if self.connectOp : self.connectOp.cancel()
        if self.stream : self.stream.close( deferred=True )
        self.state = self.CLOSED
        if notify and self.closeCallback : self.closeCallback()

    def connectTo( self, peerPubKey, callback=None ) :
        assert self.state == self.INITIAL
        self.connectCallback = callback
        self.state = self.CONNECTING
        self.peerPubKey = peerPubKey
        self.connectOp = tcpConnect( ('127.0.0.1',env.port), self.reactor, self._onConnect )

    def acceptConnection( self, connectionId, callback=None ) :
        assert self.state == self.INITIAL
        self.connectCallback = callback
        self.state = self.ACCEPTING
        self.connectionId = connectionId
        self.connectOp = tcpConnect( ('127.0.0.1',env.port), self.reactor, self._onConnect )

    def writeLine( self, line ) :
        self.stream.writeData( line + '\r\n' )

    def _onConnect( self, connector ) :
        self.connectOp = None
        if connector.getError() != 0 :
            self.shutdown( notity=True )
            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 self.state == self.CONNECTING :
            self.stream.writeData( 'CONNECTPUBKEY %s TextChat\r\n' % self.peerPubKey )
        else :
           assert self.state == self.ACCEPTING
           self.stream.writeData( 'ACCEPT %s\r\n' % self.connectionId )

    def _onClose( self ) :
        self.shutdown( notify=True )

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

    def _onInput( self, line ) :
        if self.state in (self.CONNECTING,self.ACCEPTING) :
            if not line.startswith('OK') :
                self.shutdown( notify=True )
                return
            self.state = self.CONNECTED
            if self.connectCallback : self.connectCallback()
            return
        elif self.state == self.CONNECTED :
            self.inputCallback( line )
        else :
            self.shutdown( notify=True )
コード例 #5
0
ファイル: IM.py プロジェクト: AchillesA/cspace
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
コード例 #6
0
ファイル: appletserver.py プロジェクト: vesellov/datahaven
class AppletConnection( object ) :
    DEFAULT = 0
    CONNECTING = 1
    WAITING_BRIDGE = 2
    LISTENER = 3
    CLOSED = 4
    def __init__( self, sock, reactor, appletServer ) :
        self.reactor = reactor
        self.stream = TCPLineStream( sock, reactor )
        self.appletServer = appletServer
        self.appletServer.appletConnections[self] = 1
        self.session = appletServer.session
        self.incoming = appletServer.incoming
        self.state = self.DEFAULT
        self._writeData = self.stream.writeData
        rt = {}
        self.requestTable = rt
        rt['echo'] = self._doEcho
        rt['getcontacts'] = self._doGetContacts
        rt['getpubkey'] = self._doGetPubKey
        rt['getcontactpubkeys'] = self._doGetContactPubKeys
        rt['connect'] = self._doConnect
        rt['connectpubkey'] = self._doConnectPubKey
        rt['accept'] = self._doAccept
        rt['getincomingpubkey'] = self._doGetIncomingPubKey
        rt['registerlistener'] = self._doRegisterListener
        rt['sendlistener'] = self._doSendListener
        self.stream.setInputCallback( self._onInput )
        self.stream.setCloseCallback( self._onClose )
        self.stream.setErrorCallback( self._onError )
        self.stream.enableRead( True )

    def _setClosed( self ) :
        del self.appletServer.appletConnections[self]
        self.state = self.CLOSED

    def shutdown( self, deferred=False ) :
        if self.state == self.CONNECTING :
            self.connectOp.cancel()
        elif self.state == self.LISTENER :
            self.appletServer.unregisterListener( self.listenerName )
        elif self.state == self.WAITING_BRIDGE :
            sslAbort( self.peerSSLConn )
        self.stream.close( deferred )
        self._setClosed()

    def _onClose( self ) :
        self.shutdown()

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

    def _writeLine( self, line ) :
        self._writeData( line + '\r\n' )

    def _writeWords( self, words ) :
        words = [wordEncode(w) for w in words]
        self._writeData( ' '.join(words) + '\r\n' )

    def _writeError( self, msg ) :
        self._writeLine( 'ERROR %s' % msg )

    def _writeResult( self, words ) :
        self._writeWords( ['OK'] + words )

    def dispatchMessage( self, msg ) :
        assert self.state == self.LISTENER
        self._writeWords( ['MSG'] + msg )

    def _doEcho( self, words ) :
        self._writeResult( words )

    def _doGetContacts( self, words ) :
        if len(words) != 0 :
            self._writeError( 'Malformed request' )
            return
        if not self.session.isOnline() :
            self._writeError( 'Not online' )
            return
        names = self.session.getProfile().getContactNames()
        self._writeResult( names )

    def _doGetPubKey( self, words ) :
        if len(words) > 1 :
            self._writeError( 'Malformed request' )
            return
        if not self.session.isOnline() :
            self._writeError( 'Not online' )
            return
        if len(words) == 0 :
            keyData = self.session.getProfile().rsaKey.toDER_PublicKey()
            self._writeResult( [hexEncode(keyData)] )
            return
        contact = self.session.getProfile().getContactByName( words[0] )
        if contact is None :
            self._writeError( 'Unknown contact' )
            return
        self._writeResult( [hexEncode(contact.publicKeyData)] )

    def _doGetContactPubKeys( self, words ) :
        if len(words) != 0 :
            self._writeError( 'Malformed request' )
            return
        if not self.session.isOnline() :
            self._writeError( 'Not online' )
            return
        out = []
        profile = self.session.getProfile()
        for name in profile.getContactNames() :
            c = profile.getContactByName( name )
            out.extend( [c.name,hexEncode(c.publicKeyData)] )
        self._writeResult( out )

    def _connectInternal( self, publicKey, service ) :
        def onWriteComplete() :
            self.stream.shutdown()
            sock = self.stream.getSock()
            self.appletServer.bridgeThread.threadQueue.postMessage(
                    ('bridge',sock,self.peerSSLConn) )
            self._setClosed()
        def onConnect( err, sslConn ) :
            if err < 0 :
                self._writeError( 'Connect failed' )
                self.state = self.DEFAULT
                return
            self._writeResult( ['Connected'] )
            self.peerSSLConn = sslConn
            self.state = self.WAITING_BRIDGE
            self.stream.enableRead( False )
            self.stream.setWriteCompleteCallback( onWriteComplete )
        self.connectOp = self.session.connectTo( publicKey, service,
                onConnect )
        self.state = self.CONNECTING

    def _doConnect( self, words ) :
        if len(words) != 2 :
            self._writeError( 'Malformed request' )
            return
        contactName, service = words
        if not self.session.isOnline() :
            self._writeError( 'Not online' )
            return
        contact = self.session.getProfile().getContactByName( contactName )
        if not contact :
            self._writeError( 'Unknown contact' )
            return
        self._connectInternal( contact.publicKey, service )

    def _doConnectPubKey( self, words ) :
        if len(words) != 2 :
            self._writeError( 'Malformed request' )
            return
        hexPubKey, service = words
        if not self.session.isOnline() :
            self._writeError( 'Not online' )
            return
        try :
            pubKeyData = hexDecode( hexPubKey )
            pubKey = RSAKey()
            pubKey.fromDER_PublicKey( pubKeyData )
        except (HexDecodeError,RSAError) :
            self._writeError( 'Malformed publickey' )
            return
        self._connectInternal( pubKey, service )

    def _doAccept( self, words ) :
        if len(words) != 1 :
            self._writeError( 'Malformed request' )
            return
        connectionId = words[0]
        sslConn = self.incoming.acceptIncoming( connectionId )
        if not sslConn :
            self._writeError( 'Invalid connection' )
            return
        self._writeResult( ['Connected'] )
        self.peerSSLConn = sslConn
        self.state = self.WAITING_BRIDGE
        self.stream.enableRead( False )
        def onWriteComplete() :
            self.stream.shutdown()
            sock = self.stream.getSock()
            self.appletServer.bridgeThread.threadQueue.postMessage(
                    ('bridge',sock,self.peerSSLConn) )
            self._setClosed()
        self.stream.setWriteCompleteCallback( onWriteComplete )

    def _doGetIncomingPubKey( self, words ) :
        if len(words) != 1 :
            self._writeError( 'Malformed request' )
            return
        connectionId = words[0]
        peerKey = self.incoming.getPeerKey( connectionId )
        if not peerKey :
            self._writeError( 'Invalid connection' )
            return
        self._writeResult( [hexEncode(peerKey.toDER_PublicKey())] )

    def _doRegisterListener( self, words ) :
        if len(words) != 1 :
            self._writeError( 'Malformed request' )
            return
        listenerName = words[0]
        result = self.appletServer.registerListener( listenerName, self )
        if not result :
            self._writeError( 'Listener already registered' )
            return
        self.listenerName = listenerName
        self.state = self.LISTENER
        self._writeResult( ['Registered'] )

    def _doSendListener( self, words ) :
        if len(words) <= 1 :
            self._writeError( 'Malformed request' )
            return
        listenerName = words[0]
        listener = self.appletServer.getListener( listenerName )
        if listener is None :
            self._writeError( 'No such listener' )
            return
        listener.dispatchMessage( words[1:] )
        self._writeResult( ['Sent'] )

    def _onInput( self, line ) :
        assert self.state in (self.DEFAULT,self.CONNECTING,self.LISTENER)
        if self.state in (self.CONNECTING,self.LISTENER) :
            self._writeError( 'Junk received' )
            self.shutdown( deferred=True )
            return
        words = line.strip().split()
        if len(words) == 0 : return
        try :
            words = [wordDecode(w) for w in words]
        except WordDecodeError :
            self._writeError( 'Malformed request' )
            return
        cmd = words[0].lower()
        handler = self.requestTable.get( cmd, None )
        if not handler :
            self._writeError( 'Unknown request' )
            return
        handler( words[1:] )
コード例 #7
0
class MainWindow(QVBox):
    CONNECTING = 0
    CONNECTED = 1
    CLOSED = 2

    def __init__(self, parent, reactor):
        QVBox.__init__(self, parent)
        self.reactor = reactor
        self.setCaption('CSpace Test Applet')
        self.chatOutputView = QTextEdit(self)
        self.chatOutputView.setReadOnly(True)
        self.chatInputEdit = QLineEdit(self)
        self.chatInputEdit.setFocus()
        self.state = self.CONNECTING
        self.chatInputEdit.setEnabled(False)
        self.isClient = (cspaceEvent == 'CONTACTACTION')
        self.chatOutputView.append(
            self.isClient and 'Connecting to %s...' % cspaceContactNickName
            or 'Accepting connection from %s' % cspacePeerNickName)
        addr = ('127.0.0.1', int(cspacePort))
        self.tcpConnectOp = tcpConnect(addr, self.reactor, self._onTCPConnect)
        self.stream = None

    def _onTCPConnect(self, connector):
        self.tcpConnectOp = None
        if connector.getError() != 0:
            self.chatOutputView.append('ERROR')
            return
        self.sock = connector.getSock()
        self.stream = TCPLineStream(self.sock, self.reactor)
        self.stream.setCloseCallback(self._onClose)
        self.stream.setErrorCallback(self._onError)
        self.stream.setInputCallback(self._onInput)
        self.stream.enableRead(True)
        if self.isClient:
            self.stream.writeData('CONNECT %s test\r\n' %
                                  cspaceContactNickName)
        else:
            self.stream.writeData('ACCEPT %s\r\n' % cspaceConnectionId)

    def shutdown(self):
        if self.tcpConnectOp: self.tcpConnectOp.cancel()
        if self.stream: self.stream.close()
        self.state = self.CLOSED

    def _onClose(self):
        self.chatOutputView.append('Connection closed')
        self.shutdown()

    def _onError(self, err, errMsg):
        self.chatOutputView.append('Connection error(%d): %s' % (err, errMsg))
        self.shutdown()

    def _onInput(self, line):
        if self.state == self.CONNECTING:
            if line.startswith('ERROR'):
                self.chatOutputView.append('Connection failed')
                return
            if line.startswith('OK'):
                self.chatOutputView.append('Connected')
                self.state = self.CONNECTED
                self.chatInputEdit.setEnabled(True)
                self.chatInputEdit.setFocus()
                self.connect(self.chatInputEdit, SIGNAL('returnPressed()'),
                             self._onChatInputReturnPressed)
        elif self.state == self.CONNECTED:
            line = line.strip()
            self.chatOutputView.append(line)

    def _onChatInputReturnPressed(self):
        if self.state != self.CONNECTED: return
        s = str(self.chatInputEdit.text()).strip()
        if not s: return
        self.chatOutputView.append(s)
        self.stream.writeData(s + '\r\n')
        self.chatInputEdit.clear()