Package org.w3c.www.protocol.http.icp

Source Code of org.w3c.www.protocol.http.icp.ICPFilter

// 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.HTML

package 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);
    }

}
TOP

Related Classes of org.w3c.www.protocol.http.icp.ICPFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.