use of javax.sip.SipException in project XobotOS by xamarin.
the class SipProviderImpl method sendRequest.
/*
* (non-Javadoc)
*
* @see javax.sip.SipProvider#sendRequest(javax.sip.message.Request)
*/
public void sendRequest(Request request) throws SipException {
if (!sipStack.isAlive())
throw new SipException("Stack is stopped.");
// message.
if (((SIPRequest) request).getRequestLine() != null && request.getMethod().equals(Request.ACK)) {
Dialog dialog = sipStack.getDialog(((SIPRequest) request).getDialogId(false));
if (dialog != null && dialog.getState() != null) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logWarning("Dialog exists -- you may want to use Dialog.sendAck() " + dialog.getState());
}
}
Hop hop = sipStack.getRouter((SIPRequest) request).getNextHop(request);
if (hop == null)
throw new SipException("could not determine next hop!");
SIPRequest sipRequest = (SIPRequest) request;
// Null request is used to send default proxy keepalive messages.
if ((!sipRequest.isNullRequest()) && sipRequest.getTopmostVia() == null)
throw new SipException("Invalid SipRequest -- no via header!");
try {
/*
* JvB: Via branch should already be OK, dont touch it here? Some
* apps forward statelessly, and then it's not set. So set only when
* not set already, dont overwrite CANCEL branch here..
*/
if (!sipRequest.isNullRequest()) {
Via via = sipRequest.getTopmostVia();
String branch = via.getBranch();
if (branch == null || branch.length() == 0) {
via.setBranch(sipRequest.getTransactionId());
}
}
MessageChannel messageChannel = null;
if (this.listeningPoints.containsKey(hop.getTransport().toUpperCase()))
messageChannel = sipStack.createRawMessageChannel(this.getListeningPoint(hop.getTransport()).getIPAddress(), this.getListeningPoint(hop.getTransport()).getPort(), hop);
if (messageChannel != null) {
messageChannel.sendMessage((SIPMessage) sipRequest, hop);
} else {
throw new SipException("Could not create a message channel for " + hop.toString());
}
} catch (IOException ex) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logException(ex);
}
throw new SipException("IO Exception occured while Sending Request", ex);
} catch (ParseException ex1) {
InternalErrorHandler.handleException(ex1);
} finally {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("done sending " + request.getMethod() + " to hop " + hop);
}
}
use of javax.sip.SipException in project XobotOS by xamarin.
the class AuthenticationHelperImpl method handleChallenge.
/*
* (non-Javadoc)
*
* @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#handleChallenge(javax.sip.message.Response,
* javax.sip.ClientTransaction, javax.sip.SipProvider)
*/
public ClientTransaction handleChallenge(Response challenge, ClientTransaction challengedTransaction, SipProvider transactionCreator, int cacheTime) throws SipException, NullPointerException {
try {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("handleChallenge: " + challenge);
}
SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest());
Request reoriginatedRequest = null;
/*
* If the challenged request is part of a Dialog and the
* Dialog is confirmed the re-originated request should be
* generated as an in-Dialog request.
*/
if (challengedRequest.getToTag() != null || challengedTransaction.getDialog() == null || challengedTransaction.getDialog().getState() != DialogState.CONFIRMED) {
reoriginatedRequest = (Request) challengedRequest.clone();
} else {
/*
* Re-originate the request by consulting the dialog. In particular
* the route set could change between the original request and the
* in-dialog challenge.
*/
reoriginatedRequest = challengedTransaction.getDialog().createRequest(challengedRequest.getMethod());
Iterator<String> headerNames = challengedRequest.getHeaderNames();
while (headerNames.hasNext()) {
String headerName = headerNames.next();
if (reoriginatedRequest.getHeader(headerName) != null) {
ListIterator<Header> iterator = reoriginatedRequest.getHeaders(headerName);
while (iterator.hasNext()) {
reoriginatedRequest.addHeader(iterator.next());
}
}
}
}
// remove the branch id so that we could use the request in a new
// transaction
removeBranchID(reoriginatedRequest);
if (challenge == null || reoriginatedRequest == null) {
throw new NullPointerException("A null argument was passed to handle challenge.");
}
ListIterator authHeaders = null;
if (challenge.getStatusCode() == Response.UNAUTHORIZED) {
authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME);
} else if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) {
authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME);
} else {
throw new IllegalArgumentException("Unexpected status code ");
}
if (authHeaders == null) {
throw new IllegalArgumentException("Could not find WWWAuthenticate or ProxyAuthenticate headers");
}
// Remove all authorization headers from the request (we'll re-add them
// from cache)
reoriginatedRequest.removeHeader(AuthorizationHeader.NAME);
reoriginatedRequest.removeHeader(ProxyAuthorizationHeader.NAME);
// rfc 3261 says that the cseq header should be augmented for the new
// request. do it here so that the new dialog (created together with
// the new client transaction) takes it into account.
// Bug report - Fredrik Wickstrom
CSeqHeader cSeq = (CSeqHeader) reoriginatedRequest.getHeader((CSeqHeader.NAME));
try {
cSeq.setSeqNumber(cSeq.getSeqNumber() + 1l);
} catch (InvalidArgumentException ex) {
throw new SipException("Invalid CSeq -- could not increment : " + cSeq.getSeqNumber());
}
/* Resolve this to the next hop based on the previous lookup. If we are not using
* lose routing (RFC2543) then just attach hop as a maddr param.
*/
if (challengedRequest.getRouteHeaders() == null) {
Hop hop = ((SIPClientTransaction) challengedTransaction).getNextHop();
SipURI sipUri = (SipURI) reoriginatedRequest.getRequestURI();
// BEGIN android-added
if (!hop.getHost().equalsIgnoreCase(sipUri.getHost()) && !hop.equals(sipStack.getRouter(challengedRequest).getOutboundProxy()))
// END android-added
sipUri.setMAddrParam(hop.getHost());
if (hop.getPort() != -1)
sipUri.setPort(hop.getPort());
}
ClientTransaction retryTran = transactionCreator.getNewClientTransaction(reoriginatedRequest);
WWWAuthenticateHeader authHeader = null;
SipURI requestUri = (SipURI) challengedTransaction.getRequest().getRequestURI();
while (authHeaders.hasNext()) {
authHeader = (WWWAuthenticateHeader) authHeaders.next();
String realm = authHeader.getRealm();
AuthorizationHeader authorization = null;
String sipDomain;
if (this.accountManager instanceof SecureAccountManager) {
UserCredentialHash credHash = ((SecureAccountManager) this.accountManager).getCredentialHash(challengedTransaction, realm);
URI uri = reoriginatedRequest.getRequestURI();
sipDomain = credHash.getSipDomain();
authorization = this.getAuthorization(reoriginatedRequest.getMethod(), uri.toString(), (reoriginatedRequest.getContent() == null) ? "" : new String(reoriginatedRequest.getRawContent()), authHeader, credHash);
} else {
UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm);
sipDomain = userCreds.getSipDomain();
if (userCreds == null)
throw new SipException("Cannot find user creds for the given user name and realm");
// we haven't yet authenticated this realm since we were
// started.
authorization = this.getAuthorization(reoriginatedRequest.getMethod(), reoriginatedRequest.getRequestURI().toString(), (reoriginatedRequest.getContent() == null) ? "" : new String(reoriginatedRequest.getRawContent()), authHeader, userCreds);
}
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("Created authorization header: " + authorization.toString());
if (cacheTime != 0)
cachedCredentials.cacheAuthorizationHeader(sipDomain, authorization, cacheTime);
reoriginatedRequest.addHeader(authorization);
}
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("Returning authorization transaction." + retryTran);
}
return retryTran;
} catch (SipException ex) {
throw ex;
} catch (Exception ex) {
sipStack.getStackLogger().logError("Unexpected exception ", ex);
throw new SipException("Unexpected exception ", ex);
}
}
use of javax.sip.SipException in project XobotOS by xamarin.
the class SIPClientTransaction method createAck.
/*
* (non-Javadoc)
*
* @see javax.sip.ClientTransaction#createAck()
*/
public Request createAck() throws SipException {
SIPRequest originalRequest = this.getOriginalRequest();
if (originalRequest == null)
throw new SipException("bad state " + getState());
if (getMethod().equalsIgnoreCase(Request.ACK)) {
throw new SipException("Cannot ACK an ACK!");
} else if (lastResponse == null) {
throw new SipException("bad Transaction state");
} else if (lastResponse.getStatusCode() < 200) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse);
}
throw new SipException("Cannot ACK a provisional response!");
}
SIPRequest ackRequest = originalRequest.createAckRequest((To) lastResponse.getTo());
// Pull the record route headers from the last reesponse.
RecordRouteList recordRouteList = lastResponse.getRecordRouteHeaders();
if (recordRouteList == null) {
// request URI.
if (lastResponse.getContactHeaders() != null && lastResponse.getStatusCode() / 100 != 3) {
Contact contact = (Contact) lastResponse.getContactHeaders().getFirst();
javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI().clone();
ackRequest.setRequestURI(uri);
}
return ackRequest;
}
ackRequest.removeHeader(RouteHeader.NAME);
RouteList routeList = new RouteList();
// start at the end of the list and walk backwards
ListIterator<RecordRoute> li = recordRouteList.listIterator(recordRouteList.size());
while (li.hasPrevious()) {
RecordRoute rr = (RecordRoute) li.previous();
Route route = new Route();
route.setAddress((AddressImpl) ((AddressImpl) rr.getAddress()).clone());
route.setParameters((NameValueList) rr.getParameters().clone());
routeList.add(route);
}
Contact contact = null;
if (lastResponse.getContactHeaders() != null) {
contact = (Contact) lastResponse.getContactHeaders().getFirst();
}
if (!((SipURI) ((Route) routeList.getFirst()).getAddress().getURI()).hasLrParam()) {
// Contact may not yet be there (bug reported by Andreas B).
Route route = null;
if (contact != null) {
route = new Route();
route.setAddress((AddressImpl) ((AddressImpl) (contact.getAddress())).clone());
}
Route firstRoute = (Route) routeList.getFirst();
routeList.removeFirst();
javax.sip.address.URI uri = firstRoute.getAddress().getURI();
ackRequest.setRequestURI(uri);
if (route != null)
routeList.add(route);
ackRequest.addHeader(routeList);
} else {
if (contact != null) {
javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI().clone();
ackRequest.setRequestURI(uri);
ackRequest.addHeader(routeList);
}
}
return ackRequest;
}
use of javax.sip.SipException in project XobotOS by xamarin.
the class SIPClientTransaction method sendRequest.
/*
* (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()) {
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));
// 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;
this.sendMessage(sipRequest);
} catch (IOException ex) {
this.setState(TransactionState.TERMINATED);
throw new SipException("IO Error sending request", ex);
}
}
use of javax.sip.SipException in project XobotOS by xamarin.
the class SIPServerTransaction method sendResponse.
/*
* (non-Javadoc)
*
* @see javax.sip.ServerTransaction#sendResponse(javax.sip.message.Response)
*/
public void sendResponse(Response response) throws SipException {
SIPResponse sipResponse = (SIPResponse) response;
SIPDialog dialog = this.dialog;
if (response == null)
throw new NullPointerException("null response");
try {
sipResponse.checkHeaders();
} catch (ParseException ex) {
throw new SipException(ex.getMessage());
}
// check for meaningful response.
if (!sipResponse.getCSeq().getMethod().equals(this.getMethod())) {
throw new SipException("CSeq method does not match Request method of request that created the tx.");
}
/*
* 200-class responses to SUBSCRIBE requests also MUST contain an "Expires" header. The
* period of time in the response MAY be shorter but MUST NOT be longer than specified in
* the request.
*/
if (this.getMethod().equals(Request.SUBSCRIBE) && response.getStatusCode() / 100 == 2) {
if (response.getHeader(ExpiresHeader.NAME) == null) {
throw new SipException("Expires header is mandatory in 2xx response of SUBSCRIBE");
} else {
Expires requestExpires = (Expires) this.getOriginalRequest().getExpires();
Expires responseExpires = (Expires) response.getExpires();
/*
* If no "Expires" header is present in a SUBSCRIBE request, the implied default
* is defined by the event package being used.
*/
if (requestExpires != null && responseExpires.getExpires() > requestExpires.getExpires()) {
throw new SipException("Response Expires time exceeds request Expires time : See RFC 3265 3.1.1");
}
}
}
// Check for mandatory header.
if (sipResponse.getStatusCode() == 200 && sipResponse.getCSeq().getMethod().equals(Request.INVITE) && sipResponse.getHeader(ContactHeader.NAME) == null)
throw new SipException("Contact Header is mandatory for the OK to the INVITE");
if (!this.isMessagePartOfTransaction((SIPMessage) response)) {
throw new SipException("Response does not belong to this transaction.");
}
// Fix up the response if the dialog has already been established.
try {
/*
* The UAS MAY send a final response to the initial request before
* having received PRACKs for all unacknowledged reliable provisional responses,
* unless the final response is 2xx and any of the unacknowledged reliable provisional
* responses contained a session description. In that case, it MUST NOT send a final
* response until those provisional responses are acknowledged.
*/
if (this.pendingReliableResponse != null && this.getDialog() != null && this.getState() != TransactionState.TERMINATED && ((SIPResponse) response).getContentTypeHeader() != null && response.getStatusCode() / 100 == 2 && ((SIPResponse) response).getContentTypeHeader().getContentType().equalsIgnoreCase("application") && ((SIPResponse) response).getContentTypeHeader().getContentSubType().equalsIgnoreCase("sdp")) {
try {
boolean acquired = this.provisionalResponseSem.tryAcquire(1, TimeUnit.SECONDS);
if (!acquired) {
throw new SipException("cannot send response -- unacked povisional");
}
} catch (Exception ex) {
this.sipStack.getStackLogger().logError("Could not acquire PRACK sem ", ex);
}
} else {
// pending response task.
if (this.pendingReliableResponse != null && sipResponse.isFinalResponse()) {
this.provisionalResponseTask.cancel();
this.provisionalResponseTask = null;
}
}
// being sent makes sense.
if (dialog != null) {
if (sipResponse.getStatusCode() / 100 == 2 && sipStack.isDialogCreated(sipResponse.getCSeq().getMethod())) {
if (dialog.getLocalTag() == null && sipResponse.getTo().getTag() == null) {
// Trying to send final response and user forgot to set
// to
// tag on the response -- be nice and assign the tag for
// the user.
sipResponse.getTo().setTag(Utils.getInstance().generateTag());
} else if (dialog.getLocalTag() != null && sipResponse.getToTag() == null) {
sipResponse.setToTag(dialog.getLocalTag());
} else if (dialog.getLocalTag() != null && sipResponse.getToTag() != null && !dialog.getLocalTag().equals(sipResponse.getToTag())) {
throw new SipException("Tag mismatch dialogTag is " + dialog.getLocalTag() + " responseTag is " + sipResponse.getToTag());
}
}
if (!sipResponse.getCallId().getCallId().equals(dialog.getCallId().getCallId())) {
throw new SipException("Dialog mismatch!");
}
}
// Backward compatibility slippery slope....
// Only set the from tag in the response when the
// incoming request has a from tag.
String fromTag = ((SIPRequest) this.getRequest()).getFrom().getTag();
if (fromTag != null && sipResponse.getFromTag() != null && !sipResponse.getFromTag().equals(fromTag)) {
throw new SipException("From tag of request does not match response from tag");
} else if (fromTag != null) {
sipResponse.getFrom().setTag(fromTag);
} else {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("WARNING -- Null From tag in request!!");
}
// or if the state of the dialog needs to be changed.
if (dialog != null && response.getStatusCode() != 100) {
dialog.setResponseTags(sipResponse);
DialogState oldState = dialog.getState();
dialog.setLastResponse(this, (SIPResponse) response);
if (oldState == null && dialog.getState() == DialogState.TERMINATED) {
DialogTerminatedEvent event = new DialogTerminatedEvent(dialog.getSipProvider(), dialog);
// Provide notification to the listener that the dialog has
// ended.
dialog.getSipProvider().handleEvent(event, this);
}
} else if (dialog == null && this.getMethod().equals(Request.INVITE) && this.retransmissionAlertEnabled && this.retransmissionAlertTimerTask == null && response.getStatusCode() / 100 == 2) {
String dialogId = ((SIPResponse) response).getDialogId(true);
this.retransmissionAlertTimerTask = new RetransmissionAlertTimerTask(dialogId);
sipStack.retransmissionAlertTransactions.put(dialogId, this);
sipStack.getTimer().schedule(this.retransmissionAlertTimerTask, 0, SIPTransactionStack.BASE_TIMER_INTERVAL);
}
// Send message after possibly inserting the Dialog
// into the dialog table to avoid a possible race condition.
this.sendMessage((SIPResponse) response);
if (dialog != null) {
dialog.startRetransmitTimer(this, (SIPResponse) response);
}
} catch (IOException ex) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logException(ex);
this.setState(TransactionState.TERMINATED);
raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
throw new SipException(ex.getMessage());
} catch (java.text.ParseException ex1) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logException(ex1);
this.setState(TransactionState.TERMINATED);
throw new SipException(ex1.getMessage());
}
}
Aggregations