/* 
 * Copyright 2012 by AVM GmbH <info@avm.de>
 *
 * This software contains free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License ("License") as 
 * published by the Free Software Foundation  (version 3 of the License). 
 * This software 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 copy of the 
 * License you received along with this software for more details.
 */

package de.avm.android.tr064.net;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyStore;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;

import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

/**
 * SSL socket factory for accepting self signed certificates
 * - TLS
 * - accepting self signed certificates
 * - accepting all hosts
 */
public class SoapSSLSocketFactory implements SocketFactory, LayeredSocketFactory
{
	private SSLContext mSSLContext = null;

	public static SoapSSLSocketFactory getInstance(KeyStore keyStore)
			throws IOException
	{
		SoapSSLSocketFactory factory = new SoapSSLSocketFactory();
        try
        {
        	factory.mSSLContext = SSLContext.getInstance("TLS");
        	factory.mSSLContext.init(null,
        			new TrustManager[] { new SoapTrustManager(keyStore) },
        			null);
        	return factory;
        }
        catch (Exception e)
        {
        	if (IOException.class.isAssignableFrom(e.getClass()))
        		throw (IOException)e;
        	IOException exp = new IOException(e.getMessage());
        	exp.initCause(e);
            throw exp;
        }
	}

	public Socket connectSocket(Socket sock, String host, int port,
			InetAddress localAddress, int localPort, HttpParams params)
			throws IOException, UnknownHostException, ConnectTimeoutException
	{
        Socket sslSock = (sock == null) ? createSocket() : sock;
        if ((localAddress != null) || (localPort > 0))
            sslSock.bind(new InetSocketAddress(localAddress,
            		(localPort < 0) ? 0 : localPort));
        
        sslSock.connect(new InetSocketAddress(host, port),
        		HttpConnectionParams.getConnectionTimeout(params));
        sslSock.setSoTimeout(HttpConnectionParams.getSoTimeout(params));

        return sslSock;
	}

	public Socket createSocket() throws IOException
	{
        return mSSLContext.getSocketFactory().createSocket();
	}

	public Socket createSocket(Socket socket, String host, int port,
			boolean autoClose) throws IOException, UnknownHostException
	{
        return mSSLContext.getSocketFactory()
        		.createSocket(socket, host, port, autoClose);
	}

	public boolean isSecure(Socket sock) throws IllegalArgumentException
	{
		return true;
	}
	
	/**
	 * use getSocketFactory()
	 */
	private SoapSSLSocketFactory()
	{
	}
}
