isproxy.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:7k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** isproxy.c
  3. **
  4. ** Copyright (c) 1995-1997 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "phttpd.h"
  23. #include <netinet/in.h>
  24. static struct table *proxy_table = NULL;
  25. struct proxy_config
  26. {
  27.     char *url;
  28.     
  29.     char *host;
  30.     char *port;
  31.     char *pattern;
  32.     struct sockaddr_in sin;
  33. };
  34. static int str2proxy_config(char *cmd,
  35.     char *line,
  36.     void *var)
  37. {
  38.     struct proxy_config *pcp;
  39.     char *cp, *url, *host, *port, *pattern;
  40.     
  41.     if (debug)
  42. fprintf(stderr, "str2proxy_config("%s")n", line);
  43.     pcp = s_malloc(sizeof(struct proxy_config));
  44.     url = cmd;
  45.     if (!url)
  46. goto Fail;
  47.     
  48.     host = strtok_r(line, ":", &cp);
  49.     if (!host)
  50. goto Fail;
  51.     
  52.     port = strtok_r(NULL, " t", &cp);
  53.     if (!port)
  54. goto Fail;
  55.     
  56.     pattern = strtok_r(NULL, " t", &cp);
  57.     pcp->url = s_strdup(url);
  58.     pcp->host = s_strdup(host);
  59.     pcp->port = s_strdup(port);
  60.     pcp->pattern = s_strdup(pattern);
  61.     if (fd_mksockaddr_in(pcp->host, pcp->port, &pcp->sin) < 0)
  62. goto Fail;
  63.     
  64.     * (struct proxy_config **) var = pcp;
  65.     if (debug)
  66. fprintf(stderr, "t-> %s %s %s %sn",
  67. pcp->url, pcp->host, pcp->port,
  68. pcp->pattern ? pcp->pattern : "<null>");
  69.     
  70.     return 1;
  71.     
  72.   Fail:
  73.     if (debug)
  74. fprintf(stderr, "t-> Errorn");
  75.     if (pcp->url)
  76. s_free(pcp->url);
  77.     
  78.     if (pcp->host)
  79. s_free(pcp->host);
  80.     
  81.     if (pcp->port)
  82. s_free(pcp->port);
  83.     
  84.     if (pcp->pattern)
  85. s_free(pcp->pattern);
  86.     s_free(pcp);
  87.     return 0;
  88.     
  89. }
  90. char *connect_error_page = NULL;
  91. static struct options isproxy_cfg_table[] =
  92. {
  93.     { "connect-error-page",  T_STRING, &connect_error_page, NULL  },
  94.     
  95.     { "proxy-table",         T_TABLE, &proxy_table, str2proxy_config },
  96.     { NULL,                  -1,       NULL,    NULL }
  97. };
  98. int pm_init(const char **argv)
  99. {
  100.     const char *name = argv[0];
  101.     char *cfg_path, *cp;
  102.     int cfgsize;
  103.     
  104.     if (debug > 1)
  105. fprintf(stderr, "*** isproxy/pm_init("%s") called ***n", name);
  106.     cfgsize = strlen(name)+6;
  107.     cfg_path = s_malloc(cfgsize);
  108.     s_strcpy(cfg_path, cfgsize, name);
  109.     
  110.     cp = strrchr(cfg_path, '.');
  111.     if (cp && strcmp(cp, ".so") == 0)
  112. *cp = '';
  113.     
  114.     s_strcat(cfg_path, cfgsize, ".conf");
  115.     if (config_parse_file(cfg_path, isproxy_cfg_table, 0) < 0)
  116. return -1;
  117.     
  118.     if (config_parse_argv(argv+1, isproxy_cfg_table) < 0)
  119. return -1;
  120.     
  121.     return 0;
  122. }
  123. static void proxy_free(void *p)
  124. {
  125.     struct proxy_config *pcp = (struct proxy_config *) p;
  126.     
  127.     if (pcp->url)
  128. s_free(pcp->url);
  129.     if (pcp->host)
  130. s_free(pcp->host);
  131.     if (pcp->pattern)
  132. s_free(pcp->pattern);
  133.     s_free(pcp);
  134. }
  135. void pm_exit(void)
  136. {
  137.     if (debug > 1)
  138. fprintf(stderr, "*** isproxy/pm_exit() called ***n");
  139.     if (proxy_table)
  140. tbl_free(proxy_table, proxy_free);
  141.     if (connect_error_page)
  142. s_free(connect_error_page);
  143. }
  144. static int send_page(struct connectioninfo *cip, char *page)
  145. {
  146.     return http_redirect(cip, page, NULL, NULL, 302);
  147. }
  148. static void write_data(int fd,
  149.        struct httpinfo *hip,
  150.        char *url,
  151.        char *client_addr,
  152.        char *server_url)
  153. {
  154.     char buf[2048];
  155.     
  156.     fd_printf(fd, "%s %s%s%s%s%sn",
  157. hip->method,
  158. url_quote(url, buf, sizeof(buf), "?", 0), 
  159. hip->request == NULL ? "" : "?",
  160. hip->request == NULL ? "" : hip->request,
  161. hip->version == NULL ? "" : " ",
  162. hip->version == NULL ? "" : hip->version);
  163.     fd_flush(fd);
  164.     
  165.     if (hip->mip)
  166.     {
  167. fd_printf(fd, "Forwarded: by %s/ for %sn",
  168.   server_url, client_addr);
  169. mime_writeheaders(fd, hip->mip);
  170.     
  171. fd_putc('n', fd);
  172.     }
  173.     fd_flush(fd);
  174. }
  175. #define STATUS_RELAYED 200
  176. struct ctinfo
  177. {
  178.     char *url;
  179.     struct proxy_config *result;
  180. };
  181. static int check_table(void *value, void *misc)
  182. {
  183.     struct proxy_config *pcp;
  184.     struct ctinfo *ctp;
  185.     int len;
  186.     
  187.     pcp = (struct proxy_config *) value;
  188.     ctp = (struct ctinfo *) misc;
  189.     
  190.     if (debug)
  191. fprintf(stderr, "Checking %s vs %sn", pcp->url, ctp->url);
  192.     
  193.     len = strlen(pcp->url);
  194.     if (len > (int) strlen(ctp->url))
  195. return 0;
  196.     if (strncmp(pcp->url, ctp->url, len) == 0)
  197.     {
  198. ctp->result = pcp;
  199. return 1;
  200.     }
  201.     return 0;
  202. }
  203. int pm_request(struct connectioninfo *cip)
  204. {
  205.     int sock_fd, i;
  206.     char url_buf[2048];
  207.     struct ctinfo ctb;
  208.     struct proxy_config *pcp;
  209.     char *cp;
  210.     int content_length=-1;
  211.     char *address;
  212.     
  213.     int fd = cip->fd;
  214.     struct httpinfo *hip = cip->hip;
  215.     
  216.     
  217.     if (debug > 1)
  218.     {
  219. fprintf(stderr, "*** isproxy/pm_request() called ***n");
  220. fprintf(stderr, "thip->method = %sn", hip->method);
  221. fprintf(stderr, "thip->url = %sn", hip->url);
  222.     }
  223.     i = 0;
  224.     if (proxy_table == NULL)
  225. return 0;
  226.     ctb.url = hip->url;
  227.     ctb.result = NULL;
  228.     tbl_foreach(proxy_table, check_table, &ctb);
  229.     
  230.     if (ctb.result == NULL)
  231. return 0;
  232.     pcp = ctb.result;
  233.     
  234.     if (pcp->pattern)
  235.     {
  236. if (url_rewrite(hip->url,
  237. pcp->pattern,
  238. url_buf,
  239. sizeof(url_buf)) == NULL)
  240.     return error_not_found(cip);
  241.     }
  242.     else
  243. s_strcpy(url_buf, sizeof(url_buf), hip->url);
  244.     
  245.     if (debug > 2)
  246. fprintf(stderr, "Proxy Connection to %s:%sn",
  247. pcp->host, pcp->port);
  248.     
  249.     sock_fd = fd_connect((struct sockaddr *) &pcp->sin, sizeof(pcp->sin));
  250.     if (sock_fd < 0)
  251.     {
  252. if (connect_error_page)
  253.     return send_page(cip, connect_error_page);
  254. else
  255.     return error_system(cip, "connect");
  256.     }
  257.     address = NULL;
  258.     (void) dns_get(cip->client, NULL, NULL, &address, NULL);
  259.     
  260.     write_data(sock_fd, hip, url_buf, address, cip->sip->url);
  261.     if (hip->mip)
  262.     {
  263.         cp = mime_getheader(hip->mip, "CONTENT-LENGTH", 1);
  264.         if (cp)
  265.             content_length = atoi(cp);
  266.     }
  267.     if ( strcasecmp(hip->method,"POST")==0 ) 
  268. {
  269.      fd_prelay(sock_fd, fd, 1, content_length+1);
  270. }
  271.     else
  272. {
  273.      fd_relay(sock_fd, fd, 1);
  274. }
  275.     
  276.     fd_close(sock_fd);
  277.  
  278.     return STATUS_RELAYED;
  279. }