com.bt.aloha.stack.SimpleSipStack.java Source code

Java tutorial

Introduction

Here is the source code for com.bt.aloha.stack.SimpleSipStack.java

Source

/*
 * Aloha Open Source SIP Application Server- https://trac.osmosoft.com/Aloha
 *
 * Copyright (c) 2008, British Telecommunications plc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 3.0 of the License, or (at your option) any later
 * version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package com.bt.aloha.stack;

import gov.nist.javax.sip.ListeningPointImpl;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.header.CSeq;
import gov.nist.javax.sip.header.RouteList;
import gov.nist.javax.sip.header.Via;
import gov.nist.javax.sip.message.SIPResponse;

import java.net.SocketException;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.Vector;

import javax.sdp.SessionDescription;
import javax.sip.ClientTransaction;
import javax.sip.ListeningPoint;
import javax.sip.PeerUnavailableException;
import javax.sip.ResponseEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.SipFactory;
import javax.sip.SipListener;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.TransactionAlreadyExistsException;
import javax.sip.TransactionUnavailableException;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.URI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.ToHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.MDC;

import com.bt.aloha.util.NetworkHelper;

public class SimpleSipStack {
    public static final String CONTENT_TYPE_APPLICATION = "application";

    public static final String CONTENT_SUBTYPE_SDP = "sdp";

    public static final String SIP_MESSAGES_LOGGER = "com.bt.aloha.messages";

    private static final String TRUE = "true";

    private static final String GOV_NIST_JAVAX_SIP_REENTRANT_LISTENER = "gov.nist.javax.sip.REENTRANT_LISTENER";

    private static final String GOV_NIST_JAVAX_SIP_LOG_MESSAGE_CONTENT = "gov.nist.javax.sip.LOG_MESSAGE_CONTENT";

    private static final String JAVAX_SIP_STACK_NAME = "javax.sip.STACK_NAME";

    private static final String JAVAX_SIP_AUTOMATIC_DIALOG_SUPPORT = "javax.sip.AUTOMATIC_DIALOG_SUPPORT";

    private static final String JAVAX_SIP_RETRANSMISSION_FILTER = "javax.sip.RETRANSMISSION_FILTER";

    private static final String JAVAX_SIP_ROUTER_PATH = "javax.sip.ROUTER_PATH";

    private static final String JAVAX_SIP_OUTBOUND_PROXY = "javax.sip.OUTBOUND_PROXY";

    private static final String GOV_NIST_JAVAX_SIP_TRACE_LEVEL = "gov.nist.javax.sip.TRACE_LEVEL";

    private static final String GOV_NIST_JAVAX_SIP_DEBUG_LOG = "gov.nist.javax.sip.DEBUG_LOG";

    private static final String GOV_NIST_JAVAX_SIP_SERVER_LOG = "gov.nist.javax.sip.SERVER_LOG";

    private static final String GOV_NIST_JAVAX_SIP_THREAD_POOL_SIZE = "gov.nist.javax.sip.THREAD_POOL_SIZE";

    private static final String GOV_NIST_JAVAX_SIP_CANCEL_CLIENT_TRANSACTION_CHECKED = "gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED";

    private static final String GOV_NIST_JAVAX_SIP_MAX_SERVER_TRANSACTIONS = "gov.nist.javax.sip.MAX_SERVER_TRANSACTIONS";

    private static final String HR = "--------------------------------------------------";

    private static final String ERROR_PROXYING_REQUEST_STRING = "Error proxying request";

    private static final int DEFAULT_MAX_FORWARDS_VALUE = 70;

    private static final String ERROR_CREATING_NEW_SERVER_TRANSACTION_STRING = "Error creating new server transaction for call id: %s";

    private static final int DEFAULT_SIP_PORT = 5060;

    private static final Log LOG = LogFactory.getLog(SimpleSipStack.class);

    private static final Log SIP_LOG = LogFactory.getLog(SIP_MESSAGES_LOGGER);

    private SipStack sipStack;

    private String ipAddress;

    private int port;

    private String transport;

    private SipProvider sipProvider;

    private SipListener sipListener;

    private MessageFactory messageFactory;

    private AddressFactory addressFactory;

    private HeaderFactory headerFactory;

    private String contactAddress;

    private Random random = new Random((new Date()).getTime());

    private String stackName;

    private String sipTraceLevel = "16";

    private String sipDebugLog = "debugLog.txt";

    private String sipServerLog = "serverLog.txt";

    private int sleepIntervalBeforeSending;

    private Properties jainStackProps = new Properties();

    private SipStackMessageQueueCollection sipStackMessageQueueCollection;

    public SimpleSipStack() {
        this.contactAddress = null;
        this.sleepIntervalBeforeSending = 0;
        this.sipStackMessageQueueCollection = null;
    }

    public String getStackName() {
        return stackName;
    }

    public void setJainStackProperties(Properties someProps) {
        this.jainStackProps = someProps;
    }

    public Properties getJainStackProperties() {
        return this.jainStackProps;
    }

    public void setSipListener(final SipListener aSipListener) {
        this.sipListener = aSipListener;
    }

    public void setSipDebugLog(String aSipDebugLog) {
        this.sipDebugLog = aSipDebugLog;
    }

    public void setSipServerLog(String aSipServerLog) {
        this.sipServerLog = aSipServerLog;
    }

    public void setSipTraceLevel(String aSipTraceLevel) {
        this.sipTraceLevel = aSipTraceLevel;
    }

    public String getContactAddress() {
        String address = null;
        if (this.contactAddress != null) {
            address = this.contactAddress;
        } else {
            address = getIpAddress() + (getPort() == DEFAULT_SIP_PORT ? "" : ":" + getPort());
        }
        return address;
    }

    public void setContactAddress(final String aContactAddress) {
        if (null == aContactAddress || aContactAddress.length() < 1) {
            this.contactAddress = null;
            return;
        }
        LOG.info(String.format("Setting contact address for stack %s to %s", stackName, aContactAddress));
        this.contactAddress = aContactAddress;
    }

    public String getIpAddress() {
        return this.ipAddress;
    }

    public int getPort() {
        return this.port;
    }

    public String getTransport() {
        return this.transport;
    }

    public SipProvider getSipProvider() {
        return this.sipProvider;
    }

    public AddressFactory getAddressFactory() {
        return this.addressFactory;
    }

    public HeaderFactory getHeaderFactory() {
        return this.headerFactory;
    }

    public MessageFactory getMessageFactory() {
        return this.messageFactory;
    }

    public void setNextHopRoutes(String routes) {
        if (routes == null || routes.trim().length() == 0)
            return;
        String[] hops = routes.split(";");
        for (String hop : hops) {
            String[] values = hop.split("=");
            if (values.length != 2)
                throw new IllegalArgumentException(String.format("Invalid routes set: %s", routes));
        }
        System.setProperty(NextHopRouter.NEXT_HOP + "_" + stackName, routes);
    }

    public void setSipStackMessageQueueCollection(SipStackMessageQueueCollection aSipMessageQueueCollection) {
        this.sipStackMessageQueueCollection = aSipMessageQueueCollection;
    }

    protected SipStack createSipStack() throws PeerUnavailableException {
        MDC.put("stackname", this.stackName);
        SipFactory sipFactory = SipFactory.getInstance();
        sipFactory.setPathName("gov.nist");

        this.headerFactory = sipFactory.createHeaderFactory();
        this.addressFactory = sipFactory.createAddressFactory();
        this.messageFactory = sipFactory.createMessageFactory();

        LOG.debug(String.format("Sip logging tracelevel: %s, debug log: %s, server log: %s", sipTraceLevel,
                sipDebugLog, sipServerLog));

        if (!jainStackProps.keySet().contains(GOV_NIST_JAVAX_SIP_LOG_MESSAGE_CONTENT))
            jainStackProps.setProperty(GOV_NIST_JAVAX_SIP_LOG_MESSAGE_CONTENT, TRUE);
        if (!jainStackProps.keySet().contains(JAVAX_SIP_STACK_NAME))
            jainStackProps.setProperty(JAVAX_SIP_STACK_NAME, this.stackName);
        if (!jainStackProps.keySet().contains(JAVAX_SIP_RETRANSMISSION_FILTER))
            jainStackProps.setProperty(JAVAX_SIP_RETRANSMISSION_FILTER, "on");
        if (!jainStackProps.keySet().contains(JAVAX_SIP_AUTOMATIC_DIALOG_SUPPORT))
            jainStackProps.setProperty(JAVAX_SIP_AUTOMATIC_DIALOG_SUPPORT, "off");
        if (!jainStackProps.keySet().contains(GOV_NIST_JAVAX_SIP_REENTRANT_LISTENER))
            jainStackProps.setProperty(GOV_NIST_JAVAX_SIP_REENTRANT_LISTENER, TRUE);

        return sipFactory.createSipStack(jainStackProps);
    }

    public void init() {
        LOG.info(String.format("Creating stack listening point - address: %s port: %d transport: %s",
                this.ipAddress, Integer.valueOf(this.port), this.transport));
        try {
            this.sipStack = this.createSipStack();
        } catch (PeerUnavailableException e) {
            throw new StackException("Problem creating Sip Stack using SipFactory.", e);
        }

        initStackListener(this.sipStack, this.ipAddress, this.port, this.transport);

        showStartupMessage();
    }

    private void showStartupMessage() {
        LOG.info(HR);
        LOG.info("               Started SimpleSipStack             ");
        LOG.info(HR);
        LOG.info(stackName);
        LOG.info(" - IP Address: " + getIpAddress());
        LOG.info(" - Port:       " + getPort());
        LOG.info(" - Transport:  " + getTransport());

        if (this.jainStackProps.keySet().contains(JAVAX_SIP_OUTBOUND_PROXY))
            LOG.info(" - Outbound Proxy:  " + this.jainStackProps.getProperty(JAVAX_SIP_OUTBOUND_PROXY));
        if (this.jainStackProps.keySet().contains(JAVAX_SIP_ROUTER_PATH))
            LOG.info(" - Sip Router class:  " + this.jainStackProps.getProperty(JAVAX_SIP_ROUTER_PATH));
        if (this.sipStackMessageQueueCollection != null)
            LOG.info(" - Sip message queue retry interval:  "
                    + this.sipStackMessageQueueCollection.getQueuedSipMessageBlockingInterval());
        LOG.info(HR);
    }

    protected void initStackListener(SipStack stack, String ip, int aPort, String aTransport) {
        try {
            ListeningPoint lp = stack.createListeningPoint(ip, aPort, aTransport);
            this.sipProvider = stack.createSipProvider(lp);
            this.sipProvider.addSipListener(this.sipListener);
            stack.start();
        } catch (Throwable t) {
            throw new StackException("Failed to add listening point", t);
        }
    }

    public void destroy() {
        if (this.sipStack != null) {
            this.sipStack.stop();
            this.sipStack = null;
        }

        LOG.info(String.format("One listening point (port %d, transport %s) removed for stack on %s",
                Integer.valueOf(this.port), this.transport, this.ipAddress));
    }

    /**
     * @param ipPattern
     * @return The host address matching the wildcard pattern passed in. If no
     *         network address matches the pattern then a StackException is
     *         thrown.
     * @throws StackException
     */
    public void setIpAddress(final String ipPattern) {
        String hostAddress;
        try {
            hostAddress = NetworkHelper.lookupIpAddress(ipPattern);
        } catch (SocketException e) {
            throw new StackException("Problem looking up network interfaces", e);
        }

        if (hostAddress == null) {
            throw new StackException(String.format("No network adapter matches IP address pattern %s", ipPattern));
        }

        ipAddress = hostAddress;
    }

    public String generateNewTag() {
        int r = this.random.nextInt(Integer.MAX_VALUE);
        return Integer.toString(r);
    }

    protected SipStack getSipStack() {
        return sipStack;
    }

    protected void setSipStack(SipStack aSipStack) {
        this.sipStack = aSipStack;
    }

    public int getSleepIntervalBeforeSending() {
        return sleepIntervalBeforeSending;
    }

    public void setSleepIntervalBeforeSending(int aSleepIntervalBeforeSending) {
        if (aSleepIntervalBeforeSending > 0) {
            LOG.warn(HR);
            LOG.warn(String.format("Setting sleep interval before sends to %d", aSleepIntervalBeforeSending));
            LOG.warn(HR);
        }
        this.sleepIntervalBeforeSending = aSleepIntervalBeforeSending;
    }

    public ServerTransaction createNewServerTransaction(Request request) {
        try {
            return getSipProvider().getNewServerTransaction(request);
        } catch (TransactionAlreadyExistsException e) {
            throw new StackException(String.format(ERROR_CREATING_NEW_SERVER_TRANSACTION_STRING,
                    ((CallIdHeader) request.getHeader(CallIdHeader.NAME)).getCallId()), e);
        } catch (TransactionUnavailableException e) {
            throw new StackException(String.format(ERROR_CREATING_NEW_SERVER_TRANSACTION_STRING,
                    ((CallIdHeader) request.getHeader(CallIdHeader.NAME)).getCallId()), e);
        }
    }

    public void sendResponse(Request request, ServerTransaction serverTransaction, int responseCode) {
        LOG.info("Sending response " + responseCode + " with server transaction");
        ServerTransaction newServerTransaction = serverTransaction;
        if (newServerTransaction == null) {
            LOG.warn("No server transaction, creating one");
            newServerTransaction = createNewServerTransaction(request);
        }
        Response response;
        try {
            response = getMessageFactory().createResponse(responseCode, request);
        } catch (ParseException e) {
            throw new IllegalArgumentException("Error creating response", e);
        }
        sendResponse(response, newServerTransaction);
    }

    public void sendResponse(Response response, ServerTransaction serverTransaction) {
        sleepBeforeSending();
        SIP_LOG.debug(String.format("Sending response:\n%s", response.toString()));
        try {
            serverTransaction.sendResponse(response);
        } catch (Throwable t) {
            throw new StackException("Unable to send response", t);
        }
    }

    public Request createAckRequest(ResponseEvent responseEvent, String requestUri, RouteList routeList) {
        try {
            SipUri requestURI = (SipUri) getAddressFactory().createAddress(requestUri).getURI();
            CSeq cseq = new CSeq();
            cseq.setMethod(Request.ACK);
            cseq.setSeqNumber(((CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME)).getSeqNumber());

            // Via header
            ListeningPointImpl lp = (ListeningPointImpl) getSipProvider().getListeningPoint(getTransport());
            Via via = lp.getViaHeader();

            Request ackRequest = ((SIPResponse) responseEvent.getResponse()).createRequest(requestURI, via, cseq);
            if (routeList != null && routeList.size() > 0) {
                LOG.debug(String.format("Setting route list for ACK request to %s", routeList.toString()));
                ackRequest.addHeader(routeList);
            }
            return ackRequest;
        } catch (Throwable t) {
            throw new StackException("Failed to create ACK request", t);
        }
    }

    public Request createRequest(String requestUri, String method, String callId, long sequenceNumber,
            Address localParty, String localTag, Address remoteParty, String remoteTag, String viaBranchId,
            RouteList routeList, SessionDescription sessionDescription) {
        LOG.debug(String.format(
                "Creating request with requestUri %s, method %s, callId %s, seqnum %d, localParty %s, localTag %s, remoteParty %s, remoteTag %s, sdp\n%s\n",
                requestUri, method, callId, sequenceNumber, localParty.getURI().toString(), localTag,
                remoteParty.getURI().toString(), remoteTag, sessionDescription));

        try {
            SipUri requestURI = (SipUri) getAddressFactory().createAddress(requestUri).getURI();

            // Call-ID:
            CallIdHeader callIdHeader;
            callIdHeader = getHeaderFactory().createCallIdHeader(callId);

            CSeqHeader cseqHeader = getHeaderFactory().createCSeqHeader(sequenceNumber, method);

            // From Header:
            FromHeader fromHeader = getHeaderFactory().createFromHeader(localParty, localTag);

            // To header:
            ToHeader toHeader = getHeaderFactory().createToHeader(remoteParty, remoteTag);

            // Via header
            ListeningPointImpl lp = (ListeningPointImpl) getSipProvider().getListeningPoint(getTransport());
            ViaHeader viaHeader = lp.getViaHeader();
            if (viaBranchId != null)
                viaHeader.setBranch(viaBranchId);
            List<ViaHeader> viaList = new Vector<ViaHeader>();
            viaList.add(viaHeader);

            // MaxForwards header:
            MaxForwardsHeader maxForwardsHeader = getHeaderFactory()
                    .createMaxForwardsHeader(DEFAULT_MAX_FORWARDS_VALUE);

            Request request = null;
            if (sessionDescription != null) {
                // Content-Type:
                ContentTypeHeader contentTypeHeader = getHeaderFactory()
                        .createContentTypeHeader(CONTENT_TYPE_APPLICATION, CONTENT_SUBTYPE_SDP);

                request = getMessageFactory().createRequest(requestURI, method, callIdHeader, cseqHeader,
                        fromHeader, toHeader, viaList, maxForwardsHeader, contentTypeHeader,
                        sessionDescription.toString());
            } else {
                request = getMessageFactory().createRequest(requestURI, method, callIdHeader, cseqHeader,
                        fromHeader, toHeader, viaList, maxForwardsHeader);
            }

            // Contact header
            if (Request.INVITE.equals(request.getMethod()))
                addContactHeader(request);

            // Route set
            if (routeList != null && routeList.size() > 0) {
                LOG.debug(String.format("Setting route list for %s request to %s", method, routeList.toString()));
                request.addHeader(routeList);
            }

            return request;
        } catch (Throwable t) {
            throw new StackException("Failed to create request", t);
        }
    }

    protected void addContactHeader(Request request) {
        addContactHeader(request, null);
    }

    protected void addContactHeader(Request request, String userId) {
        Address contact = getContactAddress(userId);
        request.addHeader(getHeaderFactory().createContactHeader(contact));
    }

    public void addContactHeader(Response response) {
        addContactHeader(response, null);
    }

    public void addContactHeader(Response response, String userId) {
        Address contact = getContactAddress(userId);
        response.addHeader(getHeaderFactory().createContactHeader(contact));
    }

    private Address getContactAddress(String userId) {
        URI calleeContact;
        try {
            calleeContact = getAddressFactory().createURI(getContactSipUri(userId));
        } catch (ParseException e) {
            throw new IllegalArgumentException("Error adding contact header", e);
        }
        return getAddressFactory().createAddress(calleeContact);
    }

    public String getContactSipUri(String userName) {
        return "sip:" + ((userName == null || userName.length() == 0) ? "" : userName + "@") + getContactAddress();
    }

    public void setContent(Response response, String type, String subType, String content) {
        try {
            ContentTypeHeader ct = getHeaderFactory().createContentTypeHeader(type, subType);
            response.setContent(content, ct);
        } catch (ParseException e) {
            throw new IllegalArgumentException("Error adding content", e);
        }
    }

    public ClientTransaction sendRequest(Request request) {
        ClientTransaction clientTransaction;
        try {
            clientTransaction = getSipProvider().getNewClientTransaction(request);
        } catch (TransactionUnavailableException e) {
            throw new StackException("Unable to create a new client transaction", e);
        }
        return sendRequest(clientTransaction);
    }

    public ClientTransaction sendRequest(ClientTransaction clientTransaction) {
        return sendRequest(clientTransaction.getRequest(), clientTransaction);
    }

    public void resendRequest(Request request) {
        sendRequest(request, null);
    }

    private ClientTransaction sendRequest(Request request, ClientTransaction clientTransaction) {
        String sipCallId = ((CallIdHeader) request.getHeader(CallIdHeader.NAME)).getCallId();
        long sequenceNumber = ((CSeqHeader) request.getHeader(CSeqHeader.NAME)).getSeqNumber();
        String requestMethod = request.getMethod();
        try {
            sipStackMessageQueueCollection.blockUntilCanSendRequest(sipCallId, sequenceNumber, requestMethod);
            sleepBeforeSending();
            if (clientTransaction != null) {
                SIP_LOG.debug(String.format("Sending request\n%s", request.toString()));
                clientTransaction.sendRequest();
            } else {
                SIP_LOG.debug(String.format("Sending transactionless request\n%s", request.toString()));
                getSipProvider().sendRequest(request);
            }
            dequeueRequest(sipCallId, sequenceNumber, requestMethod);
            return clientTransaction;
        } catch (Exception t) {
            throw new StackException(
                    String.format("Unable to send request (%s:%s:%d)", sipCallId, requestMethod, sequenceNumber),
                    t);
        }
    }

    private void sleepBeforeSending() {
        if (sleepIntervalBeforeSending > 0) {
            LOG.debug(String.format("sleeping for %d ms", sleepIntervalBeforeSending));
            try {
                Thread.sleep(sleepIntervalBeforeSending);
            } catch (InterruptedException e) {
                LOG.warn(e.getMessage(), e);
            }
        }
    }

    protected void proxyRequest(Request request) {
        proxyRequest(request, null);
    }

    protected void proxyRequest(Request request, String destinationUri) {
        try {
            if (destinationUri != null)
                request.setRequestURI(getAddressFactory().createURI(destinationUri));
            LOG.info(String.format("Proxying request\n%s", request.toString()));
            getSipProvider().sendRequest(request);
        } catch (SipException e) {
            throw new StackException(ERROR_PROXYING_REQUEST_STRING, e);
        } catch (ParseException e) {
            throw new StackException(ERROR_PROXYING_REQUEST_STRING, e);
        }
    }

    protected void proxyResponse(Response response) {
        try {
            ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
            if (viaHeader != null)
                viaHeader.removeParameter(Via.RPORT);
            LOG.info(String.format("Proxying response\n%s", response.toString()));
            getSipProvider().sendResponse(response);
        } catch (SipException e) {
            throw new StackException(ERROR_PROXYING_REQUEST_STRING, e);
        }
    }

    public long enqueueRequestAssignSequenceNumber(String sipCallId, long sequenceNumber, String method) {
        return sipStackMessageQueueCollection.enqueueRequest(sipCallId, sequenceNumber, method);
    }

    public void enqueueRequestForceSequenceNumber(String sipCallId, long sequenceNumber, String method) {
        sipStackMessageQueueCollection.enqueueRequestForceSequenceNumber(sipCallId, sequenceNumber, method);
    }

    public void dequeueRequest(String sipCallId, long sequenceNumber, String requestMethod) {
        sipStackMessageQueueCollection.dequeueRequest(sipCallId, sequenceNumber, requestMethod);
    }

    public void setPort(int aPort) {
        this.port = aPort;
    }

    public void setTransport(String aTransport) {
        this.transport = aTransport;
    }

    public void setStackName(String aStackName) {
        this.stackName = aStackName;
    }

    public void setJainStackPropertiesTraceLevel(String traceLevel) {
        this.jainStackProps.put(GOV_NIST_JAVAX_SIP_TRACE_LEVEL, traceLevel);
    }

    public void setJainStackPropertiesDebugLog(String debugLog) {
        this.jainStackProps.put(GOV_NIST_JAVAX_SIP_DEBUG_LOG, debugLog);
    }

    public void setJainStackPropertiesServerLog(String serverLog) {
        this.jainStackProps.put(GOV_NIST_JAVAX_SIP_SERVER_LOG, serverLog);
    }

    public void setJainStackPropertiesThreadPoolSize(String threadPoolSize) {
        this.jainStackProps.put(GOV_NIST_JAVAX_SIP_THREAD_POOL_SIZE, threadPoolSize);
    }

    public void setJainStackPropertiesCancelClientTransactionChecked(String cancelClientTransactionChecked) {
        this.jainStackProps.put(GOV_NIST_JAVAX_SIP_CANCEL_CLIENT_TRANSACTION_CHECKED,
                cancelClientTransactionChecked);
    }

    public void setJainStackPropertiesMaxServerTransactions(int maxServerTransactions) {
        this.jainStackProps.put(GOV_NIST_JAVAX_SIP_MAX_SERVER_TRANSACTIONS, maxServerTransactions);
    }

    public void setJainStackPropertiesRouterPath(String routerPath) {
        this.jainStackProps.put(JAVAX_SIP_ROUTER_PATH, routerPath);
    }
}