mirror of
https://github.com/ubf/ubf.git
synced 2026-04-21 12:15:39 +00:00
209 lines
7.4 KiB
Plaintext
209 lines
7.4 KiB
Plaintext
|
|
This is ubf, a framework for Getting Erlang to talk to the outside
|
|
world. This repository is based on Joe Armstrong's original UBF code
|
|
with an MIT license file added to the distribution.
|
|
|
|
|
|
To build
|
|
========
|
|
|
|
1. Get and install an erlang system
|
|
(http://www.erlang.org)
|
|
|
|
2. Optionally, get and install erlang-rfc4627
|
|
(http://www.lshift.net/blog/2007/02/17/json-and-json-rpc-for-erlang)
|
|
|
|
3. Change to the src directory and type make
|
|
$ cd src
|
|
$ make
|
|
|
|
4. Run the unit test
|
|
$ make check
|
|
|
|
5. If you have installed erlang-rfc4627, run the unit test for jsf $
|
|
make check-jsf
|
|
|
|
One quick/kludge method to "install" is to obtain & compile the
|
|
erlang-rfc4627 code from LShift and add a "-pz /path/to/.../ebin"
|
|
flag to the "check-jsf" target inside "src/Makefile", then run
|
|
"make check-jsf".
|
|
|
|
|
|
Documentation -- Where should I start?
|
|
======================================
|
|
|
|
This README is a good first step. Check out and build using the "To
|
|
build" instructions above.
|
|
|
|
The documentation is in a state of slow improvement. Contributions
|
|
from the wider world are welcome. :-)
|
|
|
|
One of the better places to start is to look in the "edoc" directory.
|
|
The docs for the three modules there represent most of the public API
|
|
for creating UBF/EBF/JSF servers.
|
|
|
|
The unit tests in the "src/Unit-Test-Files" directory provide small
|
|
examples of how to use all of the public API. In particular, the
|
|
*client*.erl files contain comments at the top with a list of
|
|
prerequisites and small examples, recipe-style, for starting each
|
|
server and using the client.
|
|
|
|
The original documentation is in the "priv/doc" directory.
|
|
|
|
|
|
What is UBF?
|
|
============
|
|
|
|
UBF is the "Universal Binary Format", designed and implemented by Joe
|
|
Armstrong. See http://www.sics.se/~joe/ubf.html for full details. A
|
|
really short summary:
|
|
|
|
* UBF(A) is a protocol above a stream transport (e.g. TCP/IP), for
|
|
encoding structured data roughly equivalent to well-formed XML.
|
|
|
|
* UBF(B) is a programming langauge for describing types in UBF(A)
|
|
and protocols between clients and servers. UBF(B) is roughly
|
|
equivalent to to Verified XML, XML-schemas, SOAP and WDSL.
|
|
|
|
|
|
What is EBF?
|
|
============
|
|
|
|
EBF is an implementation of UBF(B) but does not use UBF(A) for
|
|
client<->server communication. Instead, Erlang-style conventions are
|
|
used instead:
|
|
|
|
* Structured terms are serialized via the Erlang BIFs
|
|
term_to_binary() and binary_to_term().
|
|
|
|
* Terms are framed using the 'gen_tcp' {packet, 4} format: a 32-bit
|
|
unsigned integer (big-endian?) specifies packet length.
|
|
|
|
+-------------------------+-------------------------------+
|
|
| Packet length (32 bits) | Packet data (variable length) |
|
|
+-------------------------+-------------------------------+
|
|
|
|
The name "EBF" is short for "Erlang Binary Format".
|
|
|
|
|
|
What is JSF?
|
|
============
|
|
|
|
JSF is an implementation of UBF(B) but does not use UBF(A) for
|
|
client<->server communication. Instead, JSON (RFC 4627) is used.
|
|
|
|
"JSF" is short for "JavaScript Format".
|
|
|
|
There is no agreed-upon convention for converting Erlang terms to JSON
|
|
objects. This library uses the convention set forth by LShift's JSON
|
|
library (see URL above). In addition, there are a couple of other
|
|
conventions layered on top of LShift's implementation.
|
|
|
|
The UBF(B) contract checker has been modified to make a distinction
|
|
between an Erlang record and an arbitrary Erlang tuple. An
|
|
experience Erlang developer would view such a distinction either
|
|
with skepticism or with approval.
|
|
|
|
For the skeptics, the contract author has the option of having the
|
|
UBF(B) contract compiler automatically generate Erlang -record()
|
|
definitions for appropriate tuples within the contract. Such
|
|
record definitions are very convenient for developers on the Erlang
|
|
side of the world, but they introduce more complication to the
|
|
JavaScript side of the world. For example, JavaScript does not
|
|
have a concept of an arbitrary atom, as Erlang does. Also, the
|
|
JavaScript side must make a distinction between {foo, 42} and {bar,
|
|
42} when #foo is a record on the Erlang side but #bar is not.
|
|
|
|
This extra convention creates something slightly messy-looking, if you
|
|
look at the raw JSON passed back-and-forth. The examples of the
|
|
Erlang record {foo, 42} and the general tuple {bar, 42} would look
|
|
like this:
|
|
|
|
record (defined in the contract as "foo() = #foo{attribute1 = term()};")
|
|
|
|
{"$R":"foo", "attribute1":42}
|
|
|
|
general tuple
|
|
|
|
{"$T":[{"$A":"bar"}, 42]}
|
|
|
|
However, it requires very little JavaScript code to convert objects
|
|
with the "$R", "$T", and "$A" notation (for records, tuples, and
|
|
atoms) into whatever object is most convenient.
|
|
|
|
|
|
Does the package include a JSON-RPC server?
|
|
===========================================
|
|
|
|
At this time, no. Gemini Mobile Technologies has implemented such a
|
|
server (using the Yaws HTTP server) but the source code is not yet
|
|
ready for outside distribution (as of late April 2009). We hope to
|
|
add the JSON-RPC implementation in the near future ... unless someone
|
|
else implements it first!
|
|
|
|
|
|
To do (in short term)
|
|
=====================
|
|
|
|
- cleanup (or remove) old documentation under priv/doc
|
|
- add ChangeLog template
|
|
- document new features
|
|
+ ubf contract (and contract checker) primitives
|
|
- atom(), binary(), float(), integer(), proplist(), string(), term(),
|
|
tuple(), void()
|
|
- atom(ascii), atom(asciiprintable), atom(nonempty), atom(nonundefined),
|
|
atom(ascii,nonempty), atom(ascii,nonundefined),
|
|
atom(asciiprintable,nonempty), atom(asciiprintable,nonundefined),
|
|
atom(ascii,nonempty,nonundefined),
|
|
atom(asciiprintable,nonempty,nonundefined)
|
|
- binary(ascii), binary(asciiprintable), binary(nonempty),
|
|
binary(ascii,nonempty), binary(asciiprintable,nonempty)
|
|
- proplist(nonempty)
|
|
- string(ascii), string(asciiprintable), string(nonempty),
|
|
string(ascii,nonempty), string(asciiprintable,nonempty)
|
|
- term(nonempty), term(nonundefined), term(nonempty,nonundefined)
|
|
- tuple(nonempty)
|
|
- ascii: all items in atom name/string/binary are ASCII values
|
|
- asciiprintable: all items in atom name/string/binary are printable
|
|
ASCII values
|
|
- nonempty: not equal to '', [], <<>>, or {}
|
|
- nonundefined: not equal to 'undefined'
|
|
+ ubf contract type imports
|
|
+ ubf server and ubf client
|
|
+ stateless server w/simplified plugin handler callbacks
|
|
- For protocols that do not require state transitions: a single
|
|
state called ANYSTATE is used for the contract, and
|
|
the implementation callback function API is a bit less complex.
|
|
+ network formats
|
|
* ebf - Erlang Binary Format
|
|
* jsf - Java Script Format
|
|
* etf - Erlang Term Format
|
|
+ jsf contract and json rpc helpers
|
|
+ ???
|
|
|
|
|
|
To do (in medium term)
|
|
======================
|
|
|
|
- ubf contract generators for QuickCheck
|
|
- ABNF (RFC 5234) support and integration
|
|
- erlang spec (EEP 8) integration
|
|
- asynchronous events from client to server
|
|
- n-bidirectional requests/responses over single tcp/ip connection (similiar to smpp)
|
|
- replace plugin manager and plugin handler with gen_server-based
|
|
implementation
|
|
- enable/disable contract checker by configuration
|
|
- eunit tests
|
|
- quickcheck tests
|
|
|
|
|
|
Credits
|
|
=======
|
|
|
|
Many, many thanks to Joe Armstrong, UBF's designer and original
|
|
implementor.
|
|
|
|
Gemini Mobile Technologies, Inc. has approved the release of its
|
|
extensions, improvements, etc. under an MIT license. Joe Armstrong
|
|
has also given his blessing to Gemini's license choice.
|