I'd like to use BitTorrent for sharing files with Nessie. So, I started doing some research about private trackers. It took me quite a while to scrape together enough information about BitTorrent protocols to figure out how private trackers work. (It would have helped if I had found the official BitTorrent specifications sooner.) It turns out to be quite simple.
Basically torrent trackers and clients exchange dictionaries of meta-data. In the meta-data sent from the client to the tracker is a passkey (with the key name 'key'). The passkey is per-user and added to the announce URL in the .torrent file which is dynamically generated for each registered user that downloads it. The tracker then uses that key like a session key in a web app. The key can be used for connection limiting, ratio tracking, IP restriction, etc. Useful!
When trackers send data back to the clients, a private flag bit is set (with the key name 'private'). Well behaved clients will then refrain fr…
I came across a nice code snippet today to accomplish this. Naturally, this doesn't work for NAT.def GetPublicIpAddress(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(('google.com', 80)) return s.getsockname()Another great snippet for finding the IP address of a given network interface is in the ASPN Python Cookbook.
I spent some time today picking up wxPython to add a GUI to Nessie. Here's a few things I learned:
wxPython defaults to logging errors into a wx window on Windows and Mac. That's pretty useless if your application crashes and the window disappears immediately. To redirect output to your console use: wx.App(redirect=False)The wxPython style guide suggests using sizers for laying out your application. The most useful of these is the GridBagSizer (basically a table where items can span multiple cells). Unfortunately, the API for this sizer is a bit cumbersome. It requires you to specify the coordinates for each item in the grid. That's fine until you want to insert a new row and end up shifting all the following coordinates by one. I wrote a quick factory wrapper around the GridBagSizer that I think makes for a nicer API.class GridBagSizerFactory(object): def __init__(self, hgap, vgap): self.sizer = wx.GridBagSizer(hgap, vgap) self._row = 0 self._col = 0