sslhandler.java
来自「一款Java实现的HTTP代理服务器」· Java 代码 · 共 238 行
JAVA
238 行
package rabbit.proxy;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import rabbit.http.HttpHeader;import rabbit.io.WebConnection;import rabbit.io.WebConnectionListener;import rabbit.util.Coder;import rabbit.util.Logger;/** A handler that shuttles ssl traffic * * @author <a href="mailto:robo@khelekore.org">Robert Olofsson</a> */class SSLHandler implements TunnelDoneListener { private HttpProxy proxy; private Connection con; private TrafficLoggerHandler tlh; private HttpHeader request; private SocketChannel channel; private Selector selector; private ByteBuffer buffer; private WebConnection wc; public SSLHandler (HttpProxy proxy, Connection con, HttpHeader request, TrafficLoggerHandler tlh) { this.proxy = proxy; this.con = con; this.request = request; this.tlh = tlh; } /** Are we allowed to proxy ssl-type connections ? * @return true if we allow the CONNECT <port> command. */ public boolean isAllowed () { String hp = request.getRequestURI (); int c = hp.indexOf (':'); Integer port = new Integer (443); if (c >= 0) { try { port = new Integer (hp.substring (c+1)); } catch (NumberFormatException e) { getLogger ().logWarn ("Connect to odd port: " + e); return false; } } if (proxy.proxySSL == false) return false; if (proxy.proxySSL == true && proxy.sslports == null) return true; for (int i = 0; i < proxy.sslports.size (); i++) { if (port.equals (proxy.sslports.get (i))) return true; } return false; } /** handle the tunnel. * @param channel the client channel * @param selector the proxy selector * @param buffer the buffer used, may contain data from client. */ public void handle (SocketChannel channel, Selector selector, ByteBuffer buffer) { this.channel = channel; this.selector = selector; this.buffer = buffer; if (proxy.isProxyConnected ()) { String auth = proxy.getProxyAuthString (); // it should look like this (using RabbIT:RabbIT): // Proxy-authorization: Basic UmFiYklUOlJhYmJJVA== request.setHeader ("Proxy-authorization", "Basic " + Coder.uuencode (auth)); } WebConnectionListener wcl = new WebConnector (); proxy.getWebConnection (request, wcl); } private class WebConnector implements WebConnectionListener { private String uri; public WebConnector () { uri = request.getRequestURI (); // java needs protocoll to build URL request.setRequestURI ("http://" + uri); } public void connectionEstablished (WebConnection wce) { wc = wce; if (proxy.isProxyConnected ()) { request.setRequestURI (uri); // send correct connect to next proxy. setupChain (); } sendOkReplyAndTunnel (null); } public void timeout () { String err = "SSLHandler: Timeout waiting for web connection"; getLogger ().logWarn (err); closeDown (); } public void failed (Exception e) { String err = "SSLHandler: failed to get web connection: " + e; getLogger ().logWarn (err); closeDown (); } } private Logger getLogger () { return proxy.getLogger (); } private ConnectionLogger getConnectionLogger () { return proxy.getConnectionLogger (); } private void closeDown () { if (wc != null) { try { wc.close (); } catch (IOException e) { getLogger ().logWarn ("failed to close webconnection: " + e); } wc = null; } con.logAndClose (null); } private void setupChain () { HttpResponseListener cr = new ChainResponseHandler (); try { HttpResponseReader sender = new HttpResponseReader (wc.getChannel (), selector, proxy.getLogger (), tlh.getNetwork (), request, proxy.getStrictHttp (), proxy.isProxyConnected (), cr); } catch (IOException e) { String err = "IOException when waiting for chained response: " + e; getLogger ().logWarn (err); closeDown (); } } private class ChainResponseHandler implements HttpResponseListener { public void httpResponse (HttpHeader response, ByteBuffer buffer, boolean keepalive, boolean isChunked, long dataSize) { String status = response.getStatusCode (); if (!"200".equals (status)) { closeDown (); } else { sendOkReplyAndTunnel (buffer); } } public void failed (Exception cause) { String err = "SSLHandler: failed to get chained response"; getLogger ().logWarn (err); closeDown (); } public void timeout () { String err = "SSLHandler: Timeout waiting for chained response"; getLogger ().logWarn (err); closeDown (); } } private void sendOkReplyAndTunnel (ByteBuffer server2client) { HttpHeader reply = new HttpHeader (); reply.setStatusLine ("HTTP/1.0 200 Connection established"); reply.setHeader ("Proxy-agent", proxy.getServerIdentity ()); HttpHeaderSentListener tc = new TunnelConnected (server2client); try { HttpHeaderSender sender = new HttpHeaderSender (channel, selector, proxy.getLogger (), tlh.getClient (), reply, false, tc); } catch (IOException e) { getLogger ().logWarn ("IOException when sending header: " + e); closeDown (); } } private class TunnelConnected implements HttpHeaderSentListener { private ByteBuffer server2client; public TunnelConnected (ByteBuffer server2client) { this.server2client = server2client; } public void httpHeaderSent () { tunnelData (server2client); } public void timeout () { String err = "SSLHandler: Timeout when sending http header"; getLogger ().logWarn (err); closeDown (); } public void failed (Exception e) { String err = "SSLHandler: Exception when sending http header: " + e; getLogger ().logWarn (err); closeDown (); } } private void tunnelData (ByteBuffer server2client) { SocketChannel sc = wc.getChannel (); try { Tunnel t1 = new Tunnel (selector, getLogger (), channel, buffer, tlh.getClient (), sc, server2client, tlh.getNetwork (), this); } catch (IOException e) { getLogger ().logWarn ("SSLHandler error setting up tunnels: " + e); closeDown (); } } public void tunnelClosed () { if (wc != null) { con.logAndClose (null); try { wc.close (); } catch (IOException e) { getLogger ().logWarn ("failed to close webconnection: " + e); } } wc = null; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?