<?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>chris moos's blog</title>
	<atom:link href="http://chrismoos.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://chrismoos.com</link>
	<description>my 2 cents</description>
	<lastBuildDate>Thu, 11 Feb 2010 02:13:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Getting started with Scala using SBT</title>
		<link>http://chrismoos.com/2010/02/10/getting-started-with-scala-using-sbt/</link>
		<comments>http://chrismoos.com/2010/02/10/getting-started-with-scala-using-sbt/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 02:13:03 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[sbt]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=707</guid>
		<description><![CDATA[One of my biggest gripes with Java (and all the languages that run on the JVM) is getting my project setup and building it. Maven is not my favorite, and ant..well..I don&#8217;t like it either. Fortunately, if you want to start a new project in Scala, there is a great build tool available that takes [...]]]></description>
			<content:encoded><![CDATA[<p>One of my biggest gripes with Java (and all the languages that run on the JVM) is getting my project setup and building it. Maven is not my favorite, and ant..well..I don&#8217;t like it either. Fortunately, if you want to start a new project in Scala, there is a great build tool available that takes a lot of the pain out of project management and building &#8211; SBT, <a href="http://code.google.com/p/simple-build-tool/">simple-build-tool</a>.</p>
<blockquote><p>sbt is a simple build tool for Scala projects that aims to do the basics well. It requires Java 1.5 or later.</p></blockquote>
<h3>Installing SBT</h3>
<p>
I&#8217;m using Mac OS X, but the following instructions should be pretty much the same on any Unix based OS.
</p>
<p>You can find the latest version of SBT <a href="http://code.google.com/p/simple-build-tool/downloads/list">here</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> ~
<span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>simple-build-tool.googlecode.com<span style="color: #000000; font-weight: bold;">/</span>files<span style="color: #000000; font-weight: bold;">/</span>sbt-launcher-0.5.6.jar
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">mv</span> sbt-launcher-0.5.6.jar <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sbt-launcher.jar
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;java -Xmx512M -jar /usr/local/bin/sbt-launcher.jar <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\$</span>@<span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">tee</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sbt
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> +x <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sbt</pre></div></div>

<p>This will install the SBT jar and create a script called <em>sbt</em> that will allow you to run the sbt jar.</p>
<p>Just type <em>sbt</em> and press enter, and you know have access to sbt.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ sbt
Project does not exist, create new project? <span style="color: #7a0874; font-weight: bold;">&#40;</span>y<span style="color: #000000; font-weight: bold;">/</span>N<span style="color: #000000; font-weight: bold;">/</span>s<span style="color: #7a0874; font-weight: bold;">&#41;</span> : n</pre></div></div>

<h3>Creating a new Scala project</h3>
<p>Now we will create a Hello World Scala project with SBT.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> hello_scala
<span style="color: #7a0874; font-weight: bold;">cd</span> hello_scala</pre></div></div>

<p>Running the <em>sbt</em> command in a directory where there is no project will prompt you to create one.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">sbt</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">Project does not exist, create <span style="color: #000000; font-weight: bold;">new</span> project<span style="color: #339933;">?</span> <span style="color: #009900;">&#40;</span>y<span style="color: #339933;">/</span>N<span style="color: #339933;">/</span>s<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> y
<span style="color: #003399;">Name</span><span style="color: #339933;">:</span> Hello, Scala<span style="color: #339933;">!</span>
Organization <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> 
Version <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1.0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> 
Scala version <span style="color: #009900;">&#91;</span>2.7.7<span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> 
sbt version <span style="color: #009900;">&#91;</span>0.5.6<span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span> 
<span style="color: #339933;">::</span> retrieving <span style="color: #339933;">::</span> sbt#boot
	confs<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #000000; font-weight: bold;">default</span><span style="color: #009900;">&#93;</span>
	<span style="color: #cc66cc;">2</span> artifacts copied, <span style="color: #cc66cc;">0</span> already retrieved <span style="color: #009900;">&#40;</span>9911kB<span style="color: #339933;">/</span>72ms<span style="color: #009900;">&#41;</span>
<span style="color: #339933;">::</span> retrieving <span style="color: #339933;">::</span> sbt#boot
	confs<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #000000; font-weight: bold;">default</span><span style="color: #009900;">&#93;</span>
	<span style="color: #cc66cc;">3</span> artifacts copied, <span style="color: #cc66cc;">0</span> already retrieved <span style="color: #009900;">&#40;</span>3409kB<span style="color: #339933;">/</span>15ms<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#91;</span>success<span style="color: #009900;">&#93;</span> Successfully initialized directory structure.
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> Building project Hello, Scala<span style="color: #339933;">!</span> <span style="color: #cc66cc;">1.0</span> using sbt.<span style="color: #006633;">DefaultProject</span>
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span>    with sbt 0.5.6 and Scala 2.7.7
<span style="color: #009900;">&#91;</span>success<span style="color: #009900;">&#93;</span> Build completed successfully.
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> 
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> Total build time<span style="color: #339933;">:</span> <span style="color: #cc66cc;">0</span> s</pre></div></div>

<p>Awesome. It handles all the Scala dependencies for us! Now let&#8217;s create a file that contains our Hello, Scala example.</p>
<p>Below is the directory structure of an SBT project.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
lib	project	src</pre></div></div>

<h3>Creating our HelloScala sources and running</h3>
<p>Now we are going to create our main file, <strong>HelloScala.scala</strong></p>
<p><strong>src/main/scala/HelloScala.scala</strong></p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #0000ff; font-weight: bold;">object</span> HelloScala <span style="color: #F78811;">&#123;</span>
  <span style="color: #0000ff; font-weight: bold;">def</span> main<span style="color: #F78811;">&#40;</span>args<span style="color: #000080;">:</span> Array<span style="color: #F78811;">&#91;</span>String<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
    println<span style="color: #F78811;">&#40;</span><span style="color: #6666FF;">&quot;Hello, Scala!&quot;</span><span style="color: #F78811;">&#41;</span>
  <span style="color: #F78811;">&#125;</span>
<span style="color: #F78811;">&#125;</span></pre></div></div>

<p>And now we can build and run it by just issuing the following:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">sbt run</pre></div></div>

<p>And the output:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> Building project Hello, Scala<span style="color: #339933;">!</span> <span style="color: #cc66cc;">1.0</span> using sbt.<span style="color: #006633;">DefaultProject</span>
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span>    with sbt 0.5.6 and Scala 2.7.7
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> 
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> compile <span style="color: #339933;">==</span>
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span>   Source analysis<span style="color: #339933;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #000000; font-weight: bold;">new</span><span style="color: #339933;">/</span>modified, <span style="color: #cc66cc;">0</span> indirectly invalidated, <span style="color: #cc66cc;">0</span> removed.
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> Compiling main sources...
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> Nothing to compile.
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span>   Post<span style="color: #339933;">-</span>analysis<span style="color: #339933;">:</span> <span style="color: #cc66cc;">2</span> classes.
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> compile <span style="color: #339933;">==</span>
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> 
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> copy<span style="color: #339933;">-</span>resources <span style="color: #339933;">==</span>
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> copy<span style="color: #339933;">-</span>resources <span style="color: #339933;">==</span>
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> 
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> run <span style="color: #339933;">==</span>
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> Running HelloScala ...
<span style="color: #006633;">Hello</span>, Scala<span style="color: #339933;">!</span>
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> run <span style="color: #339933;">==</span>
<span style="color: #009900;">&#91;</span>success<span style="color: #009900;">&#93;</span> Successful.
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> 
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> Total time<span style="color: #339933;">:</span> <span style="color: #cc66cc;">0</span> s
<span style="color: #009900;">&#91;</span>success<span style="color: #009900;">&#93;</span> Build completed successfully.
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> 
<span style="color: #009900;">&#91;</span>info<span style="color: #009900;">&#93;</span> Total build time<span style="color: #339933;">:</span> <span style="color: #cc66cc;">1</span> s</pre></div></div>

<p>And that&#8217;s it. Setting up a new Scala project with SBT is painless. In the next part I will talk about managing dependencies and how SBT makes this also very easy.</p>
<p>You can read a lot more about SBT by checking out <a href="http://code.google.com/p/simple-build-tool/w/list">their wiki</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/02/10/getting-started-with-scala-using-sbt/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>AjaxTask &#8211; a rails plugin for managing background tasks</title>
		<link>http://chrismoos.com/2010/02/09/ajaxtask-a-rails-plugin-for-managing-background-tasks/</link>
		<comments>http://chrismoos.com/2010/02/09/ajaxtask-a-rails-plugin-for-managing-background-tasks/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 06:14:27 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[background]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[workling]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=684</guid>
		<description><![CDATA[SOAP, Background Tasks, and AJAX
Recently in Rails I&#8217;ve been interacting with various SOAP services and running them in the background with Workling. I needed to relay the SOAP response to the client&#8217;s web browser, so I decided to use AJAX to poll the status of my background tasks.
This is great if you have < 30 [...]]]></description>
			<content:encoded><![CDATA[<h3>SOAP, Background Tasks, and AJAX</h3>
<p>Recently in Rails I&#8217;ve been interacting with various SOAP services and running them in the background with Workling. I needed to relay the SOAP response to the client&#8217;s web browser, so I decided to use AJAX to poll the status of my background tasks.</p>
<p>This is great if you have < 30 second background tasks running, but don't want to block a user (and a request). </p>
<h3>The Solution</h3>
<p>I created a Rails plugin, called <a href="http://github.com/chrismoos/ajaxtask">AjaxTask</a>, that has two components:</p>
<ul>
<li>Methods to use in your controller to define a task handler and create tasks</li>
<li>Javascript library to manage the AJAX between the browser and the handler.
</ul>
<p>GitHub Link: <a href="http://github.com/chrismoos/ajaxtask">http://github.com/chrismoos/ajaxtask</a></p>
<p>In a nutshell, the client initiates a task, the handler responds with a task ID, and the client polls at a user defined interval until the task has finished, or has an error.</p>
<p>The plugin takes the pain out of implementing the handler, as well as the Javascript. All you have to do is run code for your task, and periodically update the status.</p>
<p>I am using <a href="http://github.com/purzelrakete/workling">Workling</a> to run my background tasks, as well as maintain the status using Workling&#8217;s return store.</p>
<p>Okay, enough with the intro, here is the example.</p>
<h3>Example</h3>
<h4>Controller/Routes</h4>
<p>The first thing to do is define the handler. This instructs the AjaxTask plugin to create a handler that will respond to ajax requests, as well as dispatch to your actual tasks. The only parameter to <em>ajaxtask_handler</em> is a symbol, which <strong>MUST</strong> be identical to a named route. This is how a URL gets from Rails to the plugin.</p>
<p><em>routes.rb</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">map.<span style="color:#9900CC;">ajaxtask_demo</span> <span style="color:#996600;">'/ajaxtask/handler/:task'</span>, <span style="color:#ff3333; font-weight:bold;">:controller</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:demo</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:ajaxtask_demo</span></pre></div></div>

<p><em>demo_controller.rb</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">ajaxtask_handler <span style="color:#ff3333; font-weight:bold;">:ajaxtask_demo</span></pre></div></div>

<p>Now we will define a task:</p>
<p><em>demo_controller.rb</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">ajaxtask <span style="color:#ff3333; font-weight:bold;">:mytask</span></pre></div></div>

<p>This tells the plugin to respond to a task named <em>mytask</em>.</p>
<p>By doing this, we must implement two methods in our controller. </p>
<p><em>mytask_start</em> is called when a browser starts a new task. You should probably fire off your background task in this method.</p>
<p><em>mytask_start</em> should return a unique ID for the task. By using Workling and calling .async, a unique ID is returned.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> mytask_start
    <span style="color:#0000FF; font-weight:bold;">return</span> MyWorklingWorker.<span style="color:#9900CC;">async_mytask</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> mytask_status<span style="color:#006600; font-weight:bold;">&#40;</span>uid<span style="color:#006600; font-weight:bold;">&#41;</span>
    Workling.<span style="color:#0000FF; font-weight:bold;">return</span>.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span>uid<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h4>The Worker</h4>
<p>The worker is the meat of our background task. In this we will do something that might take a while, and also update the status.</p>
<p><em>my_workling_worker.rb</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> MyWorklingWorker <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Workling::Base</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> mytask<span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#41;</span>
    Workling.<span style="color:#0000FF; font-weight:bold;">return</span>.<span style="color:#9900CC;">set</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:uid</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#006600; font-weight:bold;">&#123;</span>:pending <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'i am just starting...wait up!'</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">begin</span>
      <span style="color:#008000; font-style:italic;"># your long running task goes here</span>
			<span style="color:#CC0066; font-weight:bold;">sleep</span> <span style="color:#006666;">10</span>
    <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
      Workling.<span style="color:#0000FF; font-weight:bold;">return</span>.<span style="color:#9900CC;">set</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:uid</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#006600; font-weight:bold;">&#123;</span>:error <span style="color:#006600; font-weight:bold;">=&gt;</span> e.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    Workling.<span style="color:#0000FF; font-weight:bold;">return</span>.<span style="color:#9900CC;">set</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:uid</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#006600; font-weight:bold;">&#123;</span>:done <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'i finished!})
  end
end</span></pre></div></div>

<p>The important things to note here are what we set the <em>return</em> to. AjaxTask recognizes the following:</p>
<ul>
<li>:error</li>
<li>:pending</li>
<li>:done</li>
</ul>
<p>They should be pretty self explanatory. Now let&#8217;s see what the client side looks like.</p>
<h3>The Client</h3>
<p>For the client, we will be interacting with the AjaxTask javascript library. Make sure you copy the <em>ajaxtask.js</em> file to your javascripts directory, and include it in your page. The following will copy the javascript for you:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>ajaxtask
rake ajax_task_js</pre></div></div>

<p>Here is an example of what an HTML page that uses AjaxTask:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;">&lt;%= javascript_include_tag <span style="color: #ff0000;">'ajaxtask.js'</span> %<span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
function mytaskHandler() {
	$(this).bind('onTaskError', onTaskError);
	$(this).bind('onTaskFinished', onTaskFinished);
	$(this).bind('onTaskPending', onTaskPending);
&nbsp;
	function onTaskError(event, error) {
		alert('error: ' + error);
	}
&nbsp;
	function onTaskPending(event, data) {
		alert(&quot;pending: &quot; + data);
	}
&nbsp;
	function onTaskFinished(event, data) {
		alert(&quot;finished: &quot; + data);
	}
}
&nbsp;
$(document).ready(function() {	
	var myTask = new AjaxTask({
		url: &quot;<span style="color: #009900;">&lt;%= ajaxtask_demo_url :task =<span style="color: #000000; font-weight: bold;">&gt;</span></span> :mytask %&gt;&quot;,
		handler: new mytaskHandler(),
		taskStatusDiv: $(&quot;#taskStatus&quot;),
		taskStatusLoadingMsg: 'Please wait while my task runs...',
		taskStatusLoadingImg: '/images/smallactivity.gif',
		taskStatusErrorMsg: 'Oops...something bad happened.'
	});
	myTask.start();
});
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;taskStatus&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Looking at the above client code, you can see how easy it is to present a background task&#8217;s processing to a user. </p>
<p>That does it for now, I&#8217;ll try to document and post more soon abou AjaxTask.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/02/09/ajaxtask-a-rails-plugin-for-managing-background-tasks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL and partitioning tables with millions of rows</title>
		<link>http://chrismoos.com/2010/01/31/mysql-partitioning-tables-with-millions-of-rows/</link>
		<comments>http://chrismoos.com/2010/01/31/mysql-partitioning-tables-with-millions-of-rows/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 19:43:58 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[moostrax]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[partitioning]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=644</guid>
		<description><![CDATA[The Problem
I&#8217;ve been running a mobile GPS tracking service, MoosTrax (formerly BlackBerry Tracker), for a few years and have encountered a large amount of data in the process.
A user&#8217;s phone sends its location to the server and it is stored in a MySQL database. Each &#8220;location&#8221; entry is stored as a single row in a [...]]]></description>
			<content:encoded><![CDATA[<h2>The Problem</h2>
<p>I&#8217;ve been running a mobile GPS tracking service, <a href="http://moostrax.com">MoosTrax</a> (formerly BlackBerry Tracker), for a few years and have encountered a large amount of data in the process.</p>
<p>A user&#8217;s phone sends its location to the server and it is stored in a MySQL database. Each &#8220;location&#8221; entry is stored as a single row in a table.</p>
<p>Right now there are approximately 12 million rows in the location table, and things are getting slow now, as a full table scan can take ~3-4 minutes on my limited hardware. This means that if a user is pulling a location from history it could potentially block all other users (as the table is locked) access to the site until the query is complete.</p>
<h2>Partitioning</h2>
<p>Partitioning allows you to store parts of your table in their own logical space. With partitioning, you want to divide up your rows based on how you access them. If you partition your rows and you are still hitting all the partitions, it does you no good. The goal is that when you query, you will only have to look at a subset of the data to get a result, and not the whole table.</p>
<p>There are various ways in MySQL to partition a database, such as:</p>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/partitioning-range.html">RANGE</a> &#8211; rows are partitioned based on the range of a column (i.e date, 2006-2007, 2007-20008, etc,.) </li>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html">HASH</a> &#8211; hashes a column and depending on the result of the hash, has a different partition</li>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/partitioning-list.html">LIST</a>, <a href="http://dev.mysql.com/doc/refman/5.1/en/partitioning-key.html">KEY</a></li>
</ul>
<p>Choosing the partition type is important, so I looked at how my application looks up a user&#8217;s location.</p>
<p><strong>Getting a user&#8217;s current location</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Location.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:device_id <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@device</span>.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#ff3333; font-weight:bold;">:order</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;date_added desc&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:limit</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">6</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p><strong>Getting a users&#8217;s location history</strong></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Location.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:date_added <span style="color:#006600; font-weight:bold;">=&gt;</span> startdate.<span style="color:#9900CC;">utc</span>..<span style="color:#9900CC;">enddate</span>.<span style="color:#9900CC;">utc</span>, <span style="color:#ff3333; font-weight:bold;">:device_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@device</span>.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#ff3333; font-weight:bold;">:order</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;date_added desc&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:limit</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">500</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>At first, I thought about RANGE partitioning by date, and while I am using the date in my queries, it is very common for a query to have a very large date range, and that means it could easily span all partitions.</p>
<p>After a second look, it seemed that <em>device_id</em> might be the best, using the HASH partitioning type. </p>
<p>This means that all the locations would be partitioned equally by their device_id. This is great because MoosTrax is only looking at one device at a time, history or live tracking, and doesn&#8217;t aggregate the locations across devices or users. </p>
<h3>Preparing to partition</h3>
<p>First, to partition a table the column you want to partition by must be part of the primary key. I only had &#8220;id&#8221; in my primary key, so I modified it to include my partitioning column, <em>device_id</em>.</p>
<h4>Drop the Primary Key</h4>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> location <span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span></pre></div></div>

<h3>Partition the table</h3>
<p>Now we are going to add our new primary key, and tell MySQL to partition, with HASH, by device_id. We also specify the option, <em>partitions</em>, to tell MySQL how many partitions we want it to use. I believe the limit is 1024.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> location 
<span style="color: #993333; font-weight: bold;">ADD</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span>id<span style="color: #66cc66;">,</span> device_id<span style="color: #66cc66;">&#41;</span>
partition <span style="color: #993333; font-weight: bold;">BY</span> HASH<span style="color: #66cc66;">&#40;</span>device_id<span style="color: #66cc66;">&#41;</span>
partitions <span style="color: #cc66cc;">200</span></pre></div></div>

<p>FYI: Running the above may take a while depending on the size of your table.</p>
<h3>Does it work?</h3>
<p>MySQL has a command that we can run, <em>explain partitions</em>, that will let us specify a query, and MySQL will tell us if and how it is using partitioning to get the result.</p>
<p>Because we partitioned by device_id, let&#8217;s try a simple select with device_id in the where clause.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mysql<span style="color: #000000; font-weight: bold;">&gt;</span> explain partitions <span style="color: #000000; font-weight: bold;">select</span> <span style="color: #000000; font-weight: bold;">*</span> from location where device_id = <span style="color: #000000;">1</span>;
+----+-------------+----------+------------+------+---------------+-----------+---------+-------+------+-------+
<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">id</span> <span style="color: #000000; font-weight: bold;">|</span> select_type <span style="color: #000000; font-weight: bold;">|</span> table    <span style="color: #000000; font-weight: bold;">|</span> partitions <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #7a0874; font-weight: bold;">type</span> <span style="color: #000000; font-weight: bold;">|</span> possible_keys <span style="color: #000000; font-weight: bold;">|</span> key       <span style="color: #000000; font-weight: bold;">|</span> key_len <span style="color: #000000; font-weight: bold;">|</span> ref   <span style="color: #000000; font-weight: bold;">|</span> rows <span style="color: #000000; font-weight: bold;">|</span> Extra <span style="color: #000000; font-weight: bold;">|</span>
+----+-------------+----------+------------+------+---------------+-----------+---------+-------+------+-------+
<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">1</span>  <span style="color: #000000; font-weight: bold;">|</span> SIMPLE      <span style="color: #000000; font-weight: bold;">|</span> location <span style="color: #000000; font-weight: bold;">|</span> p1         <span style="color: #000000; font-weight: bold;">|</span> ref  <span style="color: #000000; font-weight: bold;">|</span> device_id     <span style="color: #000000; font-weight: bold;">|</span> device_id <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">4</span>       <span style="color: #000000; font-weight: bold;">|</span> const <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">1</span>    <span style="color: #000000; font-weight: bold;">|</span>       <span style="color: #000000; font-weight: bold;">|</span>
+----+-------------+----------+------------+------+---------------+-----------+---------+-------+------+-------+
<span style="color: #000000;">1</span> rows <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">0.14</span> sec<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
mysql<span style="color: #000000; font-weight: bold;">&gt;</span></pre></div></div>

<p>If you look at the result of the explain, you can see that MySQL only needs to use partition <em>p1</em> to find our result..this is great! There are way less rows in the partition than in the whole table. </p>
<p>Now let&#8217;s try another query, that won&#8217;t use our partitioning column.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">&nbsp;
mysql<span style="color: #000000; font-weight: bold;">&gt;</span> explain partitions <span style="color: #000000; font-weight: bold;">select</span> <span style="color: #000000; font-weight: bold;">*</span> from location where date_added <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #ff0000;">'2009-10-10'</span>;
+----+-------------+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+---------------+------+---------+------+---------+-------------+
<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">id</span> <span style="color: #000000; font-weight: bold;">|</span> select_type <span style="color: #000000; font-weight: bold;">|</span> table    <span style="color: #000000; font-weight: bold;">|</span> partitions                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #7a0874; font-weight: bold;">type</span> <span style="color: #000000; font-weight: bold;">|</span> possible_keys <span style="color: #000000; font-weight: bold;">|</span> key  <span style="color: #000000; font-weight: bold;">|</span> key_len <span style="color: #000000; font-weight: bold;">|</span> ref  <span style="color: #000000; font-weight: bold;">|</span> rows    <span style="color: #000000; font-weight: bold;">|</span> Extra       <span style="color: #000000; font-weight: bold;">|</span>
+----+-------------+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+---------------+------+---------+------+---------+-------------+
<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">1</span>  <span style="color: #000000; font-weight: bold;">|</span> SIMPLE      <span style="color: #000000; font-weight: bold;">|</span> location <span style="color: #000000; font-weight: bold;">|</span> p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25,p26,p27,p28,p29,p30,p31,p32,p33,p34,p35,p36,p37,p38,p39,p40,p41,p42,p43,p44,p45,p46,p47,p48,p49,p50,p51,p52,p53,p54,p55,p56,p57,p58,p59,p60,p61,p62,p63,p64,p65,p66,p67,p68,p69,p70,p71,p72,p73,p74,p75,p76,p77,p78,p79,p80,p81,p82,p83,p84,p85,p86,p87,p88,p89,p90,p91,p92,p93,p94,p95,p96,p97,p98,p99,p100,p101,p102,p103,p104,p105,p106,p107,p108,p109,p110,p111,p112,p113,p114,p115,p116,p117,p118,p119,p120,p121,p122,p123,p124,p125,p126,p127,p128,p129,p130,p131,p132,p133,p134,p135,p136,p137,p138,p139,p140,p141,p142,p143,p144,p145,p146,p147,p148,p149,p150,p151,p152,p153,p154,p155,p156,p157,p158,p159,p160,p161,p162,p163,p164,p165,p166,p167,p168,p169,p170,p171,p172,p173,p174,p175,p176,p177,p178,p179,p180,p181,p182,p183,p184,p185,p186,p187,p188,p189,p190,p191,p192,p193,p194,p195,p196,p197,p198,p199 <span style="color: #000000; font-weight: bold;">|</span> ALL  <span style="color: #000000; font-weight: bold;">|</span> date_added    <span style="color: #000000; font-weight: bold;">|</span> NULL <span style="color: #000000; font-weight: bold;">|</span> NULL    <span style="color: #000000; font-weight: bold;">|</span> NULL <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">12641367</span> <span style="color: #000000; font-weight: bold;">|</span> Using where <span style="color: #000000; font-weight: bold;">|</span>
+----+-------------+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+---------------+------+---------+------+---------+-------------+
<span style="color: #000000;">1</span> rows <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1.81</span> sec<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
mysql<span style="color: #000000; font-weight: bold;">&gt;</span></pre></div></div>

<p>As you can see, MySQL would need to go through all 200 partitions to get the result. Fortunately, MoosTrax doesn&#8217;t use a query like that, as the device_id is always available. Therefore, if I am searching by date, I will also specify the device_id as well, so that MySQL will use the partition.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mysql<span style="color: #000000; font-weight: bold;">&gt;</span> explain partitions <span style="color: #000000; font-weight: bold;">select</span> <span style="color: #000000; font-weight: bold;">*</span> from location where date_added <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #ff0000;">'2009-10-10'</span> and device_id = <span style="color: #000000;">1</span>;
+----+-------------+----------+------------+------+----------------------+-----------+---------+-------+------+-------------+
<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">id</span> <span style="color: #000000; font-weight: bold;">|</span> select_type <span style="color: #000000; font-weight: bold;">|</span> table    <span style="color: #000000; font-weight: bold;">|</span> partitions <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #7a0874; font-weight: bold;">type</span> <span style="color: #000000; font-weight: bold;">|</span> possible_keys        <span style="color: #000000; font-weight: bold;">|</span> key       <span style="color: #000000; font-weight: bold;">|</span> key_len <span style="color: #000000; font-weight: bold;">|</span> ref   <span style="color: #000000; font-weight: bold;">|</span> rows <span style="color: #000000; font-weight: bold;">|</span> Extra       <span style="color: #000000; font-weight: bold;">|</span>
+----+-------------+----------+------------+------+----------------------+-----------+---------+-------+------+-------------+
<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">1</span>  <span style="color: #000000; font-weight: bold;">|</span> SIMPLE      <span style="color: #000000; font-weight: bold;">|</span> location <span style="color: #000000; font-weight: bold;">|</span> p1         <span style="color: #000000; font-weight: bold;">|</span> ref  <span style="color: #000000; font-weight: bold;">|</span> device_id,date_added <span style="color: #000000; font-weight: bold;">|</span> device_id <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">4</span>       <span style="color: #000000; font-weight: bold;">|</span> const <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000;">1</span>    <span style="color: #000000; font-weight: bold;">|</span> Using where <span style="color: #000000; font-weight: bold;">|</span>
+----+-------------+----------+------------+------+----------------------+-----------+---------+-------+------+-------------+
<span style="color: #000000;">1</span> rows <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">0.11</span> sec<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
mysql<span style="color: #000000; font-weight: bold;">&gt;</span></pre></div></div>

<p>That&#8217;s better. Now its using our partitions correctly.</p>
<p>As long as you always <strong>use your partitioning column in your query</strong>, you will be able to take advantage of the partitioning.</p>
<h2>The Result</h2>
<p>After switching to partitioning, many queries are running much much faster than before. I couldn&#8217;t be happier.</p>
<p>If you want to read more about MySQL partitioning, check out the <a href="http://dev.mysql.com/doc/refman/5.1/en/partitioning.html">manual</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2010/01/31/mysql-partitioning-tables-with-millions-of-rows/feed/</wfw:commentRss>
		<slash:comments>56</slash:comments>
		</item>
		<item>
		<title>Why I didn&#8217;t like Java 5 years ago, and why I don&#8217;t like it now</title>
		<link>http://chrismoos.com/2009/12/07/why-i-didnt-like-java-5-years-ago-and-why-i-dont-like-it-now/</link>
		<comments>http://chrismoos.com/2009/12/07/why-i-didnt-like-java-5-years-ago-and-why-i-dont-like-it-now/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 01:35:34 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=634</guid>
		<description><![CDATA[Then

I started out programming in C, which taught me a lot about the fundamentals of computer science. I learned about types, memory management, functions, and logic. As I began to evaluate other programming languages to try out, I of course ended up trying Java. My first impression of it was how heavy it felt. Of [...]]]></description>
			<content:encoded><![CDATA[<h2>Then</h2>
<p>
I started out programming in C, which taught me a lot about the fundamentals of computer science. I learned about types, memory management, functions, and <em>logic</em>. As I began to evaluate other programming languages to try out, I of course ended up trying Java. My first impression of it was how heavy it felt. Of course, this was when 4GB of memory wasn&#8217;t standard in a desktop, and memory allocations and processing power &#8212; were still relatively precious. </p>
<p>I remember trying out Swing and that only made me more disgusted with Java, as a Swing application felt horribly slow. </p>
<p>Java users don&#8217;t have to worry about memory management (technically), as the garbage collection system takes care of it for the user. I think this was a huge benefit for novice developers, because dealing with memory management definitely isn&#8217;t fun &#8212; and usually presents issues if not done properly.</p>
<p>The next thing I tried in Java was creating a web application. I bought a book on J2EE and as I began learning the ins and outs, I began to hate it with a passion. The amount of configuration and boiler plate code to get something simple up and running, was a huge turn off to me. I was disgusted with the concept of EJBs and all the various patterns in J2EE. </p>
<p>After a short while, J2EE was gone with the wind for me. I moved on to scripting languages, such as the notoriously shitty PHP, which was still in my opinion, more practical than Java&#8230;but I wouldn&#8217;t settle on a good web framework and language until Python and Ruby really caught my eye.
</p>
<h2>Now</h2>
<p>Flash forward to today&#8230;and I&#8217;m still not liking Java.</p>
<p>It is still plagued with lots of configuration, descriptors, assembly, and boiler plate code. And now that memory is relatively cheap and available, Java still eats it like a fat boy eating at McDonalds. PermGen errors, anyone? The JVM has moved forward a lot in the past years, but its still a memory hog, and I feel like it abstracts so much low level coding that developers tend to not pay attention to the performance of a system &#8212; just throw more hardware at the JVM. </p>
<p>My productivity in Java is much lower than most other languages &#8212; even C. When building enterprise software in Java the complexity of getting it setup and going seems like too much at times.</p>
<p>DAO&#8217;s, interfaces, implementations, proxies &#8212; its just boring to me.</p>
<p>Ever used a BlackBerry? It feels slow to me&#8230;and I bet if it was coded in C it would be a lot snappier&#8230;same goes for Android. I&#8217;m currently using an iPhone now and it definitely feels the most repsonsive out of all 3.</p>
<p>What do you think about Java? Any recommendations on feeling more productive and not slowed down?</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/12/07/why-i-didnt-like-java-5-years-ago-and-why-i-dont-like-it-now/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>libactor now at google code</title>
		<link>http://chrismoos.com/2009/10/30/libactor-now-at-google-code/</link>
		<comments>http://chrismoos.com/2009/10/30/libactor-now-at-google-code/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 06:52:55 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[libactor]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=628</guid>
		<description><![CDATA[libactor is now available on google code. Check it out: http://code.google.com/p/libactor/
If you have any problems or ideas, post them there!
Chris
]]></description>
			<content:encoded><![CDATA[<p>libactor is now available on google code. Check it out: <a href="http://code.google.com/p/libactor/">http://code.google.com/p/libactor/</a></p>
<p>If you have any problems or ideas, post them there!</p>
<p>Chris</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/10/30/libactor-now-at-google-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>libactor &#8211; a C library based on the Actor model</title>
		<link>http://chrismoos.com/2009/10/28/libactor-a-c-library-based-on-the-actor-model/</link>
		<comments>http://chrismoos.com/2009/10/28/libactor-a-c-library-based-on-the-actor-model/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 06:38:38 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[actor]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[library]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=604</guid>
		<description><![CDATA[Recently I&#8217;ve been really interested in functional, concurrent programming languages, such as Erlang. This prompted me to have some fun in C, and try to implement a simple library that is based on the Actor Model.
Right now it is usable, although it may not be ready for production. It uses pthreads and the library handles [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve been really interested in functional, concurrent programming languages, such as Erlang. This prompted me to have some fun in C, and try to implement a simple library that is based on the <a href="http://en.wikipedia.org/wiki/Actor_model">Actor Model</a>.</p>
<p>Right now it is usable, although it may not be ready for production. It uses pthreads and the library handles all of the threading issues, so you don&#8217;t have to worry about any of it at all. </p>
<p>In a future version I plan to add more sandboxing to the actors, so that when one actor crashes, they don&#8217;t all go down!</p>
<p>Right now it supports the following:</p>
<ul>
<li>Spawn actor</li>
<li>Sending messages</li>
<li>Broadcast message</li>
<li>Actor memory management convenience functions(when an actor dies, the memory is freed!)</li>
</ul>
<p>Here is what a simple ping/pong example looks like:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;libactor/actor.h&gt;</span>
&nbsp;
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>pong_func<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        actor_msg_t <span style="color: #339933;">*</span>msg<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                msg <span style="color: #339933;">=</span> actor_receive<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>msg<span style="color: #339933;">-&gt;</span>type <span style="color: #339933;">==</span> PING_MSG<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;PING! &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                        actor_reply_msg<span style="color: #009900;">&#40;</span>msg<span style="color: #339933;">,</span> PONG_MSG<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                arelease<span style="color: #009900;">&#40;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>ping_func<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        actor_msg_t <span style="color: #339933;">*</span>msg<span style="color: #339933;">;</span>
        actor_id aid <span style="color: #339933;">=</span> spawn_actor<span style="color: #009900;">&#40;</span>pong_func<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                actor_send_msg<span style="color: #009900;">&#40;</span>aid<span style="color: #339933;">,</span> PING_MSG<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                msg <span style="color: #339933;">=</span> actor_receive<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>msg<span style="color: #339933;">-&gt;</span>type <span style="color: #339933;">==</span> PONG_MSG<span style="color: #009900;">&#41;</span> <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;PONG!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                arelease<span style="color: #009900;">&#40;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>main_func<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #993333;">struct</span> actor_main <span style="color: #339933;">*</span>main <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> actor_main<span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>args<span style="color: #339933;">;</span>
        <span style="color: #993333;">int</span> x<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* Accessing the arguments passed to the application */</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Number of arguments: %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> main<span style="color: #339933;">-&gt;</span>argc<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>x <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> x <span style="color: #339933;">&lt;</span> main<span style="color: #339933;">-&gt;</span>argc<span style="color: #339933;">;</span> x<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Argument: %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> main<span style="color: #339933;">-&gt;</span>argv<span style="color: #009900;">&#91;</span>x<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* PING/PONG example */</span>
        spawn_actor<span style="color: #009900;">&#40;</span>ping_func<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
DECLARE_ACTOR_MAIN<span style="color: #009900;">&#40;</span>main_func<span style="color: #009900;">&#41;</span></pre></div></div>

<p>There is a more detailed example in the source distribution, located in the <em>examples/</em> directory.</p>
<p>You can get the source <a href="http://chrismoos.com/libactor-0.1.tar.gz">here</a>. Please, let me know what you think about it, it was really fun to write!</p>
<p>Documentation is available here: <a href="http://chrismoos.com/libactordocs/">http://chrismoos.com/libactordocs/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/10/28/libactor-a-c-library-based-on-the-actor-model/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Colloquy for iPhone &#8212; Push Notification Server</title>
		<link>http://chrismoos.com/2009/10/22/colloquy-for-iphone-push-notification-server/</link>
		<comments>http://chrismoos.com/2009/10/22/colloquy-for-iphone-push-notification-server/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 00:04:42 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[colloquy]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[push]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=590</guid>
		<description><![CDATA[Colloquy is a great IRC client for Mac, as well as the iPhone. Currently, to run Colloquy on the iPhone you must purchase the mobile version from the App Store. The other option is to download the source and build it yourself, but you must be a registered iPhone developer to run it on an [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://colloquy.info/">Colloquy</a> is a great IRC client for Mac, as well as the iPhone. Currently, to run Colloquy on the iPhone you must purchase the mobile version from the App Store. The other option is to download the source and <a href="http://colloquy.info/project/wiki/MobileFAQs#CanIgetthesourcetobuildMobileColloquymyself">build it yourself</a>, but you must be a registered iPhone developer to run it on an actual iPhone. Also, if you intend to use push notifications (via the Colloquy ZNC plugin), you must have a push certificate as well. </p>
<h2>Getting Started</h2>
<p>I am going to assume that you have znc installed, and you know how to use it. Next, we need to install the Colloquy ZNC module, so that Colloquy can communicate with ZNC (and allow us to have push functionality). See <a href="http://colloquy.info/project/wiki/PushNotifications#ZNCforMacOSXandLinux">this page</a> for complete instructions.</p>
<p>The module for ZNC accepts commands from the Colloquy client, notably information on push notifications(device token, etc,.).</p>
<h2>Modifying the Colloquy Mobile Source</h2>
<p>Next, we need to download and <a href="http://colloquy.info/project/wiki/MobileFAQs#CanIgetthesourcetobuildMobileColloquymyself">build the source</a>. Once you have downloaded the source and loaded up the Mobile Colloquy project in Xcode, we need to make a few modifications.</p>
<h4>Certificates</h4>
<p>To run any application on an actual iPhone device, it must be signed. Login to your Developer portal on Apple&#8217;s site and generate a certificate (and make sure to enable push). Download the certificate and install it. Next, assign that certificate to the Colloquy Mobile Project. <em>Project&#8230;Edit Active Target</em>. Make sure that under the <em>Properties</em> tab, you have the same Identifier name that you used when generating the certificate. Go to Build, and then <em>Code Signing Identity</em> and select the certificate.</p>
<h4>Modifying the source</h4>
<p>Next, find the <em>CQConnectionsController.m</em> file (Controllers/Connections) and change the following line from:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>self sendRawMessage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;PUSH service colloquy.mobi 7906&quot;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>and change it to:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>self sendRawMessage<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;PUSH service 127.0.0.1 7906&quot;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>This will make the client tell the Colloquy ZNC module to send push notifications to our custom server.</p>
<p>Build the project and put it onto your device.</p>
<h2>Push Server</h2>
<p>I wrote a simple python script that waits on port 7906, receives a connection from the Colloquy ZNC module, and then pushes a notification to your phone (via Apple&#8217;s Push Service).</p>
<p>The script requires your push certificate and private key file so it can authenticate to Apple&#8217;s push service.</p>
<p>Export the push certificate and private key as a .p12 from Keychain Access. After that, we have to convert it to PEM format:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">openssl pkcs12 <span style="color: #660033;">-in</span> key.p12 <span style="color: #660033;">-out</span> certs.pem <span style="color: #660033;">-nodes</span></pre></div></div>

<p>where key.p12 is the file exported from Keychain access.</p>
<p>After that, you may need to put that certs.pem file on your server that you are running ZNC on.</p>
<h4>Installing the Colloquy Push Server</h4>
<p>Run the following to install the Colloquy Push Server:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> easy_install http:<span style="color: #000000; font-weight: bold;">//</span>www.tech9computers.com<span style="color: #000000; font-weight: bold;">/</span>ColloquyPushServer-0.1.tar.gz</pre></div></div>

<p>Next, run the command <em>colloquypushsrv.py</em> to make sure installation was successful. </p>
<p>The usage looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">usage: <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>colloquypushsrv.py <span style="color: #7a0874; font-weight: bold;">&#91;</span>-p listen_port<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>--sandbox<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>-b<span style="color: #7a0874; font-weight: bold;">&#93;</span> certs_file
	Command Summary:
		certs_file	        PEM encoded Apple Push certificate and private key <span style="color: #c20cb9; font-weight: bold;">file</span><span style="color: #7a0874; font-weight: bold;">&#40;</span>absolute path<span style="color: #7a0874; font-weight: bold;">&#41;</span>
		<span style="color: #660033;">-p</span> listen_port	Default Listen Port: <span style="color: #000000;">7906</span>	
		<span style="color: #660033;">--sandbox</span> 	Connect to Sandbox Service
		<span style="color: #660033;">-b</span>		        Run <span style="color: #000000; font-weight: bold;">in</span> background</pre></div></div>

<p>Now, let&#8217;s start the push server in the foreground. Make sure to specify the full path to the pem file we created.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">colloquypushsrv.py ~<span style="color: #000000; font-weight: bold;">/</span>certs.pem</pre></div></div>

<h2>Conclusion</h2>
<p>Finally, connect to your ZNC server with the custom built Colloquy Mobile. Your iPhone should register with the ZNC module. After, exit the Colloquy Mobile application and pull up Colloquy (or any other IRC client) on your desktop. Send yourself a message, and see if you get the push notification!</p>
<p>I realize this process may not be completely clear, so if you have any questions, I would be happy to walk you through the process.</p>
<p>Also, I just wrote this up today, so it may not be production ready <img src='http://chrismoos.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/10/22/colloquy-for-iphone-push-notification-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a FreeSWITCH Caller ID spoofing interface</title>
		<link>http://chrismoos.com/2009/10/16/writing-a-freeswitch-caller-id-spoofing-interface/</link>
		<comments>http://chrismoos.com/2009/10/16/writing-a-freeswitch-caller-id-spoofing-interface/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 00:06:21 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[callerid]]></category>
		<category><![CDATA[freeswitch]]></category>
		<category><![CDATA[spoof]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=583</guid>
		<description><![CDATA[Lately I have been really interested in voice over IP, I think there is a lot of power in it. I was using Asterisk, but I&#8217;ve moved onto a much better and more powerful solution, FreeSWITCH. I was playing with it recently and decided a Caller ID spoofing interface would be fun.
When the following script [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I have been really interested in voice over IP, I think there is a lot of power in it. I was using Asterisk, but I&#8217;ve moved onto a much better and more powerful solution, <a href="http://freeswitch.org/">FreeSWITCH</a>. I was playing with it recently and decided a Caller ID spoofing interface would be fun.</p>
<p>When the following script is ran, it will prompt you for an access code, and if it is correct, it will let you specify a number to spoof, and a number to call. Its fun <img src='http://chrismoos.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Also, it can send an email whenever a spoofed call is made (if you want to track your friends usage, for example).</p>
<p>To use the following script, put this in your dialplan: (I&#8217;ve put spoof.py in the fspy package.)</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;application</span> <span style="color: #000066;">action</span>=<span style="color: #ff0000;">&quot;python&quot;</span> <span style="color: #000066;">data</span>=<span style="color: #ff0000;">&quot;fspy.spoof&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

<h3>spoof.py</h3>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>,<span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> freeswitch <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> mktime
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">httplib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">random</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">smtplib</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_number<span style="color: black;">&#40;</span>session,invalid,num=<span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>:
	digits = session.<span style="color: black;">getDigits</span><span style="color: black;">&#40;</span>num, <span style="color: #483d8b;">&quot;#&quot;</span>, <span style="color: #ff4500;">6000</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> digits == <span style="color: #483d8b;">''</span>:
		<span style="color: #ff7700;font-weight:bold;">if</span> invalid == <span style="color: #ff4500;">3</span>:
			session.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'You have entered too many in valid entries. Goodbye.'</span><span style="color: black;">&#41;</span>
			session.<span style="color: black;">hangup</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			session.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Invalid entry. Please try again.'</span><span style="color: black;">&#41;</span>
			get_number<span style="color: black;">&#40;</span>session,invalid+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">else</span>:
		<span style="color: #ff7700;font-weight:bold;">return</span> digits
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> handler<span style="color: black;">&#40;</span>session, args<span style="color: black;">&#41;</span>:
	session.<span style="color: black;">answer</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	session.<span style="color: black;">set_tts_parms</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'cepstral'</span>, <span style="color: #483d8b;">'Allison'</span><span style="color: black;">&#41;</span>
&nbsp;
	session.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Please enter the 4 digit access code.'</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">code</span> = get_number<span style="color: black;">&#40;</span>session,<span style="color: #ff4500;">2</span>,num=<span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">code</span> == <span style="color: #008000;">None</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #dc143c;">code</span> <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">'6969'</span><span style="color: black;">&#41;</span>:
		session.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Invalid access code, goodbye!'</span><span style="color: black;">&#41;</span>
		session.<span style="color: black;">hangup</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">return</span>
	session.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Please enter the number you would like to spoof.'</span><span style="color: black;">&#41;</span>
	spoof_number = get_number<span style="color: black;">&#40;</span>session, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
	session.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Please enter the number you would like to call.'</span><span style="color: black;">&#41;</span>
	dest_number = get_number<span style="color: black;">&#40;</span>session, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
	session.<span style="color: black;">setVariable</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;effective_caller_id_number&quot;</span>, spoof_number<span style="color: black;">&#41;</span>
&nbsp;
	session.<span style="color: black;">speak</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Calling...please wait'</span><span style="color: black;">&#41;</span>
	server = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'smtp.mydomain.com'</span><span style="color: black;">&#41;</span>
&nbsp;
	fromaddr = <span style="color: #483d8b;">'freeswitch@mydomain.com'</span>
	toaddrs = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'someaddr@mydomain.com'</span><span style="color: black;">&#93;</span>
	subject = <span style="color: #483d8b;">&quot;A spoofed call was made&quot;</span>
	msg = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;From: %s<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>To: %s<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>Subject: %s<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>fromaddr, <span style="color: #483d8b;">&quot;, &quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>toaddrs<span style="color: black;">&#41;</span>, subject<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	d = <span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%A, %B %d, %Y %I:%M%p'</span><span style="color: black;">&#41;</span>
	msgContents = <span style="color: #483d8b;">&quot;Date: %s<span style="color: #000099; font-weight: bold;">\n</span>Caller ID: %s<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>Destination Number: %s<span style="color: #000099; font-weight: bold;">\n</span>Spoofed Number: %s<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>Sincerely, <span style="color: #000099; font-weight: bold;">\n</span>FreeSwitch Spoofer&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>d, session.<span style="color: black;">getVariable</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;caller_id_number&quot;</span><span style="color: black;">&#41;</span>, dest_number, spoof_number<span style="color: black;">&#41;</span>
&nbsp;
	server.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span>fromaddr, toaddrs, msg+msgContents<span style="color: black;">&#41;</span>
	session.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'transfer'</span>, dest_number<span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/10/16/writing-a-freeswitch-caller-id-spoofing-interface/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building an Erlang chat server with Comet – Part 3</title>
		<link>http://chrismoos.com/2009/10/16/building-an-erlang-chat-server-with-comet-part-3/</link>
		<comments>http://chrismoos.com/2009/10/16/building-an-erlang-chat-server-with-comet-part-3/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 23:32:12 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[chat]]></category>
		<category><![CDATA[comet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[mochiweb]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=567</guid>
		<description><![CDATA[You can see a live demo of the following tutorial here.
Overview
In the last part, we implemented the first version of our chat server. Now that the framework is down, we can start adding some more features. You can find the source for this tutorial here
In this part, we will add the following features:

Rate Limiting for [...]]]></description>
			<content:encoded><![CDATA[<p>You can see a live demo of the following tutorial <a href="http://chat.tech9computers.com">here</a>.</p>
<h2>Overview</h2>
<p>In the <a href="http://chrismoos.com/2009/09/29/building-an-erlang-chat-server-with-comet-part-2/">last part</a>, we implemented the first version of our chat server. Now that the framework is down, we can start adding some more features. You can find the source for this tutorial <a href="http://tech9computers.com/erl_chat-0.2.tar.gz">here</a></p>
<p>In this part, we will add the following features:</p>
<ul>
<li>Rate Limiting for Messages</li>
<li>Admin Login</li>
<li>Kick/Ban users</li>
<li>Limiting connections per host</li>
</ul>
<h2>Rate Limiting</h2>
<p>This feature will *help* in stopping people from spamming the chat room. It isn&#8217;t very complex, but it will give you the idea of what rate limiting can do. The algorithm for rate limiting is very simple, if a user sends too many messages in a certain interval, stop them from sending. At the top of <em>chat_room.erl</em> I&#8217;ve added the following: </p>
<p><span id="more-567"></span></p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">RATE_MSG_INTERVAL</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">3</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">RATE_MSG_COUNT</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">10</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>I&#8217;ve just randomly chosen these values for now, and it means if you try to send more than 10 messages in 3 seconds, you will be rate limited. The check for rate limiting will go in the chat_message function: </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>chat_message<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Msg</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">when</span> <span style="color: #ff3c00;">is_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Msg</span><span style="color: #109ab8;">&#41;</span> <span style="color: #ff3c00;">and</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">length</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Msg</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">&gt;</span> <span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>nick<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">C</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">CleanMsg</span> <span style="color: #014ea4;">=</span> chat_util:<span style="color: #ff3c00;">unicode_clean</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">sublist</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Msg</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">256</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">NewC</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #186895;">case</span> <span style="color: #ff3c00;">handle_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">NewC</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">CleanMsg</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
                <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S1</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S1</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
                <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span>
                    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">should_rate_limit</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">NewC</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
                        <span style="color: #109ab8;">&#123;</span>yes<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S2</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
                            <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">NewC</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;You are sending messages to fast. Please wait a few seconds and try again.&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                            <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S2</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
                        <span style="color: #109ab8;">&#123;</span>no<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">RateClient</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S2</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
                            <span style="color: #006600;">chat_postoffice</span>:<span style="color: #ff3c00;">broadcast_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>chat_msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">CleanMsg</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                            chat_postoffice:<span style="color: #ff3c00;">send_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">ID</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>sent_chat_msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">CleanMsg</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                            <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S3</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">RateClient</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>last_msg<span style="color: #014ea4;">=</span><span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S2</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                            <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S3</span><span style="color: #109ab8;">&#125;</span>
                    <span style="color: #186895;">end</span>
            <span style="color: #186895;">end</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>We&#8217;ve just added a check that calls should_rate_limit and based on what it returns, the user is rate limited(and we notify them), or they are not, and the message can be sent. Also, you may notice the <em>handle_command</em> function, we will discuss this in a little.</p>
<p>To implement rate limiting, I&#8217;ve updated our client&#8217;s state with <em>last_msg</em> and <em>msg_count</em>: </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">client_state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>
id<span style="color: #6bb810;">,</span> nick<span style="color: #6bb810;">,</span> host<span style="color: #6bb810;">,</span>last_action<span style="color: #6bb810;">,</span>admin<span style="color: #014ea4;">=</span>false<span style="color: #6bb810;">,</span>last_msg<span style="color: #014ea4;">=</span>never<span style="color: #6bb810;">,</span>msg_count<span style="color: #014ea4;">=</span><span style="color: #ff9600;">0</span>
<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Finally, the implementation of <em>should_rate_limit</em>. This function implements our simple algorithm.</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">should_rate_limit</span><span style="color: #109ab8;">&#40;</span>#<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>last_msg<span style="color: #014ea4;">=</span>never<span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">C</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> 
    <span style="color: #45b3e6;">NewState</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>last_msg<span style="color: #014ea4;">=</span><span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>msg_count<span style="color: #014ea4;">=</span><span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>no<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
<span style="color: #ff3c00;">should_rate_limit</span><span style="color: #109ab8;">&#40;</span>#<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>last_msg<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">LastMsg</span><span style="color: #6bb810;">,</span>msg_count<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Count</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">C</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #45b3e6;">RateSecs</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">calendar</span>:<span style="color: #ff3c00;">datetime_to_gregorian_seconds</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">calendar</span>:<span style="color: #ff3c00;">now_to_datetime</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">-</span> <span style="color: #ff4e18;">calendar</span>:<span style="color: #ff3c00;">datetime_to_gregorian_seconds</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">calendar</span>:<span style="color: #ff3c00;">now_to_datetime</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">LastMsg</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #186895;">case</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">RateSecs</span> <span style="color: #014ea4;">=&lt;</span> ?<span style="color: #6941fd;">RATE_MSG_INTERVAL</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Count</span> <span style="color: #014ea4;">+</span> <span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">&gt;</span> ?<span style="color: #6941fd;">RATE_MSG_COUNT</span><span style="color: #109ab8;">&#125;</span> <span style="color: #186895;">of</span>
	    <span style="color: #109ab8;">&#123;</span>true<span style="color: #6bb810;">,</span> true<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>yes<span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>msg_count<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Count</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
	    <span style="color: #109ab8;">&#123;</span>false<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>no<span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>msg_count<span style="color: #014ea4;">=</span><span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
	    <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>no<span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>msg_count<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Count</span><span style="color: #014ea4;">+</span><span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span>
	<span style="color: #186895;">end</span><span style="color: #6bb810;">;</span>
<span style="color: #ff3c00;">should_rate_limit</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>no<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<h2>Admin Control</h2>
<p>This feature allows the administrator exercise some control over the chat server, with features such as kicking/banning users. The admin features are only protected by a password. We define the admin password as so:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">ADMIN_PASSWORD</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;demopass&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>It is probably a good idea to change this password if you are running it on a public server.</p>
<p>I have updated the client state to contain another field, called <em>admin</em>. When a user joins, this value defaults to false. To become an admin, (and to change a client&#8217;s state to admin=true), the user must authenticate. To handle authentication, and various other commands, we will use an IRC style <em>/command param1 param2 param3..paramN</em>. If you want to add spaces for a parameter, surround it with quotes.</p>
<p>You probably noticed in the previous section that we added a <em>handle_command</em> check in the chat message function. This will allow us to parse and handle any possible commands. It looks like the following: </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Msg</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff4e18;">re</span>:<span style="color: #ff3c00;">run</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Msg</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;^/([A-Za-z0-9]+) ?(.+){0,1}&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span>capture<span style="color: #6bb810;">,</span> all_but_first<span style="color: #6bb810;">,</span> <span style="color: #fa6fff;">list</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>match<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Cmd</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">process_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Cmd</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>match<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Cmd</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ParamStr</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">process_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Cmd</span><span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">get_params</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">ParamStr</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> no_command<span style="color: #109ab8;">&#125;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>It takes a chat message, and tries to parse out a command. If it is valid, we then process the command further. <em>process_command</em> takes the command (value after the slash), and a list of parameters (along with the client state, and server state). Using Erlang&#8217;s pattern matching, we can easily handle any command we want by just matching the string. For now, process_command handles two commands, /help, and /auth. </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">process_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;help&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Commands: (/auth password)&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">% Generic admin handler.</span>
<span style="color: #ff3c00;">process_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;admin&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Args</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>admin<span style="color: #014ea4;">=</span>true<span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">process_admin_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Args</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">% Authenticate an administrator    </span>
<span style="color: #ff3c00;">process_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;auth&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span>?<span style="color: #6941fd;">ADMIN_PASSWORD</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> 
    <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;You are now authenticated as an administrator. Type /admin help for commands.&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #186895;">case</span> <span style="color: #45b3e6;">Client</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #6bb810;">.</span>admin <span style="color: #186895;">of</span>
        false <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">chat_postoffice</span>:<span style="color: #ff3c00;">broadcast_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>admin_logged_in<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #6bb810;">.</span>nick<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">ok</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>admin<span style="color: #014ea4;">=</span>true<span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span> 
<span style="color: #ff3c00;">process_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;auth&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Invalid adminstrator password.&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>  
&nbsp;
<span style="color: #666666; font-style: italic;">% Unknown command. </span>
<span style="color: #ff3c00;">process_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> 
    <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Invalid command or format.&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>/help just prints out help. All users can access this command. The auth command is what will give us administrator access. Using pattern matching, we can check to see if the correct password was entered. If it was, we update the client state and notify all the other users that this user has became an admin. </p>
<p>Once a user is authenticated, the <em>Generic Admin Handler</em> function will match, and the process_admin_command function will be called.</p>
<h3>Admin Commands</h3>
<p>Now that the user is logged in, we want to add some admin functionality. In this tutorial, we add the following commands:</p>
<ul>
<li>/admin logout</li>
<li>/admin help</li>
<li>/admin kick user reason</li>
<li>/admin ban user reason seconds</li>
<li>/admin unban host</li>
<li>/admin info user</li>
<li>/admin bans</li>
</ul>
<h4>Kicking a user</h4>
<p>To kick a user, the admin will specify a user, and a reason. The code is: </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">% Kick a user</span>
<span style="color: #ff3c00;">process_admin_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #ff7800;">&quot;kick&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">User</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">MySess</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_user_by_nick</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">User</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Unable to kick: user not found.&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Sess</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">C</span><span style="color: #109ab8;">&#125;</span> <span style="color: #186895;">when</span> <span style="color: #45b3e6;">Sess</span> <span style="color: #014ea4;">/=</span> <span style="color: #45b3e6;">MySess</span> <span style="color: #6bb810;">-&gt;</span> 
            <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;You have been kicked from the chat room. Reason: &quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            chat_room:<span style="color: #ff3c00;">leave</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;kicked: &quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Sorry, you can't kick yourself!&quot;</span><span style="color: #109ab8;">&#41;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>First, we lookup the user. If the user exists, we *make* them leave the chat room, and specify the reason. That&#8217;s it. </p>
<h4>Banning a user</h4>
<p>This is a little more complicated, as we want to persist the ban between server restarts. To do this, we use a <a href="http://www.erlang.org/doc/man/dets.html">DETS</a> table, which is basically ETS(Erlang&#8217;s in memory database), persisted to disk. Erlang stores the database in a file. We use the file name &#8220;bans.dets&#8221;. The table is created/opened in our chat_room init function: </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">init</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">_Args</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> 
	<span style="color: #ff3c00;">process_flag</span><span style="color: #109ab8;">&#40;</span>trap_exit<span style="color: #6bb810;">,</span> true<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">BansTable</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">dets</span>:<span style="color: #ff3c00;">open_file</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;bans.dets&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #45b3e6;">_ConnTable</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">ets</span>:<span style="color: #ff3c00;">new</span><span style="color: #109ab8;">&#40;</span>conns<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span>named_table<span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #ff4e18;">timer</span>:<span style="color: #ff3c00;">apply_after</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">CHECK_IDLE_TIME</span><span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> find_idle_clients<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>bans_table<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">BansTable</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Each item in the bans_table will be defined by the following record: </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">user_ban</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>
host<span style="color: #6bb810;">,</span>last_nick<span style="color: #6bb810;">,</span>reason<span style="color: #6bb810;">,</span>until
<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Okay, now for the fun part. First, let&#8217;s see the function to ban a user:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">% Ban a user</span>
<span style="color: #ff3c00;">process_admin_command</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #ff7800;">&quot;ban&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">User</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Seconds</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">MySess</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #109ab8;">&#123;</span><span style="color: #ff3c00;">get_user_by_nick</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">User</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #ff4e18;">string</span>:<span style="color: #ff3c00;">to_integer</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Seconds</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Unable to ban: invalid time specified.&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span><span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Unable to ban: user not found.&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span><span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span>host<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Host</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">C</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Secs</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #186895;">when</span> <span style="color: #45b3e6;">Sess</span> <span style="color: #014ea4;">/=</span> <span style="color: #45b3e6;">MySess</span> <span style="color: #6bb810;">-&gt;</span> 
            <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Mega</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Micro</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #45b3e6;">BanTime</span> <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Mega</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">S</span> <span style="color: #014ea4;">+</span> <span style="color: #45b3e6;">Secs</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Micro</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span>
            <span style="color: #45b3e6;">BanTimeStr</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">httpd_util</span>:<span style="color: #ff3c00;">rfc1123_date</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">calendar</span>:<span style="color: #ff3c00;">now_to_local_time</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">BanTime</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;You have been banned from the chat room until &quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">BanTimeStr</span> <span style="color: #014ea4;">++</span> <span style="color: #ff7800;">&quot;. Reason: &quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            chat_room:<span style="color: #ff3c00;">leave</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;banned: &quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #ff4e18;">dets</span>:<span style="color: #ff3c00;">insert</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">.</span>bans_table<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">user_ban</span><span style="color: #109ab8;">&#123;</span>host<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span>last_nick<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">User</span><span style="color: #6bb810;">,</span>reason<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Reason</span><span style="color: #6bb810;">,</span>until<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">BanTime</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">send_system_msg</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Sorry, you can't ban yourself!&quot;</span><span style="color: #109ab8;">&#41;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>This function looks up the user, and if the user exists, we let them know that they have been banned(and disconnect them) and store an item in the DETS table describing the ban.</p>
<p>Now that the user has been disconnected, we need to make sure they can&#8217;t login until the ban is up. This check is implemented in our join function.</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_call</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>join<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Host</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_From</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>clients<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Clients</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">when</span> <span style="color: #ff3c00;">is_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Nick</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #109ab8;">&#123;</span><span style="color: #ff3c00;">is_banned</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span><span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">can_connect</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Host</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">validate_nick</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span><span style="color: #109ab8;">&#123;</span>yes<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Until</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>banned<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Until</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
		<span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> no<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> too_many_conns<span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
		<span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>yes<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NumConns</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ValidNick</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">Session</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">get_unique_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #186895;">case</span> chat_postoffice:<span style="color: #ff3c00;">create_mailbox</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Session</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
                ok <span style="color: #6bb810;">-&gt;</span> 
					<span style="color: #ff3c00;">update_host_conns</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NumConns</span> <span style="color: #014ea4;">+</span> <span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                    chat_postoffice:<span style="color: #ff3c00;">broadcast_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>user_joined_room<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ValidNick</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Session</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                    <span style="color: #45b3e6;">Client</span> <span style="color: #014ea4;">=</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Session</span><span style="color: #6bb810;">,</span>nick<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">ValidNick</span><span style="color: #6bb810;">,</span>host<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span>last_action<span style="color: #014ea4;">=</span><span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span>
                    <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Session</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>clients<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Client</span> | <span style="color: #45b3e6;">Clients</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
                <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_available<span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span>
            <span style="color: #186895;">end</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>We have updated this function to call the function, is_banned, which determines if a user is indeed banned. If they are, we return an error, and the message is displayed to the user.</p>
<p>The ban function simply looks up a host/ip address in the bans table, and determines if it is still active. </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">is_banned</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>bans_table<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Table</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">Now</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #186895;">case</span> <span style="color: #ff4e18;">qlc</span>:<span style="color: #ff3c00;">e</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">qlc</span>:<span style="color: #ff3c00;">q</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Ban</span> <span style="color: #014ea4;">||</span> <span style="color: #45b3e6;">Ban</span> <span style="color: #014ea4;">&lt;-</span> <span style="color: #ff4e18;">dets</span>:<span style="color: #ff3c00;">table</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Table</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Ban</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">user_ban</span><span style="color: #6bb810;">.</span>host <span style="color: #014ea4;">==</span> <span style="color: #45b3e6;">Host</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">no</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#91;</span>#<span style="color: #d400ed;">user_ban</span><span style="color: #109ab8;">&#123;</span>until<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Until</span><span style="color: #109ab8;">&#125;</span> | <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#93;</span> <span style="color: #186895;">when</span> <span style="color: #45b3e6;">Until</span> <span style="color: #014ea4;">&gt;=</span> <span style="color: #45b3e6;">Now</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>yes<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Until</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">no</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></pre></div></div>

<h2>Connection Limiting</h2>
<p>Finally, we&#8217;ve added a simple check in the join function, called can_connect, which checks to see if a user has the maximum connections allowed open. This is defined as: </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">% Max connections per host</span>
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">MAX_CONNECTIONS</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">3</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>The number of connections for a host is stored in an ETS table. We don&#8217;t need to persist this because if the server crashes, all connections will be gone anyway. </p>
<p>When a user joins, we update the connections table.</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">% Updates a host in connections ETS table</span>
<span style="color: #ff3c00;">update_host_conns</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Conns</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff4e18;">ets</span>:<span style="color: #ff3c00;">insert</span><span style="color: #109ab8;">&#40;</span>conns<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Conns</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>When a user leaves, we update the connections table.</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">host_disconnected</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Host</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #186895;">case</span> <span style="color: #ff4e18;">ets</span>:<span style="color: #ff3c00;">lookup</span><span style="color: #109ab8;">&#40;</span>conns<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Host</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
		<span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">ok</span><span style="color: #6bb810;">;</span>
		<span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Num</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span> <span style="color: #186895;">when</span> <span style="color: #ff3c00;">is_integer</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Num</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff4e18;">ets</span>:<span style="color: #ff3c00;">insert</span><span style="color: #109ab8;">&#40;</span>conns<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Num</span> <span style="color: #014ea4;">-</span> <span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
		<span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff4e18;">ets</span>:<span style="color: #ff3c00;">insert</span><span style="color: #109ab8;">&#40;</span>conns<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span>
	<span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></pre></div></div>

<h2>Conclusion</h2>
<p>Now we have a more functional server, but it still needs lots of work(that&#8217;s for you to decide). The source is available <a href="http://tech9computers.com/erl_chat-0.2.tar.gz">here</a>. Try it out locally, by doing: </p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>tech9computers.com<span style="color: #000000; font-weight: bold;">/</span>erl_chat-0.2.tar.gz
<span style="color: #c20cb9; font-weight: bold;">tar</span> <span style="color: #660033;">-xvzf</span> erl_chat-0.2.tar.gz
<span style="color: #7a0874; font-weight: bold;">cd</span> erl_chat-<span style="color: #000000;">0.2</span>
<span style="color: #c20cb9; font-weight: bold;">make</span> erl_chat</pre></div></div>

<p>Then visit <a href="http://localhost:8000">http://localhost:8000</a> to try it out</p>
<p>If anyone has any comments/suggestions/requests please let me know, I&#8217;d be happy to get some feedback on this. And also, you can try a demo <a href="http://chat.tech9computers.com">here</a>, although don&#8217;t think that <em>demopass</em> will get you admin control <img src='http://chrismoos.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/10/16/building-an-erlang-chat-server-with-comet-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building an Erlang chat server with Comet &#8211; Part 2</title>
		<link>http://chrismoos.com/2009/09/29/building-an-erlang-chat-server-with-comet-part-2/</link>
		<comments>http://chrismoos.com/2009/09/29/building-an-erlang-chat-server-with-comet-part-2/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 01:01:34 +0000</pubDate>
		<dc:creator>Chris Moos</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[chat]]></category>
		<category><![CDATA[comet]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[mochiweb]]></category>

		<guid isPermaLink="false">http://chrismoos.com/?p=494</guid>
		<description><![CDATA[You can see a live demo of the following tutorial at chat.tech9computers.com
Getting into the code
In the previous part, I introduced the chat system and how it should work. Now we are going to write the chat_postoffice, chat_mailbox, chat_room, and chat_web modules. Before you read download the source for this tutorial here. and dedicate about 20 [...]]]></description>
			<content:encoded><![CDATA[<p>You can see a live demo of the following tutorial at <a href="http://chat.tech9computers.com">chat.tech9computers.com</a></p>
<h2>Getting into the code</h2>
<p>In the <a href="http://chrismoos.com/2009/09/28/building-an-erlang-chat-server-with-comet-part-1/">previous part</a>, I introduced the chat system and how it should work. Now we are going to write the chat_postoffice, chat_mailbox, chat_room, and chat_web modules. Before you read download the source for this tutorial <a href="http://tech9computers.com/erl_chat-0.1.tar.gz">here</a>. and dedicate about 20 minutes to read through this tutorial, because it&#8217;s kind of long (sorry).</p>
<h3>Setting up the project</h3>
<p>When you look at the source, take a look at the structure of the files and folders. There is a makefile to help you build and run the project. To run the server, just do the following:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">cd</span> erl_chat
$ <span style="color: #c20cb9; font-weight: bold;">make</span> erl_chat</pre></div></div>

<p>This will compile all the code, and start the OTP application. The web server runs on port 8000.</p>
<h2>The Mailbox Process</h2>
<p>Before we set up the post office, let&#8217;s define how a mailbox will work. First, it will run in its own process and keep a list of messages. Essentially it is just a loop, that accepts the following messages: </p>
<p><span id="more-494"></span></p>
<ul>
<li>{mail, {msg, Data}}</li>
<li>{mail, {add_listener, {MsgID, Pid}}}</li>
<li>{mail, {remove_listener, Pid}}</li>
<li>{mail, {get_msg_id, Pid}}</li>
<li>quit</li>
</ul>
<p>To create a mailbox, the post office will spawn a process and then the <em>chat_mailbox:start</em> function is called. The start function sets the initial state and then puts the process into hibernation.</p>
<h4>start</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">start</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff4e18;">proc_lib</span>:<span style="color: #ff3c00;">hibernate</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> loop<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span>#<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>The following are the record definitions for the mailbox: </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">message</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>
id<span style="color: #6bb810;">,</span>data
<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>
id<span style="color: #6bb810;">,</span>cur_id<span style="color: #014ea4;">=</span><span style="color: #ff9600;">0</span><span style="color: #6bb810;">,</span>listeners<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span>messages<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span>
<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<h4>NOTE: What is proc_lib:hibernate</h4>
<p>This function helps keep the memory footprint much lower for a process. It is very useful when a process only does action when it receives a message. It discards the call stack and garbage collects for the process. </p>
<p>Now let&#8217;s write the loop function for our mailbox. It just receives a message for our process and does something with it. Here is the entire loop function.</p>
<h4>loop</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">loop</span><span style="color: #109ab8;">&#40;</span>#<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">ID</span><span style="color: #6bb810;">,</span>cur_id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">CurID</span><span style="color: #6bb810;">,</span>messages<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Msgs</span><span style="color: #6bb810;">,</span>listeners<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Listeners</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">receive</span>
        <span style="color: #109ab8;">&#123;</span>mail<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>add_listener<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_MsgID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_Pid</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Listener</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">NewState</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">notify_listeners</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>listeners<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Listener</span> | <span style="color: #45b3e6;">Listeners</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #ff4e18;">proc_lib</span>:<span style="color: #ff3c00;">hibernate</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> loop<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>mail<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>remove_listener<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">NewListeners</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">filter</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_Id</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">P</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #45b3e6;">P</span> <span style="color: #014ea4;">/=</span> <span style="color: #45b3e6;">Pid</span> <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Listeners</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #ff4e18;">proc_lib</span>:<span style="color: #ff3c00;">hibernate</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> loop<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>listeners<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">NewListeners</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>mail<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>get_msg_id<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">!</span> <span style="color: #109ab8;">&#123;</span>cur_msg_id<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">CurID</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span>
            <span style="color: #ff4e18;">proc_lib</span>:<span style="color: #ff3c00;">hibernate</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> loop<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>mail<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Data</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">Msg</span> <span style="color: #014ea4;">=</span> #<span style="color: #d400ed;">message</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">CurID</span><span style="color: #6bb810;">,</span>data<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Data</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span>
            <span style="color: #45b3e6;">NewState</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">notify_listeners</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>messages<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Msg</span> | <span style="color: #45b3e6;">Msgs</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span>cur_id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">CurID</span><span style="color: #014ea4;">+</span><span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #ff4e18;">proc_lib</span>:<span style="color: #ff3c00;">hibernate</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> loop<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        quit <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">ok</span><span style="color: #6bb810;">;</span>
        <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff4e18;">proc_lib</span>:<span style="color: #ff3c00;">hibernate</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> loop<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Okay, let&#8217;s break down everything in that loop.</p>
<h4>add_listener</h4>
<p>When a new listener is added, the first thing we do is call notify_listeners, which will try to update the newly added listener(and any others) with any messages that have a higher/or equal message ID. Well go over notify listeners in a little.</p>
<h4>remove_listener</h4>
<p>This just goes through the list of listeners, if one matches the given Pid, remove it.</p>
<h4>get_msg_id</h4>
<p>This just returns the highest message ID (so the client knows what the latest message ID is).</p>
<h4>msg</h4>
<p>This adds a message to the mailbox. notify_listeners is also called to try and update anyone interested.</p>
<h4>quit</h4>
<p>Tells the mailbox to quit (and the process will exit).</p>
<h3>Notifying listeners</h3>
<p>Finally, our mailbox needs a <em>notify_listener</em> function. This will go through each listener and then check to see if any messages are available, and if so, send them to the Pid. If a listener is notified, it is removed also.</p>
<h4>notify_listeners</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">notify_listeners</span><span style="color: #109ab8;">&#40;</span>#<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>listeners<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Listeners</span><span style="color: #6bb810;">,</span>messages<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Msgs</span><span style="color: #6bb810;">,</span>cur_id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">CurID</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">NewListeners</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">filter</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">MsgID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
        <span style="color: #186895;">case</span> <span style="color: #45b3e6;">MsgID</span> <span style="color: #014ea4;">&gt;=</span> <span style="color: #45b3e6;">CurID</span> <span style="color: #186895;">of</span>
            true <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">true</span><span style="color: #6bb810;">;</span>
            <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span>
                <span style="color: #666666; font-style: italic;">% Select messages that are greater than or equal to the requested ID</span>
                <span style="color: #186895;">case</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">filter</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span>#<span style="color: #d400ed;">message</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #45b3e6;">ID</span> <span style="color: #014ea4;">&gt;=</span> <span style="color: #45b3e6;">MsgID</span> <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Msgs</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
                    <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">true</span><span style="color: #6bb810;">;</span> <span style="color: #666666; font-style: italic;">% no messages were found for this listener, keep it in the list</span>
                    <span style="color: #45b3e6;">M</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">!</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">map</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span>#<span style="color: #d400ed;">message</span><span style="color: #109ab8;">&#123;</span>data<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Data</span><span style="color: #6bb810;">,</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">MID</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">MID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Data</span><span style="color: #109ab8;">&#125;</span> <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">M</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> false <span style="color: #666666; font-style: italic;">% remove it</span>
                <span style="color: #186895;">end</span>
        <span style="color: #186895;">end</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Listeners</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>listeners<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">NewListeners</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Okay, that does it for our mailbox, now let&#8217;s work on the post office, which will communicate with our mailbox.</p>
<h2>Creating the Post Office</h2>
<p>Now it&#8217;s time to implement the post office. Without really focusing on the chat room aspects now, the post office should work somewhat like it does in real life. Ours will do the following:</p>
<ul>
<li>Create/Delete mailboxes.</li>
<li>Send message to a mailbox by a unique ID (aka address).</li>
<li>Send message to all mailboxes (junk mail, broadcast).</li>
</ul>
<p>Our chat_postoffice module uses the gen_server behavior so a lot of the code in the module is related to that. First let&#8217;s define the state of our postoffice server. It is very simple and just contains a list of mailboxes.</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>
mailboxes<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span>
<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Each item in the <em>mailboxes</em> list will be a tuple:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Id</span><span style="color: #6bb810;">,</span><span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span></pre></div></div>

<p>Where Id is the mailbox ID, and Pid is the process ID for the mailbox. You can see in our <em>init</em> function that our server starts with no mailboxes(empty list).</p>
<p>Our create_mailbox function is defined below. First we check to see if the mailbox already exists, if not, we add it to our list and spawn off a mailbox process (we will go into the chat_mailbox module in a little bit).</p>
<h4>create_mailbox</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_call</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>create_mailbox<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_From</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>mailboxes<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">MBoxes</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_mailbox</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">ID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> already_exists<span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> notfound<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">spawn_link</span><span style="color: #109ab8;">&#40;</span>chat_mailbox<span style="color: #6bb810;">,</span> start<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #45b3e6;">NewBox</span> <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">ID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span>
            <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>mailboxes<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">NewBox</span> | <span style="color: #45b3e6;">MBoxes</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>And here is our method for deleting a mailbox. It removes the mailbox from the list and sends a message to the mailbox process to quit.</p>
<h4>delete_mailbox</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>delete_mailbox<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>mailboxes<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">MBoxes</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">NewBoxes</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">filter</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Id</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
        <span style="color: #186895;">case</span> <span style="color: #45b3e6;">Id</span> <span style="color: #014ea4;">/=</span> <span style="color: #45b3e6;">ID</span> <span style="color: #186895;">of</span>
            false <span style="color: #6bb810;">-&gt;</span> 
                <span style="color: #666666; font-style: italic;">% tell the mailbox process to quit</span>
                <span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">!</span> quit<span style="color: #6bb810;">,</span> false<span style="color: #6bb810;">;</span>
            <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">true</span>
        <span style="color: #186895;">end</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">MBoxes</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>mailboxes<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">NewBoxes</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>Now we want to create methods for sending and broadcasting mail.</p>
<p>To send mail, we look up the mailbox ID, and send the process a message. Note: Delivery is not guaranteed, if the mailbox process dies then it will never receive the message. In another post we will make it more fault tolerant, but for now, I wouldn&#8217;t worry about the mailbox process dying.</p>
<h4>send_mail</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>send_mail<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">ID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Msg</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_mailbox</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">ID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">_Id</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">!</span> <span style="color: #109ab8;">&#123;</span>mail<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Msg</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">ok</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>And finally, let&#8217;s make our broadcast function. It takes a message and a list of ID&#8217;s not to send to.</p>
<h4>broadcast_mail</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>broadcast_mail<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Msg</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Except</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>mailboxes<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">MBoxes</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">when</span> <span style="color: #ff3c00;">is_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Except</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">!</span> <span style="color: #109ab8;">&#123;</span>mail<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Msg</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">||</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Id</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">&lt;-</span> <span style="color: #45b3e6;">MBoxes</span><span style="color: #6bb810;">,</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">member</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Id</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Except</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">==</span> false<span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span></pre></div></div>

<h3>chat_room server</h3>
<p>This server contains the core logic of our chat room. This includes maintaining all connected users, and functions to allow a user to join or leave the chat room, get list of online users, and send/receive messages(and events).</p>
<p>The state of the chat_room server is defined below. At the most basic level, it is just going to contain a list of all the users in the chat room. The client state is also defined below.</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>
clients<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span>
<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">record</span><span style="color: #109ab8;">&#40;</span><span style="color: #d400ed;">client_state</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>
id<span style="color: #6bb810;">,</span> nick<span style="color: #6bb810;">,</span> host<span style="color: #6bb810;">,</span>last_action
<span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>The chat_room server will have the following functions:</p>
<ul>
<li>join</li>
<li>leave</li>
<li>wait/wait_finish</li>
<li>chat_message</li>
<li>get_users</li>
<li>get_msg_id</li>
<li>find_idle_clients</li>
</ul>
<p>Let&#8217;s start by writing the join function. This will first check to make sure that a nickname is valid(alphanumeric, no longer than 16 characters) and available. If everything is okay, we will create a mailbox for the user, notify all other users that a user has joined, and return a unique session to the caller. If an error occurs, it is returned to the caller as well.</p>
<h4>join</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_call</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>join<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Host</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_From</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>clients<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Clients</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">when</span> <span style="color: #ff3c00;">is_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Nick</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">validate_nick</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ValidNick</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">Session</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">get_unique_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #186895;">case</span> chat_postoffice:<span style="color: #ff3c00;">create_mailbox</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Session</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
                ok <span style="color: #6bb810;">-&gt;</span> 
                    <span style="color: #006600;">chat_postoffice</span>:<span style="color: #ff3c00;">broadcast_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>user_joined_room<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ValidNick</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Session</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                    <span style="color: #45b3e6;">Client</span> <span style="color: #014ea4;">=</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Session</span><span style="color: #6bb810;">,</span>nick<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">ValidNick</span><span style="color: #6bb810;">,</span>host<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Host</span><span style="color: #6bb810;">,</span>last_action<span style="color: #014ea4;">=</span><span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span>
                    <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Session</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>clients<span style="color: #014ea4;">=</span><span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Client</span> | <span style="color: #45b3e6;">Clients</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
                <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_available<span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span>
            <span style="color: #186895;">end</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>The leave function is used to log out of the chat room. It will remove the user, and notify the others that that user has left. In the next part, we will implement a timeout so that if a user hasn&#8217;t done anything in a specified time, he will be removed.</p>
<h4>leave</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>leave<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>clients<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Clients</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">when</span> <span style="color: #ff3c00;">is_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Client</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #006600;">chat_postoffice</span>:<span style="color: #ff3c00;">delete_mailbox</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Client</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #6bb810;">.</span>id<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #45b3e6;">CleanReason</span> <span style="color: #014ea4;">=</span>  chat_util:<span style="color: #ff3c00;">unicode_clean</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">sublist</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Reason</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">32</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            chat_postoffice:<span style="color: #ff3c00;">broadcast_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>user_left_room<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Client</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #6bb810;">.</span>nick<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">CleanReason</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Client</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #6bb810;">.</span>id<span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #45b3e6;">OtherClients</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">filter</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span>#<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #45b3e6;">ID</span> <span style="color: #014ea4;">/=</span> <span style="color: #45b3e6;">Client</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">client_state</span><span style="color: #6bb810;">.</span>id <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Clients</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #109ab8;">&#123;</span>clients<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">OtherClients</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>Chat message will broadcast a message to the chat room.</p>
<h4>chat_message</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>chat_message<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Msg</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">when</span> <span style="color: #ff3c00;">is_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Msg</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> #<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>nick<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span>id<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">C</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">CleanMsg</span> <span style="color: #014ea4;">=</span> chat_util:<span style="color: #ff3c00;">unicode_clean</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">sublist</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Msg</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">256</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            chat_postoffice:<span style="color: #ff3c00;">broadcast_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>chat_msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">CleanMsg</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">ID</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            chat_postoffice:<span style="color: #ff3c00;">send_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">ID</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>sent_chat_msg<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Nick</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">CleanMsg</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #45b3e6;">NewState</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#125;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>Finally, we have ,wait, wait_finish, and get_users.</p>
<p>The <em>wait</em> function will add a listener to the user&#8217;s mailbox.</p>
<h4>wait</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>wait<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">MsgID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">when</span> <span style="color: #ff3c00;">is_integer</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">MsgID</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">!</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> bad_session<span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">C</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">NewState</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> 
            chat_postoffice:<span style="color: #ff3c00;">send_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>add_listener<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">MsgID</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#125;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>wait_finish removes the listener from a mailbox.</p>
<h4>wait_finish</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_cast</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>wait_finish<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #006600;">chat_postoffice</span>:<span style="color: #ff3c00;">send_mail</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>remove_listener<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>noreply<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>The get_users function just returns a list with the nickname of every user.</p>
<h4>get_users</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_call</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span>get_users<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Sess</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_From</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #ff3c00;">get_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_found<span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
        <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">C</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> 
            <span style="color: #45b3e6;">NewState</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">update_client</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">C</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #109ab8;">&#123;</span>reply<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">map</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span>#<span style="color: #d400ed;">client_state</span><span style="color: #109ab8;">&#123;</span>nick<span style="color: #014ea4;">=</span><span style="color: #45b3e6;">Nick</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #45b3e6;">Nick</span> <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">State</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">state</span><span style="color: #6bb810;">.</span>clients<span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewState</span><span style="color: #109ab8;">&#125;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>That does it for the chat_room server. If you look through the code you will also see a find_idle_clients function, which runs on a timer to see if any clients have left the browser and timed out. </p>
<h2>Finally, the web front-end</h2>
<p>There are two pages that the end user will see. The login page, where they can choose a nickname, and the chat page. There are two templates that we will be using, called <em>index.html</em>, the login page, and <em>chat.html</em>, the chat screen. The rest of the interaction between the web browser and the server will take place with AJAX.</p>
<p>First, let&#8217;s make it so a user can join the chat room. Take a look at the chat_web module and you will see a section called Request Handlers. These are functions that are called when a request comes in. We can look at the path to decide what to do.</p>
<p>At the bottom of our request handlers, we have one that will just try to serve a file from our docroot directory. This is where we will store our javascript and any other static files.</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_request</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Path</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">serve_file</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">string</span>:<span style="color: #ff3c00;">sub_string</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Path</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">2</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;docroot&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Also, I&#8217;ve included some helper functions in chat_util for loading templates with ErlyDTL. You can use the Django template language in your templates, and then render them with any variables you want. We don&#8217;t use this that much.</p>
<h3>Login</h3>
<p>Our login page, which is at the path <em>/</em>, is rendered like so:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_request</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/&quot;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">html_ok</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> chat_util:<span style="color: #ff3c00;">get_template</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;index&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>You can take a look at the template, it basically does a simple HTTP post to the path, /login/.</p>
<p>Our login handler just calls chat_room:join to attempt to join the chat room. If an error occurs, it is passed into the login template and returned to the user. If all is good, we set a cookie with the user&#8217;s chat session ID.</p>
<h4>login</h4>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_request</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/login/&quot;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">Post</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">parse_post</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #186895;">case</span> chat_room:<span style="color: #ff3c00;">join</span><span style="color: #109ab8;">&#40;</span>chat_util:<span style="color: #ff3c00;">get_parameter</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;nick&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Post</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">get</span><span style="color: #109ab8;">&#40;</span>peer<span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
	    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">SessID</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> 
	        <span style="color: #45b3e6;">SessCookie</span> <span style="color: #014ea4;">=</span> mochiweb_cookies:<span style="color: #ff3c00;">cookie</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;chat_sess&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">SessID</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span>path<span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/&quot;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	        <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">respond</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span><span style="color: #ff9600;">302</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">SessCookie</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;Location&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/chat/&quot;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #ee3800;">&lt;&lt;&gt;&gt;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
		<span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> not_available<span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">html_ok</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> chat_util:<span style="color: #ff3c00;">get_template</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;index&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;The nickname is not available.&quot;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
	    <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">html_ok</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> chat_util:<span style="color: #ff3c00;">get_template</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;index&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;The nickname must be alphanumeric and not blank.&quot;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span>
	<span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<h3>The main chat interface</h3>
<p>Once the user is redirected to the /chat/ path and has a session cookie set, the AJAX will take over. I don&#8217;t want to go too much into the javascript, but it mainly does the following: </p>
<ul>
<li>Get&#8217;s the current message ID and validates the session.</li>
<li>Get&#8217;s the list of online users.</li>
<li>Waits for any messages to come in from the server.</li>
</ul>
<p>Start client is called to get the message ID. If successful, it gets the online users.</p>
<h4>startClient</h4>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> startClient<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	addSystemMsg<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Establishing connection to chat service...&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">new</span> Ajax.<span style="color: #660066;">Request</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/chat/start/'</span><span style="color: #339933;">,</span>
	  <span style="color: #009900;">&#123;</span>
	    method<span style="color: #339933;">:</span><span style="color: #3366CC;">'get'</span><span style="color: #339933;">,</span>
	    onSuccess<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>transport<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #003366; font-weight: bold;">var</span> response <span style="color: #339933;">=</span> transport.<span style="color: #660066;">responseText</span>.<span style="color: #660066;">evalJSON</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>response.<span style="color: #000066;">status</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;ok&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				msgID <span style="color: #339933;">=</span> response.<span style="color: #660066;">response</span><span style="color: #339933;">;</span>
				addSystemMsg<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Connected to chat service.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				getOnlineUsers<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
			<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>response.<span style="color: #000066;">status</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;error&quot;</span> <span style="color: #339933;">&amp;&amp;</span> response.<span style="color: #660066;">response</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;bad_session&quot;</span><span style="color: #009900;">&#41;</span> addSystemMsg<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Unable to locate your session. Please &lt;a href=<span style="color: #000099; font-weight: bold;">\&quot;</span>/<span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;login&lt;/a&gt; again.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	    onFailure<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> addSystemMsg<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;The chat service is not responding at this time.&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span>
	  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>After the message ID  and the online users are retrieved, the client enters the message loop. After a message is received, it is processed by <em>handleServiceMsg</em>, which basically looks at the JSON object and decides what to do(user joined, chat message, etc,.).</p>
<h4>getServiceMsg</h4>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> getServiceMsg<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">new</span> Ajax.<span style="color: #660066;">Request</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/chat/wait/?msg_id='</span> <span style="color: #339933;">+</span> msgID<span style="color: #339933;">,</span>
	  <span style="color: #009900;">&#123;</span>
	    method<span style="color: #339933;">:</span><span style="color: #3366CC;">'get'</span><span style="color: #339933;">,</span>
	    onSuccess<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>transport<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	        <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>transport.<span style="color: #660066;">responseText</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	            setTimeout<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'getServiceMsg();'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">10000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	        <span style="color: #009900;">&#125;</span>
	        <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
	            addSystemMsg<span style="color: #009900;">&#40;</span>transport.<span style="color: #660066;">responseText</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	            <span style="color: #003366; font-weight: bold;">var</span> response <span style="color: #339933;">=</span> transport.<span style="color: #660066;">responseText</span>.<span style="color: #660066;">evalJSON</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	            <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>handleServiceMsg<span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		  	        getServiceMsg<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		        <span style="color: #009900;">&#125;</span>
	        <span style="color: #009900;">&#125;</span>
	    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
	    onFailure<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> 
	        setTimeout<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'getServiceMsg();'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">10000</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span>
	  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>getServiceMsg talks to the following handler, which just adds a listener for our session, and waits for a message.</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_request</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/chat/wait/&quot;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">MsgID</span> <span style="color: #014ea4;">=</span> chat_util:<span style="color: #ff3c00;">get_parameter_int</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;msg_id&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">parse_qs</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    chat_room:<span style="color: #ff3c00;">wait</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">get_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">MsgID</span><span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">self</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">timer</span>:<span style="color: #ff3c00;">apply_after</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">COMET_TIMEOUT</span><span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> timeout_wait<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #ff3c00;">self</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">proc_lib</span>:<span style="color: #ff3c00;">hibernate</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #6bb810;">,</span> wait<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Req</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>If there are no messages after a certain time(?COMET_TIMEOUT), a timeout message is sent and the client is told to reconnect.</p>
<p>When the user wants to send a message, an AJAX post is performed to the path /chat/send_msg/. The following is the handler for sending a chat message. It&#8217;s pretty simple. </p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_request</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/chat/send_msg/&quot;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #006600;">chat_room</span>:<span style="color: #ff3c00;">chat_message</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">get_session</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> chat_util:<span style="color: #ff3c00;">get_parameter</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;msg&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">parse_post</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff3c00;">json_respond</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">json_client_ok</span><span style="color: #109ab8;">&#40;</span><span style="color: #ee3800;">&lt;&lt;</span><span style="color: #ff7800;">&quot;&quot;</span><span style="color: #ee3800;">&gt;&gt;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Req</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span></pre></div></div>

<h2>Conclusion</h2>
<p>Well, that&#8217;s it for now. You can download the <a href="http://tech9computers.com/erl_chat-0.1.tar.gz">source</a> and try it out yourself. The server runs on port 8000. (http://localhost:8000).</p>
<p>In the next part, I will discuss some more advanced features, such as rate limiting, limiting connections for a host, admin control, more fault tolerance(using ETS/DETS) for storing messages, and more. While you are waiting, come chat: <a href="http://chat.tech9computers.com">chat.tech9computers.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/09/29/building-an-erlang-chat-server-with-comet-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
