<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>David Underhill &#187; Coding</title>
	<atom:link href="http://dound.com/category/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://dound.com</link>
	<description>dound&#039;s space on the web</description>
	<lastBuildDate>Sun, 13 Jun 2010 23:17:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Rate limiting users requests on app engine (optionally with Captchas)</title>
		<link>http://dound.com/2010/06/rate-limiting-gae-with-captchas/</link>
		<comments>http://dound.com/2010/06/rate-limiting-gae-with-captchas/#comments</comments>
		<pubDate>Sun, 13 Jun 2010 22:59:55 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[bot]]></category>
		<category><![CDATA[captcha]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[rate limit]]></category>

		<guid isPermaLink="false">http://dound.com/?p=447</guid>
		<description><![CDATA[You may have some functionality on your app engine site that you want to protect from robots and prevent users from executing too frequently.  For example, perhaps users can leave comments but you only want them to be able to leave a comment every N seconds &#8211; faster than that and the &#8220;user&#8221; is [...]]]></description>
			<content:encoded><![CDATA[<p>You may have some functionality on your app engine site that you want to protect from robots and prevent users from executing too frequently.  For example, perhaps users can leave comments but you only want them to be able to leave a comment every <code>N</code> seconds &#8211; faster than that and the &#8220;user&#8221; is either a bot or is not using the system as intended.</p>
<p>One way to discourage this behavior is to limit how often a user can take a certain action to a fixed rate.  I&#8217;ve created a <code>RateLimiter</code> class which handles the logic of tracking how quickly a user is making requests, and determines when your code (optionally) should challenge the user with a captcha before allowing them to continue.  If you simply want to rate limit the user&#8217;s requests, you can ignore the captcha business and just return an error to the user whenever they exceed the allowed rate.</p>
<p>The source is available at <a href="http://gist.github.com/437051#file_rate_limit.py">http://gist.github.com/437051</a> (including the optional captcha handling code).</p>
<p><strong>Example Usage:</strong><br />
The example code below shows a rate limiter which allows a user to interact with a particular page once every 2 seconds.  It also gives the user 3 &#8220;tokens&#8221; which allows the user to violate this limit by up to 3 requests.  Tokens are consumed if a user makes a request within 2 seconds of the previous request.  Tokens are returned if the user if the user slows down, or if the user solves a captcha.</p>
<p>This example is written as if the request is expected to be made via JavaScript on your page.  The client-side JavaScript would check the response for the <code>'captcha-show'</code> text and prompt the user with a captcha if that test was present.  When the captcha is answered, another AJAX call would be made to send the user&#8217;s response to the <code>CaptchaHandler</code> class in <a href="http://gist.github.com/437051#file_rate_limit.py">rate_limit.py</a>.  You are free to integrate the captcha challenge however you like.  Just call <code>RateLimiter.captcha_solved()</code> or <code>RateLimiter.rate_limit(uid, captcha_solved=True)</code> when the user meets your challenge (it doesn&#8217;t even have to be a captcha).</p>
<p><script src="http://gist.github.com/437051.js?file=example.py"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://dound.com/2010/06/rate-limiting-gae-with-captchas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Country and State Chooser JavaScript Widget</title>
		<link>http://dound.com/2010/05/country-and-state-chooser-javascript-widget/</link>
		<comments>http://dound.com/2010/05/country-and-state-chooser-javascript-widget/#comments</comments>
		<pubDate>Sat, 08 May 2010 04:23:31 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://dound.com/?p=436</guid>
		<description><![CDATA[I&#8217;ve put together a simple JavaScript widget which dynamically populates a state dropdown box when a country is selected.  The widget includes states for the United States, Canada, and a few other countries.   It should be trivial to modify the script to use a list of countries and states of your choosing. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve put together a simple JavaScript widget which dynamically populates a state dropdown box when a country is selected.  The widget includes states for the United States, Canada, and a few other countries.   It should be trivial to modify the script to use a list of countries and states of your choosing.  The full source is below.  A <a href="http://gist.github.com/raw/394325/4b7294bc9b64ffbb852bbb542d430db5adde3a6c/location_picker-min.js">minified version</a> is also available.  Enjoy!</p>
<p><script src="http://gist.github.com/394325.js?file=location_picker.js"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://dound.com/2010/05/country-and-state-chooser-javascript-widget/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FAST Google App Engine Sessions (and RPX integration)</title>
		<link>http://dound.com/2010/04/google-app-engine-sessions-and-rpx-integration/</link>
		<comments>http://dound.com/2010/04/google-app-engine-sessions-and-rpx-integration/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 04:16:30 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[app-engine]]></category>
		<category><![CDATA[gae-sessions]]></category>
		<category><![CDATA[OpenID]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[sessions]]></category>

		<guid isPermaLink="false">http://dound.com/?p=307</guid>
		<description><![CDATA[The Google App Engine infrastructure provides many services, but sessions is not one of them.  There are several Python-based session middlewares which already do this so I considered them first (spoiler: I ended up writing my own and it is orders of magnitudes faster than the alternatives: gae-sessions).
Beaker is a solid implementation, but it [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://code.google.com/appengine/">Google App Engine</a> infrastructure provides many services, but sessions is not one of them.  There are several Python-based session middlewares which already do this so I considered them first (spoiler: I ended up writing my own and it is <a href="http://wiki.github.com/dound/gae-sessions/comparison-with-alternative-libraries">orders of magnitudes faster than the alternatives</a>: <strong><a href="http://github.com/dound/gae-sessions">gae-sessions</a></strong>).</p>
<p><a href="http://beaker.groovie.org/">Beaker</a> is a solid implementation, but it lacks support for memcache on app engine.  This means every request must go to the datastore to fetch session data &#8211; yuck.</p>
<p><a href="http://gaeutilities.appspot.com/">gaeutilities</a> is designed for app engine and takes advantage of both memcache and the datastore.  Unfortunately, the code is a bit heavyweight &#8211; it is coupled to unrelated functionality (e.g., &#8220;flash&#8221; messaging) and it is complicated by support for options I do not need (e.g., cookie-only sessions and automatic token rotation).  Most significantly, its performance suffers from excess API calls and inefficient model storage.</p>
<p>Since I was unsatisfied with these options, I wrote my own sessions middleware, <a href="http://github.com/dound/gae-sessions">gae-sessions</a>.  It strives to be lightweight, fast (but reliable), secure, and easy to use.  I ended up with a pretty small library (200 lines of code) which met these goals.  It uses memcache (for speed) and the datastore (for reliability) but only reads and writes  when it must.  db.Model objects are efficiently stored by converting them to protobufs instead of using the automatic pickling functionality (which is slow since app engine lacks cPickle).</p>
<p>Consider <a href="http://github.com/dound/gae-sessions">gae-sessions</a> if you need sessions support for a Python web application hosted on Google&#8217;s app engine.  The project includes demo code which you can run without modification on the app engine development server.  The demo shows gae-sessions working with an <a href="http://openid.net/">OpenID</a>-based authentication system powered by <a href="http://www.rpxnow.com">RPX</a> (check it out to see how easy it is to integrate with RPX).</p>
<p><strong>Update</strong>: I&#8217;ve created an <a href="http://bit.ly/gae-sessions"><strong>in-depth comparison page</strong></a> which compares both the features and performance of alternative sessions libraries (beaker, geautilities, gmemsess, and suas) with gae-sessions.</p>
]]></content:encoded>
			<wfw:commentRss>http://dound.com/2010/04/google-app-engine-sessions-and-rpx-integration/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Python logging and performance: how to have your cake and eat it too</title>
		<link>http://dound.com/2010/02/python-logging-performance/</link>
		<comments>http://dound.com/2010/02/python-logging-performance/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 05:08:48 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[comment]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[preprocess]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://dound.com/?p=268</guid>
		<description><![CDATA[I love Python&#8217;s logging module.  I use it all the time to log a wide variety of information &#8212; messages to help me debug as well as informative messages for the user.  Though you can toggle which messages you want to be printed, if the Python interpreter encounters a logging method call it [...]]]></description>
			<content:encoded><![CDATA[<p>I love <a href="http://www.python.org">Python</a>&#8217;s <a href="http://docs.python.org/library/logging.html">logging module</a>.  I use it all the time to log a wide variety of information &#8212; messages to help me debug as well as informative messages for the user.  Though you can toggle which messages you want to be printed, if the Python interpreter encounters a logging method call it still creates the string for the log message (the argument to the method) (sadly there Python doesn&#8217;t have <a href="http://www.haskell.org/haskellwiki/Performance/Laziness">lazy evaluation</a> like <a href="http://www.haskell.org/">Haskell</a>).  If creating this string is expensive, then your application&#8217;s performance may suffer.  Unfortunately, there is no Python preprocessor (like C&#8217;s <a href="http://gcc.gnu.org/onlinedocs/cpp/">cpp</a> &#8230; though <a href="http://code.google.com/p/preprocess/">preprocess</a> might be able to do it) so it is difficult to automatically remove a large number of logging statements prior to running an application in a production environment.</p>
<p>The best solution I&#8217;ve seen is to prefix logging statements with <code>if __debug__:</code> so that they are optimized away by <code>python -O</code> (see <a href="http://stackoverflow.com/questions/2006190/python-equivalent-of-define-func-or-how-to-comment-out-a-function-call-in-p">this post on StackOverflow</a>).  I like it, but it unfortunately requires this statement to be prefixed to every logging statement I don&#8217;t want in a production environment.  That&#8217;s a lot of ugly extra code and it isn&#8217;t easy to change which statements it applies to either.</p>
<p>I decided to write a script which automatically parses a Python file and replaces logging statements of a particular level with a <code>pass</code> statement and a commented out copy of the logging code.  It can also do the reverse operation.  It has some limitations (see the code, or run the script with the <code>--help</code> option), but it should work for most Python files.  I used it for the <a href="http://yuba.stanford.edu/vns">VNS</a> project and it successfully operated on every file in the project.  It also improved performance dramatically &#8211; the maximum throughput of the VNS simulator <a href="http://yuba.stanford.edu/vns/2010/02/fairness/">increased by 25%</a>!  In comparison, running the code with <a href="http://psyco.sourceforge.net/">Psyco</a> only garnered a 6% improvement (though pretty substantial for the minimal <a href="http://github.com/dound/vns/commit/54d5415a43043062ae6195b828707692b9231aab">13 lines</a> I had to add to take advantage of it).</p>
<p>I think this script is worth using before running your code in a production environment if you are a heavy user of the logging module like I am.  You can find the code <a href="http://www.siafoo.net/snippet/348">here</a> (it is hosted on <a href="http://www.siafoo.com">Siafoo</a>, a neat site for sharing code).  Here&#8217;s the latest version of the code:<br />
<script type='text/javascript' src='http://www.siafoo.net/snippet/348/embed.js?nolinenos'></script></p>
]]></content:encoded>
			<wfw:commentRss>http://dound.com/2010/02/python-logging-performance/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Integrating Twisted with a pcap-based Python packet sniffer</title>
		<link>http://dound.com/2009/09/integrating-twisted-with-a-pcap-based-python-packet-sniffer/</link>
		<comments>http://dound.com/2009/09/integrating-twisted-with-a-pcap-based-python-packet-sniffer/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 00:53:34 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[pcap]]></category>
		<category><![CDATA[pcapy]]></category>
		<category><![CDATA[raw socket]]></category>
		<category><![CDATA[sniffer]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://dound.com/?p=223</guid>
		<description><![CDATA[Twisted is an awesome event-driven networking engine.  Unfortunately, it does not have good support for interfacing with raw sockets (unlike its support for many network protocols, which is amazing).  Anyway, I recently needed to work with raw sockets so I had to find a way to make it work with Twisted.  Though [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twistedmatrix.com/">Twisted</a> is an awesome event-driven networking engine.  Unfortunately, it does not have good support for interfacing with <a href="http://en.wikipedia.org/wiki/Raw_socket">raw sockets</a> (unlike its <a href="http://twistedmatrix.com/documents/8.1.0/api/twisted.protocols.html">support</a> for many network protocols, which is amazing).  Anyway, I recently needed to work with raw sockets so I had to find a way to make it work with Twisted.  Though Twisted does have a module (<a href="http://twistedmatrix.com/trac/wiki/TwistedPair">twisted.pair</a>) which tries to provide some support for raw sockets, the module is poorly documented and requires a library which is not readily available.</p>
<p>Luckily, I stumbled on a module which works on top of the <a href="http://www.tcpdump.org/">libpcap</a> packet capture library called <a href="http://oss.coresecurity.com/projects/pcapy.html">pcapy</a>.  It is simple to use, and thread-safe &#8212; and easy to integrate into a Twisted-based project.</p>
<p>I put together a short sample (see below) which shows how to capture raw packets alongside the main Twisted event loop.  It would be trivial to extend this example to also write to a raw socket (using an ordinary <a href="http://docs.python.org/library/socket.html">Python socket</a>).  This example can also be downloaded <a href="http://dound.com/wp/files/twisted_and_pcap_together.py">here</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># This sample shows how to run a libpcap-based packet sniffer concurrently with</span>
<span style="color: #808080; font-style: italic;"># the Twisted framework.  The Twisted component is an &quot;Echo&quot; TCP server</span>
<span style="color: #808080; font-style: italic;"># (listening on port 9999) which prints everything it receives.  When a client</span>
<span style="color: #808080; font-style: italic;"># connects, it starts the pcap thread.  When the pcap thread receives a packet,</span>
<span style="color: #808080; font-style: italic;"># it sends a message to the client telling it the size of the received packet.</span>
<span style="color: #808080; font-style: italic;"># Finally, when the client disconnects the program is terminated.</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># To try this contrived example out, run this script as root (so that it can use</span>
<span style="color: #808080; font-style: italic;"># pcap) and then connect to the echo server (e.g., telnet localhost 9999).  Note</span>
<span style="color: #808080; font-style: italic;"># that the pcap parameters are hard-coded.  This code uses twisted 8.0.2 and</span>
<span style="color: #808080; font-style: italic;"># pcapy-0.10.4.</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> pcapy <span style="color: #ff7700;font-weight:bold;">import</span> open_live
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span>.<span style="color: black;">protocol</span> <span style="color: #ff7700;font-weight:bold;">import</span> Protocol, Factory
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> reactor
&nbsp;
<span style="color: #808080; font-style: italic;"># pcap settings</span>
DEV          = <span style="color: #483d8b;">'eth0'</span>  <span style="color: #808080; font-style: italic;"># interface to listen on</span>
MAX_LEN      = <span style="color: #ff4500;">1514</span>    <span style="color: #808080; font-style: italic;"># max size of packet to capture</span>
PROMISCUOUS  = <span style="color: #ff4500;">1</span>       <span style="color: #808080; font-style: italic;"># promiscuous mode?</span>
READ_TIMEOUT = <span style="color: #ff4500;">100</span>     <span style="color: #808080; font-style: italic;"># in milliseconds</span>
PCAP_FILTER  = <span style="color: #483d8b;">''</span>      <span style="color: #808080; font-style: italic;"># empty =&gt; get everything (or we could use a BPF filter)</span>
MAX_PKTS     = -<span style="color: #ff4500;">1</span>      <span style="color: #808080; font-style: italic;"># number of packets to capture; -1 =&gt; no limit</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> run_pcap<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># the method which will be called when a packet is captured</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> ph<span style="color: black;">&#40;</span>hdr, data<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'pcap heard: when=%s sz=%dB'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>hdr.<span style="color: black;">getts</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># thread safety: call from the main twisted event loop</span>
        reactor.<span style="color: black;">callFromThread</span><span style="color: black;">&#40;</span>f, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># start the packet capture</span>
    p = open_live<span style="color: black;">&#40;</span>DEV, MAX_LEN, PROMISCUOUS, READ_TIMEOUT<span style="color: black;">&#41;</span>
    p.<span style="color: black;">setfilter</span><span style="color: black;">&#40;</span>PCAP_FILTER<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Listening on %s: net=%s, mask=%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>DEV, p.<span style="color: black;">getnet</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, p.<span style="color: black;">getmask</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    p.<span style="color: black;">loop</span><span style="color: black;">&#40;</span>MAX_PKTS, ph<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># a silly echo server which prints what it receives and sends info about the</span>
<span style="color: #808080; font-style: italic;"># size of each packet captured on DEV</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Echo<span style="color: black;">&#40;</span>Protocol<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> connectionLost<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, reason<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">os</span>._exit<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># kill the whole process</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> connectionMade<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># run pcap in another thread (it will run forever)</span>
        reactor.<span style="color: black;">callInThread</span><span style="color: black;">&#40;</span>run_pcap, <span style="color: #008000;">self</span>.<span style="color: black;">pcapDataReceived</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> dataReceived<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, data<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'echo got: %s'</span> <span style="color: #66cc66;">%</span> data
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> pcapDataReceived<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, sz<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">transport</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'pcap got: %uB<span style="color: #000099; font-weight: bold;">\n</span>'</span> <span style="color: #66cc66;">%</span> sz<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># starts the silly echo server on port 9999</span>
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    factory = Factory<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    factory.<span style="color: black;">protocol</span> = Echo
    reactor.<span style="color: black;">listenTCP</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">9999</span>, factory<span style="color: black;">&#41;</span>
    reactor.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://dound.com/2009/09/integrating-twisted-with-a-pcap-based-python-packet-sniffer/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>LaTeX: adding footnotes in tables (or other floats)</title>
		<link>http://dound.com/2009/06/latex-adding-footnotes-in-tables-or-other-floats/</link>
		<comments>http://dound.com/2009/06/latex-adding-footnotes-in-tables-or-other-floats/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 04:10:48 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[LaTeX]]></category>
		<category><![CDATA[caption]]></category>
		<category><![CDATA[figure]]></category>
		<category><![CDATA[float]]></category>
		<category><![CDATA[footnote]]></category>
		<category><![CDATA[latex]]></category>
		<category><![CDATA[table]]></category>
		<category><![CDATA[tabular]]></category>

		<guid isPermaLink="false">http://dound.com/?p=184</guid>
		<description><![CDATA[I recently wanted to put a footnote reference inside a table.  Unfortunately, LaTeX makes it somewhat difficult to add footnotes inside floats (e.g., tabular).  If you try to put a footnote inside a tabular, then pdflatex will show the reference but not the footnote itself!  I came across several suggestions for fixing [...]]]></description>
			<content:encoded><![CDATA[<p>I recently wanted to put a footnote reference inside a table.  Unfortunately, <a href="http://www.latex-project.org/">LaTeX</a> makes it somewhat difficult to add footnotes inside floats (e.g., <code><a href="http://www.andy-roberts.net/misc/latex/latextutorial4.html">tabular</a></code>).  If you try to put a footnote inside a <code>tabular</code>, then <code>pdflatex</code> will show the reference but not the footnote itself!  I came across several suggestions for fixing this:</p>
<p><a href="http://www.hep.man.ac.uk/u/jenny/jcwdocs/latex/latex.html">One idea</a> is to put the table in a <code><a href="http://www-h.eng.cam.ac.uk/help/tpl/textprocessing/teTeX/latex/latex2e-html/ltx-267.html">minipage</a></code>.  This causes the footnote to show up at the bottom of the table (in its own numbering system) &#8212; but I wanted the footnote to show up at the bottom of the page like other footnotes!</p>
<p>Another idea was to manually specify the footnote number inside the text and then use the <code><a href="http://www-h.eng.cam.ac.uk/help/tpl/textprocessing/teTeX/latex/latex2e-html/ltx-234.html">\footnotetext</a></code> command (outside the <code>tabular</code>) to manually add the footer.  Unfortunately, this is not a robust solution since it forces you to manually maintain this footnote number inside the tabular.</p>
<p>Building on the previous idea, I discovered a way to make footnotes appear inside <code>tabular</code>s <i>without</i> breaking the automatic numbering of footnotes.  Here is my approach:</p>
<ol>
<li>Include the &#8220;<a href="http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=fmtcount">fmtcount</a>&#8221; package so that you can display the values of counters (e.g., the footnote counter):

<div class="wp_syntax"><div class="code"><pre class="latex" style="font-family:monospace;"><span style="color: #800000; font-weight: normal;">\usepackage</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">fmtcount</span><span style="color: #E02020; ">}</span></pre></div></div>

</li>
<li>Immediately before your tabular, increment the footnote counter:

<div class="wp_syntax"><div class="code"><pre class="latex" style="font-family:monospace;"><span style="color: #800000; font-weight: normal;">\addtocounter</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">footnote</span><span style="color: #E02020; ">}{</span><span style="color: #2020C0; font-weight: normal;">1</span><span style="color: #E02020; ">}</span></pre></div></div>

</li>
<li>Next, specify the contents of the footnote:

<div class="wp_syntax"><div class="code"><pre class="latex" style="font-family:monospace;"><span style="color: #800000; font-weight: normal;">\footnotetext</span><span style="color: #E02020; ">[</span><span style="color: #C08020; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\value</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">footnote</span><span style="color: #E02020; ">}</span></span><span style="color: #E02020; ">]{</span><span style="color: #2020C0; font-weight: normal;">your text here</span><span style="color: #E02020; ">}</span></pre></div></div>

</li>
<li>Finally, add a reference to the footnote inside the table:

<div class="wp_syntax"><div class="code"><pre class="latex" style="font-family:monospace;"><span style="color: #8020E0; font-weight: normal;">$^{<span style="color: #2020C0; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\decimal</span><span style="color: #E02020; ">{</span>footnote</span><span style="color: #E02020; ">}}</span>$</span></pre></div></div>

</li>
</ol>
<p>You can extend this idea to add multiple footnotes within a single <code>tabular</code> by adjusting the counters (using <code><a href="http://www-h.eng.cam.ac.uk/help/tpl/textprocessing/teTeX/latex/latex2e-html/ltx-195.html">\addtocounter</a></code>) appropriately.  Here is a complete example of how to add two footnotes inside a single <code>tabular</code> (you can see the <a href="http://dound.com/wp/files/footnote-in-tabular-example.pdf">PDF output here</a>):</p>

<div class="wp_syntax"><div class="code"><pre class="latex" style="font-family:monospace;"><span style="color: #800000; font-weight: normal;">\<span style="color: #800000; font-weight: bold;">documentclass</span></span><span style="color: #E02020; ">[</span><span style="color: #C08020; font-weight: normal;">12pt</span><span style="color: #E02020; ">]{</span><span style="color: #2020C0; font-weight: normal;">article</span><span style="color: #E02020; ">}</span>
&nbsp;
<span style="color: #800000; font-weight: normal;">\usepackage</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">fmtcount</span><span style="color: #E02020; ">}</span> <span style="color: #2C922C; font-style: italic;">% displaying latex counters</span>
&nbsp;
<span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">document</span></span><span style="color: #E02020; ">}</span>
    <span style="color: #800000; font-weight: normal;">\title</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">An Example of Footnotes Inside a Tabular</span><span style="color: #E02020; ">}</span>
    <span style="color: #800000; font-weight: normal;">\author</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">David Gridley Underhill</span><span style="color: #E02020; ">}</span>
    <span style="color: #800000; font-weight: normal;">\maketitle</span>
&nbsp;
<span style="color: #2C922C; font-style: italic;">% manually add a footnote which exists inside the table</span>
<span style="color: #800000; font-weight: normal;">\addtocounter</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">footnote</span><span style="color: #E02020; ">}{</span><span style="color: #2020C0; font-weight: normal;">1</span><span style="color: #E02020; ">}</span>
<span style="color: #800000; font-weight: normal;">\footnotetext</span><span style="color: #E02020; ">[</span><span style="color: #C08020; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\value</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">footnote</span><span style="color: #E02020; ">}</span></span><span style="color: #E02020; ">]{</span><span style="color: #2020C0; font-weight: normal;">my first footnote</span><span style="color: #E02020; ">}</span>
&nbsp;
<span style="color: #2C922C; font-style: italic;">% add another footnote</span>
<span style="color: #800000; font-weight: normal;">\addtocounter</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">footnote</span><span style="color: #E02020; ">}{</span><span style="color: #2020C0; font-weight: normal;">1</span><span style="color: #E02020; ">}</span>
<span style="color: #800000; font-weight: normal;">\footnotetext</span><span style="color: #E02020; ">[</span><span style="color: #C08020; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\value</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">footnote</span><span style="color: #E02020; ">}</span></span><span style="color: #E02020; ">]{</span><span style="color: #2020C0; font-weight: normal;">my second footnote</span><span style="color: #E02020; ">}</span>
&nbsp;
<span style="color: #2C922C; font-style: italic;">% reset the counter to the first footnote's value</span>
<span style="color: #800000; font-weight: normal;">\addtocounter</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">footnote</span><span style="color: #E02020; ">}{</span><span style="color: #2020C0; font-weight: normal;">-1</span><span style="color: #E02020; ">}</span>
&nbsp;
<span style="color: #C00000; font-weight: normal;">\begin</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">tabular</span></span><span style="color: #E02020; ">}{</span><span style="color: #E02020; "><span style="color: #2020C0; font-weight: normal;">|l|l|</span></span><span style="color: #E02020; ">}</span>
  <span style="color: #800000; font-weight: normal;">\<span style="color: #800000; font-weight: bold;">hline</span></span>
  <span style="color: #2C922C; font-style: italic;">% this next row references the first footnote I added above, and then</span>
  <span style="color: #2C922C; font-style: italic;">% advances the counter to the next footnote.</span>
  <span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\bf</span> First Column</span><span style="color: #E02020; ">}</span> <span style="color: #E02020; ">&amp;</span> <span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\bf</span> Second Column</span><span style="color: #E02020; ">}</span><span style="color: #8020E0; font-weight: normal;">$^{<span style="color: #2020C0; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\decimal</span><span style="color: #E02020; ">{</span>footnote</span><span style="color: #E02020; ">}}</span>$</span><span style="color: #800000; font-weight: normal;">\addtocounter</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;">footnote</span><span style="color: #E02020; ">}{</span><span style="color: #2020C0; font-weight: normal;">1</span><span style="color: #E02020; ">}</span> <span style="color: #E02020; ">\\</span>
&nbsp;
  <span style="color: #800000; font-weight: normal;">\<span style="color: #800000; font-weight: bold;">hline</span></span>
  <span style="color: #2C922C; font-style: italic;">% now reference the second footnote from above -- don't increment the footnote </span>
  <span style="color: #2C922C; font-style: italic;">% counter beyond the last footnote!</span>
  X <span style="color: #E02020; ">&amp;</span> Y<span style="color: #8020E0; font-weight: normal;">$^{<span style="color: #2020C0; font-weight: normal;"><span style="color: #800000; font-weight: normal;">\decimal</span><span style="color: #E02020; ">{</span>footnote</span><span style="color: #E02020; ">}}</span>$</span> <span style="color: #E02020; ">\\</span>
&nbsp;
  <span style="color: #800000; font-weight: normal;">\<span style="color: #800000; font-weight: bold;">hline</span></span>
<span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">tabular</span></span><span style="color: #E02020; ">}</span>
&nbsp;
<span style="color: #C00000; font-weight: normal;">\end</span><span style="color: #E02020; ">{</span><span style="color: #2020C0; font-weight: normal;"><span style="color: #0000D0; font-weight: normal;">document</span></span><span style="color: #E02020; ">}</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://dound.com/2009/06/latex-adding-footnotes-in-tables-or-other-floats/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>github: Send e-mail on push</title>
		<link>http://dound.com/2009/05/github-send-e-mail-on-push/</link>
		<comments>http://dound.com/2009/05/github-send-e-mail-on-push/#comments</comments>
		<pubDate>Sun, 31 May 2009 13:56:37 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[version control]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[post-receive]]></category>

		<guid isPermaLink="false">http://dound.com/?p=176</guid>
		<description><![CDATA[I&#8217;ve been looking for a way to have github, my favorite repository hosting service, send emails to interested parties whenever someone pushes new commits into the repository,  They don&#8217;t seem to provide this service directly, but they do provide both an API for programatically querying the site as well as post-receive callbacks.  The [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been looking for a way to have <a href="https://github.com/">github</a>, my favorite repository hosting service, send emails to interested parties whenever someone pushes new commits into the repository,  They don&#8217;t seem to provide this service directly, but they do provide both an <a href="http://develop.github.com/">API</a> for programatically querying the site as well as <a href="http://www.kernel.org/pub/software/scm/git/docs/githooks.html">post-receive</a> callbacks.  The latter sends a POST request to URL(s) of your choice.  The POST request includes <a href="http://www.json.org/">JSON</a> data which contains information about the repository and the new commits (for details, <a href="http://github.com/guides/post-receive-hooks">see here</a>).  Using this, I was able to put together a relatively simple <a href="http://www.php.net/">PHP</a> script which repackages this information into a human-readable form and sends it off in an email (<b><a href="https://github.com/dound/github-post-receive-php-handler/tree">source code here</a></b>).</p>
<p>I wanted to use the github API to get a list of those who watch the project, and then send an email to those people.  Unfortunately the API does not let you query that yet.  Instead, my script lets you specify the recipients manually.  Alternatively, a simple mailing list implementation is provided so people can sign up for the post-receive emails through a webpage instead.</p>
<p>The only downside is that the JSON github provides does not include information about how many lines were modified, just files.  In this respect, <a href="http://git.kernel.org/?p=git/git.git;a=history;f=contrib/hooks/post-receive-email">Andy Parkin&#8217;s post-receive</a> script produces slightly more informative e-mails (but of course it doesn&#8217;t work with github).</p>
]]></content:encoded>
			<wfw:commentRss>http://dound.com/2009/05/github-send-e-mail-on-push/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projects list updated</title>
		<link>http://dound.com/2009/05/projects-list-updated/</link>
		<comments>http://dound.com/2009/05/projects-list-updated/#comments</comments>
		<pubDate>Fri, 22 May 2009 03:13:52 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://dound.com/?p=166</guid>
		<description><![CDATA[I&#8217;ve revamped the front page to list current projects instead of past ones.  I&#8217;ve also updated the Projects page to include some more recent projects including jToolbar, a minimum spanning tree algorithm library, and the ENVI network visualization and control framework.  I also updated ltprotocol to provide additional and more symmetric (between the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve revamped the front page to list current projects instead of past ones.  I&#8217;ve also updated the <a href="http://dound.com/projects/">Projects page</a> to include some more recent projects including <a href="https://github.com/dound/jtoolbar/tree">jToolbar</a>, a <a href="https://github.com/dound/mst/tree">minimum spanning tree algorithm library</a>, and the <a href="http://www.openflowswitch.org/wp/gui/">ENVI network visualization and control framework</a>.  I also updated <a href="http://dound.com/projects/ltprotocol/">ltprotocol</a> to provide additional and more symmetric (between the client and server) callbacks.</p>
]]></content:encoded>
			<wfw:commentRss>http://dound.com/2009/05/projects-list-updated/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>git: forever remove files or folders from history</title>
		<link>http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/</link>
		<comments>http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 23:39:23 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[version control]]></category>
		<category><![CDATA[binary file]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[history]]></category>
		<category><![CDATA[remove]]></category>
		<category><![CDATA[repository]]></category>

		<guid isPermaLink="false">http://dound.com/?p=132</guid>
		<description><![CDATA[I recently had a need to rewrite a git repository&#8217;s history.  This isn&#8217;t generally a very good idea, though it is useful if your repository contains files it should not (such as unneeded large binary files or copyrighted material).  I also am using it because I had a branch where I only wanted [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had a need to rewrite a <a href="http://git-scm.com/">git</a> repository&#8217;s history.  This isn&#8217;t generally a very good idea, though it is useful if your repository contains files it should not (such as unneeded large binary files or copyrighted material).  I also am using it because I had a branch where I only wanted to merge a subset of files back into master (though there are probably better ways of doing this).  Anyway, it is not very hard to rewrite history thanks to the excellent <a href="http://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html">git-filter-branch</a> tool which comes with <a href="http://git-scm.com/">git</a>.  However, if your goal was to reduce a large repository&#8217;s size then <a href="http://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html">git-filter-branch</a> does not quite finish the job since it makes temporary backups of the filtered out files.  To remove those, you need to do a little more work.  To make it easier to permanently remove files, I wrapped it in a little bash script <a href="http://dound.com/wp/files/git-remove-history">git-remove-history</a> (also shown below) &#8212; simply go to the root of your repository and run the script with the list of files you want to delete and it will do the rest.  There is an interesting thread about doing this <a href="http://kerneltrap.org/mailarchive/git/2007/10/7/331471">here</a> on <a href="http://kerneltrap.org/">KernelTrap</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-o</span> errexit
&nbsp;
<span style="color: #666666; font-style: italic;"># Author: David Underhill</span>
<span style="color: #666666; font-style: italic;"># Script to permanently delete files/folders from your git repository.  To use </span>
<span style="color: #666666; font-style: italic;"># it, cd to your repository's root and then run the script with a list of paths</span>
<span style="color: #666666; font-style: italic;"># you want to delete, e.g., git-delete-history path1 path2</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$#</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #7a0874; font-weight: bold;">exit</span> 0are still
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># make sure we're at the root of git repo</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> .git <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Error: must run this script from the root of a git repository&quot;</span>
    <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># remove all paths passed as arguments from the history of the repo</span>
<span style="color: #007800;">files</span>=$<span style="color: #000000; font-weight: bold;">@</span>
git filter-branch <span style="color: #660033;">--index-filter</span> <span style="color: #ff0000;">&quot;git rm -rf --cached --ignore-unmatch <span style="color: #007800;">$files</span>&quot;</span> HEAD
&nbsp;
<span style="color: #666666; font-style: italic;"># remove the temporary history git-filter-branch otherwise leaves behind for a long time</span>
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> .git<span style="color: #000000; font-weight: bold;">/</span>refs<span style="color: #000000; font-weight: bold;">/</span>original<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> git reflog expire <span style="color: #660033;">--all</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span>  git <span style="color: #c20cb9; font-weight: bold;">gc</span> <span style="color: #660033;">--aggressive</span> <span style="color: #660033;">--prune</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Python + Twisted Length-Type-Based Protocol Client / Server</title>
		<link>http://dound.com/2009/03/python-and-twisted-length-type-based-protocol-client-server/</link>
		<comments>http://dound.com/2009/03/python-and-twisted-length-type-based-protocol-client-server/#comments</comments>
		<pubDate>Sun, 08 Mar 2009 09:25:12 +0000</pubDate>
		<dc:creator>David Underhill</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[client]]></category>
		<category><![CDATA[protocol]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[tcp]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://dound.com/?p=108</guid>
		<description><![CDATA[I often have a need to work with a simple TCP protocol whose messages have a header which starts with the length of the message and an integer representing the message type.  To save myself the trouble of creating and debugging a very similar custom implementation each time I have this need, I decided to package it as a simple <a href="http://www.python.org">Python</a> framework which does this for me.  It is based on the event-driven <a href="http://www.twistedmatrix.com">Twised</a> networking engine.]]></description>
			<content:encoded><![CDATA[<p>It seems like I often have a need to work with a simple TCP protocol whose messages have a header which starts with the length of the message and an integer representing the message type (<a href="http://openflowswitch.org/">OpenFlow</a> is one of many such protocols).  To save myself the trouble of creating and debugging a very similar custom implementation each time I have this need, I decided to package it as a simple <a href="http://www.python.org">Python</a> framework which does this for me.  It is based on the event-driven <a href="http://www.twistedmatrix.com">Twised</a> networking engine.  Using this simple extension on top of Twisted has a number of benefits:</p>
<ol>
<li>Automatic handling of the length and type fields when sending and receiving messages.</li>
<li>Automatic unpacking of messages based on type.</li>
<li>Client automatically tries to reconnect if the connection is lost.</li>
<li>Server can handle any number of clients simultaneously.</li>
</ol>
<p>You can view the official package on the <a href="http://pypi.python.org">PyPi</a> website <a href="http://pypi.python.org/pypi/ltprotocol">here</a>.  My local page for the package is <a href="http://dound.com/projects/python/ltprotocol/">here</a> &#8212; please <a href="http://dound.com/projects/python/ltprotocol/">view it</a> for an example on how to use this package.</p>
]]></content:encoded>
			<wfw:commentRss>http://dound.com/2009/03/python-and-twisted-length-type-based-protocol-client-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
