Package lacewing :: Package moo :: Module server
[frames] | no frames]

Source Code for Module lacewing.moo.server

  1  from twisted.internet.protocol import ServerFactory 
  2   
  3  from lacewing.moo.protocol import MooProtocol 
  4   
  5  from lacewing.moo.packet import ServerPacket, ClientPacket 
  6   
  7  from lacewing.moo.packetloaders.server import * 
  8  from lacewing.moo.packetloaders.client import * 
  9   
 10  from lacewing.multidict import MultikeyDict 
 11   
 12  from lacewing.moo.packetloaders.message import * 
 13   
 14  from lacewing.idpool import IDPool 
 15   
16 -class Channel(object):
17 name = None 18 id = None 19 factory = None 20 21 connections = None 22
23 - def __init__(self, name, id, factory):
24 self.name = name 25 self.id = id 26 self.factory = factory 27 28 self.connections = MultikeyDict()
29
30 - def addConnection(self, connection):
31 self.connections[connection.name, connection.id] = connection 32 connection.channels[self.name, self.id] = self 33 34 newJoined = ChannelJoined() 35 newJoined.setChannel(self) 36 newJoined.setConnection(connection) 37 connection.sendLoader(newJoined) 38 39 newExists = PlayerExists() 40 newExists.setChannel(self) 41 42 newJoined = PlayerJoined() 43 newJoined.setChannel(self) 44 newJoined.setConnection(connection) 45 46 for otherConnection in self.connections.values(): 47 if otherConnection != connection: 48 newExists.setConnection(otherConnection) 49 connection.sendLoader(newExists) 50 otherConnection.sendLoader(newJoined)
51
52 - def removeConnection(self, connection):
53 newLeft = PlayerLeft() 54 newLeft.setChannel(self) 55 newLeft.setConnection(connection) 56 self.sendLoader(newLeft) 57 58 del self.connections[connection] 59 del connection.channels[self] 60 61 return len(self.connections) != 0
62
63 - def sendMessage(self, connection, value, subchannel, type = None, toClient = None):
64 newValue = Message(**connection.settings) 65 newValue.type = type or detectType(value) 66 newValue.value = value 67 newMessage = FromChannelMessage() 68 newMessage.setChannel(self) 69 newMessage.setConnection(connection) 70 newMessage.message = newValue 71 newMessage.subchannel = subchannel 72 if toClient: 73 toClient.sendLoader(newMessage) 74 else: 75 self.sendLoader(newMessage, connection)
76
77 - def sendLoader(self, loader, fromClient = None):
78 for connection in self.connections.values(): 79 if connection != fromClient: 80 connection.sendLoader(loader)
81
82 - def getMaster(self):
83 return self.connections.values()[0]
84
85 -class MooServerProtocol(MooProtocol):
86 _sendPacket = ServerPacket 87 _receivePacket = ClientPacket 88
89 - def connectionMade(self):
90 self.settings = self.factory.settings 91 if not self.acceptConnection(): 92 return 93 newMotd = MOTD() 94 newMotd.motd = self.factory.motd 95 self.sendLoader(newMotd) 96 newAssigned = AssignedID() 97 newId = self.factory.userPool.popId() 98 self.id = newId 99 newAssigned.playerId = newId 100 self.sendLoader(newAssigned) 101 self.isAccepted = True 102 self.connectionAccepted()
103
104 - def connectionLost(self, reason):
105 for channel in self.channels.values(): 106 self.leaveChannel(channel) 107 self.factory.userPool.putBackId(self.id)
108
109 - def loaderReceived(self, loader):
110 if isinstance(loader, SetName): 111 self.name = loader.playerName 112 self.nameSet(self.name) 113 114 elif not self.isAccepted or not self.name: 115 # if the client has come this far, 116 # it means it is sending messages 117 # without getting accepted 118 # or setting name 119 self.transport.loseConnection() 120 121 elif isinstance(loader, ClientMessage): 122 self.messageReceived(loader.message, loader.subchannel) 123 124 elif isinstance(loader, JoinChannel): 125 channelName = loader.channelName 126 if channelName in self.channels: 127 # client is in the channel already, 128 # so ignore 129 return 130 if not self.acceptChannelJoin(channelName): 131 return 132 self.joinChannel(channelName) 133 134 elif isinstance(loader, LeaveChannel): 135 channelId = loader.channelId 136 if not channelId in self.channels: 137 # the client isn't already 138 # in the channel, so we just 139 # ignore 140 return 141 channel, = self.channels[channelId] 142 if not self.acceptChannelLeave(channel): 143 return 144 self.leaveChannel(channel) 145 146 elif isinstance(loader, ToChannelMessage): 147 channelId = loader.channelId 148 if not channelId in self.channels: 149 # client has not 150 # joined a channel with 151 # this id-- ignore. 152 return 153 channel, = self.channels[channelId] 154 message = loader.message 155 subchannel = loader.subchannel 156 if not self.acceptChannelMessage(channel, message, subchannel): 157 return 158 channel.sendMessage(self, message.value, subchannel, message.type) 159 self.channelMessageReceived(channel, message, subchannel) 160 161 elif isinstance(loader, PrivateMessage): 162 channelId = loader.channelId 163 if not channelId in self.channels: 164 # client has not 165 # joined a channel with 166 # this id-- ignore. 167 return 168 channel, = self.channels[channelId] 169 playerId = loader.playerId 170 if not playerId in channel.connections: 171 # player is not to be found in the 172 # channel 173 return 174 player, = channel.connections[playerId] 175 message = loader.message 176 subchannel = loader.subchannel 177 if not self.acceptPrivateMessage(channel, player, message, subchannel): 178 return 179 channel.sendMessage(self, message.value, subchannel, message.type, player) 180 self.privateMessageReceived(channel, player, message, subchannel) 181 182 elif isinstance(loader, ChangeName): 183 if not self.acceptNameChange(self.name, loader.newName): 184 return 185 self.changeName(loader.newName) 186 187 else: 188 raise NotImplementedError
189 190 # accept-like 191
192 - def acceptConnection(self):
193 """ 194 Return False to stop the server from sending 195 a welcome to the client 196 """ 197 return True
198
199 - def acceptNameChange(self, oldName, newName):
200 """ 201 Return False to decline the client to change 202 it's name (after setting the inital name) 203 """ 204 return True
205
206 - def acceptChannelJoin(self, channelName):
207 """ 208 Return False to stop the client from joining the specified 209 channel 210 """ 211 return True
212
213 - def acceptChannelMessage(self, channel, message, subchannel):
214 """ 215 Return False to stop the channel message from being 216 sent to the other channel members 217 """ 218 return True
219
220 - def acceptPrivateMessage(self, channel, connection, message, subchannel):
221 """ 222 Return False to stop the private message from reaching 223 the recipient 224 """ 225 return True
226
227 - def acceptChannelLeave(self, channel):
228 """ 229 Return False to stop the client from leaving the specified 230 channel 231 """ 232 return True
233 234 # event-like 235
236 - def connectionAccepted(self):
237 """ 238 Called when the connection has been accepted, and the 239 client notified. 240 """
241
242 - def nameSet(self, name):
243 """ 244 Called after the name has been set 245 """
246
247 - def nameChanged(self, oldName, newName):
248 """ 249 Called when the client has changed name 250 """
251
252 - def messageReceived(self, message, subchannel):
253 """ 254 Called upon receiving a client message. 255 256 @type message: L{Message} object 257 """
258
259 - def channelJoined(self, channel):
260 """ 261 Called when the client has been let into 262 a channel 263 """
264
265 - def channelMessageReceived(self, channel, message, subchannel):
266 """ 267 Called after a channel message has been relayed. 268 269 @type message: lacewing.moo.packetloaders.message.Message object 270 """
271
272 - def privateMessageReceived(self, channel, player, message, subchannel):
273 """ 274 Called after a private message has been relayed. 275 276 @type message: lacewing.moo.packetloaders.message.Message object 277 """
278
279 - def channelLeft(self, channel):
280 """ 281 Called when the client has left a channel 282 """
283
284 - def getHost(self):
285 """ 286 This method returns the IP address of the connection. 287 Override if you would like to hide/edit the IP 288 """ 289 return self.transport.getPeer().host
290 291 # action-like 292
293 - def changeName(self, name):
294 oldName = self.name 295 296 self.name = name 297 298 newChanged = PlayerChanged() 299 newChanged.setConnection(self) 300 301 for channel in self.channels.values(): 302 channel.sendLoader(newChanged) 303 304 self.nameChanged(oldName, name)
305
306 - def sendMessage(value, subchannel, type = None):
307 """ 308 Sends a message to the other end 309 """ 310 newValue = Message(**self.settings) 311 newValue.type = type or detectType(value) 312 newValue.value = value 313 newMessage = FromChannelMessage() 314 newMessage.setServer() 315 newMessage.message = newValue 316 newMessage.subchannel = subchannel 317 self.sendLoader(newMessage)
318
319 - def sendChannelMessage(self, channel, *arg, **kw):
320 channel.sendMessage(self, *arg, **kw)
321
322 - def joinChannel(self, channelName):
323 newChannel = self.factory.createChannel(channelName) 324 newChannel.addConnection(self) 325 self.channelJoined(newChannel)
326
327 - def leaveChannel(self, channel):
331
332 -class MooServerFactory(ServerFactory):
333 motd = '' 334 335 channels = None 336 connections = None 337 338 channelPool = None 339 userPool = None 340
341 - def __init__(self, **settings):
342 self.settings = settings 343 self.channels = MultikeyDict() 344 self.connections = MultikeyDict() 345 self.userPool = IDPool(1) 346 self.channelPool = IDPool(1)
347
348 - def createChannel(self, channelName):
349 try: 350 channel, = self.channels[channelName] 351 return channel 352 except KeyError: 353 newId = self.channelPool.popId() 354 newChannel = Channel(channelName, newId, self) 355 self.channels[channelName, newId] = newChannel 356 self.channelCreated(newChannel) 357 return newChannel
358
359 - def destroyChannel(self, channel):
360 del self.channels[channel] 361 self.channelDestroyed(channel)
362
363 - def channelCreated(self, channel):
364 """ 365 Called when a new channel is 366 created 367 """
368
369 - def channelDestroyed(self, channel):
370 """ 371 Called when the channel is destroyed because 372 it is now empty 373 """
374