From: <Blu...@us...> - 2009-10-24 20:27:42
|
Revision: 306 http://virtplayground.svn.sourceforge.net/virtplayground/?rev=306&view=rev Author: BlueWolf_ Date: 2009-10-24 18:56:45 +0000 (Sat, 24 Oct 2009) Log Message: ----------- * Will now uses the defaults in the config * Send will not crash when the connection is dead * connection_close renamed to connection_closed * Some changes in the callback Modified Paths: -------------- trunk/server/core/__init__.py trunk/server/core/callback.py trunk/server/core/server.py Modified: trunk/server/core/__init__.py =================================================================== --- trunk/server/core/__init__.py 2009-10-21 22:34:25 UTC (rev 305) +++ trunk/server/core/__init__.py 2009-10-24 18:56:45 UTC (rev 306) @@ -1,3 +1,7 @@ +""" +This is the server core for Virtual Playground. +You can use this by importing Server and Callback +""" ## This file is part of Virtual Playground ## Copyright (c) 2009 Jos Ratsma + Koen Koning @@ -19,3 +23,4 @@ Server = server.Server Callback = callback.Callback +__all__ = ['Server', 'Callback'] Modified: trunk/server/core/callback.py =================================================================== --- trunk/server/core/callback.py 2009-10-21 22:34:25 UTC (rev 305) +++ trunk/server/core/callback.py 2009-10-24 18:56:45 UTC (rev 306) @@ -16,40 +16,54 @@ ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. class Callback: - def server_online(self, clients): + def server_online(self): """ - server_online(self, clients) Called when the server is online and ready to accept incoming connections. This means it has successfully bounded itself to a port. Most of the times this will be called immediately after calling Server.start() - This is a placeholder. - If you want to catch this event, overwrite it. + + This is placeholder. If you want to catch this event, + overwrite this in your own callback. """ pass def connection_opened(self, uid, client, host, port): """ - connection_opened(self, uid, client, host, port) - Called when a new client connects, and we accepted the + Called when a new client connects and we accepted the connection. You can, however, still kill the connection by returning True in this function. - This is a placeholder. - If you want to catch this event, overwrite it. + uid: + The unique ID for this connection. This is usually + 'ip:port'. + client: + The client class. Normally, you don't need this. + host: + The IP adress for this user + port: + The current port this connection uses. + + + This is placeholder. If you want to catch this event, + overwrite this in your own callback. """ pass def connection_closed(self, uid): """ - connection_closed(self, uid) Called when a connection with a client is closed. This can be when they closed their connection themselves, or when we disconnect someone. - This is a placeholder. - If you want to catch this event, overwrite it. + uid: + The unique ID for this connection. This is usually + 'ip:port'. + + + This is placeholder. If you want to catch this event, + overwrite this in your own callback. """ #TODO: Reason? pass @@ -57,34 +71,53 @@ def connection_limit_exceeded(self, ip, current_connections, max_connections): """ - connection_limit_exceeded(self, ip, current_connections, - max_connections) Called when a new client connects, but the maximum number of connections is exceeded. You can, however, still accept the connection by returning True in this function. - This is a placeholder. - If you want to catch this event, overwrite it. + ip: + The IP-adress for this connection + current_connections: + Amount of current open connections + max_connections: + This is the same as in the config + 'max_connections'. + + + This is placeholder. If you want to catch this event, + overwrite this in your own callback. """ pass def data_received(self, uid, data): """ - data_received(self, uid, data) Called when the server received data from one of the clients. + Normally, you don't need this. - This is a placeholder. - If you want to catch this event, overwrite it. + uid: + The unique ID for this connection. This is usually + 'ip:port'. + + + This is placeholder. If you want to catch this event, + overwrite this in your own callback. """ pass def data_send(self, uid, data): """ - data_send(self, uid, data) Called when the server send data to one of the clients. + Normally, you don't need this. - This is a placeholder. - If you want to catch this event, overwrite it. + uid: + The unique ID for this connection. This is usually + 'ip:port'. + data: + Dict with the data that will be send. + + + This is placeholder. If you want to catch this event, + overwrite this in your own callback. """ pass Modified: trunk/server/core/server.py =================================================================== --- trunk/server/core/server.py 2009-10-21 22:34:25 UTC (rev 305) +++ trunk/server/core/server.py 2009-10-24 18:56:45 UTC (rev 306) @@ -19,46 +19,76 @@ from parser import Parser class Server(threading.Thread): - def __init__(self, config, callback_class): - """ - Will handle all connections from clients. It has one main - socket, and creates all (client)sockets. + """ + This is the server-core for Virtual Playground. This will handle all + connections from clients. It has one main socket, and it will create + all (client)sockets. + + + config: + This should be a dict with settings for the server. See the + bottom of this documentation for a list of all possible + settings. + callback_class: + The callback class will be used to notify you for certain events + that happens in the core. It has to look something like this: - Config: (maybe this explanation should be moved? maybe provide - example config with the core? maybe this function - should check the given config for error, raise - exceptions, and fill in standard values for some - missing keys) - Should be dict with settings for the server. Below a list of all - posible keys and an explanation. + class Callback(core.Callback): + ... - -host: Host to which the server binds itself(am i saying this - correctly?) standard value is '', an empty string, which - means everyone can connect to the server. - -port: Port the server should listen on. Should be int, and can - be anything. - -max_connections: Maximum ammount of clients that can be - connected simultaneously. If this number is exceeded, - the client will dropped, unless specified otherwise (see - callback `connection_limit_exceeded`). Should be int. If - this value is either None or 0, there will be no limit. - """ + See the doc in core.Callback for more information about this. + + -------- + + The settings: + -host: + Host to which the server binds itself. The default is an + empty string, an empty string, which means everyone can + connect to the server. + -port: + The port the server should listen on. Should be int + between 1 and 65535. Note that everything lower than 100 + usually needs to be run as root under Unix/Linux. + Default is 5162. + + -max_connections: + Maximum amount of clients that can be connected + simultaneously. If this number is exceeded, the new + connection will dropped, unless specified otherwise + (see callback `connection_limit_exceeded`). Should be + int. If this value is either None or 0, there will be no + limit. Default is 0. But it is wise to specify a limit. + """ + + + def __init__(self, config, callback_class): self.__sock = None - self.__call = callback_class() + self.__call = callback_class + + # Create all default settings + self.__config_default(config) self.__config = config - self.__clients = {} - self.__parse = Parser(self.__call, self.__clients) + self.clients = {} + self.__parse = Parser(self.__call, self.clients) + threading.Thread.__init__(self) + + def __config_default(self, config): + """ + Create all the config-defaults + """ + config.setdefault('host', '') + config.setdefault('port', 5162) + config.setdefault('max_connections', 0) + def start_server(self): """ - start_server() => None - - This will start the server. It will listen on the port - specified in the config. + This will start the server. It will listen on the port specified + in the config. """ #Isn't the server running already? @@ -90,19 +120,19 @@ time.sleep(1) self.__sock.listen(20) - self.__call.server_online(self.__clients) + self.__call.server_online(self.clients) #Infinite loop that will wait for incomming connections while 1: sock, addr = self.__sock.accept() - if self.__config['max_connections'] != None and \ - len(self.__clients) >= \ + if self.__config['max_connections'] and \ + len(self.clients) >= \ self.__config['max_connections']: #We exceeded our connection limit, but maybe #this is a special occasion? Send callback! if not self.__call.connection_limit_exceeded( - addr[0], len(self.__clients), + addr[0], len(self.clients), self.__config['max_connections']): #We're full, kick him out @@ -111,24 +141,25 @@ continue uid = addr[0] + ':' + str(addr[1]) - self.__clients[uid] = Client(uid, sock, self.__clients, + self.clients[uid] = Client(uid, sock, self.clients, self.__call, self.__parse) - self.__clients[uid].start() + self.clients[uid].start() if self.__call.connection_opened(uid, - self.__clients[uid], *addr): + self.clients[uid], *addr): #User returned True -> drop user time.sleep(0.1) #Let the `run` start - self.__clients[uid].close() + self.clients[uid].close() class Client(threading.Thread): + """ + This class manages the socket for the connection to clients. + Each client has it's own class. + """ + def __init__(self, uid, sock, clients, callback, parser): - """ - This class manages the socket for the connection to clients. - Each client has it's own class. - """ self.__uid = uid self.__sock = sock @@ -176,26 +207,27 @@ def close(self): """ - close() => None - Closes this connection, and kills the socket. + Closes the connection for this client and kills the socket. """ self.__sock.close() self.is_online = False - self.__call.connection_close(self.__uid) + self.__call.connection_closed(self.__uid) del self.__clients[self.__uid] def send(self, data_header, data_body = {}): """ - send(data_header, data_body = {}) => None Sends `data_body` of type `data_header` to the client. It will automatically be encoded as JSON, and the delimeter character (chr(1)) will be send automatically too. - `Data_header` is a string, `data_body` a dict. + `data_header` is a string, `data_body` a dict. """ self.__call.data_send(self.__uid, {data_header:data_body}) data = simplejson.dumps({data_header:data_body}) - self.__sock.send(data + chr(1)) + + try: + self.__sock.send(data + chr(1)) + except: pass This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |