This plugin provides full support to implement an Event State Compositor, according to RFC3903. It uses by default the built-in RAM-only store, but can be configured to use any other database implementing callback sip_publish_store/2.
PUBLISH will also be added to default generared Allow headers.
None
Option | Default | Description |
---|---|---|
sip_event_compositor_default_expires | 60 (secs) | Default expiration for stored events |
find(App::nksip:srv_id()|term(), AOR::nksip:aor(), Tag::binary()) ->
{ok, #reg_publish{}} | not_found | {error, term()}.
Finds a stored published information.
request(nksip:request()) ->
nksip:sipreply().
Call this function to process and incoming PUBLISH request. It returns an appropiate response, depending on the registration result.
For example, you could implement the following sip_publish/2 callback function:
sip_publish(Req, _Call) ->
case nksip_request:meta(domain, Req) of
{ok, <<"nksip">>} -> {reply, nksip_event_compositor:process(Req)};
_ -> {reply, forbidden}
end.
- If No Sip-If-Match header is found:
- If we have a body, the server will generate a Tag, and store the boy under this AOR and Tag.
- If we have no body, the request fails
- If Sip-If-Match header is found:
- If we alredy had a body stored with this Tag, and Expires=0, it is deleted
- If Expires>0, and we have no body, the content is refreshed
- If Expires>0, and we have a body, the content is updated
- If we had no body stored, the request fails
clear(nksip:srv_name()|nksip:srv_id()) ->
ok | callback_error | service_not_found.
Clear all stored records by a Service.
You can implement any of these callback functions in your Service callback module.
sip_event_compositor_store(StoreOp, AppId) ->
[RegPublish] | ok | not_found when
StoreOp :: {get, AOR, Tag} | {put, AOR, Tag, RegPublish, TTL} |
{del, AOR, Tag} | del_all,
AppId :: nksip:srv_id(),
AOR :: nksip:aor(),
Tag :: binary(),
RegPublish :: nksip_event_compositor:reg_publish(),
TTL :: integer().
Called when a operation database must be done on the publisher database. By default the in-memory database is used, but you can impement it to use your own database.
The possible values for Op and their allowed reply are:
Op | Response | Comments |
---|---|---|
{get, AOR, Tag} | RegPublish | not_found | Retrieve store information this AOR , AppId and Tag . |
{put, AOR, Tag, RegPublish, TTL} | ok | Store this information this AOR , AppId and Tag . The record must be automatically deleted after TTL seconds. |
{del, AOR, Tag} | ok | not_found | Delete stored information for this AOR , AppId and Tag , returning ok or not_found if it is not found. |
del_all | ok | Delete all stored information for this AppId . |
See the default implementation as a basis.
-module(example).
-include_lib("nksip/include/nksip.hrl").
-include_lib("nksip/plugins/include/nksip_event_compositor.hrl").
-compile([export_all]).
start() ->
{ok, _} = nksip:start(client1, [
{sip_from, "sip:client1@nksip"},
{sip_local_host, "localhost"},
{sip_listen, "sip:all:5060, sips:all:5061"}
]),
{ok, _} = nksip:start(server, [
{sip_from, "sip:server@nksip"},
{sip_local_host, "127.0.0.1"},
{sip_no_100, true},
{sip_events, "nkpublish"}
{plugins, [nksip_event_compositor]},
{sip_listen, "sip:all:5070, sips:all:5071"}
]).
stop() ->
ok = nksip:stop(client1),
ok = nksip:stop(server).
test() ->
{ok, 200, [{sip_etag, ETag1}, {expires, 5}]} =
nksip_uac:publish(client1, "sip:[email protected]:5070",
[{event, "nkpublish"}, {expires, 5}, {body, <<"data1">>}]),
AOR = {sip, <<"user1">>, <<"127.0.0.1">>},
{ok, #reg_publish{data = <<"data1">>}} = nksip_event_compositor:find(server, AOR, ETag1),
% This ETag1 is not at the server
{ok, 412, []} = nksip_uac:publish(client1, "sip:[email protected]:5070",
[{event, "nkpublish"}, {sip_if_match, <<"other">>}]),
{ok, 200, [{sip_etag, ETag1}, {expires, 0}]} =
nksip_uac:publish(client1, "sip:[email protected]:5070",
[{event, "nkpublish"}, {expires, 0}, {sip_if_match, ETag1}]),
not_found = nksip_event_compositor:find(server, AOR, ETag1),
{ok, 200, [{sip_etag, ETag2}, {expires, 60}]} =
nksip_uac:publish(client1, "sip:[email protected]:5070",
[{event, "nkpublish"}, {expires, 60}, {body, <<"data2">>}]),
{ok, #reg_publish{data = <<"data2">>}} = nksip_event_compositor:find(server, AOR, ETag2),
{ok, 200, [{sip_etag, ETag2}, {expires, 1}]} =
nksip_uac:publish(client1, "sip:[email protected]:5070",
[{event, "nkpublish"}, {expires, 1}, {sip_if_match, ETag2}, {body, <<"data3">>}]),
{ok, #reg_publish{data = <<"data3">>}} = nksip_event_compositor:find(server, AOR, ETag2),
ok.
%%%%%%%%%%%%%%%%%%%%%%% CallBacks (we need no callback module) %%%%%%%%%%%%%%%%%%%%%