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

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** server.c HTTP Server implementation code.
  3. **
  4. ** Copyright (c) 1994-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 <syslog.h>
  20. #include <errno.h>
  21. #include <string.h>
  22. #define IN_DNS_C
  23. #include "phttpd.h"
  24. struct serverinfo *si_new(void)
  25. {
  26.     struct serverinfo *sip;
  27.     
  28.     sip = s_malloc(sizeof(sip));
  29.     
  30.     mutex_init(&sip->lock, USYNC_THREAD, NULL);
  31.     sip->use = 1;
  32.     sip->host = NULL;
  33.     sip->url = NULL;
  34.     
  35.     sip->port = -1;
  36.     sip->fd = -1;
  37.     return sip;
  38. }
  39. struct serverinfo *si_dup(struct serverinfo *sip)
  40. {
  41.     mutex_lock(&sip->lock);
  42.     sip->use++;
  43.     mutex_unlock(&sip->lock);
  44.     return sip;
  45. }
  46. void si_free(struct serverinfo *sip)
  47. {
  48.     if (sip == NULL)
  49. return;
  50.     
  51.     mutex_lock(&sip->lock);
  52.     sip->use--;
  53.     if (sip->use > 0)
  54.     {
  55. mutex_unlock(&sip->lock);
  56. return;
  57.     }
  58.     if (sip->host)
  59. s_free(sip->host);
  60.     if (sip->url)
  61. s_free(sip->url);
  62.     mutex_destroy(&sip->lock);
  63.     s_free(sip);
  64. }
  65. static void *request_thread(struct connectioninfo *cip)
  66. {
  67.     int len, result = -1;
  68.     int keepalive = 0;
  69.     struct sockaddr_in client_sin, server_sin;
  70.     
  71.     if (debug > 1)
  72. fprintf(stderr, "request_thread(): Startn");
  73.     
  74.     fd_reopen(cip->fd, 2, FDT_SOCKET);
  75.     cip->tid = thr_self();
  76.     len = sizeof(server_sin);
  77.     if (getsockname(cip->fd, (struct sockaddr *) &server_sin, &len) < 0)
  78.     {
  79. syslog(LOG_INFO, "getsockname() failed: %m");
  80. goto Done;
  81.     }
  82.     
  83.     len = sizeof(client_sin);
  84.     if (getpeername(cip->fd, (struct sockaddr *) &client_sin, &len) < 0)
  85.     {
  86. syslog(LOG_INFO, "getpeername() failed: %m");
  87. goto Done;
  88.     }
  89.     cip->server = dns_lookup_name(&server_sin);
  90.     cip->client = dns_lookup_name(&client_sin);
  91.     if (ident_lookups)
  92. cip->ident = ident_lookup(&server_sin, &client_sin);
  93.     
  94.   Again:
  95.     keepalive = 0;
  96.     result = http_get_request(cip, &keepalive);
  97.     if (keepalive_enabled && keepalive && result > 0 && result < 400 )
  98.     {
  99. if (debug > 1)
  100.     fprintf(stderr, "Keepalive, retrying (fd=%d)n", cip->fd);
  101. fd_flush(cip->fd);
  102. if (cip->hip)
  103. {
  104.     log_connection(cip, result);
  105.     if (debug > 6 )
  106. fprintf(stderr, "after log: server_url: %s %lxn",(cip->sip->url)?cip->sip->url:"<NULL>",(long) (cip->server->sin.sin_addr.s_addr));
  107.     http_freeinfo(cip->hip);
  108.     cip->hip = NULL;
  109. }
  110. goto Again;
  111.     }
  112.     
  113.     if (debug > 1)
  114. fprintf(stderr, "No keepalive, closing (fd=%d)n", cip->fd);
  115.   Done:
  116. /*fprintf(stderr,"befor log %sn",(cip->hip->aip)?"POINTER":"NULL"); */
  117.     if (debug > 8 )
  118. fprintf(stderr, "calling log_connectionn");
  119.     if (cip->hip)
  120. log_connection(cip, result);
  121.     if (debug > 6 )
  122. {
  123. if ( cip->sip && cip->server )
  124. /* fprintf(stderr, "after2: server_url: %s %lxn",(cip->sip->url)?cip->sip->url:"<NULL>",(long) (cip->server->sin.sin_addr.s_addr)); */
  125. fprintf(stderr, "after2: server_url: %s %lxn","cip->sip->url?? <NULL>",(long) (cip->server->sin.sin_addr.s_addr));
  126. }
  127.     if (debug > 8 )
  128. fprintf(stderr, "calling cn_freen");
  129.     cn_free(cip);
  130.     
  131.     if (debug > 1)
  132. fprintf(stderr, "request_thread(): Stopn");
  133.     
  134.     return NULL;
  135. }
  136. static void *accept_thread(void *info)
  137. {
  138.     static mutex_t req_lock;
  139.     struct connectioninfo *cip;
  140.     int fd;
  141.     struct serverinfo *sip;
  142.     
  143.     sip = (struct serverinfo *) info;
  144.     
  145.   Loop:
  146.     if ( do_restart == 1 ) return NULL;
  147.     fd = accept(sip->fd, NULL, NULL);
  148.     if (fd < 0)
  149.     {
  150. if (errno != EINTR)
  151.     syslog(LOG_INFO, "accept() failed: %m");
  152. goto Loop;
  153.     }
  154.     cip = cn_new(fd);
  155.     
  156.     cip->sip = si_dup(sip);
  157.     
  158.     mutex_lock(&req_lock);
  159.     cip->request_no = ++n_requests;
  160. /* Max request opt restart */
  161.     if ( debug > 4 ) fprintf(stderr,"Req # %d/%dn",n_requests,restart_requests);
  162.     if ( restart_requests != 0 && n_requests > restart_requests )
  163.     {
  164. /* we need to restart */
  165. if ( debug > 1 ) 
  166. { fprintf(stderr,"Restart_requests %d/%d exeededn",n_requests,restart_requests); 
  167.   syslog(LOG_NOTICE, "MAX Restart_requests exeeded -- reforking");
  168. }
  169. /* we send outself a signal QUIT */
  170. sigsend(P_PID,getpid(),SIGQUIT);
  171.     }
  172.     mutex_unlock(&req_lock);
  173.     if (thr_create(NULL,
  174.    0,
  175.    (void *(*)(void *)) request_thread,
  176.    (void *) cip,
  177.    THR_DETACHED,
  178.    NULL))
  179.     {
  180. syslog(LOG_ERR, "thr_create(request_thread) failed: %m");
  181. exit(1);
  182.     }
  183.     
  184.     goto Loop;
  185. }    
  186. char *make_server_url(char *host, int port)
  187. {
  188.     char server_url[2048];
  189.     if (port == 80)
  190.     {
  191. s_strcpy(server_url, sizeof(server_url), "http://");
  192. s_strcat(server_url, sizeof(server_url), host);
  193.     }
  194.     else
  195.     {
  196.         int slen;
  197.         s_strcpy(server_url, sizeof(server_url), "http://");
  198. s_strcat(server_url, sizeof(server_url), host);
  199. slen = s_strcat(server_url, sizeof(server_url), ":");
  200. s_sprintf(server_url+slen, sizeof(server_url)-slen, "%d", port);
  201.     }
  202.     
  203.     return s_strdup(server_url);
  204. }
  205. struct serverinfo *create_http_server(char *addr, int port)
  206. {
  207.     struct serverinfo *sip;
  208.     
  209.     sip = si_new();
  210.     sip->fd = create_listen_socket(addr, port);
  211.     if (sip->fd < 0)
  212.     {
  213. s_free(sip);
  214. return NULL;
  215.     }
  216.     if (strcmp(addr, "*") == 0)
  217. addr = server_host;
  218.     
  219.     sip->host = s_strdup(addr);
  220.     sip->port = port;
  221.     sip->url = make_server_url(addr, port);
  222.     if ( debug > 3 )
  223. fprintf(stderr,"create_http_server: host=%s port=%d url=%sn",sip->host,sip->port,sip->url);
  224.     
  225.     return sip;
  226. }
  227. int start_http_server(struct serverinfo *sip, thread_t *tidp, thread_t *acthr_id)
  228. {
  229.     if (thr_create(NULL,
  230.    0,
  231.    (void *(*)(void *)) accept_thread,
  232.    (void *) sip,
  233.    tidp == NULL ? THR_DETACHED : 0,
  234.    acthr_id))
  235.     {
  236. syslog(LOG_ERR, "thr_create(accept_thread) failed: %m");
  237. return -1;
  238.     }
  239.     return 0;
  240. }