use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.
the class SIPDialog method createAck.
/*
* (non-Javadoc) The UAC core MUST generate an ACK request for each 2xx received from the
* transaction layer. The header fields of the ACK are constructed in the same way as for any
* request sent within a dialog (see Section 12) with the exception of the CSeq and the header
* fields related to authentication. The sequence number of the CSeq header field MUST be the
* same as the INVITE being acknowledged, but the CSeq method MUST be ACK. The ACK MUST
* contain the same credentials as the INVITE. If the 2xx contains an offer (based on the
* rules above), the ACK MUST carry an answer in its body. If the offer in the 2xx response is
* not acceptable, the UAC core MUST generate a valid answer in the ACK and then send a BYE
* immediately.
*
* Note that for the case of forked requests, you can create multiple outgoing invites each
* with a different cseq and hence you need to supply the invite.
*
* @see javax.sip.Dialog#createAck(long)
*/
public Request createAck(long cseqno) throws InvalidArgumentException, SipException {
// then send INVITE+ACK later on
if (!method.equals(Request.INVITE))
throw new SipException("Dialog was not created with an INVITE" + method);
if (cseqno <= 0)
throw new InvalidArgumentException("bad cseq <= 0 ");
else if (cseqno > ((((long) 1) << 32) - 1))
throw new InvalidArgumentException("bad cseq > " + ((((long) 1) << 32) - 1));
if (this.remoteTarget == null) {
throw new SipException("Cannot create ACK - no remote Target!");
}
if (this.sipStack.isLoggingEnabled()) {
this.sipStack.getStackLogger().logDebug("createAck " + this + " cseqno " + cseqno);
}
// out of order ACK sending. Old ACKs seqno's can always be ACKed.
if (lastInviteOkReceived < cseqno) {
if (sipStack.isLoggingEnabled()) {
this.sipStack.getStackLogger().logDebug("WARNING : Attempt to crete ACK without OK " + this);
this.sipStack.getStackLogger().logDebug("LAST RESPONSE = " + this.lastResponse);
}
throw new SipException("Dialog not yet established -- no OK response!");
}
try {
// JvB: Transport from first entry in route set, or remote Contact
// if none
// Only used to find correct LP & create correct Via
SipURI uri4transport = null;
if (this.routeList != null && !this.routeList.isEmpty()) {
Route r = (Route) this.routeList.getFirst();
uri4transport = ((SipURI) r.getAddress().getURI());
} else {
// should be !=null, checked above
uri4transport = ((SipURI) this.remoteTarget.getURI());
}
String transport = uri4transport.getTransportParam();
if (transport == null) {
// JvB fix: also support TLS
transport = uri4transport.isSecure() ? ListeningPoint.TLS : ListeningPoint.UDP;
}
ListeningPointImpl lp = (ListeningPointImpl) sipProvider.getListeningPoint(transport);
if (lp == null) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logError("remoteTargetURI " + this.remoteTarget.getURI());
sipStack.getStackLogger().logError("uri4transport = " + uri4transport);
sipStack.getStackLogger().logError("No LP found for transport=" + transport);
}
throw new SipException("Cannot create ACK - no ListeningPoint for transport towards next hop found:" + transport);
}
SIPRequest sipRequest = new SIPRequest();
sipRequest.setMethod(Request.ACK);
sipRequest.setRequestURI((SipUri) getRemoteTarget().getURI().clone());
sipRequest.setCallId(this.callIdHeader);
sipRequest.setCSeq(new CSeq(cseqno, Request.ACK));
List<Via> vias = new ArrayList<Via>();
// Via via = lp.getViaHeader();
// The user may have touched the sentby for the response.
// so use the via header extracted from the response for the ACK =>
// https://jain-sip.dev.java.net/issues/show_bug.cgi?id=205
// strip the params from the via of the response and use the params from the
// original request
Via via = this.lastResponse.getTopmostVia();
via.removeParameters();
if (originalRequest != null && originalRequest.getTopmostVia() != null) {
NameValueList originalRequestParameters = originalRequest.getTopmostVia().getParameters();
if (originalRequestParameters != null && originalRequestParameters.size() > 0) {
via.setParameters((NameValueList) originalRequestParameters.clone());
}
}
// new branch
via.setBranch(Utils.getInstance().generateBranchId());
vias.add(via);
sipRequest.setVia(vias);
From from = new From();
from.setAddress(this.localParty);
from.setTag(this.myTag);
sipRequest.setFrom(from);
To to = new To();
to.setAddress(this.remoteParty);
if (hisTag != null)
to.setTag(this.hisTag);
sipRequest.setTo(to);
sipRequest.setMaxForwards(new MaxForwards(70));
if (this.originalRequest != null) {
Authorization authorization = this.originalRequest.getAuthorization();
if (authorization != null)
sipRequest.setHeader(authorization);
}
// ACKs for 2xx responses
// use the Route values learned from the Record-Route of the 2xx
// responses.
this.updateRequest(sipRequest);
return sipRequest;
} catch (Exception ex) {
InternalErrorHandler.handleException(ex);
throw new SipException("unexpected exception ", ex);
}
}
use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.
the class SIPDialog method sendAck.
/**
* Sends ACK Request to the remote party of this Dialogue.
*
*
* @param request the new ACK Request message to send.
* @param throwIOExceptionAsSipException - throws SipException if IOEx encountered. Otherwise,
* no exception is propagated.
* @param releaseAckSem - release ack semaphore.
* @throws SipException if implementation cannot send the ACK Request for any other reason
*
*/
private void sendAck(Request request, boolean throwIOExceptionAsSipException) throws SipException {
SIPRequest ackRequest = (SIPRequest) request;
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("sendAck" + this);
if (!ackRequest.getMethod().equals(Request.ACK))
throw new SipException("Bad request method -- should be ACK");
if (this.getState() == null || this.getState().getValue() == EARLY_STATE) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logError("Bad Dialog State for " + this + " dialogID = " + this.getDialogId());
}
throw new SipException("Bad dialog state " + this.getState());
}
if (!this.getCallId().getCallId().equals(((SIPRequest) request).getCallId().getCallId())) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logError("CallID " + this.getCallId());
sipStack.getStackLogger().logError("RequestCallID = " + ackRequest.getCallId().getCallId());
sipStack.getStackLogger().logError("dialog = " + this);
}
throw new SipException("Bad call ID in request");
}
try {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("setting from tag For outgoing ACK= " + this.getLocalTag());
sipStack.getStackLogger().logDebug("setting To tag for outgoing ACK = " + this.getRemoteTag());
sipStack.getStackLogger().logDebug("ack = " + ackRequest);
}
if (this.getLocalTag() != null)
ackRequest.getFrom().setTag(this.getLocalTag());
if (this.getRemoteTag() != null)
ackRequest.getTo().setTag(this.getRemoteTag());
} catch (ParseException ex) {
throw new SipException(ex.getMessage());
}
Hop hop = sipStack.getNextHop(ackRequest);
// Hop hop = defaultRouter.getNextHop(ackRequest);
if (hop == null)
throw new SipException("No route!");
try {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("hop = " + hop);
ListeningPointImpl lp = (ListeningPointImpl) this.sipProvider.getListeningPoint(hop.getTransport());
if (lp == null)
throw new SipException("No listening point for this provider registered at " + hop);
InetAddress inetAddress = InetAddress.getByName(hop.getHost());
MessageChannel messageChannel = lp.getMessageProcessor().createMessageChannel(inetAddress, hop.getPort());
boolean releaseAckSem = false;
long cseqNo = ((SIPRequest) request).getCSeq().getSeqNumber();
if (!this.isAckSent(cseqNo)) {
releaseAckSem = true;
}
this.setLastAckSent(ackRequest);
messageChannel.sendMessage(ackRequest);
// Sent atleast one ACK.
this.isAcknowledged = true;
this.highestSequenceNumberAcknowledged = Math.max(this.highestSequenceNumberAcknowledged, ((SIPRequest) ackRequest).getCSeq().getSeqNumber());
if (releaseAckSem && this.isBackToBackUserAgent) {
this.releaseAckSem();
} else {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("Not releasing ack sem for " + this + " isAckSent " + releaseAckSem);
}
}
} catch (IOException ex) {
if (throwIOExceptionAsSipException)
throw new SipException("Could not send ack", ex);
this.raiseIOException(hop.getHost(), hop.getPort(), hop.getTransport());
} catch (SipException ex) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logException(ex);
throw ex;
} catch (Exception ex) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logException(ex);
throw new SipException("Could not create message channel", ex);
}
if (this.dialogDeleteTask != null) {
this.dialogDeleteTask.cancel();
this.dialogDeleteTask = null;
}
this.ackSeen = true;
}
use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.
the class SIPDialog method createPrack.
/*
* (non-Javadoc) Retransmissions of the reliable provisional response cease when a matching
* PRACK is received by the UA core. PRACK is like any other request within a dialog, and the
* UAS core processes it according to the procedures of Sections 8.2 and 12.2.2 of RFC 3261. A
* matching PRACK is defined as one within the same dialog as the response, and whose method,
* CSeq-num, and response-num in the RAck header field match, respectively, the method from
* the CSeq, the sequence number from the CSeq, and the sequence number from the RSeq of the
* reliable provisional response.
*
* @see javax.sip.Dialog#createPrack(javax.sip.message.Response)
*/
public Request createPrack(Response relResponse) throws DialogDoesNotExistException, SipException {
if (this.getState() == null || this.getState().equals(DialogState.TERMINATED))
throw new DialogDoesNotExistException("Dialog not initialized or terminated");
if ((RSeq) relResponse.getHeader(RSeqHeader.NAME) == null) {
throw new SipException("Missing RSeq Header");
}
try {
SIPResponse sipResponse = (SIPResponse) relResponse;
SIPRequest sipRequest = (SIPRequest) this.createRequest(Request.PRACK, (SIPResponse) relResponse);
String toHeaderTag = sipResponse.getTo().getTag();
sipRequest.setToTag(toHeaderTag);
RAck rack = new RAck();
RSeq rseq = (RSeq) relResponse.getHeader(RSeqHeader.NAME);
rack.setMethod(sipResponse.getCSeq().getMethod());
rack.setCSequenceNumber((int) sipResponse.getCSeq().getSeqNumber());
rack.setRSequenceNumber(rseq.getSeqNumber());
sipRequest.setHeader(rack);
return (Request) sipRequest;
} catch (Exception ex) {
InternalErrorHandler.handleException(ex);
return null;
}
}
use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.
the class SIPServerTransaction method isMessagePartOfTransaction.
/**
* Determines if the message is a part of this transaction.
*
* @param messageToTest Message to check if it is part of this transaction.
*
* @return True if the message is part of this transaction, false if not.
*/
public boolean isMessagePartOfTransaction(SIPMessage messageToTest) {
// List of Via headers in the message to test
ViaList viaHeaders;
// Topmost Via header in the list
Via topViaHeader;
// Branch code in the topmost Via header
String messageBranch;
// Flags whether the select message is part of this transaction
boolean transactionMatches;
transactionMatches = false;
String method = messageToTest.getCSeq().getMethod();
// http://bugs.sipit.net/show_bug.cgi?id=769
if ((method.equals(Request.INVITE) || !isTerminated())) {
// Get the topmost Via header and its branch parameter
viaHeaders = messageToTest.getViaHeaders();
if (viaHeaders != null) {
topViaHeader = (Via) viaHeaders.getFirst();
messageBranch = topViaHeader.getBranch();
if (messageBranch != null) {
// does not start with the magic cookie,
if (!messageBranch.toLowerCase().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) {
// Flags this as old
// (RFC2543-compatible) client
// version
messageBranch = null;
}
}
// If a new branch parameter exists,
if (messageBranch != null && this.getBranch() != null) {
if (method.equals(Request.CANCEL)) {
// Cancel is handled as a special case because it
// shares the same same branch id of the invite
// that it is trying to cancel.
transactionMatches = this.getMethod().equals(Request.CANCEL) && getBranch().equalsIgnoreCase(messageBranch) && topViaHeader.getSentBy().equals(((Via) getOriginalRequest().getViaHeaders().getFirst()).getSentBy());
} else {
// Matching server side transaction with only the
// branch parameter.
transactionMatches = getBranch().equalsIgnoreCase(messageBranch) && topViaHeader.getSentBy().equals(((Via) getOriginalRequest().getViaHeaders().getFirst()).getSentBy());
}
} else {
// This is an RFC2543-compliant message; this code is here
// for backwards compatibility.
// It is a weak check.
// If RequestURI, To tag, From tag, CallID, CSeq number, and
// top Via headers are the same, the
// SIPMessage matches this transaction. An exception is for
// a CANCEL request, which is not deemed
// to be part of an otherwise-matching INVITE transaction.
String originalFromTag = super.fromTag;
String thisFromTag = messageToTest.getFrom().getTag();
boolean skipFrom = (originalFromTag == null || thisFromTag == null);
String originalToTag = super.toTag;
String thisToTag = messageToTest.getTo().getTag();
boolean skipTo = (originalToTag == null || thisToTag == null);
boolean isResponse = (messageToTest instanceof SIPResponse);
// be CANCEL for it to have a chance at matching.
if (messageToTest.getCSeq().getMethod().equalsIgnoreCase(Request.CANCEL) && !getOriginalRequest().getCSeq().getMethod().equalsIgnoreCase(Request.CANCEL)) {
transactionMatches = false;
} else if ((isResponse || getOriginalRequest().getRequestURI().equals(((SIPRequest) messageToTest).getRequestURI())) && (skipFrom || originalFromTag != null && originalFromTag.equalsIgnoreCase(thisFromTag)) && (skipTo || originalToTag != null && originalToTag.equalsIgnoreCase(thisToTag)) && getOriginalRequest().getCallId().getCallId().equalsIgnoreCase(messageToTest.getCallId().getCallId()) && getOriginalRequest().getCSeq().getSeqNumber() == messageToTest.getCSeq().getSeqNumber() && ((!messageToTest.getCSeq().getMethod().equals(Request.CANCEL)) || getOriginalRequest().getMethod().equals(messageToTest.getCSeq().getMethod())) && topViaHeader.equals(getOriginalRequest().getViaHeaders().getFirst())) {
transactionMatches = true;
}
}
}
}
return transactionMatches;
}
use of gov.nist.javax.sip.message.SIPRequest in project XobotOS by xamarin.
the class SIPClientTransaction method createCancel.
/*
* (non-Javadoc)
*
* @see javax.sip.ClientTransaction#createCancel()
*/
public Request createCancel() throws SipException {
SIPRequest originalRequest = this.getOriginalRequest();
if (originalRequest == null)
throw new SipException("Bad state " + getState());
if (!originalRequest.getMethod().equals(Request.INVITE))
throw new SipException("Only INIVTE may be cancelled");
if (originalRequest.getMethod().equalsIgnoreCase(Request.ACK))
throw new SipException("Cannot Cancel ACK!");
else {
SIPRequest cancelRequest = originalRequest.createCancelRequest();
cancelRequest.setInviteTransaction(this);
return cancelRequest;
}
}
Aggregations