<?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&#039;s blog &#187; mochiweb</title>
	<atom:link href="http://chrismoos.com/tag/mochiweb/feed/" rel="self" type="application/rss+xml" />
	<link>http://chrismoos.com</link>
	<description>developer by day, developer by night</description>
	<lastBuildDate>Fri, 30 Jul 2010 04:52:47 +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>Building an Erlang chat server with Comet – Part&#160;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&#160;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>
		<item>
		<title>Building an Erlang chat server with Comet &#8211; Part&#160;1</title>
		<link>http://chrismoos.com/2009/09/28/building-an-erlang-chat-server-with-comet-part-1/</link>
		<comments>http://chrismoos.com/2009/09/28/building-an-erlang-chat-server-with-comet-part-1/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 04:10:32 +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=466</guid>
		<description><![CDATA[Introduction
Comet is a technique to stream data, or &#8220;push&#8221; events to the web browser, instead of making the client poll the server every few seconds. This lets the client receive near real-time updates. If you want to read more about Comet, check out the article on Wikipedia, more specifically, the section about Ajax with long [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Comet is a technique to stream data, or &#8220;push&#8221; events to the web browser, instead of making the client poll the server every few seconds. This lets the client receive near real-time updates. If you want to read more about Comet, check out <a href="http://en.wikipedia.org/wiki/Comet_%28programming%29">the article</a> on Wikipedia, more specifically, the section about <em>Ajax with long polling</em>, as this is what our server will implement.</p>
<p>I chose web based chat because it is a great &#8220;hello world&#8221; for learning how Comet works, and I really enjoy programming chat related stuff (see my <a href="http://gameranger.sourceforge.net">very old implementation of GameRanger</a>) </p>
<h3>Chat Architecture</h3>
<p>Before we get into any code, we have to talk about how the overall chat system works. Here are a few specifications.</p>
<ul>
<li>Erlang is going to handle all server-side tasks.</li>
<li>Mochiweb will be used to serve the browsers.</li>
<li>There will be only one (global) chat room.</li>
<li>When a user sends a message, all others in the room will see it.</li>
</ul>
<p>Okay, that should do it for now. That is the very basic outline of what the chat system needs to do. Now let&#8217;s talk about the server.</p>
<h3>Server Overview</h3>
<p>The server will use Erlang&#8217;s OTP feature to make sure that all of our services remain running and are monitored.</p>
<p>We are going to have the following logical services managed by OTP:</p>
<ul>
<li>chat_room</li>
<li>chat_postoffice</li>
<li>chat_web</li>
</ul>
<p>The other modules are: </p>
<ul>
<li>chat_mailbox &#8211; handles mailbox processing</li>
<li>chat_util &#8211; helper functions for the application</li>
<li>chat_sup &#8211; supervisor</li>
<li>chat_server &#8211; the chat_server application </li>
</ul>
<h4>chat_room</h4>
<p>This module will be used to maintain the state of our chat room, and allow us to implement any &#8220;chat_room&#8221; logic, such as join/leave, sending messages, etc,.</p>
<h4>chat_postoffice</h4>
<p>This module is very important, it will hold all the mailboxes for each user in the chat room. Whenever we want to notify a user of something, we will send a message to the &#8220;post office&#8221;. The post office will then relay the message to an individual user&#8217;s mailbox. After the message has arrived in a user&#8217;s mailbox, the mailbox may notify our web server, and the web server can notify the client&#8217;s web browser. (I know, that&#8217;s a lot handle, but don&#8217;t worry, it will be explained).</p>
<h4>chat_web</h4>
<p>Finally, the chat_web module is what the web browsers will be talking to, this is the front-end of the chat system. The web module will handle the basic tasks, such as joining the chat room, sending messages, and of course, receiving messages.</p>
<h3>Implementing chat_mailbox</h3>
<p>In <a href="http://chrismoos.com/2009/09/29/building-an-erlang-chat-server-with-comet-part-2/">Part 2</a>, we will implement the chat_mailbox module for our chat server. (Source code will be included).</p>
]]></content:encoded>
			<wfw:commentRss>http://chrismoos.com/2009/09/28/building-an-erlang-chat-server-with-comet-part-1/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
