- Who owns NIST-SIP?
NIST owns it and has released it to the public domain as required
by act of U.S. Congress.
This includes the stack (gov.nist....) the SDP implementation, the
proxy, the trace viewer tool IM client and the TCK. Specific copyrights
apply everything else. These are noted in the code
and copyright statements included with the documents.
- What are the
restrictions on its use?
Do whatever you want with it but just dont demand support. If you do
use it in your product or project, be aware that it is experimental
code and is
therefore subject to frequent changes. Do acknowledge that your code
was
derived from NIST-SIP. It helps us keep the project alive.
- What is its
intended use?
JAIN-SIP/ NIST-SIP is meant for SIP developers. As such it is not a
stand-alone product.
Its primary use is for integrating SIP into your applications. If you
have an applicaton already and wish to SIP-enable it, JAIN-SIP/NIST-SIP
is a reasonable choice.
- Show me a quick
how-to
See examples/shootist. We'll be working several examples as time
permits.
- Why do I see a
lot of strange exceptions in the log file?
These are just for stack tracing (ok there are better ways to do this
under 1.4.2 but we want to be 1.3.1 and above compatible). The
implementation
does new Exception().printStack trace and captures the execution trace
in a file for later use.
- Why is there only
superficial resemblance between JAIN SIP 1.0 and
JAIN SIP 1.1?
- The previous API had a few problems.
These are documented in the JAIN-SIP-INTEREST
discussion list
- The scope of the specification was made broader (support for
dialogs,
Routers, support for SIMPLE REFER etc.).
- The RFC changed a lot over between 2543 and 3261.
- How involved is
it to port applications between JAIN-SIP 1.0 and JAIN-SIP
1.1
It is not difficult but it is not trivial. Anecdotal evidence indicates
several
hours or maybe a day or two of effort.
- Does the RI
support Re-Invite and how do I issue a re-invite?
Request inviteRequest = dialog.createRequest(Request.INVITE);
ClientTransaction ct = sipProvider.getNewClientTransaction(inviteRequest);
dialog.sendRequest(ct);
-
Is JAIN-SIP 1.2 Stateful/Stateless or DialogStateful?
Your application can choose its desired behavior. You
have the option to create a dialog for the first (dialog creating)
transaction. Once a dialog is created, however, all incoming requests
that belong to the dialog are automatically given a server transaction
and are hence handled statefully. You can also create dialogs
under program control and associate it with the Server or Client
Transaction ( new feature added for JAIN-SIP-1.2)
- Why does my
application get a null ServerTransaction for INVITE transactions
?
In order to support both statefull and stateless modes of operation,
the
INIVITE request gets delivered to your application with a null ServerTransaction. You
can choose to create a ServerTransacton and associated dialog using provider.getNewServerTransaction(inviteRequest)
- Who manages
From/To tags
From the client side, for the initial outgoing transaction, the
application
needs to specify a From tag. From the server side, the application
specifies
the initial To tag when responding to the request. After that, the
stack
manages things. Transactions are assigned to dialogs based on tags in
requests/respomses.
- Why
Dialog.sendRequest but no Dialog.sendResponse
Dialog.sendRequest uses route set and other dialog specific
information. Responses take all the information they need from the
transaction.
- Does the
Softphone work on Linux?
Yes. You need a 2.4 Kernel and the latest version of the Java Media
Framework.
- How do I cancel a
transaction.
Request cancelRequest = originalClientTransaction.createCancel();
ClientTransaction ct = sipProvider.getNewClientTransaction(cancelRequest);
ct.sendRequest();
- What is the
difference between Transaction.sendRequest,
Dialog.sendRequest and SipProvider.sendRequest
Dialog.sendRequest stamps the outgoing request with dialog state. This
includes
the local sequence number, Request URI and Route set. For requests
within
a dialog you should use Dialog.sendRequest. For sending request for a
transaction that is not associated with a Dialog, you should use
Transaction.sendRequest. For sending requests statelessly, you should
use
SipProvider.sendRequest. Stateless requests do not result in the
creation
of a new Transaction or Dialog.
- What does the
javax.sip.Router do?
The router routes requests outside a dialog. This would be a good place
to add customizations like
looking up in a location database or registry for forwarding requests
out of dialog.
- How much
backward compatibility with 2543 do you support
We do not guarantee complete backward compatibility with RFC 2543. We
support
it to the extent that the implementation does not break. If there is a
life
threatening conflict between RFC 2543 and RFC 3261, then RFC 3261 wins.
- What is the
difference between sending ACK for a transaction
and Dialog.sendRequest(Request.ACK) ?
The latter includes dialog state and places a fresh branch id in the
Via.
This ensures it will not match any transaction on the server. Use this
when
ACKing 2xx responses and the former when ACKing error directed towards
a transction (3xx) and the like.
- What is the
Provider method for creating dialogs?
One of the new features added to JSIP-1.2 is to allow applications
the ability to have control over dialog creation. To enable, you
have to set AUTOMATIC_DIALOG_SUPPORT="off" when you create the stack.
You may also disable automatic dialog support on a per-provider basis.
Then use the method. SipProvider.getNewDialog(tansaction) to
create a dialog.
Under the stack configuration parameter, AUTOMATIC_DIALOG_SUPPORT="on" ,
Dialog creation and destruction is managed by the stack. When the
client transcaction is created, a Dialog is associated with it but
not mapped (its state is null). When you complete the transaction
successfully it actually gets mapped and a valid state is assigned to
it. On the server side, when you get the request, provided the method of
the request has the ability to create a Dialog, you can elect to create a
Dialog by creating a new Server Transaction at which point the stack
automatically creates a Dialog for transaction but defers actually
mapping it until a final response is sent out.
- I am constructing
a stateful proxy/B2BUA. I forward the request
after modifying it and then respond statefully. Why are the
tags/headers/something else modified in the response ?
NIST-SIP does not copy the request when it hands it over to the
listener. This is for efficiency. If you want to modify an outgoing
request (for example
if you are building a stateful proxy server or B2BUA) clone it.
JAIN-SIP
specifies a Deep cloning operation for this purpose.
- How to set up
MSN messenger for SIP?
MSN Messenger 4.7 (on windows XP) supports SIP but SIP support
is not working well on MSN 5.0 (on Win2K).
Enable communications services in Accounts tab. Go to Advanced and set
your proxy from there.
- Does NIST-SIP do
eager or lazy parsing? I see no parse exceptions on
get methods. What happened to all the JAIN SIP lazy parsing stuff?
The new JAIN Spec does not specify the type of parser to be employed.
An
implementation may employ lazy parsing. Parse failures are silent. If
something
parsing fails then the header is silently added
to the uparseable header list and null is returned to the application.
The application can later retrieve it as a String as an Unparseable
header.
This can happen either lazily or eagerly; however, Lazy/eager parsing
is
not exposed at the API level. NIST-SIP employs an eager strategy
(mostly
because of implementation ease). This is likely to be revised but your
app
does not get affected.
- What support is
provided for sending out-of-dialog requests?
Use clientTransaction.sendRequest(). This will get the next hop from
the
Router and use that to send the request. If you use dialog.sendRequest,
the next hop is obtained from the Dialog route set if one exists.
- How do I
communicate with the Router from the application?
This issue may arise when you want to use Loose or Strict routing. Only
the Application knows whether to use Loose or Strict Routing but the
Router
needs to decide the Next Hops. Thus we need to communicate with the
router.
Currently, it is a bit hacky. Use an extension header and place it in
the
Request then examine it in the Router. For example, use a header like
IS-STRICT-ROUTE which the router will see as an extension header and
strip off before deciding the next hop set.
- How are IO
Exceptions reported to the Application?
For JAIN-SIP 1.2, there is a new listener method for reporting IO Exceptions to
applications. Additionally, the Tranaction for which the
IO Exception is delivered will be immediately terminated.
- Why is the Transacton Request returned
from transaction.getRequest() set to null?
The client
transaction is only obliged to hold a reference to the Request until
the
transaction goes to COMPLETED state. After that, the reference to the
Request is nulled out to save heap space and ehance scalability of the
implementation. If you want to hold a long term reference to the
request,
then please do this in your application.
- How do you identify the listening point for an
incoming server transaction in the case where you are supporting
multiple
listening points?
SipProvider sipProvider = (SipProvider) sipEvent.getSource();
ListeningPoint lp = sipProvider.getListeningPoint();
- Why is my application getting Server Transaction
timeouts even
after I send response?
If the stack configuration property javax.sip.RETRANSMISSION_FILTER is
"false" or "off", for INVITE
Transactions, your application is alerted to send response periodically
until ACK is received from the client side. This happens through the
mechanism of your application fielding a Timeout Event.
- Why am I getting
a "Transaction not available" sip execption on
an incoming INVITE?
Check your application to see if you cloned the request before you
requested the server transaction. A Server transaction can only be
created for the incoming request that is identitically equal to the
incoming request that was received by the stack and not for a cloned
request. Further, you cannot cache the request and ask that a server
transaction be created at some future time. You must create the server
transaction synchronously when the request is delivered to
your application and not later.
-
How do you remove log4j for logging?
Because log4j is configured by default to log to a file, you may
want to remove it from the implementaton. Doing this is quite
simple - modify gov.nist.core.LogWriter.java. You can change
its behavior to log to a network connection or remove it entirely
and convert to println.
- I see a SIP message headed for my machine on Ethereal but my application (Listener) does not see it. Why ?
There could be one of several things going on:
- The message does not have a required header -
in which case the message is discarded and logged.
- The Listener may have blocked while processing a transaction.
Do not block in your listener method.
If you need to block, start a thread and block in it dont block in the
thread that you were called in the listener.
- The message may be stale (ie old sequence number). If the stack sees an in-dialog message that
does not have a valid sequence number, it will discard the message.
- The stack may be automatically re-transmitting the last response or the last Ack.
Once the transaction goes into completed state, the stack will manage it until it goes into
TERMINATED state
-
How do I ensure that the stack closes TCP connections after transaction completion?
The following two configuration parameters instruct the stack to close
TCP connections after a linger period:
gov.nist.javax.sip.CACHE_SERVER_CONNECTIONS=false
Default is true. Does reference counting for server transactions if
false and releases resources after refcount goes to 0.
gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS=false
Default is true. Does reference counting for client transactions and
releases socket and thread resources after refcount goes to 0.
Setting to false will close the connection and release any threads and
buffers after all transactions that use the connection have terminated
and a keepalive period (currently 32 sec) has expired. In some
circumstances (eg. if you are supporting NAT via tcp, then it may be
appropriate not to close server connections).
Defaults for these are true - which may be appropriate to do if you are burrowing through firewalls using tcp.
-
How do I limit the size of messages that the stack will accept?
For UDP this is not an issue. For TCP,
gov.nist.javax.sip.MAX_MESSAGE_SIZE=number
default for this property is inifinity (no limit).
-
While sending ACK request for 200 OK should I use transaction.createAck()
or Dialog.createRequest(Request.ACK)?
Use the following when ACKing final responses
Request ackRequest = dialog.createRequest(Request.ACK);
dialog.sendAck(ackRequest);
-
Can I run the stack in an applet?
Yes - take a look at jain-sip-applet-phone.dev.java.net. If your server
caches connections, you can use TCP sip transactions to transport chunks of
binary data and thereby construct an applet phone.
-
I want to be able to send SIP packets to different SIP servers using
different local identities. Any tips on how this is best handled
with this stack?
The way to do this through the router. Note that you can specify a Router
class implementation when the stack is created. The Router sets up the
path to the next hop. In your Router, look at the user trying to set up
the call and return the Hop implementation corresponding to the gateway
to which that user should be pointed to.
Note also that the Router is only used to route requests out of dialog -
which is to say it is used for pre-dialog establishment, requests that
dont belong to any particular dialog and stateless requests.
- The stack seems to be slow. Can you do something to improve performance?
This is a reference implementation. As such, the emphasis is on clarity
not performance. In its current state, the RI performs reasonably
well and is suited for client applications. You may need to do some
work by way of performance tuning to get it to work well in a high
performance server setting. In particular, you may wish to fine tune
object allocation, transaction location (searching for a transaction
that corresponds to an incoming message) and other such details.
- I downloaded a version of NIST-SIP some time ago and worked long
and hard to fix bugs and customize it.
It now works but lately I noticed a strange
bug. I am afraid of your changes so can you help me fix that vintage version?
This one's easy. NO. I do not have the time for this and even if I did, I
would consider it a waste of time. Please use cvs if you want to customize
your code and make sure you are up to date with the latest version before
you post bug reports. I cannot fix back level code.
- How can I take advantage of my multi-processor mutli-threaded machine
with dual headed monitors to get better performance out of NIST-SIP?
This may be of use when you are building a high performance server
software component. Inform the stack that your listener is re-entrant
using the gov.nist.javax.sip.stack.REENTRANT_LISTENER=true configuration
property. Manage the thread pool size to suit your needs. See the
gov.nist.javax.sip.stack.THREAD_POOL_SIZE=number configuration property.
Be careful that your listener is indeed re-entrant. The stack will parse,
manage the transaction state machine and call your listener code in the
same thread avoiding queueing.
- What dialog support is provided in JAIN-SIP?
JAIN-SIP allows for stateless or dialog stateful processing. Under
dialog stateful processing. Dialog support is provided to facilitate
in-dialog request generation, maintenance of route sets, maintenance
of sequence numbers and other dialog functionality that is specified in
Chapter 12 of the SIP RFC. Additionally, the dialog layer will shield your
application from out of sequence messages and generate appropriate error
responses when necessary. ( An implementation may choose to buffer early
arriving messages and deliver to the application at a later time.) No
dialog support is provided for authentication. This is an application
responsibility. In dialog requests are delvered to the application in
strict sequentially increasing order as specified in Chapter 12 of the
RFC 3261.
-
How do you make shootist shoot somewhere else (at another machine) ?
Change the variable peerHostPort in Shootist.java to whatever host
and port you want to shoot at (ie. where the shootme resides will be
a wise choice). Change change Shootme.java likewise.
You can also leave out the RouterImpl and HopImpl and
just use the default (just dont specify the stack configuration property
for ROUTER_PATH ). The example router was provided to show you how you
can write your own router (to look up DNS records for example).
- How do you find out which IP address and port a SIP Message arrived
on?
From the Listening Point on which the message was received, retrieve the IP
Address and Port.
- How do you enable/use the STUN support?
set the gov.nist.javax.sip.STUN_SERVER to point to
stun_server_ip_address[:port] where your stun server resides.
The stack will return mapped address when you
getIpAddress() from the stack and getPort() from the listening point.
With stun, if you have a NAT box, these will in general be different
from the IP address and port used to create the LP.
Your application needs to use these in setting up the contact address and
SDP parameters as appropriate. The stack is not responsible for this.
- Can you delay sending responses to requests until after the Listener runs ?
You cannot do this. You must respond to the request when the listener is
invoked. You must do this synchronously (not from another thread). This is
because housekeeping functions are performed after the listener completes
invocation.
- How do you build under IBM java implementation ?
A user sent in the following helpful tip: I needed to tell eclipse that
the files were "US-ASCII" rather than UTF-8.
Then I edited my build-config and added "-encoding US-ASCII" to the end
of the line that defines JAVAC for OS other than Windows_NT. Then "make
ri" completed without incident.
- What happens to Terminated Transactions ?
Once the Transaction is terminated, it is done and the server discards
records of it. Thus you can well see the following behavior:
- Other party sends INVITE, times out and retransmits several times
- The SipListener finally sees the first transmission and, being
busy, responds "503 service unavailable"
- Later, the SipListener sees one of the retransmissions. The
SipListener does not keep track of terminated calls, and since it now
has resources, it responds "200 OK"
- The other party ignores the "200 OK" since it already has seen the 503
- Eventually, the server INVITE transaction times out.
- How many calls per second can NIST-SIP handle?
NIST-SIP is suitable for most User Agent Applications. It can handle roughly
75 Calls/Second. Thats usually enough for your average desktop phone
unless you are an extremely busy person. Proxy server type applications
requiring higher thruput are best built as stateless applications
(ie. no transactions or dialogs are allocated). There are several
optimizations possible including the use of NIO and lazy parsing. These
will be implemented as time permits.
- I'm writing a SIP user agent to connect to various SIP resources,
and I'm having an issue where my SipListener is receiving unexpected
DialogTerminatedEvent's via processDialogTerminated (..). These appear
to happen almost exactly 40 seconds after an INVITE is processed,
so I'm assuming there's some sort of timeout issue at work here.
I am even sending an ACK for the Dialog.
Dear Abby, please tell me what is wrong with my application?
Check to see if you are using Dialog.sendAck in your application. You should
use Dialog.sendAck to send out the Ack if you have created a Dialog. Otherwise
the Dialog will time out after a period of time has expired.
- I really like my Router implementation and want to send subliminal suggestions
to him. How do I communicate with the Router
- Specify your Router implementation as a property when you create the stack. Then access
the created object using
Router myRouter = (MyRouter)sipStack.getRouter();
Now send your subliminal message to the Router using
myRouter.sendSubliminalMessage()
- I want to loosen up on the parsing of headers. However,
I cannot extend your Header implementation classes. If I supply my
own implementation of a header to setHeader, I get ClassCastException.
Why not let me extend the implementation classes or supply my own
Header implementation classes?
The point behind JAIN is to try to make your application portable
across different implementations of the standard. This includes Native
code implementations of the stack, Headers etc. If we allowed for
applications to be able to pass in their own implementations of Header
objects, this would not be possible. Hence, to simplify implementation
headaches, and ensure portability, a conscious decision was made to not
necessitate a requirement that a given provider be able to recognize
Header implementations other than those created by its own factory.
If you want to modify the way in which Headers are parsed etc. the
simplest thing to do would be to hack the source code.