From basic at us.netrek.org Wed Sep 19 12:23:24 2012 From: basic at us.netrek.org (Bob Tanner) Date: Wed, 19 Sep 2012 12:23:24 -0500 Subject: [netrek-dev] Client connection: State? Message-ID: Long story short, I want to improve my Cocoa and objective-c skill set. I've combined 2 of my favorite FOSS projects together. 1 (obviously) is netrek and the other is Adium (http://adium.im/). What I want to get out of this coding adventure is an Adium plugin that can connect to a netrek server and act as an observer. I got the view (gui) stuff and socket stuff done (gratitious concepts takes from pygame and MacTrek). What I'm failing to get to work properly is the "game packet" processing. Looking at packet.h there's a general protocol state outline. Starting states CP_SOCKET CP_FEATURE, optional, to indicate feature packets are known SP_MOTD SP_FEATURE, only if CP_FEATURE was seen SP_QUEUE, optional, repeats until slot is available SP_YOU, indicates slot number assigned Login states CP_LOGIN CP_FEATURE SP_LOGIN SP_YOU SP_PLAYER_INFO My netrek-game-protocol-fu is rusty (working in objective-c isn't helping me). I assume "short-cut" some states if all I want to do is connect as observer? My packet trace looks nothing like a real client so I'm looking for help on what I'm doing wrong (pseudocode): connect to server port 2593 send CP_SOCKET assume I don't need to send CP_FEATURE? read SP_MOTD Assuming the above is correct, the problem is I get a 1340 byte payload and the first byte is not 0x0b (11, aka SP_MOTD) so either my state stuff is wrong OR my socket code is wrong. I see a spiffy tool called lurk.py (James?) in the cow code base. Sadly it doesn't work on Mountain Lion/Python 2.7.2 (haven't really looked at it yet). If I read the code right is this effectively a netrek-game protocol sniffer? Thanks. -- Bob Tanner Key fingerprint = 9906 320A 8BB6 64AD 96A7 ?7785 CBFB 10BF 568B F98C From quozl at us.netrek.org Wed Sep 19 18:30:25 2012 From: quozl at us.netrek.org (James Cameron) Date: Thu, 20 Sep 2012 09:30:25 +1000 Subject: [netrek-dev] Client connection: State? In-Reply-To: References: Message-ID: <20120919233025.GA2180@us.netrek.org> On Wed, Sep 19, 2012 at 12:23:24PM -0500, Bob Tanner wrote: > Long story short, I want to improve my Cocoa and objective-c skill > set. I've combined 2 of my favorite FOSS projects together. 1 > (obviously) is netrek and the other is Adium (http://adium.im/). > > What I want to get out of this coding adventure is an Adium plugin > that can connect to a netrek server and act as an observer. I hope you'll take it further so that people can play. > > I got the view (gui) stuff and socket stuff done (gratitious > concepts takes from pygame and MacTrek). > > What I'm failing to get to work properly is the "game packet" processing. > > Looking at packet.h there's a general protocol state outline. > > Starting states > CP_SOCKET > CP_FEATURE, optional, to indicate feature packets are known > SP_MOTD > SP_FEATURE, only if CP_FEATURE was seen > SP_QUEUE, optional, repeats until slot is available > SP_YOU, indicates slot number assigned > > Login states > CP_LOGIN > CP_FEATURE > SP_LOGIN > SP_YOU > SP_PLAYER_INFO > > My netrek-game-protocol-fu is rusty (working in objective-c isn't > helping me). I assume "short-cut" some states if all I want to do > is connect as observer? No, not really. Observer mode was tacked on. It is the same protocol with very few differences. > > My packet trace looks nothing like a real client so I'm looking for > help on what I'm doing wrong (pseudocode): > > connect to server port 2593 > send CP_SOCKET > assume I don't need to send CP_FEATURE? > read SP_MOTD > > Assuming the above is correct, the problem is I get a 1340 byte > payload and the first byte is not 0x0b (11, aka SP_MOTD) so either > my state stuff is wrong OR my socket code is wrong. That seems likely. What is the payload? > I see a spiffy tool called lurk.py (James?) in the cow code base. > Sadly it doesn't work on Mountain Lion/Python 2.7.2 (haven't really > looked at it yet). If I read the code right is this effectively a > netrek-game protocol sniffer? It is a scriptable observer client without a graphics head. It was cut down from an earlier version of Gytha. It can be used as the basis for a protocol sniffer, but by far the best sniffer we have at the moment is Gytha. (I'm preparing for the usual holiday camp a week and a half away where we will play organised Netrek games for a couple of hours). -- James Cameron http://quozl.linux.org.au/ From basic at us.netrek.org Wed Sep 19 18:43:30 2012 From: basic at us.netrek.org (Bob Tanner) Date: Wed, 19 Sep 2012 18:43:30 -0500 Subject: [netrek-dev] Client connection: State? References: <20120919233025.GA2180@us.netrek.org> Message-ID: On 2012-09-19 23:30:25 +0000, James Cameron said: > but by far the best sniffer we have at > the moment is Gytha. aka netrek-client-pygame? Hosted at http://james.tooraweenah.com/darcs/netrek-client-pygame ? I think I found my problem, the whole motd handling is convoluted. Poking around client.py:tcp_readable client.py:tcp_readable_steam client.py:tcp_read_more I see some funky handling of "large" packets. Let me poke around more. To be honest I really like the simple and elegant python code you wrote. The obj-c stuff seems messy. -- Bob Tanner Key fingerprint = 9906 320A 8BB6 64AD 96A7 7785 CBFB 10BF 568B F98C From quozl at us.netrek.org Wed Sep 19 18:56:07 2012 From: quozl at us.netrek.org (James Cameron) Date: Thu, 20 Sep 2012 09:56:07 +1000 Subject: [netrek-dev] Client connection: State? In-Reply-To: References: <20120919233025.GA2180@us.netrek.org> Message-ID: <20120919235607.GB2180@us.netrek.org> On Wed, Sep 19, 2012 at 06:43:30PM -0500, Bob Tanner wrote: > On 2012-09-19 23:30:25 +0000, James Cameron said: > > >but by far the best sniffer we have at > >the moment is Gytha. > > aka netrek-client-pygame? Yes > > Hosted at http://james.tooraweenah.com/darcs/netrek-client-pygame ? Yes, and I've just fixed that, please try again. I'm yet to get the darcs web interface working again, after losing the configuration in an equipment failure. I use darcs so rarely now, so I'm inclined to convert to git, and did some work on that last night, but darcs-to-git fails half way with a patch that created a conflict. Next thing to try is darcs-bridge aka darcs-fastconvert. > I think I found my problem, the whole motd handling is convoluted. > > Poking around > > client.py:tcp_readable > client.py:tcp_readable_steam > client.py:tcp_read_more > > I see some funky handling of "large" packets. > > Let me poke around more. If I recall correctly, the challenge is that the socket layer returns the data in precise order, but with chunk boundaries unlike the transmission. Hence the buffering. > > To be honest I really like the simple and elegant python code you > wrote. The obj-c stuff seems messy. I'm a simple kinda guy. ;-) -- James Cameron http://quozl.linux.org.au/ From basic at us.netrek.org Sat Sep 22 00:19:58 2012 From: basic at us.netrek.org (Bob Tanner) Date: Sat, 22 Sep 2012 00:19:58 -0500 Subject: [netrek-dev] Client connection: State? References: Message-ID: On 2012-09-19 17:23:24 +0000, Bob Tanner said: > connect to server port 2593 > send CP_SOCKET > assume I don't need to send CP_FEATURE? > read SP_MOTD Making progress. I need to stop thinking Linux+C :-) Still having some bugs related to processing the SP_MOTD stuff. As I'm building game packets from the TCP stream I see a SP_MOTD packet what is just "@@@". On continuum I see the MOTD come across then I believe the text representation of stuff in sysdef (see below). Is the "@@@" a boundry marker of some sort? I see on MacTrek it's uses as a "flag" to say the MOTD is "done". Thanks. Welcome to The Continuum, please enjoy the game. Real Time Enterprises, Inc. http://www.real-time.com 2009-07-11 See http://netrek.org/ for more about Netrek. This server welcomes new players to Netrek. Expert players are encouraged to educate new players by leading and showing a good example ... rather than dishearten them by insisting on dodge practice. Not everyone can read. -- Hosting : Basic Administration : Quozl @@@ Binary Verification : disabled Tournament Mode : 4 players / side Ships Allowed : SC DD CA BB AS SB Tractor/Pressor Beams : enabled Plasma Torpedoes : enabled Kills Required for Plasma : 2 Rank Required for SB : Captain (4) Planets Required for SB : 5 Hidden Mode : tournament only Multiple Entry Planets : no Chaos Mode : disabled Hunter Killer : No Message to GOD Log : Yes SB Transwarp : Yes Surrender Counter : 2 -- Bob Tanner Key fingerprint = 9906 320A 8BB6 64AD 96A7 7785 CBFB 10BF 568B F98C -------------- next part -------------- An HTML attachment was scrubbed... URL: From billbalcerski at gmail.com Sat Sep 22 00:35:46 2012 From: billbalcerski at gmail.com (Bill Balcerski) Date: Sat, 22 Sep 2012 01:35:46 -0400 Subject: [netrek-dev] Client connection: State? In-Reply-To: References: Message-ID: On Sat, Sep 22, 2012 at 1:19 AM, Bob Tanner wrote: > ** > > On continuum I see the MOTD come across then I believe the text > representation of stuff in sysdef (see below). Is the "@@@" a boundry > marker of some sort? > > It is signal from server that the configuration info (most clients display this on galactic window) is about to be sent. -------------- next part -------------- An HTML attachment was scrubbed... URL: From quozl at us.netrek.org Sat Sep 22 00:42:53 2012 From: quozl at us.netrek.org (James Cameron) Date: Sat, 22 Sep 2012 15:42:53 +1000 Subject: [netrek-dev] Client connection: State? In-Reply-To: References: Message-ID: <20120922054253.GI5433@us.netrek.org> Yes, @@@ marks the boundary between the MOTD file and the sysdef file. Another one of those changes made to avoid changing a protocol. gytha/motd.py has more detail, pay close attention to the comments about not having a terminator in the flow. -- James Cameron http://quozl.linux.org.au/ From quozl at us.netrek.org Sat Sep 22 03:40:08 2012 From: quozl at us.netrek.org (James Cameron) Date: Sat, 22 Sep 2012 18:40:08 +1000 Subject: [netrek-dev] Gytha play testing needed Message-ID: <20120922084008.GA26666@us.netrek.org> G'day, I'm looking for play testers for changes to the Gytha client that I've made in the past few days. Testing is needed in the next four days. These changes add a client-side achievement-unlocked dialog for a set of early learning achievements, for players who have never seen the game before. These are tracked per-user in their home directory. An experienced player will find these _very_ annoying, so you have to use the command-line flag --ubertweak when starting the game. A new key "A" is set up for showing the achievement progress. The achievements in suggested learning order are: 'Started', 'Using Help', 'Using Keyboard Help', 'Using Information', 'Using the Galactic Map', 'Moving', 'Turning', 'Planet Lock', 'Orbit', 'Bombing', 'Shields Lowered', 'Phaser Hit', 'Detonate', 'Cloaked Flight', 'Pick', 'Drop', 'Calling a Take', 'Calling Escort', 'A conquer parade!', 'Phaser Hit a Cloaked Enemy', 'Phaser Hit a Plasma', 'Drop on Agricultural', 'Drop on Enemy Homeworld', 'Ten Kills', 'Planet Hook', The achievements do not provide any advantage in the game, they are only for learning progress tracking. Here's the source in darcs: http://james.tooraweenah.com/darcs/netrek-client-pygame/ The most likely problems I'm looking for are: - random crashes in untested code, please capture the stderr traceback, - obvious ways to circumvent the achievements, - missing obvious achivements for new players. Some minimal sound effects have also been added, again oriented not toward enjoyment but toward learning goals: - an orchestral hit "ta da" when an achievement is unlocked, - men shouting "Hey!" when your team planet count increases, - a slide whistle down when your team planet count decreases, - a dramatic orchestral sequence when an LPS starts, - applause when a conquer parade begins, - an explosion for when your ship explodes (but not others), -- James Cameron http://quozl.linux.org.au/ From basic at us.netrek.org Sat Sep 22 13:29:17 2012 From: basic at us.netrek.org (Bob Tanner) Date: Sat, 22 Sep 2012 13:29:17 -0500 Subject: [netrek-dev] Client connection: State? References: <20120922054253.GI5433@us.netrek.org> Message-ID: On 2012-09-22 05:42:53 +0000, James Cameron said: > gytha/motd.py has more detail, pay close attention to the comments > about not having a terminator in the flow. I must have an old release? Here's the motd.py I have: class MOTD: """ message of the day """ def __init__(self): self.list = [] def add(self, text): self.list.append(text) def get(self): return self.list -- Bob Tanner Key fingerprint = 9906 320A 8BB6 64AD 96A7 7785 CBFB 10BF 568B F98C From quozl at us.netrek.org Sun Sep 23 04:13:10 2012 From: quozl at us.netrek.org (James Cameron) Date: Sun, 23 Sep 2012 19:13:10 +1000 Subject: [netrek-dev] Client connection: State? In-Reply-To: References: <20120922054253.GI5433@us.netrek.org> Message-ID: <20120923091310.GB10591@us.netrek.org> On Sat, Sep 22, 2012 at 01:29:17PM -0500, Bob Tanner wrote: > On 2012-09-22 05:42:53 +0000, James Cameron said: > > >gytha/motd.py has more detail, pay close attention to the comments > >about not having a terminator in the flow. > > I must have an old release? Here's the motd.py I have: > > class MOTD: > """ message of the day """ > def __init__(self): > self.list = [] > > def add(self, text): > self.list.append(text) > > def get(self): > return self.list Yes, that's quite old. It was before the server-side tips implementation was added. Check your repository or source release version. Here's a recent one: http://james.tooraweenah.com/darcs/netrek-client-pygame/gytha/motd.py Included here: """ message of the day handling. SP_MOTD packets are received from server. the first batch of packets arrives during connection, and contain administrative text flow, terminated by a parameters marker. the second batch of packets also arrives during connection, and contain procedural parameter text flow, and are not terminated. the batch simply ceases. subsequent batches of packets arrive on death of a ship, and contain playing tips relating to the immediately previous ship flight, and are prefixed with a clear marker. """ STATE_INITIAL = 0 STATE_PARAMETERS = 1 STATE_TIPS = 2 MARKER_PARAMETERS = '@@@' MARKER_CLEAR = 'CLEAR_MOTD' class MOTD: """ message of the day """ def __init__(self): self.list = [] self.status = STATE_INITIAL def add(self, text): """ add a line to the list, called on SP_MOTD """ if MARKER_CLEAR in text: self.list = [] self.status = STATE_TIPS return if MARKER_PARAMETERS in text: self.status = STATE_PARAMETERS if self.status in [STATE_INITIAL, STATE_TIPS]: self.list.append(text) def get(self): """ return the list to the caller """ return self.list def tips(self): """ return tips to the caller, if tips state was detected """ if self.status != STATE_TIPS: return None return self.list -- James Cameron http://quozl.linux.org.au/ From basic at us.netrek.org Mon Sep 24 15:48:56 2012 From: basic at us.netrek.org (Bob Tanner) Date: Mon, 24 Sep 2012 15:48:56 -0500 Subject: [netrek-dev] Client connection: State? References: <20120922054253.GI5433@us.netrek.org> <20120923091310.GB10591@us.netrek.org> Message-ID: On 2012-09-23 09:13:10 +0000, James Cameron said: > Here's a recent one: > http://james.tooraweenah.com/darcs/netrek-client-pygame/gytha/motd.py Much more documentation. My whole packet process stuff can be greatly simplified given the whole "@@@" stuff. Thank you. -- Bob Tanner Key fingerprint = 9906 320A 8BB6 64AD 96A7 7785 CBFB 10BF 568B F98C From netrek at gmail.com Mon Sep 24 16:43:28 2012 From: netrek at gmail.com (Zachary Uram) Date: Mon, 24 Sep 2012 17:43:28 -0400 Subject: [netrek-dev] Gytha play testing needed In-Reply-To: <20120922084008.GA26666@us.netrek.org> References: <20120922084008.GA26666@us.netrek.org> Message-ID: how can i test this in MS Windows? zach On Sat, Sep 22, 2012 at 4:40 AM, James Cameron wrote: > G'day, > > I'm looking for play testers for changes to the Gytha client that I've > made in the past few days. Testing is needed in the next four days. > > These changes add a client-side achievement-unlocked dialog for a set > of early learning achievements, for players who have never seen the > game before. These are tracked per-user in their home directory. > > An experienced player will find these _very_ annoying, so you have to > use the command-line flag --ubertweak when starting the game. > > A new key "A" is set up for showing the achievement progress. > > The achievements in suggested learning order are: > > 'Started', > 'Using Help', > 'Using Keyboard Help', > 'Using Information', > 'Using the Galactic Map', > 'Moving', > 'Turning', > 'Planet Lock', > 'Orbit', > 'Bombing', > 'Shields Lowered', > 'Phaser Hit', > 'Detonate', > 'Cloaked Flight', > 'Pick', > 'Drop', > 'Calling a Take', > 'Calling Escort', > 'A conquer parade!', > 'Phaser Hit a Cloaked Enemy', > 'Phaser Hit a Plasma', > 'Drop on Agricultural', > 'Drop on Enemy Homeworld', > 'Ten Kills', > 'Planet Hook', > > The achievements do not provide any advantage in the game, they are > only for learning progress tracking. > > Here's the source in darcs: > > http://james.tooraweenah.com/darcs/netrek-client-pygame/ > > The most likely problems I'm looking for are: > > - random crashes in untested code, please capture the stderr > traceback, > > - obvious ways to circumvent the achievements, > > - missing obvious achivements for new players. > > Some minimal sound effects have also been added, again oriented not > toward enjoyment but toward learning goals: > > - an orchestral hit "ta da" when an achievement is unlocked, > > - men shouting "Hey!" when your team planet count increases, > > - a slide whistle down when your team planet count decreases, > > - a dramatic orchestral sequence when an LPS starts, > > - applause when a conquer parade begins, > > - an explosion for when your ship explodes (but not others), > > -- > James Cameron > http://quozl.linux.org.au/ > _______________________________________________ > netrek-dev mailing list > netrek-dev at us.netrek.org > http://mailman.us.netrek.org/mailman/listinfo/netrek-dev -- http://www.fidei.org From basic at us.netrek.org Tue Sep 25 10:45:13 2012 From: basic at us.netrek.org (Bob Tanner) Date: Tue, 25 Sep 2012 10:45:13 -0500 Subject: [netrek-dev] Gytha play testing needed References: <20120922084008.GA26666@us.netrek.org> Message-ID: On 2012-09-24 21:43:28 +0000, Zachary Uram said: > how can i test this in MS Windows? Partition a section of hard disk for Linux, install linux, apt-get install? :-) Poking around the repository I found this link: http://quozl.linux.org.au/netrek-client-pygame/build-on-windows.phtml -- Bob Tanner Key fingerprint = 9906 320A 8BB6 64AD 96A7 7785 CBFB 10BF 568B F98C From quozl at us.netrek.org Tue Sep 25 18:07:12 2012 From: quozl at us.netrek.org (James Cameron) Date: Wed, 26 Sep 2012 09:07:12 +1000 Subject: [netrek-dev] Gytha play testing needed In-Reply-To: References: <20120922084008.GA26666@us.netrek.org> Message-ID: <20120925230712.GC4911@us.netrek.org> On Tue, Sep 25, 2012 at 10:45:13AM -0500, Bob Tanner wrote: > On 2012-09-24 21:43:28 +0000, Zachary Uram said: > > >how can i test this in MS Windows? > > Partition a section of hard disk for Linux, install linux, apt-get > install? :-) Partition? Wow, that's so 1990s. ;-) I'd use a VM these days. > Poking around the repository I found this link: > http://quozl.linux.org.au/netrek-client-pygame/build-on-windows.phtml Indeed. I've pushed some more changes to my repository overnight. The lack of play testing is worrisome, so I'll plan to do it all myself, and with desk checks of patches. -- James Cameron http://quozl.linux.org.au/ From basic at us.netrek.org Wed Sep 26 11:04:43 2012 From: basic at us.netrek.org (Bob Tanner) Date: Wed, 26 Sep 2012 11:04:43 -0500 Subject: [netrek-dev] Client connection: State? References: <20120919233025.GA2180@us.netrek.org> Message-ID: On 2012-09-19 23:30:25 +0000, James Cameron said: > It is a scriptable observer client without a graphics head. It was > cut down from an earlier version of Gytha. It can be used as the > basis for a protocol sniffer, but by far the best sniffer we have at > the moment is Gytha. James can you give a description of how this code works? I've never seen the __metaclass__ stuff. I understand in Python classes are objects and metaclasses are classes' classes :-) Duplicating the functionality in obj-c has been a stumbling block. Just hoping for some plain English on how this works so I better understand how to simulation the concept in obj-c. """ server originated packets """ sp_table = {} class ServerPacket(type): def __new__(cls, name, bases, dct): server_packet = type.__new__(cls, name, bases, dct) if dct['code'] not in sp_table: obj = server_packet() sp_table[server_packet.code] = ( struct.calcsize(server_packet.format), obj) if name.lower() not in globals(): globals()[name.lower()] = obj return server_packet class SP: __metaclass__ = ServerPacket code = -1 format = '' def find(self, number): """ given a packet type return a tuple consisting of (size, instance), or (1, self) if type not known """ if number not in sp_table: return (1, self) return sp_table[number] def handler(self, data): raise NotImplemented class SP_MOTD(SP): code = 11 format = '!bxxx80s' def handler(self, data): (ignored, message) = struct.unpack(self.format, data) message = strnul(message) if opt.sp: print "SP_MOTD message=", message galaxy.motd.add(message) -- Bob Tanner Key fingerprint = 9906 320A 8BB6 64AD 96A7 7785 CBFB 10BF 568B F98C From quozl at us.netrek.org Wed Sep 26 23:47:04 2012 From: quozl at us.netrek.org (James Cameron) Date: Thu, 27 Sep 2012 14:47:04 +1000 Subject: [netrek-dev] Client connection: State? In-Reply-To: References: <20120919233025.GA2180@us.netrek.org> Message-ID: <20120927044704.GE7343@us.netrek.org> G'day Bob, This awesome bit of code is from Stephen Thorne, possibly around 26th June 2007, during an IRC collaboration while we were organising a holiday technology camp. I've gathered it into my mind again just now, so that I can better explain it. The main requirement was a list of packet types and sizes, for processing the data stream from the server. I had built something that was a bit ugly, using my limited knowledge of Python. Stephen optimised it by using metaclasses. I still have the IRC log from #netrek. sp_table is a dictionary of server packet types, indexed by the packet type, each entry holding a packet size in bytes and a packet handler object. sp_table is populated by the __new__ method of the ServerPacket class, which is called for each of the SP_* classes as they are defined. The method calculates the size of the packet using the struct format string. This saves having to track the packet format or size in more than one place. A lowercase global name is also added. This ensures an instance of each object is preserved during execution, as well as making the object available for direct access. Direct access is common for cp_* objects, but not for sp_* objects. Examples of cp_* access are every keyboard handler. Examples of sp_* access are the references to sp_badversion.why and sp_warning.synthetic(). When the Client object is created in nt_init(), a pointer to the only instance of the SP class is given to it, and it is preserved in the Client object and used whenever a packet is received. In particular, the find method of the SP class is called. So when a packet is received (in tcp_readable); - the first byte is examined, - the sp_table is referenced, to obtain the packet size, (self.sp.find()), - enough bytes to fill the packet are dequeued from the network socket, "if we have not got the complete packet, read some more", - the packet is passed to a packet type handler, (instance.handler()). The only thing I don't quite understand is how sp_table is used without triggering an error "UnboundLocalError: local variable 'sp_table' referenced before assignment", but it works. sp_table looks like this (print repr(sp_table)): {1: (84, ), 2: (4, ), 3: (8, ), 4: (12, ), 5: (8, ), 6: (12, ), 7: (16, ), 8: (8, ), 9: (12, ), 10: (84, ), 11: (84, ), 12: (32, ), 13: (4, ), 14: (28, ), 15: (12, ), 16: (4, ), 17: (104, ), 18: (8, ), 19: (4, ), 20: (4, ), 21: (4, ), 22: (4, ), 23: (56, ), 24: (52, ), 25: (20, ), 26: (28, ), 28: (8, ), 29: (4, ), 32: (32, ), 39: (60, ), 46: (8, ), 60: (88, ), -1: (0, )} -- James Cameron http://quozl.linux.org.au/ From stephen at thorne.id.au Wed Sep 26 23:53:24 2012 From: stephen at thorne.id.au (Stephen Thorne) Date: Wed, 26 Sep 2012 21:53:24 -0700 Subject: [netrek-dev] Client connection: State? In-Reply-To: <20120927044704.GE7343@us.netrek.org> References: <20120919233025.GA2180@us.netrek.org> <20120927044704.GE7343@us.netrek.org> Message-ID: On behalf of Stephen Thorne of 2007, Stephen Thorne of 2012 would like to apologise for using metaclasses. On Sep 26, 2012 9:47 PM, "James Cameron" wrote: > G'day Bob, > > This awesome bit of code is from Stephen Thorne, possibly around 26th > June 2007, during an IRC collaboration while we were organising a > holiday technology camp. > > I've gathered it into my mind again just now, so that I can better > explain it. > > The main requirement was a list of packet types and sizes, for > processing the data stream from the server. I had built something > that was a bit ugly, using my limited knowledge of Python. Stephen > optimised it by using metaclasses. I still have the IRC log from > #netrek. > > sp_table is a dictionary of server packet types, indexed by the packet > type, each entry holding a packet size in bytes and a packet handler > object. > > sp_table is populated by the __new__ method of the ServerPacket class, > which is called for each of the SP_* classes as they are defined. The > method calculates the size of the packet using the struct format > string. This saves having to track the packet format or size in more > than one place. > > A lowercase global name is also added. This ensures an instance of > each object is preserved during execution, as well as making the > object available for direct access. Direct access is common for cp_* > objects, but not for sp_* objects. Examples of cp_* access are every > keyboard handler. Examples of sp_* access are the references to > sp_badversion.why and sp_warning.synthetic(). > > When the Client object is created in nt_init(), a pointer to the only > instance of the SP class is given to it, and it is preserved in the > Client object and used whenever a packet is received. In particular, > the find method of the SP class is called. > > So when a packet is received (in tcp_readable); > > - the first byte is examined, > > - the sp_table is referenced, to obtain the packet size, > (self.sp.find()), > > - enough bytes to fill the packet are dequeued from the network > socket, "if we have not got the complete packet, read some more", > > - the packet is passed to a packet type handler, (instance.handler()). > > The only thing I don't quite understand is how sp_table is used > without triggering an error "UnboundLocalError: local variable > 'sp_table' referenced before assignment", but it works. > > sp_table looks like this (print repr(sp_table)): > > {1: (84, ), > 2: (4, ), > 3: (8, ), > 4: (12, ), > 5: (8, ), > 6: (12, ), > 7: (16, ), > 8: (8, ), > 9: (12, ), > 10: (84, ), > 11: (84, ), > 12: (32, ), > 13: (4, ), > 14: (28, ), > 15: (12, ), > 16: (4, ), > 17: (104, ), > 18: (8, ), > 19: (4, ), > 20: (4, ), > 21: (4, ), > 22: (4, ), > 23: (56, ), > 24: (52, ), > 25: (20, ), > 26: (28, ), > 28: (8, ), > 29: (4, ), > 32: (32, ), > 39: (60, ), > 46: (8, ), > 60: (88, ), > -1: (0, )} > > -- > James Cameron > http://quozl.linux.org.au/ > -------------- next part -------------- An HTML attachment was scrubbed... URL: