<html>
<head>
<base href="https://wiki.asterisk.org/wiki">
<link rel="stylesheet" href="/wiki/s/2033/1/7/_/styles/combined.css?spaceKey=TOP&forWysiwyg=true" type="text/css">
</head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
<h2><a href="https://wiki.asterisk.org/wiki/display/TOP/Support+for+subscriptions+to+and+from+external+entities">Support for subscriptions to and from external entities</a></h2>
<h4>Page <b>edited</b> by <a href="https://wiki.asterisk.org/wiki/display/~mmichelson">Mark Michelson</a>
</h4>
<br/>
<h4>Changes (8)</h4>
<div id="page-diffs">
<table class="diff" cellpadding="0" cellspacing="0">
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >class SubscriptionData <br>{ <br></td></tr>
<tr><td class="diff-changed-lines" >int <span class="diff-changed-words">expiration<span class="diff-added-chars"style="background-color: #dfd;">Seconds</span>;</span> <br></td></tr>
<tr><td class="diff-unchanged" > string recipient; <br> string sender; <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;"> PublishedState state; <br></td></tr>
<tr><td class="diff-unchanged" >}; <br>{newcode} <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >class SubscriptionResponse <br>{ <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">SubscriptionResult<span class="diff-added-chars"style="background-color: #dfd;">Code</span></span> result; <br></td></tr>
<tr><td class="diff-unchanged" > Subscription *handler; <br>}; <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">{code} <br></td></tr>
<tr><td class="diff-unchanged" > <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">{{result}} can be used by the subscriber to determine if a component accepted the subscription request. If a component has not accepted the request, then {{result}} can also be used to determine why the subscription request was not accepted. The {{handler}} is a proxy that will be used by the subscriber to send any further information regarding the subscription. Here is the slice for {{SubscriptionResult}}: <br> <br>{code:language=slice} <br></td></tr>
<tr><td class="diff-unchanged" >enum SubscriptionResultCode <br>{ <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" > NotSupported <br>}; <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;"> <br>class SubscriptionResult <br>{ <br> SubscriptionResultCode reason; <br>}; <br></td></tr>
<tr><td class="diff-unchanged" >{code} <br> <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Specific subscription types may define subclasses of {{SubscriptionResult}} that contain type-specific reasons for failure. The {{Subscription}} class is defined as follows: <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">{{result}} can be used by the subscriber to determine if a component accepted the subscription request. If a component has not accepted the request, then {{result}} can also be used to determine why the subscription request was not accepted. The {{handler}} is a proxy that will be used by the subscriber to send any further information regarding the subscription. Specific subscription types may define subclasses of {{SubscriptionResponse}} that contain more detailed reasons for rejection beyond those defined in {{SubscriptionResultCode}}. The {{Subscription}} class is defined as follows: <br></td></tr>
<tr><td class="diff-unchanged" > <br>{code:language=slice} <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
</table>
</div> <h4>Full Content</h4>
<div class="notificationGreySide">
<h1><a name="Supportforsubscriptionstoandfromexternalentities-Concept"></a>Concept</h1>
<p>Subscriptions in AsteriskSCF may come in many flavors. One obvious one would be SIP subscriptions as defined in <a href="http://www.ietf.org/rfc/rfc3265.txt" class="external-link" rel="nofollow">RFC 3265</a>. However, subscriptions may be started via other protocols or via administration. Therefore, subscription support needs to be written in such a way that it is protocol-agnostic. While Asterisk SCF needs to be able to understand protocol-specific methods of subscribing to resources, it is not within the scope of Asterisk SCF to make decisions regarding such matters. With this in mind, the majority of session-oriented protocols that support subscriptions of some sort will make use of a <tt>SubscriptionBroker</tt> in order to make it known what is happening. The <tt>SubscriptionBroker</tt> is alerted whenever a subscription request arrives. It is up to the <tt>SubscriptionBroker</tt> to make the decision about how to handle such a request.</p>
<p>At the basis of all of this is the subscription itself. There are certain attributes present in all subscription types, and they are represented in a <tt>SubscriptionData</tt> class.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
class SubscriptionData
{
int expirationSeconds;
string recipient;
string sender;
};
]]></script>
</div></div>
<p>Note that a subscription type is not a member of the class. This is because specific types of subscriptions should be defined as subclasses of the SubscriptionData class. The PublishedState object is a subscription package-specific set of information that describes the current state of the subscription. For a presence subscription, for instance, this would convey the current presence state, like "available" or "busy."</p>
<h1><a name="Supportforsubscriptionstoandfromexternalentities-InboundSubscriptions"></a>Inbound Subscriptions</h1>
<p>We'll examine subscriptions from two different viewpoints: inbound and outbound. First, we'll inspect the <tt>SubscriptionBroker</tt> interface. This is used by a communications protocol that has received an inbound subscription request.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
interface SubscriptionBroker
{
SubscriptionResponse subscribe(SubscriptionData data, Subscriber *sub);
};
]]></script>
</div></div>
<p>When an inbound subscription is requested, the SubscriptionBroker is told of the request. The SubscriptionBroker is then responsible for finding an appropriate Asterisk SCF component to be able to handle the subscription request. Once the broker has determined which, if any, component is going to handle the subscription, then the SubscriptionBroker should create a SubscriptionResponse to return to the subscriber. The SubscriptionResponse class is defined as such:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
class SubscriptionResponse
{
SubscriptionResultCode result;
Subscription *handler;
};
enum SubscriptionResultCode
{
//XXX More reasons may need to be added here.
//This is primarily for illustrative purposes.
Success,
NotPermitted,
RecipientUnknown,
NotSupported
};
]]></script>
</div></div>
<p><tt>result</tt> can be used by the subscriber to determine if a component accepted the subscription request. If a component has not accepted the request, then <tt>result</tt> can also be used to determine why the subscription request was not accepted. The <tt>handler</tt> is a proxy that will be used by the subscriber to send any further information regarding the subscription. Specific subscription types may define subclasses of <tt>SubscriptionResponse</tt> that contain more detailed reasons for rejection beyond those defined in <tt>SubscriptionResultCode</tt>. The <tt>Subscription</tt> class is defined as follows:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
interface Subscription
{
void renew(SubscriptionData data);
void expire(SubscriptionData data);
void terminate(SubscriptionData data);
};
]]></script>
</div></div>
<p>Each of these methods notifies the subscription handler of changes to the subscription state. <tt>renew</tt> is mostly informational and alerts the subscription handler that the subscriber has extended his subscription beyond the initial expiration period. <tt>expire</tt> indicates that the subscription has been ended due to a failure to re-subscribe in time. The <tt>terminated</tt> method indicates that the subscriber has ended his subscription manually. Each method takes a <tt>SubscriptionData</tt> member so that the listener can identify which subscription the method call pertains to as well as to see potential differences made to the data.</p>
<p>One detail that has been glossed over is how the <tt>SubscriptionBroker</tt> gets a <tt>Subscription</tt> object to hand back to the subscriber. Any component capable of creating a <tt>Subscription</tt> will have a <tt>SubscriptionFactory</tt> interface exposed so that new <tt>Subscriptions</tt> may be requested.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
interface SubscriptionFactory
{
Subscription *createSubscription(SubscriptionData data);
};
]]></script>
</div></div>
<p>The listener must also be able to communicate with the subscriber. The means of doing this will be using the <tt>Subscriber</tt> interface. Recall that a proxy to a <tt>Subscriber</tt> was passed to the <tt>SubscriptionBroker</tt> in <tt>SubscriptionBroker::subscribe</tt>. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="toolbar: false; theme: Confluence; brush: java; gutter: false"><![CDATA[
interface Subscriber
{
void terminate();
void notify(PublishedState state);
};
]]></script>
</div></div>
<p>The <tt>terminate</tt> method is a method for a subscription handler to end a subscription. The <tt>notify</tt> method is used to indicate to the subscriber that the subscription state has been updated.</p>
<h1><a name="Supportforsubscriptionstoandfromexternalentities-OutboundSubscriptions"></a>Outbound Subscriptions</h1>
<p>Outbound subscriptions mostly work the same way as inbound ones, except for a few key differences. First off, the role of subscriber and subscription handler is reversed. In other words, a custom-written user component will be the subscriber and the subscription handler will be a session-oriented protocol component such as SIP. Furthermore, there is no need to use a <tt>SubscriptionBroker</tt> since a <tt>SubscriptionFactory</tt> may be used directly.</p>
<h1><a name="Supportforsubscriptionstoandfromexternalentities-SimpleExamples"></a>Simple Examples</h1>
<p>So let's consider a typical sequence of events. Lifelines in the sequence diagrams are color-coded to indicate the owning component. Lifelines with the same color are owned by the same component.</p>
<p><span class="image-wrap" style=""><img src="/wiki/download/attachments/9568785/InboundSubscription.png?version=1&modificationDate=1294245916008" style="border: 0px solid black" /></span></p>
<p>This is a one-legged inbound subscription scenario. Whatever resource Bob wishes to subscribe to is handled entirely by a component within Asterisk SCF. Notifications of state change originate in the <tt>UserComponent</tt> in such a situation. Another common scenario will be that Asterisk SCF sets up a bridge between two external entities. Below are two methods a user might use in order to accomplish the task.</p>
<p><span class="image-wrap" style=""><img src="/wiki/download/attachments/9568785/SubscriptionBridge.png?version=1&modificationDate=1294245916077" style="border: 0px solid black" /></span></p>
<p>This is the stateless version, where the <tt>UserComponent</tt> is only involved in the setup. Once the subscription is established, The <tt>UserComponent</tt> never sees any more of the messages. The <tt>UserComponent</tt> is able to make initial decisions regarding how to route the subscription, as well as whether to permit the subscription's acceptance.</p>
<p><span class="image-wrap" style=""><img src="/wiki/download/attachments/9568785/SubscriptionBridge2.png?version=1&modificationDate=1294245916119" style="border: 0px solid black" /></span></p>
<p>This is the stateful version, where the <tt>UserComponent</tt> intercepts all messages passed during the lifetime of the subscription. The way it does this is to create a <tt>Subscription</tt> and a <tt>Subscriber</tt> that the respective SIP components communicate with.</p>
</div>
<div id="commentsSection" class="wiki-content pageSection">
<div style="float: right;">
<a href="https://wiki.asterisk.org/wiki/users/viewnotifications.action" class="grey">Change Notification Preferences</a>
</div>
<a href="https://wiki.asterisk.org/wiki/display/TOP/Support+for+subscriptions+to+and+from+external+entities">View Online</a>
|
<a href="https://wiki.asterisk.org/wiki/pages/diffpagesbyversion.action?pageId=9568785&revisedVersion=17&originalVersion=16">View Changes</a>
|
<a href="https://wiki.asterisk.org/wiki/display/TOP/Support+for+subscriptions+to+and+from+external+entities?showComments=true&showCommentArea=true#addcomment">Add Comment</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>