|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
public interface SipConnection
SipConnection
is the base interface for SIP connections.
SipConnection
holds the common properties and methods for
subinterfaces SipClientConnection
and SipServerConnection
.
javax.microedition.io.Connector
A new SIP connection is instantiated by a call to Connector.open()
.
An application SHOULD call close()
when it is finished with the connection.
It should be noticed that the Connector.open()
returns a
client mode connection (SipClientConnection
) or
server mode connection (SipConnectionNotifier
)
depending on the string (SIP URI) passed to the Connector.open()
.
The SIP URI is specified in RFC3261 [1] and here it takes general form of:
{scheme}:[{target}][{params}]
where:
scheme
is SIP scheme supported by the system sip
or
sips
target
is user network address in form of
[{user_name}@]{target_host}[:{port}]
or {telephone_number}
,
see examples below.
params
stands for additional SIP URI parameters
like ;transport=udp
The SIP URI may contain quote characters. The application can
use either the quote character or it's escaped version (%22)
, the
API implementation must support both forms.
(SipClientConnection)
If the target host is included a, SipClientConnection
will be returned.
Examples:
sip:[email protected] sip:[email protected]:5060 sips:[email protected]:5060;transport=tcp sip:+358-555-1234567;[email protected];user=phone
(SipConnectionNotifier)
The server mode is detected by missing target host in the SIP URI. The server connection can be opened in two modes shared and dedicated (see also SIP Identity chapter). It is not required that an implementation of this specification supports both server modes. There may be devices where dedicating separate ports for applications is not feasible. Conversely there may be devices where sharing the SIP listening port among applications is not feasible. Naturally it is required that either shared or dedicated server mode is supported.
This specification defines a special URI format for opening the SIP server mode connections:
{scheme}:[{port}][{params}]
where:
scheme
is SIP scheme supported by the system sip
or
sips
port
optional port number e.g. 5060 or asterisk *
. Asterisk *
is used to detect shared
mode server connections (see below).
params
additional parameters e.g. like media feature tags. See below.
sip:*;type="application/<app_subtype>"[;<other_params>]
Returns SipConnectionNotifier
in shared mode.
The SipConnectionNotifier
is sharing the user's SIP identity with other SIP
applications and also sharing the system listening port. Because the listening port is
shared the parameter 'type'
identifying the application is mandatory in this
mode. Furthermore, the SIP registration is done by the system. The application does not
register itself separately.
The IOException
is thrown if the application type is already reserved or the shared mode
can not be opened for other reason.
URI parameters are:
type
application identifier as MIME type feature tag, where <app_subtype>
is an unique application type/name. Example value: type="application/vnd.company.x-game"
<other_params>
Other possible media feature tags or parameters (see RFC3840 [4])
The incoming requests targeted to the application tagged with the parameter
'type'
are routed to this SipConnectionNotifier
.
sip:[nnnn][;<params>]
Returns SipConnectionNotifier
in
dedicated mode, where a dedicated listening port is opened for the application.
The SipConnectionNotifier
is listening to incoming SIP requests on
port number nnnn
. If the port number is omitted an arbitrary number is
allocated by the system. Application identifier 'type'
and other media feature
parameters are optional. Since the user's SIP identity is not shared the application has
to do the SIP registration by itself. The IOException
is thrown if the port number is already in use or it cannot
be opened for other reason. URI parameters are:
<params>
Optional media feature tag parameters e.g.
'type'
and others (see RFC3840 [4]).
If the application identifier 'type'
is specified the requests targeted to this
application are routed to this SipConnectionNotifier
.
Examples of opening a SIP server connection:
// Shared mode, the application MIME type identifier is // application/vnd.company.x-game SipConnectionNotifier scn = (SipConnectionNotifier) Connector.open("sip:*;type=\"application/vnd.company.x-game\""); // Dedicated mode, port number 5060 opened for the application SipConnectionNotifier scn = (SipConnectionNotifier) Connector.open("sip:5060"); // Dedicated mode, port number 5080, using secure transport // the application identifier is "application/messenger" SipConnectionNotifier scn = (SipConnectionNotifier) Connector.open("sips:5080;type=\"application/messenger\""); // Dedicated mode, dedicated port number selected by the system SipConnectionNotifier scn = (SipConnectionNotifier) Connector.open("sip:");
The optional second parameter 'mode' in Connector.open()
specifies
the access mode. This is ignored in SIP API. This is because both connection modes:
client mode connection and server mode connection can
send and receive messages.
The optional third parameter is a boolean flag that indicates if the calling code can handle timeout exceptions. That parameter is also ignored by the SIP API.
The Connector
convenience methods to gain access to a
specific input or output stream directly are not supported by the SIP API. The
implementations MUST throw IOException
if these methods are
called with SIP URIs.
IllegalArgumentException
ConnectionNotFoundException
IOException
SecurityException
SipException
transport
URI parameter.All compliant implementations MUST support sending and receiving SIP
messages, at least on UDP and TCP transport protocols, as defined in
RFC 3261 (section 18). The default transport protocol MUST be UDP. Whenever
requested, the preferred transport protocol MUST be indicated with the
;transport={transport}
parameter within the URI indicated in the
Connector.open()
method, either for client or server connections.
The choice of transport protocols on which an UAS MUST listen are specified
by RFC 3261 (18.2.1):
For any port and interface that a server listens on for UDP, it MUST listen on that same port and interface for TCP. This is because a message may need to be sent using TCP, rather than UDP, if it is too large. As a result, the converse is not true. A server need not listen for UDP on a particular address and port just because it is listening on that same address and port for TCP.
This means that for a SipConnectionNotifier
listening on UDP
transport protocol is not mandatory if all requests have been sent on top
of TCP, that is if all the Contact headers sent within a registration or
within dialogs indicate transport=tcp
.
SIP identity is a logical identity (address-of-record, AOR), a type of Uniform Resource Identifier (URI) called a SIP URI. SIP identity is frequently thought of as the "public address" of the user. (see RFC 3261 [1], 6 Definitions, p.20). SIP terminal is typically configured for one user at the time (in SIP settings). The AOR is associated (inside the terminal) with one listening port e.g. 5060 (udp/tcp). So, all incoming SIP requests to that particular address-of-record are received through that port.
Now it is still possible to have several applications that want to share the same SIP identity, without specifying own listening ports (audio/video, instant message/presence and e.g. game applications). It is not feasible, or even possible, for every application to reserve own listening port and register that to the SIP registrar. This is particularly not feasible in resource-constrained terminals/networks. On the other hand, some applications can still use their own SIP identity (for that particular service), which does not share the system SIP properties.
In SIP terms: if the request is targeted to specific application (and it is sent outside an existing dialog) it is not possible to always route incoming SIP requests using: port number, SDP media type or SIP method name (INVITE, MESSAGE, SUBSCRIBE, ...).
The issue falls to the decisions on how the initial SIP requests are routed (inside
the terminal) to the User Agents (applications). This kind of functionality is specified in
SIP Working Group as
callee capabilities RFC3840 [4] and caller preferences RFC3841 [5]. The JSR180
specification utilizes similar functinality und uses the media feature tag 'type'
for specifying the application identifier, which is used to route the incoming requests
for correct applications.
Applications can use the MIME type feature tag first to register locally to the
SIP system and second to indicate that in a caller preference header
Accept-Contact
. Each application is mapped to a certain MIME type.
JSR180 SIP API provides the way to utilize this functionality as specified below.
To allow the Java SIP API to share the system SIP identity or use application's own
identity, the following rules are defined when the SIP server connection is opened with
Connector.open()
:
Connector SIP URI | SIP Identity | Request routing | |
1) | sip:*;type="application/subtype" |
|
route incoming SIP requests with MIME type feature tag
"application/subtype" to this
SipConnectionNotifier |
2) | sip:5080[;type="application/subtype"] |
|
route all incoming SIP requests on port 5080 to this SipConnectionNotifier .
If the optional MIME type feature tag "application/subtype" is set, route
only the requests with the matching tag. |
3) | sip: |
|
route all incoming SIP requests to the selected port to this SipConnectionNotifier |
The following routing rules are based on the information available in the incoming request. The implementations may define local policy that overrides any of these rules for security reasons. The incoming request is routed based on following information:
The request is routed according to the following rules, based on which of the information
above is available. Every request may include Accept-Contact
and
Reject-Contact
headers. INVITE request can also have SDP payload.
|
Accept-Contact | SDP media | Routing |
1) | yes | - | Header field contains feature sets that describe UAs
that the caller would like to reach. In this specification
the minimum requirement is the application MIME type
indicated by the Accept-Contact parameter 'type' |
2) | yes | yes | Same as case 1) |
3) | - | yes | (OPTIONAL) The request is routed based on SDP media information. |
The rule 1) defines the minimum required operation for this specification. The SIP dispatcher should implement the decision rules defined in caller prefs [RFC3841] specification. For security reasons the dispatcher implementation may define routing rules that cannot be overridden by other applications.
If matching application is not found a suitable error response is sent e.g.
405 Method Not Allowed
415 Unsupported Media Type
480 Temporarily Unavailable
Accept-Contact
header and incoming requestThe format of the Accept-Contact
header is:
Accept-Contact: *;<feature_set>
Where "*"
is purely there to match the SIP extensions syntax and <feature_set>
is a list of feature parameters.
Examples:
Accept-Contact: *;type="application/vnd.company.battleships" Accept-Contact: *;type="application/x-chess"; Accept-Contact: *;audio;voice;mobility="mobile";
Example of an incoming request with Accept-Contact
header, matching the
application MIME type "application/x-chess"
:
INVITE sip:[email protected] SIP/2.0 From: sip:[email protected] To: sip:[email protected] Accept-Contact: *;type="application/x-chess";explicit Content-Type: application/sdp ...SDP...
Access to certain header types may be restricted. Typically these headers are related to SIP routing and transaction handling so they are not needed to be read and/or modified by the user. The following two list of headers apply to all header manipulation methods of this class.
An implementation MAY throw
SipException
with INVALID_OPERATION error code if the user
tries to modify the following headers:
Call-ID, Cseq, Proxy-Authenticate, WWW-Authenticate
An implementation MAY return null
if the user tries to read the following headers. Trying to modify these
headers will result in SipException.INVALID_OPERATION
:
Authentication-Info, Authorization, Max-Forwards, Min-Expires,
Proxy-Authorization, Record-Route, Security-Server, Security-Verify,
Service-Route, Via
To enable applications to test for the presence of the SIP API and its
version during runtime, a system property is defined. Platforms where
this API is implemented according to this specification shall include
a system property with a key "microedition.sip.version"
. When
System.getProperty
is called with this key,
implementations conforming to this specification shall return the
version string "1.1.1"
.
SipClientConnection
,
SipServerConnection
,
SipConnectionNotifier
Method Summary | |
---|---|
void |
addHeader(java.lang.String name,
java.lang.String value)
Adds a header to the SIP message. |
SipDialog |
getDialog()
Returns the current SIP dialog. |
java.lang.String |
getHeader(java.lang.String name)
Gets the header field value of specified header type. |
java.lang.String[] |
getHeaders(java.lang.String name)
Gets the header field value(s) of specified header type. |
java.lang.String |
getMethod()
Gets the SIP method. |
java.lang.String |
getReasonPhrase()
Gets SIP response reason phrase. |
java.lang.String |
getRequestURI()
Gets Request-URI. |
int |
getStatusCode()
Gets SIP response status code. |
java.io.InputStream |
openContentInputStream()
Returns InputStream to read the message body content of a
request or response received. |
java.io.OutputStream |
openContentOutputStream()
Returns OutputStream to fill the SIP message body content. |
void |
removeHeader(java.lang.String name)
Removes header from the message. |
void |
send()
Sends the SIP message. |
void |
setErrorListener(SipErrorListener sel)
Sets the listener for error notifications. |
void |
setHeader(java.lang.String name,
java.lang.String value)
Sets header value in SIP message. |
Method Detail |
---|
void send() throws java.io.IOException, SipException
Sends the SIP message. Send must also close the OutputStream
if it
was opened. Calling send()
is asynchronous. Any kind of immediate failure will
throw IOException
or SipException
. Errors during the
send operation can be handled with the SipErrorListener
mechanism. With SipServerConnection
it is possible to resend 2xx responses
in Completed state, by calling directly send()
.
java.io.IOException
- if the message could not be sent
or because of network failure. When IOException is thrown the
connection moves to the Terminated state.
SipException
- INVALID_STATE if the message
can not be sent in this state. INVALID_MESSAGE if there was an
error in the message format.SipErrorListener
void setHeader(java.lang.String name, java.lang.String value) throws SipException
Sets header value in SIP message. If the header does not exist it will be added to the message, otherwise the existing header is overwritten. If multiple header field values exist the topmost is overwritten. The implementations MAY restrict the access to some headers according to RFC 3261 [1], see also "Restricted access to headers".
The implementations are free to store the multiple header field-values either as separate rows or as comma-separated list (if the header type follows the grammar defined in [RFC3261] section 7.3).
The value
argument of the method may contain a list of
comma-separated header values. Note that this feature should not be used
for headers (like the Authorization header) which use comma as parameter
separator instead of semicolon. If there exist headers of the same type
then only the first (topmost) one will be overwritten, indifferently of
the number of header values in the comma-separated list. See example
3. below.
The method works atomically, that is if the value
argument of
the method is a list of comma-separated values then the method should
either set all of them or none of them. That is if an exception is
thrown from the method then no headers are changed, even if the error
occurred when setting the second, third etc header value.
Example1: Replacing single header field row. The message already contains following headers:
Route: <sip:[email protected]> Route: <sip:[email protected]> setHeader("Route", "<sip:[email protected]>"); the result will be Route: <sip:[email protected]> Route: <sip:[email protected]>
Example2: Setting multiple header field rows as a comma-separated list. The message already contains one header:
Route: <sip:[email protected]> setHeader("Route", "<sip:[email protected]>, <sip:[email protected]>"); the result will be either Route: <sip:[email protected]>, <sip:[email protected]> or Route: <sip:[email protected]> Route: <sip:[email protected]>
Example3: Setting multiple header field rows as a comma-separated list. The message already contains two headers:
Route: <sip:[email protected]> Route: <sip:[email protected]> setHeader("Route", "<sip:[email protected]>, <sip:[email protected]>"); the result will be either Route: <sip:[email protected]>, <sip:[email protected]>, <sip:[email protected]> or Route: <sip:[email protected]> Route: <sip:[email protected]> Route: <sip:[email protected]> The result would be the same if the original message contained the headers in a concatenated list form: Route: <sip:[email protected]>, <sip:[email protected]>
name
- name of the header, either in full or compact form see [1] p.32value
- the header value. Empty string or null means a
header with no value.
java.lang.NullPointerException
- if name is null
java.lang.IllegalArgumentException
- if the header or value
is invalid.
SipException
- INVALID_STATE if header
can not be set in this state. INVALID_OPERATION if the system does
not allow to set this header.void addHeader(java.lang.String name, java.lang.String value) throws SipException
Adds a header to the SIP message. If multiple header field values exist the header value is added topmost of this type of headers. The implementations MAY restrict the access to some headers according to RFC 3261 [1], see also "Restricted access to headers".
Some SIP headers can occur only once in a message, for these it is
recommended that setHeader
is used instead of addHeader
.
Implementations of this specification are not mandated to check that
the multiplicity of headers conform to the relevant RFCs when the message
is composed.
The header value string may contain a single value or multiple values as a comma-separated list (that is, if it follows the grammar defined in [RFC3261] section 7.3). Note that this feature should not be used for headers (like the Authorization header) which use comma as parameter separator instead of semicolon. The implementations are free to store the multiple header field rows either as comma separated list or in separate rows.
The method works atomically, that is if the value
argument of
this method is a list of comma-separated values then the method should
either add all of them or none of them. That is if an exception is
thrown from the method then no headers are changed, even if the error
occurred when adding the second, third etc header value.
Example1: Adding single header field row. The message already contains header
Route: <sip:[email protected]>. addHeader("Route", " <sip:[email protected]>"); the result will be Route: <sip:[email protected]> Route: <sip:[email protected]> or Route: <sip:[email protected]>, <sip:[email protected]>
Example2: Adding multiple header field rows as a comma-separated list. The message already contains header
Route: <sip:[email protected]>. addHeader("Route", "<sip:[email protected]>, <sip:[email protected]>"); the result will be either Route: <sip:[email protected]>, <sip:[email protected]> Route: <sip:[email protected]> or Route: <sip:[email protected]> Route: <sip:[email protected]> Route: <sip:[email protected]> or Route: <sip:[email protected]>, <sip:[email protected]>, <sip:[email protected]>
name
- name of the header, either in full or compact form see [1] p.32value
- the header value. Empty string or null means a header with
no value.
java.lang.NullPointerException
- if name is null
java.lang.IllegalArgumentException
- if the header or value
is invalid.
SipException
- INVALID_STATE if header can
not be added in this state. INVALID_OPERATION if the system does not
allow to add this header.void removeHeader(java.lang.String name) throws SipException
Removes header from the message. If multiple header field values exist the topmost is removed. If the named header is not found this method does nothing. The implementations MAY restrict the access to some headers according to RFC 3261 [1], see also "Restricted access to headers". The method only removes one header value even if the header values are stored in a comma-separated list.
Example1: Removing header from a message that contains two Route headers in separate header field rows.
Route: <sip:[email protected]> Route: <sip:[email protected]> removeHeader("Route"); the result is: Route: <sip:[email protected]>
Example2: Removing header from a message that contains three Route headers in a comma-separated header field value.
Route: <sip:[email protected]>, <sip:[email protected]>, <sip:[email protected]> removeHeader("Route"); the result is: Route: <sip:[email protected]>, <sip:[email protected]>
name
- name of the header to be removed, either in full or compact form see [1] p.32
java.lang.NullPointerException
- if name is null
SipException
- INVALID_STATE if header
can not be removed in this state. INVALID_OPERATION if the system does
not allow to remove this header.java.lang.String[] getHeaders(java.lang.String name)
Gets the header field value(s) of specified header type. The method returns the header field-values separated in an array regardless of how they are stored in the message. The implementations MAY restrict the access to some headers according to RFC 3261 [1], see also "Restricted access to headers".
Example1: Get Route headers from a message that contains two Route headers in separate header field rows.
Route: <sip:[email protected]> Route: <sip:[email protected]> getHeaders("Route"); the result is a String array: {"<sip:[email protected]>", "<sip:[email protected]>"}
Example2: Get Route headers from a message that contains three Route headers in a comma-separated header field value.
Route: <sip:[email protected]>,<sip:[email protected]>,<sip:[email protected]> getHeaders("Route"); the result is a String array: {"<sip:[email protected]>", "<sip:[email protected]>", "<sip:[email protected]>"}
name
- name of the header type, either in full or compact form
see [1] p.32
null
if the current message does not have such a header or the header is
for other reason not available (e.g. message is not initialized, the
connection is closed or the
implementation does not allow this header to be read). The returned
array may contain empty strings.
java.lang.NullPointerException
- if name is nulljava.lang.String getHeader(java.lang.String name)
Gets the header field value of specified header type. The implementations MAY restrict the access to some headers according to RFC 3261 [1], see also "Restricted access to headers".
Example1: Get topmost Route header from a message that contains three Route headers in a comma-separated header field value.
Route: <sip:[email protected]>,<sip:[email protected]>,<sip:[email protected]> getHeader("Route"); the result is: <sip:[email protected]>
name
- name of the header type, either in full or compact form see
[1] p.32
null
or empty. It is
null
if the current message does not have such a header or
the header is
for other reason not available (e.g. message is not initialized, the
connection is closed or the implementation does not allow this header
to be read).
java.lang.NullPointerException
- if name is nulljava.lang.String getMethod()
Gets the SIP method. Applicable when a message has been initialized or received.
null
if the method is not available (e.g. message is
not initialized, the connection is closed).java.lang.String getRequestURI()
Gets Request-URI. If supported, available when
SipClientConnection
is in Initialized state or
when SipServerConnection
is in Request Received state.
Built from the original URI given in Connector.open()
.
See RFC 3261 p.35 (8.1.1.1 Request-URI)
It is not mandated that this method be supported, an implementation may
return null
in any state.
null
if the Request-URI is not available (e.g. message is not initialized
or the connection is closed) or getting the Request-URI is not
supported.int getStatusCode()
Gets SIP response status code. Available when SipClientConnection
is in Proceeding, Unauthorized or Completed state or when
SipServerConnection
is in Initialized state.
java.lang.String getReasonPhrase()
Gets SIP response reason phrase. Available when SipClientConnection
is in Proceeding, Unauthorized or Completed state or when
SipServerConnection
is in Initialized state.
null
if the reason phrase is not available (e.g. message is not initialized or
the connection is closed). Returns an empty string is the reason phrase
was set with null
or empty string in setReasonPhrase
.SipDialog getDialog()
Returns the current SIP dialog. This is available when the
SipConnection
belongs to a created SipDialog
,
which is in Early or Confirmed state (see
SipDialog
).
The SipDialog
returned from the SipConnection
defines
always the peer-to-peer association created by the latest sent or
received request or response.
The method returns null
if a terminating error response
(3xx - 6xx) is received or sent on the connection or the connection
is closed.
The following rules apply when this method is called on a
SipServerConnection
instance:
CANCEL
then the method
returns null
since the dialog is in early state and the
CANCEL
request does not relate to the dialog.ACK
then the method returns the dialog
object if it is available.
SipDialog
object if this connection belongs to a
dialog, otherwise returns null
. See also the rules defined at
the method's description.SipDialog
java.io.InputStream openContentInputStream() throws java.io.IOException, SipException
Returns InputStream
to read the message body content of a
request or response received. It is not
required that implementations store the message content after it was
sent, so calling this method after sending a request or response may
fail.
java.io.IOException
- if the InputStream
can not be opened, because of an I/O error occurred.
SipException
- INVALID_STATE if the
InputStream
can not be opened in this state (e.g. no message
received or message has already been sent).java.io.OutputStream openContentOutputStream() throws java.io.IOException, SipException
Returns OutputStream
to fill the SIP message body content.
When calling close()
on OutputStream
the message
will be sent to the network. So it is equivalent to call
send()
. This method must not be called after closing
the OutputStream
, since it will throw Exception because of
calling the method in wrong state.
Before opening the OutputStream
the Content-Type
header has to be set. If not
SipException.UNKNOWN_TYPE
will be thrown. The
Content-Length
header need not be set, it is automatically set
by the API implementation immediately before sending the message. If it
is set by the application, it will be overwritten with the correct
length of the stream.
java.io.IOException
- if the OutputStream
can not be
opened, because of an I/O error occurred.
SipException
- INVALID_STATE if the
OutputStream
can not be opened in this state (e.g. no
message initialized). UNKNOWN_TYPE Content-Type
if the
type
header is not set.send()
void setErrorListener(SipErrorListener sel) throws SipException
Sets the listener for error notifications. Applications that want to
receive notification about a failure of an asynchoronous send operation
must implement the SipErrorListener
interface and register it
with a connection using this method. Only one listener can be set
at any time, if a listener is already set
it will be overwritten. Setting listener to null
will remove
the current listener.
This method is added to version 1.1.0 so that applications can receive notifications about transmission errors, like failure in the GPRS connection.
sel
- reference to the listener object. The value null
will remove the existing listener.
SipException
- INVALID_STATE if the connection is closed
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |