<commit_before>/*
 *  Copyright (C) 2008 Pingtel Corp., certain elements licensed under a Contributor Agreement.
 *  Contributors retain copyright to elements licensed under a Contributor Agreement.
 *  Licensed to the User under the LGPL license.
 *
 */
package org.sipfoundry.sipxbridge.symmitron;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import javax.net.ssl.SSLServerSocket;

import net.java.stun4j.StunAddress;
import net.java.stun4j.client.NetworkConfigurationDiscoveryProcess;
import net.java.stun4j.client.StunDiscoveryReport;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.mortbay.http.HttpContext;
import org.mortbay.http.HttpListener;
import org.mortbay.http.HttpServer;
import org.mortbay.http.SocketListener;
import org.mortbay.http.SslListener;
import org.mortbay.jetty.servlet.ServletHandler;
import org.mortbay.util.InetAddrPort;
import org.mortbay.util.ThreadedServer;
import org.sipfoundry.commons.log4j.SipFoundryAppender;
import org.sipfoundry.commons.log4j.SipFoundryLayout;
import org.sipfoundry.sipxbridge.SipXbridgeException;

/**
 * The SIPXbridge XML RPC handler.
 * 
 * @author <NAME>
 * 
 */
@SuppressWarnings("unchecked")
public class SymmitronServer implements Symmitron {

    private static Logger logger = Logger.getLogger(SymmitronServer.class.getPackage().getName());

    protected static Timer timer = new Timer();

    private static String status;

    /*
     * Map that pairs the SymSession id with the SymSession
     */
    private static Map<String, Sym> sessionMap = new ConcurrentHashMap<String, Sym>();

    /*
     * Map that pairs the rtpSesion owner with the rtp session
     */
    private static Map<String, HashSet<Sym>> sessionResourceMap = new ConcurrentHashMap<String, HashSet<Sym>>();

    /*
     * A map that pairs the RtpBridge id with the rtp Bridge.
     */
    private static Map<String, Bridge> bridgeMap = new ConcurrentHashMap<String, Bridge>();

    /*
     * A map that pairs the owner with the RtpBridge
     */
    private static Map<String, HashSet<Bridge>> bridgeResourceMap = new ConcurrentHashMap<String, HashSet<Bridge>>();

    /*
     * A map of component name to instance handle.
     */
    private static Map<String, String> instanceTable = new ConcurrentHashMap<String, String>();

    private static PortRangeManager portRangeManager;

    /*
     * My Instance handle
     */
    private static String myHandle = "sipxbridge:" + Math.abs(new Random().nextLong());

    private static boolean isWebServerRunning;

    private static HttpServer webServer;

    private static InetAddress localAddressByName;

    private static InetAddress publicAddress;

    private static SymmitronConfig symmitronConfig;

    private static final int STUN_PORT = 3478;

    // /////////////////////////////////////////////////////////////

    /**
     * Discover our address using stun.
     * 
     * @throws SipXbridgeException
     */
    static void discoverAddress() throws Exception {
        try {

            String stunServerAddress = symmitronConfig.getStunServerAddress();

            if (stunServerAddress != null) {

                // Todo -- deal with the situation when this port may be taken.
                // The port may be taken by sipxbridge.
                StunAddress localStunAddress = new StunAddress(symmitronConfig.getLocalAddress(),
                        STUN_PORT + 1);

                StunAddress serverStunAddress = new StunAddress(stunServerAddress, STUN_PORT);

                NetworkConfigurationDiscoveryProcess addressDiscovery = new NetworkConfigurationDiscoveryProcess(
                        localStunAddress, serverStunAddress);
                java.util.logging.LogManager logManager = java.util.logging.LogManager
                        .getLogManager();
                java.util.logging.Logger log = logManager
                        .getLogger(NetworkConfigurationDiscoveryProcess.class.getName());
                log.setLevel(java.util.logging.Level.OFF);

                addressDiscovery.start();
                StunDiscoveryReport report = addressDiscovery.determineAddress();
                if (report == null) {
                    logger.error("No stun report - could not do address discovery");
                    return;
                }
                StunAddress stunAddress = report.getPublicAddress();
                if (stunAddress == null) {
                    logger.error("No stun address - could not do address discovery");
                    return;
                }

                publicAddress = stunAddress.getSocketAddress().getAddress();
                logger.debug("Stun report = " + report);
                String publicAddr = publicAddress.getHostAddress();
                logger.debug("publicAddress = " + publicAddr);
                symmitronConfig.setPublicAddress(publicAddr);

            }
        } catch (Exception ex) {

            logger.error("Error discovering  address -- could be networking is bad", ex);
            throw ex;
        }
    }

    private Map<String, Object> createErrorMap(int errorCode, String reason) {
        Map<String, Object> retval = new HashMap<String, Object>();
        retval.put(STATUS_CODE, ERROR);
        retval.put(ERROR_CODE, new Integer(errorCode).toString());
        retval.put(ERROR_INFO, reason);

        retval.put(INSTANCE_HANDLE, myHandle);

        return retval;
    }

    private Map<String, Object> createSuccessMap() {
        Map<String, Object> retval = new HashMap<String, Object>();
        retval.put(STATUS_CODE, OK);
        retval.put(INSTANCE_HANDLE, myHandle);
        return retval;
    }

    private void addSymResource(String controllerId, Sym sym) {
        sessionMap.put(sym.getId(), sym);
        HashSet<Sym> syms = sessionResourceMap.get(controllerId);
        if (syms != null) {
            syms.add(sym);
        } else {
            syms = new HashSet<Sym>();
            syms.add(sym);
            sessionResourceMap.put(controllerId, syms);
        }
    }
    
    private static InetAddress findIpAddress (String localAddress) throws UnknownHostException {
        
        String[] addressParts = localAddress.split(".");
        boolean isIpAddress = true;
        byte[] addressBytes = new byte[addressParts.length];
        int i = 0;
        for (String addressPart : addressParts  ) {
            try {
                addressBytes[i++] = (byte) Integer.parseInt(addressPart);         
            } catch (NumberFormatException ex) {
                isIpAddress = false;
                break;
            }
        }
        
        InetAddress retval;
        /*
         * User specified a host name -- see if we can resolve it.
         */
        if (!isIpAddress) {
             retval = InetAddress.getByName(localAddress);<commit_msg>XECS-2277 : NAT Traversal Configuration error seen when SCS is not connected to Internet & SIP Proxy Fails.<commit_after>/*
 *  Copyright (C) 2008 Pingtel Corp., certain elements licensed under a Contributor Agreement.
 *  Contributors retain copyright to elements licensed under a Contributor Agreement.
 *  Licensed to the User under the LGPL license.
 *
 */
package org.sipfoundry.sipxbridge.symmitron;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

import javax.net.ssl.SSLServerSocket;

import net.java.stun4j.StunAddress;
import net.java.stun4j.client.NetworkConfigurationDiscoveryProcess;
import net.java.stun4j.client.StunDiscoveryReport;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.mortbay.http.HttpContext;
import org.mortbay.http.HttpListener;
import org.mortbay.http.HttpServer;
import org.mortbay.http.SocketListener;
import org.mortbay.http.SslListener;
import org.mortbay.jetty.servlet.ServletHandler;
import org.mortbay.util.InetAddrPort;
import org.mortbay.util.ThreadedServer;
import org.sipfoundry.commons.log4j.SipFoundryAppender;
import org.sipfoundry.commons.log4j.SipFoundryLayout;
import org.sipfoundry.sipxbridge.SipXbridgeException;

/**
 * The SIPXbridge XML RPC handler.
 * 
 * @author <NAME>
 * 
 */
@SuppressWarnings("unchecked")
public class SymmitronServer implements Symmitron {

    private static Logger logger = Logger.getLogger(SymmitronServer.class.getPackage().getName());

    protected static Timer timer = new Timer();

    private static String status;

    /*
     * Map that pairs the SymSession id with the SymSession
     */
    private static Map<String, Sym> sessionMap = new ConcurrentHashMap<String, Sym>();

    /*
     * Map that pairs the rtpSesion owner with the rtp session
     */
    private static Map<String, HashSet<Sym>> sessionResourceMap = new ConcurrentHashMap<String, HashSet<Sym>>();

    /*
     * A map that pairs the RtpBridge id with the rtp Bridge.
     */
    private static Map<String, Bridge> bridgeMap = new ConcurrentHashMap<String, Bridge>();

    /*
     * A map that pairs the owner with the RtpBridge
     */
    private static Map<String, HashSet<Bridge>> bridgeResourceMap = new ConcurrentHashMap<String, HashSet<Bridge>>();

    /*
     * A map of component name to instance handle.
     */
    private static Map<String, String> instanceTable = new ConcurrentHashMap<String, String>();

    private static PortRangeManager portRangeManager;

    /*
     * My Instance handle
     */
    private static String myHandle = "sipxbridge:" + Math.abs(new Random().nextLong());

    private static boolean isWebServerRunning;

    private static HttpServer webServer;

    private static InetAddress localAddressByName;

    private static InetAddress publicAddress;

    private static SymmitronConfig symmitronConfig;

    private static final int STUN_PORT = 3478;

    // /////////////////////////////////////////////////////////////

    /**
     * Discover our address using stun.
     * 
     * @throws SipXbridgeException
     */
    static void discoverAddress() throws Exception {
        try {

            String stunServerAddress = symmitronConfig.getStunServerAddress();

            if (stunServerAddress != null) {

                // Todo -- deal with the situation when this port may be taken.
                // The port may be taken by sipxbridge.
                StunAddress localStunAddress = new StunAddress(symmitronConfig.getLocalAddress(),
                        STUN_PORT + 1);

                StunAddress serverStunAddress = new StunAddress(stunServerAddress, STUN_PORT);

                NetworkConfigurationDiscoveryProcess addressDiscovery = new NetworkConfigurationDiscoveryProcess(
                        localStunAddress, serverStunAddress);
                java.util.logging.LogManager logManager = java.util.logging.LogManager
                        .getLogManager();
                java.util.logging.Logger log = logManager
                        .getLogger(NetworkConfigurationDiscoveryProcess.class.getName());
                log.setLevel(java.util.logging.Level.OFF);

                addressDiscovery.start();
                StunDiscoveryReport report = addressDiscovery.determineAddress();
                if (report == null) {
                    logger.error("No stun report - could not do address discovery");
                    return;
                }
                StunAddress stunAddress = report.getPublicAddress();
                if (stunAddress == null) {
                    logger.error("No stun address - could not do address discovery");
                    return;
                }

                publicAddress = stunAddress.getSocketAddress().getAddress();
                logger.debug("Stun report = " + report);
                String publicAddr = publicAddress.getHostAddress();
                logger.debug("publicAddress = " + publicAddr);
                symmitronConfig.setPublicAddress(publicAddr);

            }
        } catch (Exception ex) {

            logger.error("Error discovering  address -- could be networking is bad", ex);
            throw ex;
        }
    }

    private Map<String, Object> createErrorMap(int errorCode, String reason) {
        Map<String, Object> retval = new HashMap<String, Object>();
        retval.put(STATUS_CODE, ERROR);
        retval.put(ERROR_CODE, new Integer(errorCode).toString());
        retval.put(ERROR_INFO, reason);

        retval.put(INSTANCE_HANDLE, myHandle);

        return retval;
    }

    private Map<String, Object> createSuccessMap() {
        Map<String, Object> retval = new HashMap<String, Object>();
        retval.put(STATUS_CODE, OK);
        retval.put(INSTANCE_HANDLE, myHandle);
        return retval;
    }

    private void addSymResource(String controllerId, Sym sym) {
        sessionMap.put(sym.getId(), sym);
        HashSet<Sym> syms = sessionResourceMap.get(controllerId);
        if (syms != null) {
            syms.add(sym);
        } else {
            syms = new HashSet<Sym>();
            syms.add(sym);
            sessionResourceMap.put(controllerId, syms);
        }
    }
    
    private static InetAddress findIpAddress (String localAddress) throws UnknownHostException {
        String[] addressParts = localAddress.split("\\.");
        boolean isIpAddress = true;
        byte[] addressBytes = new byte[addressParts.length];
        int i = 0;
        for (String addressPart : addressParts  ) {
            try {
                addressBytes[i++] = (byte) Integer.parseInt(addressPart);         
            } catch (NumberFormatException ex) {
                isIpAddress = false;
                break;
            }
        }
        
        InetAddress retval;
        /*
         * User specified a host name -- see if we can resolve it.
         */
        if (!isIpAddress) {
             retval = InetAddress.getByName(localAddress);
{'fraction_non_alphanumeric': 0.09817304377800759, 'fraction_numerical': 0.002619786280592899, 'mean_word_length': 2.4645330785765465, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3404150', 'n_tokens_mistral': 3948, 'n_tokens_neox': 3784, 'n_words': 980}