httpproxy.java
来自「一款Java实现的HTTP代理服务器」· Java 代码 · 共 694 行 · 第 1/2 页
JAVA
694 行
/** Run the proxy in a separate thread. */ public void start () { started = System.currentTimeMillis (); Thread t = new Thread (this, VERSION); running = true; t.start (); } /** Run the proxy in a separate thread. */ public void stop () { // TODO: what level do we want here? getLogger ().logFatal ("HttpProxy.stop() called, shutting down"); closeSocket (); // TODO: wait for remaining connections. // TODO: as it is now, it will just close connections in the middle. executorService.shutdown (); logger.close (); cache.flush (); cache.stop (); running = false; } public void run () { while (running) { while (!accepting || !selector.isOpen ()) { try { // wait for reconfigure Thread.sleep (2 * 1000); } catch (InterruptedException e) { // ignore } } try { int num = selector.select (10 * 1000); if (selector.isOpen ()) { cancelTimeouts (); handleSelects (); runReturnedTasks (); } } catch (IOException e) { logger.logError ("Failed to accept, " + "trying to restart serversocket: " + e); closeSocket (); openSocket (); } catch (Exception e) { logger.logError ("Unknown error: " + e + " attemting to ignore"); e.printStackTrace (); } } } private void cancelTimeouts () throws IOException { long now = System.currentTimeMillis (); for (SelectionKey sk : selector.keys ()) { Object a = sk.attachment (); if (a instanceof String) { // ignore, this is used for status. } else { HandlerRegistration hr = (HandlerRegistration)a; if (hr != null && now - hr.when > 60 * 1000) { cancelKeyAndCloseChannel (sk); hr.handler.timeout (); } } } } /** Close down a client that has timed out. */ private void cancelKeyAndCloseChannel (SelectionKey sk) { sk.cancel (); try { SocketChannel sc = (SocketChannel)sk.channel (); sc.close (); } catch (IOException e) { logger.logError ("failed to shutdown and close socket: " + e); } } private void handleSelects () throws IOException { Set<SelectionKey> selected = selector.selectedKeys (); for (Iterator<SelectionKey> i = selected.iterator (); i.hasNext (); ) { SelectionKey sk = i.next (); Object a = sk.attachment (); if (a != null && a instanceof HandlerRegistration) { HandlerRegistration hr = (HandlerRegistration)a; if (hr != null && hr.handler != null) handle (sk, hr.handler); } else if (a == null) { logger.logWarn ("No handler for:" + sk); } else { // Ok, something is very bad here, try to shutdown the channel // and hope that we handle it ok elsewhere... logger.logError ("Bad handler for:" + sk + ": " + a); sk.cancel (); sk.channel ().close (); } } selected.clear (); } private void handle (SelectionKey sk, SocketHandler handler) { if (handler.useSeparateThread ()) { // need to cancel so that we do not get multiple selects... sk.cancel (); executorService.execute (handler); } else { handler.run (); } } private void runReturnedTasks () { synchronized (returnedTasks) { for (Runnable r : returnedTasks) r.run (); returnedTasks.clear (); } } public void runMainTask (Runnable r) { synchronized (returnedTasks) { returnedTasks.add (r); selector.wakeup (); } } public void runThreadTask (Runnable run) { executorService.execute (run); } public Cache<HttpHeader, HttpHeader> getCache () { return cache; } public Logger getLogger () { return logger; } public long getOffset () { return logger.getOffset (); } public long getStartTime () { return started; } ConnectionLogger getConnectionLogger () { return logger; } ServerSocketChannel getServerSocketChannel () { return ssc; } public Counter getCounter () { return counter; } SocketAccessController getSocketAccessController () { return socketAccessController; } HttpHeaderFilterer getHttpHeaderFilterer () { return httpHeaderFilterer; } public Config getConfig () { return config; } HandlerFactory getHandlerFactory (String mime) { return handlerFactoryHandler.getHandlerFactory (mime); } HandlerFactory getCacheHandlerFactory (String mime) { return handlerFactoryHandler.getCacheHandlerFactory (mime); } public String getVersion () { return VERSION; } public String getServerIdentity () { return serverIdentity; } /** Get the local host. * @return the InetAddress of the host the proxy is running on. */ public InetAddress getHost () { return localhost; } /** Get the port this proxy is using. * @return the port number the proxy is listening on. */ public int getPort () { return port; } /** Get the InetAddress for a given url. * We do dns lookups on a separate thread until we have an * asyncronous dns library. * We jump back on the main thread before telling the listener. */ public void getInetAddress (final URL url, final InetAddressListener ial) { if (isProxyConnected ()) { ial.lookupDone (proxy); return; } Runnable r = new Runnable () { public void run () { try { final InetAddress ia = dnsHandler.getInetAddress (url); runMainTask (new Runnable () { public void run () { ial.lookupDone (ia); } }); } catch (final UnknownHostException e) { runMainTask (new Runnable () { public void run () { ial.unknownHost (e); } }); } } }; executorService.execute (r); } /** Get the port to connect to. * @param port the port we want to connect to. * @return the port to connect to. */ public int getConnectPort (int port) { if (isProxyConnected ()) // are we talking through another proxy? return proxyport; return port; } /** Try hard to check if the given address matches the proxy. * Will use the localhost name and all ip addresses. */ public boolean isSelf (String uhost, int urlport) { if (urlport == getPort ()) { String proxyhost = getHost ().getHostName (); if (uhost.equalsIgnoreCase (proxyhost)) return true; try { Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces(); while (e.hasMoreElements ()) { NetworkInterface ni = e.nextElement (); Enumeration<InetAddress> ei = ni.getInetAddresses (); while (ei.hasMoreElements ()) { InetAddress ia = ei.nextElement (); if (ia.getHostAddress ().equals (uhost)) return true; } } } catch (SocketException e) { logger.logWarn ("failed to get network interfaces: " + e); } } return false; } /** Is this proxy chained to another proxy? * @return true if the proxy is connected to another proxy. */ public boolean isProxyConnected () { return proxy != null; } /** Get the authenticationstring to use for proxy. * @return an authentication string. */ public String getProxyAuthString () { return config.getProperty (getClass ().getName (), "proxyauth"); } /** Get a WebConnection. * @param header the http header to get the host and port from * @param wcl the listener that wants to get the connection. */ public void getWebConnection (HttpHeader header, WebConnectionListener wcl) { conhandler.getConnection (header, wcl); } /** Release a WebConnection so that it may be reused if possible. * @param wc the WebConnection to release. */ public void releaseWebConnection (WebConnection wc) { conhandler.releaseConnection (wc); } /** Mark a WebConnection for pipelining. * @param wc the WebConnection to mark. */ public void markForPipelining (WebConnection wc) { conhandler.markForPipelining (wc); } /** Add a current connection * @param con the connection */ public void addCurrentConnection (Connection con) { connections.add (con); } /** Remove a current connection. * @param con the connection */ public void removeCurrentConnection (Connection con) { connections.remove (con); } /** Get the connection handler. */ public ConnectionHandler getConnectionHandler () { return conhandler; } /** Get all the current connections */ public List<Connection> getCurrentConnections () { return Collections.unmodifiableList (connections); } /** Update the currently transferred traffic statistics. */ protected void updateTrafficLog (TrafficLoggerHandler tlh) { synchronized (this.tlh) { tlh.addTo (this.tlh); } } /** Get the currently transferred traffic statistics. */ public TrafficLoggerHandler getTrafficLoggerHandler () { return tlh; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?