icpfilter.java
来自「很棒的web服务器源代码」· Java 代码 · 共 363 行
JAVA
363 行
// ICPFilter.java// $Id: ICPFilter.java,v 1.13 2000/08/16 21:38:04 ylafon Exp $// (c) COPYRIGHT MIT and INRIA, 1996.// please first read the full copyright statement in file COPYRIGHT.HTMLpackage org.w3c.www.protocol.http.icp;import java.util.Hashtable;import java.util.StringTokenizer;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.MalformedURLException;import java.net.SocketException;import java.net.URL;import java.net.UnknownHostException;import java.io.BufferedInputStream;import java.io.DataInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FilterInputStream;import java.io.IOException;import java.io.PrintStream;import org.w3c.util.ObservableProperties;import org.w3c.util.PropertyMonitoring;import org.w3c.www.protocol.http.HttpException;import org.w3c.www.protocol.http.HttpManager;import org.w3c.www.protocol.http.PropRequestFilter;import org.w3c.www.protocol.http.PropRequestFilterException;import org.w3c.www.protocol.http.Reply;import org.w3c.www.protocol.http.Request;import org.w3c.www.protocol.http.cache.CacheFilter;public class ICPFilter implements PropRequestFilter, PropertyMonitoring { /** * Properties - Our debug flag. */ public static final String DEBUG_P = "org.w3c.www.protocol.http.icp.debug"; /** * Properties - Our configuration file. */ public static final String CONFIG_P = "org.w3c.www.protocol.http.icp.config"; /** * Properties - Our own UDP port number. */ public static final String PORT_P = "org.w3c.www.protocol.http.icp.port"; /** * Properties - Our default timeout value. */ public static final String TIMEOUT_P = "org.w3c.www.protocol.http.icp.timeout"; /** * Properties - disable caching when fetching from a neighbour proxy. */ public static final String DISABLE_CACHE_P = "org.w3c.www.protocol.http.icp.disable-cache"; /** * The properties we are initialized from. */ protected ObservableProperties props = null; /** * Our ICP engine. */ protected ICPReceiver icp = null; /** * Our ICP neighbors. */ ICPSender senders[] = null; /** * Our senders, indexed by InetAddress. */ protected Hashtable friends = null; /** * Our default timeout value for waiting for replies (in ms). */ protected long timeoutValue = 500; /** * Our we in debug mode ? */ protected boolean debug = false; /** * Our sending and source port. */ int port = -1; /** * Should we disablecaching when fetching through a proxy ? */ protected boolean disableCache = true; public boolean propertyChanged(String name) { System.out.println("ICPFilter:"+name+": property changed."); return true; } protected DatagramSocket getSocket() { return icp.getSocket(); } protected void createICPSender(String host, int dstport, String http) throws UnknownHostException, MalformedURLException, SocketException { InetAddress addr = InetAddress.getByName(host); URL url = new URL(http); ICPSender sender = new ICPSender(this, port, addr, dstport, url); // Add it to the array of senders: if ( senders == null ) { senders = new ICPSender[1]; senders[0] = sender; } else { ICPSender ns[] = new ICPSender[senders.length+1]; System.arraycopy(senders, 0, ns, 0, senders.length); ns[senders.length] = sender; senders = ns; } // Add it to our hashtable of hosts: byte baddr[] = addr.getAddress(); Long key = new Long((((long) dstport) << 32) + ((baddr[0] & 0xff) << 24) + ((baddr[1] & 0xff) << 16) + ((baddr[2] & 0xff) << 8) + (baddr[3] & 0xff)); friends.put(key, sender); if ( debug ) System.out.println("icp: friend "+key+" http="+http); } /** * Parse the configuration file. */ protected void parseConfiguration() { DataInputStream in = null; String host = null; int port = -1; String http = null; File file = props.getFile(CONFIG_P, new File("icp.conf")); try { in = (new DataInputStream (new BufferedInputStream (new FileInputStream(file)))); } catch (IOException ex) { System.out.println("*** ICP, unable to read config file " + file.getAbsolutePath()); return; } // Parse the file in: try { for (String line = null; (line = in.readLine()) != null; ) { // Syntax (FIXME) // host udp-port http-location // | '#' comments if ( line.startsWith("#") || line.length() == 0 ) continue; StringTokenizer st = new StringTokenizer(line, " \t"); host = st.nextToken(); port = Integer.parseInt(st.nextToken()); http = st.nextToken(); createICPSender(host, port, http); } } catch (Exception ex) { System.out.println("*** ICP, unable to create " + host + "@" + port + "[" + http + "]: " + ex.getMessage()); } finally { try { if ( in != null) in.close(); } catch (IOException ex) {} } } /** * Get the sender object for the given InetAddress instance. * @param addr The InetAddress of the sender. * @return An ICPSender instance, if available, <strong>null</strong> * otherwise. */ public ICPSender getSender(InetAddress addr, int port) { byte baddr[] = addr.getAddress(); Long key = new Long((((long) port) << 32) + ((baddr[0] & 0xff) << 24) + ((baddr[1] & 0xff) << 16) + ((baddr[2] & 0xff) << 8) + (baddr[3] & 0xff)); return (ICPSender) friends.get(key); } /** * Locate the HTTP service of the proxy that has emitted that reply. * @param reply The reply emitted by the host that alos host the HTTP * service we are looking for. * @return The URL of the proxy, or <strong>null</strong> if no matching * proxy was found. */ protected URL locateProxy(ICPReply reply) { ICPSender sender = getSender(reply.getSenderAddress() , reply.getSenderPort()); return (sender != null) ? sender.getProxyLocation() : null; } /** * Send the given query to all our neighbors. * @return The number of times we emitted the query. */ protected int sendQuery(ICPQuery query) { int count = 0; if ( senders != null ) { for (int i = 0 ; i < senders.length ; i++) { if ( debug ) System.out.println("icp: query@" + senders[i].getAddress() + "/" + senders[i].getPort() + " for " + query.getURL()); if ( senders[i].send(query) ) count++; } } return count; } /** * Run the ICP query, and return the proxy we should go to. * @param url The URL we are looking for. * @return The URL of the proxy we should go to for that URL, or <strong> * null</strong> if none was found. */ protected URL runQuery(ICPQuery query) { // Create a new waiter block for this query, and register it: ICPWaiter waiter = new ICPWaiter(query.getIdentifier()); icp.addReplyWaiter(waiter); // Emit the query, and wait for a suitable reply: try { long curtime = -1; long nxttime = -1; long timeout = timeoutValue; int sent = sendQuery(query); while ((sent > 0) && (timeout > 0)) { ICPReply reply = waiter.getNextReply(timeout); if (reply != null) { sent--; if ( reply.isHit() ) { return locateProxy(reply); } } else { // Our timeout has expired, notify failure return null; } nxttime = System.currentTimeMillis(); timeout -= (nxttime -curtime); curtime = nxttime; } } finally { icp.removeReplyWaiter(waiter); } return null; } /** * This filter doesn't handle exceptions. * @param request The request that triggered the exception. * @param ex The triggered exception. * @return Always <strong>false</strong>. */ public boolean exceptionFilter(Request request, HttpException ex) { return false; } /** * Our ingoingFilter method. * This method emits (only for GET requestst currently) an ICP query * to all our neighbors, and wait for either one of them to * reply with a hit, or, our timeout value to expire. * <p>If a hit reply is received, we then use the corresponding proxy * to fullfill the request. * @param request The request that is about to be emitted. * @return Always <strong>null</strong>. */ public Reply ingoingFilter(Request request) { if ( request.getMethod().equals("GET") && ( ! request.hasState(CacheFilter.STATE_NOCACHE) ) && ( ! request.hasState(CacheFilter.STATE_REVALIDATION)) ) { ICPQuery query = icp.createQuery(request.getURL()); URL proxy = runQuery(query); if ( proxy != null ) { if ( debug ) System.out.println("*** routing "+request.getURL() + " to "+proxy); // Disable caching and set proxy: if ( disableCache ) { request.setState(CacheFilter.STATE_NOCACHE, Boolean.TRUE); } request.setProxy(proxy); } } return null; } /** * Our outgoingFilter does nothing (at all). * @param request The request that has been processed. * @param reply The original reply (from origin server) * @return Always <strong>null</strong>. */ public Reply outgoingFilter(Request request, Reply reply) { return null; } /** * This filter doesn't maintain dynamic state. */ public void sync() { return ; } /** * Initialize the ICP filter. * This is where we parse the configuration file in order to know * about our neighbors. We then register ourself to the HTTP manager. * @param manager The HTTP manager. * @exception PropRequestFilterException If the filter cannot * launch its server part (listening for incomming ICP requests) */ public void initialize(HttpManager manager) throws PropRequestFilterException { // Setup our properties: props = manager.getProperties(); props.registerObserver(this); port = props.getInteger(PORT_P, 2005); // Get property values: this.friends = new Hashtable(10); if ( debug = props.getBoolean(DEBUG_P, false) ) System.out.println("["+getClass().getName()+"]: debugging on"); parseConfiguration(); timeoutValue = props.getInteger(TIMEOUT_P, (int) timeoutValue); disableCache = props.getBoolean(DISABLE_CACHE_P, disableCache); // Initialize our ICPReceiver: try { icp = new ICPReceiver(manager, this, port); } catch (SocketException ex) { ex.printStackTrace(); throw new PropRequestFilterException(ex.getMessage()); } if ( debug ) System.out.println("icp: listening on port "+port); manager.setFilter(this); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?