123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- <html>
- <head>
- <meta charset="utf-8" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <meta name="description" content="" />
- <meta name="author" content="Maxim Sokhatsky" />
- <title>N2O</title>
- <link rel="stylesheet" href="https://n2o.space/n2o.css" />
- </head>
- <body>
- <header>
- <a href="../index.html"><img src="https://n2o.space/img/Synrc Neo.svg"></a>
- <h1>N2O API</h1>
- </header>
- <main>
- <section>
- <h3>INTRO</h3>
- <p>The <b>n2o</b> defines the way you create, configure and run
- arbitrary applications and protocols inside some hosts, into
- which N2O can be injected, such as <b>cowboy</b> and <b>emqttd</b>.
- Each application can spawn its instance in its own way, like
- web pages spawn WebSocket connections, workflow engines
- spawn business proceseses and chat applications spawns roster
- and chatroom processes. With N2O everything is managed by protocols.</p>
- <p>The N2O itself a an enbeddable protocol loop. However besides that
- it handles cache and session ETS tables along with flexible async
- processes with no ownership restriction. It also introduces logging
- approach, AES/CBC—128 pickling and with BERT/JSON formatter.</p>
- </section>
- <section>
- <h3>RECORDS</h3>
- <figure><figcaption>Listing 1. Erlang/OTP records</figcaption><code>
- #ok { data = [] :: term() }.
- #error { data = [] :: term() }.
- </code></figure>
- <figure><figcaption>Listing 2. N2O Protocol</figcaption><code>
- #reply { data = [] :: [] | binary(),
- req = [] :: [] | term(),
- state = [] :: [] | term() }.
- #unknown { data = [] :: [] | binary(),
- req = [] :: [] | term(),
- state = [] :: [] | term() }.
- </code></figure>
- <figure><figcaption>Listing 3. N2O State</figcaption><code>
- #cx { session = [] :: [] | binary(),
- formatter = bert :: bert | json,
- actions = [] :: list(tuple()),
- state = [] :: [] | term(),
- module = [] :: [] | atom(),
- lang = [] :: [] | atom(),
- path = [] :: [] | binary(),
- node = [] :: [] | atom(),
- pid = [] :: [] | pid(),
- vsn = [] :: [] | integer() }).
- </code></figure>
- </section>
- <section>
- <h3>PROTOCOLS</h3>
- <p>While all application protocols in the system
- are desired to be placed in the single effectful
- environment or same error handling path, <b>n2o</b> defines
- single protocol loop for all applications in its federation of protocols.</p>
- <p>In core bundle <b>n2o</b> is shipped with NITRO and FTP protocols which
- allows you to create real-time web applications with binary-based protocols,
- priving also robust and performant upload client and file transfer protocol.
- For bulding web based NITRO applications you need to include
- <b>nitro</b> dependency.</p>
- <h4>info(term(),term(),#cx{}) -> #reply{} | #unknown{}.</h4>
- <p>The <b>info/2</b> is a N2O protocol callback that will be called on each
- incoming request. N2O code should be embedded into applications host:
- MQTT (as ring of MQTT clients), or HTTP server or WebSocket, or raw TCP.</p>
- </section>
- <section>
- <h3>RPC MQTT</h3>
- <p>N2O provides RPC over MQ mechanism for MQTT devices. N2O spawn a set of
- <a href="n2o_vnode.htm">n2o_vnode</a> workers as <a href="n2o_async.htm">n2o_async</a>
- processes that listen to <b>events</b> topic. Response are sent to <b>actions</b> topic,
- which is subscribed automatically on MQTT session init.</p>
- <figure><figcaption>Listing 4. MQTT RPC Topics</figcaption><code>
- actions/:vsn/:module/:client
- events/:vsn/:node/:module/:client
- </code></figure>
- </section>
- <section>
- <h3>RPC WebSocket</h3>
- <p>In pure WebSocket case N2O implements <a href="n2o_proto.htm">n2o_proto</a> as cowboy module supporting binary and text messages.</p>
- <figure><figcaption>Listing 5. Cowboy stream protocol</figcaption><code>
- #binary { data :: binary() }.
- #text { data :: binary() }.
- </code></figure>
- </section>
- <section>
- <h3>EXAMPLE</h3>
- <p>Here is little example of overriding INIT protocol message from NITRO protocol
- and generate standart token stored in KVS.</p>
- <figure><figcaption>Listing 6. Custom INIT Protocol</figcaption><code>
- -module(custom_init).
- -compile(export_all).
- info({init, <<>>}, Req, State = #cx{session = Session}) ->
- {'Token', Token} = n2o_auth:gen_token([], Session),
- #cx{params = Client} = get(context),
- kvs:put(#'Token'{token = Token, client = Client}),
- n2o_nitro:info({init, n2o:format(Token)}, Req, State);
- info(Message,Req,State) -> {unknown,Message,Req,State}.
- </code></figure>
- </section>
- <section>
- <h3>CONFIG</h3>
- <p>Just put protocol implementation module name to <b>protocol</b> option in sys.config.</p>
- <figure><code>
- [{n2o,[{cache,n2o},
- {mq,n2o},
- {formatter,n2o_format},
- {logging,n2o_io},
- {log_modules,n2o},
- {log_level,n2o},
- {session,n2o_session},
- {pickler,n2o_secret},
- {protocols,[custom_init,n2o_ftp,n2o_nitro]},
- {timer,{0,10,0}}]}].
- </code></figure>
- <p>N2O is the facade of the following services: cache, mq, message formating, loging,
- sessions, pickling and protocol loops. The other part of N2O is <a href="n2o_async.htm">n2o_async</a> module
- for spawning supervised application processes tha use N2O API. In this simple
- configuration you may set any implementation to any service.</p>
- </section>
- <section>
- <h3>CACHE</h3>
- <p>Cache is fast expirable memory store. Just put values onto keys using these
- functions and system timer will clear expired entries eventually.
- You can select caching module implementation by seting <b>cache</b> n2o parameter to module name.
- Default n2o cache implementation just turns each ets store into expirable.</p>
- <h4>cache(Tab, Key, Value, Till) -> term().</h4>
- <p>Sets a Value with a given TTL.</p>
- <h4>cache(Tab, Key) -> term().</h4>
- <p>Gets a Value.</p>
- </section>
- <section>
- <h3>PUBSUB</h3>
- <p>The minimal requirement for any framework is to pub/sub API.
- N2O provides selectable API through <b>mq</b> environment parameter.</p>
- <h4>subscribe(Client, Topic, Options) -> term().</h4>
- <p>Subscribe an absctract client to a transient topic. In particular
- implementation the semantics could differ. In MQTT you can subscribe
- offline/online clients to any persistent topics.</p>
- <h4>unsubscribe(Client, Topic, Options) -> term().</h4>
- <p>Unsubscribe an abstract client from a transient topic. In MQTT
- we remove the subscription from persistent database.</p>
- <h4>publish(Topic, Message, Options) -> term().</h4>
- <p>Publish a message to a topic. In MQTT if clients are offline
- they will receive offline messages from the
- inflight srotarge once they become online.</p>
- </section>
- <section>
- <h3>FORMAT</h3>
- <p>Call this function for changeable at runtime socket binary formatting.
- Used to format data field of the returned values in protocol implementations.
- N2O provides selectable API through <b>formatter</b> environment parameter.</p>
- <h4>format(Message, bert | json) -> binary().</h4>
- <figure><code>
- > io:format("~ts~n",[n2o:format(#io{},json)]).
- {"t":104,"v":[{"t":100,"v":"io"},{"t":109,"v":""},{"t":109,"v":[131,106]}]}
- ok
- > n2o:format(#ok{code=undefined},bert).
- {binary,<<131,104,2,100,0,2,111,107,100,0,9,117,110,100,
- 101,102,105,110,101,100>>}
- </code></figure>
- </section>
- <section>
- <h3>LOG</h3>
- <p>First you need specify global module in sys.config,
- where functions <b>log_level</b> and <b>log_modules</b> are placed.
- See options in config with with same names as functions.</p>
- <p>Then implement these function in way of returning the list
- modules you want to trace, and global log level for them.</p>
- <figure><figcaption>Listing 7. Log Framework</figcaption>
- <code>
- log_modules() -> [n2o,n2o_async,n2o_proto].
- log_level() -> info.
- </code></figure>
- <p>In your code you should use following trace functions
- which are the same as callback API for n2o logging
- environment variable.</p>
- <h4>error(Module, Format, Args) -> ok | skip.</h4>
- <h4>info(Module, Format, Args) -> ok | skip.</h4>
- <h4>warning(Module, Format, Args) -> ok | skip.</h4>
- </section>
- <section>
- <h3>SESSION</h3>
- <p>Sessions are stored in <b>cookies</b> table and indexed by security token which
- is usually a password based token. All session variables from all users are stored in this table.
- each user see only its variables indexed by his token. Sessions like a cache are expirable.
- Technically, N2O sessions are the server controlling mechanism of JavaScript cookies.</p>
- <h4>session(Key, Value) -> term().</h4>
- <p>Sets a Value into ETS table <b>cookies</b> for a token from #cx.session which
- is set there earlier from INIT message or MQTT headers,
- before entering the top level N2O loop.</p>
- <figure><figcaption>Listing 8. Sessions</figcaption>
- <code>
- 1> rr(n2o).
- [bin,client,cx,direct,ev,flush,ftp,ftpack,handler,
- mqtt_client,mqtt_message,pickle,server]
- 2> put(context,#cx{session=10}).
- undefined
- 3> n2o:session(user,maxim).
- maxim
- 4> ets:tab2list(cookies).
- [{{10,user},
- <<"/">>,
- {1504,977449,476430},
- {{2017,9,9},{20,32,29}},
- maxim}]
- </code></figure>
- <h4>session(Key) -> term().</h4>
- <p>Gets a Value by any Key.</p>
- </section>
- <section>
- <h3>PICKLE</h3>
- <p>Call this function for changeable at runtime term pickling.</p>
- <h4>pickle(term()) -> binary().</h4>
- <h4>depickle(binary()) -> term().</h4>
- </section>
- <section>
- <p>This module may refer to:
- <a href="http://erlang.org/doc/man/io.html">io</a></b>,
- <a href="http://erlang.org/doc/man/ets.html">ets</a></b>,
- <a href="n2o_async.htm">n2o_asynrc</a></b>,
- <a href="n2o_vnode.htm">n2o_vnode</a></b>,
- <a href="n2o_proto.htm"><b>n2o_proto</b></a>.
- </p>
- </section>
- </main>
- <footer>
- 2005—2017 © Synrc Research Center
- </footer>
- </body>
- </html>
|