use of javax.sip.ClientTransaction in project XobotOS by xamarin.
the class SipHelper method sendInvite.
public ClientTransaction sendInvite(SipProfile caller, SipProfile callee, String sessionDescription, String tag, ReferredByHeader referredBy, String replaces) throws SipException {
try {
Request request = createRequest(Request.INVITE, caller, callee, tag);
if (referredBy != null)
request.addHeader(referredBy);
if (replaces != null) {
request.addHeader(mHeaderFactory.createHeader(ReplacesHeader.NAME, replaces));
}
request.setContent(sessionDescription, mHeaderFactory.createContentTypeHeader("application", "sdp"));
ClientTransaction clientTransaction = mSipProvider.getNewClientTransaction(request);
if (DEBUG)
Log.d(TAG, "send INVITE: " + request);
clientTransaction.sendRequest();
return clientTransaction;
} catch (ParseException e) {
throw new SipException("sendInvite()", e);
}
}
use of javax.sip.ClientTransaction in project XobotOS by xamarin.
the class SipProviderImpl method getNewClientTransaction.
/*
* (non-Javadoc)
*
* @see javax.sip.SipProvider#getNewClientTransaction(javax.sip.message.Request)
*/
public ClientTransaction getNewClientTransaction(Request request) throws TransactionUnavailableException {
if (request == null)
throw new NullPointerException("null request");
if (!sipStack.isAlive())
throw new TransactionUnavailableException("Stack is stopped");
SIPRequest sipRequest = (SIPRequest) request;
if (sipRequest.getTransaction() != null)
throw new TransactionUnavailableException("Transaction already assigned to request");
if (sipRequest.getMethod().equals(Request.ACK)) {
throw new TransactionUnavailableException("Cannot create client transaction for " + Request.ACK);
}
// sloppy
if (sipRequest.getTopmostVia() == null) {
ListeningPointImpl lp = (ListeningPointImpl) this.getListeningPoint("udp");
Via via = lp.getViaHeader();
request.setHeader(via);
}
// Give the request a quick check to see if all headers are assigned.
try {
sipRequest.checkHeaders();
} catch (ParseException ex) {
throw new TransactionUnavailableException(ex.getMessage(), ex);
}
/*
* User decided to give us his own via header branch. Lets see if it
* results in a clash. If so reject the request.
*/
if (sipRequest.getTopmostVia().getBranch() != null && sipRequest.getTopmostVia().getBranch().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE) && sipStack.findTransaction((SIPRequest) request, false) != null) {
throw new TransactionUnavailableException("Transaction already exists!");
}
if (request.getMethod().equalsIgnoreCase(Request.CANCEL)) {
SIPClientTransaction ct = (SIPClientTransaction) sipStack.findCancelTransaction((SIPRequest) request, false);
if (ct != null) {
ClientTransaction retval = sipStack.createClientTransaction((SIPRequest) request, ct.getMessageChannel());
((SIPTransaction) retval).addEventListener(this);
sipStack.addTransaction((SIPClientTransaction) retval);
if (ct.getDialog() != null) {
((SIPClientTransaction) retval).setDialog((SIPDialog) ct.getDialog(), sipRequest.getDialogId(false));
}
return retval;
}
}
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("could not find existing transaction for " + ((SIPRequest) request).getFirstLine() + " creating a new one ");
// Could not find a dialog or the route is not set in dialog.
Hop hop = null;
try {
hop = sipStack.getNextHop((SIPRequest) request);
if (hop == null)
throw new TransactionUnavailableException("Cannot resolve next hop -- transaction unavailable");
} catch (SipException ex) {
throw new TransactionUnavailableException("Cannot resolve next hop -- transaction unavailable", ex);
}
String transport = hop.getTransport();
ListeningPointImpl listeningPoint = (ListeningPointImpl) this.getListeningPoint(transport);
String dialogId = sipRequest.getDialogId(false);
SIPDialog dialog = sipStack.getDialog(dialogId);
if (dialog != null && dialog.getState() == DialogState.TERMINATED) {
// throw new TransactionUnavailableException
// ("Found a terminated dialog -- possible re-use of old tag
// parameters");
sipStack.removeDialog(dialog);
}
try {
// Set the brannch id before you ask for a tx.
// If the user has set his own branch Id and the
// branch id starts with a valid prefix, then take it.
// otherwise, generate one. If branch ID checking has
// been requested, set the branch ID.
String branchId = null;
if (sipRequest.getTopmostVia().getBranch() == null || !sipRequest.getTopmostVia().getBranch().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE) || sipStack.checkBranchId()) {
branchId = Utils.getInstance().generateBranchId();
sipRequest.getTopmostVia().setBranch(branchId);
}
Via topmostVia = sipRequest.getTopmostVia();
//set port and transport if user hasn't already done this.
if (topmostVia.getTransport() == null)
topmostVia.setTransport(transport);
if (topmostVia.getPort() == -1)
topmostVia.setPort(listeningPoint.getPort());
branchId = sipRequest.getTopmostVia().getBranch();
SIPClientTransaction ct = (SIPClientTransaction) sipStack.createMessageChannel(sipRequest, listeningPoint.getMessageProcessor(), hop);
if (ct == null)
throw new TransactionUnavailableException("Cound not create tx");
ct.setNextHop(hop);
ct.setOriginalRequest(sipRequest);
ct.setBranch(branchId);
// if the stack supports dialogs then
if (sipStack.isDialogCreated(request.getMethod())) {
// (but noticed by Brad Templeton)
if (dialog != null)
ct.setDialog(dialog, sipRequest.getDialogId(false));
else if (this.isAutomaticDialogSupportEnabled()) {
SIPDialog sipDialog = sipStack.createDialog(ct);
ct.setDialog(sipDialog, sipRequest.getDialogId(false));
}
} else {
if (dialog != null) {
ct.setDialog(dialog, sipRequest.getDialogId(false));
}
}
// The provider is the event listener for all transactions.
ct.addEventListener(this);
return (ClientTransaction) ct;
} catch (IOException ex) {
throw new TransactionUnavailableException("Could not resolve next hop or listening point unavailable! ", ex);
} catch (java.text.ParseException ex) {
InternalErrorHandler.handleException(ex);
throw new TransactionUnavailableException("Unexpected Exception FIXME! ", ex);
} catch (InvalidArgumentException ex) {
InternalErrorHandler.handleException(ex);
throw new TransactionUnavailableException("Unexpected Exception FIXME! ", ex);
}
}
use of javax.sip.ClientTransaction in project XobotOS by xamarin.
the class SIPDialog method setLastResponse.
/**
* Set the last response for this dialog. This method is called for updating the dialog state
* when a response is either sent or received from within a Dialog.
*
* @param transaction -- the transaction associated with the response
* @param sipResponse -- the last response to set.
*/
public void setLastResponse(SIPTransaction transaction, SIPResponse sipResponse) {
this.callIdHeader = sipResponse.getCallId();
int statusCode = sipResponse.getStatusCode();
if (statusCode == 100) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logWarning("Invalid status code - 100 in setLastResponse - ignoring");
return;
}
this.lastResponse = sipResponse;
this.setAssigned();
// Adjust state of the Dialog state machine.
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("sipDialog: setLastResponse:" + this + " lastResponse = " + this.lastResponse.getFirstLine());
}
if (this.getState() == DialogState.TERMINATED) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("sipDialog: setLastResponse -- dialog is terminated - ignoring ");
}
// This is handy for late arriving OK's that we want to ACK.
if (sipResponse.getCSeq().getMethod().equals(Request.INVITE) && statusCode == 200) {
this.lastInviteOkReceived = Math.max(sipResponse.getCSeq().getSeqNumber(), this.lastInviteOkReceived);
}
return;
}
String cseqMethod = sipResponse.getCSeq().getMethod();
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logStackTrace();
sipStack.getStackLogger().logDebug("cseqMethod = " + cseqMethod);
sipStack.getStackLogger().logDebug("dialogState = " + this.getState());
sipStack.getStackLogger().logDebug("method = " + this.getMethod());
sipStack.getStackLogger().logDebug("statusCode = " + statusCode);
sipStack.getStackLogger().logDebug("transaction = " + transaction);
}
// responses.
if (transaction == null || transaction instanceof ClientTransaction) {
if (sipStack.isDialogCreated(cseqMethod)) {
// Make a final tag assignment.
if (getState() == null && (statusCode / 100 == 1)) {
/*
* Guard aginst slipping back into early state from confirmed state.
*/
// Was (sipResponse.getToTag() != null || sipStack.rfc2543Supported)
setState(SIPDialog.EARLY_STATE);
if ((sipResponse.getToTag() != null || sipStack.rfc2543Supported) && this.getRemoteTag() == null) {
setRemoteTag(sipResponse.getToTag());
this.setDialogId(sipResponse.getDialogId(false));
sipStack.putDialog(this);
this.addRoute(sipResponse);
}
} else if (getState() != null && getState().equals(DialogState.EARLY) && statusCode / 100 == 1) {
/*
* This case occurs for forked dialog responses. The To tag can change as a
* result of the forking. The remote target can also change as a result of the
* forking.
*/
if (cseqMethod.equals(getMethod()) && transaction != null && (sipResponse.getToTag() != null || sipStack.rfc2543Supported)) {
setRemoteTag(sipResponse.getToTag());
this.setDialogId(sipResponse.getDialogId(false));
sipStack.putDialog(this);
this.addRoute(sipResponse);
}
} else if (statusCode / 100 == 2) {
if (cseqMethod.equals(getMethod()) && (sipResponse.getToTag() != null || sipStack.rfc2543Supported) && this.getState() != DialogState.CONFIRMED) {
setRemoteTag(sipResponse.getToTag());
this.setDialogId(sipResponse.getDialogId(false));
sipStack.putDialog(this);
this.addRoute(sipResponse);
setState(SIPDialog.CONFIRMED_STATE);
}
// Capture the OK response for later use in createAck
if (cseqMethod.equals(Request.INVITE)) {
this.lastInviteOkReceived = Math.max(sipResponse.getCSeq().getSeqNumber(), this.lastInviteOkReceived);
}
} else if (statusCode >= 300 && statusCode <= 699 && (getState() == null || (cseqMethod.equals(getMethod()) && getState().getValue() == SIPDialog.EARLY_STATE))) {
/*
* This case handles 3xx, 4xx, 5xx and 6xx responses. RFC 3261 Section 12.3 -
* dialog termination. Independent of the method, if a request outside of a
* dialog generates a non-2xx final response, any early dialogs created
* through provisional responses to that request are terminated.
*/
setState(SIPDialog.TERMINATED_STATE);
}
/*
* This code is in support of "proxy" servers that are constructed as back to back
* user agents. This could be a dialog in the middle of the call setup path
* somewhere. Hence the incoming invite has record route headers in it. The
* response will have additional record route headers. However, for this dialog
* only the downstream record route headers matter. Ideally proxy servers should
* not be constructed as Back to Back User Agents. Remove all the record routes
* that are present in the incoming INVITE so you only have the downstream Route
* headers present in the dialog. Note that for an endpoint - you will have no
* record route headers present in the original request so the loop will not
* execute.
*/
if (this.getState() != DialogState.CONFIRMED && this.getState() != DialogState.TERMINATED) {
if (originalRequest != null) {
RecordRouteList rrList = originalRequest.getRecordRouteHeaders();
if (rrList != null) {
ListIterator<RecordRoute> it = rrList.listIterator(rrList.size());
while (it.hasPrevious()) {
RecordRoute rr = (RecordRoute) it.previous();
Route route = (Route) routeList.getFirst();
if (route != null && rr.getAddress().equals(route.getAddress())) {
routeList.removeFirst();
} else
break;
}
}
}
}
} else if (cseqMethod.equals(Request.NOTIFY) && (this.getMethod().equals(Request.SUBSCRIBE) || this.getMethod().equals(Request.REFER)) && sipResponse.getStatusCode() / 100 == 2 && this.getState() == null) {
// This is a notify response.
this.setDialogId(sipResponse.getDialogId(true));
sipStack.putDialog(this);
this.setState(SIPDialog.CONFIRMED_STATE);
} else if (cseqMethod.equals(Request.BYE) && statusCode / 100 == 2 && isTerminatedOnBye()) {
// Dialog will be terminated when the transction is terminated.
setState(SIPDialog.TERMINATED_STATE);
}
} else {
if (cseqMethod.equals(Request.BYE) && statusCode / 100 == 2 && this.isTerminatedOnBye()) {
/*
* Only transition to terminated state when 200 OK is returned for the BYE. Other
* status codes just result in leaving the state in COMPLETED state.
*/
this.setState(SIPDialog.TERMINATED_STATE);
} else {
boolean doPutDialog = false;
if (getLocalTag() == null && sipResponse.getTo().getTag() != null && sipStack.isDialogCreated(cseqMethod) && cseqMethod.equals(getMethod())) {
setLocalTag(sipResponse.getTo().getTag());
doPutDialog = true;
}
if (statusCode / 100 != 2) {
if (statusCode / 100 == 1) {
if (doPutDialog) {
setState(SIPDialog.EARLY_STATE);
this.setDialogId(sipResponse.getDialogId(true));
sipStack.putDialog(this);
}
} else {
// see https://jain-sip.dev.java.net/servlets/ReadMsg?list=users&msgNo=797
if (statusCode == 489 && (cseqMethod.equals(Request.NOTIFY) || cseqMethod.equals(Request.SUBSCRIBE))) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("RFC 3265 : Not setting dialog to TERMINATED for 489");
} else {
// see rfc 5057 for better explanation
if (!this.isReInvite() && getState() != DialogState.CONFIRMED) {
this.setState(SIPDialog.TERMINATED_STATE);
}
}
}
} else {
/*
* JvB: RFC4235 says that when sending 2xx on UAS side, state should move to
* CONFIRMED
*/
if (this.dialogState <= SIPDialog.EARLY_STATE && (cseqMethod.equals(Request.INVITE) || cseqMethod.equals(Request.SUBSCRIBE) || cseqMethod.equals(Request.REFER))) {
this.setState(SIPDialog.CONFIRMED_STATE);
}
if (doPutDialog) {
this.setDialogId(sipResponse.getDialogId(true));
sipStack.putDialog(this);
}
/*
* We put the dialog into the table. We must wait for ACK before re-INVITE is
* sent
*/
if (transaction.getState() != TransactionState.TERMINATED && sipResponse.getStatusCode() == Response.OK && cseqMethod.equals(Request.INVITE) && this.isBackToBackUserAgent) {
/*
* Acquire the flag for re-INVITE so that we cannot re-INVITE before
* ACK is received.
*/
if (!this.takeAckSem()) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("Delete dialog -- cannot acquire ackSem");
}
this.delete();
return;
}
}
}
}
}
}
use of javax.sip.ClientTransaction in project Openfire by igniterealtime.
the class SimpleListener method processResponse.
public void processResponse(ResponseEvent responseEvent) {
if (responseEvent.getClientTransaction() != null) {
Log.debug("SimpleListener for " + myUsername + ": Getting client transaction...");
ClientTransaction clientTransaction = responseEvent.getClientTransaction();
Dialog clientDialog = clientTransaction.getDialog();
getSession().printDialog(clientDialog);
}
Log.debug("SimpleListener for " + myUsername + ": Received a response event: " + responseEvent.getResponse().toString());
// String fromAddr = "";
String toAddr = "";
Response response = responseEvent.getResponse();
// }
if (response.getHeader(ToHeader.NAME) != null) {
ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
URI toUri = toHeader.getAddress().getURI();
if (toUri instanceof SipUri)
toAddr = ((SipUri) toUri).getUser() + "@" + ((SipUri) toUri).getHost();
else
toAddr = toUri.toString();
}
if (response.getHeader(CSeqHeader.NAME) != null) {
String method = ((CSeqHeader) response.getHeader(CSeqHeader.NAME)).getMethod();
if (method.equals(Request.REGISTER)) {
if (response.getStatusCode() / 100 == 2) {
int expires = 0;
if (response.getHeader(ContactHeader.NAME) != null) {
expires = ((ContactHeader) response.getHeader(ContactHeader.NAME)).getExpires();
} else if (response.getHeader(ExpiresHeader.NAME) != null) {
expires = ((ExpiresHeader) response.getHeader(ExpiresHeader.NAME)).getExpires();
}
if (expires > 0) {
Log.debug("SimpleListener(" + myUsername + ").processResponse: " + getSession().getRegistration().getUsername() + " log in successful!");
getSession().sipUserLoggedIn();
} else {
if (getSession().getLoginStatus().equals(TransportLoginStatus.LOGGING_OUT)) {
Log.debug("SimpleListener(" + myUsername + ").processResponse: " + getSession().getRegistration().getUsername() + " log out successful!");
getSession().sipUserLoggedOut();
getSession().removeStack();
}
}
}
}
if (method.equals(Request.SUBSCRIBE)) {
if (response.getStatusCode() / 100 == 2) {
Log.debug("SimpleListener for " + myUsername + ": Handling SUBSCRIBE acknowledgement!!");
int expires = 0;
if (response.getHeader(ContactHeader.NAME) != null) {
expires = ((ContactHeader) response.getHeader(ContactHeader.NAME)).getExpires();
}
if (response.getHeader(ExpiresHeader.NAME) != null) {
expires = ((ExpiresHeader) response.getHeader(ExpiresHeader.NAME)).getExpires();
}
if (expires > 0) {
// Confirm subscription of roster item
getSession().contactSubscribed(toAddr);
} else {
// Confirm unsubscription of roster item
getSession().contactUnsubscribed(toAddr);
}
Log.debug("SimpleListener for " + myUsername + ": Handled SUBSCRIBE acknowledgement!!");
}
}
}
}
use of javax.sip.ClientTransaction in project camel by apache.
the class SipPresenceAgentListener method sendNotification.
private void sendNotification(EventHeader eventHeader, boolean isInitial, Object body) throws SipException, ParseException {
/*
* NOTIFY requests MUST contain a "Subscription-State" header with a
* value of "active", "pending", or "terminated". The "active" value
* indicates that the subscription has been accepted and has been
* authorized (in most cases; see section 5.2.). The "pending" value
* indicates that the subscription has been received, but that
* policy information is insufficient to accept or deny the
* subscription at this time. The "terminated" value indicates that
* the subscription is not active.
*/
Request notifyRequest = dialog.createRequest("NOTIFY");
// Mark the contact header, to check that the remote contact is updated
((SipURI) sipPresenceAgent.getConfiguration().getContactHeader().getAddress().getURI()).setParameter(sipPresenceAgent.getConfiguration().getFromUser(), sipPresenceAgent.getConfiguration().getFromHost());
SubscriptionStateHeader sstate;
if (isInitial) {
// Initial state is pending, second time we assume terminated (Expires==0)
sstate = sipPresenceAgent.getConfiguration().getHeaderFactory().createSubscriptionStateHeader(isInitial ? SubscriptionStateHeader.PENDING : SubscriptionStateHeader.TERMINATED);
// Need a reason for terminated
if (sstate.getState().equalsIgnoreCase("terminated")) {
sstate.setReasonCode("deactivated");
}
} else {
sstate = sipPresenceAgent.getConfiguration().getHeaderFactory().createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
}
notifyRequest.addHeader(sstate);
notifyRequest.setHeader(eventHeader);
notifyRequest.setHeader(sipPresenceAgent.getConfiguration().getContactHeader());
notifyRequest.setContent(body, sipPresenceAgent.getConfiguration().getContentTypeHeader());
LOG.debug("Sending the following NOTIFY request to Subscriber: {}", notifyRequest);
ClientTransaction clientTransactionId = sipPresenceAgent.getProvider().getNewClientTransaction(notifyRequest);
dialog.sendRequest(clientTransactionId);
}
Aggregations