Package com.ericsson.ssa.sip

Source Code of com.ericsson.ssa.sip.B2buaHelperImpl

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.ericsson.ssa.sip;

import com.ericsson.ssa.config.SipFactoryFacade;
import com.ericsson.ssa.sip.PathNode.Type;

import com.sun.enterprise.util.LocalStringManagerImpl;

import org.jvnet.glassfish.comms.util.LogUtil;

import java.net.InetAddress;
import java.net.InetSocketAddress;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.sip.Address;
import javax.servlet.sip.B2buaHelper;
import javax.servlet.sip.ServletParseException;
import javax.servlet.sip.SipApplicationSession;
import javax.servlet.sip.SipFactory;
import javax.servlet.sip.SipServletMessage;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipServletResponse;
import javax.servlet.sip.SipSession;
import javax.servlet.sip.TooManyHopsException;
import javax.servlet.sip.UAMode;
import javax.servlet.sip.URI;
import javax.servlet.sip.ar.SipApplicationRoutingDirective;
import javax.servlet.sip.ar.SipApplicationRoutingRegion;


/**
* Implementation of jsr289 B2buaHelper interface.
*
* @author ehsroha
*/
public class B2buaHelperImpl implements B2buaHelper {
    private static final Logger _log = LogUtil.SIP_LOGGER.getLogger();
    protected static final LocalStringManagerImpl localStrings = new LocalStringManagerImpl(SipSessionImplBase.class);
    private SipServletRequestImpl _originalRequest = null;
    private final SipFactory _sf;

    public B2buaHelperImpl(SipServletRequestImpl req) {
        _sf = req.getApplicationSessionImpl().getServletDispatcher()
                 .getSipFactory();

        if (req.isInitial()) {
            _originalRequest = req;
        }
    }

    public synchronized SipServletRequest createRequest(
        SipServletRequest origRequest, boolean linkedSessions,
        Map<String, List<String>> headerMap)
        throws IllegalArgumentException, TooManyHopsException {
        if (origRequest == null) {
            throw new NullPointerException();
        }

        if (!origRequest.isInitial()) {
            throw new IllegalStateException();
        }

        if (origRequest.getMaxForwards() == 0) {
            throw new TooManyHopsException();
        }

        Map<String, List<String>> clonedHeaderMap = null;

        if (headerMap != null) {
            clonedHeaderMap = new HashMap<String, List<String>>(headerMap);
        } else {
            clonedHeaderMap = new HashMap<String, List<String>>();
        }

        List<String> from = null;
        List<String> to = null;
        List<String> contact = null;
        List<String> route = null;

        if (clonedHeaderMap != null) {
            from = clonedHeaderMap.remove("From");
            to = clonedHeaderMap.remove("To");
            contact = clonedHeaderMap.remove("Contact");
            route = clonedHeaderMap.remove("Route");
        }

        SipServletRequestImpl origRequestImpl = (SipServletRequestImpl) origRequest;

        if ((clonedHeaderMap != null) && !clonedHeaderMap.isEmpty()) {
            // are there any illegal system headers to add?
            if (isSystemHeader(clonedHeaderMap.keySet(), origRequestImpl, true)) {
                // not allowed to add system headers...
                throw new IllegalArgumentException();
            }
        }

        // time to give birth to a new request...
        SipServletRequest copiedReq = null;

        // need special treatment for from and to headers
        // Set<String> from = headerMap != null ? headerMap.remove("From") : null;
        // Set<String> to = headerMap != null ? headerMap.remove("To") : null;
        SipFactoryFacade sfImpl = (SipFactoryFacade) _sf;
        SipApplicationSessionImpl sappSessImpl = (SipApplicationSessionImpl) origRequest.getApplicationSession();

        try {
            if ((from != null) && (to != null)) {
                copiedReq = sfImpl.createRequestImpl(sappSessImpl,
                        origRequest.getMethod(),
                        sfImpl.createAddress(from.iterator().next()),
                        sfImpl.createAddress(to.iterator().next()), false,
                        origRequestImpl);
            } else if (from != null) {
                copiedReq = sfImpl.createRequestImpl(sappSessImpl,
                        origRequest.getMethod(),
                        sfImpl.createAddress(from.iterator().next()),
                        origRequestImpl.getToImpl(), false, origRequestImpl);
            } else if (to != null) {
                copiedReq = sfImpl.createRequestImpl(sappSessImpl,
                        origRequest.getMethod(), origRequestImpl.getFromImpl(),
                        sfImpl.createAddress(to.iterator().next()), false,
                        origRequestImpl);
            } else {
                copiedReq = sfImpl.createRequestImpl(sappSessImpl,
                        origRequest.getMethod(), origRequestImpl.getFromImpl(),
                        origRequestImpl.getToImpl(), false, origRequestImpl);
            }
        } catch (ServletParseException e) {
            throw new IllegalArgumentException(e);
        }

        SipServletRequestImpl copiedReqImpl = (SipServletRequestImpl) copiedReq;

        // lets add non system headers
        if ((clonedHeaderMap != null) && !clonedHeaderMap.isEmpty()) {
            Iterator<String> names = clonedHeaderMap.keySet().iterator();
            Iterator<List<String>> values = clonedHeaderMap.values().iterator();

            while (names.hasNext()) {
                setHeader(names.next(), values.next(), copiedReqImpl);
            }
        }

        if (route != null) {
            MultiLineHeader rHdr = new MultiLineHeader(Header.ROUTE, true);
            for (String s: route) {
                rHdr.setValue(s, false);
            }
            copiedReqImpl.setHeader(rHdr);
        } else {
            Header rt = origRequestImpl.getRawHeader(Header.ROUTE);

            if (rt != null) {
                copiedReqImpl.setHeader((Header) rt.clone());
            }
        }

        if (contact != null) {
            if (origRequest.getMethod().equals("REGISTER")) {
                copiedReqImpl.setHeader("Contact", contact.iterator().next());
            } else { // change only parameters and user part of the URI

                try {
                    Address cnctAddr = new AddressImpl(contact.iterator().next());
                    Address contactAddr = copiedReqImpl.getAddressHeaderImpl(
                            "Contact");

                    if (contactAddr != null && !contactAddr.isWildcard()) {
                        ((AddressImpl) contactAddr).modifyContactParameters(cnctAddr);
                    }
                } catch (ServletParseException ex) {
                    if (_log.isLoggable(Level.FINE)) {
                        _log.log(Level.FINE,
                            " Exception while parsing Contact address ", ex);
                    }
                }
            }
        }


        if (linkedSessions) {
            SipSession session1 = origRequest.getSession();
            SipSession session2 = copiedReq.getSession();

            if ((session1 == null) || (session2 == null)) {
                throw new NullPointerException();
            }

            // are sessions consistent?
            if ((isValidSessions((SipSessionBase) session1,
                        (SipSessionBase) session2) &&
                    (origRequest.getApplicationSession(false) != null) &&
                    session1.getApplicationSession()
                                .equals(origRequest.getApplicationSession())) == false) {
                throw new IllegalArgumentException();
            }

             // always link requests...
            if (isAlreadyLinked(origRequestImpl)) {
                throw new IllegalArgumentException();
            }
      
            if (!isAlreadyLinkedToEachOther((SipSessionBase) session1,
                        (SipSessionBase) session2)) {
                // sessions are not linked to each other...
                if (!isNotLinkedToAnyone((SipSessionBase) session1,
                            (SipSessionBase) session2)) {
                    // ...but one session is linked somewhere else.
                    throw new IllegalArgumentException();
                }

                // lets link sessions.
                linkSipSessions((SipSessionBase) session1,
                    (SipSessionBase) session2);
            }
            // requests are not linked, lets link them...
            linkRequests(origRequestImpl, copiedReqImpl);
        }
       
        copiedReqImpl.setB2buaHelper(this);
       
        return copiedReq;
    }

    public synchronized SipServletRequest createRequest(SipSession session2,
        SipServletRequest origRequest, Map<String, List<String>> headerMap)
        throws IllegalArgumentException {
        if ((origRequest == null)) {
            throw new NullPointerException();
        }

        if (isAlreadyLinked((SipServletRequestImpl) origRequest)) {
            throw new IllegalArgumentException();
        }

        SipSession session1 = origRequest.getSession();

        if ((session1 == null) || (session2 == null)) {
            throw new NullPointerException();
        }

        // are sessions consistent?
        if (isValidSessions((SipSessionBase) session1, (SipSessionBase) session2) &&
                (origRequest.getApplicationSession(false) != null) &&
                (session1.getApplicationSession()
                             .equals(origRequest.getApplicationSession()) == false)) {
            throw new IllegalArgumentException();
        }

        // headerMap can only contain TO, FROM or CONTACT system headers.
        if ((headerMap != null) && !headerMap.isEmpty()) {
            Map<String, List<String>> clonedHeaderMap = new HashMap<String, List<String>>(headerMap);
            clonedHeaderMap.remove(Header.FROM);
            clonedHeaderMap.remove(Header.TO);
            clonedHeaderMap.remove(Header.CONTACT);

            if (!clonedHeaderMap.isEmpty()) {
                // are there any illegal system headers to add?
                if (isSystemHeader(clonedHeaderMap.keySet(),
                            (SipServletRequestImpl) origRequest, false)) {
                    // not allowed to add system headers other than from, to and contact...
                    throw new IllegalArgumentException();
                }
            }
        }

        boolean shouldLinkSessions = false;

        if (!isAlreadyLinkedToEachOther((SipSessionBase) session1,
                    (SipSessionBase) session2)) {
            // sessions are not linked to each other...
            if (!isNotLinkedToAnyone((SipSessionBase) session1,
                        (SipSessionBase) session2)) {
                // ...but one session is linked somewhere else.
                throw new IllegalArgumentException();
            }

            // ...lets link them later.
            shouldLinkSessions = true;
        }

        SipServletRequest newRequest = session2.createRequest(origRequest.getMethod());

        // set Routing directive to CONTINUE (will also copy the stateInfo)
        // only in case of initial requests (JSR289)
        if (origRequest.isInitial()) {
            // set implicit routing directive (will be overridden by app if it feels like it
            ((SipServletRequestImpl) newRequest).setInternalRoutingDirective(SipApplicationRoutingDirective.CONTINUE,
                origRequest);
            ((SipServletRequestImpl) newRequest).setRegion(origRequest.getRegion());
        }

        // lets add non system headers
        if ((headerMap != null) && !headerMap.isEmpty()) {
            Iterator<String> names = headerMap.keySet().iterator();
            Iterator<List<String>> values = headerMap.values().iterator();

            while (names.hasNext()) {
                setHeader(names.next(), values.next(),
                    (SipServletRequestImpl) newRequest);
            }
        }

        if (shouldLinkSessions) {
            // lets link sessions.
            linkSipSessions((SipSessionBase) session1, (SipSessionBase) session2);
        }

        // requests are not linked, lets link them...
        linkRequests((SipServletRequestImpl) origRequest,
            (SipServletRequestImpl) newRequest);
        ((SipServletRequestImpl) newRequest).setB2buaHelper(this);

        return newRequest;
    }

    public SipServletRequest createRequest(SipServletRequest origRequest) {
        if (origRequest == null) {
            throw new NullPointerException();
        }

        if (!origRequest.isInitial()) {
            throw new IllegalStateException();
        }

        SipServletRequestImpl origRequestImpl = (SipServletRequestImpl) origRequest;

        SipFactoryFacade sfImpl = (SipFactoryFacade) _sf;
        SipApplicationSessionImpl sappSessImpl = (SipApplicationSessionImpl) origRequest.getApplicationSession();
        SipServletRequestImpl copiedReq = null;
        copiedReq = sfImpl.createRequestImpl(sappSessImpl,
                origRequestImpl.getMethod(), origRequestImpl.getFromImpl(),
                origRequestImpl.getToImpl(), false, origRequestImpl);

        if (origRequest.getMethod().equals("REGISTER")) {
            Header cnct = origRequestImpl.getRawHeader(Header.CONTACT);

            if (cnct != null) {
                copiedReq.setHeader((Header) cnct.clone());
            }
        }

        return copiedReq;
    }

    public SipServletRequest createCancel(SipSession session) {
        if (session == null)
            throw new NullPointerException("SipSession Argument is null");
        DialogSet ds = ((SipSessionImplBase) session).getDS();

        if (ds != null) {
            DialogFragment df = ds.getInitialDialogFragment();

            if (df != null) {
                PathNode pn = df.getFirst();

                if (pn instanceof UA) {
                    INVITESession inviteFSM = UA.class.cast(pn).getInviteFSM();
                    SipServletRequestImpl invite = inviteFSM.getOrigRequestImpl();

                    if (invite != null) {
                        return invite.createCancel();
                    }
                }
            }
        }

        throw new IllegalStateException(localStrings.getLocalString(
                "cannot_create_cancel", "Cannot create CANCEL for this session"));
    }

    private void setHeader(String name, List<String> values,
        SipServletRequestImpl req1) throws IllegalArgumentException {
        if (Header.isSingleLineHeader(name) && (values.size() > 1)) {
            throw new IllegalArgumentException("Header " + name +
                " should be a singel line header.");
        }

        Header header = Header.createFormatted(name, req1);
        boolean isFirst = true;

        for (String value : values) {
            header.setValue(value, isFirst);
            isFirst = false;
        }

        // since the initial request can add new from and to header,
        // and also modify Contact header,
        // make sure they have proper address format...
        if ((Header.FROM.equalsIgnoreCase(name) ||
                Header.TO.equalsIgnoreCase(name)) ||
                Header.CONTACT.equalsIgnoreCase(name)) {
            try {
                header.getAddressValue();
            } catch (ServletParseException e) {
                throw new IllegalArgumentException("Header " + name +
                    " is not valid.", e);
            }
        }

        req1.setHeader(header);
    }

    private boolean isSystemHeader(Set<String> headers,
        SipServletMessageImpl message, boolean isInitial) {
        for (String name : headers) {
            // it's allowed to change From and To header of initial request
            if (!(isInitial &&
                    (Header.FROM.equalsIgnoreCase(name) ||
                    Header.TO.equalsIgnoreCase(name)))) {
                if (Header.isSystemHeader(Header.format(name), message)) {
                    return true;
                }
            }
        }

        return false;
    }

    private boolean isAlreadyLinked(SipServletRequestImpl req1) {
        return req1.getLinkedRequest() != null;
    }

    private void linkRequests(SipServletRequestImpl origReq,
        SipServletRequestImpl linkedReq) {
        origReq.setLinkedRequest(linkedReq);
        linkedReq.setLinkedRequest(origReq);       
    }

    private void updateTransactionStack(SipServletResponseImpl resp) {
        // need to update transaction path since there are new nodes.
        // lets start by cleaning the top of the stack...
        PathNode p = null;
        Iterator<PathNode> i = resp.getDialog().getCaller2CalleePath();

        if (i.hasNext()) {
            // skip this since it is the uas, which is not on the stack
            i.next();
        }

        while (i.hasNext()) {
            resp.popDispatcher();
        }

        // ...and replace it with the new nodes.
        i = resp.getDialog().getCaller2CalleePath();

        if (i.hasNext()) {
            // skip this since it is the uas, which is not on the stack
            i.next();
        }

        while (i.hasNext()) {
            // add the rest of the nodes..
            p = i.next();
            resp.pushTransactionDispatcher(p);
        }
    }

    public synchronized SipServletResponse createResponseToOriginalRequest(
        SipSession session, int status, String reasonPhrase) {
        return createResponseToOriginalRequest((SipSessionBase) session,
            status, reasonPhrase);
    }

    private SipServletResponse createResponseToOriginalRequest(
        SipSessionBase session2, int status, String reasonPhrase) {
        // 1. create response with original request
        // 2. verify that only final response 200OK has been created before
        // otherwise throw IllegalStateException: included in createResponse
        if (_originalRequest == null) {
            throw new IllegalStateException(
                "Only allowed to create response to original request.");
        }

        if (!session2.isValid())
            throw new IllegalArgumentException("Session is invalid");

        SipSessionBase session = null;

        TempSession tempSession = null;

        // some trix to make jsr289 12.5.1 Cloning and Linking working.
        // see also getLinkedSession()
        if (session2 instanceof TempSession) {
            if (_log.isLoggable(Level.FINE)) {
                _log.log(Level.FINE, "Convert FacadeSession -> session");
            }

            tempSession = (TempSession) session2;
            session = tempSession.getDerivedUACSessionToLink();
        } else {
            session = session2;
        }

        SipServletResponseImpl resp = null;

        if (session.isDerived()) {
            // maybe it's a subsequent response or retransmission
            // and hence sessions might already be linked
            SipSessionBase linkedSession = (SipSessionBase) getLinkedSession(session,
                    false);

            if (linkedSession != null) {
                DialogFragment dialog = _originalRequest.getDialog()
                                                        .getDialogSet()
                                                        .searchForDialog(linkedSession.getToTag(),
                        linkedSession.getFragmentId());

                if (dialog != null) {
                    // make a copy of the original request, can't change the original
                    SipServletRequestImpl clone = (SipServletRequestImpl) _originalRequest.clone();

                    // adjust the clone, needed because of new fragmentId,
                    // which changes contact
                    clone.setDialog(dialog);
                   
                    resp = (SipServletResponseImpl) clone.createResponse(status,
                            reasonPhrase);

                    // point back again...
                    resp.setRequest(_originalRequest);

                    resp.setSession((SipSessionBase) linkedSession);

                    updateTransactionStack(resp);

                    if (_log.isLoggable(Level.FINE)) {
                        _log.log(Level.FINE,
                            "Session is derivied and linked, uac session = " +
                            session + ", uas session = " + linkedSession +
                            " , linked dialog =" + dialog + ", " + resp);
                    }
                } else {
                    throw new IllegalStateException(
                        "Derived session is already linked but dialog is not established.");
                }
            } else {
                // need to create a new structure (dialog, etc.)
                // of the derived linked session

                // fetch the original uas
                PathNode uas = _originalRequest.getDialog().getLast();

                // clone only until uas, i.e. exclude it
                DialogFragment d = _originalRequest.getDialog()
                                                   .cloneFromCallerToCalleeUntil(uas,
                        true);

                // create the new uas replacing the original
                uas = new UA(_originalRequest.getApplicationSessionImpl(), false);

                // lets add the current uas to the application & transaction path
                d.addToPath(uas);

                // make a copy of the original request, can't change the original
                SipServletRequestImpl clone = (SipServletRequestImpl) _originalRequest.clone();
               
                // adjust the clone, needed because of new fragmentId,
                // which changes contact
                clone.setDialog(d);

                // create response
                resp = (SipServletResponseImpl) clone.createResponse(status,
                        reasonPhrase);

                // point back again...
                resp.setRequest(_originalRequest);

                // need to update transaction stack
                updateTransactionStack(resp);

                // save session in response.
                // It will later be linked to new derived session.
                //
                // It is also used as signal of b2buaHelper usage.
                if (tempSession != null) {
                    resp.setB2buaHelperTempSession(tempSession);
                }

                if (_log.isLoggable(Level.FINE)) {
                    _log.log(Level.FINE,
                        "Session is derivied but not linked, uac session = " +
                        session + ", uas session = " + linkedSession +
                        " , linked dialog =" + d + ", " + resp);
                }
            }
        } else {
            resp = (SipServletResponseImpl) _originalRequest.createResponse(status,
                    reasonPhrase);

            if (!isAlreadyLinkedToEachOther(session,
                        _originalRequest.getSessionImpl())) {
                // lets link the sessions...
                linkSipSessions(session, _originalRequest.getSessionImpl());

                if (_log.isLoggable(Level.FINE)) {
                    _log.log(Level.FINE,
                        "Session is original and was not linked, uac session = " +
                        session + ", uas session = " +
                        _originalRequest.getSessionImpl() +
                        " , linked dialog =" + _originalRequest.getDialog() +
                        ", " + resp);
                }
            } else {
                if (_log.isLoggable(Level.FINE)) {
                    _log.log(Level.FINE,
                        "Session is original and already linked, uac session = " +
                        session + ", uas session = " +
                        _originalRequest.getSessionImpl() +
                        " , linked dialog =" + _originalRequest.getDialog() +
                        ", " + resp);
                }
            }
        }

        return resp;
    }

    public synchronized SipSession getLinkedSession(SipSession session) {
        if (!session.isValid())
            throw new IllegalArgumentException(" Session is not valid ");
        return getLinkedSession((SipSessionBase) session, true);
    }

    /**
     * Special handling to support jsr289 12.5.1 Cloning and Linking. Furnish the
     * UAS-2 (a clone of UAS-1) when the getLinkedSipSession is invoked with
     * UAC-2 according to jsr289. Since lazy creation of sessions are enabled
     * only a wrapper session (FacadeSession) is returned. It will later be
     * replaced by the correct one.
     *
     * @param session
     * @param enableFacade -
     *           enables jsr289 12.5.1 Cloning and Linking
     * @return
     */
    private SipSession getLinkedSession(SipSessionBase session,
        boolean enableFacade) {
        SipApplicationSession app = session.getApplicationSession();
        SipSessionBase sb = (SipSessionBase) session;
        String id = sb.getLinkedSipSessionId();

        if (enableFacade && (id == null) && sb.isDerived()) {
            // jsr289 support 12.5.1 Cloning and Linking.
            // lazy creation is enforced, lets return a dummy wrapper...
            // NOTE: TempSession wrappes UAC session, not UAS session
            return new TempSession(sb);
        }

        return (id != null)
        ? ((SipApplicationSessionImpl) app).getSipSession(id) : null;
    }

    public SipServletRequest getLinkedSipServletRequest(SipServletRequest req) {
        return getLinkedSipServletRequest((SipServletRequestImpl) req);
    }

    private synchronized SipServletRequestImpl getLinkedSipServletRequest(
        SipServletRequestImpl req1) {
        SipServletRequestImpl req2 = req1.getLinkedRequest();

        if (req2 != null) {
            SipSession session1 = req1.getSession();
            SipSession session2 = req2.getSession();

            if (!isAlreadyLinkedToEachOther((SipSessionBase) session1,
                        (SipSessionBase) session2)) {
                // since the sessions are not linked to each other,
                // the request can't be linked either...
                req2 = null;
            }
        }

        return req2;
    }

    public List<SipServletMessage> getPendingMessages(SipSession session,
        UAMode mode) {
        if (!session.isValid())
            throw new IllegalArgumentException("Session is not valid");
        return ((SipSessionBase) session).getPendingMessages(mode);
    }

    private boolean isValidSessions(SipSessionBase session1,
        SipSessionBase session2) {
        return (session1.isValid() && session2.isValid()) &&
        (session1.getApplicationSession().getId()
                 .equals(session2.getApplicationSession().getId()));
    }

    private boolean isNotLinkedToAnyone(SipSessionBase session1,
        SipSessionBase session2) {
        return (session1.getLinkedSipSessionId() == null) &&
        (session2.getLinkedSipSessionId() == null);
    }

    private boolean isAlreadyLinkedToEachOther(SipSessionBase session1,
        SipSessionBase session2) {
        return session1.equals(session2) ||
        (((session1.getLinkedSipSessionId() != null) &&
        (session2.getLinkedSipSessionId() != null)) &&
        ((session1.getLinkedSipSessionId().equals(session2.getId())) &&
        (session2.getLinkedSipSessionId().equals(session1.getId()))));
    }

    public synchronized void linkSipSessions(SipSession session1,
        SipSession session2) {
        if ((session1 == null) || (session2 == null)) {
            throw new NullPointerException();
        }
       
        if (isTerminated(session1) || isTerminated(session2)) {
            throw new IllegalArgumentException();
        }

        // silently ignore if already linked
        if (!isAlreadyLinkedToEachOther((SipSessionBase) session1,
                    (SipSessionBase) session2)) {
            if ((!isValidSessions((SipSessionBase) session1,
                        (SipSessionBase) session2)) ||
                    !isNotLinkedToAnyone((SipSessionBase) session1,
                        (SipSessionBase) session2)) {
                throw new IllegalArgumentException();
            }

            linkSipSessions((SipSessionBase) session1, (SipSessionBase) session2);
        }
    }

    private void linkSipSessions(SipSessionBase session1,
        SipSessionBase session2) {
        if (_log.isLoggable(Level.FINE)) {
            _log.log(Level.FINE,
                "linkSipSessions(" + session1.getId() + "," + session2.getId() +
                ")");
        }

        session1.setLinkedSipSessionId(session2.getId());
        session2.setLinkedSipSessionId(session1.getId());
    }
   
    private boolean isTerminated(SipSession sess) {
        return sess.getState() == SipSession.State.TERMINATED;
    }

    public synchronized void unlinkSipSessions(SipSession session1) {
        SipSession session2 = getLinkedSession((SipSessionBase) session1, false);

        if ((session2 == null) || isTerminated(session1) ) {
            throw new IllegalArgumentException();
        }

        unlinkSipSessions((SipSessionBase) session1, (SipSessionBase) session2);
       
        // Also unlink requests
        if (this._originalRequest != null && this._originalRequest.getLinkedRequest() != null) {
          this._originalRequest.getLinkedRequest().setLinkedRequest(null);
          this._originalRequest.setLinkedRequest(null);
        }
    }

    private void unlinkSipSessions(SipSessionBase session1,
        SipSessionBase session2) {
        session1.setLinkedSipSessionId(null);
        session2.setLinkedSipSessionId(null);
    }

    /**
     * Only a dummy wrapper for B2buaHelper support 12.5.1 Cloning and Linking
     * Support saving attributes and will be replaced by a real sip session after
     * send of message.
     *
     * @author ehsroha
     * @since 2007-apr-01
     *
     */
    class TempSession implements SipSessionBase {
        private static final long serialVersionUID = -5845365964095917542L;
        private ConcurrentHashMap<String, Object> _sessionAttributeMap = new ConcurrentHashMap<String, Object>();
        private final SipSessionBase _session;

        private TempSession(SipSessionBase derivedUACSessionToLink) {
            _session = derivedUACSessionToLink;
        }

        /**
         * Method MUST be kept as is.
         * Call this method when finally the derived UAC session should be
         * linked with the derived UAS session (which is not jet created).
         * @return
         */
        SipSessionBase getDerivedUACSessionToLink() {
            return _session;
        }

        public long getCreationTime() {
            return 0;
        }

        public String getId() {
            return "";
        }

        public long getLastAccessedTime() {
            return 0;
        }

        public void invalidate() {
        }

        public boolean isReadyToInvalidate() {
            return false;
        }

        public void setInvalidateWhenReady(boolean invalidateWhenReady) {
            throw new RuntimeException(" Not yet implemented ");
        }

        public boolean getInvalidateWhenReady() {
            return false;
        }

        public void setOutboundInterface(InetAddress address) {
        }

        public void setOutboundInterface(InetSocketAddress address) {
        }

        public void addPendingMessage(SipServletMessageImpl m, UAMode mode) {
    }

    public void createPendingMessageHelper() {
    }

        public SipSessionInterface.State getState() {
            throw new RuntimeException(" Not yet implemented ");
        }

        public SipApplicationSession getApplicationSession() {
            return null;
        }

        public String getCallId() {
            return "";
        }

        public Address getLocalParty() {
            return null;
        }

        public Address getRemoteParty() {
            return null;
        }

        public SipServletRequest createRequest(String method) {
            return null;
        }

        public void setHandler(String name) throws ServletException {
        }

        public Object getAttribute(String name) {
            return _sessionAttributeMap.get(name);
        }

        public void access() {
        }

        public Enumeration<String> getAttributeNames() {
            // Since Map doesn't have Enumeration as interface need to convert via
            // private class EnumerationConverter.
            synchronized (_sessionAttributeMap) {
                return new EnumerationConverter<String>(_sessionAttributeMap.keySet());
            }
        }

        public void setAttribute(String name, Object attribute) {
            if (name.equals(SipFactoryImpl.REMOTE_TARGET)) {
                throw new IllegalStateException("reserved key.");
            }

            _sessionAttributeMap.put(name, attribute);
        }

        public void removeAttribute(String name) {
            _sessionAttributeMap.remove(name);
        }

        public SipApplicationRoutingRegion getRegion() {
            return SipApplicationRoutingRegion.TERMINATING_REGION; // correct?
        }

        public URI getSubscriberURI() throws IllegalStateException {
            return null;
        }

        public ServletContext getServletContext() {
            return null;
        }

        public boolean isValid() {
            return true;
        }

        public SipApplicationSessionImpl getApplicationSessionImpl() {
            return null;
        }

        public String getFragmentId() {
            return null;
        }

        public String getFromTag() {
            return "";
        }

        public String getHandler() {
            return "";
        }

        public String getLinkedSipSessionId() {
            return "";
        }

        public SipSessionBase getOriginalOrDerivedSessionAndRegisterDialog(
            SipServletRequestImpl req, DialogFragment d) {
            return null;
        }

        public SipSessionBase getOriginalOrDerivedSessionAndRegisterDialog(
            SipServletResponseImpl resp, DialogFragment d) {
            return null;
        }

        public URI getRemoteTarget() {
            return null;
        }

        public Address getTo() {
            return null;
        }

        public String getToTag() {
            return "";
        }

        public boolean hasNoToTag() {
            return false;
        }

        public void invalidate(boolean hasTimedOut) {
        }

        public boolean is1xxReliableOngoing() {
            return false;
        }

        public boolean is1xxReliableSDP() {
            return false;
        }

        public boolean isDerived() {
            return true;
        }

        public void reset1xxReliable() {
        }

        public void resetUpdateOngoing() {
        }

        public boolean set1xxReliableOngoing(boolean sdp) {
            return false;
        }

        public void setLinkedSipSessionId(String id) {
        }

        public void setRegion(SipApplicationRoutingRegion region) {
        }

        public void setRemoteTarget(URI contact) {
        }

        public void setSubscriberURI(URI subscriberURI) {
        }

        public void setType(Type type) {
        }

        public boolean setUpdateOngoing() {
            return false;
        }

        public boolean isReplicable() {
            return false;
        }

        public List<SipServletMessage> getPendingMessages(UAMode mode) {
            return null;
        }

        public void setShouldBePersisted() {
        }

        public void updateSipSessionState(SipServletRequest req, Type type) {
        }

        public void updateSipSessionState(SipServletResponse resp, Type type) {
        }

        public int getCSeq() {
            return 1;
        }
    public boolean isB2buaHelper() {
      return true;
    }
    }
}
TOP

Related Classes of com.ericsson.ssa.sip.B2buaHelperImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.