Added the demo branch.
[krufty_fps.git] / server.py
blobc7889b2ee037eb6a3c9229b598cc032bb9ffdc4b
1 #!/usr/bin/python
3 import os, sys
4 from os.path import *
6 import threading
7 from socket import *
8 from xml.dom.minidom import parse, parseString
9 from threading import Lock
10 from signal import *
12 CONFIG = 'config.xml'
14 BROADCAST = 50030
15 MESSAGE = 40031
16 PASSWORD = "changethis"
17 NAME = "default"
19 BUFSIZE = 120
21 # this will change
23 SERVERREQUEST = "i_want_server"
24 SERVEROFFER = "Want_server?"
25 SERVERKILL = "DIE_server!!"
26 YOUTHERE = "you_there?"
27 IMHERE = "yeah,i'm_here"
28 WANTIN = "i_want_in"
29 YOUREIN = "urine"
30 IMOUT = "i_leave"
31 GETLIST = "get_list"
32 LIST = "peoples_on_server"
33 SOMEONEJOINED = "dude,someone_joined"
34 SOMEONELEFT = "someone_left"
35 YOUROUT = "get_lost_punk"
36 LETTER = "listen_to_me"
38 # end changes
40 TIMEOUT = .1
42 my_server = 0
44 class Server:
46 def __init__(self, config):
48 self.running = 1
50 self.outgoing = []
51 self.incoming = []
53 self.outgoing_lock = Lock()
54 self.incoming_lock = Lock()
56 self.broadcast = socket(AF_INET, SOCK_DGRAM)
57 self.message = socket(AF_INET, SOCK_DGRAM)
59 self.message_lock = Lock()
61 self.members = {}
63 self.configuration = config
65 if (config.has_key('broadcast')):
66 self.broadcast.bind(('', config['broadcast']))
67 else:
68 print "Server.__init__(): No broadcast socket number chosen, using", BROADCAST
69 self.broadcast.bind(('', BROADCAST))
71 if (config.has_key('message')):
72 self.message.bind(('', config['message']))
73 else:
74 print "Server.__init__(): No message socket number chosen, using", MESSAGE
75 self.message.bind(('', MESSAGE))
77 def receive(self):
79 print "Server.receive() beginning..."
81 self.message.settimeout(TIMEOUT)
83 while (self.running):
84 try:
85 self.message_lock.acquire()
86 data_in = self.message.recvfrom(BUFSIZE)
87 self.message_lock.release()
88 except:
89 data_in = ()
91 if (data_in != ()):
92 self.incoming_lock.acquire()
93 self.incoming.append(data_in)
94 print "Got data", data_in
95 self.incoming_lock.release()
97 return
99 def send(self):
101 print "Server.send() beginning..."
103 while (self.running):
105 if (len(self.outgoing)):
107 self.outgoing_lock.acquire()
108 print "Server.send(): Acquired outgoing_lock"
110 data_out = self.outgoing.pop(0)
112 self.outgoing_lock.release()
113 print "Server.send(): Released outgoing_lock"
115 self.message.sendto(data_out[0], data_out[1])
116 print "Server.send(): Sent data", data_out
117 return
119 def process_in(self):
121 print "Server.process_in() beginning..."
123 while (self.running):
125 if (len(self.incoming)):
126 # data in = ()
128 self.incoming_lock.acquire()
129 print "Server.process_in(): Acquired incoming_lock"
131 data_in = self.incoming.pop(0)
133 self.incoming_lock.release()
134 print "Server.process_in(): Released incoming_lock"
136 if (data_in[0][:len(WANTIN)] == WANTIN):
137 print "Server.process_in(): Received WANTIN"
139 response = [YOUREIN, data_in[1]]
141 self.outgoing_lock.acquire()
142 print "Server.process_in(): Acquired outgoing_lock"
144 self.outgoing.append(response)
146 self.outgoing_lock.release()
147 print "Server.process_in(): Released outgoing_lock"
149 self.members[data_in[0][len(WANTIN) + 1:]] = data_in[1]
151 if (data_in[0][:len(YOUTHERE)] == YOUTHERE):
152 print "Server.process_in(): Received YOUTHERE, responding with IMHERE"
154 response = [IMHERE, data_in[1]]
156 self.outgoing_lock.acquire()
157 print "Server.process_in(): Acquired outgoing_lock"
159 self.outgoing.append(response)
161 self.outgoing_lock.release()
162 print "Server.process_in(): Released outgoing_lock"
164 if (data_in[0][:len(IMOUT)] == IMOUT):
165 print "Server.process_in(): Received IMOUT, notifying clients"
167 response = []
168 name_to_delete = ''
170 for name, address in self.members.iteritems():
171 if (data_in[1] == address):
172 response[0] = SOMEONELEFT + " " + name
173 name_to_delete = name
175 if (name_to_delete != ''):
176 del self.members[name_to_delete]
178 for name, address in self.members.iteritems():
179 response[1] = address
181 self.outgoing_lock.acquire()
182 print "Server.process_in(): Acquired outgoing_lock"
184 self.outgoing.append(response)
186 self.outgoing_lock.release()
187 print "Server.process_in(): Released outgoing_lock"
189 if (data_in[0] == GETLIST):
190 print "Server.process_in(): Received GETLIST, responding with member list"
192 for name, address in self.members.iteritems():
193 if (address == data_in[1]):
194 response = []
196 response[0] = LIST + " "
197 response[1] = address
199 for iname, iaddress in self.members.iteritems():
200 if (iname != name):
201 response[0] = response[0] + iname + " "
203 self.outgoing_lock.acquire()
205 print "Server.process_in(): Acquired outgoing_lock"
207 self.outgoing.append(response)
209 self.outgoing_lock.release()
210 print "Server.process_in(): Released outgoing_lock"
212 if (data_in[0][:len(SERVERKILL)] == SERVERKILL):
213 print "Server.process_in(): Received SERVERKILL"
215 if (data_in[0][len(SERVERKILL) + 1:] == self.configuration['password']):
216 self.running = 0
218 if (data_in[0][:len(LETTER)] == LETTER):
219 print "Server.process_in(): Received LETTER"
221 responses = []
223 the_data = data_in[0]
224 it_is = ''
226 origin = ''
228 for name in self.members.keys():
229 if self.members[name] == data_in[1]:
230 origin = name
232 if origin != '':
234 response = [LETTER + ":" + origin + ":", []]
236 if the_data[len(LETTER):len(LETTER)+2] == '::':
238 it_is = the_data[the_data.find("::") + 2:]
239 response[0] += it_is
241 for name in self.members.keys():
243 if origin != name:
245 responses.append(response)
246 responses[-1][1] = self.members[name]
248 else:
250 it_is = the_data[the_data.find(":", the_data.find(":") + 1) + 1:]
251 response[0] += it_is
253 string_parts = the_data[the_data.find(":") + 1:
254 the_data.find(":", the_data.find(":") + 1)].split()
256 for dest in string_parts:
258 if self.members.has_key(dest):
260 responses.append(response)
261 responses[-1][1] = self.members[dest]
263 for response_i in responses:
265 self.outgoing_lock.acquire()
266 self.outgoing.append(response_i)
267 self.outgoing_lock.release()
269 return
271 def process_out(self):
273 print "Server.process_out(): Not implemented yet."
275 return
277 def broadcast_listen(self):
279 print "Listening on broadcast port:", self.configuration['broadcast']
281 broadcast_message = SERVEROFFER + " " + str(self.configuration['message'])
282 broadcast_message = broadcast_message + " " + self.configuration['name']
284 while (self.running):
285 data_in = self.broadcast.recvfrom(BUFSIZE)
287 if (data_in[0][0:len(SERVERREQUEST)] == SERVERREQUEST):
288 new_message = [broadcast_message]
289 new_message.append((data_in[1][0], int(data_in[0][len(SERVERREQUEST) + 1:])))
291 self.outgoing_lock.acquire()
292 print "Server.broadcast_listen(): Acquired outgoing_lock"
294 self.outgoing.append(new_message)
296 self.outgoing_lock.release()
297 print "Server.broadcast_listen(): Released outgoing_lock"
299 return
301 def end_it(self):
302 self.running = 0
303 return
305 def parse_config(filename):
307 parsed = {'error': 1}
309 if (exists(filename)):
310 dom = parse(filename)
311 else:
312 print "parse_config():", filename, "doesn't exist"
313 return parsed
315 if (dom.childNodes[0].nodeName == 'server_config'):
316 for node in dom.childNodes[0].childNodes:
318 if (node.nodeName == 'name' and len(node.childNodes)):
319 parsed['name'] = node.childNodes[0].nodeValue
321 if (node.nodeName == 'password' and len(node.childNodes)):
322 parsed['password'] = node.childNodes[0].nodeValue
324 if (node.nodeName == 'broadcast' and len(node.childNodes)):
325 parsed['broadcast'] = int(node.childNodes[0].nodeValue)
327 if (node.nodeName == 'message' and len(node.childNodes)):
328 parsed['message'] = int(node.childNodes[0].nodeValue)
330 parsed['error'] = 0
332 return parsed
334 def run(configuration):
336 my_server = Server(configuration)
338 receive_thread = threading.Thread(target=my_server.receive)
339 send_thread = threading.Thread(target=my_server.send)
340 process_in_thread = threading.Thread(target=my_server.process_in)
341 process_out_thread = threading.Thread(target=my_server.process_out)
342 broadcast_thread = threading.Thread(target=my_server.broadcast_listen)
344 receive_thread.start()
345 send_thread.start()
346 broadcast_thread
347 process_in_thread.start()
348 process_out_thread.start()
349 broadcast_thread.start()
351 receive_thread.join()
352 send_thread.join()
353 broadcast_thread.join()
354 process_in_thread.join()
355 process_out_thread.join()
357 return
359 def handler(signal, frame):
360 if (signal == SIGINT):
361 my_server.end_it()
362 print "It should have ended"
364 def main():
366 # parsing command line options
368 if (len(sys.argv) > 1):
369 config_file = sys.argv[1]
370 else:
371 print "main(): No config file specified, using", CONFIG
372 config_file = CONFIG
374 parsed_config = parse_config(config_file)
376 if (parsed_config['error']):
377 print "main(): Error parsing config, ending"
378 return
380 signal(SIGINT, handler)
382 run(parsed_config)
384 if __name__ == '__main__':
385 main()