<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 (43)</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" >Subscriptions in AsteriskSCF may come in many flavors. One obvious one would be SIP subscriptions as defined in [RFC 3265|http://www.ietf.org/rfc/rfc3265.txt]. 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 listener interface in order to make it known what is happening. Listeners are alerted whenever a subscription request arrives. It is up to the listener to make the decision about how to handle such a request. If a subscription is accepted, then the listener that accepted the subscription will notify the Asterisk SCF component responsible for communicating with the subscriber his such that any further events regarding the subscription can be directed to the appropriate listener. <br> <br></td></tr>
<tr><td class="diff-changed-lines" >At the basis of all of this is the subscription itself. There is no such thing as an all-encompassing subscription class since all subscriptions will have data that is specific to the subscription type. However, there are certain attributes present in all subscription types, and they are represented in a <span class="diff-changed-words"><span class="diff-added-chars"style="background-color: #dfd;">{{</span>SubscriptionData<span class="diff-added-chars"style="background-color: #dfd;">}}</span></span> class. <br></td></tr>
<tr><td class="diff-unchanged" > <br>{newcode:language=slice} <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >h1. Inbound Subscriptions <br> <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">Subscriptions are divided into inbound and outbound types. First, we'll inspect the InboundSubscriptionListener interface. This is used by a communications protocol that has received an inbound subscription request. <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">We'll examine subscriptions from two different viewpoints: inbound and outbound. First, we'll inspect the {{SubscriptionBroker}} interface. This is used by a communications protocol that has received an inbound subscription request. <br></td></tr>
<tr><td class="diff-unchanged" > <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">new</span>code:language=slice}</span> <br></td></tr>
<tr><td class="diff-changed-lines" >interface <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">InboundSubscriptionListener</span> <span class="diff-added-words"style="background-color: #dfd;">SubscriptionBroker</span> <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;"> InboundSubscriptionResponse requested(SubscriptionData data, InboundSubscription *sub); <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;"> SubscriptionResponse subscribe(SubscriptionData data, Subscriber *sub); <br></td></tr>
<tr><td class="diff-unchanged" >}; <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">new</span>code}</span> <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;">When an inbound subscription is requested, InboundSubscriptionListeners are told of the request one-by-one until one accepts the request. The SubscriptionResponse class is defined as such: <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">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: <br></td></tr>
<tr><td class="diff-unchanged" > <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">new</span>code:language=slice}</span> <br></td></tr>
<tr><td class="diff-changed-lines" >class <span class="diff-changed-words"><span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">Inbound</span>SubscriptionResponse</span> <br></td></tr>
<tr><td class="diff-unchanged" >{ <br> SubscriptionResult result; <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">InboundSubscriptionHandler</span> <span class="diff-added-words"style="background-color: #dfd;">Subscription</span> *handler; <br></td></tr>
<tr><td class="diff-unchanged" >}; <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">{code} <br></td></tr>
<tr><td class="diff-unchanged" > <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. 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" > SubscriptionResultCode reason; <br>}; <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">new</span>code}</span> <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;">From the InboundSubscriptionResponse class, the potential subscriber can tell if the subscription should be handled by the listener by inspecting the "reason" member of the InboundSubscriptionResponse. Specific subscription types may define subclasses of SubscriptionResult that contain type-specific reasons for failure. The InboundSubscriptionHandler proxy in the SubscriptionResponse is used to communicate further changes to the listener of the subscription. The interface is defined below: <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">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-unchanged" > <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">new</span>code:language=slice}</span> <br></td></tr>
<tr><td class="diff-changed-lines" >interface <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">InboundSubscriptionHandler</span> <span class="diff-added-words"style="background-color: #dfd;">Subscription</span> <br></td></tr>
<tr><td class="diff-unchanged" >{ <br></td></tr>
<tr><td class="diff-changed-lines" >void <span class="diff-changed-words">renew<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">ed</span>(SubscriptionData</span> data); <br></td></tr>
<tr><td class="diff-changed-lines" >void <span class="diff-changed-words">expire<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">d</span>(SubscriptionData</span> data); <br></td></tr>
<tr><td class="diff-changed-lines" >void <span class="diff-changed-words">terminate<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">d</span>(SubscriptionData</span> data); <br></td></tr>
<tr><td class="diff-unchanged" >}; <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">new</span>code}</span> <br></td></tr>
<tr><td class="diff-unchanged" > <br></td></tr>
<tr><td class="diff-changed-lines" >Each of these methods notifies the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">listener</span> <span class="diff-added-words"style="background-color: #dfd;">subscription handler</span> of changes to the subscription state. <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">"renewed"</span> <span class="diff-added-words"style="background-color: #dfd;">{{renew}}</span> is mostly informational and alerts the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">listener</span> <span class="diff-added-words"style="background-color: #dfd;">subscription handler</span> that the subscriber has extended his subscription beyond the initial expiration period. <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">"expired"</span> <span class="diff-added-words"style="background-color: #dfd;">{{expire}}</span> indicates that the subscription has been ended due to a failure to re-subscribe in time. The <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">"terminated"</span> <span class="diff-added-words"style="background-color: #dfd;">{{terminated}}</span> method indicates that the subscriber has ended his subscription manually. Each method takes a <span class="diff-changed-words"><span class="diff-added-chars"style="background-color: #dfd;">{{</span>SubscriptionData<span class="diff-added-chars"style="background-color: #dfd;">}}</span></span> 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. <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;">The listener must also be able to communicate with the subscriber. The means of doing this will be using InboundSubscription, which is passed to the listener as part of InboundSubscriptionListener::requested(). <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">The listener must also be able to communicate with the subscriber. The means of doing this will be using the {{Subscriber}} interface. Recall that a proxy to a {{Subscriber}} was passed to the {{SubscriptionBroker}} in {{SubscriptionBroker::subscribe}}. <br></td></tr>
<tr><td class="diff-unchanged" > <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">new</span>code:language=slice}</span> <br></td></tr>
<tr><td class="diff-changed-lines" >interface <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">InboundSubscription</span> <span class="diff-added-words"style="background-color: #dfd;">Subscrber</span> <br></td></tr>
<tr><td class="diff-unchanged" >{ <br> void terminate(); <br> void notify(PublishedState state); <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;"> void addHandlers(InboundSubscriptionHandlerSeq listeners); <br> void removeHandlers(InboundSubscriptionHandlerSeq listeners); <br></td></tr>
<tr><td class="diff-unchanged" >}; <br></td></tr>
<tr><td class="diff-changed-lines" ><span class="diff-changed-words">{<span class="diff-deleted-chars"style="color:#999;background-color:#fdd;text-decoration:line-through;">new</span>code}</span> <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;">The "terminate" method is a method for a handler to end a subscription. The "notify" method is used to indicate to the subscriber that the subscription state has been updated. "addHandlers" and "removeHandlers" provides methods by which more components may listen for events on an established subscription. <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">The {{terminate}} method is a method for a subscription handler to end a subscription. The {{notify}} method is used to indicate to the subscriber that the subscription state has been updated. <br></td></tr>
<tr><td class="diff-unchanged" > <br>h1. Outbound Subscriptions <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">What we have so far allows for Asterisk SCF to communicate with an outside subscriber. But what about if an Asterisk SCF component wishes to subscribe to an outside entity? First off, AsteriskSCF will require the ability to take appropriate actions, such as subscribing, as well as renewing and canceling subscriptions. In other words, the items that the subscription listener listens for need to have corresponding actions that Asterisk SCF can itself make. For this, we have OutboundSubscription. <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">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, the method of using a {{SubscriptionBroker}} will be modified as well. For inbound subscriptions, a user-defined {{SubscriptionBroker}} is defined and called into by a subscriber in order to properly create a {{Subscription}}. For outbound scenarios, since the user component should already know which session-oriented protocol to be using based on the intended recipient of the subscription request, the user component will simply call into a {{SubscriptionBroker}} interface provided by the particular session-oriented protocol component. In this case, the {{SubscriptionBroker}} functions more like a factory. <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;">{newcode:language=slice} <br>class OutboundSubscription <br>{ <br> SubscriptionResult request(SubscriptionData data, OutboundSubscriptionHandler *handler); <br> void renew(SubscriptionData data); <br> void terminate(SubscriptionData data); <br> void addHandlers(OutboundSubscriptionHandlerSeq listeners); <br> void removeHandlers(OutboundSubscriptionHandlerSeq listeners); <br>}; <br>{newcode} <br> <br>The "request" method will be used to send an outbound subscription. The "renew" method will be used to renew a previously accepted subscription. The "terminate" method is used to end a subscription. <br>Once a subscription is established, Asterisk SCF will need a way of knowing when changes have been made to the state of the outbound subscription. For this, we have the OutboundSubscriptionHandler class. <br> <br>{newcode:language=slice} <br>interface OutboundSubscriptionHandler <br>{ <br> void terminated(OutboundSubscription *sub); <br> void notified(OutboundSubscription *sub, PublishedState state); <br>}; <br>{newcode} <br> <br>"terminated" is called if the entity to which we are subscribing terminates the subscription. "notified" is called when the entity to which we are subscribing changes its published state. <br></td></tr>
<tr><td class="diff-unchanged" >h1. Simple Examples <br>So let's consider a typical sequence of events: <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >1. Bob sends a SIP SUBSCRIBE to Asterisk SCF for a particular resource. <br>2. Asterisk SCF's SIP subscription component receives the incoming SUBSCRIBE. <br></td></tr>
<tr><td class="diff-changed-lines" >3. The SIP subscription component recognizes the event type and creates an appropriate SubscriptionData object, as well as a <span class="diff-added-words"style="background-color: #dfd;">corresponding</span> subclass of the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">InboundSubscription</span> <span class="diff-added-words"style="background-color: #dfd;">{{Subscriber}}</span> interface. <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">4. The SIP subscription component begins querying its InboundSubscriptionListeners using the InboundSubscriptionListener::requested() method. <br>5. InboundSubscriptionListenerA does not support the subscription type, but InboundSubscriptionListenerB does, so it indicates a successful response. Note that in the diagram, InboundSubscriptionListenerB also functions as the InboundSubscriptionHandler. <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;">4. The SIP subscription component queries the {{SubscriptionBroker}} to provide an appropriate {{Subscription}}. <br>5. The {{SubscriptionBroker}} finds an appropriate component to provide a {{Subscription}} and hands it off to the subscriber. <br></td></tr>
<tr><td class="diff-unchanged" >6. The SIP subscription component sends a 200 OK to Bob. <br></td></tr>
<tr><td class="diff-changed-lines" >7. The <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">InboundSubscriptionHandler</span> <span class="diff-added-words"style="background-color: #dfd;">{{Subscription}}</span> at some point in the future determines that the resource has undergone a change and so it <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">sends a notify() message to the InboundSubscription.</span> <span class="diff-added-words"style="background-color: #dfd;">calls {{Subscriber::notify()}}.</span> <br></td></tr>
<tr><td class="diff-changed-lines" >8. The <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">InboundSubscription</span> <span class="diff-added-words"style="background-color: #dfd;">subscriber</span> handles this situation by sending a SIP NOTIFY to Bob, to which Bob replies with a 200 OK. <br></td></tr>
<tr><td class="diff-unchanged" >9. Bob later decides that he no longer wishes to keep his subscription alive. He therefore sends a SUBSCRIBE with the Expires header set to 0. <br></td></tr>
<tr><td class="diff-changed-lines" >10. The SIP component receives this and sends the <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">terminated() message to the InboundSubscriptionHandler.</span> <span class="diff-added-words"style="background-color: #dfd;">{{Subscription::terminated()}} message.</span> <br></td></tr>
<tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">11. The SIP component destroys the InboundSubscription and sends a 200 OK to Bob. <br></td></tr>
<tr><td class="diff-unchanged" > <br>Now let's modify the situation a bit. In the new situation, Asterisk SCF does not manage Alice's presence, but it knows that it can subscribe to an external resource that is responsible for reporting Alice's presence. In such a situation, Asterisk SCF will act like a subscription "bridge" between Bob and Alice, necessitating both an inbound and outbound subscription to be used. The process starts much the same as before. Steps 1-4 are identical. We pick up with step 5. <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 listener interface in order to make it known what is happening. Listeners are alerted whenever a subscription request arrives. It is up to the listener to make the decision about how to handle such a request. If a subscription is accepted, then the listener that accepted the subscription will notify the Asterisk SCF component responsible for communicating with the subscriber his such that any further events regarding the subscription can be directed to the appropriate listener.</p>
<p>At the basis of all of this is the subscription itself. There is no such thing as an all-encompassing subscription class since all subscriptions will have data that is specific to the subscription type. However, 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 expiration;
string recipient;
string sender;
PublishedState state;
};
]]></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
{
SubscriptionResult result;
Subscription *handler;
};
]]></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. Here is the slice for <tt>SubscriptionResult</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[
enum SubscriptionResultCode
{
//XXX More reasons may need to be added here.
//This is primarily for illustrative purposes.
Success,
NotPermitted,
RecipientUnknown,
NotSupported
};
class SubscriptionResult
{
SubscriptionResultCode reason;
};
]]></script>
</div></div>
<p>Specific subscription types may define subclasses of <tt>SubscriptionResult</tt> that contain type-specific reasons for failure. 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>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 Subscrber
{
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, the method of using a <tt>SubscriptionBroker</tt> will be modified as well. For inbound subscriptions, a user-defined <tt>SubscriptionBroker</tt> is defined and called into by a subscriber in order to properly create a <tt>Subscription</tt>. For outbound scenarios, since the user component should already know which session-oriented protocol to be using based on the intended recipient of the subscription request, the user component will simply call into a <tt>SubscriptionBroker</tt> interface provided by the particular session-oriented protocol component. In this case, the <tt>SubscriptionBroker</tt> functions more like a factory.</p>
<h1><a name="Supportforsubscriptionstoandfromexternalentities-SimpleExamples"></a>Simple Examples</h1>
<p>So let's consider a typical sequence of events:</p>
<p><span class="image-wrap" style=""><img src="/wiki/download/attachments/9568785/InboundSubscription.png?version=1&modificationDate=1294178253864" style="border: 0px solid black" /></span></p>
<p>1. Bob sends a SIP SUBSCRIBE to Asterisk SCF for a particular resource.<br/>
2. Asterisk SCF's SIP subscription component receives the incoming SUBSCRIBE.<br/>
3. The SIP subscription component recognizes the event type and creates an appropriate SubscriptionData object, as well as a corresponding subclass of the <tt>Subscriber</tt> interface.<br/>
4. The SIP subscription component queries the <tt>SubscriptionBroker</tt> to provide an appropriate <tt>Subscription</tt>.<br/>
5. The <tt>SubscriptionBroker</tt> finds an appropriate component to provide a <tt>Subscription</tt> and hands it off to the subscriber.<br/>
6. The SIP subscription component sends a 200 OK to Bob.<br/>
7. The <tt>Subscription</tt> at some point in the future determines that the resource has undergone a change and so it calls <tt>Subscriber::notify()</tt>.<br/>
8. The subscriber handles this situation by sending a SIP NOTIFY to Bob, to which Bob replies with a 200 OK.<br/>
9. Bob later decides that he no longer wishes to keep his subscription alive. He therefore sends a SUBSCRIBE with the Expires header set to 0.<br/>
10. The SIP component receives this and sends the <tt>Subscription::terminated()</tt> message.</p>
<p>Now let's modify the situation a bit. In the new situation, Asterisk SCF does not manage Alice's presence, but it knows that it can subscribe to an external resource that is responsible for reporting Alice's presence. In such a situation, Asterisk SCF will act like a subscription "bridge" between Bob and Alice, necessitating both an inbound and outbound subscription to be used. The process starts much the same as before. Steps 1-4 are identical. We pick up with step 5.</p>
<p><span class="image-wrap" style=""><img src="/wiki/download/attachments/9568785/SubscriptionBridge.png?version=1&modificationDate=1293577159782" style="border: 0px solid black" /></span></p>
<p>5. An OutboundSubscriptionListener asks for the SipSubscriptionService to create an OutboundSubscription and calls OutboundSubscription::request().<br/>
7. The SIP subscription component sends an outbound SUBSCRIBE to the appropriate external resource.<br/>
8. At some point, the SIP subscription component receives a 200 OK for the outbound SUBSCRIBE.<br/>
9. The SIP subscription component returns a successful SubscriptionResult to the creator of the OutboundSubscription.<br/>
10. The InboundSubscriptionHandler can now successfully respond to the initial request() call.<br/>
11. The SIP subscription component sends a 200 OK to Bob.</p>
<p>At this point, Asterisk SCF serves as a subscription bridge, so to speak, between Bob and Alice. Notifications from Alice are intercepted by Asterisk SCF, and they can be sent out to Bob. If Bob, Alice, or Asterisk SCF decides to end the subscriptions, it can be done.</p>
<h1><a name="Supportforsubscriptionstoandfromexternalentities-LingeringQuestions%3A"></a>Lingering Questions:</h1>
<p>1. In the above example, the SIP component has a preexisting set of InboundSubscriptionListeners to send requests to. Where does this come from?<br/>
2. Should there be a distinction made between InboundSubscriptionListeners that actually have the ability to make decisions based on an incoming subscription request and those that simply listen passively for events on subscriptions? My initial thought is that to the component calling the listener methods, he's not really going to care one way or the other, and so a distinction shouldn't be made. But from the viewpoint of usability and clarity, a distinction may help.<br/>
3. I've constructed these APIs with separate call and response methods as opposed to using two-way methods. Any reason to consider changing this?<br/>
4. Is having PublishedState as a member of SubscriptionData a wise choice? The main use of this as I see it, is that if a listener adds itself to a subscription late, then when given the SubscriptionData, the listener also knows the current state of the subscription.<br/>
5. I've put addListeners() and removeListeners() methods to InboundSubscription and OutboundSubscription, but I don't know exactly how a new listener is supposed to be able to actually add itself in the first place. How would a potential listener receive the subscription object so that it could add itself as a listener? The only thing I can think of at the moment would be that an IceStorm topic is created such that any established subscriptions would be reported to listeners of the topic, and those who receive events on the topic could then add themselves as listeners to subscriptions. Perhaps such IceStorm listening could be the solution to question 1 as well...<br/>
6. Are there any suggestions for cosmetic improvement (e.g. class/method name changes)?</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=12&originalVersion=11">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>