hydrus/include/HydrusServerAMP.py

250 lines
8.2 KiB
Python

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.ForbiddenException ] = 'FORBIDDEN'
errors[ HydrusExceptions.NetworkVersionException ] = 'NETWORK_VERSION'
errors[ HydrusExceptions.NotFoundException ] = 'NOT_FOUND'
errors[ HydrusExceptions.PermissionException ] = '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.ForbiddenException )
normal_errors.append( HydrusExceptions.NetworkVersionException )
normal_errors.append( HydrusExceptions.NotFoundException )
normal_errors.append( HydrusExceptions.PermissionException )
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 )
'''