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

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