FileDocCategorySizeDatePackage
SipServerConnectionImpl.javaAPI DocphoneME MR2 API (J2ME)36776Wed May 02 18:00:42 BST 2007gov.nist.microedition.sip

SipServerConnectionImpl

public class SipServerConnectionImpl extends Object implements javax.microedition.sip.SipServerConnection
SIP ServerConnection implementation. This code is in the public domain.

Fields Summary
public static final int
TERMINATED
Terminated, the final state, in which the SIP connection has been terminated by error or closed
public static final int
REQUEST_RECEIVED
Request Received, SipServerConnection returned from SipConnectionNotifier or provisional response(s) (1xx) sent.
public static final int
INITIALIZED
Initialized, response initialized calling initResponse()
public static final int
STREAM_OPEN
Stream Open, OutputStream opened with openContentOutputStream(). Opening InputStream for received request does not trigger state transition.
public static final int
COMPLETED
Completed, transaction completed with sending final response (2xx, 3xx, 4xx, 5xx, 6xx)
private int
state
Attribute keeping the actual state of this server transaction
private javax.microedition.sip.SipDialog
sipDialog
the sip dialog this client transaction belongs to
private Request
request
the request for this server transaction
private Response
response
the response to the actual request
private SDPOutputStream
contentOutputStream
content of the response body
private InputStream
contentInputStream
content from the request body
private SipConnectionNotifierImpl
sipConnectionNotifierImpl
Receiver of incoming messages
private boolean
useResponse
Flag indicating which SIP message (request or response) should be used in getHeader()/getHeaders()/setHeader()/removeHeader().
private boolean
resend2xxAllowed
Boolean flag used to indicate if 2xx is allowed to resend This flag is set to true if 2xx is sent and SipServerConnectionImpl transitions to COMPLETED state
Constructors Summary
protected SipServerConnectionImpl(Request request, javax.microedition.sip.SipDialog sipDialog, SipConnectionNotifierImpl sipConnectionNotifierImpl)
Constructor.

param
request the protocol connection request
param
sipDialog the current transaction state
param
sipConnectionNotifierImpl the notification handler


                           
     
             
             
              
        this.request   = request;
        this.sipDialog = sipDialog;
        this.sipConnectionNotifierImpl = sipConnectionNotifierImpl;
        if (request.getMethod() == Request.ACK) {
            state = COMPLETED;
        } else {
            state = REQUEST_RECEIVED;
        }
    
Methods Summary
public voidaddHeader(java.lang.String name, java.lang.String value)
Adds a header to the SIP message. If multiple header field values exist the header value is added topmost of this type of headers. The implementations MAY restrict the access to some headers according to RFC 3261.

param
name - name of the header, either in full or compact form. RFC 3261 p.32
param
value - the header value
throws
SipException - INVALID_STATE if header can not be added in this state.
INVALID_OPERATION if the system does not allow to add this header.
throws
IllegalArgumentException - MAY be thrown if the header or value is invalid

        if (state != INITIALIZED)
            throw new SipException("the Header can not be add,"
                    + " because of wrong state.",
                    SipException.INVALID_STATE);
        if (name == null)
            throw new
                IllegalArgumentException("The header name can not be null");
        if (value == null)
            throw new
                IllegalArgumentException("The header value can not be null");

        Header header = null;
        try {
            header = StackConnector.headerFactory.createHeader(name, value);
        } catch (ParseException pe) {
            throw new IllegalArgumentException("The header can not be created,"
                    + " check if it is correct");
        }

        Message currentMessage = useResponse ? (Message)response :
            (Message)request;

        if (currentMessage == null) {
            throw new SipException("Failure in addHeader(),"
                    + " associated request or response is null",
                    SipException.INVALID_MESSAGE);
        }

        currentMessage.addHeader(header);
    
private voidchangeDialogState(gov.nist.siplite.stack.ServerTransaction serverTransaction)
Change the state of the dialog after sending a response.

param
serverTransaction current transaction

        // System.out.println(">>> SERVER: changing state, " +
        //     response.getCSeqHeader().getMethod());

        int statusCode = response.getStatusCode();

        if (statusCode == 100 || sipDialog == null) {
            return;
        }

        String cseqMethod = response.getCSeqHeader().getMethod();
        SipDialogImpl sipDialogImpl = (SipDialogImpl)sipDialog;

        if (cseqMethod.equals(Request.NOTIFY)) {
            // System.out.println(">>> SERVER: NOTIFY!!!");
            sipDialogImpl.handleNotify(request,
                serverTransaction.getDialog(), null);
            return;
        }

        // Default is to not create a dialog.
        // The dialog only is created for the methods that are known
        // to establish a dialog.
        int statusGroup = statusCode / 100;

        if (sipConnectionNotifierImpl.getStackConnector().getSipStack().
                isDialogCreated(cseqMethod) || cseqMethod.equals(Request.BYE)) {
            if (statusGroup == 2) {
                // RFC 3261, section 13.2.2.4:
                // If the dialog identifier in the 2xx response matches the
                // dialog identifier of an existing dialog, the dialog MUST
                // be transitioned to the "confirmed" state.
                sipDialogImpl.setDialog(serverTransaction.getDialog());
                sipDialogImpl.setState(SipDialog.CONFIRMED);

                if (statusCode == 200) {
                    if (cseqMethod.equals(Request.SUBSCRIBE) ||
                            cseqMethod.equals(Request.REFER)) {
                        sipDialogImpl.addSubscription(new Subscription(
                            sipDialogImpl.getDialog(), request));
                    } else if (cseqMethod.equals(Request.BYE)) {
                        sipDialogImpl.setWaitForBye(false);
                        sipDialogImpl.terminateIfNoSubscriptions();
                    }
                }
            } else if (statusGroup == 1) {
                // provisional response
                if (sipDialog.getState() == SipDialogImpl.INITIALIZED) {
                   // switch to EARLY state
                   sipDialogImpl.setState(SipDialog.EARLY);
                }
            } else { // another response code - switch to TERMINATED state
                sipDialogImpl.terminateIfNoSubscriptions();
            }

            // set dialog ID if need
            if (sipDialogImpl.getDialogID() == null) {
                int state = sipDialog.getState();
                if ((state == SipDialog.EARLY) ||
                        (state == SipDialog.CONFIRMED)) {
                    sipDialogImpl.setDialog(serverTransaction.getDialog());
                    sipDialogImpl.setDialogID(response.getDialogId(true));
                }
            }
        }
    
public voidclose()
Closes the connection.

exception
IOException if an I/O error occurs
see
javax.microedition.io.Connection#close()

        state = TERMINATED;
    
private SipConnectionNotifierImplfindNotifier()
Finds a connection notifier that listens on the port given in the Contact header of the response. When a 2xx response contains a new Contact with the port that is different from one that is used by the connection notifier associated with this server connection object (sipConnectionNotifierImpl), the notifier must be changed accordingly.

returns
SipConnectionNotifier listening on the new Contact or null if such notifier was not found.

        // IMPL_NOTE: handle shared connections
        int localPort = SIPConstants.DEFAULT_NONTLS_PORT;
        String localTransport = SIPConstants.TRANSPORT_UDP;

        ContactList contactList = response.getContactHeaders();
        if (contactList != null) {
            ContactHeader contact = (ContactHeader)contactList.getFirst();
            HostPort hp = contact.getHostPort();
            if (hp != null) {
                localPort = hp.getPort();
            }

            URI uri = contact.getAddress().getURI();
            String transport = uri.isSipURI() ?
                ((SipURI)uri).getTransportParam() : null;
            if (transport != null) {
                localTransport = transport;
            }
        }

        // Find a SipConnectionNotifier listening on the given port.
        StackConnector stackConnector =
            sipConnectionNotifierImpl.getStackConnector();

        SipConnectionNotifierImpl newNotifier = (SipConnectionNotifierImpl)
            stackConnector.getSipConnectionNotifier(localPort,
                sipConnectionNotifierImpl.getMIMEType());

        return newNotifier;
    
public javax.microedition.sip.SipDialoggetDialog()
Returns the current SIP dialog. This is available when the SipConnection belongs to a created SipDialog and the system has received (or sent) provisional (101-199) or final response (200).

return
SipDialog object if this connection belongs to a dialog, otherwise returns null.

        if (sipDialog != null) {
            byte dialogState = this.sipDialog.getState();
            if ((dialogState != SipDialog.EARLY) &&
                (dialogState != SipDialog.CONFIRMED)) {
                return null;
            }
        }

        return sipDialog;
    
public java.lang.StringgetHeader(java.lang.String name)
Gets the header field value of specified header type.

param
name - name of the header type, either in full or compact form. RFC 3261 p.32
return
topmost header field value, or null if the current message does not have such a header or the header is for other reason not available (e.g. message not initialized).

        Message currentMessage = useResponse ? (Message)response :
            (Message)request;

        // Return null if associated request or response is null
        if (currentMessage == null) {
            return null;
        }

        Header header = currentMessage.getHeader(name);

        if (header == null) {
            return null;
        }

        return header.getHeaderValue();
    
public java.lang.String[]getHeaders(java.lang.String name)
Gets the header field value(s) of specified header type

param
name - name of the header, either in full or compact form. RFC 3261 p.32
return
array of header field values (topmost first), or null if the current message does not have such a header or the header is for other reason not available (e.g. message not initialized).

        Message currentMessage = useResponse ? (Message)response :
            (Message)request;

        // Return null if associated request or response is null
        if (currentMessage == null) {
            return null;
        }

        HeaderList nameList = currentMessage.getHeaderList(name);

        if (nameList == null) {
            return null;
        }

        int size = nameList.size();

        if (size < 1) {
            return null;
        }

        String[] headerValues = new String[size];

        for (int count = 0; count < size; count++) {
            headerValues[count] =
                    ((Header)nameList.elementAt(count)).getHeaderValue();
        }

        return headerValues;
    
public java.lang.StringgetMethod()
Gets the SIP method. Applicable when a message has been initialized or received.

return
SIP method name REGISTER, INVITE, NOTIFY, etc. Returns null if the method is not available.

        if (TERMINATED == state) {
            return null;
        } else {
            return request.getMethod();
        }
    
public java.lang.StringgetReasonPhrase()
Gets SIP response reason phrase. Available when SipClientConnection is in Proceeding or Completed state or when SipServerConnection is in Initialized state.

return
reason phrase. Returns null if the reason phrase is not available.

        if (state != INITIALIZED || response == null) {
            return null;
        } else {
            return response.getReasonPhrase();
        }
    
public java.lang.StringgetRequestURI()
Gets Request-URI. Available when SipClientConnection is in Initialized state or when SipServerConnection is in Request Received state. Built from the original URI given in Connector.open(). See RFC 3261 p.35 (8.1.1.1 Request-URI)

return
Request-URI of the message. Returns null if the Request-URI is not available.

        // from the JSR180 spec:
        // "Returns null if the Request-URI is not available...
        // Available when... SipServerConnection is in Request Received state."
        // Most likely, because only in this case there's no ambiguity whether
        // the request or the response was meant.
        if (REQUEST_RECEIVED != state) {
            return null;
        } else {
            return request.getRequestURI().toString();
        }
    
public intgetState()
Return the state of SIP server connection

return
state of the SIP Server Connection

        return state;
    
public intgetStatusCode()
Gets SIP response status code. Available when SipClientConnection is in Proceeding or Completed state or when SipServerConnection is in Initialized state.

return
status code 1xx, 2xx, 3xx, 4xx, ... Returns 0 if the status code is not available.

        if (state != INITIALIZED || response == null) {
            return 0;
        } else {
            return response.getStatusCode();
        }
    
public voidinitResponse(int code)
Initializes SipServerConnection with a specific SIP response to the received request. The default headers and reason phrase will be initialized automatically. After this the SipServerConnection is in Initialized state. The response can be sent. The procedure of generating the response and header fields is defined in RFC 3261 [1] p. 49-50. At least following information is set by the method: From MUST equal the From header field of the request Call-ID MUST equal the Call-ID header field of the request CSeq MUST equal the CSeq field of the request Via MUST equal the Via header field values in the request and MUST maintain the same ordering To MUST Copy if exists in the original request, 'tag' MUST be added if not present Furthermore, if the system has automatically sent the 100 Trying response, the 100 response initialized and sent by the user is just ignored.

param
code - Response status code 1xx - 6xx
throws
IllegalArgumentException - if the status code is out of range 100-699 (RFC 3261 p.28-29)
throws
SipException - INVALID_STATE if the response can not be initialized, because of wrong state.

        // Check if the code is not out of range
        if (code < 100 || code > 699)
            throw new
                IllegalArgumentException("the response code is out of range.");

        // Check if we are in a good state to init the response
        if (state != REQUEST_RECEIVED)
            throw new SipException("the response can not be initialized,"
                    + " because of wrong state.",
                    SipException.INVALID_STATE);

        // Generating the response to the request
        try {
            response = StackConnector
                    .messageFactory.createResponse(code, request);
        } catch (ParseException pe) {
            if (Logging.REPORT_LEVEL <= Logging.ERROR) {
                Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
                    "Exception in SSC.initResponse(): " + pe);
                pe.printStackTrace();
            }
        }

        // Set the toTag in the ToHeader if not already present
        ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
        if (toHeader.getTag() == null)
            toHeader.setTag(StackConnector.generateTag());

        // if we don't have any contact headers we add one
        ContactList contactList = response.getContactHeaders();
        if (contactList == null || contactList.isEmpty()) {
            ContactHeader contactHeader = null;
            String transport = sipConnectionNotifierImpl.
                getSipProvider().getListeningPoint().getTransport();
            try {
                Address address = StackConnector
                        .addressFactory
                        .createAddress(
                        "<sip:"
                        + sipConnectionNotifierImpl.getLocalAddress()
                        + ":"
                        + sipConnectionNotifierImpl.getLocalPort()
                        + ";transport="
                        + transport
                        + ">");
                contactHeader = StackConnector.headerFactory
                        .createContactHeader(address);
                response.addHeader(contactHeader);
            } catch (IOException ioe) {
                ioe.printStackTrace();
            } catch (ParseException pe) {
                pe.printStackTrace();
            }
        }

        state = INITIALIZED;
        useResponse = true;

        // System.out.println("The following response has been initialized:\n"+
        //                    response.toString());
    
public java.io.InputStreamopenContentInputStream()
Returns InputStream to read SIP message body content.

return
InputStream to read body content
throws
java.io.IOException - if the InputStream can not be opened, because of an I/O error occurred.
throws
SipException - INVALID_STATE the InputStream can not be opened in this state (e.g. no message received).

        if (state != REQUEST_RECEIVED)
            throw new SipException("the content input stream can not be open,"
                    + " because of wrong state: " + state,
                    SipException.INVALID_STATE);

        if (request == null) {
            throw new IOException("Request is null.");
        }

        ContentLengthHeader contentLengthHeader =
            request.getContentLengthHeader();
        if (contentLengthHeader == null) {
            throw new
                IOException("Request contains no content length header.");
        }

        int bodyLength = contentLengthHeader.getContentLength();
        if (bodyLength == 0) {
            throw new IOException("Request's body has zero length.");
        }

        byte[] buf = request.getRawContent();
        if (buf == null) { // body is empty
            throw new IOException("Body of SIP request is empty.");
        }

        contentInputStream = new ByteArrayInputStream(buf);
        return contentInputStream;
    
public java.io.OutputStreamopenContentOutputStream()
Returns OutputStream to fill the SIP message body content. When calling close() on OutputStream the message will be sent to the network. So it is equivalent to call send(). Again send() must not be called after closing the OutputStream, since it will throw Exception because of calling the method in wrong state. Before opening OutputStream the Content-Length and Content-Type headers has to se set. If not SipException.UNKNOWN_LENGTH or SipException.UNKNOWN_TYPE will be thrown respectively.

return
OutputStream to write body content
throws
IOException if the OutputStream can not be opened, because of an I/O error occurred.
throws
SipException INVALID_STATE the OutputStream can not be opened in this state (e.g. no message initialized). UNKNOWN_LENGTH Content-Length header not set. UNKNOWN_TYPE Content-Type header not set.

        if (state != INITIALIZED)
            throw new SipException("the content output strean can not be open,"
                    + " because of wrong state.",
                    SipException.INVALID_STATE);
        if (state == TERMINATED) {
            throw new IOException("can not open content output stream"
                    + " because SipServerConnection is TERMINATED");
        }

        if (response.getHeader(Header.CONTENT_TYPE) == null)
            throw new SipException("Content-Type unknown, set the"
                    + " content-type header first",
                    SipException.UNKNOWN_TYPE);
        if (response.getHeader(Header.CONTENT_LENGTH) == null)
            throw new SipException("Content-Length unknown, set the "
                    + "content-length header first",
                    SipException.UNKNOWN_LENGTH);
        contentOutputStream = new SDPOutputStream(this);
        state = STREAM_OPEN;
        return contentOutputStream;
    
public voidremoveHeader(java.lang.String name)
Removes header from the SIP message. If multiple header field values exist the topmost is removed. The implementations MAY restrict the access to some headers according to RFC 3261. If the named header is not found this method does nothing.

param
name - name of the header to be removed, either int full or compact form RFC 3261 p.32.
throws
SipException - INVALID_STATE if header can not be removed in this state.
INVALID_OPERATION if the system does not allow to remove this header.

        if (state != INITIALIZED) {
            throw new SipException("the Header can not be removed,"
                    + " because of wrong state.",
                    SipException.INVALID_STATE);
        }

        if (name == null) {
            throw new
                    IllegalArgumentException("The header name can not be null");
        }

        Message currentMessage = useResponse ? (Message)response :
            (Message)request;

        if (currentMessage == null) {
            throw new SipException("Failure in removeHeader(),"
                    + " associated request or response is null",
                    SipException.INVALID_MESSAGE);
        }

        currentMessage.removeHeader(name, true);
    
public voidsend()
(non-Javadoc)

see
javax.microedition.sip.SipConnection#send()

        if (state == REQUEST_RECEIVED) {
            throw new SipException("can not send response"
                    + " because of wrong state.",
                    SipException.INVALID_STATE);
        }

        if ((state == COMPLETED) && !resend2xxAllowed) {
            throw new SipException("COMPLETED state allows"
                    + " only resend of 2xx responses",
                    SipException.INVALID_STATE);
        }

        if (state == TERMINATED) {
            throw new SipException("can not send response"
                    + " because SipServerConnection is TERMINATED",
                    SipException.INVALID_STATE);
        }

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                "Actual request for the response we want to send:\n" +
                request.toString());
        }

        ServerTransaction serverTransaction =
                (ServerTransaction)request.getTransaction();

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                "SipServerTransaction :" + serverTransaction);
        }

        // Set the sdp body of the message
        if (contentOutputStream != null) {
            contentOutputStream.setOpen(false);
            response.setContent(
                contentOutputStream.getByteArrayOutputStream().toByteArray());
            contentOutputStream = null;
        }

        String method = request.getMethod();
        final int statusCode = response.getStatusCode();
        final int statusGroup = statusCode / 100;

        // send the response
        if (!resend2xxAllowed) { // don't create new transaction on resending
            SipStack sipStack =
                sipConnectionNotifierImpl.getStackConnector().getSipStack();

            if (serverTransaction == null || sipStack.isDialogCreated(method)) {
                try {
                    SipProvider sipProvider =
                        sipConnectionNotifierImpl.getSipProvider();
                    if (serverTransaction == null) {
                        serverTransaction =
                            sipProvider.getNewServerTransaction(request);
                    } else {
                        /*
                         * 12.1 Creation of a Dialog
                         * Dialogs are created through the generation of
                         * non-failure responses to requests with specific
                         * methods.  Within this specification, only 2xx and
                         * 101-199 responses with a To tag, where the request
                         * was INVITE, will establish a dialog.
                         */
                        if (statusCode > 100 && statusCode < 300) {
                            // Equip a dialog in case of dialog is null
                            // or its state is INITIALIZED only prevent
                            // changing contact property of dialog by
                            // sending 200 OK response for INVITE
                            // after sending 200 OK for UPDATE
                            boolean equipDialog = false;
                            if (sipDialog == null) {
                                equipDialog = true;
                            } else if (sipDialog.getState() ==
                                    Dialog.INITIAL_STATE) {
                                equipDialog = true;
                            }

                            if (equipDialog) {
                                sipProvider.equipADialogForTransaction(
                                    serverTransaction, request);
                            }
                        } else if ((sipDialog != null) &&
                            (statusGroup > 2 && statusGroup < 7)) {
                            // JSR180, p.42
                            // Terminated state: error response (3xx-6xx)
                            // received (or sent).
                            ((SipDialogImpl)sipDialog).setState
                                    (SipDialog.TERMINATED);
                        }
                    }
                } catch (TransactionAlreadyExistsException taee) {
                    if (Logging.REPORT_LEVEL <= Logging.ERROR) {
                        Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
                            "Exception in SSC.send(): " + taee);
                        taee.printStackTrace();
                    }
                    // return;
                } catch (TransactionUnavailableException tue) {
                    if (Logging.REPORT_LEVEL <= Logging.ERROR) {
                        Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
                            "Exception in SSC.send(): " + tue);
                        tue.printStackTrace();
                    }
                    // return;
                }
            }
        }

        SipConnectionNotifierImpl newNotifier = sipConnectionNotifierImpl;

        if (sipDialog != null) {
            Dialog dialog = ((SipDialogImpl)sipDialog).getDialog();

            if (dialog != null &&
                    (statusCode > 199 && statusCode < 300)) {
                if (method.equals(Request.UPDATE)) {
                    // processing UPDATE - change dialog contact property
                    dialog.addRoute(serverTransaction.getOriginalRequest());
                }

                newNotifier = findNotifier();
                Transaction transaction = (Transaction)
                    dialog.getFirstTransaction();
                if (transaction instanceof ServerTransaction) {
                    transaction.setApplicationData(newNotifier);
                }

                if (newNotifier != null) {
                    sipConnectionNotifierImpl = newNotifier;
                }
            }
        }

        // Set the application data so that when the request comes in,
        // it will retrieve this SipConnectionNotifier
        serverTransaction.setApplicationData(newNotifier);

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                "response to send : " + response);
        }

        // May throw IOException and SipException
        serverTransaction.sendResponse(response);

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
                "response sent");
        }

        // Change the state of SipServerConnection
        int responseClass = response.getStatusCode()/100;
        if (responseClass == 1) { // 1xx responses
            state = REQUEST_RECEIVED;
        } else {
            state = COMPLETED;
            if (responseClass == 2) {
                // Allow 2xx response to be resent
                resend2xxAllowed = true;
            }
        }

        // Change the dialog state
        changeDialogState(serverTransaction);
    
public voidsetHeader(java.lang.String name, java.lang.String value)
Sets header value in SIP message. If the header does not exist it will be added to the message, otherwise the existing header is overwritten. If multiple header field values exist the topmost is overwritten. The implementations MAY restrict the access to some headers according to RFC 3261.

param
name - name of the header, either in full or compact form. RFC 3261 p.32
param
value - the header value
throws
SipException - INVALID_STATE if header can not be set in this state.
INVALID_OPERATION if the system does not allow to set this header.
throws
IllegalArgumentException - MAY be thrown if the header or value is invalid

        if (state != INITIALIZED)
            throw new SipException("the Header can not be set,"
                    + " because of wrong state.",
                    SipException.INVALID_STATE);

        if (name == null)
            throw new
                IllegalArgumentException("The header name can not be null");

        if (value == null)
            throw new
                IllegalArgumentException("The header value can not be null");

        Header header = null;

        try {
            header = StackConnector.headerFactory.createHeader(name, value);
        } catch (ParseException pe) {
            throw new IllegalArgumentException(pe.getMessage());
        }

        if (header == null)
            throw new IllegalArgumentException("null header!");

        // response.attachHeader(header, false, true);
        Message currentMessage = useResponse ? (Message)response :
            (Message)request;

        if (currentMessage == null) {
            throw new SipException("Failure in setHeader(),"
                    + " associated request or response is null",
                    SipException.INVALID_MESSAGE);
        }

        currentMessage.attachHeader(header, true, true);
    
public voidsetReasonPhrase(java.lang.String phrase)
Changes the default reason phrase.

param
phrase the default reason phrase.
throws
SipException INVALID_STATE if the response can not be initialized, because of wrong state. INVALID_OPERATION if the reason phrase can not be set.
throws
IllegalArgumentException if the reason phrase is illegal.

        if (state != INITIALIZED)
            throw new SipException("the Reason Phrase can not be set,"
                    + " because of wrong state.",
                    SipException.INVALID_STATE);

        if (phrase == null) {
            throw new
                IllegalArgumentException("The reason phrase can not be null.");
        }

        // RFC 3261, section 7.2: No CR or LF is allowed
        // (in the Status Line) except in the final CRLF sequence.
        if ((phrase.indexOf("\n") != -1) || (phrase.indexOf("\r") != -1)) {
            throw new
                IllegalArgumentException("Invalid reason phrase.");
        }

        response.setReasonPhrase(phrase);