Module mcuser
[hide private]
[frames] | no frames]

Source Code for Module mcuser

  1  # -*- coding: utf-8 -*- 
  2   
  3  ############################################################################ 
  4  # mcuser.py 
  5  # 
  6  # User object of MOCOP Architecture. 
  7  # 
  8  # (C) 2009 Likya Software Ltd. 
  9  ############################################################################ 
 10   
 11  from twisted.internet import task 
 12  from twisted.spread import pb 
 13  from twisted.python import log 
 14  import zope.interface 
 15  import mx.DateTime 
 16  import M2Crypto as m2 
 17   
 18  from util import Util 
 19  from constants import Constants 
20 21 22 -class MCUser:
23 24 zope.interface.implements(pb.IPerspective) 25
26 - def __init__(self, userAttributes, clientServices=None, virtual=False):
27 ''' 28 Generates a user object. 29 ''' 30 # Username 31 self._userName = userAttributes['username'] 32 # The domain of the user 33 self._domainName = userAttributes['domain'] 34 # Reference to client connection object 35 self._client = userAttributes.get('clientReference') 36 # Services that are published for clients 37 self._clientServices = clientServices 38 # Full name of this user 39 self._fullname = None 40 # Language choice of user 41 self._lang = None 42 # Reference to server instance 43 self._server = None 44 # If the user is a virtual user, not a real user of the domain 45 self._virtual = virtual 46 # Unique ID of this user 47 self._id = Util.uniq() 48 # User's IP address 49 self._ip = None 50 # Time that the user connected 51 self._start = None 52 # Number of concurrent connections of this user 53 self._numConns = 0 54 # Pointer to other connected MCUser objects 55 self._avatarList = None 56 # Periodic task used for detecting client time-outs() 57 self._pingTask = task.LoopingCall(self.pingClient) 58 # Method used for disconnecting a client. This method is 59 # assigned by the client realm. 60 self._loseConnection = None 61 # Count of sent out ping request, initially zero 62 self._missingPingCount = 0 63 # Authentication code list 64 self._authList = [1,2,3]
65
66 - def toDict(self):
67 ''' 68 Convert to a dict holding only standard python types. 69 ''' 70 __slots__ = ['_userName', '_domainName', '_fullname', '_lang', '_virtual', '_id', '_authList'] 71 return dict([(k, getattr(self, k, None)) for k in __slots__])
72 73 @staticmethod
74 - def fromDict(aDict):
75 ''' 76 Returns an MCUser instance by using the dictionary passed. 77 78 @param aDict: A dictionary, previously obtained by toDict() 79 @type aDict: dict 80 @returns: A new MCUser instance 81 ''' 82 __slots__ = ['_fullname', '_lang', '_virtual', '_id', '_authList'] 83 user = MCUser({'username':aDict['_userName'], 'domain':aDict['_domainName']}) 84 85 for attr in __slots__: 86 setattr(user, attr, aDict[attr]) 87 88 return user
89
90 - def clientServices(self):
91 ''' 92 Returns the client service object assigned. 93 ''' 94 return self._clientServices
95
96 - def setIP(self, address):
97 ''' 98 Sets the currently connected client's IP address. 99 100 @param address: IP address 101 ''' 102 self._ip = address
103
104 - def setClient(self, client):
105 ''' 106 Sets the remote client reference. 107 108 @param client: Avatar's mind object (reference to remote client 109 presence) 110 ''' 111 self._client = client
112
113 - def client(self):
114 ''' 115 Returns the remote client reference. 116 ''' 117 return self._client
118
119 - def setLoseConnection(self, method):
120 ''' 121 Sets the method to be used for disconnecting client represented 122 by this object. 123 124 @param method: Reference to client's loseConnection method. 125 ''' 126 self._loseConnection = method
127
128 - def setFullName(self, fullName):
129 ''' 130 Sets the connected user's full name. 131 132 @param fullName: Full name of user 133 @type fullName: str 134 ''' 135 self._fullname = fullName
136
137 - def setStartTime(self, time=None):
138 ''' 139 Sets the starting time for this user connection. 140 141 @param time: If given, this time is used as the start time 142 of connection. If None, current time is used. 143 @type time: mx.DateTime 144 ''' 145 if time is None: 146 time = mx.DateTime.now() 147 self._start = time
148
149 - def setServer(self, server):
150 ''' 151 Sets a reference to the application server. 152 153 @param server: Reference to application server. 154 @type server: Server 155 ''' 156 self._server = server
157
158 - def setAvatarList(self, avatarList):
159 ''' 160 Assigns the currently connected avatar list to this avatar. 161 162 @param avatarList: A list of currently connected avatars. 163 @type avatarList: list 164 ''' 165 self._avatarList = avatarList
166
167 - def uniqID(self):
168 ''' 169 Returns unique ID of this user instance. 170 ''' 171 return self._id
172
173 - def userName(self):
174 ''' 175 Return the username of the user object. 176 ''' 177 return self._userName
178
179 - def setUsername(self, userName):
180 ''' 181 Sets the username of the user object to a new name. 182 183 @param userName: User name 184 @type userName: str 185 ''' 186 self._userName = userName
187
188 - def domainName(self):
189 ''' 190 Return the domain name of the user object. 191 ''' 192 return self._domainName
193
194 - def setDomainName(self, domain):
195 ''' 196 Sets the domain name of the user object. 197 ''' 198 self._domainName = domain
199
200 - def IP(self):
201 ''' 202 Returns the client IP address of this user. 203 ''' 204 return self._ip
205
206 - def virtual(self):
207 ''' 208 Returns if user is virtual or not. 209 ''' 210 return self._virtual
211
212 - def setVirtual(self, virtual):
213 ''' 214 Sets the virtual property of the user object. 215 ''' 216 self._virtual = virtual
217
218 - def authList(self):
219 ''' 220 Returns the list of this user's authentication code list. 221 ''' 222 return self._authList
223
224 - def setAuthList(self, authList):
225 ''' 226 Sets the authentication code list of this user. 227 ''' 228 self._authList = authList
229
230 - def pingClient(self):
231 ''' 232 Periodically calls a remote ping method on the client. If the request 233 sent in the previous call is unanswered, then increments the missing ping 234 count. If missing ping count is exceeded, force the disconnect of the 235 remote user. 236 ''' 237 def cb_gotReply(result): 238 # If we receive a reply, we reset the _missingPingCount 239 self._missingPingCount = 0
240 241 if self._missingPingCount < Constants.MAX_PINGS: 242 # Last ping is request was successful, send a new request. 243 self._missingPingCount += 1 244 try: 245 self._client.callRemote('ping').addCallback(cb_gotReply) 246 return 247 except: 248 log.err() 249 250 # Last ping request is unanswered. Forcibly disconnect client. 251 log.msg('Client is being disconnected due to unanswered ping requests.') 252 self.forceDisconnect()
253
254 - def perspectiveMessageReceived(self, broker, message, args, kw):
255 ''' 256 This method was copied from spread/pb.py. 257 ''' 258 args = broker.unserialize(args, self) 259 kw = broker.unserialize(kw, self) 260 method = getattr(self, "perspective_%s" % message) 261 262 try: 263 state = method(*args, **kw) 264 except TypeError: 265 log.err("%s didn't accept %s and %s" % (method, args, kw)) 266 raise 267 268 return broker.serialize(state, self, method, args, kw)
269
270 - def connect(self, startPinger=True):
271 ''' 272 Method called upon connection of the client represented by this 273 class. 274 275 @param startPinger: If True, ping tester task is run, which is 276 the default. 277 ''' 278 self._numConns += 1 279 # Inform application user about the login action 280 self._server.userLoggedIn(self) 281 # For special use cases, startPinger may be False (i.e. web user) 282 if startPinger: 283 # Start the periodic ping tester 284 self._pingTask.start(Constants.PING_TIMEOUT)
285
286 - def disconnect(self):
287 ''' 288 Method called upon disconnection of the client represented by this 289 class. 290 ''' 291 if self._pingTask.running: 292 self._pingTask.stop() 293 294 log.msg(tr('sys00006') % (self.domainName(), self.userName())) 295 296 self._numConns -= 1 297 # Clean up our own reference in avatar list which is referenced 298 # in application server. 299 if self._numConns == 0: 300 del self._avatarList[self.uniqID()] 301 302 # Inform application server about this logout action 303 self._server.userLoggedOut(self)
304
305 - def forceDisconnect(self):
306 ''' 307 Forcibly disconnects the client represented by this object. May be 308 called directly by the developer. 309 ''' 310 self.disconnect() 311 # Special users do not have a _loseConnection method (i.e. web users) 312 if self._loseConnection: 313 self._loseConnection()
314
315 - def perspective_clientServices(self):
316 ''' 317 Returns the remotely callable services to the client. 318 ''' 319 return self.clientServices()
320
321 - def perspective_getServerCert(self):
322 ''' 323 Remote method that is to be called by the clients to obtain the server's 324 certificate that includes the public key. Certificate is returned in PEM 325 format. 326 327 @return: Server's certificate in PEM format 328 ''' 329 return m2.X509.load_cert_string(open(Constants.CERTIFICATE, 'rb').read()).as_pem()
330
331 - def perspective_ping(self):
332 ''' 333 Answers client's periodic ping requests. 334 ''' 335 return True
336