diff --git a/content/documentation/api.html b/content/documentation/api.html
index 9bf0d64..92bc801 100644
--- a/content/documentation/api.html
+++ b/content/documentation/api.html
@@ -20,6 +20,8 @@
* Class <%= my_lib_link_to "api/uri" %>
* Class <%= my_lib_link_to "api/nameAddrHeader" %>
* Class <%= my_lib_link_to "api/refer_subscriber" %>
+* Class <%= my_lib_link_to "api/subscriber" %>
+* Class <%= my_lib_link_to "api/notifier" %>
* <%= my_lib_link_to "api/node_websocket" %>
* <%= my_lib_link_to "api/ua_configuration_parameters" %>
* <%= my_lib_link_to "api/events" %>
diff --git a/content/documentation/api/notifier.html b/content/documentation/api/notifier.html
new file mode 100644
index 0000000..91c3469
--- /dev/null
+++ b/content/documentation/api/notifier.html
@@ -0,0 +1,157 @@
+---
+title: JsSIP.Notifier
+link_text: "@JsSIP.Notifier@"
+---
+
+h1. Class @JsSIP.Notifier@
+
+The class @JsSIP.Notifier@ represents a NOTIFY dialog.
+The dialog receive sequence of SUBSCRIBE messages and send NOTIFY messages.
+
+* <%= link_to "Instance Attributes", "#section_attributes" %>
+** <%= link_to "state", "#attribute_state" %>
+** <%= link_to "id", "#attribute_id" %>
+** <%= link_to "data", "#attribute_data" %>
+* <%= link_to "Instance Methods", "#section_methods" %>
+** <%= link_to "start()", "#method_start" %>
+** <%= link_to "setActiveState()", "#method_setActiveState" %>
+** <%= link_to "notify()", "#method_notify" %>
+** <%= link_to "terminate()", "#method_terminate" %>
+* <%= link_to "Events", "#section_events" %>
+** <%= link_to "subscribe", "#event_subscribe" %>
+** <%= link_to "terminated", "#event_terminated" %>
+
+h2(#section_attributes). Instance Attributes
+
+h3(#attribute_state). <%= my_lib_api_method 'state' %>
+
+@number@ The notifier dialog state.
+
+h4(#notifier_dialog_states). Notifier states
+
+|_.Constant|_.Value|_.Description|
+|@STATE_PENDING@|0|Send NOTIFY with Subscription-State: pending|
+|@STATE_ACTIVE@|1|Send NOTIFY with Subscription-State: active|
+|@STATE_TERMINATED@|2|Send NOTIFY with Subscription-State: terminated|
+
+h3(#attribute_id). <%= my_lib_api_method 'id' %>
+
+The Dialog id structure {@call_id@, @local_tag@, @remote_tag@} associated to this session.
+
+
+h3(#attribute_data). <%= my_lib_api_method 'data' %>
+
+Custom session empty @Object@ for application usage. The developer can add here custom attribute/value pairs.
+
+h2(#section_methods). Instance Methods
+
+
+h3(#method_start). <%= my_lib_api_method 'start()' %>
+
+Please call after creating the Notifier instance and setting the event handlers.
+
+h3(#method_setActiveState). <%= my_lib_api_method 'setActiveState()' %>
+
+Switch pending dialog state to active.
+
+h3(#method_notify). <%= my_lib_api_method 'notify(body)' %>
+
+Send the initial and subsequent notify request.
+
+<%= my_lib_api_parameters({
+ "body" => "Optional @String@ String representing the body of the NOTIFY."
+ }) %>
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+ let body = JSON.stringify({ temperature: 18, precipitation: 6, wind: 12 });
+ notifier.notify(body);
+
+CODE_END
+
+h3(#method_terminate). <%= my_lib_api_method 'terminate(body, reason,retryAfter)' %>
+
+Terminate. (Send the final NOTIFY request).
+
+<%= my_lib_api_parameters({
+ "body" => "Optional @String@ String representing the body of the NOTIFY.",
+ "reason" => "Optional @String@ parameter of header Subscription-State",
+ "retryAfter" => "Optional @Number@ parameter of header Subsription-State"
+ }) %>
+
+h2(#section_events). Events
+
+@JsSIP.Notifier@ class defines a series of events. Each of them allow callback functions registration in order to let the user execute a function for each given stimulus.
+
+h3(#event_subscribe). @subscribe@
+
+Fired when receive SUBSCRIBE (includes initial SUBSCRIBE)
+
+h4. Parameters
+
+<%= my_lib_api_parameters({
+ "isUnsubscribe" => "@Boolean@ If receive SUBSCRIBE with Expires value 0.",
+ "subscribe" => "#{my_lib_link_to "incomingRequest"} instance representing the incoming SUBSCRIBE SIP message.",
+ "body" => "String representing the SIP message body",
+ "contentType" => "@String@ representing the SIP SUBSCRIBE message Content-Type header field value."
+}) %>
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+notifier.on('subscribe', function(isUnsubscribe, subscribe, body, contentType)
+{
+ if (isUnsubscribe)
+ {
+ notifier.terminate();
+ }
+ else
+ {
+ notifier.notify({ temperature: 14 });
+ }
+});
+
+CODE_END
+
+h3(#event_terminated). @terminated@
+
+Fired when Notifier dialog is terminated.
+
+h4. Parameters
+
+<%= my_lib_api_parameters({
+ "terminationCode" => "@Number@ Termination code. See below.",
+ "sendFinalNotify" => "@Boolean@ If need send final NOTIFY. @true@ only for case when subscription is expires"
+}) %>
+
+
+h4(#subscription_dialog_termination_codes). Subscriber termination codes
+
+|_.Constant|_.Value|_.Description|
+|@NOTIFY_RESPONSE_TIMEOUT@|0|NOTIFY transaction response timeout.|
+|@NOTIFY_TRANSPORT_ERROR@|1|NOTIFY transaction transport error.|
+|@NOTIFY_NON_OK_RESPONSE@|2|Receive error response code.|
+|@NOTIFY_FAILED_AUTHENTICATION@|3|NOTIFY Authentication failure.|
+|@SEND_FINAL_NOTIFY@|4|Send NOTIFY with Subscription-State: terminated.|
+|@RECEIVE_UNSUBSCRIBE@|5|Receive SUBSCRIBE with Expires: 0|
+|@SUBSCRIPTION_EXPIRED@|6|Subscription is expired.|
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+notifier.on('terminated', function(terminationCode, sendFinalNotify)
+{
+ console.log('notifier: fired terminated event')
+ if (sendFinalNotify)
+ {
+ // Can be with or without body.
+ // reason must be "timeout" for the case.
+ notifier.terminate(null, "timeout");
+ }
+});
+
+CODE_END
diff --git a/content/documentation/api/subscriber.html b/content/documentation/api/subscriber.html
new file mode 100644
index 0000000..63c662e
--- /dev/null
+++ b/content/documentation/api/subscriber.html
@@ -0,0 +1,174 @@
+---
+title: JsSIP.Subscriber
+link_text: "@JsSIP.Subscriber@"
+---
+
+h1. Class @JsSIP.Subsciber@
+
+The class @JsSIP.Subscriber@ represents a SUBSCRIBE dialog.
+The dialog send sequence of SUBSCRIBE messages and receive NOTIFY messages.
+
+* <%= link_to "Instance Attributes", "#section_attributes" %>
+** <%= link_to "state", "#attribute_state" %>
+** <%= link_to "id", "#attribute_id" %>
+** <%= link_to "data", "#attribute_data" %>
+* <%= link_to "Instance Methods", "#section_methods" %>
+** <%= link_to "subscribe()", "#method_subscribe" %>
+** <%= link_to "terminate()", "#method_terminate" %>
+* <%= link_to "Events", "#section_events" %>
+** <%= link_to "accepted", "#event_accepted" %>
+** <%= link_to "pending", "#event_pending" %>
+** <%= link_to "active", "#event_active" %>
+** <%= link_to "notify", "#event_notify" %>
+** <%= link_to "terminated", "#event_terminated" %>
+
+
+h2(#section_attributes). Instance Attributes
+
+
+h3(#attribute_state). <%= my_lib_api_method 'state' %>
+
+@number@ The subscription dialog state.
+
+h4(#subscription_dialog_states). Subscriber states
+
+|_.Constant|_.Value|_.Description|
+|@STATE_PENDING@|0|Received NOTIFY with Subscription-State: pending|
+|@STATE_ACTIVE@|1|Recevied NOTIFY with Subscription-State: active|
+|@STATE_TERMINATED@|2|Received NOTIFY with Subscription-State: terminated|
+|@STATE_INIT@|3|This is state after creation.|
+|@STATE_NOTIFY_WAIT@|4|This is the state after sending the initial SUBSCRIBE|
+
+
+h3(#attribute_id). <%= my_lib_api_method 'id' %>
+
+The Dialog id structure {@call_id@, @local_tag@, @remote_tag@} associated to this session.
+
+
+h3(#attribute_data). <%= my_lib_api_method 'data' %>
+
+Custom session empty @Object@ for application usage. The developer can add here custom attribute/value pairs.
+
+h2(#section_methods). Instance Methods
+
+
+h3(#method_subscribe). <%= my_lib_api_method 'subscribe(body)' %>
+
+Send the initial (non-fetch) and subsequent subscribe.
+
+h4. Parameters
+
+<%= my_lib_api_parameters({
+ "body" => "Optional @String@ String representing the body of the SUBSCRIBE."
+}) %>
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+subscriber.subscribe('Hello');
+
+CODE_END
+
+h3(#method_terminate). <%= my_lib_api_method 'terminate(body)' %>
+
+Send un-subscribe or fetch-subscribe (with Expires: 0).
+
+h4. Parameters
+
+<%= my_lib_api_parameters({
+ "body" => "Optional @String@ String representing the body of the SUBSCRIBE."
+}) %>
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+subscriber.terminate();
+
+CODE_END
+
+h2(#section_events). Events
+
+@JsSIP.Subsciber@ class defines a series of events. Each of them allow callback functions registration in order to let the user execute a function for each given stimulus.
+
+
+h3(#event_accepted). @accepted@
+
+Fired once when initial SUBSCRIBE OK received.
+Next after initial SUBSCRIBE according specification can be send only after the event
+
+Note: If you send initial SUBSCRIBE and immediately next SUBSCRIBE.
+the next subscribe will be enqueued and send automatically after the event.
+
+h3(#event_pending). @pending@
+
+Fired once when receive NOTIFY with Subscription-State: pending.
+
+h3(#event_active). @active@
+
+Fired once when receive NOTIFY with Subscription-State: active.
+
+h3(#event_notify). @notify@
+
+Fired when receive NOTIFY
+
+h4. Parameters
+
+<%= my_lib_api_parameters({
+ "isFinal" => "@Boolean@ If receive NOTIFY with Subscription-State: terminated.",
+ "notify" => "#{my_lib_link_to "incomingRequest"} instance representing the incoming NOTIFY SIP message.",
+ "body" => "String representing the SIP message body",
+ "contentType" => "@String@ representing the SIP NOTIFY message Content-Type header field value."
+}) %>
+
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+subscriber.on('notify', function(isFinal, notify, body, contentType)
+{
+ console.log('received NOTIFY', isFinal, body);
+});
+
+CODE_END
+
+
+
+h3(#event_terminated). @terminated@
+
+Fired once when receive NOTIFY with Subscription-State: terminated.
+
+h4. Parameters
+(terminationCode, reason, retryAfter)
+<%= my_lib_api_parameters({
+ "terminatedCode" => "@Number@ terminated code. See below.",
+ "reason" => "@String@ Value of optional NOTIFY Subscription-State: terminated parameter @reason@",
+ "retryAfter" => "@Number@ Value of optional NOTIFY Subscription-State: terminated parameter @retry-after@",
+}) %>
+
+h4(#subscription_dialog_termination_codes). Subscriber termination codes
+
+|_.Constant|_.Value|_.Description|
+|@SUBSCRIBE_RESPONSE_TIMEOUT@|0|SUBSCRIBE transaction response timeout|
+|@SUBSCRIBE_TRANSPORT_ERROR@|1|SUBSCRIBE transaction transport error|
+|@SUBSCRIBE_NON_OK_RESPONSE@|2|SUBSCRIBE transaction response code >= 300|
+|@SUBSCRIBE_BAD_OK_RESPONSE@|3|Error during dialog creation using received OK response|
+|@SUBSCRIBE_FAILED_AUTHENTICATION@|4|SUBSCRIBE authentication failed|
+|@UNSUBSCRIBE_TIMEOUT@|5|Missed response to sent SUBSCRIBE with Exprires: 0|
+|@RECEIVE_FINAL_NOTIFY@|6|Received NOTIFY with Subscription-State: terminated|
+|@RECEIVE_BAD_NOTIFY@|7|Received NOTIFY without mandatory Subscription-State or Event headers|
+
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+subscriber.on('terminated', function(terminationCode, reason, retryAfter){
+ if( terminationCode === subscriber.C.RECEIVE_FINAL_NOTIFY)
+ {
+ console.log(`receive final NOTIFY. reason="${reason}" retry-after=${retryAfter}`);
+ }
+});
+CODE_END
diff --git a/content/documentation/api/ua.html b/content/documentation/api/ua.html
index 65845ba..bf8bcdb 100644
--- a/content/documentation/api/ua.html
+++ b/content/documentation/api/ua.html
@@ -22,6 +22,8 @@
** <%= link_to "isConnected()", "#method_isConnected" %>
** <%= link_to "get()", "#method_get" %>
** <%= link_to "set()", "#method_set" %>
+** <%= link_to "subscribe()", "#method_subscribe" %>
+** <%= link_to "notify()", "#method_notify" %>
* <%= link_to "Events", "#section_events" %>
** <%= link_to "connecting", "#event_connecting" %>
** <%= link_to "connected", "#event_connected" %>
@@ -34,6 +36,7 @@
** <%= link_to "newMessage", "#event_newMessage" %>
** <%= link_to "newOptions", "#event_newOptions" %>
** <%= link_to "sipEvent", "#event_sipEvent" %>
+** <%= link_to "newSubscribe", "#event_newSubscribe" %>
@@ -303,7 +306,115 @@
"value" => "New value."
}) %>
+h3(#method_subscribe). <%= my_lib_api_method 'subscribe(target, eventName, accept, options)' %>
+Create subscriber. <%= my_lib_link_to "subscriber" %> representing the subscriber dialog.
+See subscriber definition in RFC 3265 3.1
+
+Returns @Object@
+
+<%= my_lib_api_parameters({
+ "target" => "Destination of the request. @String@ representing a destination username or a complete SIP URI, or a #{my_lib_link_to "uri"} instance.",
+ "eventName" => "@String@ representing the SUBSCRIBE event name.",
+ "accept" => "@String@ representing value of Accept header",
+ "options" => "Optional @Object@ with extra parameters (see below)."
+}) %>
+
+h4. Fields in @options@ Object
+
+<%= my_lib_api_parameters({
+ "expires" => "Optional @Number@ (in seconds) value. Default 900.",
+ "contentType" => "@String@ representing the content-type of the SUBSCRIBE body.",
+ "allowEvents" => "Optional @String@ representing Allow-Events header value. See RFC 3265 3.3.7",
+ "params" => "@Object@ If set will have priority over ua configuration parameters. Can be used: to_uri, to_display_name, from_uri, from_display_name, cseq.",
+ "extraHeaders" => "Optional @Array@ of @Strings@ with extra SIP headers for each SUBSCRIBE request.",
+}) %>
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+var target = 'alice';
+var eventName = 'foo';
+var accept = 'application/json, plain/text';
+var expires = 600; // in seconds
+var contentType = 'application/json'
+var params = null;
+
+/*
+ Params are optional and are used if domain or from-user differ from those used in REGISTER.
+
+ var params = {
+ to_uri: new JsSIP.URI('sip', 'alice', 'example.com'),
+ to_display_name: null,
+ from_uri: new JsSIP.URI('sip', 'bob', 'example.com'),
+ from_display_name: null,
+}
+*/
+
+var subscriber;
+
+try {
+ subscriber = ua.subscribe(
+ target,
+ eventName,
+ accept, {
+ expires,
+ contentType,
+ params
+ });
+} catch (e) {
+ console.log('Error: cannot create subscriber', e);
+}
+
+CODE_END
+
+h3(#method_notify). <%= my_lib_api_method 'notify(subscribe, contentType, options)' %>
+
+Create notifier. <%= my_lib_link_to "notifier" %> representing the notifier dialog.
+See notifier definition in RFC 3265 3.2
+
+Returns @Object@
+
+<%= my_lib_api_parameters({
+ "subscribe" => "#{my_lib_link_to "incomingRequest"} instance of the received SUBSCRIBE request.",
+ "contentType" => "@String@ representing the content-type of the NOTIFY body.",
+ "options" => "Optional @Object@ with extra parameters (see below)."
+}) %>
+
+h4. Fields in @options@ Object
+
+<%= my_lib_api_parameters({
+ "penging" => "Optional @Boolean@ Set initial dialog state as @pending@. Default value is @false@",
+ "allowEvents" => "Optional @String@ representing Allow-Events header value. See RFC 3265 3.3.7",
+ "extraHeaders" => "Optional @Array@ of @Strings@ with extra SIP headers for each NOTIFY request.",
+}) %>
+
+h4. Example
+
+CODE_BEGIN "javascript"
+
+ua.on('newSubscribe', (e) => {
+ var subscribe = e.request;
+ let event = subscribe.parseHeader('event');
+ if (event !== 'foo') { // Check that we understand the event.
+ console.log(`Received SUBSCRIBE with unsupported event ${event}`);
+ subscribe.reply(489); // "Bad Event"
+ return;
+ }
+
+ var contentType = 'application/json';
+ var pending = true;
+ var notifier;
+
+ try {
+ notifer = ua.notify(subscribe, contentType, { pending });
+ } catch(e){
+ console.log('Error: cannot create notifier', e);
+ }
+});
+
+CODE_END
h2(#section_events). Events
@@ -486,6 +597,27 @@
}) %>
+h4. @event@ parameter
+
+<%= my_lib_api_parameters({
+ "event" => "'event-type' defined in the Event header field.",
+ "params" => "@Object@ containing the parameters received in the Event header field."
+}) %>
+
+
+h3(#event_newSubscribe). newSubscribe
+
+Fired for an incoming out of dialog SUBSCRIBE request.
+
+
+h4. Event @data@ fields
+
+<%= my_lib_api_parameters({
+ "event" => "@Event@ instance. See below.",
+ "request" => "#{my_lib_link_to "incomingRequest"} instance of the received SUBSCRIBE request."
+}) %>
+
+
h4. @event@ parameter
<%= my_lib_api_parameters({