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:] )