1
0
mirror of https://github.com/ubf/ubf.git synced 2026-04-17 10:16:06 +00:00
Files
ubf/ubf-tutorial.en.html
Joseph Wayne Norton 1c92aefe4c UBF 2.2 web assets
2014-05-12 11:03:08 +09:00

1448 lines
49 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="generator" content="AsciiDoc 8.6.9, bootstrap-docs backend">
<title>Erlang Users Conference 2010 Tutorial / UBF Basics and Hands On</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Erlang Users Conference 2010 Tutorial / UBF Basics and Hands On">
<meta name="author" content="Joseph Wayne Norton">
<link href="./bootstrap/docs/assets/css/bootstrap.css" rel="stylesheet">
<link href="./bootstrap/docs/assets/css/bootstrap-responsive.css" rel="stylesheet">
<link href="./bootstrap/docs/assets/css/docs.css" rel="stylesheet">
<link href="./bootstrap/docs/assets/js/google-code-prettify/prettify.css" rel="stylesheet">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link rel="shortcut icon" href="./bootstrap/docs/assets/ico/favicon.ico">
</head>
<body data-spy="scroll" data-target=".bs-docs-sidebar">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="brand" href="http://ubf.github.com/ubf/">UBF</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active">
<a href="#">Home</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<header class="jumbotron subhead" id="overview">
<div class="container">
<h1>Universal Binary Format</h1>
<p class="lead">Erlang Users Conference 2010 Tutorial / UBF Basics and Hands On</p>
</div>
</header>
<div class="container">
<div class="row">
<div id="sidebar" class="span3 bs-docs-sidebar">
<ul id="toc" class="nav nav-list bs-docs-sidenav">
</ul>
</div>
<div id="content" class="span9">
<section id="ubf_basics">
<div class="page-header">
<h1>UBF Basics</h1>
</div>
<p>UBF is a language for transporting and describing complex data
structures across a network. It has three components:</p>
<ul>
<li>
UBF(a) is a "language neutral" data transport format, roughly
equivalent to well-formed XML.
</li>
<li>
UBF(b) is a programming language for describing types in UBF(a) and
protocols between clients and servers. This layer is typically
called the "protocol contract". UBF(b) is roughly equivalent to
Verified XML, XML-schemas, SOAP and WDSL.
</li>
<li>
UBF(c) is a meta-level protocol used between a UBF client and a UBF
server.
</li>
</ul>
<div class="imageblock">
<div class="content">
<img src="images/ubf-flow-01.png" alt="Programming By Contract">
</div>
<div class="title">Figure 1. Programming By Contract</div>
</div>
</section>
<section id="specifications_ubf_a">
<div class="page-header">
<h1>Specifications: UBF(a)</h1>
</div>
<dl class="dl-horizontal">
<dt>
Integer
</dt>
<dd>
[-][0-9]+
</dd>
<dt>
String
</dt>
<dd>
"&#8230;"
</dd>
<dt>
Binary
</dt>
<dd>
[0-9]+ ~&#8230;~
</dd>
<dt>
Atom
</dt>
<dd>
'&#8230;'
</dd>
<dt>
Tuple
</dt>
<dd>
{ Obj1 Obj2 &#8230; ObjN-1 ObjN }
</dd>
<dt>
List
</dt>
<dd>
# ObjN &amp; ObjN-1 &amp; &#8230; &amp; Obj2 &amp; Obj1
</dd>
<dt>
Term
</dt>
<dd>
represent primitive types and compound types
</dd>
<dt>
White space
</dt>
<dd>
\s \n \r \t , %&#8230;%
</dd>
<dt>
Register
</dt>
<dd>
&gt;C C
</dd>
<dt>
Object
</dt>
<dd>
Term or Register Push or Register Pop
</dd>
</dl>
<p><span class="label label-note">Note</span> The operator <em>$</em> (i.e. "end of object") signifies when objects
are finished.</p>
</section>
<section id="specifications_ubf_a_example">
<div class="page-header">
<h1>Specifications: UBF(a) Example</h1>
</div>
<p>For example, the following UBF(a) object:</p>
<pre class="prettyprint">'person'&gt;p # {p "Joe" 123} &amp; {p 'fred' 3~abc~} &amp; $</pre>
<p>Represents the following UBF(b) term, a list that contains two
3-tuples:</p>
<pre class="prettyprint">[{'person', 'fred', &lt;&lt;"abc"&gt;&gt;}, {'person', "Joe", 123}].</pre>
</section>
<section id="specifications_ubf_b">
<div class="page-header">
<h1>Specifications: UBF(b)</h1>
</div>
<p>UBF(b) is a language independent type system and protocol description
language to specify a "contract".</p>
<p>All data sent by both the client and the server is verified by the
"Contract Manager" (an Erlang process on the "server" side of the
protocol). Any data that violates the contract is rejected.</p>
<p>A contract is defined by 2 mandatory sections and 3 optional sections.</p>
<dl class="dl-horizontal">
<dt>
Name
</dt>
<dd>
+NAME("&#8230;"). <small>mandatory</small>
</dd>
<dt>
Version
</dt>
<dd>
+VSN("&#8230;"). <small>mandatory</small>
</dd>
<dt>
Types
</dt>
<dd>
+TYPES.
</dd>
<dt>
State
</dt>
<dd>
+STATE.
<ul>
<li>
Defines a finite state machine (FSM) to model the interaction
between the client and server.
</li>
<li>
Symbolic names expressed as "atoms" are the states of the FSM.
</li>
<li>
Transitions expressed as request, response, and next state
triplets are the edges of the FSM (a.k.a. synchronous calls).
</li>
<li>
States may also be annotated with events (a.k.a. asynchronous
casts).
</li>
</ul>
</dd>
<dt>
Anystate
</dt>
<dd>
+ANYSTATE.
<ul>
<li>
Defines request and response pairs and define events that are
valid in <small>all</small> states of the FSM.
</li>
</ul>
</dd>
</dl>
</section>
<section id="specifications_ubf_a_types">
<div class="page-header">
<h1>Specifications: UBF(a) Types</h1>
</div>
<dl class="dl-horizontal">
<dt>
Definition
</dt>
<dd>
X() = T
</dd>
<dt>
Integer
</dt>
<dd>
[-][0-9]+ <small>or</small> [0-9]+#[0-9a-f]+
</dd>
<dt>
Range
</dt>
<dd>
[-][0-9]+..[-][0-9]+ <small>or</small> [-][0-9]+.. <small>or</small> ..[-][0-9]+
</dd>
<dt>
Float
</dt>
<dd>
[-][0-9]+.[0-9]+
</dd>
<dt>
Binary
</dt>
<dd>
&lt;&lt;"&#8230;"&gt;&gt;
</dd>
<dt>
String
</dt>
<dd>
"&#8230;"
</dd>
<dt>
Atom
</dt>
<dd>
'&#8230;' <small>or</small> [a-z][a-zA-Z0-9_]*
</dd>
<dt>
Reference
</dt>
<dd>
R()
</dd>
<dt>
Alternative
</dt>
<dd>
T1 | T2
</dd>
<dt>
Tuple
</dt>
<dd>
{T1, T2, &#8230;, Tn}
</dd>
<dt>
Record
</dt>
<dd>
name#T1, y=T2, &#8230;, z=Tn
</dd>
<dt>
Extended Record
</dt>
<dd>
name##T1, y=T2, &#8230;, z=Tn
</dd>
<dt>
List
</dt>
<dd>
[T]
</dd>
<dt>
Predefined
</dt>
<dd>
P() <small>or</small> P(A1, A2, &#8230;, An)
</dd>
</dl>
</section>
<section id="specifications_ubf_a_predefined_types">
<div class="page-header">
<h1>Specifications: UBF(a) Predefined Types</h1>
</div>
<table>
<colgroup>
</colgroup>
<tbody>
<tr>
<td>Type</td>
<td>ascii</td>
<td>asciiprintable</td>
<td>nonempty</td>
<td>nonundefined</td>
</tr>
<tr>
<td>integer</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>float</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>binary</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>X</td>
</tr>
<tr>
<td>string</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>X</td>
</tr>
<tr>
<td>atom</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<td>tuple</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>X</td>
</tr>
<tr>
<td>list</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>X</td>
</tr>
<tr>
<td>proplist</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>X</td>
</tr>
<tr>
<td>term</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<td>none</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
</tbody>
</table>
<p><span class="label label-note">Note</span> <em>nonempty</em> does not match: &lt;&lt;""&gt;&gt;, "", '', {}, and [].
<em>nonundefined</em> does not match: 'undefined'.</p>
</section>
<section id="specifications_ubf_b_example">
<div class="page-header">
<h1>Specifications: UBF(b) Example</h1>
</div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.7
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #990000">+</span><span style="color: #009900">NAME</span>(<span style="color: #FF0000">"irc"</span>)<span style="color: #990000">.</span>
<span style="color: #990000">+</span><span style="color: #009900">VSN</span>(<span style="color: #FF0000">"ubf2.0"</span>)<span style="color: #990000">.</span>
<span style="color: #990000">+</span><span style="color: #009900">TYPES</span>
<span style="font-weight: bold"><span style="color: #000000">info</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">info</span>;
<span style="font-weight: bold"><span style="color: #000000">description</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">description</span>;
<span style="font-weight: bold"><span style="color: #000000">contract</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">contract</span>;
<span style="font-weight: bold"><span style="color: #000000">ok</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">ok</span>;
<span style="font-weight: bold"><span style="color: #000000">bool</span></span>() <span style="color: #990000">::</span> <span style="color: #000080">true</span> | <span style="color: #000080">false</span>;
<span style="font-weight: bold"><span style="color: #000000">nick</span></span>() <span style="color: #990000">::</span> <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>();
<span style="font-weight: bold"><span style="color: #000000">oldnick</span></span>() <span style="color: #990000">::</span> <span style="font-weight: bold"><span style="color: #000000">nick</span></span>();
<span style="font-weight: bold"><span style="color: #000000">newnick</span></span>() <span style="color: #990000">::</span> <span style="font-weight: bold"><span style="color: #000000">nick</span></span>();
<span style="font-weight: bold"><span style="color: #000000">group</span></span>() <span style="color: #990000">::</span> <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>();
<span style="font-weight: bold"><span style="color: #000000">groups</span></span>() <span style="color: #990000">::</span> [<span style="font-weight: bold"><span style="color: #000000">group</span></span>()];
<span style="font-weight: bold"><span style="color: #000000">logon</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">logon</span>;
<span style="font-weight: bold"><span style="color: #000000">proceed</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">ok</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">listGroups</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">groups</span>;
<span style="font-weight: bold"><span style="color: #000000">joinGroup</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">join</span>, <span style="font-weight: bold"><span style="color: #000000">group</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">leaveGroup</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">leave</span>, <span style="font-weight: bold"><span style="color: #000000">group</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">changeNick</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">nick</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">msg</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">msg</span>, <span style="font-weight: bold"><span style="color: #000000">group</span></span>(), <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">msgEvent</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">msg</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">group</span></span>(), <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">joinEvent</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">joins</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">group</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">leaveEvent</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">leaves</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">group</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">changeNameEvent</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">changesName</span>, <span style="font-weight: bold"><span style="color: #000000">oldnick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">newnick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">group</span></span>()}<span style="color: #990000">.</span>
<span style="color: #990000">+</span><span style="color: #009900">STATE</span> <span style="color: #FF6600">start</span>
<span style="font-weight: bold"><span style="color: #000000">logon</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">proceed</span></span>() &amp; <span style="color: #FF6600">active</span><span style="color: #990000">.</span> <span style="font-style: italic"><span style="color: #9A1900">%% Nick randomly assigned</span></span>
<span style="color: #990000">+</span><span style="color: #009900">STATE</span> <span style="color: #FF6600">active</span>
<span style="font-weight: bold"><span style="color: #000000">listGroups</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">groups</span></span>() &amp; <span style="color: #FF6600">active</span>;
<span style="font-weight: bold"><span style="color: #000000">joinGroup</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">ok</span></span>() &amp; <span style="color: #FF6600">active</span>;
<span style="font-weight: bold"><span style="color: #000000">leaveGroup</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">ok</span></span>() &amp; <span style="color: #FF6600">active</span>;
<span style="font-weight: bold"><span style="color: #000000">changeNick</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">bool</span></span>() &amp; <span style="color: #FF6600">active</span>;
<span style="font-weight: bold"><span style="color: #000000">msg</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">bool</span></span>() &amp; <span style="color: #FF6600">active</span>; <span style="font-style: italic"><span style="color: #9A1900">%% False if you have not joined a group</span></span>
<span style="color: #009900">EVENT</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">msgEvent</span></span>(); <span style="font-style: italic"><span style="color: #9A1900">%% Group sends me a message</span></span>
<span style="color: #009900">EVENT</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">joinEvent</span></span>(); <span style="font-style: italic"><span style="color: #9A1900">%% Nick joins group</span></span>
<span style="color: #009900">EVENT</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">leaveEvent</span></span>(); <span style="font-style: italic"><span style="color: #9A1900">%% Nick leaves group</span></span>
<span style="color: #009900">EVENT</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">changeNameEvent</span></span>()<span style="color: #990000">.</span> <span style="font-style: italic"><span style="color: #9A1900">%% Nick changes name</span></span>
<span style="color: #990000">+</span><span style="color: #009900">ANYSTATE</span>
<span style="font-weight: bold"><span style="color: #000000">info</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>();
<span style="font-weight: bold"><span style="color: #000000">description</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>();
<span style="font-weight: bold"><span style="color: #000000">contract</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">term</span></span>()<span style="color: #990000">.</span>
</tt></pre></div></div>
</section>
<section id="specifications_ubf_c">
<div class="page-header">
<h1>Specifications: UBF(c)</h1>
</div>
<p>UBF(c) is a meta-level protocol used between a UBF client and a UBF
server.</p>
<p>UBF(c) has two primitives: synchronous "calls" and asynchronous
"casts".</p>
<dl class="dl-horizontal">
<dt>
Calls
</dt>
<dd>
Request $ &#8658; {Response, NextState} $
<ul>
<li>
"Request" is an UBF(a) type sent by the client
</li>
<li>
"Response" is an UBF(a) type and "NextState" is an UBF(a) atom
sent by the server
</li>
</ul>
</dd>
<dt>
Casts
</dt>
<dd>
{'event_in', Event} $
<ul>
<li>
"Event" is an UBF(a) type sent by the client
</li>
</ul>
</dd>
<dt>
Casts
</dt>
<dd>
{'event_out', Event} $
<ul>
<li>
"Event" is an UBF(a) type sent by the server
</li>
</ul>
</dd>
</dl>
</section>
<section id="specifications_ubf_c_errors">
<div class="page-header">
<h1>Specifications: UBF(c) errors</h1>
</div>
<dl>
<dt>
Calls - Request
</dt>
<dd>
If clients sends an invalid request, server responds with "client
broke contract":
<pre class="prettyprint">{{'clientBrokeContract', Request, ExpectsIn}, State} $</pre>
</dd>
<dt>
Calls - Responses
</dt>
<dd>
If server sends an invalid response, server responds with "server
broke contract":
<pre class="prettyprint">{{'serverBrokeContract', Response, ExpectsOut}, State} $</pre>
</dd>
<dt>
Casts
</dt>
<dd>
If client or server send an invalid event, the event is ignored and
dropped by the server.
</dd>
</dl>
</section>
<section id="contracts_and_plugins">
<div class="page-header">
<h1>Contracts and Plugins</h1>
</div>
<p>"Contracts" and "Plugins" are the basic building blocks of an Erlang
UBF server.
- Contracts are a server&#8217;s specifications.
- Plugins are a server&#8217;s implementations.</p>
<p>A contract is a UBF(b) specification stored to a file. By convention,
a contract&#8217;s filename has ".con" as the suffix part.</p>
</section>
<section id="contracts_types_only">
<div class="page-header">
<h1>Contracts: +TYPES only</h1>
</div>
<p>For example, a "+TYPES" only contract having the filename
"irc_types_plugin.con" is as follows:</p>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.7
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #990000">+</span><span style="color: #009900">NAME</span>(<span style="color: #FF0000">"irc_types"</span>)<span style="color: #990000">.</span>
<span style="color: #990000">+</span><span style="color: #009900">VSN</span>(<span style="color: #FF0000">"ubf2.0"</span>)<span style="color: #990000">.</span>
<span style="color: #990000">+</span><span style="color: #009900">TYPES</span>
<span style="font-weight: bold"><span style="color: #000000">info</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">info</span>;
<span style="font-weight: bold"><span style="color: #000000">description</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">description</span>;
<span style="font-weight: bold"><span style="color: #000000">contract</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">contract</span>;
<span style="font-weight: bold"><span style="color: #000000">ok</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">ok</span>;
<span style="font-weight: bold"><span style="color: #000000">bool</span></span>() <span style="color: #990000">::</span> <span style="color: #000080">true</span> | <span style="color: #000080">false</span>;
<span style="font-weight: bold"><span style="color: #000000">nick</span></span>() <span style="color: #990000">::</span> <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>();
<span style="font-weight: bold"><span style="color: #000000">oldnick</span></span>() <span style="color: #990000">::</span> <span style="font-weight: bold"><span style="color: #000000">nick</span></span>();
<span style="font-weight: bold"><span style="color: #000000">newnick</span></span>() <span style="color: #990000">::</span> <span style="font-weight: bold"><span style="color: #000000">nick</span></span>();
<span style="font-weight: bold"><span style="color: #000000">group</span></span>() <span style="color: #990000">::</span> <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>();
<span style="font-weight: bold"><span style="color: #000000">groups</span></span>() <span style="color: #990000">::</span> [<span style="font-weight: bold"><span style="color: #000000">group</span></span>()];
<span style="font-weight: bold"><span style="color: #000000">logon</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">logon</span>;
<span style="font-weight: bold"><span style="color: #000000">proceed</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">ok</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">listGroups</span></span>() <span style="color: #990000">::</span> <span style="color: #FF6600">groups</span>;
<span style="font-weight: bold"><span style="color: #000000">joinGroup</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">join</span>, <span style="font-weight: bold"><span style="color: #000000">group</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">leaveGroup</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">leave</span>, <span style="font-weight: bold"><span style="color: #000000">group</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">changeNick</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">nick</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">msg</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">msg</span>, <span style="font-weight: bold"><span style="color: #000000">group</span></span>(), <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">msgEvent</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">msg</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">group</span></span>(), <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">joinEvent</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">joins</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">group</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">leaveEvent</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">leaves</span>, <span style="font-weight: bold"><span style="color: #000000">nick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">group</span></span>()};
<span style="font-weight: bold"><span style="color: #000000">changeNameEvent</span></span>() <span style="color: #990000">::</span> {<span style="color: #FF6600">changesName</span>, <span style="font-weight: bold"><span style="color: #000000">oldnick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">newnick</span></span>(), <span style="font-weight: bold"><span style="color: #000000">group</span></span>()}<span style="color: #990000">.</span></tt></pre></div></div>
</section>
<section id="contracts_state_and_or_anystate_only">
<div class="page-header">
<h1>Contracts: +STATE and/or +ANYSTATE only</h1>
</div>
<p>For example, a "+STATE" and "+ANYSTATE" contract having the filename
"irc_fsm_plugin.con" is as follows:</p>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 3.1.7
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #990000">+</span><span style="color: #009900">NAME</span>(<span style="color: #FF0000">"irc"</span>)<span style="color: #990000">.</span>
<span style="color: #990000">+</span><span style="color: #009900">VSN</span>(<span style="color: #FF0000">"ubf2.0"</span>)<span style="color: #990000">.</span>
<span style="color: #990000">+</span><span style="color: #009900">STATE</span> <span style="color: #FF6600">start</span>
<span style="font-weight: bold"><span style="color: #000000">logon</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">proceed</span></span>() &amp; <span style="color: #FF6600">active</span><span style="color: #990000">.</span> <span style="font-style: italic"><span style="color: #9A1900">%% Nick randomly assigned</span></span>
<span style="color: #990000">+</span><span style="color: #009900">STATE</span> <span style="color: #FF6600">active</span>
<span style="font-weight: bold"><span style="color: #000000">listGroups</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">groups</span></span>() &amp; <span style="color: #FF6600">active</span>;
<span style="font-weight: bold"><span style="color: #000000">joinGroup</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">ok</span></span>() &amp; <span style="color: #FF6600">active</span>;
<span style="font-weight: bold"><span style="color: #000000">leaveGroup</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">ok</span></span>() &amp; <span style="color: #FF6600">active</span>;
<span style="font-weight: bold"><span style="color: #000000">changeNick</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">bool</span></span>() &amp; <span style="color: #FF6600">active</span>;
<span style="font-weight: bold"><span style="color: #000000">msg</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">bool</span></span>() &amp; <span style="color: #FF6600">active</span>; <span style="font-style: italic"><span style="color: #9A1900">%% False if you have not joined a group</span></span>
<span style="color: #009900">EVENT</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">msgEvent</span></span>(); <span style="font-style: italic"><span style="color: #9A1900">%% Group sends me a message</span></span>
<span style="color: #009900">EVENT</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">joinEvent</span></span>(); <span style="font-style: italic"><span style="color: #9A1900">%% Nick joins group</span></span>
<span style="color: #009900">EVENT</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">leaveEvent</span></span>(); <span style="font-style: italic"><span style="color: #9A1900">%% Nick leaves group</span></span>
<span style="color: #009900">EVENT</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">changeNameEvent</span></span>()<span style="color: #990000">.</span> <span style="font-style: italic"><span style="color: #9A1900">%% Nick changes name</span></span>
<span style="color: #990000">+</span><span style="color: #009900">ANYSTATE</span>
<span style="font-weight: bold"><span style="color: #000000">info</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>();
<span style="font-weight: bold"><span style="color: #000000">description</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">ubfstring</span></span>();
<span style="font-weight: bold"><span style="color: #000000">contract</span></span>() <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #000000">term</span></span>()<span style="color: #990000">.</span>
</tt></pre></div></div>
</section>
<section id="plugins">
<div class="page-header">
<h1>Plugins</h1>
</div>
<p>A plugin is just a "normal" Erlang module that follows a few simple
rules. For a "+TYPES" only contract, the plugin contains just the
name of it&#8217;s contract.</p>
<p>The plugin for the "+TYPES" only contract having the filename
"irc_types_plugin.erl" is as follows:</p>
<pre class="prettyprint">-module(irc_types_plugin).
-compile({parse_transform,contract_parser}).
-add_contract("irc_types_plugin").</pre>
<p>Otherwise, the plugin contains the name of it&#8217;s contract plus the
necessary Erlang "glue code" needed to bind the UBF server to the
server&#8217;s application.</p>
<p><span class="label label-tip">Tip</span> Check the UBF User&#8217;s Guide for possible ways that a plugin&#8217;s
contract may fail to compile.</p>
</section>
<section id="plugins_importing_types">
<div class="page-header">
<h1>Plugins - Importing Types</h1>
</div>
<p>A plugin can also import all or a subset of "+TYPES" from other
plugins. This simple yet powerful import mechanism permits sharing
and re-use of types between plugins and servers.</p>
<p>The plugin for the "+STATE" and "+ANYSTATE" contract having the
filename "irc_fsm_plugin.erl" is as follows:</p>
<pre class="prettyprint">-module(irc_fsm_plugin).
-compile({parse_transform,contract_parser}).
-add_types(irc_types_plugin).
-add_contract("irc_fsm_plugin").</pre>
<p>The "-add_types('there')" directive imports all "+TYPES" from the
plugin named 'there' into the containing plugin.</p>
<p><span class="label label-note">Note</span> An alternative syntax "-add_types({'elsewhere', ['t1',
't2', &#8230;, 'tn']})." for this directive imports a subset of
"+TYPEs" from the plugin named 'elsewhere' into the containing
plugin.</p>
</section>
<section id="transports_tcp_ip_ubf_ebf_jsf_tbf">
<div class="page-header">
<h1>Transports: TCP/IP - UBF/EBF/JSF/TBF</h1>
</div>
<p>The following TCP/IP based transports are supported:</p>
<dl class="dl-horizontal">
<dt>
UBF
</dt>
<dd>
Universal Binary Format
</dd>
<dt>
EBF
</dt>
<dd>
Erlang Binary Format
</dd>
<dt>
JSF
</dt>
<dd>
JavaScript Format
</dd>
<dt>
TBF
</dt>
<dd>
Thrift Binary Format
</dd>
</dl>
</section>
<section id="transports_http_json_rpc">
<div class="page-header">
<h1>Transports: HTTP - JSON-RPC</h1>
</div>
<p>JSON-RPC is a lightweight remote procedure call protocol similar to
XML-RPC.</p>
<p>The UBF framework implementation of JSON-RPC brings together JSF&#8217;s
encoder/decoder, UBF(b)'s contract checking, and an HTTP transport.</p>
<div class="imageblock">
<div class="content">
<img src="images/ubf-flow-02.png" alt="Programming By Contract w/ Multiple Transports">
</div>
<div class="title">Figure 2. Programming By Contract w/ Multiple Transports</div>
</div>
<p><span class="label label-note">Note</span> Any data that violates the <small>same</small> contract(s) is rejected
regardless of the transport.</p>
</section>
<section id="transports_etf_and_lpc">
<div class="page-header">
<h1>Transports: ETF and LPC</h1>
</div>
<p>Several transports that do not require an explicit network socket have
been added to the UBF framework.</p>
<dl class="dl-horizontal">
<dt>
ETF
</dt>
<dd>
Erlang Term Format <small>(Erlang&#8217;s Native Distribution)</small>
</dd>
<dt>
LPC
</dt>
<dd>
Local Procedure Call <small>(Calls made directly to a Plugin)</small>
</dd>
</dl>
<p>These transports permit an application to call a plugin directly
without the need for TCP/IP or HTTP.</p>
</section>
<section id="servers">
<div class="page-header">
<h1>Servers</h1>
</div>
<p>The UBF framework provides two types of Erlang servers: "stateless"
and "stateful". The stateless server is an extension of Joe
Armstrong&#8217;s original UBF server implementation. The "stateful" server
is Joe Armstrong&#8217;s original UBF server implementation.</p>
<p>UBF servers are introspective - which means the servers can describe
themselves. The following commands (described in UBF(a) format) are
always available:</p>
<dl class="dl-horizontal">
<dt>
'help' $
</dt>
<dd>
Help information
</dd>
<dt>
'info' $
</dt>
<dd>
Short information about the current service
</dd>
<dt>
'description' $
</dt>
<dd>
Long information about the current service
</dd>
<dt>
'services' $
</dt>
<dd>
A list of available services
</dd>
<dt>
'contract' $
</dt>
<dd>
Return the service contract
</dd>
<dt>
{'startSession', "Name", Args} $
</dt>
<dd>
To start a new session for the Name service. Args are initial
arguments for the Name service and is specific to that service.
</dd>
<dt>
{'restartService', "Name", Args} $
</dt>
<dd>
To restart the Name service. Args are restart arguments for the
Name service and is specific to that service.
</dd>
</dl>
</section>
<section id="servers_start_small_or_small_start_link">
<div class="page-header">
<h1>Servers: start <small>or</small> start_link</h1>
</div>
<p>The "ubf_server" Erlang module implements most of the commonly-used
server-side functions and provides several ways to start a server.</p>
<pre class="prettyprint">-module(ubf_server).
-type name() :: atom().
-type plugins() :: [module()].
-type ipport() :: pos_integer().
-type options() :: [{atom(), term()}].
-spec start(plugins(), ipport()) -&gt; true.
-spec start(name(), plugins(), ipport()) -&gt; true.
-spec start(name(), plugins(), ipport(), options()) -&gt; true.
-spec start_link(plugins(), ipport()) -&gt; true.
-spec start_link(name(), plugins(), ipport()) -&gt; true.
-spec start_link(name(), plugins(), ipport(), options()) -&gt; true.</pre>
<p><span class="label label-tip">Tip</span> Check the UBF User&#8217;s Guide for supported configuration options.</p>
</section>
<section id="servers_stateless">
<div class="page-header">
<h1>Servers: Stateless</h1>
</div>
<p>The plugin callback API for the stateless server.</p>
<pre class="prettyprint">%% common callback API
-spec info() -&gt; string().
-spec description() -&gt; string().
-spec handlerStop(Handler::pid(), Reason::term(), StateData::term()) -&gt;
NewStateData::term().
%% stateless callback API
-spec handlerStart(Args::term()) -&gt;
{accept, Reply::term(), StateName::atom(), StateDate::term()} |
{reject, Reply::term()}.
-spec handlerRpc(Call::term()) -&gt; Reply::term().</pre>
</section>
<section id="servers_stateful">
<div class="page-header">
<h1>Servers: Stateful</h1>
</div>
<p>The plugin callback API for the stateful server.</p>
<pre class="prettyprint">%% common callback API
-spec info() -&gt; string().
-spec description() -&gt; string().
-spec handlerStop(Handler::pid(), Reason::term(), StateData::term()) -&gt;
NewStateData::term().
%% stateful callback API
-spec handlerStart(Args::term(), Manager::pid()) -&gt;
{accept, Reply::term(), StateName::atom(), StateDate::term()} |
{reject, Reply::term()}.
-spec handlerRpc(StateName::atom(), Call::term(), StateDate::term(), Manager::pid()) -&gt;
{Reply::term(), NewStateName::atom(), NewStateData::term()}.
-spec managerStart(Args::term()) -&gt;
{ok, ManagerData::term()}.
-spec managerRestart(Args::term(), Manager::pid()) -&gt;
ok | {error, Reason::term()}.
-spec managerRpc(Args::term(), ManagerData::term()) -&gt;
{ok, NewManagerData::term()} | {error, Reason::term()}.</pre>
</section>
<section id="clients_erlang_rpc">
<div class="page-header">
<h1>Clients: Erlang RPC</h1>
</div>
<p>The "default" Erlang client is the "rpc" client and it supports TCP/IP
and ETF transports.</p>
<p>The "ubf_client" Erlang module implements most of the commonly-used
client-side functions and contains the implementation for all types of
Erlang clients.</p>
<pre class="prettyprint">-module(ubf_client).
-type host() :: nonempty_string().
-type ipport() :: pos_integer().
-type name() :: atom().
-type server() :: name() | pid().
-type plugin() :: module().
-type plugins() :: [plugin()].
-type options() :: [{atom(), term()}].
-type service() :: {'#S', nonempty_string()} | undefined.
-type statename() :: atom().
-type tlogger() :: module().
-spec connect(host() | plugins(), ipport() | server()) -&gt;
{ok, Client::pid(), service()} | {error, term()}.
-spec connect(host() | plugins(), ipport() | server(), timeout()) -&gt;
{ok, Client::pid(), service()} | {error, term()}.
-spec connect(host() | plugins(), ipport() | server(), options(), timeout()) -&gt;
{ok, Client::pid(), service()} | {error, term()}.
-spec stop(Client::pid()) -&gt; ok.
-spec rpc(Client::pid(), Call::term()) -&gt; timeout | term() | no_return().
-spec rpc(Client::pid(), Call::term(), timeout()) -&gt; timeout | term() | no_return().</pre>
<p><span class="label label-tip">Tip</span> Check the UBF User&#8217;s Guide for the "lpc" client.</p>
</section>
<section id="ubf_hands_on">
<div class="page-header">
<h1>UBF Hands On</h1>
</div>
<p>Provide an opportunity for hands-on experience to download, to build,
to develop, and to test a <strong>real</strong> UBF contract, <strong>real</strong> UBF client, and
<strong>real</strong> UBF server.</p>
<p>The goal of this exercise is to learn more about UBF and to implement
and to test your own Bert-RPC server using the UBF framework.</p>
<p>First, let&#8217;s briefly review the <a href="http://bert-rpc.org">Bert-RPC</a>
specification.</p>
</section>
<section id="setup">
<div class="page-header">
<h1>Setup</h1>
</div>
<p><span class="label label-caution">Caution</span> UBF requires Erlang/OTP R13B01 or newer. UBF has been tested
most recently with Erlang/OTP R13B04.</p>
<ol>
<li>
Copy the <em>ubf-bertrpc.tgz</em> tarball, <em>ubf-tutorial.tgz</em> tarball, and
<em>ubf-user-guide.tgz</em> tarball from the USB stick to your home
directory.
</li>
<li>
Make work directory and untar each of the tarballs:
<pre class="prettyprint">$ mkdir -p ~/work/
$ cd ~/work/
$ tar -xvzf ~/ubf-bertrpc.tgz
$ tar -xvzf ~/ubf-tutorial.tgz
$ tar -xvzf ~/ubf-user-guide.tgz</pre>
</li>
<li>
Build
<pre class="prettyprint">$ cd ~/work/ubf-bertrpc
$ env BOM_FAKE=1 ./bom.sh co src/erl-tools/ubf-bertrpc
$ env BOM_FAKE=1 ./bom.sh make
$ make ERL=/usr/local/hibari/ert/R13B04/bin/erl</pre>
<p><span class="label label-note">Note</span> Please specify the path to your erlang system&#8217;s erl executable.</p>
<p><span class="label label-tip">Tip</span> Adding DEBUG="+debug_info" will produce DEBUG enabled beam files.</p>
</li>
<li>
Unit Test
<pre class="prettyprint">$ make ERL=/usr/local/hibari/ert/R13B04/bin/erl test</pre>
</li>
</ol>
</section>
<section id="bertrpc_types">
<div class="page-header">
<h1>BERTRPC Types</h1>
</div>
<dl>
<dt>
Simple Data Types
</dt>
<dd>
<ul>
<li>
integer
</li>
<li>
float
</li>
<li>
atom
</li>
<li>
tuple
</li>
<li>
bytelist
</li>
<li>
list
</li>
<li>
binary
</li>
</ul>
</dd>
<dt>
Complex Data Types
</dt>
<dd>
<ul>
<li>
nil
</li>
<li>
boolean
</li>
<li>
dictionary
</li>
<li>
time
</li>
<li>
regex
</li>
</ul>
</dd>
</dl>
</section>
<section id="berp">
<div class="page-header">
<h1>BERP</h1>
</div>
<p>BERP is same as EBF.</p>
<p>EBF is an implementation of UBF(b) but it does not use UBF(a) for the
client and server communication. Instead, Erlang-style conventions
are used instead:</p>
<ul>
<li>
Structured terms are serialized via the Erlang BIFs term_to_binary()
and binary_to_term().
</li>
<li>
Terms are framed using the <em>gen_tcp</em> {packet, 4} format: a 32-bit
unsigned integer (big-endian?) specifies packet length.
<pre class="prettyprint">+-------------------------+-------------------------------+
| Packet length (32 bits) | Packet data (variable length) |
+-------------------------+-------------------------------+</pre>
</li>
</ul>
<p>The name "EBF" is short for "Erlang Binary Format".</p>
</section>
<section id="bert_rpc">
<div class="page-header">
<h1>BERT-RPC</h1>
</div>
<dl>
<dt>
Synchronous RPC
</dt>
<dd>
<ul>
<li>
{call, Module, Function, Arguments}
</li>
<li>
{reply, Result}
</li>
</ul>
</dd>
<dt>
"Asynchronous" RPC
</dt>
<dd>
<ul>
<li>
{cast, Module, Function, Arguments}
</li>
<li>
{noreply}
</li>
</ul>
</dd>
<dt>
Errors
</dt>
<dd>
<ul>
<li>
{error, {Type, Code, Class, Detail, Backtrace}}
</li>
<li>
Protocol Error Codes
</li>
<li>
Server Error Codes
</li>
</ul>
</dd>
<dt>
Info Directives
</dt>
<dd>
<ul>
<li>
{info, Command, Options}
</li>
<li>
{info, callback, [{service, Service}, {mfa, Mod, Fun, Args}]}
</li>
</ul>
</dd>
<dt>
Caching Features
</dt>
<dd>
<ul>
<li>
Expiration Caching
</li>
<li>
Validation Caching
</li>
</ul>
</dd>
<dt>
Streaming Features
</dt>
<dd>
<ul>
<li>
Streaming Binary Request
</li>
<li>
Streaming Binary Response
</li>
</ul>
</dd>
</dl>
</section>
<section id="ubf_bertrpc_application_1_of_2">
<div class="page-header">
<h1>UBF-BERTRPC: Application (1 of 2)</h1>
</div>
<dl>
<dt>
1.
</dt>
<dd>
Change directory to the ubf-bertrpc application.
<pre class="prettyprint">$ cd ~/work/ubf-bertrpc/src/erl-tools/ubf-bertrpc__HEAD</pre>
</dd>
<dt>
2.
</dt>
<dd>
List directory of the ubf-bertrpc application.
<pre class="prettyprint">$ ls -R
.:
BOM.mk
ChangeLog
ebin
GMBOM
include
LICENSE
priv
README
src
./ebin:
./include:
bertrpc.hrl
bertrpc_impl.hrl
./priv:
sys.config
./src:
Makefile
bert.erl
bert_driver.erl
ubf_bertrpc_plugin.con
ubf_bertrpc_plugin.erl
Unit-EUnit-Files
./src/Unit-EUnit-Files:
bertrpc_plugin.app
bertrpc_plugin_app.erl
bertrpc_plugin_sup.erl
bertrpc_plugin_test.erl</pre>
</dd>
</dl>
</section>
<section id="ubf_bertrpc_application_2_of_2">
<div class="page-header">
<h1>UBF-BERTRPC: Application (2 of 2)</h1>
</div>
<dl>
<dt>
3.
</dt>
<dd>
Review key files of the ubf-bertrpc application.
<ul>
<li>
src/ubf_bertrpc_plugin.con
</li>
<li>
src/ubf_bertrpc_plugin.erl
</li>
</ul>
</dd>
<dt>
4.
</dt>
<dd>
Review key files of the ubf-bertrpc application&#8217;s eunit tests.
<ul>
<li>
./src/Unit-EUnit-Files/bertrpc_plugin.app
</li>
<li>
./src/Unit-EUnit-Files/bertrpc_plugin_app.erl
</li>
<li>
./src/Unit-EUnit-Files/bertrpc_plugin_sup.erl
</li>
<li>
./src/Unit-EUnit-Files/bertrpc_plugin_test.erl
</li>
</ul>
</dd>
<dt>
5.
</dt>
<dd>
Review ubf-bertrpc application&#8217;s Makefile.
<ul>
<li>
src/Makefile
</li>
</ul>
</dd>
</dl>
<p><span class="label label-tip">Tip</span> The command make target "run-erl1" starts an erlang shell that
can be used for interactive development, debugging, and testing.</p>
</section>
<section id="basic_exercises_1_of_3">
<div class="page-header">
<h1>Basic Exercises (1 of 3)</h1>
</div>
<dl>
<dt>
1.
</dt>
<dd>
Implement and test BERT-RPC&#8217;s call/3 and reply/1 primitives:
<ol>
<li>
Modify ubf_bertrpc_plugin.con
</li>
<li>
Modify ubf_bertrpc_plugin.erl
</li>
<li>
Add new unit test to bertrpc_plugin_test.erl that uses
erlang:now()
</li>
</ol>
</dd>
</dl>
</section>
<section id="basic_exercises_2_of_3">
<div class="page-header">
<h1>Basic Exercises (2 of 3)</h1>
</div>
<dl>
<dt>
2.
</dt>
<dd>
Implement and test BERT-RPC&#8217;s error/1 primitive for Server Error
Codes:
<ol>
<li>
Modify ubf_bertrpc_plugin.con
</li>
<li>
Modify ubf_bertrpc_plugin.erl
</li>
<li>
Add new unit test to bertrpc_plugin_test.erl that tests calling
an unknown module "foobar".
</li>
<li>
Add new unit test bertrpc_plugin_test.erl that tests calling an
unknown function "erlang:foobar".
</li>
</ol>
</dd>
</dl>
</section>
<section id="basic_exercises_3_of_3">
<div class="page-header">
<h1>Basic Exercises (3 of 3)</h1>
</div>
<dl>
<dt>
3.
</dt>
<dd>
Implement and test BERT-RPC&#8217;s cast/1 primitive:
<ol>
<li>
Modify ubf_bertrpc_plugin.con
</li>
<li>
Modify ubf_bertrpc_plugin.erl
</li>
<li>
Add new unit test to bertrpc_plugin_test.erl that uses
error_logger:error_report/1. Manually check if your test
triggers a message to stderr.
</li>
</ol>
</dd>
</dl>
</section>
<section id="advanced_exercises_1_of_4">
<div class="page-header">
<h1>Advanced Exercises (1 of 4)</h1>
</div>
<dl>
<dt>
1.
</dt>
<dd>
Implement and test BERT-RPC&#8217;s info callback/2 primitive:
<ol>
<li>
modify ubf_bertrpc_plugin.con
</li>
<li>
modify ubf_bertrpc_plugin.erl
</li>
<li>
add new unit test to bertrpc_plugin_test.erl that tests using
erlang:now().
</li>
</ol>
</dd>
</dl>
<p><span class="label label-tip">Tip</span> Re-use the ubf_client.erl client inside the
ubf_bertrpc_plugin.erl implementation. Re-use the same test server as
target service.</p>
<p><span class="label label-caution">Caution</span> To implement the "{info,&#8230;}" construct, changes are required
for the bert.erl and bert_driver.erl modules. The module must
maintain state and should convert the "{info,&#8230;}" BERP and it&#8217;s
corresponding "{call,&#8230;.}" BERP into a 2-tuple that forms a single
UBF request. To avoid such headaches, send such a 2-tuple directly
from the UBF client to your server as a work-around.</p>
</section>
<section id="advanced_exercises_2_of_4">
<div class="page-header">
<h1>Advanced Exercises (2 of 4)</h1>
</div>
<dl>
<dt>
2.
</dt>
<dd>
Implement and test BERT-RPC&#8217;s error/1 primitive for Protocol Error
Codes:
<ol>
<li>
modify bert_driver.erl
</li>
<li>
add new unit test to bertrpc_plugin_test.erl
</li>
</ol>
</dd>
</dl>
</section>
<section id="advanced_exercises_3_of_4">
<div class="page-header">
<h1>Advanced Exercises (3 of 4)</h1>
</div>
<dl>
<dt>
3.
</dt>
<dd>
Implement Caching Directives
<ol>
<li>
modify ubf_bertrpc_plugin.erl
</li>
<li>
add new unit test to bertrpc_plugin_test.erl
</li>
</ol>
</dd>
</dl>
</section>
<section id="advanced_exercises_4_of_4">
<div class="page-header">
<h1>Advanced Exercises (4 of 4)</h1>
</div>
<dl>
<dt>
4.
</dt>
<dd>
Implement Streaming Binary Request and Response
<ol>
<li>
modify bert_driver.erl
</li>
<li>
add new unit test to bertrpc_plugin_test.erl
</li>
</ol>
</dd>
</dl>
<p><span class="label label-tip">Tip</span> Create a new ubf_bertrpc_client.erl implementation by
implementing a wrapper over the standard ubf_client.erl module.</p>
</section>
<section id="thank_you">
<div class="page-header">
<h1>Thank You</h1>
</div>
<p>For UBF, please check UBF&#8217;s GitHub repository and webpage for updates.</p>
<dl class="dl-horizontal">
<dt>
UBF
</dt>
<dd>
<a href="https://github.com/ubf/ubf">https://github.com/ubf/ubf</a>
</dd>
</dl>
</section>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<p class="pull-right"><a href="#">Back to top</a></p>
<p>Functional programming for the better good!</p>
</div>
</footer>
<script src="http://platform.twitter.com/widgets.js"></script>
<script src="./bootstrap/docs/assets/js/jquery.js"></script>
<script src="./bootstrap/docs/assets/js/google-code-prettify/prettify.js"></script>
<script src="./bootstrap/docs/assets/js/bootstrap.min.js"></script>
<script src="./bootstrap/docs/assets/js/application.js"></script>
<script src="./asciidoc.js"></script>
<script>asciidoc.install(1);</script>
</body>
</html>