comparison orpg/networking/mplay_messaging.py @ 90:d1aff41c031b alpha

Traipse Alpha 'OpenRPG' {090919-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc''s main goal is to offer more advanced features and enhance the productivity of the user. Update Summary: 00: Adds menu changes to draw attention to important updates, errors, or other events. (image info coming soon) Traipse URL is not included in the repos tab and is set as default. 01: Fixes Copy for Windows and Linux (finally!!) users. Fixes incomplete update to Grid and List nodes. Fixes incomplete update to Chat Commands. 02: Fixes problems with Remote Image Upload. Fixes Drop and Drag of Minis to Map. CherryPy can now use any image in the webfiles/ folder and sub-folders. CherryPy can now Drop and Drag Minis to the Map. 03: Minor changes to Update Manager's GUI. Expert recommendation warning added to Revision Update. Step down compatibility with open_rpg & component added to orpgCore. 19-00: Better backwards compatibility in orpgCore. Using majority of 'Grumpy' network folder to correct server lag.
author sirebral
date Sat, 19 Sep 2009 06:45:21 -0500
parents 449a8900f9ac
children 65c1604e7949
comparison
equal deleted inserted replaced
89:b84e0799fed2 90:d1aff41c031b
34 import traceback 34 import traceback
35 from threading import Event, Lock 35 from threading import Event, Lock
36 from xml.sax.saxutils import escape 36 from xml.sax.saxutils import escape
37 from struct import pack, unpack, calcsize 37 from struct import pack, unpack, calcsize
38 from string import * 38 from string import *
39 from orpg.orpg_version import VERSION, PROTOCOL_VERSION, CLIENT_STRING, SERVER_MIN_CLIENT_VERSION 39 from orpg.orpg_version import *
40 import os 40 import os
41 import time 41 import time
42 42
43 from orpg.tools.orpg_log import logger 43 from orpg.orpgCore import *
44 from orpg.orpgCore import component
45 44
46 def myescape(data): 45 def myescape(data):
47 return escape(data,{"\"":""}) 46 return escape(data,{"\"":""})
48 47
49 class messenger: 48 class messenger:
50 def __init__(self, *args, **kwargs): 49 def __init__(self, *args, **kwargs):
51 #self.xml = component.get("xml") used once, no need for the object. 50 self.log = open_rpg.get_component("log")
52 self.dir_struct = component.get("dir_struct") #used? 51 self.xml = open_rpg.get_component("xml")
53 self.validate = component.get("validate") #used?? 52 self.dir_struct = open_rpg.get_component("dir_struct")
54 #self.settings = component.get("settings") ## used once, no need for the object. 53 self.validate = open_rpg.get_component("validate")
54 self.settings = open_rpg.get_component("settings")
55 if kwargs.has_key('isServer'): 55 if kwargs.has_key('isServer'):
56 self.isServer = kwargs['isServer'] 56 self.isServer = kwargs['isServer']
57 else: 57 else:
58 self.isServer = False 58 self.isServer = False
59 self.listen_event = Event() 59 self.listen_event = Event()
62 self.inbox = Queue.Queue(0) 62 self.inbox = Queue.Queue(0)
63 self.startedEvent = Event() 63 self.startedEvent = Event()
64 self.exitEvent = Event() 64 self.exitEvent = Event()
65 self.sendThreadExitEvent = Event() 65 self.sendThreadExitEvent = Event()
66 self.recvThreadExitEvent = Event() 66 self.recvThreadExitEvent = Event()
67 self.port = int(component.get("settings").get_setting("port")) ##used even? 67 self.port = int(self.settings.get_setting("port"))
68 self.ip = socket.gethostbyname(socket.gethostname()) 68 self.ip = socket.gethostbyname(socket.gethostname())
69 self.lensize = calcsize('i') 69 self.lensize = calcsize('i')
70 self.mplay_type = ('disconnected', 'connected', 'disconnecting', 'group change', 'group change failed') 70 self.mplay_type = ('disconnected', 'connected', 'disconnecting', 'group change', 'group change failed')
71 self.status = self.mplay_type[0] 71 self.status = self.mplay_type[0]
72 self.alive = False 72 self.alive = False
135 message += ' />' 135 message += ' />'
136 return message 136 return message
137 137
138 def disconnect(self): 138 def disconnect(self):
139 self.set_status(2) 139 self.set_status(2)
140 logger.debug("client stub " + self.ip +" disconnecting...") 140 self.log.log("client stub " + self.ip +" disconnecting...", ORPG_DEBUG)
141 logger.debug("closing sockets...") 141 self.log.log("closing sockets...", ORPG_DEBUG)
142 try: 142 try:
143 self.sock.shutdown( 2 ) 143 self.sock.shutdown( 2 )
144 except: 144 except:
145 logger.general("Caught exception:\n" + traceback.format_exc()) 145 self.log.log("Caught exception:\n" + traceback.format_exc(), ORPG_GENERAL)
146 self.set_status(0) 146 self.set_status(0)
147 147
148 def reset(self, sock): 148 def reset(self, sock):
149 self.disconnect() 149 self.disconnect()
150 self.sock = sock 150 self.sock = sock
159 159
160 def update_self_from_player(self, player): 160 def update_self_from_player(self, player):
161 try: 161 try:
162 (self.name, self.ip, self.id, self.text_status, self.version, self.protocol_version, self.client_string,role) = player 162 (self.name, self.ip, self.id, self.text_status, self.version, self.protocol_version, self.client_string,role) = player
163 except: 163 except:
164 logger.general("Exception: messenger->update_self_from_player():\n" + traceback.format_exc()) 164 self.log.log("Exception: messenger->update_self_from_player():\n" + traceback.format_exc(), ORPG_GENERAL)
165 165
166 def toxml(self, act): 166 def toxml(self, act):
167 logger.exception("DEPRECIATED! messenger->toxml()") 167 self.log.log("DEPRECIATED! messenger->toxml()", ORPG_CRITICAL)
168 xml_data = self.build_message('player', 168 xml_data = self.build_message('player',
169 name=myescape(self.name), 169 name=myescape(self.name),
170 action=act, 170 action=act,
171 id=self.id, 171 id=self.id,
172 group_id=self.group_id, 172 group_id=self.group_id,
288 288
289 289
290 #Message Handaling 290 #Message Handaling
291 def message_handler(self, arg): 291 def message_handler(self, arg):
292 xml_dom = None 292 xml_dom = None
293 logger.note("message handler thread running...", ORPG_NOTE) 293 self.log.log("message handler thread running...", ORPG_NOTE)
294 while self.alive or self.status == 'connected': 294 while self.alive or self.status == 'connected':
295 data = None 295 data = None
296 try: 296 try:
297 data = self.inbox.get(0) 297 data = self.inbox.get(0)
298 except Queue.Empty: 298 except Queue.Empty:
306 #data has been passed... unlink from the variable references 306 #data has been passed... unlink from the variable references
307 #so data in passed objects doesn't change (python passes by reference) 307 #so data in passed objects doesn't change (python passes by reference)
308 del data 308 del data
309 data = None 309 data = None
310 except Exception, e: 310 except Exception, e:
311 logger.general(traceback.format_exc()) 311 self.log.log(traceback.format_exc(), ORPG_GENERAL)
312 if xml_dom: xml_dom.unlink() 312 if xml_dom: xml_dom.unlink()
313 if xml_dom: xml_dom.unlink() 313 if xml_dom: xml_dom.unlink()
314 logger.note("message handler thread exiting...") 314 self.log.log("message handler thread exiting...", ORPG_NOTE)
315 self.inbox_event.set() 315 self.inbox_event.set()
316 316
317 def parse_incoming_dom(self, data): 317 def parse_incoming_dom(self, data):
318 #print data 318 #print data
319 xml_dom = None 319 xml_dom = None
320 try: 320 try:
321 xml_dom = component.get("xml").parseXml(data) 321 xml_dom = self.xml.parseXml(data)
322 xml_dom = xml_dom._get_documentElement() 322 xml_dom = xml_dom._get_documentElement()
323 self.message_action(xml_dom, data) 323 self.message_action(xml_dom, data)
324 324
325 except Exception, e: 325 except Exception, e:
326 logger.general("Error in parse of inbound message. Ignoring message.") 326 self.log.log("Error in parse of inbound message. Ignoring message.", ORPG_GENERAL)
327 logger.general("\tOffending data(" + str(len(data)) + "bytes)=" + data) 327 self.log.log("\tOffending data(" + str(len(data)) + "bytes)=" + data, ORPG_GENERAL)
328 logger.general("Exception=" + traceback.format_exc()) 328 self.log.log("Exception=" + traceback.format_exc(), ORPG_GENERAL)
329 if xml_dom: xml_dom.unlink() 329 if xml_dom: xml_dom.unlink()
330 330
331 def message_action(self, xml_dom, data): 331 def message_action(self, xml_dom, data):
332 tag_name = xml_dom._get_tagName() 332 tag_name = xml_dom._get_tagName()
333 if self.msg_handlers.has_key(tag_name): 333 if self.msg_handlers.has_key(tag_name):
334 self.msg_handlers[tag_name](xml_dom, data) 334 self.msg_handlers[tag_name](xml_dom, data)
335 else: 335 else:
336 logger.general("Unknown Message Type") 336 self.log.log("Unknown Message Type", ORPG_GENERAL)
337 logger.general(data) 337 self.log.log(data, ORPG_GENERAL)
338 #Message Action thread expires and closes here. 338 #Message Action thread expires and closes here.
339 return 339 return
340 340
341 #Privet functions 341 #Privet functions
342 def sendThread( self, arg ): 342 def sendThread( self, arg ):
348 while( self.get_status() == 'connected' ): 348 while( self.get_status() == 'connected' ):
349 try: 349 try:
350 readMsg = self.outbox.get( block=1 ) 350 readMsg = self.outbox.get( block=1 )
351 351
352 except Exception, text: 352 except Exception, text:
353 logger.exception("Exception: messenger->sendThread(): " + str(text) 353 self.log.log("Exception: messenger->sendThread(): " + str(text), ORPG_CRITICAL)
354 354
355 # If we are here, it's because we have data to send, no doubt! 355 # If we are here, it's because we have data to send, no doubt!
356 if self.status == 'connected': 356 if self.status == 'connected':
357 try: 357 try:
358 # Send the entire message, properly formated/encoded 358 # Send the entire message, properly formated/encoded
359 sent = self.sendMsg( self.sock, readMsg ) 359 sent = self.sendMsg( self.sock, readMsg )
360 except: 360 except:
361 logger.exception("Exception: messenger->sendThread():\n" + traceback.format_exc() 361 self.log.log("Exception: messenger->sendThread():\n" + traceback.format_exc(), ORPG_CRITICAL)
362 else: 362 else:
363 # If we are not connected, purge the data queue 363 # If we are not connected, purge the data queue
364 logger.note("Data queued without a connection, purging data from queue...") 364 self.log.log("Data queued without a connection, purging data from queue...", ORPG_NOTE)
365 self.sendThreadExitEvent.set() 365 self.sendThreadExitEvent.set()
366 logger.note( "sendThread has terminated...") 366 self.log.log( "sendThread has terminated...", ORPG_NOTE)
367 367
368 def sendMsg( self, sock, msg ): 368 def sendMsg( self, sock, msg ):
369 """Very simple function that will properly encode and send a message to te 369 """Very simple function that will properly encode and send a message to te
370 remote on the specified socket.""" 370 remote on the specified socket."""
371 371
380 sentl = sock.send( lp ) 380 sentl = sock.send( lp )
381 381
382 # Now, send the message the the length was describing 382 # Now, send the message the the length was describing
383 sentm = sock.send( msg ) 383 sentm = sock.send( msg )
384 if self.isServer: 384 if self.isServer:
385 logger.debug("('data_sent', " + str(sentl+sentm) + ")") 385 self.log.log("('data_sent', " + str(sentl+sentm) + ")", ORPG_DEBUG)
386 return sentm 386 return sentm
387 except socket.error, e: 387 except socket.error, e:
388 logger.exception("Socket Error: messenger->sendMsg(): " + traceback.format_exc()) 388 self.log.log("Socket Error: messenger->sendMsg(): " + traceback.format_exc(), ORPG_CRITICAL)
389 except: 389 except:
390 logger.exception("Exception: messenger->sendMsg(): " + traceback.format_exc()) 390 self.log.log("Exception: messenger->sendMsg(): " + traceback.format_exc(), ORPG_CRITICAL)
391 391
392 def recvThread( self, arg ): 392 def recvThread( self, arg ):
393 "Receiving thread. This thread reads from the socket and writes to the data queue." 393 "Receiving thread. This thread reads from the socket and writes to the data queue."
394 394
395 # Wait to be told it's okay to start running 395 # Wait to be told it's okay to start running
411 else: 411 else:
412 # Pass along the message so it can be processed 412 # Pass along the message so it can be processed
413 self.inbox.put( readMsg ) 413 self.inbox.put( readMsg )
414 self.update_idle_time() #update the last message time 414 self.update_idle_time() #update the last message time
415 if bytes == 0: 415 if bytes == 0:
416 logger.note("Remote has disconnected!") 416 self.log.log("Remote has disconnected!", ORPG_NOTE)
417 self.set_status(2) 417 self.set_status(2)
418 self.outbox.put( "" ) # Make sure the other thread is woken up! 418 self.outbox.put( "" ) # Make sure the other thread is woken up!
419 self.sendThreadExitEvent.set() 419 self.sendThreadExitEvent.set()
420 logger.note("messenger->recvThread() has terminated...") 420 self.log.log("messenger->recvThread() has terminated...", ORPG_NOTE)
421 421
422 def recvData( self, sock, readSize ): 422 def recvData( self, sock, readSize ):
423 """Simple socket receive method. This method will only return when the exact 423 """Simple socket receive method. This method will only return when the exact
424 byte count has been read from the connection, if remote terminates our 424 byte count has been read from the connection, if remote terminates our
425 connection or we get some other socket exception.""" 425 connection or we get some other socket exception."""
437 else: 437 else:
438 # Continue to build complete message 438 # Continue to build complete message
439 offset += rs 439 offset += rs
440 data += frag 440 data += frag
441 except socket.error, e: 441 except socket.error, e:
442 logger.exception("Socket Error: messenger->recvData(): " + str(e)) 442 self.log.log("Socket Error: messenger->recvData(): " + str(e), ORPG_CRITICAL)
443 data = "" 443 data = ""
444 return data 444 return data
445 445
446 def recvMsg( self, sock ): 446 def recvMsg( self, sock ):
447 """This method now expects to receive a message having a 4-byte prefix length. It will ONLY read 447 """This method now expects to receive a message having a 4-byte prefix length. It will ONLY read
463 463
464 # Read exactly the remaining amount of data 464 # Read exactly the remaining amount of data
465 msgData = self.recvData( sock, length ) 465 msgData = self.recvData( sock, length )
466 466
467 if self.isServer: 467 if self.isServer:
468 logger.debug("('data_recv', " + str(length+4) + ")") 468 self.log.log("('data_recv', " + str(length+4) + ")", ORPG_DEBUG)
469 except: 469 except:
470 logger.exception("Exception: messenger->recvMsg():\n" + traceback.format_exc()) 470 self.log.log("Exception: messenger->recvMsg():\n" + traceback.format_exc(), ORPG_CRITICAL)
471 return msgData 471 return msgData
472 472
473 if __name__ == "__main__": 473 if __name__ == "__main__":
474 test = messenger(None) 474 test = messenger(None)
475 print test.build_message('hello', "This is a test message", attrib1="hello world", attrib2="hello world2", attrib3="hello world3") 475 print test.build_message('hello', "This is a test message", attrib1="hello world", attrib2="hello world2", attrib3="hello world3")