* (non-Javadoc)
*
* @see javax.sip.ClientTransaction#sendRequest()
*/
public void sendRequest() throws SipException {
SIPRequest sipRequest = this.getOriginalRequest();
if (this.getState() != null)
throw new SipException("Request already sent");
if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
sipStack.getStackLogger().logDebug("sendRequest() " + sipRequest);
}
try {
sipRequest.checkHeaders();
} catch (ParseException ex) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logError("missing required header");
throw new SipException(ex.getMessage());
}
if (getMethod().equals(Request.SUBSCRIBE)
&& sipRequest.getHeader(ExpiresHeader.NAME) == null) {
/*
* If no "Expires" header is present in a SUBSCRIBE request, the implied default is
* defined by the event package being used.
*
*/
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logWarning(
"Expires header missing in outgoing subscribe --"
+ " Notifier will assume implied value on event package");
}
try {
/*
* This check is removed because it causes problems for load balancers ( See issue
* 136) reported by Raghav Ramesh ( BT )
*
*/
if (this.getOriginalRequest().getMethod().equals(Request.CANCEL)
&& sipStack.isCancelClientTransactionChecked()) {
SIPClientTransaction ct = (SIPClientTransaction) sipStack.findCancelTransaction(
this.getOriginalRequest(), false);
if (ct == null) {
/*
* If the original request has generated a final response, the CANCEL SHOULD
* NOT be sent, as it is an effective no-op, since CANCEL has no effect on
* requests that have already generated a final response.
*/
throw new SipException("Could not find original tx to cancel. RFC 3261 9.1");
} else if (ct.getState() == null) {
throw new SipException(
"State is null no provisional response yet -- cannot cancel RFC 3261 9.1");
} else if (!ct.getMethod().equals(Request.INVITE)) {
throw new SipException("Cannot cancel non-invite requests RFC 3261 9.1");
}
} else
if (this.getOriginalRequest().getMethod().equals(Request.BYE)
|| this.getOriginalRequest().getMethod().equals(Request.NOTIFY)) {
SIPDialog dialog = sipStack.getDialog(this.getOriginalRequest()
.getDialogId(false));
// I want to behave like a user agent so send the BYE using the
// Dialog
if (this.getSipProvider().isAutomaticDialogSupportEnabled() && dialog != null) {
throw new SipException(
"Dialog is present and AutomaticDialogSupport is enabled for "
+ " the provider -- Send the Request using the Dialog.sendRequest(transaction)");
}
}
// Only map this after the fist request is sent out.
if (this.getMethod().equals(Request.INVITE)) {
SIPDialog dialog = this.getDefaultDialog();
if (dialog != null && dialog.isBackToBackUserAgent()) {
// Block sending re-INVITE till we see the ACK.
if ( ! dialog.takeAckSem() ) {
throw new SipException ("Failed to take ACK semaphore");
}
}
}
this.isMapped = true;
int expiresTime = -1;
if ( sipRequest.getHeader(ExpiresHeader.NAME) != null ) {
Expires expires = (Expires) sipRequest.getHeader(ExpiresHeader.NAME);
expiresTime = expires.getExpires();
}
// This is a User Agent. The user has specified an Expires time. Start a timer
// which will check if the tx is terminated by that time.
if ( this.getDefaultDialog() != null && getMethod().equals(Request.INVITE) &&