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 + -
显示快捷键?