org.bombusim.networking.NetworkSocketDataStream.java Source code

Java tutorial

Introduction

Here is the source code for org.bombusim.networking.NetworkSocketDataStream.java

Source

/*
 * Copyright (c) 2005-2011, Eugene Stahov (evgs@bombus-im.org), 
 * http://bombus-im.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.bombusim.networking;

import java.io.IOException;

import java.net.Socket;
import java.net.UnknownHostException;
import java.security.Principal;
import java.text.DateFormat;

import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocket;

import javax.net.ssl.SSLSocketFactory;
import javax.security.cert.X509Certificate;

import org.bombusim.lime.logger.LimeLog;

import android.net.SSLCertificateSocketFactory;

//import org.apache.http.conn.ssl.SSLSocketFactory;

import com.jcraft.jzlib.DeflaterOutputStream;
import com.jcraft.jzlib.InflaterInputStream;

public class NetworkSocketDataStream extends NetworkDataStream {

    private boolean zlib = false;
    private String certificateInfo;

    protected Socket socket;
    protected String host;
    protected int port;

    public NetworkSocketDataStream(String server, int port) throws UnknownHostException, IOException {

        this.host = server;
        this.port = port;

        LimeLog.i("Socket", "Connecting to " + host + ":" + port, null);
        socket = new Socket(server, port);

        //keep-alive packets every 2 hours (by default)
        socket.setKeepAlive(true);

        istream = socket.getInputStream();
        ostream = socket.getOutputStream();

    }

    public void setCompression() throws IOException {
        LimeLog.i("Socket", "Binding ZLIB", null);

        istream = new InflaterInputStream(istream);

        DeflaterOutputStream dos;
        dos = new DeflaterOutputStream(ostream);
        dos.setSyncFlush(true);
        ostream = dos;

        zlib = true;

    }

    public void setTLS() throws IOException {
        LimeLog.i("Socket", "Switching to secure socket layer", null);

        //TODO: check on different devices:
        // !!! ENSURE TLS enabled in account settings before test
        // 1. emulator/2.2 - SSLPeerUnverifiedException (jabber.ru, google.com) - bug in emulator v2.2
        // 2. cyanogen/2.3 - works (all hosts)
        // 3. emulator/ics - works
        // 4. Gratia/2.2 - works
        SSLSocketFactory sf =
                //SSLCertificateSocketFactory.getDefault(20000, null);
                SSLCertificateSocketFactory.getInsecure(20000, null);

        //TODO: check on different devices:
        // 1. emulator/2.2 - works
        // 2. cyanogen/2.3 - works
        //KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
        //trustStore.load(null, null); 
        //SSLSocketFactory sf = new AndroidSSLSocketFactory(trustStore); 
        //sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

        final SSLSocket ssls = (SSLSocket) sf.createSocket(socket, host, port, true);

        ssls.addHandshakeCompletedListener(new HandshakeCompletedListener() {
            @Override
            public void handshakeCompleted(HandshakeCompletedEvent event) {
                X509Certificate[] certs;
                try {
                    certs = ssls.getSession().getPeerCertificateChain();
                } catch (SSLPeerUnverifiedException e) {
                    return;
                }

                StringBuilder so = new StringBuilder();

                for (X509Certificate cert : certs) {
                    so.append("X509 Certificate:\n").append(" Subject:");
                    appendPrincipal(so, cert.getSubjectDN());
                    so.append("\n Issued by:");
                    appendPrincipal(so, cert.getIssuerDN());
                    so.append("\n Valid from:    ").append(DateFormat.getInstance().format(cert.getNotBefore()));
                    so.append("\n Expired after: ").append(DateFormat.getInstance().format(cert.getNotAfter()));
                    so.append("\n\n");
                }

                certificateInfo = so.toString();
                LimeLog.i("Socket", "Certificate chain verified", certificateInfo);
            }

            private void appendPrincipal(StringBuilder so, Principal p) {
                String name = p.getName();
                if (name == null) {
                    so.append("<null>\n");
                    return;
                }

                String elements[] = name.split(",");
                for (String e : elements) {
                    so.append("\n   ").append(e);
                }

                so.append("\n");
            }
        });

        ssls.startHandshake();
        socket = ssls;

        istream = socket.getInputStream();
        ostream = socket.getOutputStream();

    }

    @Override
    public void closeConnection() throws IOException {
        try {
            super.closeConnection();
        } finally {
            socket.close();
        }
    }

    public boolean isSecure() {
        return certificateInfo != null;
    }

    public boolean isCompressed() {
        return zlib;
    }

    public String getCertificateInfo() {
        // TODO Auto-generated method stub
        return certificateInfo;
    }

    @Override
    public boolean isClosed() {
        return socket.isClosed();
    }
}