comparison orpg/networking/mplay_server.py @ 56:c7f04d3c76f5 traipse_dev

Major update to Server GUI. Basically makes it functional.
author sirebral
date Fri, 07 Aug 2009 21:53:14 -0500
parents 4385a7d0efd1
children 9014d7861bb3
comparison
equal deleted inserted replaced
55:0b79d5dbbe9e 56:c7f04d3c76f5
365 # try to use it. 365 # try to use it.
366 try: 366 try:
367 self.configDom = minidom.parse(self.userPath + 'server_ini.xml') 367 self.configDom = minidom.parse(self.userPath + 'server_ini.xml')
368 self.configDom.normalize() 368 self.configDom.normalize()
369 self.configDoc = self.configDom.documentElement 369 self.configDoc = self.configDom.documentElement
370 # Obtain the lobby/server password if it's been specified 370
371 if self.configDoc.hasAttribute("admin"): 371 if hasattr(self, 'bootPassword'): self.boot_pwd = self.bootPassword
372 self.boot_pwd = self.configDoc.getAttribute("admin") 372
373 elif self.configDoc.hasAttribute("boot"): 373 else:
374 self.boot_pwd = self.configDoc.getAttribute("boot") 374 if self.configDoc.hasAttribute("admin"): self.boot_pwd = self.configDoc.getAttribute("admin")
375 if hasattr(self, 'bootPassword'): 375 elif self.configDoc.hasAttribute("boot"): self.boot_pwd = self.configDoc.getAttribute("boot")
376 self.boot_pwd = self.bootPassword 376
377 elif len(self.boot_pwd) < 1: 377 if len(self.boot_pwd) < 1: self.boot_pwd = raw_input("Enter admin password: ")
378 self.boot_pwd = raw_input("Enter boot password for the Lobby: ") 378
379 if not hasattr(self, 'reg') and self.configDoc.hasAttribute("register"): 379 if not hasattr(self, 'reg') and self.configDoc.hasAttribute("register"):
380 self.reg = self.configDoc.getAttribute("register") 380 self.reg = self.configDoc.getAttribute("register")
381 if not len(self.reg) > 0 or self.reg[0].upper() not in ("Y", "N"): 381 if not len(self.reg) > 0 or self.reg[0].upper() not in ("Y", "N"):
382 opt = raw_input("Do you want to post your server to the OpenRPG Meta Server list? (y,n) ") 382 opt = raw_input("Do you want to post your server to the OpenRPG Meta Server list? (y,n) ")
383 if len(opt) and (opt[0].upper() == 'Y'): 383 if len(opt) and (opt[0].upper() == 'Y'): self.reg = 'Y'
384 self.reg = 'Y' 384 else: self.reg = 'N'
385 else:
386 self.reg = 'N'
387 LobbyName = 'Lobby' 385 LobbyName = 'Lobby'
388 if self.configDoc.hasAttribute("lobbyname"): 386 if self.configDoc.hasAttribute("lobbyname"): LobbyName = self.configDoc.getAttribute("lobbyname")
389 LobbyName = self.configDoc.getAttribute("lobbyname")
390 map_node = service_node = self.configDoc.getElementsByTagName("map")[0] 387 map_node = service_node = self.configDoc.getElementsByTagName("map")[0]
391 msg_node = service_node = self.configDoc.getElementsByTagName("message")[0] 388 msg_node = service_node = self.configDoc.getElementsByTagName("message")[0]
392 mapFile = map_node.getAttribute('file') 389 mapFile = map_node.getAttribute('file')
393 msgFile = msg_node.getAttribute('file') 390 msgFile = msg_node.getAttribute('file')
394 if mapFile == '': 391 if mapFile == '': mapFile = 'Lobby_map.xml'
395 mapFile = 'Lobby_map.xml' 392 if msgFile == '': msgFile = 'LobbyMessage.html'
396 if msgFile == '':
397 msgFile = 'LobbyMessage.html'
398 # Update the lobby with the passwords if they've been specified 393 # Update the lobby with the passwords if they've been specified
399 if len(self.boot_pwd): 394 if len(self.boot_pwd):
400 self.groups = {'0': game_group( '0', LobbyName, "", 'The game lobby', self.boot_pwd, "", 395 self.groups = {'0': game_group( '0', LobbyName, "", 'The game lobby', self.boot_pwd, "",
401 self.userPath + mapFile.replace("myfiles/", ""), 396 self.userPath + mapFile.replace("myfiles/", ""),
402 self.userPath + msgFile.replace("myfiles/", ""), 1 ) 397 self.userPath + msgFile.replace("myfiles/", ""), 1 )
404 399
405 # set ip or dns name to send to meta server 400 # set ip or dns name to send to meta server
406 service_node = self.configDoc.getElementsByTagName("service")[0] 401 service_node = self.configDoc.getElementsByTagName("service")[0]
407 address = service_node.getAttribute("address") 402 address = service_node.getAttribute("address")
408 address = address.lower() 403 address = address.lower()
409 if address == "" or address == "hostname/address" or address == "localhost": 404 if address == "" or address == "hostname/address" or address == "localhost": self.server_address = None
410 self.server_address = None 405 else: self.server_address = address
411 else:
412 self.server_address = address
413 self.server_port = OPENRPG_PORT 406 self.server_port = OPENRPG_PORT
414 if service_node.hasAttribute("port"): 407 if service_node.hasAttribute("port"): self.server_port = int(service_node.getAttribute("port"))
415 self.server_port = int(service_node.getAttribute("port"))
416 if self.configDoc.hasAttribute("name") and len(self.configDoc.getAttribute("name")) > 0 : 408 if self.configDoc.hasAttribute("name") and len(self.configDoc.getAttribute("name")) > 0 :
417 self.name = self.configDoc.getAttribute("name") 409 self.name = self.configDoc.getAttribute("name")
418 else: 410 else:
419 if self.reg[0].upper() == "Y": 411 if self.reg[0].upper() == "Y":
420 if self.name == None: 412 if self.name == None: self.name = raw_input("Server Name? ")
421 self.name = raw_input("Server Name? ")
422 self.register() 413 self.register()
423 414
424 # Get the minimum openrpg version from config if available 415 # Get the minimum openrpg version from config if available
425 # if it isn't set min version to internal default. 416 # if it isn't set min version to internal default.
426 # 417 #
427 # server_ini.xml entry for version tag... 418 # server_ini.xml entry for version tag...
428 # <version min="x.x.x"> 419 # <version min="x.x.x">
429 try: 420 try:
430 mver = self.configDoc.getElementsByTagName("version")[0] 421 mver = self.configDoc.getElementsByTagName("version")[0]
431 self.minClientVersion = mver.getAttribute("min") 422 self.minClientVersion = mver.getAttribute("min")
432 except: 423 except: self.minClientVersion = SERVER_MIN_CLIENT_VERSION #from orpg/orpg_version.py
433 self.minClientVersion = SERVER_MIN_CLIENT_VERSION #from orpg/orpg_version.py
434 self.defaultMessageFile = "" 424 self.defaultMessageFile = ""
435 # This try/except bit is to allow older versions of python to continue without a list error. 425 # This try/except bit is to allow older versions of python to continue without a list error.
436 426
437 427
438 428
444 # <autokick silent=["no","yes"] delay="(# of seconds)"> 434 # <autokick silent=["no","yes"] delay="(# of seconds)">
445 435
446 try: 436 try:
447 ak = self.configDoc.getElementsByTagName("autokick")[0] 437 ak = self.configDoc.getElementsByTagName("autokick")[0]
448 if ak.hasAttribute("silent"): 438 if ak.hasAttribute("silent"):
449 if ((ak.getAttribute("silent")).lower() == "yes"): 439 if ((ak.getAttribute("silent")).lower() == "yes"): self.silent_auto_kick = 1
450 self.silent_auto_kick = 1 440 else: self.silent_auto_kick = 0
451 else:
452 self.silent_auto_kick = 0
453 if ak.hasAttribute("delay"): 441 if ak.hasAttribute("delay"):
454 try: 442 try:
455 delay = int(ak.getAttribute("delay")) 443 delay = int(ak.getAttribute("delay"))
456 self.zombie_time = delay 444 self.zombie_time = delay
457 except: 445 except:
495 setting = roomdefaults.getElementsByTagName('passwords')[0] 483 setting = roomdefaults.getElementsByTagName('passwords')[0]
496 rpw = setting.getAttribute('allow') 484 rpw = setting.getAttribute('allow')
497 if rpw == "no" or rpw == "0": 485 if rpw == "no" or rpw == "0":
498 roomdefault_pass = 0 486 roomdefault_pass = 0
499 self.log_msg("Room Defaults: Disallowing Passworded Rooms") 487 self.log_msg("Room Defaults: Disallowing Passworded Rooms")
500 else: 488 else: self.log_msg("Room Defaults: Allowing Passworded Rooms")
501 self.log_msg("Room Defaults: Allowing Passworded Rooms") 489 except: self.log_msg("Room Defaults: [Warning] Allowing Passworded Rooms")
502 except:
503 self.log_msg("Room Defaults: [Warning] Allowing Passworded Rooms")
504 try: 490 try:
505 setting = roomdefaults.getElementsByTagName('map')[0] 491 setting = roomdefaults.getElementsByTagName('map')[0]
506 map = setting.getAttribute('file') 492 map = setting.getAttribute('file')
507 if map != "": 493 if map != "":
508 roomdefault_map = self.userPath + map.replace("myfiles/", "") 494 roomdefault_map = self.userPath + map.replace("myfiles/", "")
512 498
513 try: 499 try:
514 setting = roomdefaults.getElementsByTagName('message')[0] 500 setting = roomdefaults.getElementsByTagName('message')[0]
515 msg = setting.getAttribute('file') 501 msg = setting.getAttribute('file')
516 if msg != "": 502 if msg != "":
517 if msg[:4].lower() == 'http': 503 if msg[:4].lower() == 'http': roomdefault_msg = msg
518 roomdefault_msg = msg 504 else: roomdefault_msg = self.userPath + msg.replace("myfiles/", "")
519 else:
520 roomdefault_msg = self.userPath + msg.replace("myfiles/", "")
521 self.log_msg("Room Defaults: Using " + str(msg) + " for room messages") 505 self.log_msg("Room Defaults: Using " + str(msg) + " for room messages")
522 except: 506 except: print ("Room Defaults: [Warning] Using Default Message")
523 print ("Room Defaults: [Warning] Using Default Message")
524 except: 507 except:
525 traceback.print_exc() 508 traceback.print_exc()
526 self.log_msg("**WARNING** Error loading default room settings from configuration file. Using internal defaults.") 509 self.log_msg("**WARNING** Error loading default room settings from configuration file. Using internal defaults.")
527 510
528 511
529 #set the defaults 512 #set the defaults
530 if roomdefault_msg != "" or roomdefault_msg != None: 513 if roomdefault_msg != "" or roomdefault_msg != None:
531 self.defaultMessageFile = roomdefault_msg #<room_defaults> tag superceeds older <newrooms> tag 514 self.defaultMessageFile = roomdefault_msg #<room_defaults> tag superceeds older <newrooms> tag
532 else: 515 else: self.defaultMessageFile = None
533 self.defaultMessageFile = None
534 516
535 if roomdefault_map != "" or roomdefault_map != None: 517 if roomdefault_map != "" or roomdefault_map != None:
536 self.defaultMapFile = roomdefault_map #<room_defaults> tag superceeds older <newrooms> tag 518 self.defaultMapFile = roomdefault_map #<room_defaults> tag superceeds older <newrooms> tag
537 else: 519 else: self.defaultMapFile = None
538 self.defaultMapFile = None
539 520
540 ##### room default map not handled yet. SETTING IGNORED 521 ##### room default map not handled yet. SETTING IGNORED
541 if roomdefault_pass == 0: self.allow_room_passwords = 0 522 if roomdefault_pass == 0: self.allow_room_passwords = 0
542 else: self.allow_room_passwords = 1 523 else: self.allow_room_passwords = 1
543 524
557 # should validate protocal 538 # should validate protocal
558 validate_protocol_node = self.configDom.getElementsByTagName("validate_protocol ") 539 validate_protocol_node = self.configDom.getElementsByTagName("validate_protocol ")
559 540
560 self.validate_protocol = 1 541 self.validate_protocol = 1
561 542
562 if(validate_protocol_node): 543 if(validate_protocol_node): self.validate_protocol = (validate_protocol_node[0].getAttribute("value") == "True")
563 self.validate_protocol = (validate_protocol_node[0].getAttribute("value") == "True") 544 if(self.validate_protocol != 1): self.log_msg("Protocol Validation: OFF")
564 if(self.validate_protocol != 1):
565 self.log_msg("Protocol Validation: OFF")
566 self.makePersistentRooms() 545 self.makePersistentRooms()
567 546
568 self.log_msg("Server Configuration File: Processing Completed.") 547 self.log_msg("Server Configuration File: Processing Completed.")
569 548
570 except Exception, e: 549 except Exception, e:
579 roomName = element.getAttribute('name') 558 roomName = element.getAttribute('name')
580 roomPassword = element.getAttribute('password') 559 roomPassword = element.getAttribute('password')
581 bootPassword = element.getAttribute('boot') 560 bootPassword = element.getAttribute('boot')
582 561
583 # Conditionally check for minVersion attribute 562 # Conditionally check for minVersion attribute
584 if element.hasAttribute('minVersion'): 563 if element.hasAttribute('minVersion'): minVersion = element.getAttribute('minVersion')
585 minVersion = element.getAttribute('minVersion') 564 else: minVersion = ""
586 else:
587 minVersion = ""
588 565
589 # Extract the map filename attribute from the map node 566 # Extract the map filename attribute from the map node
590 # we only care about the first map element found -- others are ignored 567 # we only care about the first map element found -- others are ignored
591 mapElement = element.getElementsByTagName('map')[0] 568 mapElement = element.getElementsByTagName('map')[0]
592 mapFile = self.userPath + mapElement.getAttribute('file').replace("myfiles/", "") 569 mapFile = self.userPath + mapElement.getAttribute('file').replace("myfiles/", "")
593 570
594 messageElement = element.getElementsByTagName('message')[0] 571 messageElement = element.getElementsByTagName('message')[0]
595 messageFile = messageElement.getAttribute('file') 572 messageFile = messageElement.getAttribute('file')
596 573
597 if messageFile[:4] != 'http': 574 if messageFile[:4] != 'http': messageFile = self.userPath + messageFile.replace("myfiles/", "")
598 messageFile = self.userPath + messageFile.replace("myfiles/", "")
599 575
600 # Make sure we have a message to even mess with 576 # Make sure we have a message to even mess with
601 if(len(messageFile) == 0): 577 if(len(messageFile) == 0): messageFile = self.defaultMessageFile
602 messageFile = self.defaultMessageFile 578
603 579 if(len(mapFile) == 0): mapFile = self.defaultMapFile
604 if(len(mapFile) == 0):
605 mapFile = self.defaultMapFile
606 580
607 moderated = 0 581 moderated = 0
608 if element.hasAttribute('moderated') and element.getAttribute('moderated').lower() == "true": 582 if element.hasAttribute('moderated') and element.getAttribute('moderated').lower() == "true": moderated = 1
609 moderated = 1
610 583
611 #create the new persistant group 584 #create the new persistant group
612 self.new_group(roomName, roomPassword, bootPassword, minVersion, mapFile, messageFile, persist = 1, moderated=moderated) 585 self.new_group(roomName, roomPassword, bootPassword, minVersion, mapFile, messageFile, persist = 1, moderated=moderated)
613 586
614 587
656 self.log_msg("Network Logging: ON (split logfiles)") 629 self.log_msg("Network Logging: ON (split logfiles)")
657 self.log_network_messages = 2 630 self.log_network_messages = 2
658 else: return 631 else: return
659 #when log mode changes update all connection stubs 632 #when log mode changes update all connection stubs
660 for n in self.players: 633 for n in self.players:
661 try: 634 try: self.players[n].EnableMessageLogging = mode
662 self.players[n].EnableMessageLogging = mode 635 except: self.log_msg("Error changing Message Logging Mode for client #" + str(self.players[n].id))
663 except:
664 self.log_msg("Error changing Message Logging Mode for client #" + str(self.players[n].id))
665 def NetworkLoggingStatus(self): 636 def NetworkLoggingStatus(self):
666 if self.log_network_messages == 0: return "Network Traffic Log: Off" 637 if self.log_network_messages == 0: return "Network Traffic Log: Off"
667 elif self.log_network_messages == 1: return "Network Traffic Log: Logging (composite file)" 638 elif self.log_network_messages == 1: return "Network Traffic Log: Logging (composite file)"
668 elif self.log_network_messages == 2: return "Network Traffic Log: Logging (inbound/outbound files)" 639 elif self.log_network_messages == 2: return "Network Traffic Log: Logging (inbound/outbound files)"
669 else: self.log_msg("Network Traffic Log: [Unknown]") 640 else: self.log_msg("Network Traffic Log: [Unknown]")
681 newlist = getRawMetaList() # read it into a second list 652 newlist = getRawMetaList() # read it into a second list
682 finally: 653 finally:
683 metacache_lock.release() 654 metacache_lock.release()
684 655
685 if newlist != curlist: # If the two lists aren't identical 656 if newlist != curlist: # If the two lists aren't identical
686 # then something has changed. 657 # then something has changed.
687 instance.register() # Call self.register() 658 instance.register() # Call self.register()
688 # which will force a re-read of the meta cache and 659 # which will force a re-read of the meta cache and
689 # redo the registerThreads 660 # redo the registerThreads
690 else: 661 else: instance.register()
691 instance.register()
692 662
693 # Eventually, reset the MetaServerBaseURL here 663 # Eventually, reset the MetaServerBaseURL here
694 664
695 ## Added to help clean up parser errors in the XML on clients 665 ## Added to help clean up parser errors in the XML on clients
696 ## due to characters that break welformedness of the XML from 666 ## due to characters that break welformedness of the XML from
697 ## the meta server. 667 ## the meta server.
698 ## NOTE: this is a stopgap measure -SD 668 ## NOTE: this is a stopgap measure -SD
699 def clean_published_servername(self, name): 669 def clean_published_servername(self, name):
700 #clean name of all apostrophes and quotes 670 #clean name of all apostrophes and quotes
701 badchars = "\"\\`><" 671 badchars = "\"\\`><"
702 for c in badchars: 672 for c in badchars: name = name.replace(c,"")
703 name = name.replace(c,"")
704 return name 673 return name
705 674
706 def registerRooms(self, args=None): 675 def registerRooms(self, args=None):
707 rooms = '' 676 rooms = ''
708 id = '0' 677 id = '0'
722 "act":'registerrooms'}) 691 "act":'registerrooms'})
723 get_server_dom(data+'&'+rooms, self.metas[meta].path) 692 get_server_dom(data+'&'+rooms, self.metas[meta].path)
724 693
725 694
726 def register(self,name_given=None): 695 def register(self,name_given=None):
727 if name_given == None: 696 if name_given == None: name = self.name
728 name = self.name 697 else: self.name = name = name_given
729 else:
730 self.name = name = name_given
731 698
732 name = self.clean_published_servername(name) 699 name = self.clean_published_servername(name)
733 700
734 # Set up the value for num_users 701 # Set up the value for num_users
735 if self.players: 702 if self.players: num_players = len(self.players)
736 num_players = len(self.players) 703 else: num_players = 0
737 else:
738 num_players = 0
739 704
740 # request only Meta servers compatible with version 2 705 # request only Meta servers compatible with version 2
741 metalist = getMetaServers(versions=["2"]) 706 metalist = getMetaServers(versions=["2"])
742 if self.show_meta_messages != 0: 707 if self.show_meta_messages != 0:
743 self.log_msg("Found these valid metas:") 708 self.log_msg("Found these valid metas:")
744 for meta in metalist: 709 for meta in metalist: self.log_msg("Meta:" + meta)
745 self.log_msg("Meta:" + meta)
746 710
747 # Go through the list and see if there is already a running register 711 # Go through the list and see if there is already a running register
748 # thread for the meta. 712 # thread for the meta.
749 # If so, call it's register() method 713 # If so, call it's register() method
750 # If not, start one, implicitly calling the new thread's register() method 714 # If not, start one, implicitly calling the new thread's register() method
757 if self.show_meta_messages != 0: self.log_msg("meta:" + meta + ": ") 721 if self.show_meta_messages != 0: self.log_msg("meta:" + meta + ": ")
758 if not meta in metalist: # if the meta entry running is not in the list 722 if not meta in metalist: # if the meta entry running is not in the list
759 if self.show_meta_messages != 0: self.log_msg( "Outdated. Unregistering and removing") 723 if self.show_meta_messages != 0: self.log_msg( "Outdated. Unregistering and removing")
760 self.metas[meta].unregister() 724 self.metas[meta].unregister()
761 del self.metas[meta] 725 del self.metas[meta]
762 else: 726 else:
763 if self.show_meta_messages != 0: self.log_msg( "Found in current meta list. Leaving intact.") 727 if self.show_meta_messages != 0: self.log_msg( "Found in current meta list. Leaving intact.")
764 728
765 # Now call register() for alive metas or start one if we need one 729 # Now call register() for alive metas or start one if we need one
766 for meta in metalist: 730 for meta in metalist:
767 if self.metas.has_key(meta) and self.metas[meta] and self.metas[meta].isAlive(): 731 if self.metas.has_key(meta) and self.metas[meta] and self.metas[meta].isAlive():
784 # would never get unregistered. 748 # would never get unregistered.
785 # 749 #
786 # Instead, loop through all existing meta threads and unregister them 750 # Instead, loop through all existing meta threads and unregister them
787 751
788 for meta in self.metas.values(): 752 for meta in self.metas.values():
789 if meta and meta.isAlive(): 753 if meta and meta.isAlive(): meta.unregister()
790 meta.unregister()
791
792 self.be_registered = 0 754 self.be_registered = 0
793 755
794 756 # This method runs as it's own thread and does the group_member_check every
795 757 # sixty seconds. This should eliminate zombies that linger when no one is
796 758 # around to spook them. GC: Frequency has been reduced as I question how valid
797 # This method runs as it's own thread and does the group_member_check every 759 # the implementation is as it will only catch a very small segment of lingering
798 # sixty seconds. This should eliminate zombies that linger when no one is 760 # connections.
799 # around to spook them. GC: Frequency has been reduced as I question how valid
800 # the implementation is as it will only catch a very small segment of lingering
801 # connections.
802 def player_reaper_thread_func(self,arg): 761 def player_reaper_thread_func(self,arg):
803 while self.alive: 762 while self.alive:
804 time.sleep(60) 763 time.sleep(60)
805 764
806 self.p_lock.acquire() 765 self.p_lock.acquire()
807 for group in self.groups.keys(): 766 for group in self.groups.keys(): self.check_group_members(group)
808 self.check_group_members(group)
809 self.p_lock.release() 767 self.p_lock.release()
810 768
811 #This thread runs ever 250 miliseconds, and checks various plugin stuff 769 #This thread runs ever 250 miliseconds, and checks various plugin stuff
812 def PluginThread(self): 770 def PluginThread(self):
813 while self.alive: 771 while self.alive:
814 self.p_lock.acquire() 772 self.p_lock.acquire()
815 players = ServerPlugins.getPlayer() 773 players = ServerPlugins.getPlayer()
816 774
817 for player in players: 775 for player in players:
818 if player is not None: 776 if player is not None: pass #Do something here so they can show up in the chat room for non web users'
819 #Do something here so they can show up in the chat room for non web users'
820 pass
821
822 data = ServerPlugins.preParseOutgoing() 777 data = ServerPlugins.preParseOutgoing()
823
824 for msg in data: 778 for msg in data:
825 try: 779 try:
826 xml_dom = parseXml(msg) 780 xml_dom = parseXml(msg)
827 xml_dom = xml_dom._get_documentElement() 781 xml_dom = xml_dom._get_documentElement()
828 782
830 xml_dom.setAttribute('from', '-1') 784 xml_dom.setAttribute('from', '-1')
831 785
832 xml_dom.setAttribute('to', 'all') 786 xml_dom.setAttribute('to', 'all')
833 self.incoming_msg_handler(xml_dom, msg) 787 self.incoming_msg_handler(xml_dom, msg)
834 xml_dom.unlink() 788 xml_dom.unlink()
835 except: 789 except: pass
836 pass
837 790
838 self.p_lock.release() 791 self.p_lock.release()
839 time.sleep(0.250) 792 time.sleep(0.250)
840 793
841 794
852 while offset < len(mpacket): 805 while offset < len(mpacket):
853 slice = buffer(mpacket, offset, len(mpacket)-offset) 806 slice = buffer(mpacket, offset, len(mpacket)-offset)
854 sent = sock.send(slice) 807 sent = sock.send(slice)
855 offset += sent 808 offset += sent
856 sentm = offset 809 sentm = offset
857 else: 810 else:
858 # Calculate our message length 811 length = len( msg ) # Calculate our message length
859 length = len( msg ) 812 lp = pack('!i', length) # Encode the message length into network byte order
860
861 # Encode the message length into network byte order
862 lp = pack('!i', length)
863
864 try: 813 try:
865 # Send the encoded length 814 sentl = sock.send( lp ) # Send the encoded length
866 sentl = sock.send( lp ) 815 sentm = sock.send( msg ) # Now, send the message the the length was describing
867 816 except socket.error, e: self.log_msg( e )
868 # Now, send the message the the length was describing 817 except Exception, e: self.log_msg( e )
869 sentm = sock.send( msg )
870
871 except socket.error, e:
872 self.log_msg( e )
873
874 except Exception, e:
875 self.log_msg( e )
876 818
877 819
878 def recvData( self, sock, readSize ): 820 def recvData( self, sock, readSize ):
879 """Simple socket receive method. This method will only return when the exact 821 """Simple socket receive method. This method will only return when the exact
880 byte count has been read from the connection, if remote terminates our 822 byte count has been read from the connection, if remote terminates our
883 data = "" 825 data = ""
884 offset = 0 826 offset = 0
885 try: 827 try:
886 while offset != readSize: 828 while offset != readSize:
887 frag = sock.recv( readSize - offset ) 829 frag = sock.recv( readSize - offset )
888 830 rs = len( frag ) # See if we've been disconnected
889 # See if we've been disconnected
890 rs = len( frag )
891 if rs <= 0: 831 if rs <= 0:
892 # Loudly raise an exception because we've been disconnected! 832 # Loudly raise an exception because we've been disconnected!
893 raise IOError, "Remote closed the connection!" 833 raise IOError, "Remote closed the connection!"
894 834 else: # Continue to build complete message
895 else:
896 # Continue to build complete message
897 offset += rs 835 offset += rs
898 data += frag 836 data += frag
899 837
900 except socket.error, e: 838 except socket.error, e:
901 self.log_msg("Socket Error: recvData(): " + e ) 839 self.log_msg("Socket Error: recvData(): " + e )
902 data = "" 840 data = ""
903
904 return data 841 return data
905
906
907 842
908 def recvMsg(self, sock, useCompression=False, cmpType=None): 843 def recvMsg(self, sock, useCompression=False, cmpType=None):
909 """This method now expects to receive a message having a 4-byte prefix length. It will ONLY read 844 """This method now expects to receive a message having a 4-byte prefix length. It will ONLY read
910 completed messages. In the event that the remote's connection is terminated, it will throw an 845 completed messages. In the event that the remote's connection is terminated, it will throw an
911 exception which should allow for the caller to more gracefully handles this exception event. 846 exception which should allow for the caller to more gracefully handles this exception event.
916 with the OS until we attempt to read the next complete message.""" 851 with the OS until we attempt to read the next complete message."""
917 852
918 msgData = "" 853 msgData = ""
919 try: 854 try:
920 lenData = self.recvData( sock, MPLAY_LENSIZE ) 855 lenData = self.recvData( sock, MPLAY_LENSIZE )
921
922 # Now, convert to a usable form 856 # Now, convert to a usable form
923 (length,) = unpack('!i', lenData) 857 (length,) = unpack('!i', lenData)
924
925 # Read exactly the remaining amount of data 858 # Read exactly the remaining amount of data
926 msgData = self.recvData( sock, length ) 859 msgData = self.recvData( sock, length )
927
928 try: 860 try:
929 if useCompression and cmpType != None: 861 if useCompression and cmpType != None: msgData = cmpType.decompress(msgData)
930 msgData = cmpType.decompress(msgData) 862 except: traceback.print_exc()
931 except: 863
932 traceback.print_exc() 864 except Exception, e: self.log_msg( "Exception: recvMsg(): " + str(e) )
933
934 except Exception, e:
935 self.log_msg( "Exception: recvMsg(): " + str(e) )
936
937 return msgData 865 return msgData
938
939 866
940 867
941 def kill_server(self): 868 def kill_server(self):
942 self.alive = 0 869 self.alive = 0
943 self.log_msg("Server stopping...") 870 self.log_msg("Server stopping...")
1355 1282
1356 # Re-initialize the role for this player incase they came from a different server 1283 # Re-initialize the role for this player incase they came from a different server
1357 self.handle_role("set",props['id'], "GM",self.groups[LOBBY_ID].boot_pwd, LOBBY_ID) 1284 self.handle_role("set",props['id'], "GM",self.groups[LOBBY_ID].boot_pwd, LOBBY_ID)
1358 1285
1359 cmsg = "Client Connect: (" + str(props['id']) + ") " + str(props['name']) + " [" + str(props['ip']) + "]" 1286 cmsg = "Client Connect: (" + str(props['id']) + ") " + str(props['name']) + " [" + str(props['ip']) + "]"
1287 self.log_msg(cmsg)
1288 cmsg = ("connect", props) #################################################
1360 self.log_msg(cmsg) 1289 self.log_msg(cmsg)
1361 1290
1362 # If already registered then re-register, thereby updating the Meta 1291 # If already registered then re-register, thereby updating the Meta
1363 # on the number of players 1292 # on the number of players
1364 if self.be_registered: 1293 if self.be_registered:
1862 # this line sends a handle role message to change the players role 1791 # this line sends a handle role message to change the players role
1863 self.send_player_list(from_id,group_id) 1792 self.send_player_list(from_id,group_id)
1864 1793
1865 #notify user about others in the room 1794 #notify user about others in the room
1866 self.return_room_roles(from_id,group_id) 1795 self.return_room_roles(from_id,group_id)
1867 self.log_msg(("join_group", (from_id, group_id))) 1796 self.log_msg(("join_group", (self.groups[group_id].name, group_id, from_id)))
1868 self.handle_role("set", from_id, self.players[from_id].role, self.groups[group_id].boot_pwd, group_id) 1797 self.handle_role("set", from_id, self.players[from_id].role, self.groups[group_id].boot_pwd, group_id)
1869 1798
1870 except Exception, e: 1799 except Exception, e:
1871 self.log_msg(str(e)) 1800 self.log_msg(str(e))
1872 1801
1885 # send them to players. Also note, both these methods have race 1814 # send them to players. Also note, both these methods have race
1886 # conditions written all over them. Ack! Ack! 1815 # conditions written all over them. Ack! Ack!
1887 def new_group( self, name, pwd, boot, minVersion, mapFile, messageFile, persist = 0, moderated=0 ): 1816 def new_group( self, name, pwd, boot, minVersion, mapFile, messageFile, persist = 0, moderated=0 ):
1888 group_id = str( self.next_group_id ) 1817 group_id = str( self.next_group_id )
1889 self.next_group_id += 1 1818 self.next_group_id += 1
1890
1891 self.groups[group_id] = game_group( group_id, name, pwd, "", boot, minVersion, mapFile, messageFile, persist ) 1819 self.groups[group_id] = game_group( group_id, name, pwd, "", boot, minVersion, mapFile, messageFile, persist )
1892 self.groups[group_id].moderated = moderated 1820 self.groups[group_id].moderated = moderated
1893 ins = "" 1821 ins = ""
1894 if persist !=0: ins="Persistant " 1822 if persist !=0: ins="Persistant "
1895 lmsg = "Creating " + ins + "Group... (" + str(group_id) + ") " + str(name) 1823 lmsg = "Creating " + ins + "Group... (" + str(group_id) + ") " + str(name)
1896 self.log_msg( lmsg ) 1824 self.log_msg( lmsg )
1825 self.log_msg(("create_group", (str(name), int(group_id), 0) )) ##-99 works, could be better.
1897 1826
1898 1827
1899 def change_group_name(self,gid,name,pid): 1828 def change_group_name(self,gid,name,pid):
1900 "Change the name of a group" 1829 "Change the name of a group"
1901 # Check for & in name. We want to allow this because of its common 1830 # Check for & in name. We want to allow this because of its common
2006 self.handle_role("set",from_id,"GM",boot_pwd, group_id) 1935 self.handle_role("set",from_id,"GM",boot_pwd, group_id)
2007 lmsg = "Creating Group... (" + str(group_id) + ") " + str(name) 1936 lmsg = "Creating Group... (" + str(group_id) + ") " + str(name)
2008 self.log_msg( lmsg ) 1937 self.log_msg( lmsg )
2009 jmsg = "moving to room " + str(group_id) + "." 1938 jmsg = "moving to room " + str(group_id) + "."
2010 self.log_msg( jmsg ) 1939 self.log_msg( jmsg )
1940 self.log_msg(("create_group", (str(name), group_id, from_id)))
2011 #even creators of the room should see the HTML --akoman 1941 #even creators of the room should see the HTML --akoman
2012 #edit: jan10/03 - was placed in the except statement. Silly me. 1942 #edit: jan10/03 - was placed in the except statement. Silly me.
2013 if self.defaultMessageFile != None: 1943 if self.defaultMessageFile != None:
2014 if self.defaultMessageFile[:4] == 'http': 1944 if self.defaultMessageFile[:4] == 'http':
2015 data = urllib.urlretrieve(self.defaultMessageFile) 1945 data = urllib.urlretrieve(self.defaultMessageFile)
2036 self.send_to_all("0",self.groups[group_id].toxml('update')) 1966 self.send_to_all("0",self.groups[group_id].toxml('update'))
2037 return #never remove lobby *sanity check* 1967 return #never remove lobby *sanity check*
2038 if not self.isPersistentRoom(group_id) and self.groups[group_id].get_num_players() == 0: 1968 if not self.isPersistentRoom(group_id) and self.groups[group_id].get_num_players() == 0:
2039 self.send_to_all("0",self.groups[group_id].toxml('del')) 1969 self.send_to_all("0",self.groups[group_id].toxml('del'))
2040 del self.groups[group_id] 1970 del self.groups[group_id]
2041 self.log_msg(("delete_group", (from_id, group_id))) 1971 self.log_msg(("delete_group", (group_id, from_id)))
2042 1972
2043 else: 1973 else:
2044 self.send_to_all("0",self.groups[group_id].toxml('update')) 1974 self.send_to_all("0",self.groups[group_id].toxml('update'))
2045 1975
2046 #The register Rooms thread 1976 #The register Rooms thread
2054 dmsg = "Client Disconnect: (" + str(id) + ") " + str(self.players[id].name) 1984 dmsg = "Client Disconnect: (" + str(id) + ") " + str(self.players[id].name)
2055 self.players[id].disconnect() 1985 self.players[id].disconnect()
2056 self.groups[group_id].remove_player(id) 1986 self.groups[group_id].remove_player(id)
2057 del self.players[id] 1987 del self.players[id]
2058 self.log_msg(dmsg) 1988 self.log_msg(dmsg)
1989 self.log_msg(("disconnect",id))
2059 1990
2060 1991
2061 # If already registered then re-register, thereby updating the Meta 1992 # If already registered then re-register, thereby updating the Meta
2062 # on the number of players 1993 # on the number of players
2063 # Note: Upon server shutdown, the server is first unregistered, so 1994 # Note: Upon server shutdown, the server is first unregistered, so
2463 self.players[player].send(msg,player,group) 2394 self.players[player].send(msg,player,group)
2464 2395
2465 2396
2466 def send_to_all(self,from_id,data): 2397 def send_to_all(self,from_id,data):
2467 try: 2398 try:
2399 print data
2468 self.p_lock.acquire() 2400 self.p_lock.acquire()
2469 keys = self.players.keys() 2401 keys = self.players.keys()
2470 self.p_lock.release() 2402 self.p_lock.release()
2471 for k in keys: 2403 for k in keys:
2472 if k != from_id: 2404 if k != from_id:
2473 self.players[k].outbox.put(data) 2405 self.players[k].outbox.put(data)
2474 except Exception, e: 2406 except Exception, e:
2475 traceback.print_exc() 2407 traceback.print_exc()
2476 self.log_msg("Exception: send_to_all(): " + str(e)) 2408 self.log_msg("Exception: send_to_all(): " + str(e))
2477 2409
2478
2479
2480 def send_to_group(self, from_id, group_id, data): 2410 def send_to_group(self, from_id, group_id, data):
2481 data = ServerPlugins.postParseIncoming(data) 2411 msg = ("<msg to='all' from='0' group_id='"+group_id+"'><font color='#FF0000'>" + data + "</font>")
2482 try: 2412 #data = ServerPlugins.postParseIncoming(data)
2413 try:
2414 print data
2415 self.p_lock.acquire()
2483 keys = self.groups[group_id].get_player_ids() 2416 keys = self.groups[group_id].get_player_ids()
2417 self.p_lock.release()
2418 print keys
2484 for k in keys: 2419 for k in keys:
2485 if k != from_id: 2420 if k != from_id:
2486 self.players[k].outbox.put(data) 2421 self.players[k].outbox.put(msg)
2487 except Exception, e: 2422 except Exception, e:
2488 traceback.print_exc() 2423 traceback.print_exc()
2489 self.log_msg("Exception: send_to_group(): " + str(e)) 2424 self.log_msg("Exception: send_to_group(): " + str(e))
2490 2425
2491 def send_player_list(self,to_id,group_id): 2426 def send_player_list(self,to_id,group_id):