icpserver.pl
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:4k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. #!/usr/local/bin/perl
  2. # parse and answer ICP type 1 requests via unicast/multicast UDP
  3. # cf. <URL:http://excalibur.usc.edu/icpdoc/icp.html>
  4. #
  5. # returns ICP response code, e.g. 2 == HIT, 3 == MISS, 4 == ERROR
  6. # by looking at CERN or Netscape style cache directory $cachedir
  7. #
  8. # martin hamilton <m.t.hamilton@lut.ac.uk>
  9. #  Id: icpserver,v 1.11 1995/11/24 16:20:13 martin Exp martin 
  10. # usage: icpserver [-c cachedir] [-n] [-p port] [multicast_group]
  11. #
  12. # -c    -> set cache directory
  13. # -n    -> use Netscape cache format (default is CERN)
  14. # -p    -> port number to listen on (default 3130)
  15. # -v    -> verbose - writes activitiy log to stderr
  16. #
  17. # group -> multicast group to listen on
  18. require "getopts.pl";
  19. &Getopts("c:np:v");
  20. @CODES=("xxx", "QUERY", "HIT", "MISS", "ERROR");
  21. $CACHEDIR=$opt_c||"/usr/local/www/cache";
  22. $PORT=$opt_p||3130;
  23. $SERVER=$ARGV[0]||"0.0.0.0";
  24. $SERVERIP= ($SERVER =~ m!d+.d+.d+.d+!) ? 
  25.   pack("C4", split(/./, $SERVER)) : (gethostbyname($SERVER))[4]; # lazy!
  26. $SOCKADDR = 'S n a4 x8';
  27. socket(S, 2, 2, 17) || socket(S, 2, 1, 17) || die "Couldn't get socket: $!";
  28. $us1 = pack($SOCKADDR, 2, $PORT, $SERVERIP);
  29. $us2 = pack($SOCKADDR, 2, $PORT, pack("C4", 0,0,0,0));
  30. bind(S, $us1) || bind(S, $us2) || die "Couldn't bind socket: $!";
  31. #bind(S, $us2) || die "Couldn't bind socket: $!";
  32. if ($SERVER ne "0.0.0.0") { # i.e. multicast
  33.   $whoami = (`uname -a`)[0];
  34.   $IP_ADD_MEMBERSHIP=5;
  35.   $whoami =~ /SunOS [^s]+ 5/ && ($IP_MULTICAST_TTL=19);
  36.   $whoami =~ /IRIX [^s]+ 5/ && ($IP_MULTICAST_TTL=23);
  37.   $whoami =~ /OSF1/ && ($IP_MULTICAST_TTL=12);
  38.   # any more funnies ?
  39.   setsockopt(S, 0, $IP_ADD_MEMBERSHIP, $SERVERIP."") 
  40.     || die "Couldn't join multicast group $SERVER: $!";
  41. }
  42. # Common header for ICP datagrams ... (size in bytes - total 20)
  43. #   opcode         1              Numeric code indicating type of message
  44. #   version        1              Version of the protocol being used
  45. #   length         2              Total length of packet
  46. #   reqnum         4              Request number assigned by client
  47. #   authenticator  8              Authentication information (future)
  48. #   senderid       4              Identification (host id) of sender
  49. # Type 1 query ...
  50. #   requester      4              Host id of original requester URL
  51. #   url            variable       URL whose status is to be checked
  52. # Type 2 and 3 responses just contain URL, don't return anything else
  53. # Might be fast enough to get away without forking or non-blocking I/O ... ?
  54. while(1) {
  55.   $theiraddr = recv(S, $ICP_request, 1024, 0);
  56.   ($junk, $junk, $sourceaddr, $junk) = unpack($SOCKADDR, $theiraddr);
  57.   @theirip = unpack('C4', $sourceaddr);
  58.   $URL_length = length($ICP_request) - 24;
  59.   $request_template = 'CCnx4x8x4a4a' . $URL_length;
  60.   ($type, $version, $length, $requester, $URL) = 
  61.     unpack($request_template, $ICP_request);
  62.   $URL =~ s/..///g; # be cautious - any others to watch out for ?
  63.   # lookup object in cache
  64.   $hitmisserr = 3;
  65.   if ($type eq 1 && $URL =~ m!^([^:]+):/?/?([^/]+)/(.*)!) {
  66.     $scheme = $1; $hostport = $2; $path = $3;
  67.     if ($path eq "") { $path = "index.html"; }
  68.     if ($opt_n) {
  69.       ($host, $port) = split(/:/, $hostport); # strip off port number
  70.       $port = ":$port" if ($port);
  71.       $match = "";
  72.       foreach (split(/./, $hostport)) {
  73.         $match = "$_/$match"; # little-endian -> big-endian conversion
  74.       }
  75.       $match = "$CACHEDIR/hosts/$match$scheme$port.urls"; # full path
  76.       if (-f "$match") {
  77.         #### optimize! ####
  78.         open(IN, "$match") && do {
  79.           while(<IN>) { /^$URL / && ($hitmisserr = 2, last); }
  80.           close(IN);
  81.         }
  82.       }
  83.     } else {
  84.       $hitmisserr = 2 if -f "$CACHEDIR/$scheme/$hostport/$path";
  85.     }
  86.   }
  87.   
  88.   print "$type $hitmisserr ", join(".", @theirip), " $URLn" if $opt_v;
  89.   $response_template = 'CCnx4x8x4A' . length($URL);
  90.   $ICP_response = 
  91.     pack($response_template, $hitmisserr, 2, 20 + length($URL), $URL);
  92.   send(S, $ICP_response, 0, $theiraddr) || die "Couldn't send request: $!";
  93. }