Mercurial > traipse
comparison orpg/networking/meta_server_lib.py @ 28:ff154cf3350c ornery-orc
Traipse 'OpenRPG' {100203-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 (Stable)
New Features:
New Bookmarks Feature
New 'boot' command to remote admin
New confirmation window for sent nodes
Miniatures Layer pop up box allows users to turn off Mini labels, from
FlexiRPG
New Zoom Mouse plugin added
New Images added to Plugin UI
Switching to Element Tree
New Map efficiency, from FlexiRPG
New Status Bar to Update Manager
New TrueDebug Class in orpg_log (See documentation for usage)
New Portable Mercurial
New Tip of the Day, from Core and community
New Reference Syntax added for custom PC sheets
New Child Reference for gametree
New Parent Reference for gametree
New Gametree Recursion method, mapping, context sensitivity, and
effeciency..
New Features node with bonus nodes and Node Referencing help added
New Dieroller structure from Core
New DieRoller portability for odd Dice
New 7th Sea die roller; ie [7k3] = [7d10.takeHighest(3).open(10)]
New 'Mythos' System die roller added
New vs. die roller method for WoD; ie [3v3] = [3d10.vs(3)]. Included for
Mythos roller also
New Warhammer FRPG Die Roller (Special thanks to Puu-san for the
support)
New EZ_Tree Reference system. Push a button, Traipse the tree, get a
reference (Beta!)
New Grids act more like Spreadsheets in Use mode, with Auto Calc
Fixes:
Fix to allow for portability to an OpenSUSE linux OS
Fix to mplay_client for Fedora and OpenSUSE
Fix to Text based Server
Fix to Remote Admin Commands
Fix to Pretty Print, from Core
Fix to Splitter Nodes not being created
Fix to massive amounts of images loading, from Core
Fix to Map from gametree not showing to all clients
Fix to gametree about menus
Fix to Password Manager check on startup
Fix to PC Sheets from tool nodes. They now use the tabber_panel
Fix to Whiteboard ID to prevent random line or text deleting.
Fixes to Server, Remote Server, and Server GUI
Fix to Update Manager; cleaner clode for saved repositories
Fixes made to Settings Panel and now reactive settings when Ok is
pressed
Fixes to Alternity roller's attack roll. Uses a simple Tuple instead of
a Splice
Fix to Use panel of Forms and Tabbers. Now longer enters design mode
Fix made Image Fetching. New fetching image and new failed image
Fix to whiteboard ID's to prevent non updated clients from ruining the
fix.
default_manifest.xml renamed to default_upmana.xml
author | sirebral |
---|---|
date | Wed, 03 Feb 2010 22:16:49 -0600 |
parents | 97265586402b |
children | 8e77f169f324 |
comparison
equal
deleted
inserted
replaced
27:51428d30c59e | 28:ff154cf3350c |
---|---|
20 # | 20 # |
21 # File: meta_server_lib.py | 21 # File: meta_server_lib.py |
22 # Author: Chris Davis | 22 # Author: Chris Davis |
23 # Maintainer: | 23 # Maintainer: |
24 # Version: | 24 # Version: |
25 # $Id: meta_server_lib.py,v 1.40 2007/04/04 01:18:42 digitalxero Exp $ | 25 # $Id: meta_server_lib.py,v Traipse 'Ornery-Orc' prof.ebral Exp $ |
26 # | 26 # |
27 # Description: A collection of functions to communicate with the meta server. | 27 # Description: A collection of functions to communicate with the meta server. |
28 # | 28 # |
29 | 29 |
30 | 30 |
35 | 35 |
36 from orpg.orpg_version import PROTOCOL_VERSION | 36 from orpg.orpg_version import PROTOCOL_VERSION |
37 from orpg.orpgCore import component | 37 from orpg.orpgCore import component |
38 from orpg.tools.validate import validate | 38 from orpg.tools.validate import validate |
39 from orpg.dirpath import dir_struct | 39 from orpg.dirpath import dir_struct |
40 import urllib | 40 |
41 import orpg.minidom | 41 import urllib, time, sys, traceback, re |
42 | |
42 from threading import * | 43 from threading import * |
43 import time | 44 from random import uniform |
44 import sys | 45 from urllib import urlopen, urlencode |
45 import random | 46 from orpg.tools.orpg_log import debug |
46 import traceback | 47 |
47 import re | 48 from xml.etree.ElementTree import Element, fromstring |
48 | |
49 metacache_lock = RLock() | 49 metacache_lock = RLock() |
50 | 50 |
51 def get_server_dom(data=None,path=None): | 51 def get_server_dom(data=None,path=None, string=False): |
52 # post data at server and get the resulting DOM | 52 # post data at server and get the resulting DOM |
53 | |
54 if path == None: | 53 if path == None: |
55 # get meta server URI | 54 # get meta server URI |
56 path = getMetaServerBaseURL() | 55 path = getMetaServerBaseURL() |
57 | 56 |
58 # POST the data | 57 # POST the data |
60 print | 59 print |
61 print "Sending the following POST info to Meta at " + path + ":" | 60 print "Sending the following POST info to Meta at " + path + ":" |
62 print "==========================================" | 61 print "==========================================" |
63 print data | 62 print data |
64 print | 63 print |
65 file = urllib.urlopen(path, data) | 64 file = urlopen(path, data) |
66 data = file.read() | 65 data = file.read() |
67 file.close() | 66 file.close() |
68 | 67 |
69 # Remove any leading or trailing data. This can happen on some satellite connections | 68 # Remove any leading or trailing data. This can happen on some satellite connections |
70 p = re.compile('(<servers>.*?</servers>)',re.DOTALL|re.IGNORECASE) | 69 p = re.compile('(<servers>.*?</servers>)',re.DOTALL|re.IGNORECASE) |
76 print "Got this string from the Meta at " + path + ":" | 75 print "Got this string from the Meta at " + path + ":" |
77 print "===============================================" | 76 print "===============================================" |
78 print data | 77 print data |
79 print | 78 print |
80 # build dom | 79 # build dom |
81 xml = component.get('xml') | 80 etreeEl = data |
82 xml_dom = xml.parseXml(data) | 81 if not string: return fromstring(etreeEl) |
83 xml_dom = xml_dom._get_documentElement() | 82 else: return etreeEl |
84 return xml_dom | 83 |
85 | 84 def post_server_data(name, realHostName=None): |
86 def post_server_data( name, realHostName=None): | 85 if realHostName: data = urlencode({"server_data[name]":name, |
87 if realHostName: | |
88 data = urllib.urlencode( {"server_data[name]":name, | |
89 "server_data[version]":PROTOCOL_VERSION, | 86 "server_data[version]":PROTOCOL_VERSION, |
90 "act":"new", | 87 "act":"new", |
91 "REMOTE_ADDR": realHostName } ) | 88 "REMOTE_ADDR": realHostName }) |
92 | 89 # print "Letting meta server decide the hostname to list..." |
93 else: | 90 else: data = 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, | 91 "server_data[version]":PROTOCOL_VERSION, |
97 "act":"new"} ) | 92 "act":"new"}) |
98 | 93 path = component.get('settings').get('MetaServerBaseURL') #getMetaServerBaseURL() |
99 #xml_dom = get_server_dom( data , "http://openrpg.sf.net/openrpg_servers.php")#Sourceforge still? | 94 etreeEl = get_server_dom(data, path) |
100 path = component.get('settings').get_setting('MetaServerBaseURL') #getMetaServerBaseURL() | 95 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 | 96 |
105 def post_failed_connection(id,meta=None,address=None,port=None): | 97 def post_failed_connection(id,meta=None,address=None,port=None): |
106 # For now, turning this off. This needs to be re-vamped for | 98 # For now, turning this off. This needs to be re-vamped for |
107 # handling multiple Metas. | 99 # handling multiple Metas. |
108 return 0 | 100 return 0 |
109 #data = urllib.urlencode({"id":id,"act":"failed"}); | 101 #data = urlencode({"id":id,"act":"failed"}); |
110 #xml_dom = get_server_dom(data) | 102 #xml_dom = get_server_dom(data) |
111 #ret_val = int(xml_dom.getAttribute("return")) | 103 #ret_val = int(xml_dom.getAttribute("return")) |
112 #return ret_val | 104 #return ret_val |
113 | 105 |
114 def remove_server(id): | 106 def remove_server(id): |
115 data = urllib.urlencode({"id":id,"act":"del"}); | 107 data = urlencode({"id":id,"act":"del"}); |
116 xml_dom = get_server_dom(data) | 108 etreeEl = get_server_dom(data) |
117 ret_val = int(xml_dom.getAttribute("return")) | 109 return int(etreeEl.get("return")) |
118 return ret_val | 110 |
119 | 111 def byStartAttribute(first, second): |
120 | 112 # This function is used to easily sort a list of nodes by their start time |
121 def byStartAttribute(first,second): | 113 # Ensure there is something to sort with for each |
122 # This function is used to easily sort a list of nodes | 114 |
123 # by their start time | 115 first_start = int(first.get('start')) or 0 |
124 | 116 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 | 117 |
131 # Return the result of the cmp function on the two strings | 118 # Return the result of the cmp function on the two strings |
132 return cmp(first_start,second_start) | 119 return cmp(first_start, second_start) |
133 | 120 |
134 def byNameAttribute(first,second): | 121 def byNameAttribute(first, second): |
135 # This function is used to easily sort a list of nodes | 122 # 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 | 123 # Ensure there is something to sort with for each |
139 | 124 |
140 if first.hasAttribute("name"): first_name = str(first.getAttribute("name")).lower() | 125 first_name = first.get('name') or '' |
141 else: first_name = "" | 126 second_name = second.get('name') or '' |
142 | 127 |
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 | 128 # Return the result of the cmp function on the two strings |
147 return cmp(first_name,second_name) | 129 return cmp(first_name,second_name) |
148 | 130 |
149 | 131 |
150 def get_server_list(versions = None,sort_by="start"): | 132 def get_server_list(versions = None, sort_by="start"): |
151 data = urllib.urlencode({"version":PROTOCOL_VERSION,"ports":"%"}) | 133 data = urlencode({"version":PROTOCOL_VERSION,"ports":"%"}) |
152 all_metas = getMetaServers(versions,1) # get the list of metas | 134 all_metas = getMetaServers(versions, 1) # get the list of metas |
153 base_meta = getMetaServerBaseURL() | 135 base_meta = getMetaServerBaseURL() |
154 | 136 |
155 #all_metas.reverse() # The last one checked will take precedence, so reverse the order | 137 #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 | 138 # so that the top one on the actual list is checked last |
157 | 139 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 | 140 |
159 | 141 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 | 142 #get the server's xml from the current meta |
163 bad_meta = 0 | 143 bad_meta = 0 |
164 #print "Getting server list from " + meta + "..." | 144 #print "Getting server list from " + meta + "..." |
165 try: xml_dom = get_server_dom(data=data,path=meta) | 145 try: xml_dom = get_server_dom(data=data, path=meta) |
166 except: | 146 except: bad_meta = 1 #print "Trouble getting servers from " + meta + "..." |
167 #print "Trouble getting servers from " + meta + "..." | 147 if bad_meta: continue |
168 bad_meta = 1 | 148 if base_meta == meta: updateMetaCache(xml_dom) #print "This is our base meta: " + meta |
169 | 149 node_list = xml_dom.findall('server') |
170 if bad_meta: | 150 if len(node_list): # if there are entries in the node list |
171 continue | 151 # 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 | 152 |
182 # for each node found, we're going to check the nodes from prior | 153 # 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. | 154 # metas in the list. If a match is found, then use the new values. |
184 for n in node_list: | 155 for n in node_list: |
185 | |
186 # set them from current node | 156 # set them from current node |
187 | 157 if not n.get('name'): n.set('name','NO_NAME_GIVEN') |
188 if not n.hasAttribute('name'): n.setAttribute('name','NO_NAME_GIVEN') | 158 name = n.get('name') |
189 name = n.getAttribute('name') | 159 if not n.get('num_users'): n.set('num_users','N/A') |
190 if not n.hasAttribute('num_users'): n.setAttribute('num_users','N/A') | 160 num_users = n.get('num_users') |
191 num_users = n.getAttribute('num_users') | 161 if not n.get('address'): n.set('address','NO_ADDRESS_GIVEN') |
192 if not n.hasAttribute('address'): n.setAttribute('address','NO_ADDRESS_GIVEN') | 162 address = n.get('address') |
193 address = n.getAttribute('address') | 163 if not n.get('port'): n.set('port','6774') |
194 if not n.hasAttribute('port'): n.setAttribute('port','6774') | 164 port = n.get('port') |
195 port = n.getAttribute('port') | 165 n.set('meta',meta) |
196 n.setAttribute('meta',meta) | |
197 end_point = str(address) + ":" + str(port) | 166 end_point = str(address) + ":" + str(port) |
198 if return_hash.has_key(end_point): | 167 if return_hash.has_key(end_point): |
199 if META_DEBUG: print "Replacing duplicate server entry at " + end_point | 168 if META_DEBUG: print "Replacing duplicate server entry at " + end_point |
200 return_hash[end_point] = n | 169 return_hash[end_point] = n |
201 | 170 |
202 # At this point, we have an amalgamated list of servers | 171 # At this point, we have an amalgamated list of servers |
203 # Now, we have to construct a new DOM to pass back. | 172 # Now, we have to construct a new DOM to pass back. |
204 | 173 |
205 # Create a servers element | 174 # Create a servers element |
206 return_dom = orpg.minidom.Element("servers") | 175 server_list = Element('servers') |
207 | 176 |
208 # get the nodes stored in return_hash | 177 # get the nodes stored in return_hash |
209 return_list = return_hash.values() | 178 sort_list = return_hash.values() |
210 | 179 |
211 # sort them by their name attribute. Uses byNameAttribute() | 180 # sort them by their name attribute. Uses byNameAttribute() |
212 # defined above as a comparison function | 181 # defined above as a comparison function |
213 | 182 if sort_by == "start": sort_list.sort(byStartAttribute) |
214 if sort_by == "start": return_list.sort(byStartAttribute) | 183 elif sort_by == "name": sort_list.sort(byNameAttribute) |
215 elif sort_by == "name": return_list.sort(byNameAttribute) | |
216 | 184 |
217 # Add each node to the DOM | 185 # Add each node to the DOM |
218 for n in return_list: return_dom.appendChild(n) | 186 for n in sort_list: server_list.append(n) |
219 return return_dom | 187 return server_list |
220 | 188 |
221 ## List Format: | 189 ## List Format: |
222 ## <servers> | 190 ## <servers> |
223 ## <server address=? id=? name=? failed_count=? > | 191 ## <server address=? id=? name=? failed_count=? > |
224 ## </servers> | 192 ## </servers> |
225 | 193 |
226 def updateMetaCache(xml_dom): | 194 def updateMetaCache(xml_dom): |
227 try: | 195 try: |
228 if META_DEBUG: print "Updating Meta Server Cache" | 196 if META_DEBUG: print "Updating Meta Server Cache" |
229 metaservers = xml_dom.getElementsByTagName( 'metaservers' ) # pull out the metaservers bit | 197 metaservers = xml_dom.findall('metaservers') # pull out the metaservers bit |
230 if len(metaservers) == 0: | 198 if len(metaservers) == 0: |
231 cmetalist = getRawMetaList() | 199 cmetalist = getRawMetaList() |
232 xml_dom = get_server_dom(cmetalist[0]) | 200 xml_dom = get_server_dom(cmetalist[0]) |
233 metaservers = xml_dom.getElementsByTagName( 'metaservers' ) | 201 metaservers = xml_dom.findall('metaservers') |
234 authoritative = metaservers[0].getAttribute('auth') | 202 authoritative = metaservers[0].get('auth') |
235 if META_DEBUG: print " Authoritive Meta: "+str(authoritative) | 203 if META_DEBUG: print " Authoritive Meta: "+str(authoritative) |
236 metas = metaservers[0].getElementsByTagName("meta") # get the list of metas | 204 metas = metaservers[0].findall("meta") # get the list of metas |
237 if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)" | 205 if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)" |
238 try: | 206 try: |
239 metacache_lock.acquire() | 207 metacache_lock.acquire() |
240 ini = open(dir_struct["user"]+"metaservers.cache","w") | 208 ini = open(dir_struct["user"]+"metaservers.cache","w") |
241 for meta in metas: | 209 for meta in metas: |
242 if META_DEBUG: print " Writing: "+str(meta.getAttribute('path')) | 210 if META_DEBUG: print " Writing: "+str(meta.get('path')) |
243 ini.write(str(meta.getAttribute('path')) + " " + str(meta.getAttribute('versions')) + "\n") | 211 ini.write(str(meta.get('path')) + " " + str(meta.get('versions')) + "\n") |
244 ini.close() | 212 ini.close() |
245 finally: | 213 finally: |
246 metacache_lock.release() | 214 metacache_lock.release() |
247 except Exception, e: | 215 except Exception, e: |
248 if META_DEBUG: traceback.print_exc() | 216 if META_DEBUG: traceback.print_exc() |
249 print "Meta Server Lib: UpdateMetaCache(): " + str(e) | 217 print "Meta Server Lib: UpdateMetaCache(): " + str(e) |
250 | 218 |
251 def getRawMetaList(): | 219 def getRawMetaList(path=None): |
220 ### Alpha ### | |
221 """This code will allow for a list of metas to be created. Future developement will more integrate the list of metas""" | |
222 if path != None: | |
223 metas = [] | |
224 data = urlencode({"version":PROTOCOL_VERSION,"ports":"%"}) | |
225 xml_dom = get_server_dom(data, path) | |
226 node_list = fromstring(xml_dom).findall('meta_server') | |
227 if len(node_list): | |
228 for n in node_list: | |
229 metas.append(n.get('path')) | |
230 return metas | |
252 try: | 231 try: |
253 try: | 232 try: |
254 metacache_lock.acquire() | 233 metacache_lock.acquire() |
255 # Read in the metas | 234 # Read in the metas |
256 validate.config_file("metaservers.cache","metaservers.cache") | 235 validate.config_file("metaservers.cache","metaservers.cache") |
266 return [] | 245 return [] |
267 | 246 |
268 def getMetaServers(versions = None, pick_random=0): | 247 def getMetaServers(versions = None, pick_random=0): |
269 """ | 248 """ |
270 get meta server URLs as a list | 249 get meta server URLs as a list |
271 | |
272 versions is a list of acceptable version numbers. | 250 versions is a list of acceptable version numbers. |
273 A False truth value will use getMetaServerBaseURL() | 251 A False truth value will use getMetaServerBaseURL() |
274 | |
275 set a default if we have weird reading problems | 252 set a default if we have weird reading problems |
276 default_url = "http://www.openrpg.com/openrpg_servers.php" | 253 default_url = "http://www.openrpg.com/openrpg_servers.php" |
277 """ | 254 """ |
278 | 255 |
256 ### Pre Alpha Design ### | |
257 """ 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 = [] | 258 meta_names = [] |
280 | |
281 if(versions): # If versions are supplied, then look in metaservers.conf | 259 if(versions): # If versions are supplied, then look in metaservers.conf |
282 try: | 260 try: |
283 """ | 261 """ |
284 read in the metas from file | 262 read in the metas from file |
285 format of file is one meta entry per line | 263 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 | 264 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 | 265 handle. Generally, this will be either a 1 for the original Meta format, or |
288 2 for the new one. | 266 2 for the new one. |
289 """ | 267 """ |
290 | |
291 # Read in the metas | 268 # Read in the metas |
269 #Adding a path object will attempt to look for a meta_network. | |
292 metas = getRawMetaList() | 270 metas = getRawMetaList() |
293 #print str(metas) | |
294 | 271 |
295 # go through each one to check if it should be returned, based on the | 272 # go through each one to check if it should be returned, based on the |
296 # version numbers allowed. | 273 # version numbers allowed. |
297 for meta in metas: | 274 for meta in metas: |
298 | |
299 # split the line on whitespace | 275 # split the line on whitespace |
300 # obviously, your meta servers urls shouldn't contain whitespace. duh. | 276 # obviously, your meta servers urls shouldn't contain whitespace. duh. |
301 words = meta.split() | 277 words = meta.split() |
302 success = 0 # init success flag for version check | 278 success = 0 # init success flag for version check |
303 for version in versions: # run through each allowed version from caller | 279 for version in versions: # run through each allowed version from caller |
314 # print "Warning!!\nNo valid metaservers cached." | 290 # print "Warning!!\nNo valid metaservers cached." |
315 # print "Using meta from MetaServerBaseURL: " + default_meta + "\n" | 291 # print "Using meta from MetaServerBaseURL: " + default_meta + "\n" |
316 # if we have more than one and want a random one | 292 # if we have more than one and want a random one |
317 elif pick_random: | 293 elif pick_random: |
318 if META_DEBUG: print "choosing random meta from: " + str(meta_names) | 294 if META_DEBUG: print "choosing random meta from: " + str(meta_names) |
319 i = int(random.uniform(0,len(meta_names))) | 295 i = int(uniform(0,len(meta_names))) |
320 #meta = meta_names[i] | 296 #meta = meta_names[i] |
321 meta_names = [meta_names[i]] | 297 meta_names = [meta_names[i]] |
322 if META_DEBUG: print "using: " + str(meta_names) | 298 if META_DEBUG: print "using: " + str(meta_names) |
323 else: | 299 else: |
324 if META_DEBUG: print "using all metas: " + str(meta_names) | 300 if META_DEBUG: print "using all metas: " + str(meta_names) |
345 tree = xml.parseXml(txt)._get_documentElement() | 321 tree = xml.parseXml(txt)._get_documentElement() |
346 ini.close() | 322 ini.close() |
347 node_list = tree.getElementsByTagName("MetaServerBaseURL") | 323 node_list = tree.getElementsByTagName("MetaServerBaseURL") |
348 if node_list: | 324 if node_list: |
349 url = node_list[0].getAttribute("value") | 325 url = node_list[0].getAttribute("value") |
350 | |
351 # allow tree to be collected | 326 # allow tree to be collected |
352 try: tree.unlink() | 327 try: tree.unlink() |
353 except: pass | 328 except: pass |
354 | 329 |
355 except Exception,e: | 330 except Exception,e: |
389 Because of this fact, there are some methods from wxThread | 364 Because of this fact, there are some methods from wxThread |
390 that I implemented to minimize changes to the code I had | 365 that I implemented to minimize changes to the code I had |
391 just written, i.e. TestDeleteStatus() and Delete() | 366 just written, i.e. TestDeleteStatus() and Delete() |
392 """ | 367 """ |
393 | 368 |
394 def __init__(self,name=None,realHostName=None,num_users = "Hmmm",MetaPath=None,port=6774,register_callback=None): | 369 def __init__(self, name=None, realHostName=None, num_users="0", |
395 | 370 MetaPath=None, port=6774, register_callback=None): |
396 Thread.__init__(self,name="registerThread") | 371 Thread.__init__(self, name="registerThread") |
397 self.rlock = RLock() # Re-entrant lock used to make this class thread safe | 372 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 | 373 self.die_event = Event() # The main loop in run() will wait with timeout on this |
399 if name: | 374 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 | 375 # But use Unnamed Server if for some crazy reason |
401 else: | 376 # no name is passed to the constructor |
402 self.name = "Unnamed server" # But use this if for some crazy reason no name is | 377 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 | 378 self.realHostName = realHostName # Name to advertise for connection |
406 self.id = "0" # id returned from Meta. Defaults to "0", which | 379 self.id = "0" # id returned from Meta. Defaults to "0", which |
407 # indicates a new registration. | 380 # indicates a new registration. |
408 self.cookie = "0" # cookie returned from Meta. Defaults to "0",which | 381 self.cookie = "0" # cookie returned from Meta. Defaults to "0", which |
409 # indicates a new registration. | 382 # indicates a new registration. |
410 self.interval = 0 # interval returned from Meta. Is how often to | 383 self.interval = 0 # interval returned from Meta. Is how often to |
411 # re-register, in minutes. | 384 # re-register, in minutes. |
412 self.destroy = 0 # Used to flag that this thread should die | 385 self.destroy = 0 # Used to flag that this thread should die |
413 self.port = str(port) | 386 self.port = str(port) |
420 | 393 |
421 Also, if MetaPath is specified, then use that. Makes | 394 Also, if MetaPath is specified, then use that. Makes |
422 it easier to have multiple registerThreads going to keep the server registered | 395 it easier to have multiple registerThreads going to keep the server registered |
423 on multiple (compatible) Metas. | 396 on multiple (compatible) Metas. |
424 """ | 397 """ |
425 | 398 if MetaPath == None: self.path = getMetaServerBaseURL() # Do this if no Meta specified |
426 if MetaPath == None: | 399 else: self.path = MetaPath |
427 self.path = getMetaServerBaseURL() # Do this if no Meta specified | |
428 else: | |
429 self.path = MetaPath | |
430 | 400 |
431 def getIdAndCookie(self): | 401 def getIdAndCookie(self): |
432 return self.id, self.cookie | 402 return self.id, self.cookie |
433 | 403 |
434 def TestDeleteStatus(self): | 404 def TestDeleteStatus(self): |
435 try: | 405 try: |
436 self.rlock.acquire() | 406 self.rlock.acquire() |
437 return self.die_event.isSet() | 407 return self.die_event.isSet() |
438 finally: | 408 finally: self.rlock.release() |
439 self.rlock.release() | |
440 | 409 |
441 def Delete(self): | 410 def Delete(self): |
442 try: | 411 try: |
443 self.rlock.acquire() | 412 self.rlock.acquire() |
444 self.die_event.set() | 413 self.die_event.set() |
445 finally: | 414 finally: self.rlock.release() |
446 self.rlock.release() | |
447 | 415 |
448 def run(self): | 416 def run(self): |
449 """ | 417 """ |
450 This method gets called by Thread implementation | 418 This method gets called by Thread implementation |
451 when self.start() is called to begin the thread's | 419 when self.start() is called to begin the thread's |
453 | 421 |
454 We will basically enter a loop that continually | 422 We will basically enter a loop that continually |
455 re-registers this server and sleeps Interval | 423 re-registers this server and sleeps Interval |
456 minutes until the thread is ordered to die in place | 424 minutes until the thread is ordered to die in place |
457 """ | 425 """ |
458 while(not self.TestDeleteStatus()): # Loop while until told to die | 426 while(not self.TestDeleteStatus()): # Loop while until told to die |
459 # Otherwise, call thread safe register(). | 427 # Otherwise, call thread safe register(). |
460 self.register(self.name, self.realHostName, self.num_users) | 428 self.register(self.name, self.realHostName, self.num_users) |
461 if META_DEBUG: print "Sent Registration Data" | 429 if META_DEBUG: print "Sent Registration Data" |
462 # register() will end up setting the state variables | 430 # register() will end up setting the state variables |
463 # for us, including self.interval. | 431 # for us, including self.interval. |
464 try: | 432 try: |
465 self.rlock.acquire() # Serialize access to this state information | 433 self.rlock.acquire() # Serialize access to this state information |
466 | 434 |
467 if self.interval >= 3: # If the number of minutes is one or greater | 435 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 | 436 self.interval -= 1 # wake up with 30 seconds left to re-register |
469 else: | 437 else: |
470 self.interval = .5 # Otherwise, we probably experienced some kind | 438 self.interval = .5 # Otherwise, we probably experienced some kind |
471 # of error from the Meta in register(). Sleep | 439 # of error from the Meta in register(). Sleep |
472 # for 6 seconds and start from scratch. | 440 # for 6 seconds and start from scratch. |
473 | 441 |
474 finally: # no matter what, release the lock | 442 finally: self.rlock.release() # no matter what, release the lock |
475 self.rlock.release() | |
476 # Wait interval minutes for a command to die | 443 # Wait interval minutes for a command to die |
477 die_signal = self.die_event.wait(self.interval*60) | 444 die_signal = self.die_event.wait(self.interval*60) |
478 | 445 |
479 # If we get past the while loop, it's because we've been asked to die, | 446 # 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 | 447 # so just let run() end. Once this occurs, the thread is dead and |
499 try: | 466 try: |
500 self.rlock.acquire() | 467 self.rlock.acquire() |
501 if not self.isAlive(): # check to see if this thread is dead | 468 if not self.isAlive(): # check to see if this thread is dead |
502 return 1 # If so, return an error result | 469 return 1 # If so, return an error result |
503 # Do the actual unregistering here | 470 # Do the actual unregistering here |
504 data = urllib.urlencode( {"server_data[id]":self.id, | 471 data = urlencode( {"server_data[id]":self.id, |
505 "server_data[cookie]":self.cookie, | 472 "server_data[cookie]":self.cookie, |
506 "server_data[version]":PROTOCOL_VERSION, | 473 "server_data[version]":PROTOCOL_VERSION, |
507 "act":"unregister"} ) | 474 "act":"unregister"} ) |
508 try: | 475 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 | 476 xml_dom = get_server_dom(data=data, path=self.path) |
510 if xml_dom.hasAttribute("errmsg"): | 477 if xml_dom.get("errmsg"): |
511 print "Error durring unregistration: " + xml_dom.getAttribute("errmsg") | 478 print "Error durring unregistration: " + xml_dom.get("errmsg") |
512 except: | 479 except: |
513 if META_DEBUG: print "Problem talking to Meta. Will go ahead and die, letting Meta remove us." | 480 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 | 481 # If there's an error, echo it to the console |
515 | 482 |
516 # No special handling is required. If the de-registration worked we're done. If | 483 # No special handling is required. If the de-registration worked we're done. If |
543 if name: self.name = name | 510 if name: self.name = name |
544 if num_users != None: self.num_users = num_users | 511 if num_users != None: self.num_users = num_users |
545 if realHostName: self.realHostName = realHostName | 512 if realHostName: self.realHostName = realHostName |
546 # build POST data | 513 # build POST data |
547 if self.realHostName: | 514 if self.realHostName: |
548 data = urllib.urlencode( {"server_data[id]":self.id, | 515 data = urlencode( {"server_data[id]":self.id, |
549 "server_data[cookie]":self.cookie, | 516 "server_data[cookie]":self.cookie, |
550 "server_data[name]":self.name, | 517 "server_data[name]":self.name, |
551 "server_data[port]":self.port, | 518 "server_data[port]":self.port, |
552 "server_data[version]":PROTOCOL_VERSION, | 519 "server_data[version]":PROTOCOL_VERSION, |
553 "server_data[num_users]":self.num_users, | 520 "server_data[num_users]":self.num_users, |
554 "act":"register", | 521 "act":"register", |
555 "server_data[address]": self.realHostName } ) | 522 "server_data[address]": self.realHostName } ) |
556 else: | 523 else: |
557 if META_DEBUG: print "Letting meta server decide the hostname to list..." | 524 if META_DEBUG: print "Letting meta server decide the hostname to list..." |
558 data = urllib.urlencode( {"server_data[id]":self.id, | 525 data = urlencode( {"server_data[id]":self.id, |
559 "server_data[cookie]":self.cookie, | 526 "server_data[cookie]":self.cookie, |
560 "server_data[name]":self.name, | 527 "server_data[name]":self.name, |
561 "server_data[port]":self.port, | 528 "server_data[port]":self.port, |
562 "server_data[version]":PROTOCOL_VERSION, | 529 "server_data[version]":PROTOCOL_VERSION, |
563 "server_data[num_users]":self.num_users, | 530 "server_data[num_users]":self.num_users, |
564 "act":"register"} ) | 531 "act":"register"} ) |
565 try: | 532 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 | 533 etreeEl = get_server_dom(data=data, path=self.path) |
567 except: | 534 except: |
568 if META_DEBUG: print "Problem talking to server. Setting interval for retry ..." | 535 if META_DEBUG: print "Problem talking to server. Setting interval for retry ..." |
569 if META_DEBUG: print data | 536 if META_DEBUG: print data |
570 if META_DEBUG: print | 537 if META_DEBUG: print |
571 self.interval = 0 | 538 self.interval = 0 |
582 the main thread calls register(). | 549 the main thread calls register(). |
583 """ | 550 """ |
584 return 0 # indicates that it was okay to call, not that no errors occurred | 551 return 0 # indicates that it was okay to call, not that no errors occurred |
585 | 552 |
586 # If there is a DOM returned .... | 553 # If there is a DOM returned .... |
587 if xml_dom: | 554 if etreeEl: |
588 # If there's an error, echo it to the console | 555 # If there's an error, echo it to the console |
589 if xml_dom.hasAttribute("errmsg"): | 556 if etreeEl.get("errmsg"): |
590 print "Error durring registration: " + xml_dom.getAttribute("errmsg") | 557 print "Error durring registration: " + etreeEl.get("errmsg") |
591 if META_DEBUG: print data | 558 if META_DEBUG: print data |
592 if META_DEBUG: print | 559 if META_DEBUG: print |
593 """ | 560 """ |
594 No special handling is required. If the registration worked, id, cookie, and interval | 561 No special handling is required. If the registration worked, id, cookie, and interval |
595 can be stored and used for the next time. | 562 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 | 574 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. | 575 to 6 seconds for the next retry. |
609 Is it wrong to have a method where there's more comments than code? :) | 576 Is it wrong to have a method where there's more comments than code? :) |
610 """ | 577 """ |
611 try: | 578 try: |
612 self.interval = int(xml_dom.getAttribute("interval")) | 579 self.interval = int(etreeEl.get("interval")) |
613 self.id = xml_dom.getAttribute("id") | 580 self.id = etreeEl.get("id") |
614 self.cookie = xml_dom.getAttribute("cookie") | 581 self.cookie = etreeEl.get("cookie") |
615 if not xml_dom.hasAttribute("errmsg"): | 582 if not etreeEl.get("errmsg"): updateMetaCache(xml_dom) |
616 updateMetaCache(xml_dom) | |
617 except: | 583 except: |
618 if META_DEBUG: print | 584 if META_DEBUG: print |
619 if META_DEBUG: print "OOPS! Is the Meta okay? It should be returning an id, cookie, and interval." | 585 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" | 586 if META_DEBUG: print "Check to see what it really returned.\n" |
621 # Let xml_dom get garbage collected | 587 # Let xml_dom get garbage collected |
622 try: | 588 try: xml_dom.unlink() |
623 xml_dom.unlink() | 589 except: pass |
624 except: | |
625 pass | |
626 else: # else if no DOM is returned from get_server_dom() | 590 else: # else if no DOM is returned from get_server_dom() |
627 print "Error - no DOM constructed from Meta message!" | 591 print "Error - no DOM constructed from Meta message!" |
628 return 0 # Let caller know it was okay to call us | 592 return 0 # Let caller know it was okay to call us |
629 finally: | 593 finally: self.rlock.release() |
630 self.rlock.release() | |
631 # End of class registerThread | 594 # End of class registerThread |
632 ################################################################################ | 595 ################################################################################ |