private void handleException(IOException e, String ip) {
        if (e == null || e.getMessage() == null) {
            return;
        }
        if (e instanceof SSLHandshakeException) {
            // Client doesn't accept the MITM CA certificate.
            NetBareLog.e(e.getMessage());
            if (ip != null) {
                NetBareLog.i("add %s to whitelist", ip);
                SSLWhiteList.add(ip);
            }
        } else if (e instanceof ConnectionShutdownException) {
            // Connection exception, do not mind this.
            NetBareLog.e(e.getMessage());
        } else if (e instanceof ConnectException) {
            // Connection timeout
            NetBareLog.e(e.getMessage());
        } else if (e instanceof SSLException && (e.getCause() instanceof EOFException)) {
            // Connection shutdown manually
            NetBareLog.e(e.getMessage());
        } else {
            NetBareLog.wtf(e);
            if (ip != null) {
                NetBareLog.i("add %s to whitelist", ip);
                SSLWhiteList.add(ip);
            }
        }
    }
The TCP proxy server is a nio {@link ServerSocketChannel}, it listens the connections from
{@link VpnService} and forwards request packets to real remote server. This server uses
{@link TcpVATunnel} to bind {@link VirtualGateway} and {@link NioTunnel} together. Every TCP
connection has two channels: {@link TcpProxyTunnel} and {@link TcpRemoteTunnel}.
The {@link TcpProxyTunnel} is responsible for sending remote server response packets to VPN
service, and the {@link TcpRemoteTunnel} is responsible for communicating with remote server.

@author Megatron King
@since 2018-10-11 17:35
netbare-core/src/main/java/com/github/megatronking/netbare/proxy/TcpProxyServer.java