More networking stuff.
[krufty_fps.git] / server.py~
blobf93362e47f5f3dc55249c5f4eb4211f67cc4fc94
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 my_server = 0
42 class Server:
44 def __init__(self, config):
46 self.running = 1
48 self.outgoing = []
49 self.incoming = []
51 self.outgoing_lock = Lock()
52 self.incoming_lock = Lock()
54 self.broadcast = socket(AF_INET, SOCK_DGRAM)
55 self.message = socket(AF_INET, SOCK_DGRAM)
57 self.members = {}
59 self.configuration = config
61 if (config.has_key('broadcast')):
62 self.broadcast.bind(('', config['broadcast']))
63 else:
64 print "Server.__init__(): No broadcast socket number chosen, using", BROADCAST
65 self.broadcast.bind(('', BROADCAST))
67 if (config.has_key('message')):
68 self.message.bind(('', config['message']))
69 else:
70 print "Server.__init__(): No message socket number chosen, using", MESSAGE
71 self.message.bind(('', MESSAGE))
73 def receive(self):
75 print "Server.receive() beginning..."
77 self.message.setblocking(1)
79 while (self.running):
80 data_in = self.message.recvfrom(BUFSIZE)
82 self.incoming_lock.acquire()
83 self.incoming.append(data_in)
84 print "Got data", data_in
85 self.incoming_lock.release()
87 return
89 def send(self):
91 print "Server.send() beginning..."
93 while (self.running):
95 if (len(self.outgoing)):
97 self.outgoing_lock.acquire()
98 print "Server.send(): Acquired outgoing_lock"
100 data_out = self.outgoing.pop(0)
102 self.outgoing_lock.release()
103 print "Server.send(): Released outgoing_lock"
105 self.message.sendto(data_out[0], data_out[1])
106 print "Server.send(): Sent data", data_out
107 return
109 def process_in(self):
111 print "Server.process_in() beginning..."
113 while (self.running):
115 if (len(self.incoming)):
116 # data in = ()
118 self.incoming_lock.acquire()
119 print "Server.process_in(): Acquired incoming_lock"
121 data_in = self.incoming.pop(0)
123 self.incoming_lock.release()
124 print "Server.process_in(): Released incoming_lock"
126 if (data_in[0][:len(WANTIN)] == WANTIN):
127 print "Server.process_in(): Received WANTIN"
129 response = [YOUREIN, data_in[1]]
131 self.outgoing_lock.acquire()
132 print "Server.process_in(): Acquired outgoing_lock"
134 self.outgoing.append(response)
136 self.outgoing_lock.release()
137 print "Server.process_in(): Released outgoing_lock"
139 self.members[data_in[0][len(WANTIN) + 1:]] = data_in[1]
141 if (data_in[0][:len(YOUTHERE)] == YOUTHERE):
142 print "Server.process_in(): Received YOUTHERE, responding with IMHERE"
144 response = [IMHERE, data_in[1]]
146 self.outgoing_lock.acquire()
147 print "Server.process_in(): Acquired outgoing_lock"
149 self.outgoing.append(response)
151 self.outgoing_lock.release()
152 print "Server.process_in(): Released outgoing_lock"
154 if (data_in[0][:len(IMOUT)] == IMOUT):
155 print "Server.process_in(): Received IMOUT, notifying clients"
157 response = []
158 name_to_delete = ''
160 for name, address in self.members.iteritems():
161 if (data_in[1] == address):
162 response[0] = SOMEONELEFT + " " + name
163 name_to_delete = name
165 if (name_to_delete != ''):
166 del self.members[name_to_delete]
168 for name, address in self.members.iteritems():
169 response[1] = address
171 self.outgoing_lock.acquire()
172 print "Server.process_in(): Acquired outgoing_lock"
174 self.outgoing.append(response)
176 self.outgoing_lock.release()
177 print "Server.process_in(): Released outgoing_lock"
179 if (data_in[0] == GETLIST):
180 print "Server.process_in(): Received GETLIST, responding with member list"
182 for name, address in self.members.iteritems():
183 if (address == data_in[1]):
184 response = []
186 response[0] = LIST + " "
187 response[1] = address
189 for iname, iaddress in self.members.iteritems():
190 if (iname != name):
191 response[0] = response[0] + iname + " "
193 self.outgoing_lock.acquire()
195 print "Server.process_in(): Acquired outgoing_lock"
197 self.outgoing.append(response)
199 self.outgoing_lock.release()
200 print "Server.process_in(): Released outgoing_lock"
202 if (data_in[0][:len(SERVERKILL)] == SERVERKILL):
203 print "Server.process_in(): Received SERVERKILL"
205 if (data_in[0][len(SERVERKILL) + 1:] == self.configuration['password']):
206 self.running = 0
208 if (data_in[0][:len(LETTER)] == LETTER):
209 print "Server.process_in(): Received LETTER"
211 responses = []
213 the_data = data_in[0]
214 it_is = ''
216 origin = ''
218 for name in self.members.keys():
219 if self.members[name] == data_in[1]:
220 origin = name
222 if origin != '':
224 response = [LETTER + ":" + origin + ":", []]
226 if the_data[len(LETTER):len(LETTER)+2] == '::':
228 it_is = the_data[the_data.find("::") + 2:]
229 response[0] += it_is
231 for name in self.members.keys():
233 if origin != name:
235 responses.append(response)
236 responses[-1][1] = self.members[name]
238 else:
240 it_is = the_data[the_data.find(":", the_data.find(":") + 1) + 1:]
241 response[0] += it_is
243 string_parts = the_data[the_data.find(":") + 1:
244 the_data.find(":", the_data.find(":") + 1)].split()
246 for dest in string_parts:
248 if self.members.has_key(dest):
250 responses.append(response)
251 responses[-1][1] = self.members[dest]
253 for response_i in responses:
255 self.outgoing_lock.acquire()
256 self.outgoing.append(response_i)
257 self.outgoing_lock.release()
259 return
261 def process_out(self):
263 print "Server.process_out(): Not implemented yet."
265 return
267 def broadcast_listen(self):
269 print "Listening on broadcast port:", self.configuration['broadcast']
271 broadcast_message = SERVEROFFER + " " + str(self.configuration['message'])
272 broadcast_message = broadcast_message + " " + self.configuration['name']
274 while (self.running):
275 data_in = self.broadcast.recvfrom(BUFSIZE)
277 if (data_in[0][0:len(SERVERREQUEST)] == SERVERREQUEST):
278 new_message = [broadcast_message]
279 new_message.append((data_in[1][0], int(data_in[0][len(SERVERREQUEST) + 1:])))
281 self.outgoing_lock.acquire()
282 print "Server.broadcast_listen(): Acquired outgoing_lock"
284 self.outgoing.append(new_message)
286 self.outgoing_lock.release()
287 print "Server.broadcast_listen(): Released outgoing_lock"
289 return
291 def end_it(self):
292 self.running = 0
293 return
295 def parse_config(filename):
297 parsed = {'error': 1}
299 if (exists(filename)):
300 dom = parse(filename)
301 else:
302 print "parse_config():", filename, "doesn't exist"
303 return parsed
305 if (dom.childNodes[0].nodeName == 'server_config'):
306 for node in dom.childNodes[0].childNodes:
308 if (node.nodeName == 'name' and len(node.childNodes)):
309 parsed['name'] = node.childNodes[0].nodeValue
311 if (node.nodeName == 'password' and len(node.childNodes)):
312 parsed['password'] = node.childNodes[0].nodeValue
314 if (node.nodeName == 'broadcast' and len(node.childNodes)):
315 parsed['broadcast'] = int(node.childNodes[0].nodeValue)
317 if (node.nodeName == 'message' and len(node.childNodes)):
318 parsed['message'] = int(node.childNodes[0].nodeValue)
320 parsed['error'] = 0
322 return parsed
324 def run(configuration):
326 my_server = Server(configuration)
328 receive_thread = threading.Thread(target=my_server.receive)
329 send_thread = threading.Thread(target=my_server.send)
330 process_in_thread = threading.Thread(target=my_server.process_in)
331 process_out_thread = threading.Thread(target=my_server.process_out)
332 broadcast_thread = threading.Thread(target=my_server.broadcast_listen)
334 receive_thread.start()
335 send_thread.start()
336 broadcast_thread
337 process_in_thread.start()
338 process_out_thread.start()
339 broadcast_thread.start()
341 receive_thread.join()
342 send_thread.join()
343 broadcast_thread.join()
344 process_in_thread.join()
345 process_out_thread.join()
347 return
349 def handler(signal, frame):
350 if (signal == SIGINT):
351 my_server.end_it()
352 print "It should have ended"
354 def main():
356 # parsing command line options
358 if (len(sys.argv) > 1):
359 config_file = sys.argv[1]
360 else:
361 print "main(): No config file specified, using", CONFIG
362 config_file = CONFIG
364 parsed_config = parse_config(config_file)
366 if (parsed_config['error']):
367 print "main(): Error parsing config, ending"
368 return
370 signal(SIGINT, handler)
372 run(parsed_config)
374 if __name__ == '__main__':
375 main()