mirror of
https://github.com/ubf/ubf.git
synced 2026-04-17 10:16:06 +00:00
1448 lines
49 KiB
HTML
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>
|
|
"…"
|
|
</dd>
|
|
<dt>
|
|
Binary
|
|
</dt>
|
|
<dd>
|
|
[0-9]+ ~…~
|
|
</dd>
|
|
<dt>
|
|
Atom
|
|
</dt>
|
|
<dd>
|
|
'…'
|
|
</dd>
|
|
<dt>
|
|
Tuple
|
|
</dt>
|
|
<dd>
|
|
{ Obj1 Obj2 … ObjN-1 ObjN }
|
|
</dd>
|
|
<dt>
|
|
List
|
|
</dt>
|
|
<dd>
|
|
# ObjN & ObjN-1 & … & Obj2 & Obj1
|
|
</dd>
|
|
<dt>
|
|
Term
|
|
</dt>
|
|
<dd>
|
|
represent primitive types and compound types
|
|
</dd>
|
|
<dt>
|
|
White space
|
|
</dt>
|
|
<dd>
|
|
\s \n \r \t , %…%
|
|
</dd>
|
|
<dt>
|
|
Register
|
|
</dt>
|
|
<dd>
|
|
>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'>p # {p "Joe" 123} & {p 'fred' 3~abc~} & $</pre>
|
|
<p>Represents the following UBF(b) term, a list that contains two
|
|
3-tuples:</p>
|
|
<pre class="prettyprint">[{'person', 'fred', <<"abc">>}, {'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("…"). <small>mandatory</small>
|
|
</dd>
|
|
<dt>
|
|
Version
|
|
</dt>
|
|
<dd>
|
|
+VSN("…"). <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>
|
|
<<"…">>
|
|
</dd>
|
|
<dt>
|
|
String
|
|
</dt>
|
|
<dd>
|
|
"…"
|
|
</dd>
|
|
<dt>
|
|
Atom
|
|
</dt>
|
|
<dd>
|
|
'…' <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, …, Tn}
|
|
</dd>
|
|
<dt>
|
|
Record
|
|
</dt>
|
|
<dd>
|
|
name#T1, y=T2, …, z=Tn
|
|
</dd>
|
|
<dt>
|
|
Extended Record
|
|
</dt>
|
|
<dd>
|
|
name##T1, y=T2, …, z=Tn
|
|
</dd>
|
|
<dt>
|
|
List
|
|
</dt>
|
|
<dd>
|
|
[T]
|
|
</dd>
|
|
<dt>
|
|
Predefined
|
|
</dt>
|
|
<dd>
|
|
P() <small>or</small> P(A1, A2, …, 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: <<"">>, "", '', {}, 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">=></span> <span style="font-weight: bold"><span style="color: #000000">proceed</span></span>() & <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">=></span> <span style="font-weight: bold"><span style="color: #000000">groups</span></span>() & <span style="color: #FF6600">active</span>;
|
|
<span style="font-weight: bold"><span style="color: #000000">joinGroup</span></span>() <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #000000">ok</span></span>() & <span style="color: #FF6600">active</span>;
|
|
<span style="font-weight: bold"><span style="color: #000000">leaveGroup</span></span>() <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #000000">ok</span></span>() & <span style="color: #FF6600">active</span>;
|
|
<span style="font-weight: bold"><span style="color: #000000">changeNick</span></span>() <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #000000">bool</span></span>() & <span style="color: #FF6600">active</span>;
|
|
<span style="font-weight: bold"><span style="color: #000000">msg</span></span>() <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #000000">bool</span></span>() & <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">=></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">=></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">=></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">=></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">=></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">=></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">=></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 $ ⇒ {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’s specifications.
|
|
- Plugins are a server’s implementations.</p>
|
|
<p>A contract is a UBF(b) specification stored to a file. By convention,
|
|
a contract’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">=></span> <span style="font-weight: bold"><span style="color: #000000">proceed</span></span>() & <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">=></span> <span style="font-weight: bold"><span style="color: #000000">groups</span></span>() & <span style="color: #FF6600">active</span>;
|
|
<span style="font-weight: bold"><span style="color: #000000">joinGroup</span></span>() <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #000000">ok</span></span>() & <span style="color: #FF6600">active</span>;
|
|
<span style="font-weight: bold"><span style="color: #000000">leaveGroup</span></span>() <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #000000">ok</span></span>() & <span style="color: #FF6600">active</span>;
|
|
<span style="font-weight: bold"><span style="color: #000000">changeNick</span></span>() <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #000000">bool</span></span>() & <span style="color: #FF6600">active</span>;
|
|
<span style="font-weight: bold"><span style="color: #000000">msg</span></span>() <span style="color: #990000">=></span> <span style="font-weight: bold"><span style="color: #000000">bool</span></span>() & <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">=></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">=></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">=></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">=></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">=></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">=></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">=></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’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’s contract plus the
|
|
necessary Erlang "glue code" needed to bind the UBF server to the
|
|
server’s application.</p>
|
|
<p><span class="label label-tip">Tip</span> Check the UBF User’s Guide for possible ways that a plugin’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', …, '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’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’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’s original UBF server implementation. The "stateful" server
|
|
is Joe Armstrong’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()) -> true.
|
|
-spec start(name(), plugins(), ipport()) -> true.
|
|
-spec start(name(), plugins(), ipport(), options()) -> true.
|
|
|
|
-spec start_link(plugins(), ipport()) -> true.
|
|
-spec start_link(name(), plugins(), ipport()) -> true.
|
|
-spec start_link(name(), plugins(), ipport(), options()) -> true.</pre>
|
|
<p><span class="label label-tip">Tip</span> Check the UBF User’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() -> string().
|
|
-spec description() -> string().
|
|
-spec handlerStop(Handler::pid(), Reason::term(), StateData::term()) ->
|
|
NewStateData::term().
|
|
|
|
%% stateless callback API
|
|
-spec handlerStart(Args::term()) ->
|
|
{accept, Reply::term(), StateName::atom(), StateDate::term()} |
|
|
{reject, Reply::term()}.
|
|
-spec handlerRpc(Call::term()) -> 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() -> string().
|
|
-spec description() -> string().
|
|
-spec handlerStop(Handler::pid(), Reason::term(), StateData::term()) ->
|
|
NewStateData::term().
|
|
|
|
%% stateful callback API
|
|
-spec handlerStart(Args::term(), Manager::pid()) ->
|
|
{accept, Reply::term(), StateName::atom(), StateDate::term()} |
|
|
{reject, Reply::term()}.
|
|
-spec handlerRpc(StateName::atom(), Call::term(), StateDate::term(), Manager::pid()) ->
|
|
{Reply::term(), NewStateName::atom(), NewStateData::term()}.
|
|
|
|
-spec managerStart(Args::term()) ->
|
|
{ok, ManagerData::term()}.
|
|
-spec managerRestart(Args::term(), Manager::pid()) ->
|
|
ok | {error, Reason::term()}.
|
|
-spec managerRpc(Args::term(), ManagerData::term()) ->
|
|
{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()) ->
|
|
{ok, Client::pid(), service()} | {error, term()}.
|
|
-spec connect(host() | plugins(), ipport() | server(), timeout()) ->
|
|
{ok, Client::pid(), service()} | {error, term()}.
|
|
-spec connect(host() | plugins(), ipport() | server(), options(), timeout()) ->
|
|
{ok, Client::pid(), service()} | {error, term()}.
|
|
|
|
-spec stop(Client::pid()) -> ok.
|
|
|
|
-spec rpc(Client::pid(), Call::term()) -> timeout | term() | no_return().
|
|
-spec rpc(Client::pid(), Call::term(), timeout()) -> timeout | term() | no_return().</pre>
|
|
<p><span class="label label-tip">Tip</span> Check the UBF User’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’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’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’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’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’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’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’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’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,…}" construct, changes are required
|
|
for the bert.erl and bert_driver.erl modules. The module must
|
|
maintain state and should convert the "{info,…}" BERP and it’s
|
|
corresponding "{call,….}" 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’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’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>
|