import collections from . import HydrusConstants as HC from . import HydrusDocumentHandling from . import HydrusExceptions from . import HydrusFileHandling from . import HydrusFlashHandling from . import HydrusImageHandling from . import HydrusServerResources import os import random from . import ServerFiles import traceback from twisted.internet import reactor, defer from twisted.internet.threads import deferToThread from twisted.protocols import amp from . import HydrusData from . import HydrusGlobals as HG ''' class HydrusAMPCommand( amp.Command ): errors = {} errors[ HydrusExceptions.InsufficientCredentialsException ] = 'FORBIDDEN' errors[ HydrusExceptions.NetworkVersionException ] = 'NETWORK_VERSION' errors[ HydrusExceptions.NotFoundException ] = 'NOT_FOUND' errors[ HydrusExceptions.MissingCredentialsException ] = 'PERMISSION' errors[ HydrusExceptions.SessionException ] = 'SESSION' errors[ Exception ] = 'EXCEPTION' # IMFile, for aes-encrypted file transfers, as negotiated over otr messages # file_transfer_id (so we can match up the correct aes key) # file (this is complicated -- AMP should be little things, right? I need to check max packet size.) # so, this should be blocks. a block_id and a block # MMessageReceivedPing -- server to persistent client, saying someone just now sent you a message class IMLoginPersistent( HydrusAMPCommand ): arguments = [ ( 'network_version', amp.Integer() ), ( 'session_key', amp.String() ) ] class IMLoginTemporary( HydrusAMPCommand ): arguments = [ ( 'network_version', amp.Integer() ), ( 'identifier', amp.String() ), ( 'name', amp.String() ) ] class IMMessageClient( HydrusAMPCommand ): arguments = [ ( 'identifier_from', amp.String() ), ( 'name_from', amp.String() ), ( 'identifier_to', amp.String() ), ( 'name_to', amp.String() ), ( 'message', amp.String() ) ] class IMMessageServer( HydrusAMPCommand ): arguments = [ ( 'identifier_to', amp.String() ), ( 'name_to', amp.String() ), ( 'message', amp.String() ) ] class IMSessionKey( HydrusAMPCommand ): arguments = [ ( 'access_key', amp.String() ), ( 'name', amp.String() ) ] response = [ ( 'session_key', amp.String() ) ] class MPublicKey( HydrusAMPCommand ): arguments = [ ( 'identifier', amp.String() ) ] response = [ ( 'public_key', amp.String() ) ] class HydrusAMP( amp.AMP ): def _errbackHandleError( self, failure ): HydrusData.Print( failure.getTraceback() ) normal_errors = [] normal_errors.append( HydrusExceptions.InsufficientCredentialsException ) normal_errors.append( HydrusExceptions.NetworkVersionException ) normal_errors.append( HydrusExceptions.NotFoundException ) normal_errors.append( HydrusExceptions.MissingCredentialsException ) normal_errors.append( HydrusExceptions.SessionException ) if failure.type in normal_errors: failure.raiseException() else: raise Exception( failure.getTraceback() ) class MessagingClientProtocol( HydrusAMP ): def im_message( self, identifier_from, name_from, identifier_to, name_to, message ): def do_it( gumpf ): HG.controller.pub( 'im_message_received', identifier_from, name_from, identifier_to, name_to, message ) return {} d = defer.Deferred() d.addCallback( do_it ) d.addErrback( self._errbackHandleError ) reactor.callLater( 0, d.callback, None ) return d IMMessageClient.responder( im_message ) def connectionLost( self, reason ): # report to ui that the connection is lost pass class MessagingServiceProtocol( HydrusAMP ): def __init__( self ): amp.AMP.__init__( self ) self._identifier = None self._name = None def _check_network_version( self, network_version ): if network_version != HC.NETWORK_VERSION: if network_version < HC.NETWORK_VERSION: message = 'Your client is out of date; please download the latest release.' else: message = 'This server is out of date; please ask its admin to update to the latest release.' message = 'Network version mismatch! This server\'s network version is ' + str( HC.NETWORK_VERSION ) + ', whereas your client\'s is ' + str( network_version ) + '! ' + message raise HydrusExceptions.NetworkVersionException( message ) def im_login_persistent( self, network_version, session_key ): def do_it( gumpf ): self._check_network_version( network_version ) session_manager = HG.controller.GetManager( 'messaging_sessions' ) ( identifier, name ) = session_manager.GetIdentityAndName( self.factory.service_key, session_key ) self._identifier = identifier self._name = name self.factory.AddConnection( True, self._identifier, self._name, self ) return {} d = defer.Deferred() d.addCallback( do_it ) d.addErrback( self._errbackHandleError ) reactor.callLater( 0, d.callback, None ) return d IMLoginPersistent.responder( im_login_persistent ) def im_login_temporary( self, network_version, identifier, name ): def do_it( gumpf ): self._check_network_version( network_version ) self._identifier = identifier self._name = name self.factory.AddConnection( False, self._identifier, self._name, self ) return {} d = defer.Deferred() d.addCallback( do_it ) d.addErrback( self._errbackHandleError ) reactor.callLater( 0, d.callback, None ) return d IMLoginTemporary.responder( im_login_temporary ) def im_message( self, identifier_to, name_to, message ): def do_it( gumpf ): if self._identifier is None or self._name is None: raise Exception() # who the hell are you? pls temp login connection = self.factory.GetConnection( identifier_to, name_to ) d = connection.callRemote( IMMessageClient, identifier_from = self._identifier, name_from = self._name, identifier_to = identifier_to, name_to = name_to, message = message ) return d d = defer.Deferred() d.addCallback( do_it ) d.addErrback( self._errbackHandleError ) reactor.callLater( 0, d.callback, None ) return d IMMessageServer.responder( im_message ) def im_session_key( self, access_key, name ): def catch_session_key( session_key ): return { 'session_key' : session_key } def do_it( gumpf ): session_manager = HG.controller.GetManager( 'messaging_sessions' ) d = deferToThread( session_manager.AddSession, self.factory.service_key, access_key, name ) d.addCallback( catch_session_key ) return d d = defer.Deferred() d.addCallback( do_it ) d.addErrback( self._errbackHandleError ) reactor.callLater( 0, d.callback, None ) return d IMSessionKey.responder( im_session_key ) def m_public_key( self, identifier ): # this will not be useful until we have normal messaging sorted public_key = 'public key' return { 'public_key' : public_key } MPublicKey.responder( m_public_key ) def connectionLost( self, reason ): if self._identifier is not None: self.factory.RemoveConnection( self._identifier, self._name ) '''