home *** CD-ROM | disk | FTP | other *** search
/ ftp.madoka.org / 2014.12.ftp.madoka.org.tar / ftp.madoka.org / pub / plum / 2.x / plum2_28_2.lzh / support / httpgate < prev    next >
Text File  |  1998-10-15  |  10KB  |  370 lines

  1. #!/bin/perl -w
  2. # $Id: httpgate,v 2.12 1998/10/06 04:22:26 hasegawa Exp $
  3. # copyright (c)1998 pupu_j <hasegawa@agusa.nuie.nagoya-u.ac.jp>
  4.  
  5. if ($] < 5) {
  6.   foreach $inc (@INC) {
  7.     if (-r "$inc/sys/socket.ph") {
  8.       eval { require 'sys/socket.ph' };
  9.       $SOCKET = "$inc/sys/socket.ph" unless $@;
  10.       last;
  11.     }
  12.     if (-r "$inc/socket.ph") {
  13.       eval { require 'socket.ph' };
  14.       $SOCKET = "$inc/socket.ph" unless $@;
  15.       last;
  16.     }
  17.   }
  18. } else {
  19.   eval 'use Socket';
  20.   $SOCKET = 'Socket.pm' unless $@;
  21. }
  22.  
  23. $NIL = $;;
  24.  
  25. $READSIZE = 4096;
  26. $SOCKADDR = 'S n N x8';
  27.  
  28. $PROTO = getprotobyname('tcp');
  29.  
  30. $AF_INET = eval { &AF_INET } || 2;
  31. $PF_INET = eval { &PF_INET } || 2;
  32. $SOCK_STREAM = eval { &SOCK_STREAM } || 1;
  33. $SOMAXCONN = eval { &SOMAXCONN } || 16;
  34. $INADDR_ANY = eval { &INADDR_ANY } || "\0\0\0\0";
  35. $SOL_SOCKET = eval { &SOL_SOCKET};
  36. $SO_REUSEADDR = eval { &SO_REUSEADDR };
  37.  
  38. $'rin = '';
  39.  
  40. $handle = 0;
  41.  
  42. $SIG{'PIPE'} = 'IGNORE' if &'exist(&'list(keys(%SIG)), 'PIPE');
  43.  
  44. $TIMEOUT = 3600;
  45.  
  46. &main(@ARGV);
  47.  
  48. sub main {
  49.   local(@args) = @_;
  50.   local($rout, $listenno, $nf);
  51.   if (@args < 1) {
  52.     &usage();
  53.     exit(1);
  54.   }
  55.   $listenno = &'listen($args[0], 0) || die "cannot listen port\n";
  56.   for (;;) {
  57.     $nf = select($rout = $'rin, undef, undef, undef);
  58.     die "error in select\n" if $nf < 0;
  59.     foreach $cno (&'array($httpclientlist)) {
  60.       if (vec($rout, $cno, 1)) {
  61.         &http_client($cno);
  62.       } elsif ($'access[$cno] - time() > $TIMEOUT) {
  63.         &http_close($cno);
  64.       }
  65.     }
  66.     foreach $cno (&'array($socketclientlist)) {
  67.       &socket_client($cno) if vec($rout, $cno, 1);
  68.     }
  69.     foreach $sno (&'array($socketserverlist)) {
  70.       &socket_server($sno) if vec($rout, $sno, 1);
  71.     }
  72.     foreach $lno (&'array($socketlistenlist)) {
  73.       if (vec($rout, $lno, 1)) {
  74.         &socket_accept($lno);
  75.       } elsif ($'access[$lno] - time() > $TIMEOUT) {
  76.         &'close($lno);
  77.         $socketlistenlist = &'remove($socketlistenlist, $lno);
  78.         &'close($peer[$lno]);
  79.         $httpclientlist = &'remove($httpclientlist, $peer[$lno]);
  80.         $peer[$peer[$lno]] = 0;
  81.         $peer[$lno] = 0;
  82.       }
  83.     }
  84.     &http_accept($listenno) if vec($rout, $listenno, 1);
  85.   }
  86. }
  87.  
  88. sub http_client {
  89.   local($clientno) = @_;
  90.   local($tmp, $socket, $next, $rest, $method, $url, $lno, $sno, $host, $port);
  91.   $tmp = '';
  92.   if (sysread($'socket[$clientno], $tmp, $READSIZE)) {
  93.     if ($http[$clientno]) {
  94.       $socket = $'socket[$clientno];
  95.       $rbuf[$clientno] .= $tmp;
  96.       while ((($next, $rest) = split(/\r\n/, $rbuf[$clientno], 2)) == 2) {
  97.         $rbuf[$clientno] = $rest;
  98.         if ($next) {
  99.           $request[$clientno] = &'add($request[$clientno], $next);
  100.         } else {
  101.           ($method, $url) = split(/\s+/, (&'array($request[$clientno]))[0]);
  102.           if ($method eq 'HEAD') {
  103.             $port = (split(/\//, $url))[1];
  104.             if ($lno = &'listen($port, 1)) {
  105.               print $socket 'HTTP/1.0 201 Created', "\r\n";
  106.               $host = (&'sockname($clientno))[1];
  107.               $port = (&'sockname($lno))[0];
  108.               print $socket 'Listen: ', $host, '/', $port, "\r\n";
  109.               print $socket "\r\n";
  110.               $peer[$clientno] = $lno;
  111.               $peer[$lno] = $clientno;
  112.               $socketlistenlist = &'add($socketlistenlist, $lno);
  113.               $request[$clientno] = '';
  114.             } else {
  115.               print $socket 'HTTP/1.0 403 Forbidden', "\r\n";
  116.               print $socket "\r\n";
  117.               &http_close($clientno);
  118.               last;
  119.             }
  120.           } elsif ($method eq 'POST') {
  121.             if ($peer[$clientno]) {
  122.               $http[$clientno] = 0;
  123.               $httpclientlist = &'remove($httpclientlist, $clientno);
  124.             } else {
  125.               ($host, $port) = (split(/\//, $url))[1, 2];
  126.               if ($host && $port) {
  127.                 if ($sno = &'connect($host, $port)) {
  128.                   print $socket 'HTTP/1.0 204 No Content', "\r\n";
  129.                   print $socket "\r\n";
  130.                   $peer[$clientno] = $sno;
  131.                   $peer[$sno] = $clientno;
  132.                   $http[$clientno] = 0;
  133.                   $socketserverlist = &'add($socketserverlist, $sno);
  134.                   $socket = $'socket[$sno];
  135.                   print $socket $rbuf[$clientno];
  136.                 } else {
  137.                   print $socket 'HTTP/1.0 404 Not Found', "\r\n";
  138.                   print $socket "\r\n";
  139.                   &http_close($clientno);
  140.                   last;
  141.                 }
  142.               } else {
  143.                 print $socket 'HTTP/1.0 400 Bad Request', "\r\n";
  144.                 print $socket "\r\n";
  145.                 &http_close($clientno);
  146.                 last;
  147.               }
  148.             }
  149.           } else {
  150.             print $socket 'HTTP/1.0 501 Not Implemented', "\r\n";
  151.             print $socket "\r\n";
  152.             &http_close($clientno);
  153.             last;
  154.           }
  155.         }
  156.       }
  157.       $rbuf[$clientno] = $next || '';
  158.     } else {
  159.       $socket = $'socket[$peer[$clientno]];
  160.       print $socket $tmp if fileno($socket);
  161.     }
  162.   } else {
  163.     &http_close($clientno);
  164.   }
  165. }
  166.  
  167. sub socket_client {
  168.   local($clientno) = @_;
  169.   local($tmp, $socket);
  170.   $tmp = '';
  171.   if (sysread($'socket[$clientno], $tmp, $READSIZE)) {
  172.     $socket = $'socket[$peer[$clientno]];
  173.     print $socket $tmp if fileno($socket);
  174.   } else {
  175.     &'close($clientno);
  176.     $socketclientlist = &'remove($socketclientlist, $clientno);
  177.     &'close($peer[$clientno]);
  178.     $httpclientlist = &'remove($httpclientlist, $peer[$clientno]);
  179.     $peer[$peer[$clientno]] = 0;
  180.     $peer[$clientno] = 0;
  181.   }
  182. }
  183.  
  184. sub http_close {
  185.   local($clientno) = @_;
  186.   &'close($clientno);
  187.   $httpclientlist = &'remove($httpclientlist, $clientno);
  188.   if ($peer[$clientno]) {
  189.     &'close($peer[$clientno]);
  190.     $socketlistenlist = &'remove($socketlistenlist, $peer[$clientno]);
  191.     $socketclientlist = &'remove($socketclientlist, $peer[$clientno]);
  192.     $socketserverlist = &'remove($socketserverlist, $peer[$clientno]);
  193.     $peer[$peer[$clientno]] = 0;
  194.     $peer[$clientno] = 0;
  195.   }
  196. }
  197.  
  198. sub socket_server {
  199.   local($serverno) = @_;
  200.   local($tmp, $socket);
  201.   $tmp = '';
  202.   if (sysread($'socket[$serverno], $tmp, $READSIZE)) {
  203.     $socket = $'socket[$peer[$serverno]];
  204.     print $socket $tmp if fileno($socket);
  205.   } else {
  206.     &'close($serverno);
  207.     $socketserverlist = &'remove($socketserverlist, $serverno);
  208.     &'close($peer[$serverno]);
  209.     $httpclientlist = &'remove($httpclientlist, $peer[$serverno]);
  210.     $peer[$peer[$serverno]] = 0;
  211.     $peer[$serverno] = 0;
  212.   }
  213. }
  214.  
  215. sub socket_accept {
  216.   local($listenno) = @_;
  217.   local($cno, $socket);
  218.   if ($cno = &'accept($listenno)) {
  219.     $socket = $'socket[$peer[$listenno]];
  220.     print $socket 'HTTP/1.0 202 Accepted', "\r\n";
  221.     print $socket "\r\n";
  222.     $peer[$cno] = $peer[$listenno];
  223.     $peer[$peer[$cno]] = $cno;
  224.     $socketclientlist = &'add($socketclientlist, $cno);
  225.     $httpclientlist = &'add($httpclientlist, $peer[$cno]);
  226.     $socket = $'socket[$cno];
  227.     print $socket $rbuf[$peer[$cno]];
  228.   }
  229.   &'close($listenno);
  230.   $socketlistenlist = &'remove($socketlistenlist, $listenno);
  231. }
  232.  
  233. sub http_accept {
  234.   local($listenno) = @_;
  235.   local($cno);
  236.   if ($cno = &'accept($listenno)) {
  237.     $httpclientlist = &'add($httpclientlist, $cno);
  238.     $http[$cno] = 1;
  239.     $rbuf[$cno] = '';
  240.     $peer[$cno] = 0;
  241.     $request[$cno] = '';
  242.   }
  243. }
  244.  
  245. sub usage {
  246.   print 'usage: perl httpgate <port>', "\n";
  247. }
  248.  
  249. sub 'connect {
  250.   local($host, $port) = @_;
  251.   local($serverno, $socket, $ip, @addr, $name);
  252.   if ($host =~ /^\d+$/) {
  253.     $ip = $host;
  254.   } elsif ($host =~ /^[\d\.]+$/) {
  255.     @addr = split(/\./, $host);
  256.     $ip = unpack('N', pack('C4', @addr, 0, 0, 0));
  257.   } else {
  258.     $ip = unpack('N', (gethostbyname($host))[4] || "\0\0\0\0");
  259.   }
  260.   return 0 unless $ip;
  261.   $socket = '\'S' . ++$handle;
  262.   socket($socket, $PF_INET, $SOCK_STREAM, $PROTO) || return 0;
  263.   $name = pack($SOCKADDR, $AF_INET, $port, $ip);
  264.   connect($socket, $name) || return 0;
  265.   $serverno = fileno($socket);
  266.   vec($'rin, $serverno, 1) = 1;
  267.   $'socket[$serverno] = $socket;
  268.   select((select($socket), $| = 1)[0]);
  269.   $'access[$serverno] = time();
  270.   return $serverno;
  271. }
  272.  
  273. sub 'listen {
  274.   local($port, $count) = @_;
  275.   local($listenno, $socket, $name);
  276.   $socket = '\'L' . ++$handle;
  277.   socket($socket, $PF_INET, $SOCK_STREAM, $PROTO) || return 0;
  278.   if (defined($SOL_SOCKET) && defined($SO_REUSEADDR)) {
  279.     setsockopt($socket, $SOL_SOCKET, $SO_REUSEADDR, pack('l', 1));
  280.   }
  281.   $name = pack($SOCKADDR, $AF_INET, $port, unpack('N', $INADDR_ANY));
  282.   bind($socket, $name) || return 0;
  283.   listen($socket, $count || $SOMAXCONN) || return 0;
  284.   $listenno = fileno($socket);
  285.   vec($'rin, $listenno, 1) = 1;
  286.   $'socket[$listenno] = $socket;
  287.   select((select($socket), $| = 1)[0]);
  288.   $'access[$listenno] = time();
  289.   return $listenno;
  290. }
  291.  
  292. sub 'accept {
  293.   local($listenno) = @_;
  294.   local($clientno, $socket);
  295.   $socket = '\'C' . ++$handle;
  296.   accept($socket, $'socket[$listenno]) || return 0;
  297.   $clientno = fileno($socket);
  298.   vec($'rin, $clientno, 1) = 1;
  299.   $'socket[$clientno] = $socket;
  300.   select((select($socket), $| = 1)[0]);
  301.   $'access[$clientno] = time();
  302.   return $clientno;
  303. }
  304.  
  305. sub 'close {
  306.   local($no) = @_;
  307.   close($'socket[$no]);
  308.   vec($'rin, $no, 1) = 0;
  309. }
  310.  
  311. sub 'sockname {
  312.   local($no) = @_;
  313.   local($port, $ip, $host);
  314.   ($port, $ip) = (unpack($SOCKADDR, getsockname($'socket[$no])))[1, 2];
  315.   $host = (gethostbyaddr(pack('N', $ip), $AF_INET))[0];
  316.   return ($port, $ip, $host);
  317. }
  318.  
  319. sub 'add {
  320.   local($list, @items) = @_;
  321.   $list = $NIL unless $list;
  322.   foreach $item (@items) {
  323.     next if &'exist($list, $item);
  324.     $list = $list . $item . $NIL;
  325.   }
  326.   $list = '' if $list eq $NIL;
  327.   return $list;
  328. }
  329.  
  330. sub 'remove {
  331.   local($list, @items) = @_;
  332.   local($idx);
  333.   $list = $NIL unless $list;
  334.   foreach $item (@items) {
  335.     $idx = index("\L$list\E", $NIL . "\L$item\E" . $NIL);
  336.     next if $idx == -1;
  337.     substr($list, $idx, length($NIL . $item . $NIL)) = $NIL;
  338.   }
  339.   $list = '' if $list eq $NIL;
  340.   return $list;
  341. }
  342.  
  343. sub 'exist {
  344.   local($list, @items) = @_;
  345.   return 0 unless $list;
  346.   foreach $item (@items) {
  347.     return 1 if index("\L$list\E", $NIL . "\L$item\E" . $NIL) != -1;
  348.   }
  349.   return 0;
  350. }
  351.  
  352. sub 'list {
  353.   local(@array) = @_;
  354.   local($list);
  355.   if (scalar(@array)) {
  356.     $list = $NIL . join($NIL, @array) . $NIL;
  357.   } else {
  358.     $list = '';
  359.   }
  360.   return $list;
  361. }
  362.  
  363. sub 'array {
  364.   local($list) = @_;
  365.   $list = $NIL unless $list;
  366.   return () if $list eq $NIL;
  367.   $list = substr($list, 1, length($list) - 2);
  368.   return split(/$NIL/, $list);
  369. }
  370.