Trying to move the view.
[krufty_fps.git] / .svn / text-base / server_twisted.py.svn-base
blob6a0969579c157fdf0dd4961636279088c1bdc1c7
1 #!/usr/bin/python
3 # This is a twisted version of the server
5 import os, sys
6 from os.path import exists
8 import signal
9 from signal import *
11 from xml.dom.minidom import parse, parseString
13 from twisted.internet.protocol import DatagramProtocol
14 from twisted.internet import reactor
15 from twisted.internet import task
17 CONFIG = 'config.xml'
19 BROADCAST = 50030
20 MESSAGE = 40031
21 PASSWORD = "changethis"
22 NAME = "default"
24 ECHO_TIME = 5
26 running = 1
28 # defining protocol stuff
30 SERVERREQUEST = "i_want_server"
31 SERVEROFFER = "Want_server?"
32 SERVERKILL = "DIE_server!!"
33 YOUTHERE = "you_there?"
34 IMHERE = "yeah,i'm_here"
35 WANTIN = "i_want_in"
36 YOUREIN = "urine"
37 IMOUT = "i_leave"
38 GETLIST = "get_list"
39 LIST = "peoples_on_server"
40 SOMEONEJOINED = "dude,someone_joined"
41 SOMEONELEFT = "someone_left"
42 YOUROUT = "get_lost_punk"
43 LETTER = "listen_to_me"
45 # end protocol stuff
47 MULTICAST = '234.0.0.1'
49 def main():
51 # parsing command line options
53 if (len(sys.argv) > 1):
54 config_file = sys.argv[1]
55 else:
56 print "main(): No config file specified, using", CONFIG
57 config_file = CONFIG
59 global parsed_config
60 parsed_config = parse_config(config_file)
62 if (parsed_config['error']):
63 print "main(): Error parsing config, ending"
64 return
66 signal(SIGINT, handler)
68 run(parsed_config)
70 def run(configuration):
72 global running
74 if running:
75 print "run(): Beginning..."
77 global the_messenger
78 global the_broadcast
80 global members
81 members = {}
83 the_broadcast = Broadcast()
84 the_messenger = Messenger()
86 the_messenger.echo_members = []
88 if configuration.has_key('broadcast'):
89 reactor.listenMulticast(configuration['broadcast'], the_broadcast)
90 else:
91 print "Server.__init__(): No broadcast socket number chosen, using", BROADCAST
92 reactor.listenMulticast(BROADCAST, the_broadcast)
94 if configuration.has_key('message'):
95 reactor.listenUDP(configuration['message'], the_messenger)
96 else:
97 print "Server.__init__(): No message socket number chosen, using", MESSAGE
98 reactor.listenUDP(MESSAGE, the_messenger)
100 echo_request = task.LoopingCall(the_messenger.echo_request)
102 if configuration.has_key('echo_time'):
103 echo_request.start(configuration['echo_time'])
104 else:
105 print "run(): No echo_time specified in config, using default of", ECHO_TIME
106 echo_request.start(ECHO_TIME)
108 reactor.run()
110 print "run(): Ending..."
112 return
114 def handler(signal, frame):
116 global running
117 running = 0
119 reactor.stop()
121 return
123 def is_end():
125 if not running:
126 reactor.stop()
128 return
130 def parse_config(filename):
132 parsed = {'error': 1}
134 if (exists(filename)):
135 dom = parse(filename)
136 else:
137 print "parse_config():", filename, "doesn't exist"
138 return parsed
140 if (dom.childNodes[0].nodeName == 'server_config'):
141 for node in dom.childNodes[0].childNodes:
143 if (node.nodeName == 'name' and len(node.childNodes)):
144 parsed['name'] = node.childNodes[0].nodeValue
146 if (node.nodeName == 'password' and len(node.childNodes)):
147 parsed['password'] = node.childNodes[0].nodeValue
149 if (node.nodeName == 'broadcast' and len(node.childNodes)):
150 parsed['broadcast'] = int(node.childNodes[0].nodeValue)
152 if (node.nodeName == 'message' and len(node.childNodes)):
153 parsed['message'] = int(node.childNodes[0].nodeValue)
155 if (node.nodeName == 'echo_time' and len(node.childNodes)):
156 parsed['echo_time'] = int(node.childNodes[0].nodeValue)
158 parsed['error'] = 0
160 return parsed
162 class Broadcast(DatagramProtocol):
164 def startProtocol(self):
166 self.transport.joinGroup(MULTICAST)
168 def datagramReceived(self, data, address):
170 global parsed_config
172 if data[0:len(SERVERREQUEST)] == SERVERREQUEST:
174 new_message = ''.join([SERVEROFFER, " ",
175 str(parsed_config['message']),
176 " ", parsed_config['name']])
178 destination = (address[0], int(data[len(SERVERREQUEST) + 1:]))
180 the_messenger.transport.write(new_message, destination)
182 print "Broadcast.datagramReceived(): Received SERVERREQUEST, responded with SERVEROFFER"
184 return
186 class Messenger(DatagramProtocol):
188 def datagramReceived(self, data, (host, port)):
190 global members
191 global parsed_config
193 if data[:len(WANTIN)] == WANTIN:
195 print "Messenger.datagramReceived(): WANTIN received, responding with YOUREIN"
197 members[data[len(WANTIN) + 1:]] = (host, port)
198 response = YOUREIN
199 self.transport.write(response, (host, port))
201 if data[:len(YOUTHERE)] == YOUTHERE:
203 print "Messenger.datagramReceived(): YOUTHERE received, responding with IMHERE"
205 self.transport.write(IMHERE, (host, port))
207 if data[:len(IMOUT)] == IMOUT:
209 if (host, port) in members.values():
210 print "Messenger.datagramReceived(): IMOUT received, notifying others"
212 response = ''.join([SOMEONELEFT, " "])
214 the_name = ''
215 for name in members.keys():
216 if members[name] == (host, port):
217 the_name = name
219 self.ejectMember(the_name)
221 else:
222 print "Messenger.datagramReceived(): IMOUT received, but sender not present in listing"
224 if data[:len(GETLIST)] == GETLIST:
225 print "Messenger.datagramReceived(): GETLIST received, responding with LIST"
227 response = ''.join([LIST, ' '])
229 for iname in members:
230 if iname != name:
231 response = ''.join([response, iname, ' '])
233 self.transport.write(response, members[name])
235 if data[:len(SERVERKILL)] == SERVERKILL:
237 if data[len(SERVERKILL) + 1:] == parsed_config['password']:
238 print "Messenger.datagramReceived(): SERVERKILL received, dying now."
239 reactor.stop()
241 if data[:len(LETTER)] == LETTER:
243 responses = []
245 origin = ''
247 for name in members:
248 if members[name] == (host, port):
249 origin = name
251 if origin == '':
252 print "Messenger.datagramReceived(): LETTER received, but originator not in listing"
253 else:
254 print "Messenger.datagramReceived(): LETTER received, forwarding it on..."
256 response = [''.join([LETTER, ':', origin, ':']), []]
257 message = ''
259 if data[len(LETTER):len(LETTER) + 2] == '::':
261 message = data[data.find("::") + 2:]
262 response[0] = ''.join([response[0], message])
264 for name in members:
265 if origin != name:
267 responses.append(response)
268 response[-1][1] = members[name]
269 else:
271 message = data[the_data.find(':', data.find(':') + 1) + 1:]
272 response[0] = ''.join([response[0], messsage])
274 string_parts = data[data.find(':') + 1:
275 data.find(':', data.find(':') + 1)].split()
277 for dest in string_parts:
279 if members.has_key(dest):
281 responses.append(response)
282 responses[-1][1] = members[dest]
284 for response_i in responses:
286 self.transport.write(response_i[0], response_i[1])
288 return
290 def ejectMember(self, name):
292 if name in members.keys():
293 response = YOUROUT
294 self.transport.write(response, members[name])
296 del members[name]
298 response = ''.join([SOMEONELEFT, " ", name])
300 for member in members:
302 self.transport.write(response, members[member])
304 return
306 def echo_request(self):
308 global members
309 global parsed_config
311 for member in members:
312 if member in self.echo_members:
314 self.ejectMember(member)
316 else:
317 self.transport.write(YOUTHERE, members[member])
318 self.echo_members.append(member)
320 return
322 if __name__ == '__main__':
323 main()