|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object javax.microedition.sip.SipRefreshHelper
public class SipRefreshHelper
This class implements the functionality that facilitates the handling of
refreshing requests on behalf of the application. Some SIP requests
(REGISTER, SUBSCRIBE, ...) need to be timely refreshed (binding between end
point and server, see RFC 3261 - chapter 10.2.1 page 58). For example the
REGISTER request (RFC 3261, chapter 10 page 56) needs to be re-sent to ensure
that the originating end point is still well and alive. The request's
validity is proposed by the end point in the request and confirmed in the
response by the registrar/notifier for example in expires header (RFC 3261,
chapter 2 page 5). The handling of such binding would significantly increase
application complexity and size. As a consequence the
SipRefreshHelper
can be used to facilitate such operations. The
specification does not define the strategy for timely refreshing of
registrations and subscriptions, implementations may choose the algorithm of
when to send the refresh request.
The implementation must support refreshing REGISTER and SUBSCRIBE requests
using the features of this class, however it is not mandated that
refreshing PUBLISH requests is supported by the refreshHelper mechanism.
Note that even if the SipRefreshHelper
provides no support for
PUBLISH, refreshing PUBLISH requests is possible by sending the appropriate
SIP request from the application.
When the application wants to send a refreshable request it:
SipRefreshListener
callback interface.
SipClientConnection
and sets it up.
enableRefresh(SipRefreshListener)
. A refresh ID is returned.
If the request is not refreshable the method returns 0.
SipRefreshListener
A reference to the SipRefreshHelper
object is obtained by calling
the static method
SipRefreshHelper.getInstance()
(singleton pattern).
Finally, using the refresh ID returned from
enableRefresh(SipRefreshListener)
the application can:
stop()
a
refresh. The possible binding between end point and server is cancelled
(RFC3261, chapter 10.2.2 page 61).
update(...)
the refreshed
request with new parameters (Contact info, expires header and new payload).
Note that this functionality is limited to the most typical case. A more complex case would
require to stop the refresh and to create a new request with the needed
updates.
When all refresh tasks belonging to one refresh listener are stopped, the
listener reference will be removed from the SipRefreshHelper
.
In case of failure of either the original request or a subsequent refresh
request the refreshing is automatically stopped and the failure response
is reported in the refreshEvent()
callback. The corresponding
refresh ID is invalidated, so calling update()
with the same ID
will throw an exception. The application has to start a new refresh task
if it wishes so and the implementation will assign a new refresh ID.
An implementation compliant to this
specification MUST report the refresh responses to the refreshEvent
callback in case of failure response codes (3xx – 6xx), and it MAY report
them in case of successful refreshing (2xx). It MUST NOT report provisional
(1xx) responses.
If a response arrives to a refresh request that was updated by the
application since the request was sent then the response is not reported in
the refreshEvent()
callback.
If refresh responses are not received due to network problems,
SipRefreshHelper
reports failure to the user in the
refreshEvent()
callback. The implementations are free to choose
a suitable SIP error code (like 408 – Timeout) or an implementation
specific code (with the exception of 0, 1xx and 2xx) and reason phrase.
Code example where REGISTER is sent, updated and finally stopped:
class SipRefreshExample implements SipClientConnectionListener, SipRefreshListener { int refreshID = 0; int refreshStatus = 0; SipRefreshHelper refHelper = null; public void sendRegister() { SipClientConnection sc = null; try { // Initialize connection to the registrar host.com sc = (SipClientConnection) Connector.open ("sip:host.com"); sc.setListener(this); // Initialize request and set From, To and Contact // headers sc.initRequest("REGISTER", null); sc.setHeader("From", "sip:[email protected]"); sc.setHeader("To", "sip:[email protected]"); sc.setHeader("Contact", "<sip:[email protected]>;expires=3600"); sc.setHeader("Contact", "<mailto:[email protected]>;expires=4294967295"); refreshID = sc.enableRefresh(this); sc.send(); refHelper = SipRefreshHelper.getInstance(); //----------------------------- // do something else for a while //------------------------------ // update REGISTER, with new "mailto:" Contact // and no content // check that refresh was successful (2xx) if (refreshStatus >= 200 && refreshStatus < 300) { String c[] = {"<mailto:[email protected]>"}; refHelper.update(refreshID, c, null, 0, 6000); } //----------------------------- // do something else for a while //------------------------------ // stop REGISTER refresh altogether // check that refresh is still ok if (refreshStatus >= 200 && refreshStatus < 300) { refHelper.stop(refreshID); } } catch (Exception ex) { // handle Exceptions } } public void notifyResponse(SipClientConnection scc) { try { // retrieve the response received scc.receive(0); if (scc.getStatusCode() >= 200 && scc.getStatusCode() < 300) { // handle 2xx response } else { // handle possible error responses } } catch (Exception ex) { // handle Exceptions } } public void refreshEvent(int ID, int statusCode, String reasonPhrase) { refreshStatus = statusCode; if (statusCode == 0) { // stopped refresh } else if (statusCode >= 200 && statusCode < 300) { // successful refresh } else { // failed request } } }
SipClientConnection.enableRefresh(SipRefreshListener)
Method Summary | |
---|---|
static SipRefreshHelper |
getInstance()
Returns the instance of SipRefreshHelper |
void |
stop(int refreshID)
Stop refreshing a specific request related to refeshID. |
java.io.OutputStream |
update(int refreshID,
java.lang.String[] contact,
java.lang.String type,
int length,
int expires)
Updates one refreshed request with new values. |
Methods inherited from class java.lang.Object |
---|
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Method Detail |
---|
public static SipRefreshHelper getInstance()
Returns the instance of SipRefreshHelper
SipRefreshHelper
singletonpublic void stop(int refreshID) throws SipException
Stop refreshing a specific request related to refeshID. The possible binding between end point and registrar/notifier is cancelled. The way of cancellation depends on the SIP method used in the original request. The implementation must comply to the relevant specifications when creating the SIP request for cancelling the binding, that is:
An event will be sent to the listeners with the appropriate refreshID, statusCode = 0 and reasonPhrase = "refresh stopped".
If the stop()
operation fails (e.g due to error in the native
SIP stack) then refreshing is stopped and a refresh event is sent to
the listeners with status code 0 and an implementation dependent error
phrase.
The method can not be called in every phase of the refresh operation.
There is no exact state machine defined for refresh operations but some
possible scenarios in which the method MAY throw
SipException.INVALID_STATE
are the following: stop is called
after initial registration request is sent but before 2xx-OK response
arrives, stop is called during an asynchronous update operation. Note
that no exception is thrown if stop is called
before the initial request is sent, as in this case the binding to be
cancelled is not yet established so no SIP message must be sent out, the
method returns without any action.
refreshID
- the ID of the refresh to be stopped. If the ID
does not match any refresh task the method throws
SipException.INVALID_STATE
.
SipException
- INVALID_STATE if the refreshID
doesn't
represent an ongoing refresh operation (e.g. the refresh is already
stopped by the application or because of an error) or stop
can not be
called in the current state of the refresh operation. See
the details in the method definition section.public java.io.OutputStream update(int refreshID, java.lang.String[] contact, java.lang.String type, int length, int expires) throws SipException
Updates one refreshed request with new values.
Contact
header values. existing values are kept if
this is null.Expires
header value. expires = 0 has the same effect as
calling stop(refreshID)
. expires = -1 leaves the
Expires
header out.Content-Type
and Content-Length
.
The message is sent when the returned OutputStream
is closed.
If no content is set the message will be sent automatically and the
method returns null
.Note that SipRefrehHelper
sends the updated request in an
independent transaction which implies that even if the header values are
updated, it does not change the header values of the original request
object. So if the application keeps a reference to the original client
connection object, the headers of that object are not touched after the
update()
is executed.
Giving null
or empty string as type
or 0 as
length
means that subsequent refresh request will have no
content. It does not mean that the request will contain the content
of the original request unmodified.
Similarly to stop()
the way of constructing the updated SIP
request depends on the method used. The implementation must comply to
the relevant RFCs.
If the update()
operation fails (e.g due to error in the
native SIP stack) then refreshing is stopped and a refresh event is
sent to the listeners with the status code of the response received.
If the status code is not available then an implementation dependent
error code (and response phrase) is reported in the
refreshEvent
. The implementations are free to choose a
suitable SIP error code (like 408 – Timeout) or an implementation
specific code (with the exception of 0, 1xx and 2xx) and reason
phrase. The behaviour is the same in case the
OutputStream.close()
operation fails within an update()
operation.
The method can not be called in every phase of the refresh operation.
There is no exact state machine defined for refresh operations but some
possible scenarios in which SipException.INVALID_STATE
MAY be
thrown: update is
called when the refresh is not yet active (e.g. after initial
registration request is sent but before 2xx response
arrives) or update is called before a previous update operation ends.
refreshID
- ID returned from enableRefresh(...)
. If the ID
does not match any refresh task the method throws
SipException.INVALID_STATE
.contact
- new Contact headers as String array. Replaces all old values.
Multiple Contact header values are applicable only for
REGISTER method. If contact param is null or empty the system
will set the Contact header.type
- value of Content-Type (null or empty, no content).length
- value of Content-Length (<=0, no content).expires
- value of Expires (-1, no Expires header), (0, stop the
refresh)
OutputStream
to fill the content. If the
update does not have new content (type = null
and/or
length <= 0) method returns null
and the message is
sent automatically.
java.lang.IllegalArgumentException
- if some input parameter is invalid
SipException
- INVALID_STATE if the refreshID
doesn't
represent an ongoing refresh operation (e.g. the refresh is already
stopped by the application or because of an error) or update
can not be
called in the current state of the refresh operation. See
the details in the method definition section.
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |