An Introduction to the JAIN SIP API
2009-03-10 17:28
501 查看
by Emmanuel Proulx
10/17/2007
applications using the Session Initiation Protocol (SIP) on Java SE. It
presents the JAIN SIP API, a powerful "SIP stack." A simple IM
application is shown and then dissected to explore this technology.
is a standard communication protocol, discussed in a previous article.
Put Java and SIP together and you get the JAIN SIP API, a standard and
powerful API for telecommunications. This idea started in 1999 with JSR 32. The reference implementation
is open source, very stable, and very widely used. If you're writing a
SIP application with Java, using this SIP stack makes perfect sense.
This API is typically used for client-side application development. Other container-based technologies, like SIP Servlet API
(see BEA WebLogic SIP Server for example), are better suited for
server-side development. A previous article focuses on the SIP Servlet
API. Now we're going to turn to the client API stack.
Also, I suggest you familiarize yourself with SIP, as using the JAIN
SIP API requires a good understanding of this protocol. SIP signaling,
especially messages and headers, is particularly important. See the
References section at the end of the article for links to relevant
information.
Other files are not needed in this example. Include these libraries in your project.
I suggest you have a look at the first section of the Appendix
for a list of the various classes and interfaces provided in the JAIN
SIP API. These classes and interfaces are standard and provided to you
free of charge, and soon you will see how to use them as part of our
dissect an application that you may be familiar with if you read the
article on the topic of SIP Servlets I wrote previously. The TextClient
is an instant messaging application that can send and receive text
messages over the SIP protocol. One instance of this application can
send messages to another instance, but in theory, this client can be
used to send messages to other kinds of SIP instant messaging clients,
and even SIP server applications. Figure 1 shows a screen capture.
Figure 1. The TextClient returns
To run this application, first you need to download
the provided source code. Second, you have to build it using the
provided Ant script. This will produce a JAR file. Finally, you run the
application, using this command:
You can run multiple instances of this client (make
sure they use different ports) and send each other messages. The rest
of the article explores the code of this sample application.
In the upcoming sections, I'll introduce the
class at all because it simply contains user interface Swing code and
is not relevant to the topic of this article. For more information,
please refer to the source code provided with this article.
interface. To decouple the SIP layer from the GUI layer, you use a
callback interface that allows sending information from the former
without having to know the signature of the latter. The interface is
shown below:
The
must be able to receive asynchronous messages coming from other SIP end
points. The observer pattern is used for this: The class implements the
The methods of this interface are:
In this example, the most important methods evidently are
Next are two fields to store objects needed later.
These are not directly related to the SIP API, but you'll need them for
the example. The first is a
discussed before. You also need to keep the username handy. These two
fields have getters and setters which, for brevity, I'm not showing in
this article.
Next is the constructor. A typical way to start a
JAIN SIP API application—and TextClient follows this pattern—is to set
up a bunch of objects that will be useful later on. I'm talking about a
number of factories, and a single SIP stack instance, initialized.
The SIP factory is used to instantiate a
The
of properties. At a minimum, you must set the stack name. All other
properties are optional. Here I'm setting an IP address to use by the
stack, for cases where a single computer has more than one IP address.
Note that there are standard properties, which all SIP API
implementations must support, and non-standard ones that are dependent
on the implementation. See the References section for links to these
properties.
The next step is to create a pair of
objects. These objects provide the communication functionality of
sending and receiving messages. There's one set of these for TCP and
one set for UDP. This is also where you select the
And this is how the constructor ends. You've just used the JAIN SIP API to create a
In the prerequisites I suggested that you must know
SIP fairly well before you can start using the SIP API. You'll now see
what I mean by that! The SIP API is quite a low-level abstraction and,
in most cases, doesn't use default values or hide headers, request
URIs, or contents of SIP messages. The advantage of this design is that
you have complete control over what SIP messages contain.
The following method is a bit lengthy. It prepares and sends a SIP request. It can roughly be split into four subsections:
Create main elements
Create message
Complete message
Send message
The following main SIP elements are minimally needed to construct a message using the JAIN SIP API:
Request URI
Method
Call-ID header
CSeq header
From header
An array of Via headers
Max-forwards header
For information about these elements, please see An
Introduction to SIP, Part 1 (Dev2Dev, 2006). The following code snippet
creates all of these elements:
I'm using factories that were created in the constructor,
Next let's instantiate the actual SIP message itself, passing in all the elements created earlier:
Note the use of
Then let's add other elements to the message: a
contact header and the contents of the message (payload). It's possible
to add custom headers too at this point.
For more information on how to further massage the request, there's a description of the
Lastly, you send the message using the
means messages are not related to each other. This works well for a
simple instant-messaging application like the TextClient.
An alternative would be to create a dialog
(sometimes called a session) using an INVITE message, and then send
messages inside this dialog. The TextClient doesn't use this technique.
However, I think it's something worth learning. So as a compromise,
this subsection describes how it's done.
Sending a message inside a dialog requires the creation of
objects. On the initial message (that is, the message that creates the
dialog), instead of using the provider to send out the message, you
instantiate a
Later when you wish to send a new message inside the same dialog, you use the
Essentially, you're skipping the "create main
elements" step when sending a message inside an existing dialog. When
you use an INVITE to create a dialog, don't forget to clean it up by
sending an in-dialog BYE message at the end. This technique is also
used to refresh registrations and subscriptions.
Previously, you've seen the
methods. These are called automatically at the end of a dialog and
transaction, respectively. Typically, you implement these methods to
clean things up (for example, discard the
In this method you check if the response of an
earlier MESSAGE message represents a success (2xx range of status
codes) or an error (otherwise). You then relay this information back to
the user through the callback interface.
Typically, you read only the
method. The only exception is for a success response to an INVITE
message; in this case, you must send an ACK request right back, like
this:
For a description of the
object. This is the same type that you've seen before, and it has the
same methods. However, you shouldn't set any fields on an incoming
request as it doesn't make much sense.
A typical implementation of
In this case, you always reply with a success
response (200), but you could also send back any of the error responses
(typically 4xx range). Here's a useful list of SIP status codes.
interface that you haven't implemented yet. They are called by the SIP
stack when a request cannot be sent for specific reasons. For example,
the
receiving the message doesn't answer in time. This is a special
situation for which there is no response, so no
of the request that timed out, and you can use this to link back to the
original request if you want to. In this implementation you simply
inform the user using the callback interface:
Similarily, Input/Output (IO) errors are processed using the following method:
(point to point) or together with a server to provide extra
functionality like proxying or call routing.
I suggest you have a look at my Aarticle on SIP
Servlets. It contains a neat SIP Server application that can work with
TextClient to provide a chat room-type service. This illustrates how
you can use the TextClient together with the BEA WebLogic SIP Server
and double its usefulness.
API, and I've shown how to write a simple application to use this
technology. Right now, you should have a pretty good idea of the APIs
available, and know how to write your own IM client with SIP.
Nevertheless, why stop here? I could add many more
features to this application. And as I said before, if the client talks
with a server application, you can double its usefulness. If you need
suggestions, consider the following:
Automatic text answers, store-and-forward
(for example, "John is offline right now, but he will receive your
messages as soon as he logs back in")
A neat networked checkers video game
A location-based service for your laptop
A media-sharing client
An RSS-like client
The possibilities are almost limitless.
including SIP message formats. Be sure to read the section "Relation
among Call, Dialog, Transaction & Message" (external tutorial)
Standard SIP stack properties
Non-standard SIP stack properties of the reference implementation
SIP status codes
RTP stack
SIP Communicator (java.net project)
The
Now let's glance through the
The
Emmanuel Proulx is an expert in J2EE and SIP. He is a
certified WebLogic Server engineer.
10/17/2007
Abstract
This article shows how to develop client-sideapplications using the Session Initiation Protocol (SIP) on Java SE. It
presents the JAIN SIP API, a powerful "SIP stack." A simple IM
application is shown and then dissected to explore this technology.
About JAIN SIP API
The Java APIs for Integrated Networks (JAIN) is a JCP work group managing telecommunication standards. Session Initiation Protocol (SIP)is a standard communication protocol, discussed in a previous article.
Put Java and SIP together and you get the JAIN SIP API, a standard and
powerful API for telecommunications. This idea started in 1999 with JSR 32. The reference implementation
is open source, very stable, and very widely used. If you're writing a
SIP application with Java, using this SIP stack makes perfect sense.
This API is typically used for client-side application development. Other container-based technologies, like SIP Servlet API
(see BEA WebLogic SIP Server for example), are better suited for
server-side development. A previous article focuses on the SIP Servlet
API. Now we're going to turn to the client API stack.
Prerequisites
This article requires a good understanding of Java.Also, I suggest you familiarize yourself with SIP, as using the JAIN
SIP API requires a good understanding of this protocol. SIP signaling,
especially messages and headers, is particularly important. See the
References section at the end of the article for links to relevant
information.
Libraries
To get the JAIN SIP API libraries, go to the jain-sip project home page. Click the link to go to the download page. You'll need to get these files:JainSipApi1.2.jar: SIP interfaces and main classes
JainSipRi1.2.jar: SIP reference implementation
log4j-1.2.8.jar(Available inside the file
jain-sip-1.2.jarunder the folder
jain-sip/lib): Logging service
concurrent.jar(Available inside the file
jain-sip-1.2.jarunder the folder
jain-sip/lib): Concurrency utilities
Other files are not needed in this example. Include these libraries in your project.
I suggest you have a look at the first section of the Appendix
for a list of the various classes and interfaces provided in the JAIN
SIP API. These classes and interfaces are standard and provided to you
free of charge, and soon you will see how to use them as part of our
SipLayerexample class.
The TextClient Sample Application
As an example of a JAIN SIP API program, let'sdissect an application that you may be familiar with if you read the
article on the topic of SIP Servlets I wrote previously. The TextClient
is an instant messaging application that can send and receive text
messages over the SIP protocol. One instance of this application can
send messages to another instance, but in theory, this client can be
used to send messages to other kinds of SIP instant messaging clients,
and even SIP server applications. Figure 1 shows a screen capture.
Figure 1. The TextClient returns
To run this application, first you need to download
the provided source code. Second, you have to build it using the
provided Ant script. This will produce a JAR file. Finally, you run the
application, using this command:
[code]java -jar textclient.jar <username> <port>
You can run multiple instances of this client (make
sure they use different ports) and send each other messages. The rest
of the article explores the code of this sample application.
TextClient Code Overview
A couple of classes and an interface make up the whole TextClient code. This table introduces them:Class / Interface | Description |
---|---|
TextClient | Main class, Swing window that contains the widgets of the application. See Figure 1. |
SipLayer | Class that takes care of all the SIP communication. It is instantiated by the TextClientclass, and calls it back through the MessageProcessorinterface. |
MessageProcessor | Callback interface (observer pattern), which serves to decouple the SipLayerfrom its container. |
MessageProcessorand then spend most of the time looking at
SipLayer. I won't talk about the
TextClient
class at all because it simply contains user interface Swing code and
is not relevant to the topic of this article. For more information,
please refer to the source code provided with this article.
Message Processor
Before I jump into theSipLayerclass, I'll briefly cover the
MessageProcessor
interface. To decouple the SIP layer from the GUI layer, you use a
callback interface that allows sending information from the former
without having to know the signature of the latter. The interface is
shown below:
[code]public interface MessageProcessor { public void processMessage(String sender, String message); public void processError(String errorMessage); public void processInfo(String infoMessage); }
The
SipLayerconstructor will take an implementation of this interface (that is, the
TextClientobject) as a parameter and will hold on to it. Later you'll be able to use this object to send information back to the GUI.
SIP Stack Preparation
Let's start writing theSipLayerclass.
TextClient
must be able to receive asynchronous messages coming from other SIP end
points. The observer pattern is used for this: The class implements the
SipListenerinterface to process incoming messages:
[code]public class SipLayer implements SipListener {
The methods of this interface are:
[code] void processRequest(RequestEvent evt); void processResponse(ResponseEvent evt); void processTimeout(TimeoutEvent evt); void processIOException(IOExceptionEvent evt); void processTransactionTerminated(TransactionTerminatedEvent evt); void processDialogTerminated(DialogTerminatedEvent evt);
In this example, the most important methods evidently are
processRequest()and
processResponse()for processing incoming messages. I'll look at those a bit later.
Next are two fields to store objects needed later.
These are not directly related to the SIP API, but you'll need them for
the example. The first is a
MessageProcessorobject as
discussed before. You also need to keep the username handy. These two
fields have getters and setters which, for brevity, I'm not showing in
this article.
[code]private MessageProcessor messageProcessor; private String username;
Next is the constructor. A typical way to start a
JAIN SIP API application—and TextClient follows this pattern—is to set
up a bunch of objects that will be useful later on. I'm talking about a
number of factories, and a single SIP stack instance, initialized.
[code]private SipStack sipStack; private SipFactory sipFactory; private AddressFactory addressFactory; private HeaderFactory headerFactory; private MessageFactory messageFactory; private SipProvider sipProvider; public SipLayer(String username, String ip, int port) throws PeerUnavailableException, TransportNotSupportedException, InvalidArgumentException, ObjectInUseException, TooManyListenersException { setUsername(username); sipFactory = SipFactory.getInstance(); sipFactory.setPathName("gov.nist"); Properties properties = new Properties(); properties.setProperty("javax.sip.STACK_NAME", "TextClient"); properties.setProperty("javax.sip.IP_ADDRESS", ip); sipStack = sipFactory.createSipStack(properties); headerFactory = sipFactory.createHeaderFactory(); addressFactory = sipFactory.createAddressFactory(); messageFactory = sipFactory.createMessageFactory(); ...
The SIP factory is used to instantiate a
SipStackimplementation, but since there could be more than one implementation, you must name the one you want via the
setPathName()method. The name "
gov.nist" denotes the SIP stack you've got.
The
SipStackobject takes in a number
of properties. At a minimum, you must set the stack name. All other
properties are optional. Here I'm setting an IP address to use by the
stack, for cases where a single computer has more than one IP address.
Note that there are standard properties, which all SIP API
implementations must support, and non-standard ones that are dependent
on the implementation. See the References section for links to these
properties.
The next step is to create a pair of
ListeningPointand
SipProvider
objects. These objects provide the communication functionality of
sending and receiving messages. There's one set of these for TCP and
one set for UDP. This is also where you select the
SipLayer(this) as a listener of incoming SIP messages:
[code]... ListeningPoint tcp = sipStack.createListeningPoint(port, "tcp"); ListeningPoint udp = sipStack.createListeningPoint(port, "udp"); sipProvider = sipStack.createSipProvider(tcp); sipProvider.addSipListener(this); sipProvider = sipStack.createSipProvider(udp); sipProvider.addSipListener(this); }
And this is how the constructor ends. You've just used the JAIN SIP API to create a
SipStackinstance, a bunch of factories, two
ListeningPoints, and a
SipProvider. These objects will be needed in the upcoming methods to send and receive messages.
Sending a SIP Request
Let's now write a method to send a SIP message with the JAIN SIP API.In the prerequisites I suggested that you must know
SIP fairly well before you can start using the SIP API. You'll now see
what I mean by that! The SIP API is quite a low-level abstraction and,
in most cases, doesn't use default values or hide headers, request
URIs, or contents of SIP messages. The advantage of this design is that
you have complete control over what SIP messages contain.
The following method is a bit lengthy. It prepares and sends a SIP request. It can roughly be split into four subsections:
Create main elements
Create message
Complete message
Send message
The following main SIP elements are minimally needed to construct a message using the JAIN SIP API:
Request URI
Method
Call-ID header
CSeq header
From header
An array of Via headers
Max-forwards header
For information about these elements, please see An
Introduction to SIP, Part 1 (Dev2Dev, 2006). The following code snippet
creates all of these elements:
[code]public void sendMessage(String to, String message) throws ParseException, InvalidArgumentException, SipException { SipURI from = addressFactory.createSipURI(getUsername(), getHost() + ":" + getPort()); Address fromNameAddress = addressFactory.createAddress(from); fromNameAddress.setDisplayName(getUsername()); FromHeader fromHeader = headerFactory.createFromHeader(fromNameAddress, "textclientv1.0"); String username = to.substring(to.indexOf(":")+1, to.indexOf("@")); String address = to.substring(to.indexOf("@")+1); SipURI toAddress = addressFactory.createSipURI(username, address); Address toNameAddress = addressFactory.createAddress(toAddress); toNameAddress.setDisplayName(username); ToHeader toHeader = headerFactory.createToHeader(toNameAddress, null); SipURI requestURI = addressFactory.createSipURI(username, address); requestURI.setTransportParam("udp"); ArrayList viaHeaders = new ArrayList(); ViaHeader viaHeader = headerFactory.createViaHeader( getHost(), getPort(), "udp", null); viaHeaders.add(viaHeader); CallIdHeader callIdHeader = sipProvider.getNewCallId(); CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1, Request.MESSAGE); MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70); ...
I'm using factories that were created in the constructor,
HeaderFactoryand
AddressFactory, to instantiate these elements.
Next let's instantiate the actual SIP message itself, passing in all the elements created earlier:
[code] Request request = messageFactory.createRequest( requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards); ...
Note the use of
MessageFactoryfor this step.
Then let's add other elements to the message: a
contact header and the contents of the message (payload). It's possible
to add custom headers too at this point.
[code] SipURI contactURI = addressFactory.createSipURI(getUsername(), getHost()); contactURI.setPort(getPort()); Address contactAddress = addressFactory.createAddress(contactURI); contactAddress.setDisplayName(getUsername()); ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress); request.addHeader(contactHeader); ContentTypeHeader contentTypeHeader = headerFactory.createContentTypeHeader("text", "plain"); request.setContent(message, contentTypeHeader); ...
For more information on how to further massage the request, there's a description of the
Requestinterface in appendix.
Lastly, you send the message using the
SipProviderinstance:
[code] sipProvider.sendRequest(request); }
Sending Messages Inside a Dialog
You're sending our message outside a dialog. Thatmeans messages are not related to each other. This works well for a
simple instant-messaging application like the TextClient.
An alternative would be to create a dialog
(sometimes called a session) using an INVITE message, and then send
messages inside this dialog. The TextClient doesn't use this technique.
However, I think it's something worth learning. So as a compromise,
this subsection describes how it's done.
Sending a message inside a dialog requires the creation of
Dialogand
Transaction
objects. On the initial message (that is, the message that creates the
dialog), instead of using the provider to send out the message, you
instantiate a
Transactionand then get the
Dialogfrom it. You keep the
Dialogreference for later. You then use the
Transactionto send the message:
[code]ClientTransaction trans = sipProvider.getNewClientTransaction(invite); dialog = trans.getDialog(); trans.sendRequest();
Later when you wish to send a new message inside the same dialog, you use the
Dialogobject from before to create a new request. You can then massage the request and, lastly, use the
Transactionto send out the message.
[code]request = dialog.createRequest(Request.MESSAGE); request.setHeader(contactHeader); request.setContent(message, contentTypeHeader); ClientTransaction trans = sipProvider.getNewClientTransaction(request); trans.sendRequest();
Essentially, you're skipping the "create main
elements" step when sending a message inside an existing dialog. When
you use an INVITE to create a dialog, don't forget to clean it up by
sending an in-dialog BYE message at the end. This technique is also
used to refresh registrations and subscriptions.
Previously, you've seen the
SipListenerinterface, which contains the
processDialogTerminated()and
processTransactionTerminated()
methods. These are called automatically at the end of a dialog and
transaction, respectively. Typically, you implement these methods to
clean things up (for example, discard the
Dialogand
Transactioninstances). You'll leave these two methods empty as you don't need them in TextClient.
Receiving a Response
Earlier, you registered a listener of incoming messages. The listener interface,SipListener, contains the method
processResponse(), which is called by the SIP stack when a SIP response message arrives.
processResponse()takes a single parameter of type
ResponseEvent, which encapsulates a
Responseobject. Let's implement this method now.
[code]public void processResponse(ResponseEvent evt) { Response response = evt.getResponse(); int status = response.getStatusCode(); if( (status >= 200) && (status < 300) ) { //Success! messageProcessor.processInfo("--Sent"); return; } messageProcessor.processError("Previous message not sent: " + status); }
In this method you check if the response of an
earlier MESSAGE message represents a success (2xx range of status
codes) or an error (otherwise). You then relay this information back to
the user through the callback interface.
Typically, you read only the
Responseobject in the
processResponse()
method. The only exception is for a success response to an INVITE
message; in this case, you must send an ACK request right back, like
this:
[code]Dialog dialog = evt.getClientTransaction().getDialog() Request ack = dialog.createAck() dialog.sendAck( ack );
For a description of the
Responseinterface, refer to the Appendix.
Receiving a Request
Receiving a SIP request message is just as easy as receiving a response. You just implement another method of theSipListenerinterface,
processRequest(), and the SIP stack will call it automatically. The single parameter of this method is a
RequestEventobject, which contains (you guessed it) a
Request
object. This is the same type that you've seen before, and it has the
same methods. However, you shouldn't set any fields on an incoming
request as it doesn't make much sense.
A typical implementation of
processRequest()analyzes the request, and then creates and sends back an appropriate response. This is what you'll do now:
[code]public void processRequest(RequestEvent evt) { Request req = evt.getRequest(); String method = req.getMethod(); if( ! method.equals("MESSAGE")) { //bad request type. messageProcessor.processError("Bad request type: " + method); return; } FromHeader from = (FromHeader)req.getHeader("From"); messageProcessor.processMessage( from.getAddress().toString(), new String(req.getRawContent())); Response response=null; try { //Reply with OK response = messageFactory.createResponse(200, req); ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME); toHeader.setTag("888"); //Identifier, specific to your application ServerTransaction st = sipProvider.getNewServerTransaction(req); st.sendResponse(response); } catch (Throwable e) { e.printStackTrace(); messageProcessor.processError("Can't send OK reply."); } }
In this case, you always reply with a success
response (200), but you could also send back any of the error responses
(typically 4xx range). Here's a useful list of SIP status codes.
Dealing With Error Conditions
There are other methods in theSipListener
interface that you haven't implemented yet. They are called by the SIP
stack when a request cannot be sent for specific reasons. For example,
the
processTimeout()is called when the end point
receiving the message doesn't answer in time. This is a special
situation for which there is no response, so no
Responseobject is available. The
TimeoutEventparameter contains, among other things, the
ClientTransaction
of the request that timed out, and you can use this to link back to the
original request if you want to. In this implementation you simply
inform the user using the callback interface:
[code]public void processTimeout(TimeoutEvent evt) { messageProcessor.processError("Previous message not sent: " + "timeout"); }
Similarily, Input/Output (IO) errors are processed using the following method:
[code]public void processIOException(IOExceptionEvent evt) { messageProcessor.processError("Previous message not sent: " + "I/O Exception"); }
Point-to-Point vs. Client/Server
SIP client applications can be used standalone(point to point) or together with a server to provide extra
functionality like proxying or call routing.
I suggest you have a look at my Aarticle on SIP
Servlets. It contains a neat SIP Server application that can work with
TextClient to provide a chat room-type service. This illustrates how
you can use the TextClient together with the BEA WebLogic SIP Server
and double its usefulness.
Download
Download the TextClient source code here.Summary
This article provides an overview of the JAIN SIPAPI, and I've shown how to write a simple application to use this
technology. Right now, you should have a pretty good idea of the APIs
available, and know how to write your own IM client with SIP.
Nevertheless, why stop here? I could add many more
features to this application. And as I said before, if the client talks
with a server application, you can double its usefulness. If you need
suggestions, consider the following:
Automatic text answers, store-and-forward
(for example, "John is offline right now, but he will receive your
messages as soon as he logs back in")
A neat networked checkers video game
A location-based service for your laptop
A media-sharing client
An RSS-like client
The possibilities are almost limitless.
References
A concise tutorial,including SIP message formats. Be sure to read the section "Relation
among Call, Dialog, Transaction & Message" (external tutorial)
Standard SIP stack properties
Non-standard SIP stack properties of the reference implementation
SIP status codes
RTP stack
SIP Communicator (java.net project)
Appendix
This section is a reference to the various classes and interfaces available in the JAIN SIP API.API overview
Here's an overview of the main classes and interfaces found in the JAIN SIP API reference implementation.Class / Interface | Description |
---|---|
SipFactory / AddressFactory / HeaderFactory / MessageFactory | Factory classes to create the various objects of the system. They return objects that implement standard interfaces. |
SipStack | The first interface you'll need, used to create ListeningPoints and SipProviders. |
ListeningPoint | This interface encapsulates a transport/port pair (for example, UDP/5060). |
SipProvider | This interface is used to send SIP messages. You can also register a listener for incoming SIP messages using this interface. See SipListenerbelow. |
SipListener | You must implement this interface to allow receiving incoming SIP messages. |
RequestEvent / ResponseEvent | Represent an incoming SIP request, response. Passed to your SipListenerfor processing. Contains a Requestor Responseobject, respectively. |
TimeoutEvent | Represents a failure condition when there's no reply to an outgoing request. Passed to your SipListenerfor processing. |
IOExceptionEvent | Represents a failure condition when there's an Input/Output problem sending an outgoing request. Passed to your SipListenerfor processing. |
Request / Response | Represent a SIP request, response. Both are sub-interfaces of the Messageinterface. They provide access to headers, content, and other parts of SIP messages. |
Dialog | An object of this interface encapsulates a SIP dialog. (Reminder: In a dialog all messages are related to the same call; a dialog often starts with an INVITE and ends with a BYE.) |
ClientTransaction / ServerTransaction | Encapsulate SIP transactions. (Reminder: A transaction starts with a request and ends with a final response. Transactions often live within a dialog.) |
Message
Interface
The Messageinterface is the base interface for SIP messages. For your reference, here's an overview of available methods.
Method | Description |
---|---|
void addHeader(Header) void setHeader(Header) | Sets header fields to the SIP message. The first method can be used for headers that are repeatable or can have multiple values, like the Contact header. The second method removes existing headers of this type and then adds a single header value. |
void removeHeader(Header) | Removes existing headers of this type. |
ListIterator getHeaderNames() | Returns all header names. |
ListIterator getUnrecognizedHeaders() | Returns header names for non-standard header types. |
Header getHeader(String) ListIterator getHeaders(String) | Getters for specific headers. The second form returns all values of repeatable headers, or headers with multiple values, like the Contact header. |
void setContent(Object, ContentTypeHeader) | Sets the payload of the message, as well as the Content-Type header. Content-Length is also set if the type is a string, else use void setContentLength(ContentLengthHeader). |
byte [] getRawContent() Object getContent() | Retrieves the payload of the message. |
void removeContent() | Empties the payload. |
void setContentLength(ContentLengthHeader) ContentLengthHeader getContentLength() void setContentLanguage(ContentLanguageHeader) ContentLanguageHeader getContentLanguage() void setContentEncoding(ContentEncodingHeader) ContentEncodingHeader getContentEncoding() void setContentDisposition(ContentDispositionHeader) ContentDispositionHeader getContentDisposition() | Special payload-related header accessors. Rarely used. |
void setExpires(ExpiresHeader) ExpiresHeader getExpires() | Manages the Expires header. |
void setSipVersion(String) String getSipVersion() | Accessors for the SIP version element. Rarely used, defaults to SIP/2.0. |
Object clone() | Creates a copy of the message. Rarely used. |
Request
interface
Now let's glance through the Requestinterface (sub-interface of
Messageabove):
Method | Description |
---|---|
String getMethod() void setMethod(String) | Accessors for the method element. Can be any SIP method, including those in the constants of the Requestinterface: ACK, BYE, CANCEL, INVITE, OPTIONS, REGISTER, NOTIFY, SUBSCRIBE, MESSAGE, REFER, INFO, PRACK, and UPDATE. |
URI getRequestURI() void setRequestURI(URI) | Accessors for the request URI, which is the first line of a SIP request. Typically, this is an instance of SipURI. |
Response
interface
The Responseinterface also extends the
Messageinterface:
Method | Description |
---|---|
void setStatusCode() int getStatusCode() | Accessors for the status code. This can be any SIP status code, including those in the constant members of the Responseinterface. Here are a few of them: RINGING (180), OK (200), BAD_REQUEST (400), and so on. |
void setReasonPhrase(String) String getReasonPhrase() | Accessors for the human-readable explanation of the status code. |
certified WebLogic Server engineer.
相关文章推荐
- VoIP in-depth: An introduction to the SIP protocol, Part 1
- VoIP in-depth: An introduction to the SIP protocol, Part 1-2
- VoIP in-depth: An introduction to the SIP protocol, Part 2
- An Introduction to RDF and the Jena RDF API
- VoIP in-depth: An introduction to the SIP protocol, Part 2 , 3-4
- An Introduction to the Java Logging API (part)
- An Introduction to RDF and the Jena RDF API
- Jena文档《An Introduction to RDF and the Jena RDF API》的译文
- [转]Introduction to JAIN SIP API part1
- Jena文档《An Introduction to RDF and the Jena RDF API》的译文
- [转]Introduction to JAIN SIP API part2
- Apache Jena (2) ---- An Introduction to RDF and the Jena RDF API
- [转]Introduction to JAIN SIP API part3_FINAL
- Jena文档《An Introduction to RDF and the Jena RDF API》的译文
- Understanding Windows CardSpace: An Introduction to the Concepts and Challenges of Digital Identitie
- An Introduction to the Theory of Computation
- An Introduction to the CAN Bus: How to Programmatically Control a Car
- checked_delete问题: Beyond the C++ STL: an introduction to boostdeleter::do_it
- An basic introduction to SIP
- Minds and Computers: An Introduction to the Philosophy of Artificial Intelligence