[Twisted-Python] Writing a plug-in for an online game that uses UDP

Hi, I am currently writing a server prototype for an online game called "If I Were U" (GPL). It will be using UDP and a MySQL db. I was successful in writing the code as a plug-in. I love the idea of being able to seperate in different files the levels of abstraction. But I am not sure of how to go about the following: I have an iiwuServer class derived from DatagramProtocol. I defined the datagramReceived method. This method calls one of my other classes's methods which returns a deferred object (this is where the connection to the db happens). I am trying to set the callback function for this deferred object and I want it to be a method of iiwuServer as I need to access the transport member object which in its turn writes out a datagram to the client. And I am not sure how to set up the callbackArgs for it (the "self" argument for methods is where I am confused). What am I doing wrong? Also, if you have a couple of minutes, can u look at my other three code segments (found after the iiwuServer) and tell me if you see anything that should be changed. Don't worry, the code is not that long. The thing is that in the documentation, each part (UDP, plug-in, deferred, etc...) are very well explained. But when I tried to put all that together, I got a little confused as I did not see any examples of UDP plug-ins or more complex deferred callback functions. All these segments are actually files in a folder called UDPServer. If you prefer that I send you the directory tarred and zipped, let me know. All that is left out is the empty __init__.py file in the folder. Thanks a lot, Ib http://www.iiwu.org Here is the code for the protocol (file name: iiwuserverprotocol.py): ////////CODE START\\\\\\\\ ############################ ##This is where the UDP packets are recieved and then sent to the server logic ############################ from twisted.internet.protocol import DatagramProtocol from UDPServer import iiwuserverlogic class iiwuServer(DatagramProtocol): iiwuservice = iiwuserverlogic.LoginService() def sendingOutput(self, result, host, port): """ A callback for the deferred object returned """ self.transport.write(str(result) + "\n" + str(self) + "\n", (host, port)) return def datagramReceived(self, data, (host, port)): msg = data.split() if len(msg) != 1 and len(msg) != 3: self.sendingOutput("error" , host, port) return if msg[0] == "log" and len(msg) == 3: user = msg[1] pswd = msg[2] self.iiwuservice.logUser(user, pswd, host, port).addCallback(self.sendingOutput(self, host, port)) return if msg[0] == "get": self.iiwuservice.loggedUsers().addCallback(self.sendingOutput(self, host, port)) return return \\\\\\\\CODE END//////// Here is the code for the server's logic (file name: iiwuserverlogic.py): ////////CODE START\\\\\\\\ ############################## ##This is where all the logic of the server lies ############################## from twisted.python import components from twisted.enterprise import adbapi class IService(components.Interface): """ An object that recieves messages. """ class LoginService: """ Respond to different messages """ __implements__ = IService def __init__(self): """ Setting up the db connection pool """ self.dbpool = adbapi.ConnectionPool("MySQLdb", 'database_name', 'login', 'password') return def mysqlQuery(self, q): """ Run a MySql query and return the result """ result = self.dbpool.runQuery(q) return result #Returning a Deferred object def logUser(self, name, pswd, ip, port): """ Connects to the DB and logs the user, returning nothing """ query = "INSERT INTO users (name, pswd, ip, port) VALUES (%s, %s, %s, %s)" % (name, pswd, ip, port) return self.mysqlQuery(query) def loggedUsers(self): """ Connects to the DB and returns a list of the users logged in """ query = "SELECT * FROM users" return self.mysqlQuery(query) \\\\\\\\CODE END//////// Here is the code for the tap construction (file name: servertap.py): ////////CODE START\\\\\\\\ from twisted.application import internet # services that run TCP/SSL/etc. from UDPServer import iiwuserverprotocol # Protocol from UDPServer import iiwuserverlogic # Server code from twisted.python import usage # twisted command-line processing class Options(usage.Options): """ Defining options when building the application """ optParameters = [["port", "p", 8007, "Port number to listen on for iiwuServer protocol."]] def makeService(config): """ Return a service that will be attached to the application. """ protocol = iiwuserverprotocol.iiwuServer() port = int(config["port"]) # UCP port to listen on # Finally, set up our protocol when events arrive on the specified port return internet.UDPServer(port, protocol) \\\\\\\\CODE END//////// Finally, here is the plugins.tml file: ////////CODE START\\\\\\\\ register("IIWU Server TAP Builder", "UDPServer.servertap", description=""" IIWU TAP builder module. """ , type="tap", tapname="iiwuserv") \\\\\\\\CODE END//////// __________________________________ Do you Yahoo!? New and Improved Yahoo! Mail - 100MB free storage! http://promotions.yahoo.com/new_mail

Ibrahim Mubarak wrote:
The above line is a problem. I believe you want it to read: self.iiwuservice.logUser(user, pswd, host, port ).addCallback(self.sendingOutput, host, port ) You cannot put self.sendingOutput(self, host, port) directly in the arguments list, because Python would treat it like any other function call: call it, and then use the return value as the argument to addCallback(). In general, d.addCallback(f, *a, **kw) will lead to Twisted invoking f like this: f(result, *a, **kw) where result is the value with which the Deferred eventually fires. Jp

--- Jp Calderone <exarkun@divmod.com> wrote:
You are 100% right. I can't believe I made that mistake as I was reading the docs when writing this, hehe. But now I have another problem. This time is with the callback function never being called. Here is a small script that I worte and executed it with "...$ python deferredExample.py" : ////////CODE START\\\\\\\\ from twisted.enterprise import adbapi dbpool = adbapi.ConnectionPool("MySQLdb", 'iiwu_database', 'login', 'password') def getUserData(user): return dbpool.runQuery("SELECT name, pswd, ip, port FROM users WHERE name = ?", user) def printResult(l): if l: print l[0][0] else: print "No such user" def printError(failure): import sys sys.stderr.write(str(failure)) getUserData("ib").addCallback(printResult).addErrback(printError) print "\nEND OF FILE\n" \\\\\\\\CODE END//////// I do see the "END OF FILE" printed, but that's it. Do you have any idea what is going on? Thanks, ib _______________________________ Do you Yahoo!? Express yourself with Y! Messenger! Free. Download now. http://messenger.yahoo.com

Ibrahim Mubarak <ibmub80@yahoo.com> wrote:
[ ... ]
The dbpool isn't started unless you start the dbpool directly with dbpool.start() or start the reactor with reactor.run(). Either way, if you want your script to terminate after you get your results, you should add another callback that calls dbpool.stop() or reactor.stop(). -- Sam "Eddie" Couter | mailto:sam@couter.dropbear.id.au Debian Developer | mailto:eddie@debian.org | jabber:sam@teknohaus.dyndns.org OpenPGP fingerprint: A46B 9BB5 3148 7BEA 1F05 5BD5 8530 03AE DE89 C75C

Ibrahim Mubarak wrote:
The above line is a problem. I believe you want it to read: self.iiwuservice.logUser(user, pswd, host, port ).addCallback(self.sendingOutput, host, port ) You cannot put self.sendingOutput(self, host, port) directly in the arguments list, because Python would treat it like any other function call: call it, and then use the return value as the argument to addCallback(). In general, d.addCallback(f, *a, **kw) will lead to Twisted invoking f like this: f(result, *a, **kw) where result is the value with which the Deferred eventually fires. Jp

--- Jp Calderone <exarkun@divmod.com> wrote:
You are 100% right. I can't believe I made that mistake as I was reading the docs when writing this, hehe. But now I have another problem. This time is with the callback function never being called. Here is a small script that I worte and executed it with "...$ python deferredExample.py" : ////////CODE START\\\\\\\\ from twisted.enterprise import adbapi dbpool = adbapi.ConnectionPool("MySQLdb", 'iiwu_database', 'login', 'password') def getUserData(user): return dbpool.runQuery("SELECT name, pswd, ip, port FROM users WHERE name = ?", user) def printResult(l): if l: print l[0][0] else: print "No such user" def printError(failure): import sys sys.stderr.write(str(failure)) getUserData("ib").addCallback(printResult).addErrback(printError) print "\nEND OF FILE\n" \\\\\\\\CODE END//////// I do see the "END OF FILE" printed, but that's it. Do you have any idea what is going on? Thanks, ib _______________________________ Do you Yahoo!? Express yourself with Y! Messenger! Free. Download now. http://messenger.yahoo.com

Ibrahim Mubarak <ibmub80@yahoo.com> wrote:
[ ... ]
The dbpool isn't started unless you start the dbpool directly with dbpool.start() or start the reactor with reactor.run(). Either way, if you want your script to terminate after you get your results, you should add another callback that calls dbpool.stop() or reactor.stop(). -- Sam "Eddie" Couter | mailto:sam@couter.dropbear.id.au Debian Developer | mailto:eddie@debian.org | jabber:sam@teknohaus.dyndns.org OpenPGP fingerprint: A46B 9BB5 3148 7BEA 1F05 5BD5 8530 03AE DE89 C75C
participants (3)
-
Ibrahim Mubarak
-
Jp Calderone
-
Sam Couter