17329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom/*
27329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  Licensed to the Apache Software Foundation (ASF) under one or more
37329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  contributor license agreements.  See the NOTICE file distributed with
47329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  this work for additional information regarding copyright ownership.
57329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  The ASF licenses this file to You under the Apache License, Version 2.0
67329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  (the "License"); you may not use this file except in compliance with
77329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  the License.  You may obtain a copy of the License at
87329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *
97329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *     http://www.apache.org/licenses/LICENSE-2.0
107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *
117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  Unless required by applicable law or agreed to in writing, software
127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  distributed under the License is distributed on an "AS IS" BASIS,
137329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  See the License for the specific language governing permissions and
157329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom *  limitations under the License.
167329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom */
177329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
187329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrompackage org.apache.harmony.xnet.provider.jsse;
197329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
207329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport java.io.IOException;
217329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport java.io.InputStream;
227329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport java.io.OutputStream;
237329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport java.net.InetAddress;
247329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport java.net.SocketAddress;
257329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport java.net.SocketException;
267329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport java.net.UnknownHostException;
277329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport java.util.ArrayList;
287329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport javax.net.ssl.HandshakeCompletedEvent;
297329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport javax.net.ssl.HandshakeCompletedListener;
307329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport javax.net.ssl.SSLEngineResult;
317329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport javax.net.ssl.SSLException;
327329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport javax.net.ssl.SSLSession;
337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstromimport javax.net.ssl.SSLSocket;
347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom/**
367329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom * SSLSocket implementation.
377329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom * @see javax.net.ssl.SSLSocket class documentation for more information.
387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom */
397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrompublic class SSLSocketImpl extends SSLSocket {
407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // indicates if handshake has been started
427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private boolean handshake_started = false;
437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
446d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    // used when we're wrapping a socket
456d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    private final String wrappedHost;
466d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    private final int wrappedPort;
476d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra
487329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // record protocol to be used
497329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected SSLRecordProtocol recordProtocol;
507329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // handshake protocol to be used
517329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private HandshakeProtocol handshakeProtocol;
527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // alert protocol to be used
537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private AlertProtocol alertProtocol;
547329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // application data input stream, this stream is presented by
55608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes    // ssl socket as an input stream. Additionally this object is a
567329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // place where application data will be stored by record protocol
577329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private SSLSocketInputStream appDataIS;
58608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes    // outgoing application data stream
597329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private SSLSocketOutputStream appDataOS;
607329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // active session object
617329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private SSLSessionImpl session;
627329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
637329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private boolean socket_was_closed = false;
647329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
657329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // the sslParameters object encapsulates all the info
667329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // about supported and enabled cipher suites and protocols,
677329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // as well as the information about client/server mode of
687329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // ssl socket, whether it require/want client authentication or not,
697329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // and controls whether new SSL sessions may be established by this
707329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // socket or not.
716812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected SSLParametersImpl sslParameters;
727329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // super's streams to be wrapped:
737329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected InputStream input;
747329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected OutputStream output;
757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // handshake complete listeners
767329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private ArrayList<HandshakeCompletedListener> listeners;
777329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // logger
787329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private Logger.Stream logger = Logger.getStream("socket");
797329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
807329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // ----------------- Constructors and initializers --------------------
817329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
827329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
837329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Constructor
846812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom     * @param   sslParameters:  SSLParametersImpl
857329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#SSLSocket() method documentation
867329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * for more information.
877329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
886812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected SSLSocketImpl(SSLParametersImpl sslParameters) {
897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        this.sslParameters = sslParameters;
906d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedHost = null;
916d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedPort = -1;
927329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        // init should be called after creation!
937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
947329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
957329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
967329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Constructor
977329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   host:   String
987329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   port:   int
996812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom     * @param   sslParameters:  SSLParametersImpl
1007329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @throws  IOException
1017329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @throws  UnknownHostException
1027365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson     * @see javax.net.ssl.SSLSocket#SSLSocket(String,int)
1037329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information.
1047329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
1056812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom    protected SSLSocketImpl(String host, int port, SSLParametersImpl sslParameters)
1067329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throws IOException, UnknownHostException {
1077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        super(host, port);
1086d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedHost = host;
1096d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedPort = port;
1107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        this.sslParameters = sslParameters;
1117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        init();
1127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
1137329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
1147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
1157329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Constructor
1167329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   host:   String
1177329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   port:   int
1187329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   localHost:  InetAddress
1197329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   localPort:  int
1206812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom     * @param   sslParameters:  SSLParametersImpl
1217329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @throws  IOException
1227329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @throws  UnknownHostException
1237329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#SSLSocket(String,int,InetAddress,int)
1247329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information.
1257329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
1267329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected SSLSocketImpl(String host, int port,
1277329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            InetAddress localHost, int localPort,
1286812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom            SSLParametersImpl sslParameters) throws IOException,
1297329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            UnknownHostException {
1307329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        super(host, port, localHost, localPort);
1316d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedHost = host;
1326d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedPort = port;
1337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        this.sslParameters = sslParameters;
1347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        init();
1357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
1367329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
1377329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
1387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Constructor
1397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   host:   InetAddress
1407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   port:   int
1416812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom     * @param   sslParameters:  SSLParametersImpl
1427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @return
1437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @throws  IOException
1447365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson     * @see javax.net.ssl.SSLSocket#SSLSocket(InetAddress,int)
1457329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information.
1467329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
1477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected SSLSocketImpl(InetAddress host, int port,
1486812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom            SSLParametersImpl sslParameters) throws IOException {
1497329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        super(host, port);
1507329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        this.sslParameters = sslParameters;
1516d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedHost = null;
1526d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedPort = -1;
1537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        init();
1547329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
1557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
1567329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
1577329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Constructor
1587329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   address:    InetAddress
1597329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   port:   int
1607329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   localAddress:   InetAddress
1617329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @param   localPort:  int
1626812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom     * @param   sslParameters:  SSLParametersImpl
1637329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @return
1647329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @throws  IOException
1657329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#SSLSocket(InetAddress,int,InetAddress,int)
1667329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information.
1677329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
1687329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected SSLSocketImpl(InetAddress address, int port,
1697329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            InetAddress localAddress, int localPort,
1706812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom            SSLParametersImpl sslParameters) throws IOException {
1717329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        super(address, port, localAddress, localPort);
1727329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        this.sslParameters = sslParameters;
1736d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedHost = null;
1746d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        this.wrappedPort = -1;
1757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        init();
1767329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
1777329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
1787329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
1797329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Initialize the SSL socket.
1807329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
1817329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected void init() throws IOException {
1827329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (appDataIS != null) {
1837329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            // already initialized
1847329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            return;
1857329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
1867329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        initTransportLayer();
1877329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        appDataIS = new SSLSocketInputStream(this);
1887329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        appDataOS = new SSLSocketOutputStream(this);
1897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
1907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
1917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
1927329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Initialize the transport data streams.
1937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
1947329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected void initTransportLayer() throws IOException {
1957329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        input = super.getInputStream();
1967329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        output = super.getOutputStream();
1977329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
1987329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
1997329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
2007329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Closes the transport data streams.
2017329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
2027329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected void closeTransportLayer() throws IOException {
2037329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        super.close();
2047329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (input != null) {
2057329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            input.close();
2067329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            output.close();
2077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
2087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
2097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
2106d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    String getWrappedHostName() {
2116d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        return wrappedHost;
2126d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    }
2136d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra
2146d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    int getWrappedPort() {
2156d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        return wrappedPort;
2166d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    }
2176d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra
2186d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    String getPeerHostName() {
2196d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        if (wrappedHost != null) {
2206d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            return wrappedHost;
2216d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        }
2226d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        InetAddress inetAddress = super.getInetAddress();
2236d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        if (inetAddress != null) {
2246d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            return inetAddress.getHostName();
2256d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        }
2266d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        return null;
2276d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    }
2286d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra
2296d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    int getPeerPort() {
2306d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        return (wrappedPort == -1) ? super.getPort() : wrappedPort;
2316d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra    }
2326d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra
2337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // --------------- SSLParameters based methods ---------------------
2347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
2357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
2367329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
2377329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getSupportedCipherSuites()
2387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
2397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
2407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
2417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public String[] getSupportedCipherSuites() {
2427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return CipherSuite.getSupportedCipherSuiteNames();
2437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
2447329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
2457329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
2467329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
2477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getEnabledCipherSuites()
2487329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
2497329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
2507329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
2517329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public String[] getEnabledCipherSuites() {
2527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return sslParameters.getEnabledCipherSuites();
2537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
2547329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
2557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
2567329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
2577329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#setEnabledCipherSuites(String[])
2587329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
2597329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
2607329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
2617329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void setEnabledCipherSuites(String[] suites) {
2627329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        sslParameters.setEnabledCipherSuites(suites);
2637329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
2647329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
2657329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
2667329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
2677329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getSupportedProtocols()
2687329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
2697329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
2707329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
2717329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public String[] getSupportedProtocols() {
2727329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return ProtocolVersion.supportedProtocols.clone();
2737329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
2747329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
2757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
2767329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
2777329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getEnabledProtocols()
2787329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
2797329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
2807329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
2817329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public String[] getEnabledProtocols() {
2827329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return sslParameters.getEnabledProtocols();
2837329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
2847329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
2857329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
2867329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
2877329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#setEnabledProtocols(String[])
2887329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
2897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
2907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
2917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void setEnabledProtocols(String[] protocols) {
2927329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        sslParameters.setEnabledProtocols(protocols);
2937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
2947329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
2957329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
2967329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
2977329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#setUseClientMode(boolean)
2987329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
2997329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3007329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3017329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void setUseClientMode(boolean mode) {
3027329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (handshake_started) {
3037329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IllegalArgumentException(
3047329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            "Could not change the mode after the initial handshake has begun.");
3057329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
3067329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        sslParameters.setUseClientMode(mode);
3077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
3107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
3117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getUseClientMode()
3127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
3137329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3157329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public boolean getUseClientMode() {
3167329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return sslParameters.getUseClientMode();
3177329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3187329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3197329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
3207329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
3217329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#setNeedClientAuth(boolean)
3227329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
3237329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3247329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3257329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void setNeedClientAuth(boolean need) {
3267329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        sslParameters.setNeedClientAuth(need);
3277329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3287329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3297329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
3307329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
3317329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getNeedClientAuth()
3327329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
3337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public boolean getNeedClientAuth() {
3367329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return sslParameters.getNeedClientAuth();
3377329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
3407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
3417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#setWantClientAuth(boolean)
3427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
3437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3447329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3457329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void setWantClientAuth(boolean want) {
3467329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        sslParameters.setWantClientAuth(want);
3477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3487329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3497329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
3507329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
3517329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getWantClientAuth()
3527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
3537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3547329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public boolean getWantClientAuth() {
3567329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return sslParameters.getWantClientAuth();
3577329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3587329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3597329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
3607329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
3617329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#setEnableSessionCreation(boolean)
3627329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
3637329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3647329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3657329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void setEnableSessionCreation(boolean flag) {
3667329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        sslParameters.setEnableSessionCreation(flag);
3677329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3687329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3697329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
3707329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
3717329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getEnableSessionCreation()
3727329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
3737329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3747329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public boolean getEnableSessionCreation() {
3767329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return sslParameters.getEnableSessionCreation();
3777329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3787329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3797329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // -----------------------------------------------------------------
3807329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
3817329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
3827329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
3837329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getSession()
3847329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
3857329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
3867329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
3877329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public SSLSession getSession() {
3887329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (!handshake_started) {
3897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            try {
3907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                startHandshake();
3917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            } catch (IOException e) {
3927329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                // return an invalid session with
3937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
3947329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                return SSLSessionImpl.NULL_SESSION;
3957329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
3967329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
3977329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return session;
3987329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
3997329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4007329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
4017329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
4027329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#addHandshakeCompletedListener(HandshakeCompletedListener)
4037329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
4047329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
4057329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
4067329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void addHandshakeCompletedListener(
4077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            HandshakeCompletedListener listener) {
4087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (listener == null) {
4097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IllegalArgumentException("Provided listener is null");
4107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (listeners == null) {
4127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            listeners = new ArrayList<HandshakeCompletedListener>();
4137329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        listeners.add(listener);
4157329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
4167329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4177329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
4187329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
4197329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#removeHandshakeCompletedListener(HandshakeCompletedListener)
4207329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
4217329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
4227329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
4237329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void removeHandshakeCompletedListener(
4247329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            HandshakeCompletedListener listener) {
4257329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (listener == null) {
4267329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IllegalArgumentException("Provided listener is null");
4277329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4287329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (listeners == null) {
4297329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IllegalArgumentException(
4307329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    "Provided listener is not registered");
4317329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4327329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (!listeners.remove(listener)) {
4337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IllegalArgumentException(
4347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    "Provided listener is not registered");
4357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4367329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
4377329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
4397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Performs the handshake process over the SSL/TLS connection
4407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * as described in rfc 2246, TLS v1 specification
4417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * http://www.ietf.org/rfc/rfc2246.txt. If the initial handshake
4427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * has been already done, this method initiates rehandshake.
4437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
4447329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#startHandshake()
4457329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
4467329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
4477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
4487329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void startHandshake() throws IOException {
4497329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (appDataIS == null) {
4507329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IOException("Socket is not connected.");
4517329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (socket_was_closed) {
4537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IOException("Socket has already been closed.");
4547329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4567329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (!handshake_started) {
4577329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            handshake_started = true;
4587329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            if (sslParameters.getUseClientMode()) {
4597329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (logger != null) {
4607329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    logger.println("SSLSocketImpl: CLIENT");
4617329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
4627329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                handshakeProtocol = new ClientHandshakeImpl(this);
4637329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            } else {
4647329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (logger != null) {
4657329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    logger.println("SSLSocketImpl: SERVER");
4667329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
4677329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                handshakeProtocol = new ServerHandshakeImpl(this);
4687329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
4697329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4707329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            alertProtocol = new AlertProtocol();
4717329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            recordProtocol = new SSLRecordProtocol(handshakeProtocol,
4727329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    alertProtocol, new SSLStreamedInput(input),
4737329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    appDataIS.dataPoint);
4747329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4767329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (logger != null) {
4777329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            logger.println("SSLSocketImpl.startHandshake");
4787329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4797329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4807329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        handshakeProtocol.start();
4817329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4827329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        doHandshake();
4837329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4847329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (logger != null) {
4857329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            logger.println("SSLSocketImpl.startHandshake: END");
4867329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4877329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
4887329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
4897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
4907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
4917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getInputStream()
4927329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
4937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
4947329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
4957329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public InputStream getInputStream() throws IOException {
4967329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (socket_was_closed) {
4977329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IOException("Socket has already been closed.");
4987329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
4997329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return appDataIS;
5007329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
5017329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
5027329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
5037329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
5047329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#getOutputStream()
5057329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
5067329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
5077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
5087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public OutputStream getOutputStream() throws IOException {
5097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (socket_was_closed) {
5107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IOException("Socket has already been closed.");
5117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
5127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        return appDataOS;
5137329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
5147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
5157329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
5167329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
5177329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see java.net.Socket#connect(SocketAddress)
5187329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
5197329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
5207329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
5217329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void connect(SocketAddress endpoint) throws IOException {
5227329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        super.connect(endpoint);
5237329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        init();
5247329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
5257365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson
5267329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
5277329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
5287329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see java.net.Socket#connect(SocketAddress,int)
5297329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
5307329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
5317329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
5327365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson    public void connect(SocketAddress endpoint, int timeout)
5337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throws IOException {
5347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        super.connect(endpoint, timeout);
5357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        init();
5367329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
5377365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson
5387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
5397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method works according to the specification of implemented class.
5407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @see javax.net.ssl.SSLSocket#close()
5417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * method documentation for more information
5427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
5437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
5447329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void close() throws IOException {
5457329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (logger != null) {
5467329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            logger.println("SSLSocket.close "+socket_was_closed);
5477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
5487329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (!socket_was_closed) {
5497329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            if (handshake_started) {
5507329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                alertProtocol.alert(AlertProtocol.WARNING,
5517329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        AlertProtocol.CLOSE_NOTIFY);
5527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                try {
5537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    output.write(alertProtocol.wrap());
5547329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                } catch (IOException ex) { }
5557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                alertProtocol.setProcessed();
5567329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
5577329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            shutdown();
5587329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            closeTransportLayer();
5597329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            socket_was_closed = true;
5607329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
5617329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
5627329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
5637329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
5647329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method is not supported for SSLSocket implementation.
5657329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
5667329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
5677329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void sendUrgentData(int data) throws IOException {
5687329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        throw new SocketException(
5697329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                "Method sendUrgentData() is not supported.");
5707329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
5717329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
5727329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
5737329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method is not supported for SSLSocket implementation.
5747329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
5757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    @Override
5767329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    public void setOOBInline(boolean on) throws SocketException {
5777329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        throw new SocketException(
5787329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                "Methods sendUrgentData, setOOBInline are not supported.");
5797329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
5807329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
5817329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    // -----------------------------------------------------------------
5827329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
5837329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private void shutdown() {
5847329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (handshake_started) {
5857329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            alertProtocol.shutdown();
5867329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            alertProtocol = null;
5877329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            handshakeProtocol.shutdown();
5887329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            handshakeProtocol = null;
5897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            recordProtocol.shutdown();
5907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            recordProtocol = null;
5917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
5927329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        socket_was_closed = true;
5937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
5947329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
5957329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
5967329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * This method is called by SSLSocketInputStream class
597ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes     * when client application tries to read application data from
5987329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * the stream, but there is no data in its underlying buffer.
5997329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * @throws  IOException
6007329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
6017329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    protected void needAppData() throws IOException {
6027329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (!handshake_started) {
6037329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            startHandshake();
6047329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
6057329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        int type;
6067329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (logger != null) {
6077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            logger.println("SSLSocket.needAppData..");
6087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
6097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        try {
6107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            while(appDataIS.available() == 0) {
6117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                // read and unwrap the record contained in the transport
6127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                // input stream (SSLStreamedInput), pass it
6137329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                // to appropriate client protocol (alert, handshake, or app)
6147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                // and retrieve the type of unwrapped data
6157329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                switch (type = recordProtocol.unwrap()) {
6167329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    case ContentType.HANDSHAKE:
6177329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        if (!handshakeProtocol.getStatus().equals(
6187329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                SSLEngineResult.HandshakeStatus
6197329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                .NOT_HANDSHAKING)) {
6207365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson                            // handshake protocol got addressed to it message
6217329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            // and did not ignore it, so it's a rehandshake
6227329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            doHandshake();
6237329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        }
6247329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        break;
6257329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    case ContentType.ALERT:
6267329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        processAlert();
6277329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        if (socket_was_closed) {
6287329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            return;
6297329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        }
6307329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        break;
6317329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    case ContentType.APPLICATION_DATA:
6327329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        if (logger != null) {
6337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            logger.println(
6347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                    "SSLSocket.needAppData: got the data");
6357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        }
6367329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        break;
6377329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    default:
6387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        // will throw exception
6397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        reportFatalAlert(AlertProtocol.UNEXPECTED_MESSAGE,
6407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                new SSLException("Unexpected message of type "
6417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                    + type + " has been got"));
6427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
6437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (alertProtocol.hasAlert()) {
644ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes                    // warning alert occurred during wrap or unwrap
6457329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // (note: fatal alert causes AlertException
6467329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // to be thrown)
6477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    output.write(alertProtocol.wrap());
6487329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    alertProtocol.setProcessed();
6497329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
6507329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (socket_was_closed) {
6517329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    appDataIS.setEnd();
6527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    return;
6537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
6547329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
6557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        } catch (AlertException e) {
6567329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            // will throw exception
6577329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            reportFatalAlert(e.getDescriptionCode(), e.getReason());
6587329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        } catch (EndOfSourceException e) {
6597329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            // end of socket's input stream has been reached
6607329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            appDataIS.setEnd();
6617329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
6627329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (logger != null) {
6637329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            logger.println("SSLSocket.needAppData: app data len: "
6647329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    + appDataIS.available());
6657329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
6667329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
6677329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
6687329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /**
669ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes     * This method is called by SSLSocketOutputStream when a client application
670ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes     * tries to send the data over ssl protocol.
6717329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
672608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes    protected void writeAppData(byte[] data, int offset, int len) throws IOException {
6737329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (!handshake_started) {
6747329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            startHandshake();
6757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
6767329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (logger != null) {
6777329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            logger.println("SSLSocket.writeAppData: " +
6787329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    len + " " + SSLRecordProtocol.MAX_DATA_LENGTH);
6797329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            //logger.println(new String(data, offset, len));
6807329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
6817329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        try {
6827329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            if (len < SSLRecordProtocol.MAX_DATA_LENGTH) {
6837329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                output.write(recordProtocol.wrap(ContentType.APPLICATION_DATA,
6847329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            data, offset, len));
6857329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            } else {
6867329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                while (len >= SSLRecordProtocol.MAX_DATA_LENGTH) {
6877329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    output.write(recordProtocol.wrap(
6887329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                ContentType.APPLICATION_DATA, data, offset,
6897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                SSLRecordProtocol.MAX_DATA_LENGTH));
6907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    offset += SSLRecordProtocol.MAX_DATA_LENGTH;
6917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    len -= SSLRecordProtocol.MAX_DATA_LENGTH;
6927329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
6937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (len > 0) {
6947329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    output.write(
6957329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        recordProtocol.wrap(ContentType.APPLICATION_DATA,
6967329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                            data, offset, len));
6977329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
6987329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
6997329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        } catch (AlertException e) {
7007329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            // will throw exception
7017329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            reportFatalAlert(e.getDescriptionCode(), e.getReason());
7027329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
7037329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
7047329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
7057329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /*
706608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes     * Performs handshake process over this connection. The handshake
707d6e53e42867824f97c9fb9c427cc188897ea9315Brian Carlstrom     * process is directed by the handshake status code provided by
7087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * handshake protocol. If this status is NEED_WRAP, method retrieves
7097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * handshake message from handshake protocol and sends it to another peer.
7107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * If this status is NEED_UNWRAP, method receives and processes handshake
7117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * message from another peer. Each of this stages (wrap/unwrap) change
7127365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson     * the state of handshake protocol and this process is performed
713608263018762d64a07276b7c8f58102455ccecc8Elliott Hughes     * until handshake status is FINISHED. After handshake process is finished
7147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * handshake completed event are sent to the registered listeners.
7157329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * For more information about the handshake process see
7167329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * TLS v1 specification (http://www.ietf.org/rfc/rfc2246.txt) p 7.3.
7177329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
7187329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private void doHandshake() throws IOException {
7197329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        SSLEngineResult.HandshakeStatus status;
7207329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        int type;
7217329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        try {
7227329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            while (!(status = handshakeProtocol.getStatus()).equals(
7237329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        SSLEngineResult.HandshakeStatus.FINISHED)) {
7247329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (logger != null) {
7257329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    String s = (status.equals(
7267329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                SSLEngineResult.HandshakeStatus.NEED_WRAP))
7277329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        ? "NEED_WRAP"
7287329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        : (status.equals(
7297329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                SSLEngineResult.HandshakeStatus.NEED_UNWRAP))
7307329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            ? "NEED_UNWRAP"
7317329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            : "STATUS: OTHER!";
7327329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    logger.println("SSLSocketImpl: HS status: "+s+" "+status);
7337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
7347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (status.equals(SSLEngineResult.HandshakeStatus.NEED_WRAP)) {
7357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    output.write(handshakeProtocol.wrap());
7367329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                } else if (status.equals(
7377329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            SSLEngineResult.HandshakeStatus.NEED_UNWRAP)) {
7387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // read and unwrap the record contained in the transport
7397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // input stream (SSLStreamedInput), pass it
7407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // to appropriate client protocol (alert, handshake, or app)
7417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // and retrieve the type of unwrapped data
7427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    switch (type = recordProtocol.unwrap()) {
7437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        case ContentType.HANDSHAKE:
7447329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        case ContentType.CHANGE_CIPHER_SPEC:
7457329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            break;
7467329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        case ContentType.APPLICATION_DATA:
7477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            // So it's rehandshake and
7487329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            // if app data buffer will be overloaded
7497329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            // it will throw alert exception.
7507329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            // Probably we should count the number of
7517329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            // not handshaking data and make additional
7527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            // constraints (do not expect buffer overflow).
7537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            break;
7547329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        case ContentType.ALERT:
7557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            processAlert();
7567329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            if (socket_was_closed) {
7577329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                return;
7587329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            }
7597329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            break;
7607329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        default:
7617329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            // will throw exception
7627329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            reportFatalAlert(AlertProtocol.UNEXPECTED_MESSAGE,
7637329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                    new SSLException(
7647329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                        "Unexpected message of type "
7657329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                                        + type + " has been got"));
7667329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    }
7677329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                } else {
7687329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // will throw exception
7697329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    reportFatalAlert(AlertProtocol.INTERNAL_ERROR,
7707329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                        new SSLException(
7717329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            "Handshake passed unexpected status: "+status));
7727329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
7737329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (alertProtocol.hasAlert()) {
774ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes                    // warning alert occurred during wrap or unwrap
7757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // (note: fatal alert causes AlertException
7767329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    // to be thrown)
7777329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    output.write(alertProtocol.wrap());
7787329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    alertProtocol.setProcessed();
7797329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
7807329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
7817329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        } catch (EndOfSourceException e) {
7827329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            appDataIS.setEnd();
7837329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new IOException("Connection was closed");
7847329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        } catch (AlertException e) {
7857329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            // will throw exception
7867329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            reportFatalAlert(e.getDescriptionCode(), e.getReason());
7877329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
7887329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom
7897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        session = recordProtocol.getSession();
7907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (listeners != null) {
7917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            // notify the listeners
7927329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            HandshakeCompletedEvent event =
7937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                new HandshakeCompletedEvent(this, session);
7947329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            int size = listeners.size();
7957329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            for (int i=0; i<size; i++) {
7967329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                listeners.get(i)
7977329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    .handshakeCompleted(event);
7987329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
7997329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
8007329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
8017365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson
8027329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /*
8037329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Process received alert message
8047329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
8057329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    private void processAlert() throws IOException {
8067329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (!alertProtocol.hasAlert()) {
8077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            return;
8087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
8097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (alertProtocol.isFatalAlert()) {
8107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            alertProtocol.setProcessed();
8117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            String description = "Fatal alert received "
8127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                + alertProtocol.getAlertDescription();
8137329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            shutdown();
8147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            throw new SSLException(description);
8157329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
8167365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson
8177329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        if (logger != null) {
8187329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            logger.println("Warning alert received: "
8197329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                + alertProtocol.getAlertDescription());
8207329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
8217329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        switch(alertProtocol.getDescriptionCode()) {
8227329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            case AlertProtocol.CLOSE_NOTIFY:
8237329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                alertProtocol.setProcessed();
8247329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                appDataIS.setEnd();
8257329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                close();
8267329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                return;
8277329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            default:
8287329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                alertProtocol.setProcessed();
8297329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            // TODO: process other warning messages
8307329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        }
8317329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
8327365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson
8337329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    /*
8347329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     * Sends fatal alert message and throws exception
8357329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom     */
8367365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilson    private void reportFatalAlert(byte description_code,
8377329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            SSLException reason) throws IOException {
8387329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        alertProtocol.alert(AlertProtocol.FATAL, description_code);
8397329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        try {
8407329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            // the output stream can be closed
8417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            output.write(alertProtocol.wrap());
8427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        } catch (IOException ex) { }
8437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        alertProtocol.setProcessed();
8447329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        shutdown();
8457329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        throw reason;
8467329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom    }
8477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom}
848