TransactionUnavailableException {
if (!sipStack.isAlive())
throw new TransactionUnavailableException("Stack is stopped");
SIPServerTransaction transaction = null;
SIPRequest sipRequest = (SIPRequest) request;
try {
sipRequest.checkHeaders();
} catch (ParseException ex) {
throw new TransactionUnavailableException(ex.getMessage(), ex);
}
if ( request.getMethod().equals(Request.ACK)) {
if ( sipStack.isLoggingEnabled())
sipStack.getStackLogger().logError("Creating server transaction for ACK -- makes no sense!");
throw new TransactionUnavailableException("Cannot create Server transaction for ACK ");
}
/*
* Got a notify.
*/
if (sipRequest.getMethod().equals(Request.NOTIFY)
&& sipRequest.getFromTag() != null
&& sipRequest.getToTag() == null) {
SIPClientTransaction ct = sipStack.findSubscribeTransaction(
sipRequest, (ListeningPointImpl) this.getListeningPoint());
/* Issue 104 */
if (ct == null && ! sipStack.isDeliverUnsolicitedNotify()) {
throw new TransactionUnavailableException(
"Cannot find matching Subscription (and gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY not set)");
}
}
if ( !sipStack.acquireSem()) {
throw new TransactionUnavailableException(
"Transaction not available -- could not acquire stack lock");
}
try {
if (sipStack.isDialogCreated(sipRequest.getMethod())) {
if (sipStack.findTransaction((SIPRequest) request, true) != null)
throw new TransactionAlreadyExistsException(
"server transaction already exists!");
transaction = (SIPServerTransaction) ((SIPRequest) request)
.getTransaction();
if (transaction == null)
throw new TransactionUnavailableException(
"Transaction not available");
if (transaction.getOriginalRequest() == null)
transaction.setOriginalRequest(sipRequest);
try {
sipStack.addTransaction(transaction);
} catch (IOException ex) {
throw new TransactionUnavailableException(
"Error sending provisional response");
}
// So I can handle timeouts.
transaction.addEventListener(this);
if (isAutomaticDialogSupportEnabled()) {
// If automatic dialog support is enabled then
// this tx gets his own dialog.
String dialogId = sipRequest.getDialogId(true);
SIPDialog dialog = sipStack.getDialog(dialogId);
if (dialog == null) {
dialog = sipStack.createDialog(transaction);
}
transaction.setDialog(dialog, sipRequest.getDialogId(true));
if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) {
sipStack.putInMergeTable(transaction, sipRequest);
}
dialog.addRoute(sipRequest);
if (dialog.getRemoteTag() != null
&& dialog.getLocalTag() != null) {
this.sipStack.putDialog(dialog);
}
}
} else {
if (isAutomaticDialogSupportEnabled()) {
/*
* Under automatic dialog support, dialog is tied into a transaction. You cannot
* create a server tx except for dialog creating transactions. After that, all
* subsequent transactions are created for you by the stack.
*/
transaction = (SIPServerTransaction) sipStack.findTransaction(
(SIPRequest) request, true);
if (transaction != null)
throw new TransactionAlreadyExistsException(
"Transaction exists! ");
transaction = (SIPServerTransaction) ((SIPRequest) request)
.getTransaction();
if (transaction == null)
throw new TransactionUnavailableException(
"Transaction not available!");
if (transaction.getOriginalRequest() == null)
transaction.setOriginalRequest(sipRequest);
// Map the transaction.
try {
sipStack.addTransaction(transaction);
} catch (IOException ex) {
throw new TransactionUnavailableException(
"Could not send back provisional response!");
}
// If there is a dialog already assigned then just update the
// dialog state.
String dialogId = sipRequest.getDialogId(true);
SIPDialog dialog = sipStack.getDialog(dialogId);
if (dialog != null) {
dialog.addTransaction(transaction);
dialog.addRoute(sipRequest);
transaction.setDialog(dialog, sipRequest.getDialogId(true));
}
} else {
transaction = (SIPServerTransaction) sipStack.findTransaction(
(SIPRequest) request, true);
if (transaction != null)
throw new TransactionAlreadyExistsException(
"Transaction exists! ");
transaction = (SIPServerTransaction) ((SIPRequest) request)
.getTransaction();
if (transaction != null) {
if (transaction.getOriginalRequest() == null)
transaction.setOriginalRequest(sipRequest);
// Map the transaction.
sipStack.mapTransaction(transaction);
// If there is a dialog already assigned then just
// assign the dialog to the transaction.
String dialogId = sipRequest.getDialogId(true);
SIPDialog dialog = sipStack.getDialog(dialogId);
if (dialog != null) {
dialog.addTransaction(transaction);
dialog.addRoute(sipRequest);
transaction.setDialog(dialog, sipRequest
.getDialogId(true));
}
return transaction;
} else {
// tx does not exist so create the tx.
MessageChannel mc = (MessageChannel) sipRequest
.getMessageChannel();
transaction = sipStack.createServerTransaction(mc);
if (transaction == null)
throw new TransactionUnavailableException(
"Transaction unavailable -- too many servrer transactions");
transaction.setOriginalRequest(sipRequest);
sipStack.mapTransaction(transaction);
// If there is a dialog already assigned then just
// assign the dialog to the transaction.
String dialogId = sipRequest.getDialogId(true);
SIPDialog dialog = sipStack.getDialog(dialogId);
if (dialog != null) {
dialog.addTransaction(transaction);
dialog.addRoute(sipRequest);
transaction.setDialog(dialog, sipRequest
.getDialogId(true));
}
return transaction;
}