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 print "Messenger.datagramReceived(): WANTIN received, responding with YOUREIN"
197 members
[data
[len(WANTIN
) + 1:]] = (host
, port
)
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
, " "])
215 for name
in members
.keys():
216 if members
[name
] == (host
, port
):
219 self
.ejectMember(the_name
)
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
:
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."
241 if data
[:len(LETTER
)] == LETTER
:
248 if members
[name
] == (host
, port
):
252 print "Messenger.datagramReceived(): LETTER received, but originator not in listing"
254 print "Messenger.datagramReceived(): LETTER received, forwarding it on..."
256 response
= [''.join([LETTER
, ':', origin
, ':']), []]
259 if data
[len(LETTER
):len(LETTER
) + 2] == '::':
261 message
= data
[data
.find("::") + 2:]
262 response
[0] = ''.join([response
[0], message
])
267 responses
.append(response
)
268 response
[-1][1] = members
[name
]
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])
290 def ejectMember(self
, name
):
292 if name
in members
.keys():
294 self
.transport
.write(response
, members
[name
])
298 response
= ''.join([SOMEONELEFT
, " ", name
])
300 for member
in members
:
302 self
.transport
.write(response
, members
[member
])
306 def echo_request(self
):
311 for member
in members
:
312 if member
in self
.echo_members
:
314 self
.ejectMember(member
)
317 self
.transport
.write(YOUTHERE
, members
[member
])
318 self
.echo_members
.append(member
)
322 if __name__
== '__main__':