comparison orpg/networking/meta_server_lib.py @ 119:9314d63c0941 alpha

Traipse Alpha 'OpenRPG' {091029-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: Adds Bookmarks (Alpha) with cool Smiley Star and Plus Symbol images! Changes made to the map for increased portability. SnowDog has changes planned in Core, though. Added an initial push to the BCG. Not much to see, just shows off how it is re-writing Main code. Fix to remote admin commands Minor fix to texted based server, works in /System/ folder Some Core changes to gametree to correctly disply Pretty Print, thanks David! Fix to Splitter Nodes not being created. Added images to Plugin Control panel for Autostart feature Fix to massive amounts of images loading; from Core fix to gsclient so with_statement imports Added 'boot' command to remote admin Prep work in Pass tool for remote admin rankings and different passwords, ei, Server, Admin, Moderator, etc. Remote Admin Commands more organized, more prep work. Added Confirmation window for sent nodes. Minor changes to allow for portability to an OpenSUSE linux OS (hopefully without breaking) {091028} 00: Made changes to gametree to start working with Element Tree, mostly from Core Minor changes to Map to start working with Element Tree, from Core Preliminary changes to map efficiency, from FlexiRPG Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG Changes to main.py to start working with Element Tree {091029} 00: Changes made to server to start working with Element Tree. Changes made to Meta Server Lib. Prepping test work for a multi meta network page. Minor bug fixed with mini to gametree Zoom Mouse plugin added. Known Issue: Disconnecting causes an server side error. XML data is not being passed correctly.
author sirebral
date Thu, 29 Oct 2009 20:35:28 -0500
parents 65c1604e7949
children 36919b8a3ef9
comparison
equal deleted inserted replaced
118:217fb049bd00 119:9314d63c0941
44 import sys 44 import sys
45 import random 45 import random
46 import traceback 46 import traceback
47 import re 47 import re
48 48
49 from xml.etree.ElementTree import ElementTree, Element, iselement
50 from xml.etree.ElementTree import fromstring, tostring
51
49 metacache_lock = RLock() 52 metacache_lock = RLock()
50 53
51 def get_server_dom(data=None,path=None): 54 def get_server_dom(data=None,path=None):
52 # post data at server and get the resulting DOM 55 # post data at server and get the resulting DOM
53 56
76 print "Got this string from the Meta at " + path + ":" 79 print "Got this string from the Meta at " + path + ":"
77 print "===============================================" 80 print "==============================================="
78 print data 81 print data
79 print 82 print
80 # build dom 83 # build dom
81 xml = component.get('xml') 84 etreeEl = data
82 xml_dom = xml.parseXml(data) 85 return etreeEl
83 xml_dom = xml_dom._get_documentElement() 86
84 return xml_dom 87 def post_server_data(name, realHostName=None):
85 88 if realHostName: data = urllib.urlencode({"server_data[name]":name,
86 def post_server_data( name, realHostName=None):
87 if realHostName:
88 data = urllib.urlencode( {"server_data[name]":name,
89 "server_data[version]":PROTOCOL_VERSION, 89 "server_data[version]":PROTOCOL_VERSION,
90 "act":"new", 90 "act":"new",
91 "REMOTE_ADDR": realHostName } ) 91 "REMOTE_ADDR": realHostName })
92 92 # print "Letting meta server decide the hostname to list..."
93 else: 93 else: data = urllib.urlencode({"server_data[name]":name,
94 #print "Letting meta server decide the hostname to list..."
95 data = urllib.urlencode( {"server_data[name]":name,
96 "server_data[version]":PROTOCOL_VERSION, 94 "server_data[version]":PROTOCOL_VERSION,
97 "act":"new"} ) 95 "act":"new"})
98 96 path = component.get('settings').get('MetaServerBaseURL') #getMetaServerBaseURL()
99 #xml_dom = get_server_dom( data , "http://openrpg.sf.net/openrpg_servers.php")#Sourceforge still? 97 etreeEl = get_server_dom(data, path)
100 path = component.get('settings').get_setting('MetaServerBaseURL') #getMetaServerBaseURL() 98 return int(etreeEl.get('id'))
101 xml_dom = get_server_dom(data, path)
102 ret_val = int( xml_dom.getAttribute( "id" ) )
103 return ret_val
104 99
105 def post_failed_connection(id,meta=None,address=None,port=None): 100 def post_failed_connection(id,meta=None,address=None,port=None):
106 # For now, turning this off. This needs to be re-vamped for 101 # For now, turning this off. This needs to be re-vamped for
107 # handling multiple Metas. 102 # handling multiple Metas.
108 return 0 103 return 0
111 #ret_val = int(xml_dom.getAttribute("return")) 106 #ret_val = int(xml_dom.getAttribute("return"))
112 #return ret_val 107 #return ret_val
113 108
114 def remove_server(id): 109 def remove_server(id):
115 data = urllib.urlencode({"id":id,"act":"del"}); 110 data = urllib.urlencode({"id":id,"act":"del"});
116 xml_dom = get_server_dom(data) 111 etreeEl = get_server_dom(data)
117 ret_val = int(xml_dom.getAttribute("return")) 112 return int(etreeEl.get("return"))
118 return ret_val 113
119 114 def byStartAttribute(first, second):
120 115 # This function is used to easily sort a list of nodes by their start time
121 def byStartAttribute(first,second): 116 # Ensure there is something to sort with for each
122 # This function is used to easily sort a list of nodes 117
123 # by their start time 118 first_start = int(first.get('start')) or 0
124 119 second_start = int(second.get('start')) or 0
125 if first.hasAttribute("start"): first_start = int(first.getAttribute("start"))
126 else: first_start = 0
127
128 if second.hasAttribute("start"): second_start = int(second.getAttribute("start"))
129 else: second_start = 0
130 120
131 # Return the result of the cmp function on the two strings 121 # Return the result of the cmp function on the two strings
132 return cmp(first_start,second_start) 122 return cmp(first_start, second_start)
133 123
134 def byNameAttribute(first,second): 124 def byNameAttribute(first, second):
135 # This function is used to easily sort a list of nodes 125 # This function is used to easily sort a list of nodes by their name attribute
136 # by their name attribute
137
138 # Ensure there is something to sort with for each 126 # Ensure there is something to sort with for each
139 127
140 if first.hasAttribute("name"): first_name = str(first.getAttribute("name")).lower() 128 first_name = first.get('name') or ''
141 else: first_name = "" 129 second_name = second.get('name') or ''
142 130
143 if second.hasAttribute("name"): second_name = str(second.getAttribute("name")).lower()
144 else: second_name = ""
145
146 # Return the result of the cmp function on the two strings 131 # Return the result of the cmp function on the two strings
147 return cmp(first_name,second_name) 132 return cmp(first_name,second_name)
148 133
149 134
150 def get_server_list(versions = None,sort_by="start"): 135 def get_server_list(versions = None, sort_by="start"):
151 data = urllib.urlencode({"version":PROTOCOL_VERSION,"ports":"%"}) 136 data = urllib.urlencode({"version":PROTOCOL_VERSION,"ports":"%"})
152 all_metas = getMetaServers(versions,1) # get the list of metas 137 all_metas = getMetaServers(versions, 1) # get the list of metas
153 base_meta = getMetaServerBaseURL() 138 base_meta = getMetaServerBaseURL()
154 139
155 #all_metas.reverse() # The last one checked will take precedence, so reverse the order 140 #all_metas.reverse() # The last one checked will take precedence, so reverse the order
156 # so that the top one on the actual list is checked last 141 # so that the top one on the actual list is checked last
157 142 return_hash = {} # this will end up with an amalgamated list of servers
158 return_hash = {} # this will end up with an amalgamated list of servers 143
159 144 for meta in all_metas: # check all of the metas
160 for meta in all_metas: # check all of the metas
161
162 #get the server's xml from the current meta 145 #get the server's xml from the current meta
163 bad_meta = 0 146 bad_meta = 0
164 #print "Getting server list from " + meta + "..." 147 #print "Getting server list from " + meta + "..."
165 try: xml_dom = get_server_dom(data=data,path=meta) 148 try: xml_dom = get_server_dom(data=data, path=meta)
166 except: 149 except: bad_meta = 1 #print "Trouble getting servers from " + meta + "..."
167 #print "Trouble getting servers from " + meta + "..." 150 if bad_meta: continue
168 bad_meta = 1 151 if base_meta == meta: updateMetaCache(xml_dom) #print "This is our base meta: " + meta
169 152 node_list = fromstring(xml_dom).findall('server')
170 if bad_meta: 153 if len(node_list): # if there are entries in the node list
171 continue 154 # otherwise, just loop to next meta
172
173 if base_meta == meta:
174 #print "This is our base meta: " + meta
175 updateMetaCache(xml_dom)
176
177 node_list = xml_dom.getElementsByTagName('server')
178
179 if len(node_list): # if there are entries in the node list
180 # otherwise, just loop to next meta
181 155
182 # for each node found, we're going to check the nodes from prior 156 # for each node found, we're going to check the nodes from prior
183 # metas in the list. If a match is found, then use the new values. 157 # metas in the list. If a match is found, then use the new values.
184 for n in node_list: 158 for n in node_list:
185
186 # set them from current node 159 # set them from current node
187 160 if n.find('name') == None: n.set('name','NO_NAME_GIVEN')
188 if not n.hasAttribute('name'): n.setAttribute('name','NO_NAME_GIVEN') 161 name = n.get('name')
189 name = n.getAttribute('name') 162 if n.find('num_users') == None: n.set('num_users','N/A')
190 if not n.hasAttribute('num_users'): n.setAttribute('num_users','N/A') 163 num_users = n.get('num_users')
191 num_users = n.getAttribute('num_users') 164 if n.find('address') == None: n.set('address','NO_ADDRESS_GIVEN')
192 if not n.hasAttribute('address'): n.setAttribute('address','NO_ADDRESS_GIVEN') 165 address = n.get('address')
193 address = n.getAttribute('address') 166 if n.find('port') == None: n.set('port','6774')
194 if not n.hasAttribute('port'): n.setAttribute('port','6774') 167 port = n.get('port')
195 port = n.getAttribute('port') 168 n.set('meta',meta)
196 n.setAttribute('meta',meta)
197 end_point = str(address) + ":" + str(port) 169 end_point = str(address) + ":" + str(port)
198 if return_hash.has_key(end_point): 170 if return_hash.has_key(end_point):
199 if META_DEBUG: print "Replacing duplicate server entry at " + end_point 171 if META_DEBUG: print "Replacing duplicate server entry at " + end_point
200 return_hash[end_point] = n 172 return_hash[end_point] = n
201 173
202 # At this point, we have an amalgamated list of servers 174 # At this point, we have an amalgamated list of servers
203 # Now, we have to construct a new DOM to pass back. 175 # Now, we have to construct a new DOM to pass back.
204 176
205 # Create a servers element 177 # Create a servers element
206 return_dom = orpg.minidom.Element("servers") 178 server_list = Element('servers')
207 179
208 # get the nodes stored in return_hash 180 # get the nodes stored in return_hash
209 return_list = return_hash.values() 181 sort_list = return_hash.values()
210 182
211 # sort them by their name attribute. Uses byNameAttribute() 183 # sort them by their name attribute. Uses byNameAttribute()
212 # defined above as a comparison function 184 # defined above as a comparison function
213 185 if sort_by == "start": sort_list.sort(byStartAttribute)
214 if sort_by == "start": return_list.sort(byStartAttribute) 186 elif sort_by == "name": sort_list.sort(byNameAttribute)
215 elif sort_by == "name": return_list.sort(byNameAttribute)
216 187
217 # Add each node to the DOM 188 # Add each node to the DOM
218 for n in return_list: return_dom.appendChild(n) 189 for n in sort_list: server_list.append(n)
219 return return_dom 190 return server_list
220 191
221 ## List Format: 192 ## List Format:
222 ## <servers> 193 ## <servers>
223 ## <server address=? id=? name=? failed_count=? > 194 ## <server address=? id=? name=? failed_count=? >
224 ## </servers> 195 ## </servers>
225 196
226 def updateMetaCache(xml_dom): 197 def updateMetaCache(xml_dom):
227 try: 198 try:
228 if META_DEBUG: print "Updating Meta Server Cache" 199 if META_DEBUG: print "Updating Meta Server Cache"
229 metaservers = xml_dom.getElementsByTagName( 'metaservers' ) # pull out the metaservers bit 200 metaservers = xml_dom.findall('metaservers') # pull out the metaservers bit
230 if len(metaservers) == 0: 201 if len(metaservers) == 0:
231 cmetalist = getRawMetaList() 202 cmetalist = getRawMetaList()
232 xml_dom = get_server_dom(cmetalist[0]) 203 xml_dom = get_server_dom(cmetalist[0])
233 metaservers = xml_dom.getElementsByTagName( 'metaservers' ) 204 metaservers = xml_dom.findall('metaservers')
234 authoritative = metaservers[0].getAttribute('auth') 205 authoritative = metaservers[0].get('auth')
235 if META_DEBUG: print " Authoritive Meta: "+str(authoritative) 206 if META_DEBUG: print " Authoritive Meta: "+str(authoritative)
236 metas = metaservers[0].getElementsByTagName("meta") # get the list of metas 207 metas = metaservers[0].findall("meta") # get the list of metas
237 if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)" 208 if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)"
238 try: 209 try:
239 metacache_lock.acquire() 210 metacache_lock.acquire()
240 ini = open(dir_struct["user"]+"metaservers.cache","w") 211 ini = open(dir_struct["user"]+"metaservers.cache","w")
241 for meta in metas: 212 for meta in metas:
242 if META_DEBUG: print " Writing: "+str(meta.getAttribute('path')) 213 if META_DEBUG: print " Writing: "+str(meta.get('path'))
243 ini.write(str(meta.getAttribute('path')) + " " + str(meta.getAttribute('versions')) + "\n") 214 ini.write(str(meta.get('path')) + " " + str(meta.get('versions')) + "\n")
244 ini.close() 215 ini.close()
245 finally: 216 finally:
246 metacache_lock.release() 217 metacache_lock.release()
247 except Exception, e: 218 except Exception, e:
248 if META_DEBUG: traceback.print_exc() 219 if META_DEBUG: traceback.print_exc()
249 print "Meta Server Lib: UpdateMetaCache(): " + str(e) 220 print "Meta Server Lib: UpdateMetaCache(): " + str(e)
250 221
251 def getRawMetaList(): 222 def getRawMetaList(path=None):
223 ### Alpha ###
224 """This code will allow for a list of metas to be created. Future developement will more integrate the list of metas"""
225 if path != None:
226 metas = []
227 data = urllib.urlencode({"version":PROTOCOL_VERSION,"ports":"%"})
228 xml_dom = get_server_dom(data, path)
229 node_list = fromstring(xml_dom).findall('meta_server')
230 if len(node_list):
231 for n in node_list:
232 metas.append(n.get('path'))
233 return metas
252 try: 234 try:
253 try: 235 try:
254 metacache_lock.acquire() 236 metacache_lock.acquire()
255 # Read in the metas 237 # Read in the metas
256 validate.config_file("metaservers.cache","metaservers.cache") 238 validate.config_file("metaservers.cache","metaservers.cache")
266 return [] 248 return []
267 249
268 def getMetaServers(versions = None, pick_random=0): 250 def getMetaServers(versions = None, pick_random=0):
269 """ 251 """
270 get meta server URLs as a list 252 get meta server URLs as a list
271
272 versions is a list of acceptable version numbers. 253 versions is a list of acceptable version numbers.
273 A False truth value will use getMetaServerBaseURL() 254 A False truth value will use getMetaServerBaseURL()
274
275 set a default if we have weird reading problems 255 set a default if we have weird reading problems
276 default_url = "http://www.openrpg.com/openrpg_servers.php" 256 default_url = "http://www.openrpg.com/openrpg_servers.php"
277 """ 257 """
278 258
259 ### Pre Alpha Design ###
260 """ Here is how to handle Multiple Meta servers, and probably the best way to do it. Create an XML file that contains nodes with the various servers. Users will grab that meta data and have the option to connect to multiple meta servers which will allow them to find all the rooms. A check box should be used so if one server faile the users can continue without much lag. When creating a server hosts will need to select a meta to go too. This should be in the final of Ornery Orc."""
279 meta_names = [] 261 meta_names = []
280
281 if(versions): # If versions are supplied, then look in metaservers.conf 262 if(versions): # If versions are supplied, then look in metaservers.conf
282 try: 263 try:
283 """ 264 """
284 read in the metas from file 265 read in the metas from file
285 format of file is one meta entry per line 266 format of file is one meta entry per line
286 each entry will be the meta url, followed by one or more version numbers that it 267 each entry will be the meta url, followed by one or more version numbers that it
287 handle. Generally, this will be either a 1 for the original Meta format, or 268 handle. Generally, this will be either a 1 for the original Meta format, or
288 2 for the new one. 269 2 for the new one.
289 """ 270 """
290
291 # Read in the metas 271 # Read in the metas
272 #Adding a path object will attempt to look for a meta_network.
292 metas = getRawMetaList() 273 metas = getRawMetaList()
293 #print str(metas)
294 274
295 # go through each one to check if it should be returned, based on the 275 # go through each one to check if it should be returned, based on the
296 # version numbers allowed. 276 # version numbers allowed.
297 for meta in metas: 277 for meta in metas:
298
299 # split the line on whitespace 278 # split the line on whitespace
300 # obviously, your meta servers urls shouldn't contain whitespace. duh. 279 # obviously, your meta servers urls shouldn't contain whitespace. duh.
301 words = meta.split() 280 words = meta.split()
302 success = 0 # init success flag for version check 281 success = 0 # init success flag for version check
303 for version in versions: # run through each allowed version from caller 282 for version in versions: # run through each allowed version from caller
345 tree = xml.parseXml(txt)._get_documentElement() 324 tree = xml.parseXml(txt)._get_documentElement()
346 ini.close() 325 ini.close()
347 node_list = tree.getElementsByTagName("MetaServerBaseURL") 326 node_list = tree.getElementsByTagName("MetaServerBaseURL")
348 if node_list: 327 if node_list:
349 url = node_list[0].getAttribute("value") 328 url = node_list[0].getAttribute("value")
350
351 # allow tree to be collected 329 # allow tree to be collected
352 try: tree.unlink() 330 try: tree.unlink()
353 except: pass 331 except: pass
354 332
355 except Exception,e: 333 except Exception,e:
389 Because of this fact, there are some methods from wxThread 367 Because of this fact, there are some methods from wxThread
390 that I implemented to minimize changes to the code I had 368 that I implemented to minimize changes to the code I had
391 just written, i.e. TestDeleteStatus() and Delete() 369 just written, i.e. TestDeleteStatus() and Delete()
392 """ 370 """
393 371
394 def __init__(self,name=None,realHostName=None,num_users = "Hmmm",MetaPath=None,port=6774,register_callback=None): 372 def __init__(self, name=None, realHostName=None, num_users="0",
395 373 MetaPath=None, port=6774, register_callback=None):
396 Thread.__init__(self,name="registerThread") 374 Thread.__init__(self, name="registerThread")
397 self.rlock = RLock() # Re-entrant lock used to make this class thread safe 375 self.rlock = RLock() # Re-entrant lock used to make this class thread safe
398 self.die_event = Event() # The main loop in run() will wait with timeout on this 376 self.die_event = Event() # The main loop in run() will wait with timeout on this
399 if name: 377 self.name = name or 'Unnamed Server' # Name that the server want's displayed on the Meta
400 self.name = name # Name that the server want's displayed on the Meta 378 # But use Unnamed Server if for some crazy reason
401 else: 379 # no name is passed to the constructor
402 self.name = "Unnamed server" # But use this if for some crazy reason no name is 380 self.num_users = num_users # the number of users currently on this server
403 # passed to the constructor
404 self.num_users = num_users # the number of users currently on this server
405 self.realHostName = realHostName # Name to advertise for connection 381 self.realHostName = realHostName # Name to advertise for connection
406 self.id = "0" # id returned from Meta. Defaults to "0", which 382 self.id = "0" # id returned from Meta. Defaults to "0", which
407 # indicates a new registration. 383 # indicates a new registration.
408 self.cookie = "0" # cookie returned from Meta. Defaults to "0",which 384 self.cookie = "0" # cookie returned from Meta. Defaults to "0", which
409 # indicates a new registration. 385 # indicates a new registration.
410 self.interval = 0 # interval returned from Meta. Is how often to 386 self.interval = 0 # interval returned from Meta. Is how often to
411 # re-register, in minutes. 387 # re-register, in minutes.
412 self.destroy = 0 # Used to flag that this thread should die 388 self.destroy = 0 # Used to flag that this thread should die
413 self.port = str(port) 389 self.port = str(port)
420 396
421 Also, if MetaPath is specified, then use that. Makes 397 Also, if MetaPath is specified, then use that. Makes
422 it easier to have multiple registerThreads going to keep the server registered 398 it easier to have multiple registerThreads going to keep the server registered
423 on multiple (compatible) Metas. 399 on multiple (compatible) Metas.
424 """ 400 """
425 401 if MetaPath == None: self.path = getMetaServerBaseURL() # Do this if no Meta specified
426 if MetaPath == None: 402 else: self.path = MetaPath
427 self.path = getMetaServerBaseURL() # Do this if no Meta specified
428 else:
429 self.path = MetaPath
430 403
431 def getIdAndCookie(self): 404 def getIdAndCookie(self):
432 return self.id, self.cookie 405 return self.id, self.cookie
433 406
434 def TestDeleteStatus(self): 407 def TestDeleteStatus(self):
435 try: 408 try:
436 self.rlock.acquire() 409 self.rlock.acquire()
437 return self.die_event.isSet() 410 return self.die_event.isSet()
438 finally: 411 finally: self.rlock.release()
439 self.rlock.release()
440 412
441 def Delete(self): 413 def Delete(self):
442 try: 414 try:
443 self.rlock.acquire() 415 self.rlock.acquire()
444 self.die_event.set() 416 self.die_event.set()
445 finally: 417 finally: self.rlock.release()
446 self.rlock.release()
447 418
448 def run(self): 419 def run(self):
449 """ 420 """
450 This method gets called by Thread implementation 421 This method gets called by Thread implementation
451 when self.start() is called to begin the thread's 422 when self.start() is called to begin the thread's
453 424
454 We will basically enter a loop that continually 425 We will basically enter a loop that continually
455 re-registers this server and sleeps Interval 426 re-registers this server and sleeps Interval
456 minutes until the thread is ordered to die in place 427 minutes until the thread is ordered to die in place
457 """ 428 """
458 while(not self.TestDeleteStatus()): # Loop while until told to die 429 while(not self.TestDeleteStatus()): # Loop while until told to die
459 # Otherwise, call thread safe register(). 430 # Otherwise, call thread safe register().
460 self.register(self.name, self.realHostName, self.num_users) 431 self.register(self.name, self.realHostName, self.num_users)
461 if META_DEBUG: print "Sent Registration Data" 432 if META_DEBUG: print "Sent Registration Data"
462 # register() will end up setting the state variables 433 # register() will end up setting the state variables
463 # for us, including self.interval. 434 # for us, including self.interval.
464 try: 435 try:
465 self.rlock.acquire() # Serialize access to this state information 436 self.rlock.acquire() # Serialize access to this state information
466 437
467 if self.interval >= 3: # If the number of minutes is one or greater 438 if self.interval >= 3: # If the number of minutes is one or greater
468 self.interval -= 1 # wake up with 30 seconds left to re-register 439 self.interval -= 1 # wake up with 30 seconds left to re-register
469 else: 440 else:
470 self.interval = .5 # Otherwise, we probably experienced some kind 441 self.interval = .5 # Otherwise, we probably experienced some kind
471 # of error from the Meta in register(). Sleep 442 # of error from the Meta in register(). Sleep
472 # for 6 seconds and start from scratch. 443 # for 6 seconds and start from scratch.
473 444
474 finally: # no matter what, release the lock 445 finally: self.rlock.release() # no matter what, release the lock
475 self.rlock.release()
476 # Wait interval minutes for a command to die 446 # Wait interval minutes for a command to die
477 die_signal = self.die_event.wait(self.interval*60) 447 die_signal = self.die_event.wait(self.interval*60)
478 448
479 # If we get past the while loop, it's because we've been asked to die, 449 # If we get past the while loop, it's because we've been asked to die,
480 # so just let run() end. Once this occurs, the thread is dead and 450 # so just let run() end. Once this occurs, the thread is dead and
503 # Do the actual unregistering here 473 # Do the actual unregistering here
504 data = urllib.urlencode( {"server_data[id]":self.id, 474 data = urllib.urlencode( {"server_data[id]":self.id,
505 "server_data[cookie]":self.cookie, 475 "server_data[cookie]":self.cookie,
506 "server_data[version]":PROTOCOL_VERSION, 476 "server_data[version]":PROTOCOL_VERSION,
507 "act":"unregister"} ) 477 "act":"unregister"} )
508 try: 478 try: # this POSTS the request and returns the result
509 xml_dom = get_server_dom(data=data, path=self.path) # this POSTS the request and returns the result 479 xml_dom = get_server_dom(data=data, path=self.path)
510 if xml_dom.hasAttribute("errmsg"): 480 if xml_dom.hasAttribute("errmsg"):
511 print "Error durring unregistration: " + xml_dom.getAttribute("errmsg") 481 print "Error durring unregistration: " + xml_dom.get("errmsg")
512 except: 482 except:
513 if META_DEBUG: print "Problem talking to Meta. Will go ahead and die, letting Meta remove us." 483 if META_DEBUG: print "Problem talking to Meta. Will go ahead and die, letting Meta remove us."
514 # If there's an error, echo it to the console 484 # If there's an error, echo it to the console
515 485
516 # No special handling is required. If the de-registration worked we're done. If 486 # No special handling is required. If the de-registration worked we're done. If
560 "server_data[name]":self.name, 530 "server_data[name]":self.name,
561 "server_data[port]":self.port, 531 "server_data[port]":self.port,
562 "server_data[version]":PROTOCOL_VERSION, 532 "server_data[version]":PROTOCOL_VERSION,
563 "server_data[num_users]":self.num_users, 533 "server_data[num_users]":self.num_users,
564 "act":"register"} ) 534 "act":"register"} )
565 try: 535 try: # this POSTS the request and returns the result
566 xml_dom = get_server_dom(data=data,path=self.path) # this POSTS the request and returns the result 536 etreeEl = get_server_dom(data=data, path=self.path)
567 except: 537 except:
568 if META_DEBUG: print "Problem talking to server. Setting interval for retry ..." 538 if META_DEBUG: print "Problem talking to server. Setting interval for retry ..."
569 if META_DEBUG: print data 539 if META_DEBUG: print data
570 if META_DEBUG: print 540 if META_DEBUG: print
571 self.interval = 0 541 self.interval = 0
582 the main thread calls register(). 552 the main thread calls register().
583 """ 553 """
584 return 0 # indicates that it was okay to call, not that no errors occurred 554 return 0 # indicates that it was okay to call, not that no errors occurred
585 555
586 # If there is a DOM returned .... 556 # If there is a DOM returned ....
587 if xml_dom: 557 if etreeEl:
588 # If there's an error, echo it to the console 558 # If there's an error, echo it to the console
589 if xml_dom.hasAttribute("errmsg"): 559 if etreeEl.hasAttribute("errmsg"):
590 print "Error durring registration: " + xml_dom.getAttribute("errmsg") 560 print "Error durring registration: " + etreeEl.get("errmsg")
591 if META_DEBUG: print data 561 if META_DEBUG: print data
592 if META_DEBUG: print 562 if META_DEBUG: print
593 """ 563 """
594 No special handling is required. If the registration worked, id, cookie, and interval 564 No special handling is required. If the registration worked, id, cookie, and interval
595 can be stored and used for the next time. 565 can be stored and used for the next time.
607 the interval will be less than 1, and the main thread's while loop will reset it 577 the interval will be less than 1, and the main thread's while loop will reset it
608 to 6 seconds for the next retry. 578 to 6 seconds for the next retry.
609 Is it wrong to have a method where there's more comments than code? :) 579 Is it wrong to have a method where there's more comments than code? :)
610 """ 580 """
611 try: 581 try:
612 self.interval = int(xml_dom.getAttribute("interval")) 582 self.interval = int(etreeEl.get("interval"))
613 self.id = xml_dom.getAttribute("id") 583 self.id = etreeEl.get("id")
614 self.cookie = xml_dom.getAttribute("cookie") 584 self.cookie = etreeEl.get("cookie")
615 if not xml_dom.hasAttribute("errmsg"): 585 if not etreeEl.hasAttribute("errmsg"): updateMetaCache(xml_dom)
616 updateMetaCache(xml_dom)
617 except: 586 except:
618 if META_DEBUG: print 587 if META_DEBUG: print
619 if META_DEBUG: print "OOPS! Is the Meta okay? It should be returning an id, cookie, and interval." 588 if META_DEBUG: print "OOPS! Is the Meta okay? It should be returning an id, cookie, and interval."
620 if META_DEBUG: print "Check to see what it really returned.\n" 589 if META_DEBUG: print "Check to see what it really returned.\n"
621 # Let xml_dom get garbage collected 590 # Let xml_dom get garbage collected
622 try: 591 try: xml_dom.unlink()
623 xml_dom.unlink() 592 except: pass
624 except:
625 pass
626 else: # else if no DOM is returned from get_server_dom() 593 else: # else if no DOM is returned from get_server_dom()
627 print "Error - no DOM constructed from Meta message!" 594 print "Error - no DOM constructed from Meta message!"
628 return 0 # Let caller know it was okay to call us 595 return 0 # Let caller know it was okay to call us
629 finally: 596 finally: self.rlock.release()
630 self.rlock.release()
631 # End of class registerThread 597 # End of class registerThread
632 ################################################################################ 598 ################################################################################