Package com.ericsson.ssa.container

Source Code of com.ericsson.ssa.container.NetworkManager

/*
* 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.container;

import com.ericsson.ssa.config.annotations.Configuration;
import com.ericsson.ssa.config.annotations.UpdatePolicy;
import com.ericsson.ssa.config.annotations.UsagePolicy;
import com.ericsson.ssa.sip.Header;
import java.util.Collections;
import java.util.HashSet;
import java.util.ListIterator;
import java.util.Set;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.ericsson.ssa.sip.Layer;
import com.ericsson.ssa.sip.LayerHelper;
import com.ericsson.ssa.sip.SipServletRequestImpl;
import com.ericsson.ssa.sip.SipServletResponseImpl;
import com.ericsson.ssa.sip.ViaHeaderValidator;
import com.ericsson.ssa.sip.ViaImpl;
import com.ericsson.ssa.sip.dns.TargetResolver;
import com.ericsson.ssa.sip.dns.TargetTuple;

import java.util.concurrent.atomic.AtomicLong;
import com.ericsson.ssa.container.reporter.Reporter;
import com.ericsson.ssa.container.reporter.ReporterResolver;

import java.util.logging.Level;
import org.jvnet.glassfish.comms.util.LogUtil;
import java.util.logging.Logger;


public abstract class NetworkManager implements Layer {
    private static NetworkManager instance = null;
   
    private static final String GRIZZLY_ENABLE_PROPERTY = "sip.network.grizzly";
   
    private AtomicLong _EasInvalidSipMessages = new AtomicLong();
    private AtomicLong _EasReceivedSipRequests = new AtomicLong();
    private AtomicLong _EasReceivedSipResponses = new AtomicLong();
    private AtomicLong _EasSentSipRequests = new AtomicLong();
    private AtomicLong _EasSentSipResponses = new AtomicLong();
    private AtomicLong _Eas420Responses = new AtomicLong();

    private Map<String,AtomicLong> reqInMap;
    private Map<String,AtomicLong> reqOutMap;
    private Map<String,AtomicLong> respInMap;
    private Map<String,AtomicLong> respOutMap;
  
    private Map<String,AtomicLong>  _EasInvalidSipMessagesPerListener;
    private Map<String,AtomicLong>  _EasReceivedSipRequestsPerListener;
    private Map<String,AtomicLong>  _EasReceivedSipResponsesPerListener;
    private Map<String,AtomicLong>  _EasSentSipRequestsPerListener;
    private Map<String,AtomicLong>  _EasSentSipResponsesPerListener;

    private Map<String, String> _listenerTupleMap;

    private Map<String, String> _listenerAddressMap;
    private Reporter _reporter;
   
    public void setReporters(String reporters){
        _reporter = ReporterResolver.getInstance().getReporter(reporters);
    }
   
    public Reporter getReporter(){
        return _reporter;
    }

    private void initStatsCounters() {
        _EasInvalidSipMessagesPerListener = new ConcurrentHashMap<String, AtomicLong>(3);
        _EasReceivedSipRequestsPerListener = new ConcurrentHashMap<String, AtomicLong>(3);
        _EasReceivedSipResponsesPerListener = new ConcurrentHashMap<String, AtomicLong>(3);
        _EasSentSipRequestsPerListener = new ConcurrentHashMap<String, AtomicLong>(3);
        _EasSentSipResponsesPerListener = new ConcurrentHashMap<String, AtomicLong>(3);
        _listenerTupleMap = new ConcurrentHashMap<String, String>(3);
        _listenerAddressMap = new ConcurrentHashMap<String, String>(3);
    }

    protected void registerForMonitoring(String ctx, TargetTuple tt) {
        if (ctx == null || tt == null) {
            return;
        }
        String simpletuple = normalizeTT(tt.getIP(), tt.getPort());
        _listenerTupleMap.put(ctx, simpletuple);
        _EasInvalidSipMessagesPerListener.put(simpletuple, new AtomicLong(0));
        _EasReceivedSipRequestsPerListener.put(simpletuple, new AtomicLong(0));
        _EasReceivedSipResponsesPerListener.put(simpletuple, new AtomicLong(0));
        _EasSentSipRequestsPerListener.put(simpletuple, new AtomicLong(0));
        _EasSentSipResponsesPerListener.put(simpletuple, new AtomicLong(0));
        // only the last listener for that IP will be stored here
        _listenerAddressMap.put(tt.getIP(), simpletuple);
    }

    protected String normalizeTT(String host , int port){
        if (port == -1) {
            return _listenerAddressMap.get(host);
        }else {
            return host + ":" + port;
        }
    }

    private Logger log = LogUtil.SIP_LOGGER.getLogger();
    private int _SipLinkTimeout = 10; // ms
    private int _SipLinkTimeoutRetries = 25; // iterations
    private int _SipLinkMaxQueueLen = 50;
    private int _SipLinkWaitLockTimeout = 5000;
    private long _SipLinkAliveTimeout = 120;
    private boolean _errorResponseEnabled = false;  

    private Set<String> additionalHeaders = Collections.emptySet();
    public abstract void next(SipServletRequestImpl req);

    public abstract void next(SipServletResponseImpl resp);

    public abstract void registerNext(Layer layer);

    public abstract void dispatch(SipServletRequestImpl req);

    public abstract void dispatch(SipServletResponseImpl resp);
   
    public abstract Set<TargetTuple> getConnectionView();

    public synchronized static NetworkManager getInstance() {
        if (instance == null) {
            //TODO remove in final version so only one Network manager is present
            String grizzlyEnabledPropertyValue = System.getProperty(GRIZZLY_ENABLE_PROPERTY);
            if (grizzlyEnabledPropertyValue != null &&
                    !Boolean.parseBoolean(grizzlyEnabledPropertyValue)) {
                instance = new OLDNetworkManager();               
            } else {
                instance = new GrizzlyNetworkManager();
            }
            instance.initMethodCounters();
            instance.initStatsCounters();
        }

        return instance;
    }

    public boolean isRunning() {
        return true;
    }
   
        // package access
    void incrEasInvalidSipMessages() {
        _EasInvalidSipMessages.incrementAndGet();
    }

    void incrEasReceivedSipRequests() {
        _EasReceivedSipRequests.incrementAndGet();
    }

    void incrEasReceivedSipResponses() {
        _EasReceivedSipResponses.incrementAndGet();
    }

    void incrEasSentSipRequests() {
        _EasSentSipRequests.incrementAndGet();
    }

    void incrEasSentSipResponses() {
        _EasSentSipResponses.incrementAndGet();
    }

    public long getEasInvalidSipMessages() {
        return _EasInvalidSipMessages.longValue();
    }

    public long getEasReceivedSipRequests() {
        return _EasReceivedSipRequests.longValue();
    }

    public long getEasReceivedSipResponses() {
        return _EasReceivedSipResponses.longValue();
    }

    public long getEasSentSipRequests() {
        return _EasSentSipRequests.longValue();
    }

    public long getEasSentSipResponses() {
        return _EasSentSipResponses.longValue();
    }

    public long getEas420ResOutSipMessages(){
  return _Eas420Responses.longValue()
    }

    void incrSipMessageCount(Map<String, AtomicLong> msgmap, String host, int port) {
        String tt = normalizeTT(host, port);
        /* If tt is null then we are using
         * an IP that is not configured as a listener. If 0.0.0.0 is used
         * as the listener address then listener specific monitoring
         * values will not be available.
         */
        if (tt != null) {
            AtomicLong l = msgmap.get(tt);
            if (l != null) {
                l.incrementAndGet();
            }
        }
    }   
   
    void incrEasInvalidSipMessages(String host, int port) {
        incrEasInvalidSipMessages();       
        incrSipMessageCount (_EasInvalidSipMessagesPerListener, host, port);
      
    }

    void incrEasReceivedSipRequests(String host, int port) {
        incrEasReceivedSipRequests();
        incrSipMessageCount(_EasReceivedSipRequestsPerListener, host, port);
    }

    void incrEasReceivedSipResponses(String host, int port) {
        incrEasReceivedSipResponses();
        incrSipMessageCount(_EasReceivedSipResponsesPerListener, host, port);
    }

    void incrEasSentSipRequests(String host, int port) {
        incrEasSentSipRequests();
        incrSipMessageCount(_EasSentSipRequestsPerListener, host, port);
    }

    void incrEasSentSipResponses(String host, int port) {
        incrEasSentSipResponses();
        incrSipMessageCount(_EasSentSipResponsesPerListener, host, port);
    }

    public long getEasInvalidSipMessages(String id) {
        return _EasInvalidSipMessagesPerListener.get(_listenerTupleMap.get(id)).longValue();
    }

    public long getEasReceivedSipRequests(String id) {
        return _EasReceivedSipRequestsPerListener.get(_listenerTupleMap.get(id)).longValue();
    }

    public long getEasReceivedSipResponses(String id) {
        return _EasReceivedSipResponsesPerListener.get(_listenerTupleMap.get(id)).longValue();
    }

    public long getEasSentSipRequests(String id) {
        return _EasSentSipRequestsPerListener.get(_listenerTupleMap.get(id)).longValue();
    }

    public long getEasSentSipResponses(String id) {
        return _EasSentSipResponsesPerListener.get(_listenerTupleMap.get(id)).longValue();
    }
    void initMethodCounters() {
        reqInMap = new ConcurrentHashMap<String,AtomicLong>(14);
        reqOutMap = new ConcurrentHashMap<String,AtomicLong>(14);
        respInMap = new ConcurrentHashMap<String,AtomicLong>(6);
        respOutMap = new ConcurrentHashMap<String,AtomicLong>(6);
        reqInMap.put("INVITE",new AtomicLong(0));
        reqInMap.put("ACK",new AtomicLong(0));
        reqInMap.put("PRACK",new AtomicLong(0));
        reqInMap.put("BYE",new AtomicLong(0));
        reqInMap.put("CANCEL",new AtomicLong(0));
        reqInMap.put("SUBSCRIBE",new AtomicLong(0));
        reqInMap.put("NOTIFY",new AtomicLong(0));
        reqInMap.put("MESSAGE",new AtomicLong(0));
        reqInMap.put("REGISTER",new AtomicLong(0));
        reqInMap.put("OPTIONS",new AtomicLong(0));
        reqInMap.put("UPDATE",new AtomicLong(0));
        reqInMap.put("REFER",new AtomicLong(0));
        reqInMap.put("INFO",new AtomicLong(0));
        reqInMap.put("OTHER",new AtomicLong(0));
        reqInMap.put("PUBLISH",new AtomicLong(0));

        reqOutMap.put("INVITE",new AtomicLong(0));
        reqOutMap.put("ACK",new AtomicLong(0));
        reqOutMap.put("PRACK",new AtomicLong(0));
        reqOutMap.put("BYE",new AtomicLong(0));
        reqOutMap.put("CANCEL",new AtomicLong(0));
        reqOutMap.put("SUBSCRIBE",new AtomicLong(0));
        reqOutMap.put("NOTIFY",new AtomicLong(0));
        reqOutMap.put("MESSAGE",new AtomicLong(0));
        reqOutMap.put("REGISTER",new AtomicLong(0));
        reqOutMap.put("OPTIONS",new AtomicLong(0));
        reqOutMap.put("UPDATE",new AtomicLong(0));
        reqOutMap.put("REFER",new AtomicLong(0));
        reqOutMap.put("INFO",new AtomicLong(0));
        reqOutMap.put("OTHER",new AtomicLong(0));
        reqOutMap.put("PUBLISH",new AtomicLong(0));

        respInMap.put("1XX",new AtomicLong(0));
        respInMap.put("2XX",new AtomicLong(0));
        respInMap.put("3XX",new AtomicLong(0));
        respInMap.put("4XX",new AtomicLong(0));
        respInMap.put("5XX",new AtomicLong(0));
        respInMap.put("6XX",new AtomicLong(0));

        respOutMap.put("1XX",new AtomicLong(0));
        respOutMap.put("2XX",new AtomicLong(0));
        respOutMap.put("3XX",new AtomicLong(0));
        respOutMap.put("4XX",new AtomicLong(0));
        respOutMap.put("5XX",new AtomicLong(0));
        respOutMap.put("6XX",new AtomicLong(0));
    }
    public Map<String, AtomicLong> getReqInMethodCounters() {
        return new ConcurrentHashMap<String, AtomicLong>(reqInMap);
    }

    public Map<String, AtomicLong> getReqOutMethodCounters() {
        return new ConcurrentHashMap<String, AtomicLong>(reqOutMap);
    }

    public Map<String, AtomicLong> getRespInStatCodeCounters() {
        return new ConcurrentHashMap<String, AtomicLong>(respInMap);
    }

    public Map<String, AtomicLong> getRespOutStatCodeCounters() {
        return new ConcurrentHashMap<String, AtomicLong>(respOutMap);
    }

    void incrReqInMethodCounter(String method) {
        if (method == null || "".equals(method))
            return;
        String mthd  = method.toUpperCase();
        if (reqInMap.get(mthd) == null) {
            reqInMap.get("OTHER").incrementAndGet();
            return;
        }
        reqInMap.get(mthd).incrementAndGet();
    }

    void incrReqOutMethodCounter(String method) {
        if (method == null || "".equals(method))
            return;
        String mthd  = method.toUpperCase();
        if (reqOutMap.get(mthd) == null) {
            reqOutMap.get("OTHER").incrementAndGet();
            return;
        }
        reqOutMap.get(mthd).incrementAndGet();
    }

    void incrRespInStatCodeCounter(int code) {
        if (code < 100 || code > 699)
            return;
        int statCode = code / 100;
        switch (statCode) {
            case 1:
                respInMap.get("1XX").incrementAndGet();
                break;
            case 2:
                respInMap.get("2XX").incrementAndGet();
                break;
            case 3:
                respInMap.get("3XX").incrementAndGet();
                break;
            case 4:
                respInMap.get("4XX").incrementAndGet();
    if (code == 420){
        _Eas420Responses.incrementAndGet();
    }
                break;
            case 5:
                respInMap.get("5XX").incrementAndGet();
                break;
            case 6:
                respInMap.get("6XX").incrementAndGet();
                break;
        }
    }

    void incrRespOutStatCodeCounter(int code) {
        if (code < 100 || code > 699)
            return;
        int statCode = code / 100;
        switch (statCode) {
            case 1:
                respOutMap.get("1XX").incrementAndGet();
                break;
            case 2:
                respOutMap.get("2XX").incrementAndGet();
                break;
            case 3:
                respOutMap.get("3XX").incrementAndGet();
                break;
            case 4:
                respOutMap.get("4XX").incrementAndGet();
                break;
            case 5:
                respOutMap.get("5XX").incrementAndGet();
                break;
            case 6:
                respOutMap.get("6XX").incrementAndGet();
                break;
        }
    }
   
       /**
     * Defines timeout value in milliseconds for a single write operation of a
     * sip link.
     * </p>
     * Range: 1-50ms
     *
     * @param timeout
     */
    @Configuration (key="WriteTimeoutInMillis", node="/SipService/SipProtocol/SipLink")
    public void setSipLinkTimeout(int timeout) {
        if ((timeout > 0) && (timeout <= 50)) {
            _SipLinkTimeout = timeout;
        } else {
            if (log.isLoggable(Level.WARNING)) {
                log.log(Level.WARNING, "sip.stack.network.bad_sip_link_timeout", new Object[] { timeout });
            }            
        }
    }

    /**
     * Defines timeout value in milliseconds for a single write operation of a
     * sip link.
     *
     * @return timeout for write operation of a sip link
     */
    public int getSipLinkTimeout() {
        return _SipLinkTimeout;
    }

    /**
     * Defines timeout value in seconds for keeping an inactive link. If no
     * traffic has been generated on that link for that time period the link is
     * closed.
     *
     * @return timeout value in seconds for keeping an inactive link
     */
    public long getSipLinkAliveTimeout() {
        return _SipLinkAliveTimeout;
    }

       // this code should be refactored; the code should be moved to the Header class
    // and the header class should get a configuration hook (e.g., register itself for configuration).
    // Also the way it is used here the ExtraMultiLineHeaderNames is stuck to being a property and will not
    // be resolved if ever changed to a attribute. This might be OK.
    @Configuration (usage=UsagePolicy.IGNORE, key="ExtraMultiLineHeaderNames", node="/SipService/SipProtocol")
    public void addHeaders(String configuredHeaders) {
        HeaderSet additionalHeaderSet = new HeaderSet(configuredHeaders);
        Set<String> tempAdditionalHeaders = additionalHeaderSet.getSet();
       
        Set<String> newHeaders = new HashSet<String>(tempAdditionalHeaders);
        newHeaders.removeAll(this.additionalHeaders);
       
        Set<String> removedHeaders = new HashSet<String>(this.additionalHeaders);
        removedHeaders.removeAll(tempAdditionalHeaders);
       
        for (String header : removedHeaders) {
            Header.MULTI_LINE_HEADER_SET.remove(header);           
        }

        for (String header : newHeaders) {
            Header.MULTI_LINE_HEADER_SET.add(header);
        }
       
        this.additionalHeaders = tempAdditionalHeaders;
       
        if (log.isLoggable(Level.FINE)) {
            StringBuffer additionalHeadersString = new StringBuffer();
            additionalHeadersString.append("extra Multiline Headers: <");
            boolean first = true;
            for (String header : tempAdditionalHeaders) {
                if (first) {                   
                    first = false;
                } else {
                    additionalHeadersString.append(",");
                }
                additionalHeadersString.append(header);               
            }
            additionalHeadersString.append(">");
            log.fine(additionalHeadersString.toString());
        }
    }

    /**
     * Inner class to enable automatic conversion of
     * a comma seperated string of headernames to a set
     * of properly formatted names.
     *
     */
    public class HeaderSet {
        HashSet<String> headerSet = new HashSet<String>();
        public HeaderSet(String aCommaSeparatedHeaderSet) {
            String[] headers = aCommaSeparatedHeaderSet.split(",");
            for (int i = 0; i < headers.length; i++) {
                String header = headers[i].trim();
                if (!"".equals(header)) {
                    headerSet.add(Header.format(header));
                }
            }
        }
       
        public Set<String> getSet() {
            return headerSet;
        }
       
       
    }

    /**
     * Defines timeout value in seconds for keeping an inactive link. If no
     * traffic has been generated on that link for that time period the link is
     * closed.
     *
     * @param timeout
     *           value in seconds for keeping an inactive link
     */
    @Configuration (key="ConnectionAliveTimeoutInSeconds", node="/SipService/SipProtocol/SipLink")
    public void setSipLinkAliveTimeout(long timeout) {
        _SipLinkAliveTimeout = timeout;
    }

    /**
     * Defines the number of retries to perform of a single write operation of a
     * sip link.
     * </p>
     * Range: 1-25
     * </p>
     * The maximum time a link will try for success of a write operation is
     * defined by SipLinkTimeout * SipLinkTimeoutRetries milliseconds.
     *
     * @param retries
     */
    @Configuration (key="WriteTimeoutRetries", node="/SipService/SipProtocol/SipLink")
    public void setSipLinkTimeoutRetries(int retries) {
        if ((retries > 0) && (retries <= 25)) {
            _SipLinkTimeoutRetries = retries;
        } else {
            if (log.isLoggable(Level.WARNING)) {
                log.log(Level.WARNING, "sip.stack.network.bad_sip_link_timeout_retries", new Object[] { retries });
            }
        }

        _SipLinkTimeoutRetries = retries;
    }

    /**
     * Defines the number of retries to perform of a single write operation of a
     * sip link.
     * </p>
     * The maximum time a link will try for success of a write operation is
     * defined by SipLinkTimeout * SipLinkTimeoutRetries milliseconds.
     *
     * @return the number of retries to perform of a single write operation of a
     *         sip link.
     */
    public int getSipLinkTimeoutRetries() {
        return _SipLinkTimeoutRetries;
    }

    /**
     * Returns the maximum number of connect/write tasks that can be queued in a
     * link.
     *
     * @return the maximum number of connect/write tasks that can be queued in a
     *         link
     */
    public int getSipLinkMaxQueueLength() {
        return _SipLinkMaxQueueLen;
    }

    /**
     * Returns the maximum number of connect/write tasks that can be queued in a
     * link.
     *
     * @param length
     *           the maximum number of connect/write tasks that can be queued in
     *           a link
     */
    @Configuration (key="MaxQueueLength", node="/SipService/SipProtocol/SipLink")
    public void setSipLinkMaxQueueLength(int length) {
        _SipLinkMaxQueueLen = length;
    }

    /**
     * Returns the maximum time a thread will wait to get an exclusive lock for a
     * sip link.
     *
     * @return the maximum time a thread will wait to get an exclusive lock for a
     *         sip link.
     */
    public int getSipLinkWaitLockTimeout() {
        return _SipLinkWaitLockTimeout;
    }

    /**
     * Sets the maximum time a thread will wait to get an exclusive lock for a
     * sip link.
     *
     * @param timeout
     */
    @Configuration (key="SipLinkWaitLockTimeout", node="/SipService/SipProtocol/SipLink",
        usage=UsagePolicy.IGNORE, update=UpdatePolicy.STARTUP) //This was never before configurable!
    public void setSipLinkWaitLockTimeout(int timeout) {
        _SipLinkWaitLockTimeout = timeout;
    }
   
    /**
     * Returns whether a malformed request should be handled by sending a proper
     * informational error response.
     *
     * @return
     */
    public Boolean isErrorResponseEnabled() {
        return _errorResponseEnabled;
    }

    /**
     * Setter of the <code>ErrorResponseEnabled</code> property.
     *
     * @param responseEnabled
     */
    @Configuration (key="ErrorResponseEnabled", node="/SipService/SipProtocol")
    public void setErrorResponseEnabled(Boolean responseEnabled) {
        _errorResponseEnabled = responseEnabled;
    }   
   
   
  public SipServletResponseImpl validateAndModifyIncomingVia(SipServletRequestImpl req) {
    String vstr = req.getHeader(Header.VIA);
        if (vstr == null) {
          SipServletResponseImpl resp = req.createTerminatingResponse(400, "Missing via in request");
          return resp;
        }
       
        ViaImpl via = null;
       
        try {
          via = new ViaImpl(vstr);
        }
        catch(Throwable t){
          SipServletResponseImpl resp = req.createTerminatingResponse(400, "Via cannot be parsed");
          return resp;
        }
   
     
      String viaTransport = via.getTransport();           
      String remoteTransport = req.getRemote().getProtocol().name();
     
      if ( viaTransport!= null && remoteTransport != null && !viaTransport.equalsIgnoreCase(remoteTransport)) {
        SipServletResponseImpl resp = req.createTerminatingResponse(400, "Mismatch in VIA Transport");
        return resp;
      }
     
      TargetResolver.updateVia(req, via);
      return null;
  }
}
TOP

Related Classes of com.ericsson.ssa.container.NetworkManager

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.