mirror of
https://github.com/ubf/ubf.git
synced 2026-04-22 04:35:53 +00:00
261 lines
9.2 KiB
Plaintext
261 lines
9.2 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
|
|
|
|
|
|
**NOTE**
|
|
|
|
Before make, one quick/kludge method to "install" is to obtain and
|
|
compile the erlang-rfc4627 code from LShift. (Optionally, copy its
|
|
.beam files to a more permanent installation location.)
|
|
|
|
Then edit "src/Makefile" to change the "MY_ERLANG_RFC4627_EBIN"
|
|
variable to point to where the ebin directory that contains
|
|
erlang-rfc4627's .beam files. 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.
|
|
See the "Reference Documentation" section for suggestions on where to
|
|
find greater detail.
|
|
|
|
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 eunit tests in the "src/Unit-EUnit-Files" directory perform
|
|
several smoke and error handling uses cases.
|
|
|
|
The original documentation is in the "priv/doc" directory.
|
|
|
|
The #1 most frequently asked question is: "My term X fails contract
|
|
Y, but I can't figure out why! This X is perfectly OK. What is going
|
|
on?" See the the EDoc documentation for the contracts:checkType/3
|
|
function.
|
|
|
|
|
|
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.
|
|
|
|
* UBF(C) is a meta-level protocol used between a UBF client and a
|
|
UBF server.
|
|
|
|
|
|
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.
|
|
|
|
|
|
What about JSON-RPC?
|
|
====================
|
|
|
|
See the ubf-jsonrpc open source repository
|
|
http://github.com/norton/ubf-jsonrpc for details. ubf-jsonrpc is a
|
|
framework for integrating UBF and JSON-RPC.
|
|
|
|
|
|
What about ABNF?
|
|
================
|
|
|
|
See the ubf-abnf open source repository
|
|
http://github.com/norton/ubf-abnf for details. ubf-abnf is a
|
|
framework for integrating UBF and ABNF.
|
|
|
|
|
|
What about EEP8?
|
|
================
|
|
|
|
See the ubf-eep8 open source repository
|
|
http://github.com/norton/ubf-eep8 for details. ubf-eep8 is a
|
|
framework for integrating UBF and EEP8.
|
|
|
|
|
|
To do (in short term)
|
|
=====================
|
|
|
|
- cleanup (or remove) old documentation under priv/doc
|
|
- document new features
|
|
+ predefined ubf contract (and contract checker) primitives
|
|
- atom(), binary(), float(), integer(), list(), 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)
|
|
- list(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'
|
|
- type()? for optional types
|
|
- type(){0} for undefined types
|
|
+ user-defined ubf contract (and contract checker) primitives
|
|
- atom(), binary(), float(), integer(), and string() constants
|
|
- #record syntax, ##extended_record syntax with automatic erlang record defines
|
|
- integer ranges (min..max, ..max, min..)
|
|
- erlang-based syntax for integers
|
|
- [type()]? for optional lists
|
|
- [type()]+ for mandatory lists
|
|
- [type()]{N}, [type()]{N,}, [type()]{M,N} for length-constrained lists
|
|
+ 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
|
|
+ ???
|
|
|
|
|
|
To do (in medium term)
|
|
======================
|
|
- add Thrift (http://incubator.apache.org/thrift/) support
|
|
* Binary Format
|
|
* Compact Format (TBD)
|
|
- add Avro (http://hadoop.apache.org/avro/) support
|
|
- add Google's Protocol Buffers (http://code.google.com/apis/protocolbuffers/) support
|
|
- add Bert-RPC (http://bert-rpc.org/) support
|
|
* BERT-RPC is UBF/EBF with a specialized contract and plugin
|
|
handler implementation for BERT-RPC. UBF/EBF already supports all
|
|
of the BERT data types.
|
|
* UBF is the text-based wire protocol. EBF is the binary-based
|
|
wire protocol (based on Erlang's binary serialization format).
|
|
- ???
|
|
|
|
|
|
To do (in long term)
|
|
======================
|
|
|
|
- support multiple listeners for a single ubf server
|
|
- ubf contract generators for QuickCheck
|
|
- 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.
|