Methods Summary |
---|
public void | addExtensionMethod(java.lang.String extensionMethod)Adds an extension method.
if (! extensionMethod.equals(Request.NOTIFY)) {
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"NOTIFY Supported Natively");
}
} else {
this.dialogCreatingMethods.put(extensionMethod, "");
}
|
public void | addTransaction(ClientTransaction clientTransaction)Adds a new client transaction to the set of existing transactions.
synchronized (clientTransactions) {
clientTransactions.addElement(clientTransaction);
}
|
public void | addTransaction(ServerTransaction serverTransaction)Adds a new client transaction to the set of existing transactions.
synchronized (serverTransactions) {
this.serverTransactions.addElement(serverTransaction);
}
|
public boolean | allowDialogStateChange(java.lang.String method)Returns true if method can change dialog state.
return dialogCreatingMethods.containsKey(method.toUpperCase()) ||
method.equalsIgnoreCase(Request.BYE) ||
method.equalsIgnoreCase(Request.NOTIFY);
|
public ClientTransaction | createClientTransaction(MessageChannel encapsulatedMessageChannel)Creates a client transaction that encapsulates a MessageChannel.
Useful for implementations that want to subclass the standard
return new ClientTransaction
(this, encapsulatedMessageChannel);
|
public synchronized Dialog | createDialog(Transaction transaction)Creates a new dialog for requested transaction.
Request sipRequest = transaction.getOriginalRequest();
Dialog retval = new Dialog(transaction);
return retval;
|
public MessageChannel | createMessageChannel(Hop nextHop)Creates a client transaction to handle a new request.
Gets the real
message channel from the superclass, and then creates a new client
transaction wrapped around this channel.
synchronized (clientTransactions) {
// New client transaction to return
Transaction returnChannel;
// Create a new client transaction around the
// superclass' message channel
MessageChannel mc = super.createMessageChannel(nextHop);
if (mc == null)
return null;
returnChannel =
createClientTransaction(mc);
clientTransactions.addElement(returnChannel);
((ClientTransaction)returnChannel).setViaPort(nextHop.getPort());
((ClientTransaction)returnChannel).setViaHost(nextHop.getHost());
return returnChannel;
}
|
public MessageChannel | createMessageChannel(MessageChannel rawChannel)Creates a client transaction from a raw channel.
synchronized (clientTransactions) {
// New client transaction to return
Transaction returnChannel =
createClientTransaction(rawChannel);
clientTransactions.addElement(returnChannel);
((ClientTransaction)returnChannel).setViaPort
(rawChannel.getViaPort());
((ClientTransaction)returnChannel).setViaHost
(rawChannel.getHost());
return returnChannel;
}
|
public MessageChannel | createMessageChannel(Transaction transaction)Creates a client transaction from a raw channel.
synchronized (clientTransactions) {
// New client transaction to return
Transaction returnChannel =
createClientTransaction(transaction.getMessageChannel());
clientTransactions.addElement(returnChannel);
((ClientTransaction)returnChannel).setViaPort
(transaction.getViaPort());
((ClientTransaction)returnChannel).setViaHost
(transaction.getViaHost());
return returnChannel;
}
|
private void | createOrTerminateDialog(Request requestReceived)Creates or terminates a dialog if a subscription matching the given
NOTIFY request exists. To create a dialog a list of transactions
is searched for the matching transaction and then the corresponding
SipClientConnection is notified. To terminate a dialog a list of
dialogs is searched for the existing subscription that matches
the given NOTIFY request.
// System.out.println(">>> NOTIFY: Scanning dialogs...");
synchronized (dialogTable) {
Enumeration e = dialogTable.elements();
while (e.hasMoreElements()) {
Dialog nextDialog = (Dialog)e.nextElement();
Subscription s = nextDialog.subscriptionList.
getMatchingSubscription(requestReceived);
if (s != null) {
SubscriptionStateHeader ssh = (SubscriptionStateHeader)
requestReceived.getHeader(Header.SUBSCRIPTION_STATE);
if (ssh != null && ssh.isTerminated()) {
nextDialog.subscriptionList.removeSubscription(s);
} else {
nextDialog.setState(Dialog.CONFIRMED_STATE);
}
return;
}
}
}
// System.out.println(">>> NOTIFY: Scanning transactions...");
// Iterator through all client transactions
Enumeration transactionIterator;
ClientTransaction currClientTransaction = null;
// Loop through all client transactions
synchronized (clientTransactions) {
transactionIterator = clientTransactions.elements();
currClientTransaction = null;
String receivedToTag = requestReceived.getToTag();
CallIdHeader receivedCid = requestReceived.getCallId();
EventHeader receivedEvent = (EventHeader)
requestReceived.getHeader(Header.EVENT);
while (transactionIterator.hasMoreElements()) {
currClientTransaction =
(ClientTransaction)transactionIterator.nextElement();
Request request = currClientTransaction.getRequest();
String method = request.getMethod();
String fromTag = request.getFromHeaderTag();
CallIdHeader cid = request.getCallId();
EventHeader hEvent = (EventHeader)
request.getHeader(Header.EVENT);
boolean isSameEvent = (hEvent != null) &&
hEvent.match(receivedEvent);
if (((method.equals(Request.SUBSCRIBE) && isSameEvent) ||
method.equals(Request.REFER)) &&
fromTag != null && fromTag.equals(receivedToTag) &&
cid != null && cid.equals(receivedCid)) {
SipClientConnectionImpl sipClientConnection =
(SipClientConnectionImpl)
currClientTransaction.getApplicationData();
if (sipClientConnection != null) {
sipClientConnection.handleMatchingNotify(
requestReceived);
} else {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING,
LogChannels.LC_JSR180,
"SIPTransactionStack.createOrTerminateDialog(): " +
"Cannot find SCC for the given NOTIFY.");
}
}
break;
}
}
}
|
public MessageChannel | createRawMessageChannel(Hop hop)Creates a raw message channel. A raw message channel has no
transaction wrapper.
return super.createMessageChannel(hop);
|
public ServerTransaction | createServerTransaction(MessageChannel encapsulatedMessageChannel)Creates a server transaction that encapsulates a MessageChannel.
Useful for implementations that want to subclass the standard
return new ServerTransaction
(this, encapsulatedMessageChannel);
|
public Transaction | findCancelTransaction(Request cancelRequest, boolean isServer)Gets the transaction to cancel. Search the server transaction
table for a transaction that matches the given transaction.
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"findCancelTransaction request = \n"
+ cancelRequest +
"\nfindCancelRequest isServer = " + isServer);
}
if (isServer) {
synchronized (this.serverTransactions) {
Enumeration li = this.serverTransactions.elements();
while (li.hasMoreElements()) {
Transaction transaction =
(Transaction)li.nextElement();
Request sipRequest =
(Request) (transaction.getRequest());
ServerTransaction sipServerTransaction =
(ServerTransaction) transaction;
if (sipServerTransaction.doesCancelMatchTransaction
(cancelRequest))
return sipServerTransaction;
}
}
} else {
synchronized (this.clientTransactions) {
Enumeration li = this.clientTransactions.elements();
while (li.hasMoreElements()) {
Transaction transaction = (Transaction)li.nextElement();
Request sipRequest =
(Request) (transaction.getRequest());
ClientTransaction sipClientTransaction =
(ClientTransaction) transaction;
if (sipClientTransaction.doesCancelMatchTransaction
(cancelRequest))
return sipClientTransaction;
}
}
}
return null;
|
public ClientTransaction | findSubscribeTransaction(Request notifyMessage)Finds a matching client SUBSCRIBE to the incoming notify.
NOTIFY requests are matched to such SUBSCRIBE requests if they
contain the same "Call-ID", a "ToHeader" header "tag" parameter which
matches the "FromHeader" header "tag" parameter of the SUBSCRIBE, and the
same "Event" header field. Rules for comparisons of the "Event"
headers are described in section 7.2.1. If a matching NOTIFY request
contains a "Subscription-State" of "active" or "pending", it creates
a new subscription and a new dialog (unless they have already been
created by a matching response, as described above).
synchronized (clientTransactions) {
Enumeration it = clientTransactions.elements();
String thisToHeaderTag = notifyMessage.getTo().getTag();
if (thisToHeaderTag == null)
return null;
EventHeader eventHdr =
(EventHeader)notifyMessage.getHeader(Header.EVENT);
if (eventHdr == null)
return null;
while (it.hasMoreElements()) {
ClientTransaction ct =
(ClientTransaction)it.nextElement();
Request sipRequest = ct.getOriginalRequest();
String fromTag = sipRequest.getFromHeader().getTag();
EventHeader hisEvent =
(EventHeader)sipRequest.getHeader(Header.EVENT);
// Event header is mandatory but some slopply clients
// dont include it.
if (hisEvent == null) continue;
if (sipRequest.getMethod().equals(Request.SUBSCRIBE) &&
Utils.equalsIgnoreCase(fromTag, thisToHeaderTag) &&
hisEvent != null && eventHdr.match(hisEvent) &&
Utils.equalsIgnoreCase
(notifyMessage.getCallId().getCallId(),
sipRequest.getCallId().getCallId()))
return ct;
}
}
return null;
|
public Transaction | findTransaction(Message sipMessage, boolean isServer)Finds the transaction corresponding to a given request.
if (isServer) {
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"searching server transaction for "
+ sipMessage + " size = " +
this.serverTransactions.size());
}
synchronized (this.serverTransactions) {
Enumeration it = serverTransactions.elements();
while (it.hasMoreElements()) {
ServerTransaction sipServerTransaction =
(ServerTransaction)it.nextElement();
if (sipServerTransaction
.isMessagePartOfTransaction(sipMessage))
return sipServerTransaction;
}
}
} else {
synchronized (this.clientTransactions) {
Enumeration it = clientTransactions.elements();
while (it.hasMoreElements()) {
ClientTransaction clientTransaction =
(ClientTransaction)it.nextElement();
if (clientTransaction
.isMessagePartOfTransaction(sipMessage))
return clientTransaction;
}
}
}
return null;
|
public Dialog | getDialog(java.lang.String dialogId)Returns the dialog for a given dialog ID. If compatibility is
enabled then we do not assume the presence of tags and hence
need to add a flag to indicate whether this is a server or
client transaction.
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"Getting dialog for " + dialogId);
}
synchronized (dialogTable) {
return (Dialog)dialogTable.get(dialogId);
}
|
public boolean | isDialogCreated(java.lang.String method)Returns true if extension is supported.
// printDialogCreatingMethods();
// System.out.println("CHECKING IF DIALOG HAS BEEN CREATED"
// + " FOR THE FOLLOWING METHOD"
// + method.toUpperCase());
return dialogCreatingMethods.containsKey(method.toUpperCase());
|
protected SIPServerRequestInterface | newSIPServerRequest(Request requestReceived, MessageChannel requestMessageChannel)Handles a new SIP request.
It finds a server transaction to handle
this message. If none exists, it creates a new transaction.
try {
// Iterator through all server transactions
Enumeration transactionIterator;
// Next transaction in the set
ServerTransaction nextTransaction;
// Transaction to handle this request
ServerTransaction currentTransaction = null;
if (requestReceived.getMethod().equals(Request.NOTIFY)) {
createOrTerminateDialog(requestReceived);
}
// Loop through all server transactions
synchronized (serverTransactions) {
transactionIterator = serverTransactions.elements();
currentTransaction = null;
while (transactionIterator.hasMoreElements() &&
currentTransaction == null) {
nextTransaction =
(ServerTransaction)transactionIterator.nextElement();
// If this transaction should handle this request,
if (!nextTransaction.isTerminated() &&
nextTransaction.isMessagePartOfTransaction(
requestReceived)) {
// Mark this transaction as the one
// to handle this message
currentTransaction = nextTransaction;
}
}
// If no transaction exists to handle this message
if (currentTransaction == null) {
currentTransaction =
createServerTransaction(requestMessageChannel);
currentTransaction.setOriginalRequest(requestReceived);
if (!isDialogCreated(requestReceived.getMethod())) {
/*
* IMPL_NOTE: remove the following block of code
* after ensuring that it doesn't break anything.
*/
/*
// Dialog is not created - can we find the state?
// If so, then create a transaction and add it.
String dialogId = requestReceived.getDialogId(true);
Dialog dialog = getDialog(dialogId);
// Sequence numbers are supposed to increment.
// avoid processing old sequence numbers and
// delivering the same request up to the
// application if the request has already been seen.
// Special handling applies to ACK processing.
if (dialog != null &&
(requestReceived.getMethod().equals(Request.ACK)
|| requestReceived.getCSeqHeader()
.getSequenceNumber() >
dialog.getRemoteSequenceNumber())) {
// Found a dialog.
if (Logging.REPORT_LEVEL <=
Logging.INFORMATION) {
Logging.report(Logging.INFORMATION,
LogChannels.LC_JSR180,
"adding server transaction " +
currentTransaction);
}
serverTransactions.addElement(currentTransaction);
currentTransaction.isMapped = true;
}
*/
// Server transactions must always be added
// to the corresponding vector.
serverTransactions.addElement(currentTransaction);
currentTransaction.isMapped = true;
} else {
// Create the transaction but dont map it.
String dialogId = requestReceived.getDialogId(true);
Dialog dialog = getDialog(dialogId);
// This is a dialog creating request that is
// part of an existing dialog
// (eg. re-Invite). Re-invites get a non null
// server transaction Id (unlike the original
// invite).
if (dialog != null &&
requestReceived.getCSeqHeader().getSequenceNumber()
> dialog.getRemoteSequenceNumber()) {
try {
currentTransaction.map();
} catch (IOException ex) {
/* Ignore */
}
}
serverTransactions.addElement(currentTransaction);
currentTransaction.toListener = true;
}
}
// attach to request
requestReceived.setTransaction(currentTransaction);
// Set ths transaction's encapsulated request
// interface from the superclass
currentTransaction.setRequestInterface
(super.newSIPServerRequest
(requestReceived, currentTransaction));
return currentTransaction;
}
} catch (RuntimeException ex) {
ex.printStackTrace();
throw ex;
}
|
SIPServerResponseInterface | newSIPServerResponse(Response responseReceived, MessageChannel responseMessageChannel)Handles a new SIP response.
It finds a client transaction to handle
this message. If none exists, it sends the message directly to the
superclass.
// System.out.println("response = " + responseReceived.encode());
// Iterator through all client transactions
Enumeration transactionIterator;
// Next transaction in the set
ClientTransaction nextTransaction;
// Transaction to handle this request
ClientTransaction currentTransaction;
// Loop through all client transactions
synchronized (clientTransactions) {
transactionIterator = clientTransactions.elements();
currentTransaction = null;
int i = -1;
while (transactionIterator.hasMoreElements() &&
currentTransaction == null) {
i++;
nextTransaction =
(ClientTransaction)transactionIterator.nextElement();
// If this transaction should handle this request,
if (nextTransaction.isMessageTransOrMult(responseReceived)) {
if (nextTransaction.isMultipleResponse(responseReceived)) {
// RFC 3261, 13.2.2.4:
// Multiple 2xx responses may arrive at the UAC for
// a single INVITE request due to a forking proxy.
// create a new client transaction
currentTransaction =
nextTransaction.cloneWithNewLastResponse
(responseReceived);
currentTransaction.setState
(Transaction.PROCEEDING_STATE);
currentTransaction.setApplicationData
(nextTransaction.getApplicationData());
Dialog dialog = new Dialog(currentTransaction);
dialog.setDialogId(responseReceived.getDialogId(false));
dialog.setRemoteTag(responseReceived.getToTag());
dialog.setStack(this);
putDialog(dialog);
currentTransaction.setDialog(dialog);
// change from old to new transaction
clientTransactions.setElementAt(currentTransaction, i);
} else { // not multiple response
// Mark this transaction as the one to
// handle this message
currentTransaction = nextTransaction;
}
}
}
}
// If no transaction exists to handle this message,
if (currentTransaction == null) {
// Pass the message directly to the TU
return super.newSIPServerResponse
(responseReceived, responseMessageChannel);
}
// Set ths transaction's encapsulated response interface
// from the superclass
currentTransaction.setResponseInterface(super.newSIPServerResponse
(responseReceived,
currentTransaction));
return currentTransaction;
|
private void | printDialogCreatingMethods()Prints the Dialog creating methods.
System.out.println("PRINTING DIALOGCREATINGMETHODS HASHTABLE");
Enumeration e = dialogCreatingMethods.keys();
while (e.hasMoreElements()) {
System.out.println(e.nextElement());
}
System.out.println("DIALOGCREATINGMETHODS HASHTABLE PRINTED");
|
public void | putDialog(Dialog dialog)Puts a dialog into the dialog table.
String dialogId = dialog.getDialogId();
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"putDialog dialogId=" + dialogId);
}
// if (this.getDefaultRouteHeader() != null)
// dialog.addRoute(this.getDefaultRouteHeader(), false);
dialog.setStack(this);
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
// new Exception().printStackTrace();
}
synchronized (dialogTable) {
dialogTable.put(dialogId, dialog);
}
|