Search in sources :

Example 1 with Expires

use of gov.nist.javax.sip.header.Expires 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());
    }
}
Also used : DialogState(javax.sip.DialogState) IOException(java.io.IOException) ParseException(java.text.ParseException) SipException(javax.sip.SipException) IOException(java.io.IOException) ObjectInUseException(javax.sip.ObjectInUseException) SIPResponse(gov.nist.javax.sip.message.SIPResponse) DialogTerminatedEvent(javax.sip.DialogTerminatedEvent) SIPMessage(gov.nist.javax.sip.message.SIPMessage) ParseException(java.text.ParseException) Expires(gov.nist.javax.sip.header.Expires) SipException(javax.sip.SipException) ParseException(java.text.ParseException)

Aggregations

Expires (gov.nist.javax.sip.header.Expires)1 SIPMessage (gov.nist.javax.sip.message.SIPMessage)1 SIPResponse (gov.nist.javax.sip.message.SIPResponse)1 IOException (java.io.IOException)1 ParseException (java.text.ParseException)1 DialogState (javax.sip.DialogState)1 DialogTerminatedEvent (javax.sip.DialogTerminatedEvent)1 ObjectInUseException (javax.sip.ObjectInUseException)1 SipException (javax.sip.SipException)1