Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

227
LINES

< > BotCompany Repo | #1002822 // HTTP Proxy (with partial close, OK)

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Libraryless. Click here for Pure Java version (5434L/32K/107K).

1  
!7
2  
3  
static S vmArgs = "-XX:+PrintGC -Xmx32m";
4  
static boolean debug = false;
5  
6  
static int port = 80;
7  
static S forwardServer = "localhost";
8  
9  
static Map<S, Integer> forwardMap = litmap(
10  
  "thedevchannel.com", 3000,
11  
  "default", 8081);
12  
  
13  
static L<S> blockedIPs = litlist("41.193.22.107");
14  
15  
p {
16  
  // Safety Rebooter - to hold up thedevchannel.com and ai1.lol when admin sleeps!
17  
  
18  
  thread "Rebooter" {
19  
    sleepSeconds(60*60*24);
20  
    nohupJavax(programID(), vmArgs);
21  
    System.exit(0);
22  
  }
23  
  
24  
  // turn off memory leak
25  
  
26  
  noPrintLog();
27  
  
28  
  // Some regular GC to see accurate mem stats
29  
  
30  
  thread "Auto GC" {
31  
    while true {
32  
      sleepSeconds(60*10);
33  
      System.gc();
34  
    }
35  
  }
36  
  
37  
  // Now for the actual server...
38  
  
39  
  final ServerSocket serverSocket = new ServerSocket(port);
40  
41  
  Thread thread = new Thread("HTTP Proxy Accept Port " + port) { public void run() {
42  
   try {
43  
    while (true) {
44  
      try {
45  
        final Socket s = serverSocket.accept();
46  
        
47  
        /*thread "Lister" {
48  
          sleepSeconds(5);
49  
          listThreads();
50  
        }*/
51  
        
52  
        final S client = dropPrefix("/", s.getInetAddress().toString()); // Hmm... how to get the actual IP properly?
53  
        String threadName = "PROXY: Handling client " + client;
54  
        
55  
        if (blockedIPs.contains(client)) {
56  
          print("Blocked IP!! " + client);
57  
          pcall { s.close(); }
58  
          continue;
59  
        }
60  
61  
        Thread t2 = new Thread(threadName) {
62  
          public void run() ctex {
63  
            Socket outSocket = null;
64  
            final new AtomicLong transmitted;
65  
            final new AtomicLong outTransmitted;
66  
            try {
67  
              print("HTTP Proxy Incoming!");
68  
              
69  
              final OutputStream out = s.getOutputStream();
70  
              final InputStream in = s.getInputStream();
71  
              
72  
              // collect headers
73  
              
74  
              new ByteArrayOutputStream headersOut;
75  
              //BufferedReader headerReader = new BufferedReader(new InputStreamReader(in, "US-ASCII"), 1);
76  
              boolean forwardedFor = false;
77  
              S host = null;
78  
              while (true) {
79  
                S line = readHeaderLine(in);
80  
                if (line == null) ret;
81  
                print("Header line read: " + quote(line));
82  
                
83  
                if (startsWithIgnoreCase(line, "Host:"))
84  
                  host = dropPrefixIgnoreCase("Host:", line).trim();
85  
                else {
86  
                  S rewritten;
87  
                  if (startsWithIgnoreCase(line, "X-Forwarded-For:")) {
88  
                    forwardedFor = true;
89  
                    rewritten = line + ", " + client;
90  
                  } else
91  
                    rewritten = empty(line) ? line : rewriteHeaderLine(line);
92  
                  if (!eq(rewritten, line))
93  
                    print("Rewritten as: " + quote(rewritten));
94  
                  if (nempty(rewritten)) {
95  
                    byte[] bytes = (rewritten + "\r\n").getBytes("US-ASCII");
96  
                    //print("Sending: " + bytesToHex(bytes));
97  
                    headersOut.write(bytes);
98  
                  }
99  
                }
100  
                
101  
                if (l(line) == 0)
102  
                  break;
103  
              }
104  
              
105  
              int port = getForwardPort(host);
106  
              
107  
              outSocket = new Socket(forwardServer, port);
108  
final Socket outS = outSocket;
109  
              print("Connected to " + forwardServer + ":" + port);
110  
              final OutputStream outOut = outSocket.getOutputStream();
111  
              final InputStream outIn = outSocket.getInputStream();
112  
              
113  
              outOut.write(headersOut.toByteArray());
114  
              
115  
              if (!forwardedFor)
116  
                headerSend(outOut, "X-Forwarded-For: " + client);
117  
                
118  
              headerSend(outOut, "Host: " + addPortToHost(host, port));
119  
              
120  
              headerSend(outOut, ""); // end of headers
121  
                
122  
              outOut.flush();
123  
              
124  
              // forward content in both directions
125  
              
126  
              //copyStream(outIn, out);
127  
              
128  
              Thread inThread = new Thread("Proxy In") {
129  
                public void run() ctex {
130  
                  try {
131  
byte[] buf = new byte[1];
132  
                  while (true) {
133  
                    int n = outIn.read(buf);
134  
                    if (n <= 0) return;
135  
                    out.write(buf, 0, n);
136  
                    long t = transmitted.addAndGet(n);
137  
                    if (t % 100000 == 0) print("Transmitted to client: " + t);
138  
                  }
139  
} finally {
140  
print("Shutting down client output.");
141  
s.shutdownOutput();
142  
}
143  
                }
144  
              };
145  
              inThread.start();
146  
              
147  
              Thread outThread = new Thread("Proxy Out") {
148  
                public void run() ctex {
149  
try {
150  
                  print("Proxy Out started.");
151  
                  byte[] buf = new byte[1];
152  
                  while (true) {
153  
                    int n = in.read(buf);
154  
                    if (n <= 0) return;
155  
                    outOut.write(buf, 0, n);
156  
                    if (outTransmitted.get() == 0)
157  
                      print("Proxy Out first byte!");
158  
                    long t = outTransmitted.addAndGet(n);
159  
                    if (t % (debug ? 10 : 100000) == 0) print("Transmitted to server: " + t);
160  
                  }
161  
} finally {
162  
  print("Shutting down server output.");
163  
  outS.shutdownOutput();
164  
}
165  
                }
166  
              };
167  
              outThread.start();
168  
              
169  
              inThread.join();
170  
              outThread.join();
171  
            } catch (IOException e) {
172  
              print("[internal] " + e);
173  
            } finally {
174  
              print("Proxy request done, got " + transmitted.get() + ", sent " + outTransmitted.get() + " + headers");
175  
              pcall { s.close(); }
176  
              pcall { if (outSocket != null) outSocket.close(); }
177  
            }
178  
          }
179  
        }; // Thread t2
180  
        t2.setDaemon(true);
181  
        t2.start();
182  
      } catch (SocketTimeoutException e) {
183  
      }
184  
    }   
185  
   } catch (IOException e) {
186  
     print("[internal] " + e);
187  
   }
188  
  }};
189  
  thread.start();
190  
 
191  
  print("HTTP proxy on port " + port + " started."); 
192  
}
193  
194  
static S rewriteHeaderLine(S line) {
195  
  /*if (startsWithIgnoreCase(line, "Host:"))
196  
    line = "Host: " + forwardServer + ":" + forwardPort;*/
197  
  ret line;
198  
}
199  
200  
static int getForwardPort(S host) {
201  
  int i = host.indexOf(':');
202  
  if (i >= 0)
203  
    host = host.substring(0, i);
204  
  host = host.toLowerCase();
205  
  for (S key : forwardMap.keySet())
206  
    if (eq(host, key) || host.endsWith("." + key))
207  
      ret forwardMap.get(key);
208  
  ret forwardMap.get("default");
209  
}
210  
211  
svoid headerSend(OutputStream out, S header) ctex {
212  
  print("Sending header: " + header);
213  
  out.write((header + "\r\n").getBytes("US-ASCII"));
214  
}
215  
216  
static String readHeaderLine(InputStream inputStream) throws IOException {
217  
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
218  
    int c;
219  
    for (c = inputStream.read(); c != '\n' && c != -1 ; c = inputStream.read()) {
220  
        if (c != '\r')
221  
          byteArrayOutputStream.write(c);
222  
    }
223  
    if (c == -1 && byteArrayOutputStream.size() == 0) {
224  
        return null;
225  
    }
226  
    ret byteArrayOutputStream.toString("US-ASCII");
227  
}

Author comment

Began life as a copy of #1002783

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, jtubtzbbkimh, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1002822
Snippet name: HTTP Proxy (with partial close, OK)
Eternal ID of this version: #1002822/5
Text MD5: e820ec479ced0d5428a4dbebb2c328ef
Transpilation MD5: ed270d33b9ca8b3d2cfba60b3fd974b0
Author: stefan
Category: eleu
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-10-03 17:39:40
Source code size: 7495 bytes / 227 lines
Pitched / IR pitched: No / No
Views / Downloads: 751 / 1190
Version history: 4 change(s)
Referenced in: [show references]