<?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>nick@ &#187; Code</title>
	<atom:link href="http://kavassalis.com/category/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://kavassalis.com</link>
	<description>code, carriers, cars, cooking, cameras</description>
	<lastBuildDate>Thu, 08 Dec 2011 01:57:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Steve&#8217;s incredible gift to the world&#8230;</title>
		<link>http://kavassalis.com/2011/10/steves-incredible-gift-to-the-world/</link>
		<comments>http://kavassalis.com/2011/10/steves-incredible-gift-to-the-world/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 03:19:10 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[computing]]></category>
		<category><![CDATA[steve jobs]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=936</guid>
		<description><![CDATA[No, it&#8217;s not the iPad, the iPhone, or even the iPod. It&#8217;s definitely the Mac. Steve Jobs real gift to the world was bringing the Mac to the market in 1984. The Macintosh was a major step in making personal computers pleasant and easy enough to use to gain mass market appeal. If the Mac [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_938" class="wp-caption alignright" style="width: 310px"><a href="http://kavassalis.com/wp-content/uploads/2011/10/Screen-Shot-2011-10-05-at-8.58.45-PM.png"><img class="size-medium wp-image-938" title="Screen Shot 2011-10-05 at 8.58.45 PM" src="http://kavassalis.com/wp-content/uploads/2011/10/Screen-Shot-2011-10-05-at-8.58.45-PM-300x236.png" alt="" width="300" height="236" /></a><p class="wp-caption-text">boingboing.net&#39;s excellent tribute</p></div>
<p>No, it&#8217;s not the iPad, the iPhone, or even the iPod. It&#8217;s definitely the Mac. Steve Jobs real gift to the world was bringing the Mac to the market in 1984. The Macintosh was a major step in making personal computers pleasant and easy enough to use to gain mass market appeal. If the Mac hadn&#8217;t been released then, the industry, <em>our industry</em>, would not be where it is today. You likely would not be reading this, you would not be on Facebook or Twitter, you wouldn&#8217;t know many of the people you know, especially those met online.</p>
<p>The Mac was never the market leader, but it&#8217;s existence opened peoples eyes. Computers HAD to be easy to use like the Macintosh, cryptic commands typed into dark screens weren&#8217;t going to cut it. This changed the game, the competition released competing products and the personal computer industry as we know it was born.</p>
<p>That&#8217;s was what Steve did. He didn&#8217;t invent anything brilliant. He took fantastic people and technologies and integrated them into products that created <em>market sectors</em> that didn&#8217;t exist. He took huge gambles, that industry experts almost always said would not pay off. Sometimes they didn&#8217;t. But others really did change the world. I know it&#8217;s trendy to hate Jobs, Apple, heck, anything popular with hipsters. Just don&#8217;t forget the value of what Jobs accomplished with his much too short life. Certainly the world would look very different today if the modern computer as we know it was still sitting in the halls of Xerox and the labs of Universities for another 5 or 10 years as everyone continued to type cryptic commands into their terminals&#8230;</p>
<p>Rest in peace Steve, you changed my life, and for that I will be eternally grateful.</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/10/steves-incredible-gift-to-the-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WTF bug in OS X 10.7</title>
		<link>http://kavassalis.com/2011/07/wtf-bug-in-os-x-10-7/</link>
		<comments>http://kavassalis.com/2011/07/wtf-bug-in-os-x-10-7/#comments</comments>
		<pubDate>Thu, 21 Jul 2011 13:11:20 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[10.7]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[Lion]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[OSX]]></category>
		<category><![CDATA[UNIX]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=911</guid>
		<description><![CDATA[I know I&#8217;m WAY behind on blogging. I really hope I&#8217;ll find some time ASAP. I wanna talk really quickly about Mac OS X 10.7. First the good. The UI changes are great. I have always been a fan of tiny widgets and maximizing screen real-estate. In 10.6 and prior, I went to great lengths [...]]]></description>
			<content:encoded><![CDATA[<p>I know I&#8217;m WAY behind on blogging. I really hope I&#8217;ll find some time ASAP. I wanna talk really quickly about Mac OS X 10.7.</p>
<p><a href="http://kavassalis.com/wp-content/uploads/2011/07/Screen-Shot-2011-07-21-at-8.48.jpg"><img class="alignleft size-full wp-image-912" title="Screen-Shot-2011-07-21-at-8.48" src="http://kavassalis.com/wp-content/uploads/2011/07/Screen-Shot-2011-07-21-at-8.48.jpg" alt="" width="362" height="297" /></a>First the good. The UI changes are great. I have always been a fan of tiny widgets and maximizing screen real-estate. In 10.6 and prior, I went to great lengths to shrink every font and widget. In 10.7 theres no need. Scroll bars are tiny and automatically fade out, you can full screen most apps, fonts and widgets are just smaller. Fantastic. New UI animations and transitions are everywhere and delay things a bit, hopefully there will be a TinkerTool or similar to disable them. They&#8217;re short and tolerable but as an example, I am typing a character or two into the ether when switching spaces during the animation.  I&#8217;m not really into the LaunchPad paradigm, but the MasterControl look works for me. Mail.app&#8217;s new UI is fantastic, iCal&#8217;s is a bit over the top. Mail.app&#8217;s performance (specifically around large operations and anything RSS related) is a complete train wreck. I expect a patch soon. Reverse scrolling took less than a day to adjust to (I am an iPad/iPhone user though). Autocorrect is a nice addition. The new Finder is great, Safari updates seem good, heck even the Terminal.app updates are nice! Grab an updated version of <a href="https://github.com/rootstyle/terminalcopyonselect/network" target="_blank">TerminalCopyOnSelect</a> and away you go.</p>
<p>10.7 is a huge update, in the way 10.5 was to 10.4, and at $29. If Mail.app&#8217;s performance is fixed I&#8217;ll likely be very happy.</p>
<p>Here&#8217;s a very WTF bug though. I ran into it last night and figured it was just me, or I&#8217;d boned something up. I have a bunch of shell scripts that do SSH port forwards for accessing network appliances and infrastructure behind lock and key. Half of them stopped working on me, failing to resolve their respective hosts. How strange. Amusingly <a href="http://www.makingitscale.com/" target="_blank">Brandon</a> was complaining of basically the same problem this morning so we decided to take a look.</p>
<p><a href="http://kavassalis.com/wp-content/uploads/2011/07/Screen-Shot-2011-07-21-at-8.45.jpg"><img class="alignright size-full wp-image-913" title="Screen-Shot-2011-07-21-at-8.45" src="http://kavassalis.com/wp-content/uploads/2011/07/Screen-Shot-2011-07-21-at-8.45.jpg" alt="" width="440" height="266" /></a>Some how OS X&#8217;s resolver library is no longer checking any hostname with a dot in it against the /etc/resolv.conf search directive in 10.7. Seriously. Let&#8217;s say I have a server called admin.omghi2u.com. My /etc/resolv.conf (and OS X network control panel) contain omghi2u.com in the search field. Surely, we can resolve (ping, ssh, web browse, whatever) to &#8216;admin&#8217; since it can match that as admin.omghi2u.com. Cool. Now normally, in UNIX (heck even Windows land!) if I had admin.tor.omghi2u.com and admin.chi.omghi2u.com, simply hitting &#8216;admin.tor&#8217; or &#8216;admin.chi&#8217; would match the omghi2u.com hostnames. Not the case in 10.7. Something is clearly broken in the resolver in libSystem. Oddly despite being linked to the same library, the host command still functions properly&#8230; Maybe the search logic is handled by the command itself&#8230;</p>
<p>While it&#8217;s a simple bug fix, its an annoying oversight on Apples part. Breaking basic UNIX networking functionality is kinda shameful.</p>
<p>&nbsp;</p>
<p><a href="http://kavassalis.com/wp-content/uploads/2011/07/Screen-Shot-2011-07-21-at-9.09.jpg"><img class="aligncenter size-full wp-image-914" title="Screen-Shot-2011-07-21-at-9.09" src="http://kavassalis.com/wp-content/uploads/2011/07/Screen-Shot-2011-07-21-at-9.09.jpg" alt="" width="549" height="174" /></a></p>
<p>&nbsp;</p>
<p><strong>UPDATE (JULY 26th)</strong>: <a href="http://www.makingitscale.com/2011/fix-for-broken-search-domain-resolution-in-osx-lion.html" target="_blank">Head over to Brandon&#8217;s site for a fix!</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/07/wtf-bug-in-os-x-10-7/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Emailing events out from an F5 Big-IP &#124; epic one line bash script</title>
		<link>http://kavassalis.com/2011/06/emailing-events-out-from-an-f5-big-ip-epic-one-line-bash-script/</link>
		<comments>http://kavassalis.com/2011/06/emailing-events-out-from-an-f5-big-ip-epic-one-line-bash-script/#comments</comments>
		<pubDate>Thu, 09 Jun 2011 14:36:26 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[alerting]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[F5]]></category>
		<category><![CDATA[LTM]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=800</guid>
		<description><![CDATA[Ugh it&#8217;s almost been a month since I last blogged, and I&#8217;ve had a lot to blog. It&#8217;s been super busy with a lot of big projects coming to an end at work, and I&#8217;ve spent my free time blasting through rolls of film and enjoying the awesome weather&#8230; Going to take tomorrow off and [...]]]></description>
			<content:encoded><![CDATA[<p>Ugh it&#8217;s almost been a month since I last blogged, and I&#8217;ve had a lot to blog. It&#8217;s been super busy with a lot of big projects coming to an end at work, and I&#8217;ve spent my free time blasting through rolls of film and enjoying the awesome weather&#8230; Going to take tomorrow off and just write up any of the blog posts I can remember&#8230;..</p>
<p><a href="http://kavassalis.com/wp-content/uploads/2011/06/bigip.jpg"><img class="alignright size-full wp-image-803" title="bigip" src="http://kavassalis.com/wp-content/uploads/2011/06/bigip.jpg" alt="" width="355" height="133" /></a>I&#8217;m not a huge bash guy,  in fact nine times out of ten I&#8217;ll chose perl. I like the way perl hands strings, escaping and its general syntax better. Sometimes however, it&#8217;s just better to use bash, say for a cron, especially if you can pull it off in one line (instead of maintaining a script on disk). This is definitely advantages when you are adding a cron to an appliance, it&#8217;s nice to maintain everything that isn&#8217;t provided by the managed distribution in a single location (i.e. root&#8217;s crontab)</p>
<p>I&#8217;m a big fan of F5, the Big-IP product line is fantastic as is their support. Theres definitely a lot of way to get alerting, the best of which would be SNMP, or even have the included alertd directly email your pagers. Personally, I don&#8217;t have an SNMP driven alerting system, 99% of our devices/systems are actively monitored by dedicated monitoring systems. Modifying alertd has the problem that you have to port your changes forward during any OS updates, and we are currently split between OS 9.x and OS 10.</p>
<p>I decided to write a quick little non-intrusive script (no changes OS configuration, nothing to maintain changes to), and keep it as a single cronable line, to comb the LTM logs (though this could easily be used for GTM logs as well) and email out notifications. The log looks like:</p>
<p><code><br />
Jun  8 17:31:09 local/tmm notice tmm[1823]: 01070028:3: No members available for pool db-cluster.omghi2u.dev<br />
Jun  8 19:12:17 local/ltm1 notice mcpd[3377]: 01070640:5: Node 192.168.110.82 monitor status down.<br />
Jun  8 19:13:51 local/ltm1 notice mcpd[3377]: 01070728:5: Node 192.168.110.82 monitor status up.<br />
Jun  8 19:13:51 local/tmm notice tmm[1823]: 01070028:3: No members available for pool web-cluster.sup2u.qa<br />
Jun  8 19:15:08 local/ltm1 notice mcpd[3377]: 01070727:5: Pool member web2.sup2u.qa:80 monitor status up.<br />
</code></p>
<p>The log formatting in OS9 is a bit less verbose than OS10, but basically it always starts with a timestamp formatted %b %e %H:%M:%S, then the log entry (OS9 lacks the log level and context). We want to check every 5 minutes (could be bumped to every minute) for any new entries in the last 5 minutes, and email them out if they aren&#8217;t stuff we don&#8217;t care about.</p>
<p>Some cool stuff of note: if you want to do a for loop on new lines instead of any whitespace, you need to change the IFS variable around. Just make sure you unset it when you are done or you will screw your terminal (or cron run!) up. The code originally looked like:</p>
<p><code><br />
export IFS=$(echo -en "\n\b"); guts=$(for i in `cat /var/log/ltm | awk '{print $1 " " $2 " " $3}'` ; do unixtime=$(date --date=$i +"%s"); if (( unixtime &gt; `date --date="5 minutes ago" +%s` )); then grep `date --date="@$unixtime" +"%b %e %H:%M:%S"` /var/log/ltm; fi; done | sort | uniq | grep -v -f /root/ltm_excludes.txt); if [ -n "$guts" ]; then echo "$guts" | mail -s "$HOSTNAME logs" "ops@zomghi2u.com"; fi; unset IFS;<br />
</code></p>
<p>And worked like a charm on OS10, but OS9 is based on Redhat 3, and has an ancient version of the date command that didn&#8217;t support the @timestamp format. Lovely. Theres lots of people using the pure date command to get around this, but timezones become a problem and are messy. It&#8217;s way better to use awk&#8217;s wrapper to strftime() and thus our fully backward compatible cron is:</p>
<p><code><br />
*/5 * * * * export IFS=$(echo -en "\n\b"); guts=$(for i in `cat /var/log/ltm | awk '{print $1 " " $2 " " $3}'` ; do unixtime=$(date --date=$i +"\%s"); if (( unixtime &gt; `date --date="5 minutes ago" +\%s` )); then grep `date --date=\`echo | awk "{ print strftime(\"\%c\", $unixtime) }"\` +"\%b \%e \%H:\%M:\%S"` /var/log/ltm; fi; done | sort | uniq | grep -v -f /root/ltm_excludes.txt); if [ -n "$guts" ]; then echo "$guts" | mail -s "$HOSTNAME logs" "ops@zomghi2u.com"; fi; unset IFS;<br />
</code></p>
<p>Only thing I wasn&#8217;t totally happy with was that I had to do a dumb echo | into awk. I couldn&#8217;t figure out (from the man page and a quick googling) how to get awk to do it&#8217;s thing without stdin or a file. Oh well. That was a lot of fun to write. You could change it to a whitelist by making a /root/includes.txt kind of file and losing the -v on grep. In fact you could have two crons. General alerts goto your ops inbox, alerts you are worried about (like pools having no members left :D) go to your emergency inbox (pagers). Or many crons. Or actually just hack up the alertd.conf&#8230; Or alert on SNMP! Either way, happy scripting!</p>
<p>UPDATE: (June 21st, 2011) On a day filled with a particularly large number of port scans resulting in lots of grep-filtered RST response messages, we decided to move the grep -v up to the beginning instead of at the end, this increases performance immensely. No more spikes on the CPU0 graphs! Here&#8217;s the updated script, smarter logic this time &#8217;round:<br />
<code><br />
*/5 * * * * export IFS=$(echo -en "\n\b"); guts=$(for i in `grep -v -f /root/ltm_excludes.txt /var/log/ltm | awk '{print $1 " " $2 " " $3}'` ; do unixtime=$(date --date=$i +"\%s"); if (( unixtime > `date --date="5 minutes ago" +\%s` )); then grep `date --date=\`echo | awk "{ print strftime(\"\%c\", $unixtime) }"\` +"\%b \%e \%H:\%M:\%S"` /var/log/ltm; fi; done | sort | uniq ); if [ -n "$guts" ]; then echo "$guts" | mail -s "$HOSTNAME logs" "ops@zomghi2u.com"; fi; unset IFS;<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/06/emailing-events-out-from-an-f5-big-ip-epic-one-line-bash-script/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Labelling switch ports, the easy way!</title>
		<link>http://kavassalis.com/2011/05/labelling-switch-ports-the-easy-way/</link>
		<comments>http://kavassalis.com/2011/05/labelling-switch-ports-the-easy-way/#comments</comments>
		<pubDate>Wed, 11 May 2011 14:02:52 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[snmp]]></category>
		<category><![CDATA[switches]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=696</guid>
		<description><![CDATA[Problem: You have many (many many) servers and you want to know which server is on which switch port. Short of a manual (and very time consuming) cable trace and box audit, how do you make sure stuff is plugged in where you think it is? Solution: Ask the switch who lives where, make perl [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Problem:</strong> You have many (many many) servers and you want to know which server is on which switch port. Short of a manual (and very time consuming) cable trace and box audit, how do you make sure stuff is plugged in where you think it is?</p>
<p><strong>Solution</strong>: Ask the switch who lives where, make perl do the heavy lifting!</p>
<p>Our HP ProCurves provide what they call &#8216;port address tables&#8217; which basically tell you which MACs are seen on which ports. A bit of digging and that info was just an SNMP call away. The MACs are stored in decimal format, in the OID, and the integer value it points to is the port number. Ports after physical ports (on ProCurves) are VLANs and Trunks. (The mappings and locations of ports is probably completely vendor specific though!)</p>
<p>Once we have that MAC address, we can pretty it up, map it to an actual hostname, and then label the ports with that. No more will you have to check another table, database, text file, etc and say, hey where is XYZ plugged into&#8230; The 30 minute dirty perl code:</p>
<pre>
#!/usr/bin/perl
# switchLabel.pl - 5/10/2011 (dirty 30 minute hack version)
# label ports on an HP Procurve switch with their boxes MAC address (easy to lookup)
# and even their hostnames! --nick@fmpub.net

# configs
$debugMode = 1;

# code dont touch
if ( $#ARGV < 1 ) {
       print "usage: switchLabel.pl [switch IP/hostname] [community]\n";
       die("Please specify a switch IP and a valid r/w community string!\n");
} 

sub debug
{
        use vars qw($debugMode);
        if ($debugMode == 1) {
                print $_[0];
        }
}

my $switchIP = $ARGV[0];
my $snmpCommunity = $ARGV[1];

my $numPorts = 48; # after this is trunks and vlans, which we're going to ignore
                                  # label them manually kthx
                                  # change me for big chassis switches
                                  # could become another (optional) config variable

my @snmpWalk = `snmpwalk -On -c $snmpCommunity -v2c $switchIP 1.3.6.1.2.1.17.4.3.1.2`;
my %switchPorts = ();

foreach (@snmpWalk) {
 	$_ =~ s/.1.3.6.1.2.1.17.4.3.1.2.//; # lazy ass formating
	$_ =~ s/ = INTEGER: / /;
	chomp;
	($decMac, $port) = split(/ /, $_);
	if ($port <= $numPorts &#038;&#038; $port > 0) {
		my @macOctets = split(/\./, $decMac);
		my $hexMac = "";
		foreach (@macOctets) {
			$_ = sprintf("%0.2X", $_);
		}
		$hexMac = join(':', @macOctets);
		debug("[found] $hexMac @ $switchIP: port $port\n");

		# put code in here to map MACs back to boxnames
		# or leave a MAC for now...
		my $machineName = $hexMac;

		if (!$switchPorts{$port}) {
			$switchPorts{$port} = $machineName;
		} else {
			$switchPorts{$port} .= ", " . $machineName;
		}
	}
}

for ($i = 1; $i <= $numPorts; $i++) {
	if ($switchPorts{$i}) {
		my $portName = $switchPorts{$i};
		if (length($portName) > 64) {
			$portName = substr($portName, 0, 61) . "...";
		}
		debug("[assign] $i => $portName\n\t");
                debug(`snmpset -c $snmpCommunity -v2c
                      $switchIP .1.3.6.1.2.1.31.1.1.1.18.$i s "$portName"`);
                 #the above line was broken in half for awful wordpress formatting
	}
}
</pre>
<p>I&#8217;ve removed our implementation specific MAC address to hostname mapping bit. Basically you can tackle that a few different ways, do an ARP lookup on a box that sees and knows all, query an SQL table where you do inventory, whatever you want. Just drop it in, and if (!machineName), put the hexMac in instead (i.e. you have an unknown box!) You could (and I probably will) extend this code to alert you if boxes move around (i.e. without you knowing), for audit-ability purposes.</p>
<p>This awesome reverse mapping of MAC addresses looks to be the same as Cisco&#8217;s dynamic CAM entries table, and they are on the same OID. (In fact I wager Cisco came up with that specification) That means this above code should work on a Catalyst with no modification but I haven&#8217;t tried it :) I have (and always will be) a Cisco big iron fanboy, but these ProCurves are totally awesome for anything other than edge and carrier distribution. All the SNMP goodies you&#8217;d ever need can be found on a sub-$250 HP 2510, and thats with a lifetime warranty and support&#8230;. (insane)</p>
<p><a href="http://redbull.evul.net/~nick/src/switchLabel.txt" target="_blank">Grab the code and play around</a> and always remember, snmpwalk is a network admins best friend!</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/05/labelling-switch-ports-the-easy-way/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>O&#8217;Reilly MySQL CE 2011: Josh Berkus, &#8220;Scale Fail&#8221;</title>
		<link>http://kavassalis.com/2011/04/oreilly-mysql-ce-2011-josh-berkus-scale-fail/</link>
		<comments>http://kavassalis.com/2011/04/oreilly-mysql-ce-2011-josh-berkus-scale-fail/#comments</comments>
		<pubDate>Wed, 20 Apr 2011 01:35:07 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=666</guid>
		<description><![CDATA[I sent this out to our engineering department today, it&#8217;s mean, it&#8217;s exaggerated, it&#8217;s sarcastic, it&#8217;s hilarious. Enjoy:]]></description>
			<content:encoded><![CDATA[<p>I sent this out to our engineering department today, it&#8217;s mean, it&#8217;s exaggerated, it&#8217;s sarcastic, it&#8217;s hilarious. Enjoy: </p>
<p><iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/nPG4sK_glls?rel=0&amp;hd=1" frameborder="0" allowfullscreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/04/oreilly-mysql-ce-2011-josh-berkus-scale-fail/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IRIX porting: GCC extensions, missing functions and more fun</title>
		<link>http://kavassalis.com/2011/04/porting-gcc-extensions-missing-functions-and-more-fun/</link>
		<comments>http://kavassalis.com/2011/04/porting-gcc-extensions-missing-functions-and-more-fun/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 13:47:57 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[irix]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=628</guid>
		<description><![CDATA[I&#8217;ve spun up an IRIX machine at home to replace my long dead Linux based file server / general network management box. (It&#8217;s a 2-node IP45 Origin rack, so 8 sockets of R14000 lovin&#8217;) I don&#8217;t really like to have more than 1 active server and 1 active desktop at home at a time for [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_631" class="wp-caption alignleft" style="width: 470px"><img class="size-full wp-image-631" title="Jurassic-Park-001" src="http://kavassalis.com/wp-content/uploads/2011/04/Jurassic-Park-001.jpg" alt="" width="460" height="276" /><p class="wp-caption-text">It&#39;s a UNIX system, I know this!</p></div>
<p>I&#8217;ve spun up an IRIX machine at home to replace my long dead Linux based file server / general network management box. <a href="http://kavassalis.com/wp-content/uploads/2011/04/1HJ6.jpg" target="_blank">(It&#8217;s a 2-node IP45 Origin rack, so 8 sockets of R14000 lovin&#8217;)</a> I don&#8217;t really like to have more than 1 active server and 1 active desktop at home at a time for simplicity / heat / space reasons. I&#8217;ve been an avid IRIX user since 1990, in the golden days of the Personal IRIS and 4D/480. It was my first UNIX and will always have a special place in my heart. SGI has retired the platform and it will go End of Support in 2013, and the final generation of IRIX hardware is becoming outdated on a GFLOP/watt basis now, and thusly affordable!</p>
<p>&nbsp;</p>
<p>IRIX is POSIX, POSIX2 compliant, really strictly. It was based on SysV and later got several BSD extensions added, but anything that isn&#8217;t mandated with POSIX probably isn&#8217;t there unless they wanted it within the halls of SGI. It&#8217;s profiling support, native debugging tools and general sysadmin usability are still unmatched. I can still install and configure an SGI box in my sleep, I will definitely be sad the day the final IRIX hardware is thoroughly useless performance wise.</p>
<p>Enough of the background though, I didn&#8217;t want to turn this into a sappy rant over a dead platform. I&#8217;ve been porting stuff to IRIX for a decade at least, I find as an exercise it&#8217;s very enjoyable. I&#8217;ve often found myself porting stuff over only to never use it or even nuke it for the sake of the exercise itself. I find it generally makes you a more &#8216;aware&#8217; C (and UNIX) programmer, especially of stuff outside of the realm of Linux and GCC. I ran into a really cool one late last night. I&#8217;ve been working with a bunch of caching engines, on all layers of the equation (object, code, front end), and while I do all of my actual performance testing in Linux land, I&#8217;ve been doing some IRIX ports for shiggles. I ran into in a pretty basic mmap which is what spurred me to write this article:</p>
<blockquote><p>return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);</p></blockquote>
<p>Pretty basic, MAP_PRIVATE specifies that modifications to our memory map are private, that is our changes won&#8217;t make it to the file descriptor, it&#8217;s copy on write. MAP_ANONYMOUS (at least to me) always seemed like a given too, in Linux/BSD/Solaris it ignores the file descriptors and just gives you a zero&#8217;d memory. OS&#8217; all seem to implement this differently, just reading the OS X man page it looks like you can pass flags to the Mach VM about tags and its purgability. IRIX (and HP-UX it seems) completely lacks it. No biggie! Sure enough we can accomplish the same thing thusly!</p>
<blockquote><p>static int devZero;<br />
devZero = open(&#8220;/dev/zero&#8221;, 2);<br />
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, devZero, 0);</p></blockquote>
<p>Easy peasy. Open a file descriptor to /dev/zero, kernel then knows what to do. Worked like a charm, fast in memory caching was a go!</p>
<div id="attachment_630" class="wp-caption aligncenter" style="width: 553px"><img class="size-full wp-image-630" title="Screen-shot-2011-04-13-at-9.33" src="http://kavassalis.com/wp-content/uploads/2011/04/Screen-shot-2011-04-13-at-9.33.jpg" alt="" width="543" height="92" /><p class="wp-caption-text">Ok so this is an OS X portability issue, but IRIX lacks daemon() too. The error was just too good to not include in a portability article :P</p></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Let&#8217;s talk about some other Linux/IRIX/UNIX/whateverisms. I&#8217;m just going to skim the surface but here we go&#8230;.</p>
<p style="text-align: left;">You also run into lots of cases where IRIX&#8217;s libc does not support many &#8216;givens&#8217; in the Linux (and even FreeBSD and even sometimes Solaris&#8217;) libc. I was working on porting varnish to IRIX on Sunday morning, and while we&#8217;re still in the syscall tracing phase due to some misbehaving of its internal code compiler, but I&#8217;ll use it as an example as it had two of the most common functions that are easy substitutions I see all the time:</p>
<p><strong>setenv()</strong> setenv was added to UNIX version 7 back in 1979, somehow IRIX completely lacks it. It&#8217;s pretty easy to throw putenv in for most cases though. Looking at the varnish source we swap:</p>
<pre>        AZ(setenv("TZ", "UTC", 1));</pre>
<p>for</p>
<pre>        AZ(putenv("TZ=UTC"));</pre>
<p>Same goes for <strong>wait4()</strong>, it&#8217;s part of System 4 but not specified by POSIX so IRIX completely lacks it. Thankfully it&#8217;s what waitpid() is implemented with on many platforms (BSD), so if the *rusage isn&#8217;t specified, we can do a direct swap thusly:</p>
<pre>        r = wait4(v-&gt;pid, &amp;status, 0, NULL);</pre>
<p>becomes</p>
<pre>        r = waitpid(v-&gt;pid, &amp;status, 0);</pre>
<p>Varnish needed a few other tweaks, stuff like IOV_MAX isn&#8217;t specified in any IRIX headers, but can be gleaned from sysconfig (1024). CLOCK_MONOTONIC is not defined, but thankfully they had Solaris conditionals around it that became Solaris and IRIX conditionals.  Fun.</p>
<p>Onto GCCisms. GCC is a great compiler suite. Supports a ton of software/hardware, but it will never been the fastest on any platform. On SGI&#8217;s we have MIPSpro and on PC&#8217;s you have Intel&#8217;s really awesome compiler suite. (We used to use Intel&#8217;s suite at Cedara for our x86 medical imaging software, strictly based on its killer performance). I tend to try and port stuff to MIPSpro unless you run into too many bad GCCisms. Sometimes I think that GCC being the defacto &#8216;nix compiler, has lead people (likely CS students) to believe thats just &#8220;the way things are&#8221;.</p>
<p><strong>Zero length arrays </strong>i.e.</p>
<pre>char contents[0];</pre>
<p>Ok so it is a clever way to throw a place holder into a struct, but this could be totally handled with a char *contents; pointer too.. Not portable though&#8230;</p>
<p><strong>Variable length arrays</strong> i.e.</p>
<pre>char str[strlen (s1) + strlen (s2) + 1];</pre>
<p>Again, its a clever way to do really basic memory handling without thinking about it, but ugh. C99 does support variable length arrays, but GCC allows them in C89 and C++ code too, just to muck shit up. Don&#8217;t use these outside of C99 code, it will not be portable.</p>
<p>There are so many more, but these are the most common I tend to see. <a href="http://web.mit.edu/gnu/doc/html/gcc_8.html" target="_blank">GNU has a guide on their extensions to the C language</a>, and totally there is lots of really useful stuff there, but just know that it breaks portability. This rant would have a lot more meaning if people used much other than GCC, but nowadays even embedded development and video game consoles are moving toward GCC. At this point in time I honestly don&#8217;t see another compiler suite beating GCC but who knows&#8230;</p>
<p>Code, port, hack. Expect more cooking stuff soon :P</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/04/porting-gcc-extensions-missing-functions-and-more-fun/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nifty procmail recipe for mail piping</title>
		<link>http://kavassalis.com/2011/03/nifty-procmail-recipe-for-mail-piping/</link>
		<comments>http://kavassalis.com/2011/03/nifty-procmail-recipe-for-mail-piping/#comments</comments>
		<pubDate>Fri, 25 Mar 2011 11:38:42 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=543</guid>
		<description><![CDATA[The challenge? Redirect all emails to a domain to a pipe, with the receiver and sender as arguments, using sendmail. This is pretty trivial in postfix, but is a bit challenging in sendmail. You can&#8217;t simply pipe it through an alias, sendmail doesn&#8217;t extract/mangle the headers. Thankfully the swissarmy tool of mail deliver, procmail comes [...]]]></description>
			<content:encoded><![CDATA[<p>The challenge? Redirect all emails to a domain to a pipe, with the receiver and sender as arguments, using sendmail. This is pretty trivial in postfix, but is a bit challenging in sendmail. You can&#8217;t simply pipe it through an alias, sendmail doesn&#8217;t extract/mangle the headers. Thankfully the swissarmy tool of mail deliver, procmail comes to the rescue.</p>
<p>The main difficulty is grabbing the To/From headers. You can use bash using the SHELL directive within a procmailrc file, however we don&#8217;t want to process all the email (since this is a relatively intensive process). So we wrap everything in a conditional for our domain. Once the { } brackets come out, procmail acts as if its a totally new .procmailrc script, and you can perform your shell scripting before delivery (or matching) as desired. The script:</p>
<p>&nbsp;</p>
<pre>SHELL=/bin/sh
LOGFILE=procmail.log

:0
* ^TO *mydomain.evul.net
{
    FROM=`formail -x"From " | sed 's/^\([^@]*[ &lt;]\)//' | sed 's/\([ &gt;]\).*$//'`
    TO=`formail -x "To:" | sed 's/^\([^@]*[ &lt;]\)//' | sed 's/\([ &gt;]\).*$//'`
    :0
    | /usr/bin/php /path/to/my/script.php ${FROM} ${TO}
}</pre>
<p>Efficient? No. It&#8217;s a good 8 forks for every email, and I don&#8217;t wanna check how many fopen()s&#8230; Such a solution would not work for any high volume of email, but for a relatively low (say thousands/day) its good enough.</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/03/nifty-procmail-recipe-for-mail-piping/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux and the maximum number of processes (threads)</title>
		<link>http://kavassalis.com/2011/03/linux-and-the-maximum-number-of-processes-threads/</link>
		<comments>http://kavassalis.com/2011/03/linux-and-the-maximum-number-of-processes-threads/#comments</comments>
		<pubDate>Thu, 03 Mar 2011 22:10:57 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[limits]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=437</guid>
		<description><![CDATA[So last night we  were debugging some odd Apache behaviour when we discovered that RHEL6 has modified the default number of processes (which includes threads in linux, but I&#8217;ll refer to it as procs for the purpose of this article). In RHEL5 (and prior), each user is given the default fork init number of threads [...]]]></description>
			<content:encoded><![CDATA[<p>So last night we  were debugging some odd Apache behaviour when we discovered that RHEL6 has modified the default number of processes (which includes threads in linux, but I&#8217;ll refer to it as procs for the purpose of this article). In RHEL5 (and prior), each user is given the default fork init number of threads (which we&#8217;ll discuss shortly). It&#8217;s a huge number usually, 106, 496 threads on my RHEL5 dev box here. RHEL6 on the other hand, drops a file into /etc/security/limits.d that limits all users to 1024 procs.</p>
<p style="text-align: center;"><a href="http://mlkshk.com/r/RFS" target="_blank"><img class="aligncenter" src="http://mlkshk.com/r/RFS" alt="" width="554" height="79" /></a></p>
<p>Now, /etc/security/limits.conf and /etc/security/limits.d are read by PAM&#8217;s pam_limits.so, so only things that use PAM will ever touch these. Apache starting on a server reboot is not affected by these limits, so Apache will have access to its full 106,496 threads. But if root restarts apache from a shell (/etc/init.d/httpd restart or service httpd restart), Apache will inherit root&#8217;s proc limit of 1024! This can be verified with a &lt;?php passthru(&#8216;ulimit -u&#8217;); ?&gt; via mod_php.</p>
<p><a href="http://mlkshk.com/p/RFT"  target="_blank"><img class="alignleft" src="http://mlkshk.com/r/RFT" alt="" width="373" height="76" /></a>1024 threads is totally not enough for reasonable operation in Apache. It will begin to kill children off as they seteid() to its designated user as the call fails with errno 11. (seteid() has not always performed an nproc check, this was added in some 2.6 kernel to prevent people from sneaking over the limit) You can work around this by dropping a <em>ulimit -u &lt;much higher number&gt;</em> into /etc/sysconfig/httpd, but my preferred solution is to remove (blank) RHEL6&#8242;s new /etc/security/limits.d/90-nproc.conf . (Or I guess you could just never restart your apache, best to reboot the system if theres a problem :P) Thanks Redhat.</p>
<p>Back to that large 106,496 number. Thats the maximum number of procs that nick as a user can spawn, even using ulimit -u he can&#8217;t go higher than that. The system&#8217;s maximum number of threads (visible in /proc/sys/kernel/threads-max) is 212992 (exactly double) is decided at boot time by the kernel. I decided to do some digging in the kernel source and the maximum number of threads is calculated thusly:</p>
<p style="padding-left: 30px;">max_threads = totalram_pages / (8 * THREAD_SIZE / PAGE_SIZE);</p>
<p style="padding-left: 30px;"><em>(defined in kernel/fork.c, called by init/main.c)</em></p>
<p>PAGE_SIZE is architecture specific, for x86 it&#8217;s 4kb (and 4MB but thats a discussion for another day), and is calculated via:</p>
<p style="padding-left: 30px;">#define __AC(X,Y)       (X##Y)<br />
#define _AC(X,Y)        __AC(X,Y)<br />
#define PAGE_SHIFT      12<br />
#define PAGE_SIZE       (_AC(1,UL) &lt;&lt; PAGE_SHIFT)</p>
<p>PAGE_SHIFT is a constant for x86, other architectures support alternate (larger) page sizes. THREAD_SIZE is also architecture specific:</p>
<p style="padding-left: 30px;">#define THREAD_ORDER    1<br />
#define THREAD_SIZE  (PAGE_SIZE &lt;&lt; THREAD_ORDER)</p>
<p>THREAD_ORDER is 1 in x86, but can vary depending on the arch. These result in a PAGE_SIZE of 4096 and a THREAD_SIZE of 8192 for x86. Back to the formula  above, we can fill it in as:</p>
<p>&nbsp;</p>
<p style="padding-left: 30px;">max_threads = totalram_pages / (8 * 8192 / 4096);</p>
<p style="padding-left: 30px;">becomes</p>
<p style="padding-left: 30px;">max_threads = totalram_pages / 16 ;</p>
<p>Calculating totalram_pages is a bit tricky since its not just the full system ram allocated to pages. The easiest way to calculate it from /proc/zoneinfo, by summing the spanned pages:</p>
<p style="padding-left: 30px;">cat /proc/zoneinfo | grep spanned | awk &#8216;{totalpages=totalpages+$2} END {print totalpages}&#8217;<br />
3407872</p>
<p>So on my server with 12 gigabytes of memory we&#8217;ve got:</p>
<p style="padding-left: 30px;">max_threads =  3407872 / 16;</p>
<p style="padding-left: 30px;">becomes</p>
<p style="padding-left: 30px;">max_threads = 212992;</p>
<p>Now the default maximum number of threads is designed to be able to only consume half the memory from threads alone. But one user should also not be able to consume all of the threads on the system. Back in kernel/fork.c we have:</p>
<p style="padding-left: 30px;">init_task.signal-&gt;rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;<br />
init_task.signal-&gt;rlim[RLIMIT_NPROC].rlim_max = max_threads/2;</p>
<p><a href="http://mlkshk.com/p/RFU"  target="_blank"><br />
<img class="alignright" src="http://mlkshk.com/r/RFU" alt="" width="373" height="107" /></a></p>
<p>So there you have it, the ulimit -u for nick (or root) is now set to 106496 procs (threads). nick is unable to take up all of the processes on a box, even using ulimit, he cannot raise past max_threads/2 (106496, though root can). Unless modified via /proc/sys/kernel/threads-max, a maxed out system will not use more than 50% of the memory to store thread structures. Hopefully you too now know a little bit more about linux process limits! Big thanks to colleague and friend Jim Hull for his troubleshooting and major help last night.</p>
<p><em>The exact formulas may vary kernel to kernel, my findings were through the kernel 2.6.37 source and verified on RHEL5&#8242;s heavily modified 2.6.18-194 kernel</em></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/03/linux-and-the-maximum-number-of-processes-threads/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How to run a secure mobile phone contest</title>
		<link>http://kavassalis.com/2011/02/how-to-run-a-secure-cell-phone-contest/</link>
		<comments>http://kavassalis.com/2011/02/how-to-run-a-secure-cell-phone-contest/#comments</comments>
		<pubDate>Tue, 15 Feb 2011 04:20:36 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[cell phone]]></category>
		<category><![CDATA[contest]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[QR]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=356</guid>
		<description><![CDATA[As someone who&#8217;s been around the web application block a few times, I&#8217;m always on the look out for great web apps, and terrible web apps. I love great web apps. A great web app is attractive, responsive, intuitive, useful and secure. Another thing I love are QR codes. Original created by DENSO as a [...]]]></description>
			<content:encoded><![CDATA[<p>As someone who&#8217;s been around the web application block a few times, I&#8217;m always on the look out for great web apps, and terrible web apps. I love great web apps. A great web app is attractive, responsive, intuitive, useful and secure.</p>
<p>Another thing I love are <a href="http://justinsomnia.org/2010/06/im-famous-on-a-brazilian-futebol-site/" target="_blank">QR codes</a>. Original created by DENSO as a way of streamlining their huge automotive parts manufacturing business, they are essentially a high capacity barcode. QR codes became popular in the land of cell phone cameras (Japan) to point URLs for extra product info, free ringtones, images and for contests. This trend has of course spread here and is a lot of fun.</p>
<p>The premiss is simple. Anyone with a camera equipped phone (and nowadays this is almost every phone) can take a photo of your QR code, then using one of many free apps, translate it into a URL. One of my favourite QR code contests involved finding five different ads (for different flavours) of Maynards candy. You had to plug an email in for each one, and when you had obtained them all, you would be entered into a draw to win one of several prizes. I scoured the subway car I was in to find all the different ads (which were all different sizes), I was involved, I was smiling, it was a good execution. Of course I didn&#8217;t win but I enjoyed it anyway.</p>
<p><a href="http://mlkshk.com/p/IM9"  target="_blank"><img class="alignright" width='320' height='240' src="http://mlkshk.com/r/IM9"></a><br />
I recently encountered another QR based contest which was a give-away for a clothing store. It was pretty simple, you had to scan the code on the back of the catalog, and they would give away one gift card every day for a month and a half. My love of QR codes and these mobile contests lead me to enter it. Upon scanning the code I realized that the URL I was pointed to was non unique, that is, every catalog had the same QR code. When my phone actually visited the URL I was told I was not a winner. The experience was simple and quick which is definitely good. However when I began thinking about it, the simplicity of this contest is a serious flaw.</p>
<p>Since the contest declares an instant loss (or win), someone would just have to hit the contest repeatedly, looking for anything but a loss. Throw in some common mobile phone user-agents and a small pool of IPs in a roulette, you no longer look like a bot. Throw in randomized but short delays in between attempts and you are beginning to look human, moreover, like many humans. Pretty soon our poor contest has little defense against even a novice hacker&#8230;</p>
<p>The whole premiss of this contest is that there is one winner a day, however since you are declared a loser (or winner) right away, how do they randomly chose a winner? Basically they are rolling a huge dice with a very large number of sides, say a hundred thousand. A winner could be declared a minute after midnight making the entire days contest moot, or a minute before midnight. Once a winner is found, the contest stops rolling and declares everyone a loser. A true daily winner would require selecting one from the true pool of entrants during a 24 hour period. Asking for an email and randomly picking a winner at midnight accomplishes the goal and has real advantages for fraud prevention. We&#8217;ll talk more about using an email address later.</p>
<p>I think the #1 concern of any developer of a contest (web or otherwise) should be how to stop gaming, hacking or fraud, whatever name you chose to give it. :) You need to be able to accurately track entrants, and for the web this can be accomplished in at least three ways. The first is through an IP address. However this becomes a problem since many ISPs use proxy servers to keep their transit costs down. It becomes impossible for a primarily mobile contest as most phones do not get a unique IP, they are NAT&#8217;d out one (or a small handful) or IPs assigned to a specific cell tower. The second way to track entrants is through a tracking cookie, however defeating this for someone interested in gaming your contest is trivial. Do not rely on cookies to declare someone unique! The third solution is utilizing some sort of external tracking method, that is, do not track them through their hit of the contest URL. The best way to do this would be actual unique QR codes tied to each consumer&#8217;s catalog, with some real cryptography behind the unique string. Unfortunately this would add to the cost of printing the catalogs and may not be an option. However there are alternative methods of tracking entrants external to the actual web hit.</p>
<p>With most web based contests you would require an email address of an entrant. Creating fake email addresses isn&#8217;t difficult, but its a good hurdle and one thats fairly easy to detect. (Did you see a million entries from zomg48.info? it&#8217;s probably junk, filter it. Do a daily report on top email domains: audit audit audit!) However, since this is a mobile contest an email verification might break the flow of the app since you no longer declare that instant loss (or win), and it requires a person to enter a potentially large string (their email address) on a cell phone. </p>
<p>Alternatively, if you must declare an instant winner, you can always use a captcha. Captchas are not fool proof, but they are certainly a hurdle that would dissuade most fraud. The real draw back to captchas is that they annoy users enough on desktop web applications. Mobile web apps needs to be streamlined, and easy to use on small screens. Captchas aren&#8217;t particularly good at either of these things&#8230;</p>
<p>I really didn&#8217;t like the email approach (breaks the mobile flow), nor do I like captchas on mobile platforms. In talking to my good friend <a href="http://www.makingitscale.com/" target="_blank">Brandon</a>, he had a good suggestion. When a user hits the QR encoded URL, take them to a page where they enter their mobile number. From there you can either declare an instant winner via SMS or even SMS them at noon the next day for a true daily winner. SMS them a secure unique URL to hit to fill in their personal details, then dispatch their prize. An instant SMS wouldn&#8217;t break the flow, since SMS delivery is pretty much guaranteed as a capability of anyone entering your contest, where as email isn&#8217;t reliably instant for non-savvy smart phone users. Compared to an email address, mobile numbers are also much easier (and quicker) for cell phone users to enter on a page.</p>
<p>I guess to summarize the above:</p>
<li>Uniques based on IP is a no go for anything mobile
<li>Declaring a cooking-unique winner each day is totally silly
<li>Taking an email and declaring a daily winner is an ok idea
<li>Using a captcha and declaring an instant winner is an ok idea
<li>Taking an SMS number and declaring an instant winner (or even daily winner) is a great idea<br />
<br />
<hr />
<p>I guess thats basically it. If you work for a dev house that people outsource complete contests to like the one described above, it&#8217;s your duty to develop and maintain a secure and fair contest. Write something to defeat trivial gaming/fraud, audit daily traffic, audit winners. This is why people outsource something to a firm instead of hiring a college student and handing them creatives. Do you have an even better idea for running a secure contest? How would you ensure entrants are unique while still providing an easy entry that people will want to repeat (daily). A contest thats annoying to enter does nothing for a brand. Nor does one thats inherently insecure or unfair. It&#8217;s even worse when its a turn key mobile advertising product your company sells and skins for different retailers&#8230;</p>
<p>Happy coding, until next time!</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2011/02/how-to-run-a-secure-cell-phone-contest/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lack of updates, link aggregation</title>
		<link>http://kavassalis.com/2010/05/lack-of-updates-link-aggregation/</link>
		<comments>http://kavassalis.com/2010/05/lack-of-updates-link-aggregation/#comments</comments>
		<pubDate>Wed, 05 May 2010 14:06:19 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://kavassalis.com/?p=81</guid>
		<description><![CDATA[So first off I apologize for a lack of blogging. It always seems to fall to the side when life gets busy. My main priority right now is working on (and eventually) finishing going through Florida pictures, but everything seems to get in the way including taking more pics to add to the queue. One [...]]]></description>
			<content:encoded><![CDATA[<p>So first off I apologize for a lack of blogging. It always seems to fall to the side when life gets busy. My main priority right now is working on (and eventually) finishing going through Florida pictures, but everything seems to get in the way including taking more pics to add to the queue.</p>
<p>One thing I&#8217;ve wanted to do for awhile though is have a way to manage my interesting links. I read a lot of tech and science news in the morning and like to share said articles with family and friends. So I generally share them with Facebook, or Twitter (which in turn *usually* trickles back to Facebook unless their plugin is broken), but neither is really a trust worthy place to put any information you care about. I really like the way <a href="http://justinsomnia.org/" target="_blank">Justin does it</a>, but also wanted to tie a quick push to Twitter (and thus Facebook) in.  So I figured I might as well write a little social bookmarking thing.</p>
<p>The entire hack took about 30 minutes, including the time to register a cheap (i.e. not taken) and very short (3.2) domain name (k4v.ca) for my built in URL shortener as using kavassalis.com?blah seemed a touch long. I have yet to display my links in the blog layout, but I will probably whip up a widget tomorrow morning to appear on the right side of all the pages with the last N links. Anyway the code is pretty ugly and basic but here it is:</p>
<p>The actual link forwarder: (l.php)<br />
<code><br />
if (sizeof($_GET)!=1) { header("Location: http://kavassalis.com/"); }<br />
$code = key($_GET);</code></p>
<p><code> </code></p>
<p><code>$dbUser = "abc";<br />
$dbPass = "xyz";<br />
$dbName = "nick_blog";<br />
$dbHost = "127.0.0.1";</p>
<p>@mysql_connect($dbHost, $dbUser, $dbPass) or header("Location: http://kavassalis.com/");<br />
@mysql_select_db($dbName) or header("Location: http://kavassalis.com/");</p>
<p>$result = mysql_query("SELECT link FROM links where code='$code'");<br />
$rows = mysql_num_rows($result) ;</p>
<p></code></p>
<p><code>if ($rows == 1) {<br />
$link = mysql_result($result,0,"link");<br />
header("Location: $link");<br />
} else { header("Location: http://kavassalis.com/"); }<br />
</code></p>
<p>(The obvious flaw is that it doesn&#8217;t give an error to the user if the database is down, but I didn&#8217;t feel like doing that so&#8230;)</p>
<p>and here is the link creator: (bookmark.php)<br />
<code><br />
function mkCookie()<br />
{<br />
$pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';<br />
for ($i = 0; $i &lt; 3; $i++)<br />
{ $result .= $pool{rand(0, 61)}; }<br />
return $result;<br />
}</code></p>
<p><code> </code></p>
<p><code>if (!isset($_GET['link']) || !isset($_GET['blurb'])) {<br />
     *** FORM HTML WOULD APPEAR HERE, THANKS WORDPRESS ***<br />
} else {</p>
<p>$blurb = $_GET['blurb'];<br />
$link = $_GET['link'];</p>
<p>$dbUser = "abc";<br />
$dbPass = "xyz";<br />
$dbName = "nick_blog";<br />
$dbHost = "127.0.0.1";</p>
<p>@mysql_connect($dbHost, $dbUser, $dbPass) or die("Bah, cannot connect to my DB...");<br />
@mysql_select_db($dbName) or die("Bah, cannot select my database...");</p>
<p>// make sure we dont dupe codes, even though the code space is huge (62*62*62)<br />
while (1) {<br />
        $code = mkCookie();<br />
        $result = mysql_query("SELECT id FROM links where code='$code'");<br />
        $rows = mysql_num_rows($result) ;<br />
        if ($rows < 1) break;<br />
}</p>
<p>$result = mysql_query("INSERT INTO links (code,link,blurb) VALUES('$code','$link','$blurb')");<br />
$url = "http://k4v.ca/l?$code";<br />
header("Location: http://twitter.com/home?status=$blurb> $url");<br />
}<br />
?></p>
<p></code></p>
<p>Amusingly the WordPress &lt; code &gt; block really seems to detest HTML, i.e. WordPress renders it even though its inside the block, that just makes no sense&#8230; Too lazy to figure out how to do it for a 4 line form. So yea, thats the code. No URL tracking/stats, but thats not really what I was going after. I just wanted an easy one click way to share URLs everywhere at once, and store them somewhere safe.</p>
<p>Things have been generally busy work wise, home wise. I am going to try and blog more again. Today being May 5th means that Mucho Burrito has $5 12&#8243; burritos and I&#8217;m going to go and see if I can&#8217;t manage to consume two between now and dinner. Toodles!</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2010/05/lack-of-updates-link-aggregation/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Of Nick and hosting geo-diversity&#8230;</title>
		<link>http://kavassalis.com/2010/02/of-nick-and-hosting-geo-diversity/</link>
		<comments>http://kavassalis.com/2010/02/of-nick-and-hosting-geo-diversity/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 15:55:27 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[telecom]]></category>

		<guid isPermaLink="false">http://kavassalis.org/?p=29</guid>
		<description><![CDATA[If you look at the biggest websites and internet applications, you can pretty much divide them into two groups. Those that are geographically diverse and those that aren&#8217;t. It&#8217;s kinda shocking that in 2010, the majority of major internet properties still are located in a single (large) datacenter. Though to be fair there is a [...]]]></description>
			<content:encoded><![CDATA[<p>If you look at the biggest websites and internet applications, you can pretty much divide them into two groups. Those that are geographically diverse and those that aren&#8217;t. It&#8217;s kinda shocking that in 2010, the majority of major internet properties still are located in a single (large) datacenter. Though to be fair there is a good reason for that, geo-diversity has many challenges. Problems like directing traffic to the fastest/closest/cheapest/most available location are pretty easy to solve: most people go with BGP AnyCast, targeted DNS responses, or a combination of both. The real challenge though is making sure your actual served content is coherent among all the locations. It would be terrible for a user to upload a photo, sent the URL to their friends, only for the friends to see nothing or worse, the wrong image.</p>
<p>For static content, this is easy, even RSYNCs will be scalable to push out changes to your content amongst your farm. User uploaded content is quite a bit trickier. Within a single datacenter you can efficiently (though not always affordably) solve this using shared storage, iSCSI or NFS. Then applications pretty much can work as if they&#8217;re on a single server, session management can be tackled by using cookie or host persistence on the load balancers to make sure a user stays on the same server. What about servers in different locations though? NFS and iSCSI will not be terribly effective over transit.</p>
<p>You will have to push content between your locations then. If you are trying to geographically distribute your own application, you would just write functionality in to immediately push any user uploaded content out to other locations as its created.  Google/Youtube are great examples of this. When you hit content they&#8217;ve hosted, it isn&#8217;t even hosted on every server, and they direct you to the closest server that has said content. If that content isn&#8217;t available locally to you yet, or at all, they can stream it over their own fiber backhaul and out your closest Google POP.</p>
<p>But what if you are hosting a variety of 3rd party software. To my knowledge none of the popular blog packages, forum software, etc has any sort of geo-diversity designed into them. You could of course fork them and write your own, but then you end up supporting N different software packages for your N clients, not affordable or reasonable.  Rsync would do this task but unfortunately it is very intensive and doesn&#8217;t scale particularly well because it md5&#8242;s your entire tree constantly to see if things changed. As your content scales, the rsyncs would get slower and slower just seeing if changes occurred, eventually leading to massive delays on syncing out user created content.</p>
<p>In the end, its a cool problem, a problem that not too many people have tackled so far. We came up with our own solution, which I unfortunately probably shouldn&#8217;t disclose. I wrote the basis of the software last month, though it still needs some bug fixes, testing and more modules to be written for it. It is a difficult problem to tackle, but having worked in telecommunications, no facility is bullet proof, no power is bullet proof, no connectivity is bullet proof, no hardware is bullet proof: geo-diversity is a must going forward in this highly demanding world where everyone expects connectivity and content 24/7</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2010/02/of-nick-and-hosting-geo-diversity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Of Nick and UI&#8230;</title>
		<link>http://kavassalis.com/2010/02/of-nick-and-ui/</link>
		<comments>http://kavassalis.com/2010/02/of-nick-and-ui/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 15:50:46 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Federated Media]]></category>
		<category><![CDATA[FM]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[UI]]></category>

		<guid isPermaLink="false">http://kavassalis.org/?p=21</guid>
		<description><![CDATA[So my true weakness when it comes to end-to-end application development is always the UI. I think like a developer, am happy with terminals and verbose logging, I nitpick positioning and sizing endlessly, and I generally am never too happy with what I generate. Now the beauty of the iPhone SDK is that it uses [...]]]></description>
			<content:encoded><![CDATA[<p>So my true weakness when it comes to end-to-end application development is always the UI. I think like a developer, am happy with terminals and verbose logging, I nitpick positioning and sizing endlessly, and I generally am never too happy with what I generate.</p>
<p>Now the beauty of the iPhone SDK is that it uses XCode&#8217;s interface builder, and Cocoa / CocoaTouch support directly loading polished NIB at runtime.  NIB is of course NextStep Interface Builder, and though they actually use a .xib (XCode Interface Builder) file while you develop them, at runtime and pretty much everywhere else they&#8217;re called NIB files. (Because Cocoa *IS* NextStep)</p>
<p>So back to the topic at hand. I have always liked the way Visual Studio did interface building, as it took the coding out of creating a UI and let it be about what it should be, an art*. XCode offers the same experience but with a bit more of a learning curve. The real challenge though is that on the iPhone, you have a lot to live up to. There are a lot of very attractive apps out there. Creating a tool for sysadmins to receive and handle alerts doesn&#8217;t require the polish and pizzaz of lets say a Twitter client, but it can&#8217;t be ugly or clunky either.</p>
<p><img class="alignleft size-medium wp-image-22" title="navigation-controller-example" src="http://kavassalis.org/wp-content/uploads/2010/02/navigation-controller-example-191x300.jpg" alt="" width="191" height="300" /></p>
<p>So in Cocoa Touch we have the Navigation Controller (UINavigationController, which provides a bar at the top with text a button on the left and right to navigate through views) and the Tab Bar Controller (UITabBarController, which provides a bar across the bottom with any number of iconable tabs that represent different views) Of course you have the freedom to come up with whatever UI you want outside these, however these conform to Apple&#8217;s User Interface Guidelines (a fascinating read, and the iPad guidelines were an even cooler read) and match the look and feel of the iPhone, making it easier for users to navigate. In fact you can even combine the two types and create navigated views within a tab, or a set of tabs within a navigated view. The sky is the limit and its easy to do, which is whats the most fun about XCode and Cocoa Touch.</p>
<p><img class="alignright size-medium wp-image-23" title="tabbar-controller-example" src="http://kavassalis.org/wp-content/uploads/2010/02/tabbar-controller-example-200x300.jpg" alt="" width="200" height="300" /></p>
<p>So I decided to go with the Tab Bar. We are dealing with alert handling here, I know from experience that there are only a finite number of tasks that are required after hours, so we can stuff those as tabs a long the bottom. On Ken&#8217;s advice I added a More&#8230; tab which contains lesser used but still useful utilities like short cuts to compose emails to common distribution lists @FM, a long with access to the two ticketing systems outside of our department.  Throw in a Core Animation page flip between tabs (the code for animation in Cocoa Touch is really quite impressive) and you have something that looks decent (I think) and is fairly functional.  On a slightly side note, I kept the animation to a quarter of a second, that way it looks flashy but doesn&#8217;t slow down work flow, thats important to me. I&#8217;ve likely disabled every animation OS X has to offer on my computers after all..</p>
<p>I&#8217;ll likely write a follow up discussing my experience with some of the other UI widgets at a later time, but I wanna touch briefly on the spinning selector as seen in my Tab Bar screen shot. The iPhone&#8217;s user experience is superior to any other touch phone. (Android, Pre, Storm, I&#8217;m looking at you guys) I was very reluctant to use a touch screen interface because they usually annoy me long after the cool factor wears off. Apple has gone to great lengths to design the user interface of their own apps to work really well with fingers. The spinning selector is a great example of that. On the desktop, we normally select a choice of one from many in a drop down box. This works great, but is a tad annoying on something like an Android phone. The spinning selector is more of a wheel you spin with your finger that has very intuitive acceleration and deceleration such that its very easy to use. Because Apple makes it so easy to deploy these widgets in your own applications, you are very unlikely to see kludgy desktop-esque UI on the iPhone, making the user experience of 3rd party apps all the more familiar and better. That and they theoretically could stop you from publishing apps that don&#8217;t conform to the user interface guidelines, though in practice they pretty much only ban apps for their own dirty anti-competitive purposes&#8230;</p>
<p>*Design is an art, and UI design is at the forefront of that these days. Just look at all Apple products. You may not like their design (lord knows I&#8217;ve stripped OSX so bare its just a tiny bar on the right, no desktop and the Finder process isn&#8217;t running most of the time), but its still intuitive and attractive. In the end Apple is a design company. A PC is just a PC until its in a sleek, durable unibody aluminum case, then its a Mac. BSD is just a server operating system until its got an attractive, intuitive user interface, then its OS X.</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2010/02/of-nick-and-ui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Of Nick and the APNS&#8230;</title>
		<link>http://kavassalis.com/2010/02/of-nick-and-the-apns/</link>
		<comments>http://kavassalis.com/2010/02/of-nick-and-the-apns/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 16:44:45 +0000</pubDate>
		<dc:creator>nick</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[APNS]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Federated Media]]></category>
		<category><![CDATA[FM]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[OpenSSL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://kavassalis.org/?p=17</guid>
		<description><![CDATA[So on Sunday I got the inspiration for my second iPhone app, fmNotify. (the first was a simple multi-tab webkit integration for a friends website that made use of some clever code to hide the tab and status bars when rotated as well as the shake gesture to go back on the current page) fmNotify [...]]]></description>
			<content:encoded><![CDATA[<p>So on Sunday I got the inspiration for my second iPhone app, fmNotify. (the first was a simple multi-tab webkit integration for a friends website that made use of some clever code to hide the tab and status bars when rotated as well as the shake gesture to go back on the current page)</p>
<p>fmNotify will be (ok I&#8217;m being a tad presumptuous but I have faith :&gt;) our internal notification service for emergency alerts. It utilizes Apple&#8217;s fantastic push notification service (APNS, APN or APS depending where you read it) and some clever UI to streamline alert handling. Basically alerts and phone registration is handled by PHP code running on a server(s, easily redundant using mySQL replication) inside our network, stored in an SQL database. This allows for  pretty extensible triggering of alerts, everything from Nagios, email via procmail, and our own internally developed software.</p>
<p>The real thing I wanted to talk about is how impressed I am in the APNS bits of the SDK. iPhone SDK 3.x is really where the iPhone hit its stride, and the push SDK is a big part of that. (Prior to 3.x it was a pretty disappointing device IMO and more than a fancy toy for teenagers than anything workable.) OS 3.x makes the device a powerful device for any industry. (Though MobileMail.app is still so woefully inferior to the Blackberry)</p>
<p>BUT I DIGRESS. Working with APNS is a coders dream. When your app is setup with Apple for push support, you get a cert that can be used to connect to the APNS cloud with. APNS requires a connection via TLS or SSL, which of course can be done easily with libopenssl in C or in this case PHP. From there all you need to do is send json blobs that contain: the device id of the handset, the alert text you want to display, the badge number to show on the app (if desired) and the sound to play (if desired). Beyond that you can include whatever other custom data you want, within 256bytes. This may seem like a rather limited amount of data to work with, but its really just to trigger your app to connect to you own servers, which can then pull down whatever data you want.</p>
<p>So while your app isn&#8217;t running and a notification comes in, a popup will occur with vibration/sound if desired, and a link to automatically launch your app.  While it is running an event is triggered within the app delegate and you can handle it however you want. Pretty awesome. Throw that all together with a nice GUI and you have a really streamlined alert / alert handling work flow!</p>
<p>So the app itself is pretty simple. Just a basic UI for seeing alerts / alert history, and then panels for dealing with common alerts.  The backend is basic PHP / mySQL / simple JSON / openssl integration to handle registration (including the device id and desired alert sound) for each phone, and directing of alerts to whoever is oncall. I really look forward to future projects using APNS, considering this took less than a day to throw together, the sky is the limit!</p>
]]></content:encoded>
			<wfw:commentRss>http://kavassalis.com/2010/02/of-nick-and-the-apns/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

