3 # This is a twisted version of the server
6 from os
.path
import exists
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
21 PASSWORD
= "changethis"
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"
39 LIST
= "peoples_on_server"
40 SOMEONEJOINED
= "dude,someone_joined"
41 SOMEONELEFT
= "someone_left"
42 YOUROUT
= "get_lost_punk"
43 LETTER
= "listen_to_me"
47 MULTICAST
= '234.0.0.1'
51 # parsing command line options
53 if (len(sys
.argv
) > 1):
54 config_file
= sys
.argv
[1]
56 print "main(): No config file specified, using", CONFIG
60 parsed_config
= parse_config(config_file
)
62 if (parsed_config
['error']):
63 print "main(): Error parsing config, ending"
66 signal(SIGINT
, handler
)
70 def run(configuration
):
75 print "run(): Beginning..."
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
)
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
)
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'])
105 print "run(): No echo_time specified in config, using default of", ECHO_TIME
106 echo_request
.start(ECHO_TIME
)
110 print "run(): Ending..."
114 def handler(signal
, frame
):
130 def parse_config(filename
):
132 parsed
= {'error': 1}
134 if (exists(filename
)):
135 dom
= parse(filename
)
137 print "parse_config():", filename
, "doesn't exist"
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
)
162 class Broadcast(DatagramProtocol
):
164 def startProtocol(self
):
166 self
.transport
.joinGroup(MULTICAST
)
168 def datagramReceived(self
, data
, address
):
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"
186 class Messenger(DatagramProtocol
):
188 def datagramReceived(self
, data
, (host
, port
)):
193 if data
[:len(WANTIN
)] == WANTIN
:
195 if not members
.has_key(data
[len(WANTIN
) + 1:]):
196 print "Messenger.datagramReceived(): WANTIN received, responding with YOUREIN"
198 response
= ''.join([SOMEONEJOINED
, " ", data
[len(WANTIN
) + 1:]])
200 for member
in members
:
201 self
.transport
.write(response
, members
[member
])
203 members
[data
[len(WANTIN
) + 1:]] = (host
, port
)
205 self
.transport
.write(response
, (host
, port
))
207 if data
[:len(IMHERE
)] == IMHERE
:
209 if (host
, port
) in members
.values():
211 # print "Messenger.datagramReceived(): IMHERE received"
214 if members
[name
] == (host
, port
):
215 if name
in self
.echo_members
:
216 self
.echo_members
.remove(name
)
218 if data
[:len(YOUTHERE
)] == YOUTHERE
:
220 #print "Messenger.datagramReceived(): YOUTHERE received, responding with IMHERE"
222 self
.transport
.write(IMHERE
, (host
, port
))
224 if data
[:len(IMOUT
)] == IMOUT
:
226 if (host
, port
) in members
.values():
227 print "Messenger.datagramReceived(): IMOUT received, notifying others"
229 response
= ''.join([SOMEONELEFT
, " "])
232 for name
in members
.keys():
233 if members
[name
] == (host
, port
):
236 self
.ejectMember(the_name
)
239 print "Messenger.datagramReceived(): IMOUT received, but sender not present in listing"
241 if data
[:len(GETLIST
)] == GETLIST
:
242 print "Messenger.datagramReceived(): GETLIST received, responding with LIST"
244 response
= ''.join([LIST
, ' '])
246 for iname
in members
:
247 response
= ''.join([response
, iname
, ' '])
249 self
.transport
.write(response
, (host
, port
))
251 if data
[:len(SERVERKILL
)] == SERVERKILL
:
253 if data
[len(SERVERKILL
) + 1:] == parsed_config
['password']:
254 print "Messenger.datagramReceived(): SERVERKILL received, dying now."
257 if data
[:len(LETTER
)] == LETTER
:
264 if members
[name
] == (host
, port
):
268 print "Messenger.datagramReceived(): LETTER received, but originator not in listing"
270 print "Messenger.datagramReceived(): LETTER received, forwarding it on..."
272 response
= [''.join([LETTER
, ':', origin
, ':']), []]
275 if data
[len(LETTER
):len(LETTER
) + 2] == '::':
277 message
= data
[data
.find("::") + 2:]
278 response
[0] = ''.join([response
[0], message
])
283 responses
.append(response
)
284 response
[-1][1] = members
[name
]
287 message
= data
[the_data
.find(':', data
.find(':') + 1) + 1:]
288 response
[0] = ''.join([response
[0], messsage
])
290 string_parts
= data
[data
.find(':') + 1:
291 data
.find(':', data
.find(':') + 1)].split()
293 for dest
in string_parts
:
295 if members
.has_key(dest
):
297 responses
.append(response
)
298 responses
[-1][1] = members
[dest
]
300 for response_i
in responses
:
302 self
.transport
.write(response_i
[0], response_i
[1])
306 def ejectMember(self
, name
):
308 reactor
.callFromThread(self
.ejectThreadMember
, name
)
312 def ejectThreadMember(self
, name
):
313 if name
in members
.keys():
315 self
.transport
.write(response
, members
[name
])
319 response
= ''.join([SOMEONELEFT
, " ", name
])
321 for member
in members
:
323 self
.transport
.write(response
, members
[member
])
324 print "notify debug", members
[member
], response
328 def echo_request(self
):
336 #print "Messenger.echo_request(): Sending YOUTHERE messages..."
339 for member
in members
:
340 if member
in self
.echo_members
:
342 ejecters
.append(member
)
345 self
.transport
.write(YOUTHERE
, members
[member
])
346 self
.echo_members
.append(member
)
348 for person
in ejecters
:
350 self
.ejectMember(person
)
351 print "Messenger.echo_request(): Member ejected for lack of communication, name:", person
355 if __name__
== '__main__':