<?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>GoTinker</title>
	<atom:link href="http://www.gotinker.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gotinker.com</link>
	<description>My world in IT</description>
	<lastBuildDate>Thu, 29 Sep 2011 02:39:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Securing IPv6 with IPSec, protecting yourself in an end-to-end world!</title>
		<link>http://www.gotinker.com/2011/09/27/securing-ipv6-with-ipsec-protecting-yourself-in-an-end-to-end-world/</link>
		<comments>http://www.gotinker.com/2011/09/27/securing-ipv6-with-ipsec-protecting-yourself-in-an-end-to-end-world/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 20:52:24 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Networking]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=169</guid>
		<description><![CDATA[With IPv6 there is no more NAT.  All your machines have end-to-end connections to their destination.  It&#8217;s taken for granted the implied security that NAT provides, by preventing incoming connections.  There&#8217;s also no longer a need to use a VPN, if I want to connect to my work PC I merely use it&#8217;s publicly available IPv6 address. [...]]]></description>
			<content:encoded><![CDATA[<p>With IPv6 there is no more NAT.  All your machines have end-to-end connections to their destination.  It&#8217;s taken for granted the implied security that NAT provides, by preventing incoming connections.  There&#8217;s also no longer a need to use a VPN, if I want to connect to my work PC I merely use it&#8217;s publicly available IPv6 address.</p>
<p>So what we need is a good (default deny) firewall policy to start with, but then we have the problem of encryption without using a VPN.  This is where IPSec comes in, providing end-to-end encryption at the packet level.  That way we can then happily use normally unencrypted  protocols securely.  We can also harden already encrypted protocols (SSH, RDP).</p>
<p>&nbsp;</p>
<p>First thing we need to do is install &#8220;racoon&#8221; and &#8220;ipsec-tools&#8221; on both machines we wish to securely communicate between, in my case my Lubuntu 11.10 laptop and a Ubuntu 11.04 Server VPS.  These two machines have the following IPv6 addresses (anonymized):</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">Laptop    2604:xxxx:xxx::500
VPS       2607:xxxx:xxx::f49</pre>
<p>To install the relevant packages on Debian based systems:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">#sudo apt-get install ipsec-tools racoon</pre>
<p>Then I need to edit &#8220;/etc/ipsec-tools.conf&#8221; to tell each machine I expect IPSec to be used to/from a certain IPv6 address, on my laptop it looks like this:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">#!/usr/sbin/setkey -f
flush;
spdflush;

spdadd ::0/0               2607:xxxx:xxx::f49 any -P out ipsec esp/transport//require ah/transport//require;
spdadd 2607:xxxx:xxx::f49  ::0/0              any -P in  ipsec esp/transport//require ah/transport//require;</pre>
<p>So any IP on my laptop (::0/0) to my VPS outgoing, then my VPS to any IP on my laptop (::0/0) incoming.  Then same on the VPS but switching the IP:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">#!/usr/sbin/setkey -f
flush;
spdflush;

spdadd ::0/0               2604:xxxx:xxx::500 any -P out ipsec esp/transport//require ah/transport//require;
spdadd 2604:xxxx:xxx::500  ::0/0              any -P in  ipsec esp/transport//require ah/transport//require;</pre>
<p>Then we need to configure the level of encryption and key exchange we use on both machines.  These settings must match exactly or key exchange and encryption will fail.  These settings are defined in &#8220;/etc/racoon/racoon.conf&#8221;.  The man pages have information on the algorithms you can use, in my case I&#8217;ve gone for &#8220;uber paranoid&#8221; settings like this:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;"># Author: 	Mike Lovell
# Modified:	2011-08-16

path pre_shared_key "/home/mikelovell/.ipsec/config/keys.txt";

remote anonymous
{
	exchange_mode main;
	lifetime time 12 hour;

	proposal
	{
		encryption_algorithm   aes;
		hash_algorithm         sha512;
		authentication_method  pre_shared_key;
		dh_group               modp4096;
	}
}

sainfo anonymous
{
	pfs_group                      modp4096;
	lifetime time                  12 hour;
	encryption_algorithm           rijndael, aes;
	authentication_algorithm       hmac_sha512;
	compression_algorithm          deflate;
}</pre>
<p>I store my IPSec keys inside &#8220;/home&#8221;, which is encrypted (mounted on boot) on my machines &#8211; You&#8217;re probably best keeping your keys in &#8220;/etc/racoon/keys.txt&#8221;.  In here you need to put the destination IP along with a password to use to communicate &#8211; To generate the password I always use &#8220;apg -a 1 -m 128&#8243;, here&#8217;s what the file might look like on the laptop:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">2607:xxxx:xxx::f49   not_a_good_password!</pre>
<p>And on the VPS:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">2604:xxxx:xxx::500   not_a_good_password!</pre>
<p>All that&#8217;s left to do now is restart the IPSec service and racoon, make sure you have another way into your machine (not via IPv6) before you do this &#8211; If something doesn&#8217;t work you don&#8217;t want to be locked out!</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">#sudo /etc/init.d/setkey restart
#sudo /etc/init.d/racoon restart</pre>
<p>Once you&#8217;ve done that on both machines as soon as you establish a new connection (anything, try a ping6) you should see IPSec successfully negotiate in your syslog:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">initiate new phase 1 negotiation: 2604:xxxx:xxx::500[500]&lt;=&gt;2607:xxxx:xxx::f49[500]
begin Identity Protection mode.
received Vendor ID: DPD
ISAKMP-SA established 2604:xxxx:xxx::500[500]-2607:xxxx:xxx::f49[500] spi:d____________f
initiate new phase 2 negotiation: 2604:xxxx:xxx::500[500]&lt;=&gt;2607:xxxx:xxx::f49[500]
IPsec-SA established: AH/Transport 2604:xxxx:xxx::500[500]-&gt;2607:xxxx:xxx::f49[500] spi=11___2(0x6____)
IPsec-SA established: ESP/Transport 2604:xxxx:xxx::500[500]-&gt;2607:xxxx:xxx::f49[500] spi=1___1(0xc____)
IPsec-SA established: AH/Transport 2604:xxxx:xxx::500[500]-&gt;2607:xxxx:xxx::f49[500] spi=1___5(0xb____)
IPsec-SA established: ESP/Transport 2604:xxxx:xxx::500[500]-&gt;2607:xxxx:xxx::f49[500] spi=96___3(0x5____)</pre>
<p>Viola!  You care confirm if you like by sniffing the network traffic via &#8220;wireshark&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2011/09/27/securing-ipv6-with-ipsec-protecting-yourself-in-an-end-to-end-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IPv6 without native support from your provider, via SiXS</title>
		<link>http://www.gotinker.com/2011/09/26/ipv6-without-native-support-from-your-provider-via-sixs/</link>
		<comments>http://www.gotinker.com/2011/09/26/ipv6-without-native-support-from-your-provider-via-sixs/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 21:33:11 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Networking]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=154</guid>
		<description><![CDATA[You&#8217;ll need a Linux machine or device supporting AICCU and ip6tables to act as IPv6 router.  It doesn&#8217;t have to be the same machine/device as IPv4 router.  If you&#8217;re using DD-WRT on your IPv4 router then there&#8217;s a tutorial covering this here. First you need to pop over to www.sixxs.net and sign up for a account [...]]]></description>
			<content:encoded><![CDATA[<p>You&#8217;ll need a Linux machine or device supporting <a href="http://www.sixxs.net/tools/aiccu/">AICCU</a> and <a href="http://linux.die.net/man/8/ip6tables">ip6tables</a> to act as IPv6 router.  It doesn&#8217;t have to be the same machine/device as IPv4 router.  If you&#8217;re using <a href="http://www.dd-wrt.com/site/index">DD-WRT</a> on your IPv4 router then there&#8217;s a tutorial covering this <a href="http://www.dd-wrt.com/wiki/index.php/IPv6_(tutorial)">here</a>.</p>
<p>First you need to pop over to <a href="www.sixxs.net">www.sixxs.net</a> and sign up for a account (it&#8217;s free).  Once that&#8217;s approved you&#8217;ll need to request a tunnel.</p>
<p>For safeties sake, as some connectivity providers block other protocols, select &#8220;Dynamic NAT-traversing IPv4 Endpoint using <a href="https://www.sixxs.net/tools/ayiya/">AYIYA</a>&#8221; as your endpoint.</p>
<p><img src="http://www.gotinker.com/wp-uploads/2011/09/requesttunnel_1.png" border="1" alt="" /></p>
<p>Then you&#8217;ll need to select a PoP that&#8217;s close to you (to keep latency low) and give a reason why you want an IPv6 tunnel (use your imagination!)</p>
<p><img src="http://www.gotinker.com/wp-uploads/2011/09/requesttunnel_2.png" border="1" alt="" /></p>
<p>After that&#8217;s approved you&#8217;ll need to request a subnet</p>
<p><img src="http://www.gotinker.com/wp-uploads/2011/09/requestsubnet_1.png" border="1" alt="" /></p>
<p>Now we just need to setup our IPv6 router (in my case a Debian VM).  First lets setup AICCU which will configure a tunnel device for IPv6 with SixXS.  During the ncurses installer, you will be asked for your SixXS username and password:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;"># apt-get install aiccu</pre>
<p>An &#8220;ifconfig&#8221; should now show the tunnel to be present:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">sixxs     Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet6 addr: fe80::xxxx:xxx:xx:2/64 Scope:Link
          inet6 addr: 2604:xxxx:xxx:xx::2/64 Scope:Global
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1280  Metric:1
          RX packets:1989470 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1187540 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500
          RX bytes:1401336999 (1.3 GiB)  TX bytes:306453776 (292.2 MiB)</pre>
<p>Then we need to enable IPv6 forwarding (as root):</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">#echo 1 &gt; /proc/sys/net/ipv6/conf/all/forwarding</pre>
<p>To make this persistent you&#8217;ll need to add/ammend this rule in &#8220;/etc/sysctl.conf&#8221;:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">net.ipv6.conf.default.forwarding=1</pre>
<p>Lets now setup an IPv6 address from subnet we&#8217;ve been given to act as our IPv6 gateway, in my case my subnet is (anonymized):</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">2604:xxxx:xxx::/48</pre>
<p>So in &#8220;/etc/network/interfaces&#8221; I put the following:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">iface eth0 inet6 static
	address	2604:xxxx:xxx::1
	netmask	48</pre>
<p>Now whenever the network comes up I want to add some routes in to make sure my IPv6 traffic is directed correctly, to do this I created a script called &#8220;/etc/network/if-up.d/ipv6routes&#8221; and marked it as executable:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">#!/bin/sh

ip -6 route add 2604:8800:112::1/64 dev eth0
ip -6 route add 2604:8800:112::/48 dev lo</pre>
<p>Then we just need to setup the ip6tables rules to forward the traffic correctly, in my case:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">ip6tables -P FORWARD DROP

ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

ip6tables -A FORWARD -i eth0 -s 2604:xxxx:xxx::/48 -j ACCEPT
ip6tables -A FORWARD -i sixxs -o eth0 -d 2604:xxxx:xxx::/48 -j ACCEPT</pre>
<p>To make these persistent you&#8217;ll need to set them to be loaded when the network comes up, what I usually do is this:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">ip6tables-save &gt; /etc/iptables-ipv6.conf</pre>
<p>Then create a script called &#8220;/etc/network/if-up.d/iptables&#8221; and mark it as executable with the following inside it:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">#!/bin/sh

ip6tables-restore &lt; /etc/iptables-ipv6.conf</pre>
<p>Now we assign an IPv6 address to a different machine in the network and set the gateway as the address we setup previously (2604:xxxx:xxx::1), here&#8217;s what the &#8220;ifconfig&#8221; looks like:</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;">wlan0     Link encap:Ethernet  HWaddr 00:23:14:53:56:3c
          inet addr:192.168.x.xxx  Bcast:192.168.x.xxx  Mask:255.255.x.x
          inet6 addr: 2604:xxxx:xxx::500/64 Scope:Global
          inet6 addr: fe80::xxx:xxxx:xxxx:xxxx/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1280  Metric:1
          RX packets:403511 errors:0 dropped:0 overruns:0 frame:0
          TX packets:366141 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:195242106 (195.2 MB)  TX bytes:60409846 (60.4 MB)</pre>
<p>And hopefully, it all works!</p>
<pre style="padding-left: 30px;background: #f0f0f0;padding: 15px;"># traceroute6 -n www.sixxs.net
traceroute to nginx.sixxs.net (2001:1af8:4050::2) from 2604:xxxx:xxx::500, 30 hops max, 24 byte
 1  2604:xxxx:xxx::1  2.871 ms  2.892 ms  9.606 ms
 2  2604:xxxx:xxx:31::1  137.17 ms  150.576 ms  168.446 ms
 3  2620:0:6b0:a::1  204.796 ms  245.039 ms  329.039 ms
 4  2001:1900:2100::171  326.815 ms  256.593 ms  385.289 ms
   ...                         ...</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2011/09/26/ipv6-without-native-support-from-your-provider-via-sixs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My base &#8220;iptables&#8221; / &#8220;ip6tables&#8221; script</title>
		<link>http://www.gotinker.com/2011/09/25/my-base-iptables-ip6tables-script/</link>
		<comments>http://www.gotinker.com/2011/09/25/my-base-iptables-ip6tables-script/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 19:16:17 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Networking]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=147</guid>
		<description><![CDATA[I thought I&#8217;d post my base iptables/ip6tables script.  This is what I dump on every machine I install, then tweak from there. It also creates  a script to load the rules up (on Debian based systems) when the network starts (if-up.d) Download: firewall.tar.gz]]></description>
			<content:encoded><![CDATA[<p>I thought I&#8217;d post my base iptables/ip6tables script.  This is what I dump on every machine I install, then tweak from there.</p>
<p>It also creates  a script to load the rules up (on Debian based systems) when the network starts (if-up.d)</p>
<p><strong>Download:</strong><br />
<a title="firewall.tar.gz" href="http://www.gotinker.com/wp-uploads/2011/09/firewall.tar.gz" target="_self">firewall.tar.gz</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2011/09/25/my-base-iptables-ip6tables-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extracting music from flash videos using mencoder and mplayer</title>
		<link>http://www.gotinker.com/2011/01/26/extracting-music-from-flash-videos-using-mencoder-and-mplayer/</link>
		<comments>http://www.gotinker.com/2011/01/26/extracting-music-from-flash-videos-using-mencoder-and-mplayer/#comments</comments>
		<pubDate>Wed, 26 Jan 2011 20:30:53 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Sound]]></category>
		<category><![CDATA[Video Processing]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=116</guid>
		<description><![CDATA[If you&#8217;ve ever downloaded music videos from a website (for example via &#8220;youtube-dl&#8221;) you may have been in the position of wanting to extract the music in &#8220;MP3&#8243; format from the &#8220;FLV&#8221; (flash video) file, here&#8217;s how you can do this: #mencoder source.flv -ovc frameno -oac mp3lame -lameopts br=128 -noskip -o resampled.avi #mplayer -dumpaudio -dumpfile [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever downloaded music videos from a website (for example via <em>&#8220;youtube-dl&#8221;</em>) you may have been in the position of wanting to extract the music in <em>&#8220;MP3&#8243;</em> format from the <em>&#8220;FLV&#8221;</em> (flash video) file, here&#8217;s how you can do this:</p>
<p><code>#mencoder source.flv -ovc frameno -oac mp3lame -lameopts br=128 -noskip -o resampled.avi</code><br />
<code>#mplayer -dumpaudio -dumpfile final.mp3 resampled.avi</code></p>
<p>Both <em>&#8220;mencoder&#8221;</em> and  <em>&#8220;mplayer&#8221;</em> can be used on both Windows and Linux (in the latest version of Ubuntu both are available via the package manager).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2011/01/26/extracting-music-from-flash-videos-using-mencoder-and-mplayer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>X11 Forwarding of Pidgin with Sound using PulseAudio</title>
		<link>http://www.gotinker.com/2011/01/26/x11-forwarding-of-pidgin-with-sound-using-pulseaudio/</link>
		<comments>http://www.gotinker.com/2011/01/26/x11-forwarding-of-pidgin-with-sound-using-pulseaudio/#comments</comments>
		<pubDate>Wed, 26 Jan 2011 19:41:53 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Pidgin]]></category>
		<category><![CDATA[PulseAudio]]></category>
		<category><![CDATA[SSH]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=109</guid>
		<description><![CDATA[With the aid of PulseAudio it&#8217;s possible to remotely host applications such as Pidgin and still have sound enabled (something that&#8217;s very handy with an IM client for notification purposes). First, on the client and server, you&#8217;ll need to make sure PulseAudio is installed (it should be there by default in Ubuntu 10.10 if that&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>With the aid of PulseAudio it&#8217;s possible to remotely host applications such as Pidgin and still have sound enabled (something that&#8217;s very handy with an IM client for notification purposes).</p>
<p>First, on the client and server, you&#8217;ll need to make sure PulseAudio is installed (it should be there by default in Ubuntu 10.10 if that&#8217;s your client), for the client you can install all you need like this:</p>
<p><code>#apt-get install pulseaudio pulseaudio-utils paprefs</code></p>
<p>And for the server:</p>
<p><code>#apt-get install pulseaudio pulseaudio-utils</code></p>
<p>Then on the client allow network access to the local sound devices (you can open the preferences by typing <em>&#8220;papref&#8221;</em> at console or going to <em>&#8220;System | Preferences | PulseAudio Preferences&#8221;</em>):</p>
<p><a href="http://www.gotinker.com/wp-uploads/2011/01/paprefs.jpg"><img class="alignnone size-full wp-image-110" title="paprefs" src="http://www.gotinker.com/wp-uploads/2011/01/paprefs.jpg" alt="&quot;paprefs&quot; Dialog" width="497" height="313" /></a></p>
<p><em>(Security Note: The port being used (TCP/4713) is blocked by the firewall on this machine to anything but LocalHost, you should do the same)</em></p>
<p>Then, when we connect to the server, we want to enable X11 forwarding and setup a reverse tunnel to allow us to send sounds to the client, we do this like so:</p>
<p><code>#ssh -X R 4713:127.0.0.1:4713</code></p>
<p>Start up Pidgin:</p>
<p><code>#pidgin &amp;</code></p>
<p>Then change the sound preferences to use <em>&#8220;paplay&#8221;</em> to play the sounds down the reverse tunnel:</p>
<p><a href="http://www.gotinker.com/wp-uploads/2011/01/pidgin-sound.jpg"><img class="alignnone size-full wp-image-112" title="pidgin-sound" src="http://www.gotinker.com/wp-uploads/2011/01/pidgin-sound.jpg" alt="Pidgin Sound Dialog" width="607" height="497" /></a></p>
<p>And there we go, job done.</p>
<p>I like to have Pidgin running on a virtual machine at home to prevent any monitoring of my IM communications when at work, on-site or using an untrusted network.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2011/01/26/x11-forwarding-of-pidgin-with-sound-using-pulseaudio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hybrid Cryptosystem</title>
		<link>http://www.gotinker.com/2010/03/21/hybrid-cryptosystem/</link>
		<comments>http://www.gotinker.com/2010/03/21/hybrid-cryptosystem/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 18:11:28 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Cryptography]]></category>
		<category><![CDATA[aes]]></category>
		<category><![CDATA[cryptosystem]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[hybrid]]></category>
		<category><![CDATA[key]]></category>
		<category><![CDATA[password]]></category>
		<category><![CDATA[private]]></category>
		<category><![CDATA[public]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[Rijndael]]></category>
		<category><![CDATA[RSA]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=91</guid>
		<description><![CDATA[There are some limitations to asymmetric encryption that we can overcome by using a hybrid cryptosystem.  Combining asymmetric and symetric encryption.]]></description>
			<content:encoded><![CDATA[<p>When using &#8216;<em>asymmetric&#8217;</em> (public-private key) encryption, there are a few limitations:</p>
<ul>
<li><strong>Slow Speed</strong> - Symmetric (key) encryption is far quicker</li>
<li><strong>Single Recipient</strong> &#8211; You can only encrypt to a single public key</li>
</ul>
<p>However we can combine &#8216;asymmetric&#8217; and &#8216;symmetric&#8217; cryposystems to create a hybrid system which will allow us to harness the speed of &#8216;<em>symmetric&#8217;</em>encryption and allow multiple recipients by simply encrypting the shared &#8216;<em>symmetric key&#8217;</em> to each public &#8216;<em>asymmetric key&#8217;</em> we want to use.</p>
<p>So lets create a simple format for a &#8216;<em>hybrid cryptosystem</em>&#8216;.  We&#8217;re going to be using &#8216;<em>RSA</em>&#8216; for our &#8216;<em>asymmetric encryption</em>&#8216;, and AES (Rijndael) for our &#8216;<em>symmetric encryption</em>&#8216;.</p>
<pre>

1 Byte    <span style="text-decoration: underline;">Recepient count:</span> 1-255 recepients allowed
4 Bytes   <span style="text-decoration: underline;">Recepient 1 data:</span> Size (Int32)
20 Bytes  <span style="text-decoration: underline;">Recepient 1 data:</span> SHA1 hash of public key
<em><strong>n</strong></em> Bytes   <span style="text-decoration: underline;">Recepient 1 data:</span> Shared key/password (encrypted to public key)
...
4 Bytes   <span style="text-decoration: underline;">Recepient <strong><em>n</em></strong> data:</span> Size (Int32)
20 Bytes  <span style="text-decoration: underline;">Recepient <strong><em>n</em></strong> data:</span> SHA1 hash of public key
<strong><em>n</em></strong> Bytes   <span style="text-decoration: underline;">Recepient <strong><em>n</em></strong> data:</span> Shared key/password (encrypted to public key)
<strong><em></em></strong>
<strong><em>n</em></strong> Bytes   <span style="text-decoration: underline;">Encrypted data:</span> Encrypted using AES (Rijndael) and shared key/password
</pre>
<p> </p>
<p>Now we have our format defined, we can implement a simple C# application that follows this.  First we&#8217;re going to implement a &#8216;<em>CryptoProvider</em>&#8216; class.  This is going to handle both &#8216;<em>asymmetric</em>&#8216; and &#8216;<em>symmetric</em>&#8216; encryption and decryption, key generation, hash generation and random byte generation.  Our key/password is going to be randomly generated and 48 bytes long.  The first 16 will be the &#8216;<em>IV</em>&#8216; vector, the last 32 will be the &#8216;<em>key</em>&#8216;.</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<div class="csharpcode">
<pre><span class="lnum">   1:  </span><span class="rem">// Author: Mike Lovell (mike.lovell@gotinker.com)</span></pre>
<pre><span class="lnum">   2:  </span> </pre>
<pre><span class="lnum">   3:  </span><span class="kwrd">class</span> CryptoProvider</pre>
<pre><span class="lnum">   4:  </span>{</pre>
<pre><span class="lnum">   5:  </span>    <span class="kwrd">private</span>    RSACryptoServiceProvider    rsaProvider;</pre>
<pre><span class="lnum">   6:  </span> </pre>
<pre><span class="lnum">   7:  </span> </pre>
<pre><span class="lnum">   8:  </span>    <span class="kwrd">public</span> CryptoProvider(<span class="kwrd">int</span> keySize)</pre>
<pre><span class="lnum">   9:  </span>    {</pre>
<pre><span class="lnum">  10:  </span>        rsaProvider = <span class="kwrd">new</span> RSACryptoServiceProvider(keySize);    <span class="rem">// Generate new key</span></pre>
<pre><span class="lnum">  11:  </span>    }</pre>
<pre><span class="lnum">  12:  </span> </pre>
<pre><span class="lnum">  13:  </span> </pre>
<pre><span class="lnum">  14:  </span>    <span class="kwrd">public</span> CryptoProvider(<span class="kwrd">string</span> xmlKey)</pre>
<pre><span class="lnum">  15:  </span>    {</pre>
<pre><span class="lnum">  16:  </span>        rsaProvider = <span class="kwrd">new</span> RSACryptoServiceProvider();</pre>
<pre><span class="lnum">  17:  </span> </pre>
<pre><span class="lnum">  18:  </span>        rsaProvider.FromXmlString(xmlKey);    <span class="rem">// Import XML Key</span></pre>
<pre><span class="lnum">  19:  </span>    }</pre>
<pre><span class="lnum">  20:  </span> </pre>
<pre><span class="lnum">  21:  </span> </pre>
<pre><span class="lnum">  22:  </span>    <span class="kwrd">public</span> <span class="kwrd">string</span> ToXmlString(<span class="kwrd">bool</span> includePrivateKey)</pre>
<pre><span class="lnum">  23:  </span>    {</pre>
<pre><span class="lnum">  24:  </span>        <span class="kwrd">return</span> rsaProvider.ToXmlString(includePrivateKey);    <span class="rem">// Export XML Key</span></pre>
<pre><span class="lnum">  25:  </span>    }</pre>
<pre><span class="lnum">  26:  </span> </pre>
<pre><span class="lnum">  27:  </span> </pre>
<pre><span class="lnum">  28:  </span>    <span class="kwrd">public</span> <span class="kwrd">byte</span>[] Hash()</pre>
<pre><span class="lnum">  29:  </span>    {</pre>
<pre><span class="lnum">  30:  </span>        var sha1 = <span class="kwrd">new</span> SHA1Managed();</pre>
<pre><span class="lnum">  31:  </span> </pre>
<pre><span class="lnum">  32:  </span>        <span class="rem">// Hash from the modulus</span></pre>
<pre><span class="lnum">  33:  </span>        <span class="kwrd">return</span> sha1.ComputeHash(rsaProvider.ExportParameters(<span class="kwrd">false</span>).Modulus);</pre>
<pre><span class="lnum">  34:  </span>    }</pre>
<pre><span class="lnum">  35:  </span> </pre>
<pre><span class="lnum">  36:  </span> </pre>
<pre><span class="lnum">  37:  </span>    <span class="kwrd">public</span> <span class="kwrd">byte</span>[] Encrypt(<span class="kwrd">byte</span>[] data)</pre>
<pre><span class="lnum">  38:  </span>    {</pre>
<pre><span class="lnum">  39:  </span>        <span class="kwrd">return</span> rsaProvider.Encrypt(data, <span class="kwrd">false</span>);</pre>
<pre><span class="lnum">  40:  </span>    }</pre>
<pre><span class="lnum">  41:  </span> </pre>
<pre><span class="lnum">  42:  </span> </pre>
<pre><span class="lnum">  43:  </span>    <span class="kwrd">public</span> <span class="kwrd">byte</span>[] Decrypt(<span class="kwrd">byte</span>[] data)</pre>
<pre><span class="lnum">  44:  </span>    {</pre>
<pre><span class="lnum">  45:  </span>        <span class="kwrd">return</span> rsaProvider.Decrypt(data, <span class="kwrd">false</span>);</pre>
<pre><span class="lnum">  46:  </span>    }</pre>
<pre><span class="lnum">  47:  </span> </pre>
<pre><span class="lnum">  48:  </span> </pre>
<pre><span class="lnum">  49:  </span>    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">byte</span>[] RandomSequence(<span class="kwrd">int</span> size)</pre>
<pre><span class="lnum">  50:  </span>    {</pre>
<pre><span class="lnum">  51:  </span>        var random        = <span class="kwrd">new</span> <span class="kwrd">byte</span>[size];</pre>
<pre><span class="lnum">  52:  </span>        var rngProvider    = <span class="kwrd">new</span> RNGCryptoServiceProvider();</pre>
<pre><span class="lnum">  53:  </span></pre>
<pre><span class="lnum">  54:  </span>        rngProvider.GetBytes(random);</pre>
<pre><span class="lnum">  55:  </span> </pre>
<pre><span class="lnum">  56:  </span>        <span class="kwrd">return</span> random;</pre>
<pre><span class="lnum">  57:  </span>    }</pre>
<pre><span class="lnum">  58:  </span> </pre>
<pre><span class="lnum">  59:  </span> </pre>
<pre><span class="lnum">  60:  </span>    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">byte</span>[] Encrypt(<span class="kwrd">byte</span>[] data, <span class="kwrd">byte</span>[] password)</pre>
<pre><span class="lnum">  61:  </span>    {</pre>
<pre><span class="lnum">  62:  </span>        var rijndael    = Rijndael.Create();</pre>
<pre><span class="lnum">  63:  </span> </pre>
<pre><span class="lnum">  64:  </span>        rijndael.KeySize    = 256;    <span class="rem">// Maximum key size</span></pre>
<pre><span class="lnum">  65:  </span>        rijndael.IV            = SubBytes(password, 0, 16);    <span class="rem">// First 16 bytes is vector</span></pre>
<pre><span class="lnum">  66:  </span>        rijndael.Key        = TrimBytes(SubBytes(password, 16, password.Length - 16), 32);    <span class="rem">// Last 32 is key</span></pre>
<pre><span class="lnum">  67:  </span>        rijndael.Mode        = CipherMode.CBC;</pre>
<pre><span class="lnum">  68:  </span> </pre>
<pre><span class="lnum">  69:  </span>        var stream            = <span class="kwrd">new</span> MemoryStream();</pre>
<pre><span class="lnum">  70:  </span>        var cryptoStream    = <span class="kwrd">new</span> CryptoStream(stream, rijndael.CreateEncryptor(), CryptoStreamMode.Write);</pre>
<pre><span class="lnum">  71:  </span> </pre>
<pre><span class="lnum">  72:  </span>        cryptoStream.Write(data, 0, data.Length);</pre>
<pre><span class="lnum">  73:  </span>        cryptoStream.FlushFinalBlock();</pre>
<pre><span class="lnum">  74:  </span> </pre>
<pre><span class="lnum">  75:  </span>        cryptoStream.Close();</pre>
<pre><span class="lnum">  76:  </span> </pre>
<pre><span class="lnum">  77:  </span>        var encryptedData = stream.ToArray();</pre>
<pre><span class="lnum">  78:  </span> </pre>
<pre><span class="lnum">  79:  </span>        stream.Close();</pre>
<pre><span class="lnum">  80:  </span> </pre>
<pre><span class="lnum">  81:  </span>        <span class="kwrd">return</span> encryptedData;</pre>
<pre><span class="lnum">  82:  </span>    }</pre>
<pre><span class="lnum">  83:  </span> </pre>
<pre><span class="lnum">  84:  </span> </pre>
<pre><span class="lnum">  85:  </span>    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">byte</span>[] Decrypt(<span class="kwrd">byte</span>[] data, <span class="kwrd">byte</span>[] password)</pre>
<pre><span class="lnum">  86:  </span>    {</pre>
<pre><span class="lnum">  87:  </span>        var rijndael    = Rijndael.Create();</pre>
<pre><span class="lnum">  88:  </span> </pre>
<pre><span class="lnum">  89:  </span>        rijndael.KeySize    = 256;    <span class="rem">// Maximum key size</span></pre>
<pre><span class="lnum">  90:  </span>        rijndael.IV            = SubBytes(password, 0, 16);    <span class="rem">// First 16 bytes is vector</span></pre>
<pre><span class="lnum">  91:  </span>        rijndael.Key        = TrimBytes(SubBytes(password, 16, password.Length - 16), 32);    <span class="rem">// Last 32 is key</span></pre>
<pre><span class="lnum">  92:  </span>        rijndael.Mode        = CipherMode.CBC;</pre>
<pre><span class="lnum">  93:  </span> </pre>
<pre><span class="lnum">  94:  </span>        var stream            = <span class="kwrd">new</span> MemoryStream(data);</pre>
<pre><span class="lnum">  95:  </span>        var cryptoStream    = <span class="kwrd">new</span> CryptoStream(stream, rijndael.CreateDecryptor(), CryptoStreamMode.Read);</pre>
<pre><span class="lnum">  96:  </span> </pre>
<pre><span class="lnum">  97:  </span>        var    length            = cryptoStream.Read(data, 0, data.Length);</pre>
<pre><span class="lnum">  98:  </span>        var    decryptedData    = <span class="kwrd">new</span> <span class="kwrd">byte</span>[length];</pre>
<pre><span class="lnum">  99:  </span> </pre>
<pre><span class="lnum"> 100:  </span>        stream.Read(decryptedData, 0, length);</pre>
<pre><span class="lnum"> 101:  </span> </pre>
<pre><span class="lnum"> 102:  </span>        cryptoStream.Close();</pre>
<pre><span class="lnum"> 103:  </span>        stream.Close();</pre>
<pre><span class="lnum"> 104:  </span> </pre>
<pre><span class="lnum"> 105:  </span>        Buffer.BlockCopy(data, 0, decryptedData, 0, length);</pre>
<pre><span class="lnum"> 106:  </span> </pre>
<pre><span class="lnum"> 107:  </span>        <span class="kwrd">return</span> decryptedData;</pre>
<pre><span class="lnum"> 108:  </span>    }</pre>
<pre><span class="lnum"> 109:  </span> </pre>
<pre><span class="lnum"> 110:  </span> </pre>
<pre><span class="lnum"> 111:  </span>    <span class="kwrd">public</span> <span class="kwrd">byte</span>[] DecryptPasswordAndData(<span class="kwrd">byte</span>[] data)</pre>
<pre><span class="lnum"> 112:  </span>    {</pre>
<pre><span class="lnum"> 113:  </span>        var    buffer            = <span class="kwrd">new</span> MemoryStream(data);</pre>
<pre><span class="lnum"> 114:  </span>        var    keyCount        = buffer.ReadByte();    <span class="rem">// First byte is key count</span></pre>
<pre><span class="lnum"> 115:  </span>        var    thisHash        = Convert.ToBase64String(<span class="kwrd">this</span>.Hash());</pre>
<pre><span class="lnum"> 116:  </span>        var    password        = (<span class="kwrd">byte</span>[])<span class="kwrd">null</span>;</pre>
<pre><span class="lnum"> 117:  </span> </pre>
<pre><span class="lnum"> 118:  </span>        <span class="kwrd">if</span> (keyCount &lt; 1) <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"No keys found"</span>);</pre>
<pre><span class="lnum"> 119:  </span></pre>
<pre><span class="lnum"> 120:  </span>        var    keyLengthBuffer    = <span class="kwrd">new</span> <span class="kwrd">byte</span>[4];</pre>
<pre><span class="lnum"> 121:  </span></pre>
<pre><span class="lnum"> 122:  </span>        <span class="kwrd">for</span> (<span class="kwrd">int</span> i=0; i &lt; keyCount; i++)</pre>
<pre><span class="lnum"> 123:  </span>        {</pre>
<pre><span class="lnum"> 124:  </span>            <span class="rem">// First 4 bytes are Int32 of encrypted hash/password size</span></pre>
<pre><span class="lnum"> 125:  </span>            buffer.Read(keyLengthBuffer, 0, 4);</pre>
<pre><span class="lnum"> 126:  </span> </pre>
<pre><span class="lnum"> 127:  </span>            var    keyLength    = BitConverter.ToInt32(keyLengthBuffer, 0);</pre>
<pre><span class="lnum"> 128:  </span>            var    keyHash        = <span class="kwrd">new</span> <span class="kwrd">byte</span>[20];    <span class="rem">// First 20 bytes is SHA1 hash</span></pre>
<pre><span class="lnum"> 129:  </span>            var    keyPassword    = <span class="kwrd">new</span> <span class="kwrd">byte</span>[keyLength - 20];    <span class="rem">// Remaining byes are encrypted password</span></pre>
<pre><span class="lnum"> 130:  </span> </pre>
<pre><span class="lnum"> 131:  </span>            buffer.Read(keyHash, 0, 20);    <span class="rem">// Read first 20 bytes (SHA1 Hash)</span></pre>
<pre><span class="lnum"> 132:  </span>            buffer.Read(keyPassword, 0, keyPassword.Length);    <span class="rem">// Read remaining bytes (password)</span></pre>
<pre><span class="lnum"> 133:  </span> </pre>
<pre><span class="lnum"> 134:  </span>            <span class="kwrd">if</span> (Convert.ToBase64String(keyHash) == thisHash)</pre>
<pre><span class="lnum"> 135:  </span>            {</pre>
<pre><span class="lnum"> 136:  </span>                password = Decrypt(keyPassword);    <span class="rem">// Decrypt password</span></pre>
<pre><span class="lnum"> 137:  </span>            }</pre>
<pre><span class="lnum"> 138:  </span>        }</pre>
<pre><span class="lnum"> 139:  </span> </pre>
<pre><span class="lnum"> 140:  </span>        <span class="kwrd">if</span> (password == <span class="kwrd">null</span>) <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Data not encrypted to your key"</span>);</pre>
<pre><span class="lnum"> 141:  </span> </pre>
<pre><span class="lnum"> 142:  </span>        <span class="rem">// remaining bytes are encrypted data</span></pre>
<pre><span class="lnum"> 143:  </span>        var encryptedData     = <span class="kwrd">new</span> <span class="kwrd">byte</span>[buffer.Length - buffer.Position];</pre>
<pre><span class="lnum"> 144:  </span> </pre>
<pre><span class="lnum"> 145:  </span>        <span class="rem">// Read remaining bytes</span></pre>
<pre><span class="lnum"> 146:  </span>        buffer.Read(encryptedData, 0, encryptedData.Length);</pre>
<pre><span class="lnum"> 147:  </span> </pre>
<pre><span class="lnum"> 148:  </span>        buffer.Close();</pre>
<pre><span class="lnum"> 149:  </span> </pre>
<pre><span class="lnum"> 150:  </span>        <span class="kwrd">return</span> CryptoProvider.Decrypt(encryptedData, password);    <span class="rem">// Decrypt data</span></pre>
<pre><span class="lnum"> 151:  </span>    }</pre>
<pre><span class="lnum"> 152:  </span> </pre>
<pre><span class="lnum"> 153:  </span> </pre>
<pre><span class="lnum"> 154:  </span>    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">byte</span>[] SubBytes(<span class="kwrd">byte</span>[] source, <span class="kwrd">int</span> offset, <span class="kwrd">int</span> length)</pre>
<pre><span class="lnum"> 155:  </span>    {</pre>
<pre><span class="lnum"> 156:  </span>        var    subData    = <span class="kwrd">new</span> <span class="kwrd">byte</span>[length - offset];</pre>
<pre><span class="lnum"> 157:  </span> </pre>
<pre><span class="lnum"> 158:  </span>        Buffer.BlockCopy(source, offset, subData, 0, length - offset);</pre>
<pre><span class="lnum"> 159:  </span> </pre>
<pre><span class="lnum"> 160:  </span>        <span class="kwrd">return</span> subData;</pre>
<pre><span class="lnum"> 161:  </span>    }</pre>
<pre><span class="lnum"> 162:  </span> </pre>
<pre><span class="lnum"> 163:  </span> </pre>
<pre><span class="lnum"> 164:  </span>    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">byte</span>[] TrimBytes(<span class="kwrd">byte</span>[] source, <span class="kwrd">int</span> maxLength)</pre>
<pre><span class="lnum"> 165:  </span>    {</pre>
<pre><span class="lnum"> 166:  </span>        <span class="kwrd">if</span> (source.Length &gt; maxLength)</pre>
<pre><span class="lnum"> 167:  </span>        {</pre>
<pre><span class="lnum"> 168:  </span>            var trimmedData = <span class="kwrd">new</span> <span class="kwrd">byte</span>[maxLength];</pre>
<pre><span class="lnum"> 169:  </span> </pre>
<pre><span class="lnum"> 170:  </span>            Buffer.BlockCopy(source, 0, trimmedData, 0, maxLength);</pre>
<pre><span class="lnum"> 171:  </span> </pre>
<pre><span class="lnum"> 172:  </span>            <span class="kwrd">return</span> trimmedData;</pre>
<pre><span class="lnum"> 173:  </span>        }</pre>
<pre><span class="lnum"> 174:  </span> </pre>
<pre><span class="lnum"> 175:  </span>        <span class="kwrd">return</span> source;</pre>
<pre><span class="lnum"> 176:  </span>    }</pre>
<pre><span class="lnum"> 177:  </span>}</pre>
<pre><span class="lnum"> 178:  </span> </pre>
</div>
<p>Then lets create a collection of &#8216;<em>CryptoProvider</em>&#8216; which will allow us to encrypt our data to multiple public keys.</p>
<div class="csharpcode">
<pre><span class="lnum"> 179:  </span> </pre>
<pre><span class="lnum"> 180:  </span><span class="kwrd">class</span> CryptoProviderCollection : List&lt;CryptoProvider&gt;</pre>
<pre><span class="lnum"> 181:  </span>{</pre>
<pre><span class="lnum"> 182:  </span>    <span class="kwrd">public</span> <span class="kwrd">byte</span>[] EncryptPasswordAndData(<span class="kwrd">byte</span>[] data)</pre>
<pre><span class="lnum"> 183:  </span>    {</pre>
<pre><span class="lnum"> 184:  </span>        <span class="kwrd">if</span> (<span class="kwrd">this</span>.Count &lt; 1 || <span class="kwrd">this</span>.Count &gt; 255) <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(<span class="str">"Too few or too many recepients"</span>);</pre>
<pre><span class="lnum"> 185:  </span> </pre>
<pre><span class="lnum"> 186:  </span>        var password    = CryptoProvider.RandomSequence(16 + 32);    <span class="rem">// Random password</span></pre>
<pre><span class="lnum"> 187:  </span>                                                                    <span class="rem">// First 16 = Vector</span></pre>
<pre><span class="lnum"> 188:  </span>                                                                    <span class="rem">// Last 32 = Key</span></pre>
<pre><span class="lnum"> 189:  </span>        var stream        = <span class="kwrd">new</span> MemoryStream();</pre>
<pre><span class="lnum"> 190:  </span></pre>
<pre><span class="lnum"> 191:  </span>        stream.WriteByte((<span class="kwrd">byte</span>)<span class="kwrd">this</span>.Count); <span class="rem">// First byte is recepient count</span></pre>
<pre><span class="lnum"> 192:  </span> </pre>
<pre><span class="lnum"> 193:  </span>        var encryptedPasswords    =</pre>
<pre><span class="lnum"> 194:  </span>            (</pre>
<pre><span class="lnum"> 195:  </span>                from    item</pre>
<pre><span class="lnum"> 196:  </span>                <span class="kwrd">in</span>        <span class="kwrd">this</span></pre>
<pre><span class="lnum"> 197:  </span>                select    CombineBytes</pre>
<pre><span class="lnum"> 198:  </span>                    (</pre>
<pre><span class="lnum"> 199:  </span>                        item.Hash(),            <span class="rem">// Public key hash</span></pre>
<pre><span class="lnum"> 200:  </span>                        item.Encrypt(password)    <span class="rem">// Password encrypted for recipient</span></pre>
<pre><span class="lnum"> 201:  </span>                    )</pre>
<pre><span class="lnum"> 202:  </span>            );</pre>
<pre><span class="lnum"> 203:  </span> </pre>
<pre><span class="lnum"> 204:  </span> </pre>
<pre><span class="lnum"> 205:  </span>        <span class="kwrd">foreach</span> (var encryptedPassword <span class="kwrd">in</span> encryptedPasswords)</pre>
<pre><span class="lnum"> 206:  </span>        {    <span class="rem">// For each recepient</span></pre>
<pre><span class="lnum"> 207:  </span> </pre>
<pre><span class="lnum"> 208:  </span>            <span class="rem">// Store encrypted password length as Int32 (first 4 bytes)</span></pre>
<pre><span class="lnum"> 209:  </span>            stream.Write(BitConverter.GetBytes(encryptedPassword.Length), 0, 4);</pre>
<pre><span class="lnum"> 210:  </span>            <span class="rem">// Store encrypted password</span></pre>
<pre><span class="lnum"> 211:  </span>            stream.Write(encryptedPassword, 0,  encryptedPassword.Length);</pre>
<pre><span class="lnum"> 212:  </span>        }</pre>
<pre><span class="lnum"> 213:  </span> </pre>
<pre><span class="lnum"> 214:  </span>        var encryptedData = CryptoProvider.Encrypt(data, password);    <span class="rem">// Encrypt data</span></pre>
<pre><span class="lnum"> 215:  </span> </pre>
<pre><span class="lnum"> 216:  </span>        stream.Write(encryptedData, 0, encryptedData.Length);        <span class="rem">// Store</span></pre>
<pre><span class="lnum"> 217:  </span> </pre>
<pre><span class="lnum"> 218:  </span>        var encryptedBytes = stream.ToArray();</pre>
<pre><span class="lnum"> 219:  </span> </pre>
<pre><span class="lnum"> 220:  </span>        stream.Close();</pre>
<pre><span class="lnum"> 221:  </span> </pre>
<pre><span class="lnum"> 222:  </span>        <span class="kwrd">return</span> encryptedBytes;</pre>
<pre><span class="lnum"> 223:  </span>    }</pre>
<pre><span class="lnum"> 224:  </span> </pre>
<pre><span class="lnum"> 225:  </span> </pre>
<pre><span class="lnum"> 226:  </span>    <span class="kwrd">private</span> <span class="kwrd">byte</span>[] CombineBytes(<span class="kwrd">byte</span>[] dataA, <span class="kwrd">byte</span>[] dataB)</pre>
<pre><span class="lnum"> 227:  </span>    {</pre>
<pre><span class="lnum"> 228:  </span>        var combinedData = <span class="kwrd">new</span> <span class="kwrd">byte</span>[dataA.Length + dataB.Length];</pre>
<pre><span class="lnum"> 229:  </span> </pre>
<pre><span class="lnum"> 230:  </span>        Buffer.BlockCopy(dataA, 0, combinedData, 0, dataA.Length);</pre>
<pre><span class="lnum"> 231:  </span>        Buffer.BlockCopy(dataB, 0, combinedData, dataA.Length, dataB.Length);</pre>
<pre><span class="lnum"> 232:  </span> </pre>
<pre><span class="lnum"> 233:  </span>        <span class="kwrd">return</span> combinedData;</pre>
<pre><span class="lnum"> 234:  </span>    }</pre>
<pre><span class="lnum"> 235:  </span>}</pre>
<pre><span class="lnum"> 236:  </span> </pre>
</div>
<p>Now lets see if it works.  We&#8217;ll create 3 &#8216;<em>RSA</em>&#8216; keys then encrypt the data for the first two recipients ONLY, just to see if the 3rd cannot decrypt the data (which should be the case).</p>
<div class="csharpcode">
<pre><span class="lnum"> 237:  </span> </pre>
<pre><span class="lnum"> 238:  </span><span class="kwrd">class</span> Program</pre>
<pre><span class="lnum"> 239:  </span>{</pre>
<pre><span class="lnum"> 240:  </span>    <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)</pre>
<pre><span class="lnum"> 241:  </span>    {</pre>
<pre><span class="lnum"> 242:  </span>        var    key1    = <span class="kwrd">new</span> CryptoProvider(1024);    <span class="rem">// Make a new key</span></pre>
<pre><span class="lnum"> 243:  </span>        var    key2    = <span class="kwrd">new</span> CryptoProvider(2048);    <span class="rem">// ..</span></pre>
<pre><span class="lnum"> 244:  </span>        var    key3    = <span class="kwrd">new</span> CryptoProvider(1024);    <span class="rem">// ..</span></pre>
<pre><span class="lnum"> 245:  </span> </pre>
<pre><span class="lnum"> 246:  </span>        var col    = <span class="kwrd">new</span> CryptoProviderCollection();</pre>
<pre><span class="lnum"> 247:  </span></pre>
<pre><span class="lnum"> 248:  </span>        col.Add(key1);    <span class="rem">// Add only key1 and key2</span></pre>
<pre><span class="lnum"> 249:  </span>        col.Add(key2);    <span class="rem">// to the collection</span></pre>
<pre><span class="lnum"> 250:  </span> </pre>
<pre><span class="lnum"> 251:  </span>        <span class="rem">// Encrypt data and random password for key1 and key2</span></pre>
<pre><span class="lnum"> 252:  </span>        var encryptedData    = col.EncryptPasswordAndData(Encoding.UTF8.GetBytes(<span class="str">"Test Encrypted Data"</span>));</pre>
<pre><span class="lnum"> 253:  </span></pre>
<pre><span class="lnum"> 254:  </span>        <span class="rem">// Decrypt using key1</span></pre>
<pre><span class="lnum"> 255:  </span>        Console.WriteLine(Encoding.UTF8.GetString(key1.DecryptPasswordAndData(encryptedData)));</pre>
<pre><span class="lnum"> 256:  </span>        <span class="rem">// Decrypt using key2</span></pre>
<pre><span class="lnum"> 257:  </span>        Console.WriteLine(Encoding.UTF8.GetString(key2.DecryptPasswordAndData(encryptedData)));</pre>
<pre><span class="lnum"> 258:  </span></pre>
<pre><span class="lnum"> 259:  </span>        <span class="kwrd">try</span></pre>
<pre><span class="lnum"> 260:  </span>        {</pre>
<pre><span class="lnum"> 261:  </span>            <span class="rem">// Decrypt using key3, that we DIDN'T use for encryption, this will fail</span></pre>
<pre><span class="lnum"> 262:  </span>            Console.WriteLine(Encoding.UTF8.GetString(key3.DecryptPasswordAndData(encryptedData)));</pre>
<pre><span class="lnum"> 263:  </span>        }</pre>
<pre><span class="lnum"> 264:  </span>        <span class="kwrd">catch</span> (Exception e)</pre>
<pre><span class="lnum"> 265:  </span>        {</pre>
<pre><span class="lnum"> 266:  </span>            Console.WriteLine(<span class="str">"ERROR: {0}"</span>,  e.Message.ToString());</pre>
<pre><span class="lnum"> 267:  </span>        }</pre>
<pre><span class="lnum"> 268:  </span> </pre>
<pre><span class="lnum"> 269:  </span>        Console.ReadLine();</pre>
<pre><span class="lnum"> 270:  </span>    }</pre>
<pre><span class="lnum"> 271:  </span>}</pre>
</div>
<p>And the result you should see is the following:</p>
<pre><span style="color: #000080;">Test Encrypted Data
Test Encrypted Data
ERROR: Data not encrypted to your key</span></pre>
<p>You can expand the classes to carry out &#8216;<em>exception handling</em>&#8216;, and build a robust &#8216;<em>hybrid cryptosystem</em>&#8216; from this basic implementation.</p>
<p><a href="http://www.gotinker.com/wp-uploads/2010/03/gotinker.hybridencryption.zip"><strong>Download Visual Studio 2010 Project <em>(8.33k)</em></strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2010/03/21/hybrid-cryptosystem/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Audible Ping</title>
		<link>http://www.gotinker.com/2010/03/18/audible-ping/</link>
		<comments>http://www.gotinker.com/2010/03/18/audible-ping/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 02:32:53 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[Sound]]></category>
		<category><![CDATA[audible]]></category>
		<category><![CDATA[beep]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[console.beep]]></category>
		<category><![CDATA[delegates]]></category>
		<category><![CDATA[icmp]]></category>
		<category><![CDATA[pc]]></category>
		<category><![CDATA[pcspeaker]]></category>
		<category><![CDATA[ping]]></category>
		<category><![CDATA[speaker]]></category>
		<category><![CDATA[thread]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=85</guid>
		<description><![CDATA[Audible ping gives you a hospital heart-monitor style ICMP ping utility]]></description>
			<content:encoded><![CDATA[<p>This is either the greatest or most annoying tool ever!  I have to reboot a lot of machines and I always kick of a continuous ping against them to see them go down and come up again.  I thought it would be great if I could make a hospital heart-monitor style beeping ping utility, so I did.  Here it is.</p>
<p>First lets write a &#8216;<em>ToneHandler</em>&#8216; class to control our sound.  We&#8217;ll give this the capability to either make a single &#8216;<em>beep</em>&#8216; or a continous tone (indicating the machine is down).  We&#8217;re going to use &#8216;<em>Console.Beep</em>&#8216; for this.  We&#8217;ll run our continuous tone function in its own thread so we can terminate it when the machine starts pinging again.</p>
<div class="csharpcode">
<pre><span class="lnum">   1:  </span><span class="rem">// Author Mike Lovell (mike.lovell@gotinker.com)</span></pre>
<pre><span class="lnum">   2:  </span> </pre>
<pre><span class="lnum">   3:  </span><span class="kwrd">class</span> ToneHandler</pre>
<pre><span class="lnum">   4:  </span>{</pre>
<pre><span class="lnum">   5:  </span>    <span class="kwrd">private</span>    Thread    constantToneThread;</pre>
<pre><span class="lnum">   6:  </span> </pre>
<pre><span class="lnum">   7:  </span> </pre>
<pre><span class="lnum">   8:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> SingleTone(<span class="kwrd">int</span> frequency, <span class="kwrd">int</span> duration)</pre>
<pre><span class="lnum">   9:  </span>    {</pre>
<pre><span class="lnum">  10:  </span>        Console.Beep(frequency, duration);</pre>
<pre><span class="lnum">  11:  </span>    }</pre>
<pre><span class="lnum">  12:  </span> </pre>
<pre><span class="lnum">  13:  </span> </pre>
<pre><span class="lnum">  14:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> ConstantToneBegin()</pre>
<pre><span class="lnum">  15:  </span>    {</pre>
<pre><span class="lnum">  16:  </span>        <span class="kwrd">if</span> (constantToneThread != <span class="kwrd">null</span>) <span class="kwrd">return</span>;    <span class="rem">// If already making tone, exit</span></pre>
<pre><span class="lnum">  17:  </span> </pre>
<pre><span class="lnum">  18:  </span>        constantToneThread    = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ThreadStart(<span class="kwrd">delegate</span>()</pre>
<pre><span class="lnum">  19:  </span>            {</pre>
<pre><span class="lnum">  20:  </span>                <span class="kwrd">while</span> (<span class="kwrd">true</span>)</pre>
<pre><span class="lnum">  21:  </span>                {    <span class="rem">// Infinite loop, we'll kill it later</span></pre>
<pre><span class="lnum">  22:  </span>                    Console.Beep(500, Int32.MaxValue);</pre>
<pre><span class="lnum">  23:  </span>                }</pre>
<pre><span class="lnum">  24:  </span>            }));</pre>
<pre><span class="lnum">  25:  </span> </pre>
<pre><span class="lnum">  26:  </span>        constantToneThread.IsBackground = <span class="kwrd">true</span>;</pre>
<pre><span class="lnum">  27:  </span>        constantToneThread.Start();    <span class="rem">// Kick it off</span></pre>
<pre><span class="lnum">  28:  </span>    }</pre>
<pre><span class="lnum">  29:  </span> </pre>
<pre><span class="lnum">  30:  </span> </pre>
<pre><span class="lnum">  31:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> ConstantToneEnd()</pre>
<pre><span class="lnum">  32:  </span>    {</pre>
<pre><span class="lnum">  33:  </span>        <span class="kwrd">if</span> (constantToneThread == <span class="kwrd">null</span>) <span class="kwrd">return</span>;    <span class="rem">// If already not making tone, exit</span></pre>
<pre><span class="lnum">  34:  </span> </pre>
<pre><span class="lnum">  35:  </span>        Console.Beep(500, 1);    <span class="rem">// Send another Beep, this will terminte the other one</span></pre>
<pre><span class="lnum">  36:  </span> </pre>
<pre><span class="lnum">  37:  </span>        constantToneThread.Join(500);    <span class="rem">// Terminate thread</span></pre>
<pre><span class="lnum">  38:  </span> </pre>
<pre><span class="lnum">  39:  </span>        constantToneThread = <span class="kwrd">null</span>;</pre>
<pre><span class="lnum">  40:  </span> </pre>
<pre><span class="lnum">  41:  </span>        <span class="kwrd">return</span>;</pre>
<pre><span class="lnum">  42:  </span>    }</pre>
<pre><span class="lnum">  43:  </span>}</pre>
<pre><span class="lnum">  44:  </span> </pre>
</div>
<p>Now lets make a little wrapper for the .NET &#8216;<em>Ping</em>&#8216; class.  Because we&#8217;re going to link the tone and duration of the tone to the round-trip time of the ping, all we want our ping class to return is the time the ping took, or &#8216;<em>-1</em>&#8216; if the ping failed.</p>
<div class="csharpcode">
<pre><span class="lnum">  45:  </span> </pre>
<pre><span class="lnum">  46:  </span><span class="kwrd">class</span> PingWrapper</pre>
<pre><span class="lnum">  47:  </span>{</pre>
<pre><span class="lnum">  48:  </span>    <span class="kwrd">private</span>    IPAddress    ipAddress;</pre>
<pre><span class="lnum">  49:  </span> </pre>
<pre><span class="lnum">  50:  </span>    <span class="kwrd">private</span>    Ping        ping        = <span class="kwrd">new</span> Ping();</pre>
<pre><span class="lnum">  51:  </span>    <span class="kwrd">private</span>    PingOptions    pingOptions    = <span class="kwrd">new</span> PingOptions();</pre>
<pre><span class="lnum">  52:  </span> </pre>
<pre><span class="lnum">  53:  </span>    <span class="kwrd">private</span>    <span class="kwrd">byte</span>[]        buffer        = <span class="kwrd">new</span> <span class="kwrd">byte</span>[32]</pre>
<pre><span class="lnum">  54:  </span>        {    <span class="rem">// 32 byte buffer</span></pre>
<pre><span class="lnum">  55:  </span>            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,</pre>
<pre><span class="lnum">  56:  </span>            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,</pre>
<pre><span class="lnum">  57:  </span>            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,</pre>
<pre><span class="lnum">  58:  </span>            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF</pre>
<pre><span class="lnum">  59:  </span>        };</pre>
<pre><span class="lnum">  60:  </span> </pre>
<pre><span class="lnum">  61:  </span>    <span class="kwrd">public</span> PingWrapper(<span class="kwrd">string</span> host)</pre>
<pre><span class="lnum">  62:  </span>    {</pre>
<pre><span class="lnum">  63:  </span>        <span class="rem">// Resolve the host once, not at every ping</span></pre>
<pre><span class="lnum">  64:  </span>        ipAddress = Dns.GetHostAddresses(host)[0];</pre>
<pre><span class="lnum">  65:  </span> </pre>
<pre><span class="lnum">  66:  </span>        pingOptions.DontFragment = <span class="kwrd">true</span>;</pre>
<pre><span class="lnum">  67:  </span>    }</pre>
<pre><span class="lnum">  68:  </span> </pre>
<pre><span class="lnum">  69:  </span> </pre>
<pre><span class="lnum">  70:  </span>    <span class="kwrd">public</span> <span class="kwrd">int</span> Send()</pre>
<pre><span class="lnum">  71:  </span>    {</pre>
<pre><span class="lnum">  72:  </span>        var reply = ping.Send(ipAddress, 1000, buffer, pingOptions);</pre>
<pre><span class="lnum">  73:  </span> </pre>
<pre><span class="lnum">  74:  </span>        <span class="rem">// Only send a ping every 1 second</span></pre>
<pre><span class="lnum">  75:  </span>        Thread.Sleep(1000 - (<span class="kwrd">int</span>)reply.RoundtripTime);</pre>
<pre><span class="lnum">  76:  </span> </pre>
<pre><span class="lnum">  77:  </span>        <span class="kwrd">if</span> (reply.Status == IPStatus.Success)</pre>
<pre><span class="lnum">  78:  </span>        {</pre>
<pre><span class="lnum">  79:  </span>            <span class="kwrd">return</span> (<span class="kwrd">int</span>)reply.RoundtripTime;</pre>
<pre><span class="lnum">  80:  </span>        }</pre>
<pre><span class="lnum">  81:  </span>        <span class="kwrd">else</span></pre>
<pre><span class="lnum">  82:  </span>        {</pre>
<pre><span class="lnum">  83:  </span>            <span class="kwrd">return</span> -1;</pre>
<pre><span class="lnum">  84:  </span>        }</pre>
<pre><span class="lnum">  85:  </span>    }</pre>
<pre><span class="lnum">  86:  </span>}</pre>
<pre><span class="lnum">  87:  </span> </pre>
</div>
<p>Now we&#8217;ll take the first argument of the command line and use it as the host we&#8217;re going to ping.  We&#8217;ll setup a continuous loop in a different thread (so we can terminate it from the main thread) and get it to call our tone class based on the output of ping.  We&#8217;ll also display a 1 character status of what happened (success &#8216;<em>_</em>&#8216; or failed &#8216;<em>!</em>&#8216;)</p>
<div class="csharpcode">
<pre><span class="lnum">  88:  </span> </pre>
<pre><span class="lnum">  89:  </span><span class="kwrd">class</span> Program</pre>
<pre><span class="lnum">  90:  </span>{</pre>
<pre><span class="lnum">  91:  </span>    <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)</pre>
<pre><span class="lnum">  92:  </span>    {</pre>
<pre><span class="lnum">  93:  </span>        <span class="kwrd">if</span> (args.Length != 1)</pre>
<pre><span class="lnum">  94:  </span>        {</pre>
<pre><span class="lnum">  95:  </span>            Console.WriteLine(<span class="str">"Usage: gotinker.audibleping &lt;hostname or IP&gt;"</span>);</pre>
<pre><span class="lnum">  96:  </span>            <span class="kwrd">return</span>;</pre>
<pre><span class="lnum">  97:  </span>        }</pre>
<pre><span class="lnum">  98:  </span> </pre>
<pre><span class="lnum">  99:  </span>        var    terminate    = <span class="kwrd">false</span>;</pre>
<pre><span class="lnum"> 100:  </span>        var    toneHandler = <span class="kwrd">new</span> ToneHandler();</pre>
<pre><span class="lnum"> 101:  </span>        var    ping        = <span class="kwrd">new</span> PingWrapper(args[0]);</pre>
<pre><span class="lnum"> 102:  </span> </pre>
<pre><span class="lnum"> 103:  </span>        var loopThread    = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ThreadStart(<span class="kwrd">delegate</span>()</pre>
<pre><span class="lnum"> 104:  </span>            {</pre>
<pre><span class="lnum"> 105:  </span>                <span class="kwrd">while</span> (<span class="kwrd">true</span>)</pre>
<pre><span class="lnum"> 106:  </span>                {</pre>
<pre><span class="lnum"> 107:  </span>                    <span class="kwrd">if</span> (terminate) <span class="kwrd">break</span>;</pre>
<pre><span class="lnum"> 108:  </span> </pre>
<pre><span class="lnum"> 109:  </span>                    var result = ping.Send();</pre>
<pre><span class="lnum"> 110:  </span> </pre>
<pre><span class="lnum"> 111:  </span>                    <span class="kwrd">if</span> (result == -1)</pre>
<pre><span class="lnum"> 112:  </span>                    {</pre>
<pre><span class="lnum"> 113:  </span>                        Console.Write(<span class="str">"!"</span>);</pre>
<pre><span class="lnum"> 114:  </span>                        toneHandler.ConstantToneBegin();</pre>
<pre><span class="lnum"> 115:  </span>                    }</pre>
<pre><span class="lnum"> 116:  </span>                    <span class="kwrd">else</span></pre>
<pre><span class="lnum"> 117:  </span>                    {</pre>
<pre><span class="lnum"> 118:  </span>                        Console.Write(<span class="str">"_"</span>);</pre>
<pre><span class="lnum"> 119:  </span>                        toneHandler.ConstantToneEnd();</pre>
<pre><span class="lnum"> 120:  </span>                        toneHandler.SingleTone(500 - (result / 4), ((result * 4) + 100));</pre>
<pre><span class="lnum"> 121:  </span>                    }</pre>
<pre><span class="lnum"> 122:  </span>                }</pre>
<pre><span class="lnum"> 123:  </span>            }));</pre>
<pre><span class="lnum"> 124:  </span> </pre>
<pre><span class="lnum"> 125:  </span>        Console.WriteLine(<span class="str">"(Press any enter to exit)"</span>);</pre>
<pre><span class="lnum"> 126:  </span> </pre>
<pre><span class="lnum"> 127:  </span>        loopThread.Start();</pre>
<pre><span class="lnum"> 128:  </span> </pre>
<pre><span class="lnum"> 129:  </span>        Console.ReadLine();</pre>
<pre><span class="lnum"> 130:  </span> </pre>
<pre><span class="lnum"> 131:  </span>        terminate = <span class="kwrd">true</span>;    <span class="rem">// Our loops checks for this to exit</span></pre>
<pre><span class="lnum"> 132:  </span> </pre>
<pre><span class="lnum"> 133:  </span>        <span class="kwrd">while</span> (loopThread.ThreadState == ThreadState.Running)</pre>
<pre><span class="lnum"> 134:  </span>        {</pre>
<pre><span class="lnum"> 135:  </span>            Thread.Sleep(50);    <span class="rem">// Wait fot the thread to terminate</span></pre>
<pre><span class="lnum"> 136:  </span>        }</pre>
<pre><span class="lnum"> 137:  </span>    }</pre>
<pre><span class="lnum"> 138:  </span>}</pre>
</div>
<p>And the result, here&#8217;s me pinging something while I reboot it (<a href="http://www.gotinker.com/wp-uploads/2010/03/gotinker.audibleping.mp3">Download Audio of Demo</a>):</p>
<pre>(Press any enter to exit)
________!!!!!!_________!_____________</pre>
<p><a href="http://www.gotinker.com/wp-uploads/2010/03/gotinker.audibleping.zip"><strong>Download Visual Studio 2010 Project <em>(7.16k)</em></strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2010/03/18/audible-ping/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://www.gotinker.com/wp-uploads/2010/03/gotinker.audibleping.mp3" length="360360" type="audio/mpeg" />
		</item>
		<item>
		<title>Handling Unhandled Exceptions</title>
		<link>http://www.gotinker.com/2010/03/16/handling-unhandled-exceptions/</link>
		<comments>http://www.gotinker.com/2010/03/16/handling-unhandled-exceptions/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 01:34:18 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[Exception Handling]]></category>
		<category><![CDATA[delegate]]></category>
		<category><![CDATA[delegates]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[exception]]></category>
		<category><![CDATA[handler]]></category>
		<category><![CDATA[mail]]></category>
		<category><![CDATA[unhandled]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=78</guid>
		<description><![CDATA[Hooking up the 'UnhandledException' event handler is a great way to let your end-users notify you of any unexpected problems]]></description>
			<content:encoded><![CDATA[<p>If an exception occurs outside a &#8216;<em>try-catch block</em>&#8216;, it&#8217;s nice to have a way of either logging this, or having yourself notified.  The &#8216;<em>EventLog</em>&#8216; might be a way to go, but in the case of software running on your end-users PC, you might want to make it easy for them to send &#8216;<em>unhandled exceptions</em>&#8216; to you directly.  After all, if it&#8217;s complicated they may not have the technical expertise to get the information to you.  Something you might find easy might be beyond the reach of your end-users.</p>
<p>Here&#8217;s a quick example of both how to implement a &#8216;<em>UnhandledException</em>&#8216; EventHandler, and how to allow your end-user to easily email the information to you.</p>
<p>First lets make a little function that&#8217;s designed to fail!  This following function is going to always throw an Exception (divide by zero).</p>
<div class="csharpcode">
<pre><span class="lnum">   1:  </span><span class="kwrd">class</span> Program</pre>
<pre><span class="lnum">   2:  </span>{</pre>
<pre><span class="lnum">   3:  </span>    <span class="rem">// Author Mike Lovell (mike.lovell@gotinker.com)</span></pre>
<pre><span class="lnum">   4:  </span> </pre>
<pre><span class="lnum">   5:  </span>    <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">int</span> OtherFunction(<span class="kwrd">int</span> i)</pre>
<pre><span class="lnum">   6:  </span>    {</pre>
<pre><span class="lnum">   7:  </span>        var j = 0;</pre>
<pre><span class="lnum">   8:  </span> </pre>
<pre><span class="lnum">   9:  </span>        <span class="kwrd">return</span> i / j;    <span class="rem">// Divide by zero exception</span></pre>
<pre><span class="lnum">  10:  </span>                        <span class="rem">// will happen here</span></pre>
<pre><span class="lnum">  11:  </span>    }</pre>
<pre><span class="lnum">  12:  </span> </pre>
</div>
<p>Now the handler.  Inside &#8216;<em>AppDomain.CurrentDomain</em>&#8216; lives the &#8216;<em>UnhandledException</em>&#8216; event handler, this is fired when an exception is thrown (and of course, not handled!).  What we&#8217;re going to do is open up the end-users default mail client, with the &#8216;<em>to</em>&#8216;, &#8216;<em>subject</em>&#8216; and &#8216;<em>body</em>&#8216; prefilled with the information we need.  In this case, we&#8217;re going to take the date, the full path and filename of the executable and the full exception (including stack trace).  Because we want the exception exactly as it would have appeared, and including any non-latin characters (their mail client may not support) we&#8217;ve Base64 encoded the UTF8 bytes of our exception string.</p>
<p>We can very easily reverse this process at the other end, to get to the exception.</p>
<div class="csharpcode">
<pre><span class="lnum">  13:  </span> </pre>
<pre><span class="lnum">  14:  </span>    <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] cargs)</pre>
<pre><span class="lnum">  15:  </span>    {</pre>
<pre><span class="lnum">  16:  </span>        AppDomain.CurrentDomain.UnhandledException += <span class="kwrd">delegate</span>(<span class="kwrd">object</span> sender, UnhandledExceptionEventArgs args)</pre>
<pre><span class="lnum">  17:  </span>            {</pre>
<pre><span class="lnum">  18:  </span>                var exception = ((Exception)args.ExceptionObject);</pre>
<pre><span class="lnum">  19:  </span> </pre>
<pre><span class="lnum">  20:  </span>                var mailProcess = Process.Start</pre>
<pre><span class="lnum">  21:  </span>                    (</pre>
<pre><span class="lnum">  22:  </span>                        String.Format</pre>
<pre><span class="lnum">  23:  </span>                            (</pre>
<pre><span class="lnum">  24:  </span>                                <span class="str">"mailto:null@gotinker.com?subject=Unhandled Exception ({0})&amp;body={1}%0A{2}%0A%0A{3}"</span>,</pre>
<pre><span class="lnum">  25:  </span>                                HttpUtility.HtmlEncode(exception.Message),</pre>
<pre><span class="lnum">  26:  </span>                                DateTime.UtcNow.ToString(<span class="str">"yyyy-MM-dd hh:mm:ss"</span>),</pre>
<pre><span class="lnum">  27:  </span>                                Process.GetCurrentProcess().MainModule.FileName,</pre>
<pre><span class="lnum">  28:  </span>                                Convert.ToBase64String(Encoding.UTF8.GetBytes(exception.ToString())</pre>
<pre><span class="lnum">  29:  </span>                            )</pre>
<pre><span class="lnum">  30:  </span>                        )</pre>
<pre><span class="lnum">  31:  </span>                    );</pre>
<pre><span class="lnum">  32:  </span>            };</pre>
</div>
<p>Now we want to call the function so we actually cause the exception to be thrown</p>
<div class="csharpcode">
<pre><span class="lnum">  33:  </span> </pre>
<pre><span class="lnum">  34:  </span>        OtherFunction(123);</pre>
<pre><span class="lnum">  35:  </span>    }</pre>
<pre><span class="lnum">  36:  </span>}</pre>
</div>
<p>And the result?  Should look something like this:</p>
<div id="attachment_79" class="wp-caption alignnone" style="width: 265px"><a href="http://www.gotinker.com/wp-uploads/2010/03/gotinker.exceptionhandler.email_.jpg"><img class="size-medium wp-image-79" title="GoTinker Exception Handler Email" src="http://www.gotinker.com/wp-uploads/2010/03/gotinker.exceptionhandler.email_-255x300.jpg" alt="GoTinker Exception Handler Email" width="255" height="300" /></a><p class="wp-caption-text">Exception Handler Email</p></div>
<p><a href="http://www.gotinker.com/wp-uploads/2010/03/gotinker.unhandledexceptions.zip"><strong>Download Visual Studio 2010 Project <em>(6.78k)</em></strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2010/03/16/handling-unhandled-exceptions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Inheriting EventArgs for better events</title>
		<link>http://www.gotinker.com/2010/03/14/inheriting-eventargs-for-better-events/</link>
		<comments>http://www.gotinker.com/2010/03/14/inheriting-eventargs-for-better-events/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 04:41:58 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Events]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=74</guid>
		<description><![CDATA[In a lot of cases, you need to return some custom data from your events.  Inheriting from &#8216;EventArgs&#8217; gives you the opportunity to do this.  Here&#8217;s an example of how you do it.  Fortunately this time, it&#8217;s all self explanatory. 1: // Author Mike Lovell (mike.lovell@gotinker.com) 2: &#160; 3: class Firey 4: { 5: public class [...]]]></description>
			<content:encoded><![CDATA[<p>In a lot of cases, you need to return some custom data from your events.  Inheriting from &#8216;EventArgs&#8217; gives you the opportunity to do this.  Here&#8217;s an example of how you do it.  Fortunately this time, it&#8217;s all self explanatory.</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<div class="csharpcode">
<pre><span class="lnum">   1:  </span><span class="rem">// Author Mike Lovell (mike.lovell@gotinker.com)</span></pre>
<pre><span class="lnum">   2:  </span>&nbsp;</pre>
<pre><span class="lnum">   3:  </span><span class="kwrd">class</span> Firey</pre>
<pre><span class="lnum">   4:  </span>{</pre>
<pre><span class="lnum">   5:  </span>    <span class="kwrd">public</span> <span class="kwrd">class</span> MyEventArgs : EventArgs</pre>
<pre><span class="lnum">   6:  </span>    {</pre>
<pre><span class="lnum">   7:  </span>        <span class="kwrd">public</span>    <span class="kwrd">bool</span>    IsSomethingNice;</pre>
<pre><span class="lnum">   8:  </span>        <span class="kwrd">public</span>    <span class="kwrd">int</span>        SomeNumber;</pre>
<pre><span class="lnum">   9:  </span>        <span class="kwrd">public</span>    <span class="kwrd">string</span>    SomeText;</pre>
<pre><span class="lnum">  10:  </span>    }</pre>
<pre><span class="lnum">  11:  </span>&nbsp;</pre>
<pre><span class="lnum">  12:  </span>&nbsp;</pre>
<pre><span class="lnum">  13:  </span>    <span class="kwrd">public</span>    <span class="kwrd">event</span>    EventHandler&lt;MyEventArgs&gt;    MyEvent;</pre>
<pre><span class="lnum">  14:  </span>&nbsp;</pre>
<pre><span class="lnum">  15:  </span>&nbsp;</pre>
<pre><span class="lnum">  16:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> FireEvent()</pre>
<pre><span class="lnum">  17:  </span>    {</pre>
<pre><span class="lnum">  18:  </span>        <span class="kwrd">if</span> (MyEvent != <span class="kwrd">null</span>) MyEvent(<span class="kwrd">this</span>, <span class="kwrd">new</span> MyEventArgs()</pre>
<pre><span class="lnum">  19:  </span>            {</pre>
<pre><span class="lnum">  20:  </span>                IsSomethingNice    = <span class="kwrd">true</span>,</pre>
<pre><span class="lnum">  21:  </span>                SomeNumber        = 666,</pre>
<pre><span class="lnum">  22:  </span>                SomeText        = <span class="str">"Hello World"</span></pre>
<pre><span class="lnum">  23:  </span>            });</pre>
<pre><span class="lnum">  24:  </span>    }</pre>
<pre><span class="lnum">  25:  </span>}</pre>
<pre><span class="lnum">  26:  </span>&nbsp;</pre>
<pre><span class="lnum">  27:  </span>&nbsp;</pre>
<pre><span class="lnum">  28:  </span>&nbsp;</pre>
<pre><span class="lnum">  29:  </span><span class="kwrd">class</span> Program</pre>
<pre><span class="lnum">  30:  </span>{</pre>
<pre><span class="lnum">  31:  </span>    <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] pargs)</pre>
<pre><span class="lnum">  32:  </span>    {</pre>
<pre><span class="lnum">  33:  </span>        var firey    = <span class="kwrd">new</span> Firey();</pre>
<pre><span class="lnum">  34:  </span>&nbsp;</pre>
<pre><span class="lnum">  35:  </span>        firey.MyEvent += <span class="kwrd">delegate</span>(<span class="kwrd">object</span> sender, Firey.MyEventArgs args)</pre>
<pre><span class="lnum">  36:  </span>            {</pre>
<pre><span class="lnum">  37:  </span>                Console.WriteLine</pre>
<pre><span class="lnum">  38:  </span>                    (</pre>
<pre><span class="lnum">  39:  </span>                        <span class="str">"Event Fired:nIsSomethingNice: {0}nSomeNumber: {1}nSomeText: {2}"</span>,</pre>
<pre><span class="lnum">  40:  </span>                        args.IsSomethingNice,</pre>
<pre><span class="lnum">  41:  </span>                        args.SomeNumber,</pre>
<pre><span class="lnum">  42:  </span>                        args.SomeText</pre>
<pre><span class="lnum">  43:  </span>                    );</pre>
<pre><span class="lnum">  44:  </span>            };</pre>
<pre><span class="lnum">  45:  </span>&nbsp;</pre>
<pre><span class="lnum">  46:  </span>        firey.FireEvent();</pre>
<pre><span class="lnum">  47:  </span>&nbsp;</pre>
<pre><span class="lnum">  48:  </span>        Console.ReadLine();</pre>
<pre><span class="lnum">  49:  </span>    }</pre>
<pre><span class="lnum">  50:  </span>}</pre>
</div>
<p><a href="http://www.gotinker.com/wp-uploads/2010/03/gotinker.eventargs.zip"><strong>Download Visual Studio 2010 Project <em>(6.35k)</em></strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2010/03/14/inheriting-eventargs-for-better-events/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple custom thread queue</title>
		<link>http://www.gotinker.com/2010/03/13/a-simple-custom-thread-queue/</link>
		<comments>http://www.gotinker.com/2010/03/13/a-simple-custom-thread-queue/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 02:05:19 +0000</pubDate>
		<dc:creator>Mike Lovell</dc:creator>
				<category><![CDATA[Threading]]></category>
		<category><![CDATA[delegates]]></category>
		<category><![CDATA[linq]]></category>
		<category><![CDATA[queue]]></category>
		<category><![CDATA[thread]]></category>
		<category><![CDATA[threadpool]]></category>

		<guid isPermaLink="false">http://www.gotinker.com/?p=66</guid>
		<description><![CDATA[Implementing a custom thread queue can give you more control over your threads that the built-in ThreadPool.  It also makes a good intellectual excercise.]]></description>
			<content:encoded><![CDATA[<p>If you use the built-in <em>&#8216;ThreadPool&#8217;</em>, you lose a lot of control over the thread after you queue up your work.  Here&#8217;s an example of a custom thread queue.  You can add more work to it and adjust the maximum threads whilst it&#8217;s running, like the built-in <em>&#8216;ThreadPool&#8217;</em> &#8211; <strong><span style="text-decoration: underline;">But</span></strong> you can issue a <em>&#8216;Stop&#8217;</em> and terminate all the currently running threads.  You can expand the classes to add even more functionality but I&#8217;ve just covered the basics.</p>
<p>As always, I&#8217;m going to handle all my <em>&#8216;work&#8217;</em> using the <em>&#8216;Action&#8217;</em> class.  I&#8217;ll be using the <em>&#8216;Queue&#8217;</em> class to hold all my <em>&#8216;work&#8217;</em> inside, and a <em>&#8216;List&#8217;</em> to hold my threads, for which I&#8217;ll be making a simple wrapper for the <em>&#8216;Thread&#8217;</em> class called <em>&#8216;ManagedThread&#8217;</em>.</p>
<p>First lets define the <em>&#8216;ManagedThread&#8217;</em> class.  We&#8217;ll tack onto the end of the &#8216;work&#8217; a new delegate to call a <em>&#8216;Completed&#8217;</em> event.  So this will code will run after the <em>&#8216;work&#8217;</em> is completed and fire an event that can be monitored later in our code.</p>
<div class="csharpcode">
<pre><span class="lnum">   1:  </span><span class="rem">// Author: Mike Lovell (mike.lovell@gotinker.com)</span></pre>
<pre><span class="lnum">   2:  </span> </pre>
<pre><span class="lnum">   3:  </span><span class="kwrd">class</span> ManagedThread</pre>
<pre><span class="lnum">   4:  </span>{</pre>
<pre><span class="lnum">   5:  </span>    <span class="kwrd">private</span>    Thread    thread;</pre>
<pre><span class="lnum">   6:  </span>    <span class="kwrd">private</span>    Action    work;</pre>
<pre><span class="lnum">   7:  </span>    <span class="kwrd">private</span> <span class="kwrd">bool</span>    isRunning = <span class="kwrd">false</span>;</pre>
<pre><span class="lnum">   8:  </span> </pre>
<pre><span class="lnum">   9:  </span> </pre>
<pre><span class="lnum">  10:  </span>    <span class="kwrd">public</span> <span class="kwrd">bool</span> IsRunning</pre>
<pre><span class="lnum">  11:  </span>    {</pre>
<pre><span class="lnum">  12:  </span>        get { <span class="kwrd">return</span> isRunning; }</pre>
<pre><span class="lnum">  13:  </span>    }</pre>
<pre><span class="lnum">  14:  </span> </pre>
<pre><span class="lnum">  15:  </span> </pre>
<pre><span class="lnum">  16:  </span>    <span class="kwrd">public</span>    <span class="kwrd">event</span>    EventHandler&lt;EventArgs&gt;    Completed;</pre>
<pre><span class="lnum">  17:  </span> </pre>
<pre><span class="lnum">  18:  </span> </pre>
<pre><span class="lnum">  19:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> AssignWork(Action work)</pre>
<pre><span class="lnum">  20:  </span>    {</pre>
<pre><span class="lnum">  21:  </span>        <span class="kwrd">this</span>.work = <span class="kwrd">null</span>;    <span class="rem">// Clear old work</span></pre>
<pre><span class="lnum">  22:  </span> </pre>
<pre><span class="lnum">  23:  </span>        <span class="kwrd">this</span>.work += work;</pre>
<pre><span class="lnum">  24:  </span>    }</pre>
<pre><span class="lnum">  25:  </span> </pre>
<pre><span class="lnum">  26:  </span> </pre>
<pre><span class="lnum">  27:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> Start()</pre>
<pre><span class="lnum">  28:  </span>    {</pre>
<pre><span class="lnum">  29:  </span>        <span class="kwrd">if</span> (isRunning) <span class="kwrd">throw</span> <span class="kwrd">new</span> InvalidOperationException(<span class="str">"The thread is already started"</span>);</pre>
<pre><span class="lnum">  30:  </span> </pre>
<pre><span class="lnum">  31:  </span>        work += <span class="kwrd">delegate</span>()    <span class="rem">// Add our completed handler to the end of the work</span></pre>
<pre><span class="lnum">  32:  </span>            {</pre>
<pre><span class="lnum">  33:  </span>                <span class="kwrd">if</span> (Completed != <span class="kwrd">null</span>) Completed(<span class="kwrd">this</span>, EventArgs.Empty);    <span class="rem">// If there's a completed</span></pre>
<pre><span class="lnum">  34:  </span>                                                                            <span class="rem">// handled, call it!</span></pre>
<pre><span class="lnum">  35:  </span> </pre>
<pre><span class="lnum">  36:  </span>                isRunning = <span class="kwrd">false</span>;</pre>
<pre><span class="lnum">  37:  </span> </pre>
<pre><span class="lnum">  38:  </span>                thread = <span class="kwrd">null</span>;</pre>
<pre><span class="lnum">  39:  </span>            };</pre>
<pre><span class="lnum">  40:  </span> </pre>
<pre><span class="lnum">  41:  </span>        thread = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ThreadStart(work));</pre>
<pre><span class="lnum">  42:  </span> </pre>
<pre><span class="lnum">  43:  </span>        isRunning = <span class="kwrd">true</span>;</pre>
<pre><span class="lnum">  44:  </span> </pre>
<pre><span class="lnum">  45:  </span>        thread.Start();</pre>
<pre><span class="lnum">  46:  </span>    }</pre>
<pre><span class="lnum">  47:  </span> </pre>
<pre><span class="lnum">  48:  </span> </pre>
<pre><span class="lnum">  49:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> Stop()</pre>
<pre><span class="lnum">  50:  </span>    {</pre>
<pre><span class="lnum">  51:  </span>        <span class="kwrd">if</span> (!isRunning) <span class="kwrd">return</span>;    <span class="rem">// Not running anyway</span></pre>
<pre><span class="lnum">  52:  </span> </pre>
<pre><span class="lnum">  53:  </span>        <span class="kwrd">if</span> (thread.ThreadState != ThreadState.Stopped) thread.Abort();</pre>
<pre><span class="lnum">  54:  </span>    }</pre>
<pre><span class="lnum">  55:  </span>}</pre>
<pre><span class="lnum">  56:  </span> </pre>
</div>
<p>Now lets create a class to hold the threads and handle the work queue.  We&#8217;re going to add a <em>&#8216;Completed&#8217;</em> event to this class also, but this is going to only fire when we&#8217;re <em>&#8216;Completed&#8217;</em> <strong>ALL</strong> the work.  It can potential fire more than once (it will fire when the queue is empty, and there are no threads running &#8211; i.e. all the work assigned has been completed).</p>
<div class="csharpcode">
<pre><span class="lnum">  57:  </span> </pre>
<pre><span class="lnum">  58:  </span><span class="kwrd">class</span> ThreadQueue</pre>
<pre><span class="lnum">  59:  </span>{</pre>
<pre><span class="lnum">  60:  </span>    <span class="kwrd">public</span> <span class="kwrd">enum</span> QueueStatus</pre>
<pre><span class="lnum">  61:  </span>    {</pre>
<pre><span class="lnum">  62:  </span>        Stopped,</pre>
<pre><span class="lnum">  63:  </span>        Stopping,</pre>
<pre><span class="lnum">  64:  </span>        Started</pre>
<pre><span class="lnum">  65:  </span>    }</pre>
<pre><span class="lnum">  66:  </span> </pre>
<pre><span class="lnum">  67:  </span> </pre>
<pre><span class="lnum">  68:  </span>    <span class="kwrd">public</span>    <span class="kwrd">event</span>    EventHandler&lt;EventArgs&gt;    Completed;</pre>
<pre><span class="lnum">  69:  </span> </pre>
<pre><span class="lnum">  70:  </span>    <span class="kwrd">private</span>            Queue&lt;Action&gt;            workQueue    = <span class="kwrd">new</span> Queue&lt;Action&gt;();</pre>
<pre><span class="lnum">  71:  </span>    <span class="kwrd">private</span>            List&lt;ManagedThread&gt;        threads        = <span class="kwrd">new</span> List&lt;ManagedThread&gt;();</pre>
<pre><span class="lnum">  72:  </span> </pre>
<pre><span class="lnum">  73:  </span>    <span class="kwrd">public</span>    <span class="kwrd">int</span>         MaxThreads            = 10;</pre>
<pre><span class="lnum">  74:  </span>    <span class="kwrd">private</span>    <span class="kwrd">int</span>         runningThreads        =  0;</pre>
<pre><span class="lnum">  75:  </span>    <span class="kwrd">private</span>    <span class="kwrd">bool</span>        threadingMoreWork    = <span class="kwrd">false</span>;</pre>
<pre><span class="lnum">  76:  </span>    <span class="kwrd">private</span> QueueStatus status                = QueueStatus.Stopped;</pre>
<pre><span class="lnum">  77:  </span> </pre>
<pre><span class="lnum">  78:  </span> </pre>
<pre><span class="lnum">  79:  </span>    <span class="kwrd">public</span> QueueStatus Status</pre>
<pre><span class="lnum">  80:  </span>    {</pre>
<pre><span class="lnum">  81:  </span>        get { <span class="kwrd">return</span> status; }</pre>
<pre><span class="lnum">  82:  </span>        set { status = <span class="kwrd">value</span>; }</pre>
<pre><span class="lnum">  83:  </span>    }</pre>
<pre><span class="lnum">  84:  </span> </pre>
<pre><span class="lnum">  85:  </span> </pre>
<pre><span class="lnum">  86:  </span>    <span class="kwrd">public</span> <span class="kwrd">int</span> RunningThreads</pre>
<pre><span class="lnum">  87:  </span>    {</pre>
<pre><span class="lnum">  88:  </span>        get { <span class="kwrd">return</span> runningThreads; }</pre>
<pre><span class="lnum">  89:  </span>        set { runningThreads = <span class="kwrd">value</span>; }</pre>
<pre><span class="lnum">  90:  </span>    }</pre>
<pre><span class="lnum">  91:  </span> </pre>
<pre><span class="lnum">  92:  </span> </pre>
<pre><span class="lnum">  93:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> AssignWork(Action work)</pre>
<pre><span class="lnum">  94:  </span>    {</pre>
<pre><span class="lnum">  95:  </span>        <span class="kwrd">lock</span> (workQueue)</pre>
<pre><span class="lnum">  96:  </span>        {</pre>
<pre><span class="lnum">  97:  </span>            workQueue.Enqueue(work);</pre>
<pre><span class="lnum">  98:  </span>        }</pre>
<pre><span class="lnum">  99:  </span>    }</pre>
<pre><span class="lnum"> 100:  </span> </pre>
<pre><span class="lnum"> 101:  </span> </pre>
<pre><span class="lnum"> 102:  </span>    <span class="kwrd">public</span> <span class="kwrd">int</span> WorkQueueSize()</pre>
<pre><span class="lnum"> 103:  </span>    {</pre>
<pre><span class="lnum"> 104:  </span>        <span class="kwrd">return</span> workQueue.Count;</pre>
<pre><span class="lnum"> 105:  </span>    }</pre>
<pre><span class="lnum"> 106:  </span> </pre>
<pre><span class="lnum"> 107:  </span> </pre>
<pre><span class="lnum"> 108:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> Start()</pre>
<pre><span class="lnum"> 109:  </span>    {</pre>
<pre><span class="lnum"> 110:  </span>        <span class="kwrd">if</span> (status != QueueStatus.Stopped) <span class="kwrd">throw</span> <span class="kwrd">new</span> InvalidOperationException(<span class="str">"Cannot start when Status != Stopped"</span>);</pre>
<pre><span class="lnum"> 111:  </span> </pre>
<pre><span class="lnum"> 112:  </span>        status = QueueStatus.Started;</pre>
<pre><span class="lnum"> 113:  </span> </pre>
<pre><span class="lnum"> 114:  </span>        ThreadMoreWork();</pre>
<pre><span class="lnum"> 115:  </span>    }</pre>
<pre><span class="lnum"> 116:  </span> </pre>
<pre><span class="lnum"> 117:  </span> </pre>
<pre><span class="lnum"> 118:  </span>    <span class="kwrd">private</span> <span class="kwrd">void</span> ThreadMoreWork()</pre>
<pre><span class="lnum"> 119:  </span>    {</pre>
<pre><span class="lnum"> 120:  </span>        threadingMoreWork = <span class="kwrd">true</span>;</pre>
<pre><span class="lnum"> 121:  </span> </pre>
<pre><span class="lnum"> 122:  </span>        <span class="kwrd">while</span> (status == QueueStatus.Started &amp;&amp; runningThreads &lt; MaxThreads)</pre>
<pre><span class="lnum"> 123:  </span>        {    <span class="rem">// If there's more to do, thread more work</span></pre>
<pre><span class="lnum"> 124:  </span>            <span class="kwrd">lock</span> (workQueue)</pre>
<pre><span class="lnum"> 125:  </span>            {</pre>
<pre><span class="lnum"> 126:  </span>                <span class="kwrd">if</span> (workQueue.Count &gt; 0)</pre>
<pre><span class="lnum"> 127:  </span>                {</pre>
<pre><span class="lnum"> 128:  </span>                    <span class="kwrd">lock</span> (threads)</pre>
<pre><span class="lnum"> 129:  </span>                    {</pre>
<pre><span class="lnum"> 130:  </span>                        var thread = (ManagedThread)<span class="kwrd">null</span>;</pre>
<pre><span class="lnum"> 131:  </span> </pre>
<pre><span class="lnum"> 132:  </span>                        <span class="kwrd">if</span> ((thread = AvailableThread()) == <span class="kwrd">null</span>)</pre>
<pre><span class="lnum"> 133:  </span>                        {    <span class="rem">// If there's no ManagedThreads not 'Running', create a new one</span></pre>
<pre><span class="lnum"> 134:  </span>                            thread = <span class="kwrd">new</span> ManagedThread();</pre>
<pre><span class="lnum"> 135:  </span> </pre>
<pre><span class="lnum"> 136:  </span>                            thread.Completed += <span class="kwrd">delegate</span>(<span class="kwrd">object</span> sender, EventArgs args)</pre>
<pre><span class="lnum"> 137:  </span>                                {    <span class="rem">// When the thread is completed, reduce the runningthread counter</span></pre>
<pre><span class="lnum"> 138:  </span>                                    runningThreads--;</pre>
<pre><span class="lnum"> 139:  </span></pre>
<pre><span class="lnum"> 140:  </span>                                    <span class="kwrd">lock</span> (workQueue)</pre>
<pre><span class="lnum"> 141:  </span>                                    {</pre>
<pre><span class="lnum"> 142:  </span>                                        <span class="kwrd">if</span> (workQueue.Count == 0 &amp;&amp; runningThreads == 0)</pre>
<pre><span class="lnum"> 143:  </span>                                        {    <span class="rem">// All work is done, queue is empty</span></pre>
<pre><span class="lnum"> 144:  </span>                                            <span class="kwrd">lock</span> (threads)</pre>
<pre><span class="lnum"> 145:  </span>                                            {</pre>
<pre><span class="lnum"> 146:  </span>                                                threads.Clear();</pre>
<pre><span class="lnum"> 147:  </span>                                            }</pre>
<pre><span class="lnum"> 148:  </span> </pre>
<pre><span class="lnum"> 149:  </span>                                            status                = QueueStatus.Stopped;</pre>
<pre><span class="lnum"> 150:  </span>                                            threadingMoreWork    = <span class="kwrd">false</span>;</pre>
<pre><span class="lnum"> 151:  </span> </pre>
<pre><span class="lnum"> 152:  </span>                                            <span class="kwrd">if</span> (Completed != <span class="kwrd">null</span>)Completed(<span class="kwrd">this</span>, EventArgs.Empty);</pre>
<pre><span class="lnum"> 153:  </span>                                        }</pre>
<pre><span class="lnum"> 154:  </span>                                    }</pre>
<pre><span class="lnum"> 155:  </span> </pre>
<pre><span class="lnum"> 156:  </span>                                    <span class="kwrd">if</span> (!threadingMoreWork) ThreadMoreWork();    <span class="rem">// Thread more work again</span></pre>
<pre><span class="lnum"> 157:  </span>                                };</pre>
<pre><span class="lnum"> 158:  </span> </pre>
<pre><span class="lnum"> 159:  </span>                            threads.Add(thread);</pre>
<pre><span class="lnum"> 160:  </span>                        }</pre>
<pre><span class="lnum"> 161:  </span> </pre>
<pre><span class="lnum"> 162:  </span>                        thread.AssignWork(workQueue.Dequeue());    <span class="rem">// Assign work from the queue to the new thread</span></pre>
<pre><span class="lnum"> 163:  </span> </pre>
<pre><span class="lnum"> 164:  </span>                        runningThreads++;    <span class="rem">// Increase the runningthread counter</span></pre>
<pre><span class="lnum"> 165:  </span> </pre>
<pre><span class="lnum"> 166:  </span>                        thread.Start();        <span class="rem">// Start the thread</span></pre>
<pre><span class="lnum"> 167:  </span>                    }</pre>
<pre><span class="lnum"> 168:  </span>                }</pre>
<pre><span class="lnum"> 169:  </span>            }</pre>
<pre><span class="lnum"> 170:  </span>        }</pre>
<pre><span class="lnum"> 171:  </span> </pre>
<pre><span class="lnum"> 172:  </span>        threadingMoreWork = <span class="kwrd">false</span>;</pre>
<pre><span class="lnum"> 173:  </span>    }</pre>
<pre><span class="lnum"> 174:  </span> </pre>
<pre><span class="lnum"> 175:  </span> </pre>
<pre><span class="lnum"> 176:  </span>    <span class="kwrd">public</span> <span class="kwrd">void</span> Stop()</pre>
<pre><span class="lnum"> 177:  </span>    {</pre>
<pre><span class="lnum"> 178:  </span>        status = QueueStatus.Stopping;    <span class="rem">// Indicate stopping is in progess</span></pre>
<pre><span class="lnum"> 179:  </span> </pre>
<pre><span class="lnum"> 180:  </span>        <span class="kwrd">lock</span> (threads)</pre>
<pre><span class="lnum"> 181:  </span>        {</pre>
<pre><span class="lnum"> 182:  </span> </pre>
<pre><span class="lnum"> 183:  </span>            var active    =</pre>
<pre><span class="lnum"> 184:  </span>                (    <span class="rem">// Get a list of the active threads</span></pre>
<pre><span class="lnum"> 185:  </span>                    from    item</pre>
<pre><span class="lnum"> 186:  </span>                    <span class="kwrd">in</span>        threads</pre>
<pre><span class="lnum"> 187:  </span>                    <span class="kwrd">where</span>    item.IsRunning</pre>
<pre><span class="lnum"> 188:  </span>                    select    item</pre>
<pre><span class="lnum"> 189:  </span>                ).ToList();</pre>
<pre><span class="lnum"> 190:  </span> </pre>
<pre><span class="lnum"> 191:  </span>            active.ForEach(<span class="kwrd">delegate</span>(ManagedThread thread)</pre>
<pre><span class="lnum"> 192:  </span>                {    <span class="rem">// Stop each thread</span></pre>
<pre><span class="lnum"> 193:  </span>                    thread.Stop();</pre>
<pre><span class="lnum"> 194:  </span>                });</pre>
<pre><span class="lnum"> 195:  </span> </pre>
<pre><span class="lnum"> 196:  </span>            RunningThreads = 0;    <span class="rem">// There are no more threads running, so set to 0</span></pre>
<pre><span class="lnum"> 197:  </span> </pre>
<pre><span class="lnum"> 198:  </span>            threads.Clear();    <span class="rem">// Clear out the ManagedThread List</span></pre>
<pre><span class="lnum"> 199:  </span> </pre>
<pre><span class="lnum"> 200:  </span>            <span class="kwrd">if</span> (Completed != <span class="kwrd">null</span>) Completed(<span class="kwrd">this</span>, EventArgs.Empty);    <span class="rem">// If there's a completed</span></pre>
<pre><span class="lnum"> 201:  </span>                                                                        <span class="rem">// handler call it</span></pre>
<pre><span class="lnum"> 202:  </span>        }</pre>
<pre><span class="lnum"> 203:  </span>    }</pre>
<pre><span class="lnum"> 204:  </span> </pre>
<pre><span class="lnum"> 205:  </span> </pre>
<pre><span class="lnum"> 206:  </span>    <span class="kwrd">private</span> ManagedThread AvailableThread()</pre>
<pre><span class="lnum"> 207:  </span>    {</pre>
<pre><span class="lnum"> 208:  </span>        var matches =</pre>
<pre><span class="lnum"> 209:  </span>            (    <span class="rem">// Use LINQ to get the threads not running</span></pre>
<pre><span class="lnum"> 210:  </span>                from    item</pre>
<pre><span class="lnum"> 211:  </span>                <span class="kwrd">in</span>        threads</pre>
<pre><span class="lnum"> 212:  </span>                <span class="kwrd">where</span>    !item.IsRunning</pre>
<pre><span class="lnum"> 213:  </span>                select    item</pre>
<pre><span class="lnum"> 214:  </span>            );</pre>
<pre><span class="lnum"> 215:  </span> </pre>
<pre><span class="lnum"> 216:  </span>        <span class="kwrd">if</span> (matches.Count() == 0) <span class="kwrd">return</span> <span class="kwrd">null</span>;    <span class="rem">// if there is none, return a null</span></pre>
<pre><span class="lnum"> 217:  </span> </pre>
<pre><span class="lnum"> 218:  </span>        <span class="kwrd">return</span> matches.First();    <span class="rem">// Otherwise, return the first one in the enumeration</span></pre>
<pre><span class="lnum"> 219:  </span>    }</pre>
<pre><span class="lnum"> 220:  </span>}</pre>
<pre><span class="lnum"> 221:  </span> </pre>
</div>
<p>As you can see, when new work is assigned, we enter it into our <em>&#8216;Queue&lt;Action&gt;&#8217;</em> class called <em>&#8216;workQueue&#8217; </em>.  The function &#8216;ThreadMoreWork&#8217; is used to start up new threads (if needed).  When we create a new thread and add it into &#8216;threads&#8217; we hook up the &#8216;Completed&#8217; event of that thread to call <em>&#8216;ThreadMoreWork&#8217;</em> (if it&#8217;s not already running).  This means as soon as a thread is completed, we&#8217;re going to check if we need to start another one &#8211; If we do, well, we do!  In our <em>&#8216;stop&#8217;</em> function, we&#8217;re using LINQ to find all the running threads, and using the very handy <em>&#8216;ForEach&#8217;</em> function to Stop all the individual threads.  Then we fire the <em>&#8216;Completed&#8217;</em> event.</p>
<p>Now we have a simple Console application to demonstrate the classes.  It&#8217;s going to queue up 100 pieces of <em>&#8216;work&#8217;</em> (all will just print a &#8216;.&#8217; to Console).  We&#8217;ll leave the maximum threads at the default we defined earlier (10).  We also have a timer setup to run every 5 seconds and report the progress.  We&#8217;ve hooked up the &#8216;Completed&#8217; event to print &#8216;Completed&#8217; to console when we&#8217;re all done.</p>
<div class="csharpcode">
<pre><span class="lnum"> 222:  </span> </pre>
<pre><span class="lnum"> 223:  </span><span class="kwrd">class</span> Program</pre>
<pre><span class="lnum"> 224:  </span>{</pre>
<pre><span class="lnum"> 225:  </span>    <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] cargs)</pre>
<pre><span class="lnum"> 226:  </span>    {</pre>
<pre><span class="lnum"> 227:  </span>        var threadQueue = <span class="kwrd">new</span> ThreadQueue();</pre>
<pre><span class="lnum"> 228:  </span>        var checkTimer    = <span class="kwrd">new</span> Timer(<span class="kwrd">delegate</span></pre>
<pre><span class="lnum"> 229:  </span>            {    <span class="rem">// Poll for updated progress every 5 seconds</span></pre>
<pre><span class="lnum"> 230:  </span>                Console.WriteLine(<span class="str">"nThread Information Update! Running={0}, Remaining={1}"</span>, threadQueue.RunningThreads, threadQueue.WorkQueueSize());</pre>
<pre><span class="lnum"> 231:  </span> </pre>
<pre><span class="lnum"> 232:  </span>            }, <span class="kwrd">null</span>, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));</pre>
<pre><span class="lnum"> 233:  </span> </pre>
<pre><span class="lnum"> 234:  </span>        threadQueue.Completed += <span class="kwrd">delegate</span>(<span class="kwrd">object</span> sender, EventArgs args)</pre>
<pre><span class="lnum"> 235:  </span>            {</pre>
<pre><span class="lnum"> 236:  </span>                <span class="rem">// We've finished, stop the checkTimer and notify Console</span></pre>
<pre><span class="lnum"> 237:  </span>                checkTimer.Dispose();</pre>
<pre><span class="lnum"> 238:  </span>                Console.WriteLine(<span class="str">"nCompleted!"</span>);</pre>
<pre><span class="lnum"> 239:  </span>            };</pre>
<pre><span class="lnum"> 240:  </span> </pre>
<pre><span class="lnum"> 241:  </span>        <span class="kwrd">for</span> (<span class="kwrd">int</span> i=0; i&lt;100; i++)</pre>
<pre><span class="lnum"> 242:  </span>        {    <span class="rem">// Queue up our test work</span></pre>
<pre><span class="lnum"> 243:  </span>            threadQueue.AssignWork(<span class="kwrd">delegate</span>()</pre>
<pre><span class="lnum"> 244:  </span>                {</pre>
<pre><span class="lnum"> 245:  </span>                    Console.Write(<span class="str">"."</span>);</pre>
<pre><span class="lnum"> 246:  </span> </pre>
<pre><span class="lnum"> 247:  </span>                    Thread.Sleep(<span class="kwrd">new</span> Random().Next(5000));</pre>
<pre><span class="lnum"> 248:  </span>                });</pre>
<pre><span class="lnum"> 249:  </span>        }</pre>
<pre><span class="lnum"> 250:  </span> </pre>
<pre><span class="lnum"> 251:  </span>        Console.WriteLine(<span class="str">"(Press enter to stop early)"</span>);</pre>
<pre><span class="lnum"> 252:  </span> </pre>
<pre><span class="lnum"> 253:  </span>        threadQueue.Start();    <span class="rem">// Start processing</span></pre>
<pre><span class="lnum"> 254:  </span> </pre>
<pre><span class="lnum"> 255:  </span>        Console.ReadLine();</pre>
<pre><span class="lnum"> 256:  </span> </pre>
<pre><span class="lnum"> 257:  </span>        <span class="kwrd">if</span> (threadQueue.Status != ThreadQueue.QueueStatus.Stopped) threadQueue.Stop();</pre>
<pre><span class="lnum"> 258:  </span> </pre>
<pre><span class="lnum"> 259:  </span>        Console.ReadLine();    <span class="rem">// Pause so we can see the output</span></pre>
<pre><span class="lnum"> 260:  </span>    }</pre>
<pre><span class="lnum"> 261:  </span>}</pre>
</div>
<p>Run it, and the output should look a little like this&#8230;</p>
<pre><span style="color: #000080;">(Press enter to stop early)
......................
Thread Information Update! Running=10, Remaining=78
................
Thread Information Update! Running=10, Remaining=62
....................
Thread Information Update! Running=10, Remaining=42
....................
Thread Information Update! Running=10, Remaining=22
......................
Thread Information Update! Running=10, Remaining=0</span></pre>
<pre><span style="color: #000080;">Completed!</span></pre>
<p>Job done.</p>
<p><a href="http://www.gotinker.com/wp-uploads/2010/03/gotinker.customthreadqueue.zip"><strong>Download Visual Studio 2010 Project (8.03k)</strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gotinker.com/2010/03/13/a-simple-custom-thread-queue/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

