test/jdk/java/net/httpclient/ProxyServer.java
author michaelm
Tue, 16 Jan 2018 15:52:01 +0000
branchhttp-client-branch
changeset 56010 782b2f2d1e76
parent 55973 4d9b002587db
child 56233 1753108d07b9
permissions -rw-r--r--
http-client-branch: updated server push API
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
36131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     1
/*
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
     2
 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
36131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     4
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     8
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    13
 * accompanied this code).
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    14
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    18
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    21
 * questions.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    22
 */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    23
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    24
import java.net.*;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    25
import java.io.*;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    26
import java.util.*;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    27
import java.security.*;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    28
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    29
/**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    30
 * A minimal proxy server that supports CONNECT tunneling. It does not do
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    31
 * any header transformations. In future this could be added.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    32
 * Two threads are created per client connection. So, it's not
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    33
 * intended for large numbers of parallel connections.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    34
 */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    35
public class ProxyServer extends Thread implements Closeable {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    36
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    37
    ServerSocket listener;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    38
    int port;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    39
    volatile boolean debug;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    40
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    41
    /**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    42
     * Create proxy on port (zero means don't care). Call getPort()
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    43
     * to get the assigned port.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    44
     */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    45
    public ProxyServer(Integer port) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    46
        this(port, false);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    47
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    48
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    49
    public ProxyServer(Integer port, Boolean debug) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    50
        this.debug = debug;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    51
        listener = new ServerSocket(port);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    52
        this.port = listener.getLocalPort();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    53
        setName("ProxyListener");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    54
        setDaemon(true);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    55
        connections = new LinkedList<>();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    56
        start();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    57
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    58
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    59
    public ProxyServer(String s) {  }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    60
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    61
    /**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    62
     * Returns the port number this proxy is listening on
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    63
     */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    64
    public int getPort() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    65
        return port;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    66
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    67
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    68
    /**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    69
     * Shuts down the proxy, probably aborting any connections
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    70
     * currently open
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    71
     */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    72
    public void close() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    73
        if (debug) System.out.println("Proxy: closing");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    74
            done = true;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    75
        listener.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    76
        for (Connection c : connections) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    77
            if (c.running()) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    78
                c.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    79
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    80
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    81
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    82
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    83
    List<Connection> connections;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    84
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    85
    volatile boolean done;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    86
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    87
    public void run() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    88
        if (System.getSecurityManager() == null) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    89
            execute();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    90
        } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    91
            // so calling domain does not need to have socket permission
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    92
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    93
                public Void run() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    94
                    execute();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    95
                    return null;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    96
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    97
            });
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    98
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    99
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   100
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   101
    public void execute() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   102
        try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   103
            while(!done) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   104
                Socket s = listener.accept();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   105
                if (debug)
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   106
                    System.out.println("Client: " + s);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   107
                Connection c = new Connection(s);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   108
                connections.add(c);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   109
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   110
        } catch(Throwable e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   111
            if (debug && !done) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   112
                System.out.println("Fatal error: Listener: " + e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   113
                e.printStackTrace();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   114
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   115
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   116
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   117
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   118
    /**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   119
     * Transparently forward everything, once we know what the destination is
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   120
     */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   121
    class Connection {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   122
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   123
        Socket clientSocket, serverSocket;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   124
        Thread out, in;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   125
        volatile InputStream clientIn, serverIn;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   126
        volatile OutputStream clientOut, serverOut;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   127
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   128
        boolean forwarding = false;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   129
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   130
        final static int CR = 13;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   131
        final static int LF = 10;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   132
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   133
        Connection(Socket s) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   134
            this.clientSocket= s;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   135
            this.clientIn = new BufferedInputStream(s.getInputStream());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   136
            this.clientOut = s.getOutputStream();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   137
            init();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   138
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   139
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   140
        byte[] readHeaders(InputStream is) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   141
            byte[] outbuffer = new byte[8000];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   142
            int crlfcount = 0;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   143
            int bytecount = 0;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   144
            int c;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   145
            while ((c=is.read()) != -1 && bytecount < outbuffer.length) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   146
                outbuffer[bytecount++] = (byte)c;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   147
                if (debug) System.out.write(c);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   148
                // were looking for CRLFCRLF sequence
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   149
                if (c == CR || c == LF) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   150
                    switch(crlfcount) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   151
                        case 0:
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   152
                            if (c == CR) crlfcount ++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   153
                            break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   154
                        case 1:
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   155
                            if (c == LF) crlfcount ++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   156
                            break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   157
                        case 2:
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   158
                            if (c == CR) crlfcount ++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   159
                            break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   160
                        case 3:
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   161
                            if (c == LF) crlfcount ++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   162
                            break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   163
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   164
                } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   165
                    crlfcount = 0;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   166
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   167
                if (crlfcount == 4) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   168
                    break;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   169
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   170
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   171
            byte[] ret = new byte[bytecount];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   172
            System.arraycopy(outbuffer, 0, ret, 0, bytecount);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   173
            return ret;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   174
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   175
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   176
        boolean running() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   177
            return out.isAlive() || in.isAlive();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   178
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   179
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   180
        public void close() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   181
            if (debug) System.out.println("Closing connection (proxy)");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   182
            if (serverSocket != null) serverSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   183
            if (clientSocket != null) clientSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   184
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   185
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   186
        int findCRLF(byte[] b) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   187
            for (int i=0; i<b.length-1; i++) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   188
                if (b[i] == CR && b[i+1] == LF) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   189
                    return i;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   190
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   191
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   192
            return -1;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   193
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   194
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   195
        public void init() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   196
            try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   197
                byte[] buf = readHeaders(clientIn);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   198
                int p = findCRLF(buf);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   199
                if (p == -1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   200
                    close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   201
                    return;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   202
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   203
                String cmd = new String(buf, 0, p, "US-ASCII");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   204
                String[] params = cmd.split(" ");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   205
                if (params[0].equals("CONNECT")) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   206
                    doTunnel(params[1]);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   207
                } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   208
                    doProxy(params[1], buf, p, cmd);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   209
                }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   210
            } catch (Throwable e) {
36131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   211
                if (debug) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   212
                    System.out.println (e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   213
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   214
                try {close(); } catch (IOException e1) {}
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   215
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   216
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   217
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   218
        void doProxy(String dest, byte[] buf, int p, String cmdLine)
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   219
            throws IOException
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   220
        {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   221
            try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   222
                URI uri = new URI(dest);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   223
                if (!uri.isAbsolute()) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   224
                    throw new IOException("request URI not absolute");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   225
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   226
                dest = uri.getAuthority();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   227
                // now extract the path from the URI and recreate the cmd line
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   228
                int sp = cmdLine.indexOf(' ');
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   229
                String method = cmdLine.substring(0, sp);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   230
                cmdLine = method + " " + uri.getPath() + " HTTP/1.1";
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   231
                int x = cmdLine.length() - 1;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   232
                int i = p;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   233
                while (x >=0) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   234
                    buf[i--] = (byte)cmdLine.charAt(x--);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   235
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   236
                i++;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   237
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   238
                commonInit(dest, 80);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   239
                serverOut.write(buf, i, buf.length-i);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   240
                proxyCommon();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   241
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   242
            } catch (URISyntaxException e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   243
                throw new IOException(e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   244
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   245
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   246
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   247
        void commonInit(String dest, int defaultPort) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   248
            int port;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   249
            String[] hostport = dest.split(":");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   250
            if (hostport.length == 1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   251
                port = defaultPort;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   252
            } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   253
                port = Integer.parseInt(hostport[1]);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   254
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   255
            if (debug) System.out.printf("Server: (%s/%d)\n", hostport[0], port);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   256
            serverSocket = new Socket(hostport[0], port);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   257
            serverOut = serverSocket.getOutputStream();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   258
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   259
            serverIn = new BufferedInputStream(serverSocket.getInputStream());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   260
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   261
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   262
        void proxyCommon() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   263
            out = new Thread(() -> {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   264
                try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   265
                    byte[] bb = new byte[8000];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   266
                    int n;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   267
                    while ((n = clientIn.read(bb)) != -1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   268
                        serverOut.write(bb, 0, n);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   269
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   270
                    serverSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   271
                    clientSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   272
                } catch (IOException e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   273
                    if (debug) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   274
                        System.out.println (e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   275
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   276
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   277
            });
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   278
            in = new Thread(() -> {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   279
                try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   280
                    byte[] bb = new byte[8000];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   281
                    int n;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   282
                    while ((n = serverIn.read(bb)) != -1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   283
                        clientOut.write(bb, 0, n);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   284
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   285
                    serverSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   286
                    clientSocket.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   287
                } catch (IOException e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   288
                    if (debug) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   289
                        System.out.println(e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   290
                        e.printStackTrace();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   291
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   292
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   293
            });
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   294
            out.setName("Proxy-outbound");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   295
            out.setDaemon(true);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   296
            in.setDaemon(true);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   297
            in.setName("Proxy-inbound");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   298
            out.start();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   299
            in.start();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   300
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   301
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   302
        void doTunnel(String dest) throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   303
            commonInit(dest, 443);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   304
            clientOut.write("HTTP/1.1 200 OK\r\n\r\n".getBytes());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   305
            proxyCommon();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   306
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   307
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   308
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   309
    public static void main(String[] args) throws Exception {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   310
        int port = Integer.parseInt(args[0]);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   311
        boolean debug = args.length > 1 && args[1].equals("-debug");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   312
        System.out.println("Debugging : " + debug);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   313
        ProxyServer ps = new ProxyServer(port, debug);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   314
        System.out.println("Proxy server listening on port " + ps.getPort());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   315
        while (true) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   316
            Thread.sleep(5000);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   317
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   318
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   319
}