diff options
| author | 2005-12-19 14:06:15 +0000 | |
|---|---|---|
| committer | 2005-12-19 14:06:15 +0000 | |
| commit | 84693bb5f792e6d6accd1ad2e81fe6baeb4f4ea1 (patch) | |
| tree | 34d1f68d2d887770e8a67fe5d65e82ec2cdfebe3 /nanohttp/nanohttp-server.c | |
| parent | 7fe73dd2cd46d43b97bd8766849f2dffabb6a2d4 (diff) | |
| download | csoap-84693bb5f792e6d6accd1ad2e81fe6baeb4f4ea1.tar.gz csoap-84693bb5f792e6d6accd1ad2e81fe6baeb4f4ea1.tar.bz2 | |
integrated with ssl (https) capability
Diffstat (limited to 'nanohttp/nanohttp-server.c')
| -rw-r--r-- | nanohttp/nanohttp-server.c | 173 | 
1 files changed, 120 insertions, 53 deletions
| diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c index c099ed6..d1cda7c 100644 --- a/nanohttp/nanohttp-server.c +++ b/nanohttp/nanohttp-server.c @@ -1,5 +1,5 @@  /****************************************************************** -*  $Id: nanohttp-server.c,v 1.34 2005/07/22 13:26:41 snowdrop Exp $ +*  $Id: nanohttp-server.c,v 1.35 2005/12/19 14:06:16 snowdrop Exp $  *  * CSOAP Project:  A http client/server library in C  * Copyright (C) 2003  Ferhat Ayaz @@ -22,6 +22,7 @@  * Email: ayaz@jprogrammer.net  ******************************************************************/  #include <nanohttp/nanohttp-server.h> +#include <nanohttp/nanohttp-ssl.h>  #include <stdio.h>  #include <stdlib.h> @@ -96,8 +97,12 @@ static conndata_t *_httpd_connection;  #ifdef WIN32  static void WSAReaper(void *x); +#else +sigset_t thrsigset;  #endif + +  /*   * -----------------------------------------------------   * FUNCTION: httpd_init @@ -162,7 +167,10 @@ httpd_init (int argc, char *argv[])  #endif    /* create socket */ -  hsocket_init (&_httpd_socket); +  status = hsocket_init (&_httpd_socket); +  if( status != H_OK ){ +    return status; +  }    status = hsocket_bind (&_httpd_socket, _httpd_port);    return status; @@ -292,7 +300,7 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text)    strcat (header, "Server: Nano HTTPD library\r\n");    /* set _httpd_connection status */ -  strcat (header, "Connection: close\r\n"); +  //strcat (header, "Connection: close\r\n");    /* add pairs */    cur = res->header; @@ -310,7 +318,7 @@ httpd_send_header (httpd_conn_t * res, int code, const char *text)    status = hsocket_nsend (res->sock, header, strlen (header));  	if (status != H_OK)  		return status; - +      res->out = http_output_stream_new (res->sock, res->header);    return H_OK;  } @@ -323,9 +331,15 @@ httpd_send_internal_error (httpd_conn_t * conn, const char *errmsg)      "<html><body><h3>Error!</h3><hr> Message: '%s' </body></html>\r\n";    char buffer[4064]; +  char buflen[5];    sprintf (buffer, template1, errmsg); +#ifdef WIN32 +#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) +#endif +  snprintf(buflen, 5, "%d", strlen(buffer)); +  httpd_set_header (conn, HEADER_CONTENT_LENGTH, buflen);    httpd_send_header (conn, 500, "INTERNAL"); -  return send (conn->sock, buffer, strlen (buffer), 0); +  return hsocket_nsend (conn->sock, buffer, strlen (buffer));  }  /* @@ -350,6 +364,13 @@ httpd_request_print (hrequest_t * req)      log_verbose3 (" %s = '%s'", pair->key, pair->value);      pair = pair->next;    } +  log_verbose1 (" Parsed header :"); +  pair = req->header; +  while (pair != NULL) +  { +    log_verbose3 (" %s = '%s'", pair->key, pair->value); +    pair = pair->next; +  }    log_verbose1 ("++++++++++++++++++++++++");  } @@ -378,6 +399,23 @@ void httpd_free(httpd_conn_t *conn)    free(conn);  } +void do_req_timeout(int signum){ +/* +    struct sigaction req_timeout; +    memset(&req_timeout, 0, sizeof(&req_timeout)); +    req_timeout.sa_handler=SIG_IGN; +    sigaction(SIGALRM, &req_timeout, NULL); +*/ + +    // XXX this is not real pretty, is there a better way? +    log_verbose1("Thread timeout."); +#ifdef WIN32 +   _endthread (); + #else +    pthread_exit(0); +#endif +} +  /*   * -----------------------------------------------------   * FUNCTION: httpd_session_main @@ -394,6 +432,7 @@ httpd_session_main (void *data)    conndata_t *conn = (conndata_t *) data;    const char *msg = "SESSION 1.0\n";    int len = strlen (msg); +  int done=0;    char buffer[256];             /* temp buffer for recv() */    char header[4064];            /* received header */    hrequest_t *req = NULL;       /* only for test */ @@ -404,55 +443,71 @@ httpd_session_main (void *data)    header[0] = '\0';    len = 0; - -    log_verbose1 ("starting httpd_session_main()");    conn->atime = time ((time_t) 0);    /* call the service */  /*  req = hrequest_new_from_buffer (header);*/ -  rconn = httpd_new(conn->sock); -  status = hrequest_new_from_socket (conn->sock, &req); -  if (status != H_OK) -  { -    httpd_send_internal_error (rconn, herror_message(status)/*"Request parse error!"*/); -	herror_release(status); -  } -  else -  { -    httpd_request_print (req); +  do{ +      log_verbose1("starting HTTP request"); +      rconn = httpd_new(conn->sock); +      status = hrequest_new_from_socket (conn->sock, &req); -    service = httpd_find_service (req->path); -    if (service != NULL) -    { -      log_verbose2 ("service '%s' found", req->path); -      if (service->func != NULL) +      if (status != H_OK)        { -        service->func (rconn, req); +        if(herror_code(status) != HSOCKET_SSL_CLOSE){ +            httpd_send_internal_error (rconn, herror_message(status)/*"Request parse error!"*/); +            herror_release(status); +        } +        done=1;        }        else        { -        sprintf (buffer, -                 "service '%s' not registered properly (func == NULL)", -                 req->path); -        log_verbose1 (buffer); -        httpd_send_internal_error (rconn, buffer); +        char *conn_str = hpairnode_get_ignore_case (req->header, HEADER_CONNECTION); +#ifdef WIN32 +#define strncasecmp(s1, s2, num) strncmp(s1, s2, num) +#endif +        if(conn_str && strncasecmp( conn_str, "close",5 ) == 0){ +            done=1; +        } +        if(!done){ +            done = req->version==HTTP_1_0?1:0; +        } +        httpd_request_print (req); + + +        service = httpd_find_service (req->path); +        if (service != NULL) +        { +          log_verbose2 ("service '%s' found", req->path); +          if (service->func != NULL) +          { +            service->func (rconn, req); +          } +          else +          { +            sprintf (buffer, +                     "service '%s' not registered properly (func == NULL)", +                     req->path); +            log_verbose1 (buffer); +            httpd_send_internal_error (rconn, buffer); +          } +        } +        else +        { +          sprintf (buffer, "service '%s' not found", req->path); +          log_verbose1 (buffer); +          httpd_send_internal_error (rconn, buffer); +        } + +        /* httpd_response_free(res); */ +        /*hrequest_free (req);*/        } -    } -    else -    { -      sprintf (buffer, "service '%s' not found", req->path); -      log_verbose1 (buffer); -      httpd_send_internal_error (rconn, buffer); -    } - -    /* httpd_response_free(res); */ -    /*hrequest_free (req);*/ -  } +  }while(!done);    hsocket_close(conn->sock); -  conn->sock = 0; +  conn->sock.sock = 0;    hrequest_free(req);    httpd_free(rconn);  #ifdef WIN32 @@ -513,7 +568,7 @@ void httpd_set_headers(httpd_conn_t *conn, hpair_t *header)  BOOL WINAPI  httpd_term (DWORD sig)  { -  log_debug2 ("Got signal %d", sig); +  //log_debug2 ("Got signal %d", sig);    if (sig == _httpd_terminate_signal)      _httpd_run = 0;    return TRUE; @@ -573,7 +628,7 @@ _httpd_wait_for_empty_conn ()        system_sleep (1);        i = 0;      } -    else if (_httpd_connection[i].sock == 0) +    else if (_httpd_connection[i].sock.sock == 0)      {        break;      } @@ -600,6 +655,7 @@ _httpd_start_thread (conndata_t * conn)  #ifdef PTHREAD_CREATE_DETACHED    pthread_attr_setdetachstate (&(conn->attr), PTHREAD_CREATE_DETACHED);  #endif +  pthread_sigmask(SIG_BLOCK, &thrsigset, NULL);    err = pthread_create (&(conn->tid), &(conn->attr), httpd_session_main,                          conn);    if (err) @@ -625,10 +681,17 @@ httpd_run ()    fd_set fds;    struct timeval timeout; +    log_verbose1 ("starting run routine");    timeout.tv_sec = 1;    timeout.tv_usec = 0; +#ifdef WIN32 +#else +  sigemptyset(&thrsigset); +  sigaddset(&thrsigset, SIGALRM); +#endif +    /* listen to port */    err = hsocket_listen (_httpd_socket); @@ -669,10 +732,10 @@ httpd_run ()        /* zero and set file descriptior */        FD_ZERO (&fds); -      FD_SET (_httpd_socket, &fds); +      FD_SET (_httpd_socket.sock, &fds);        /* select socket descriptor */ -      switch (select (_httpd_socket + 1, &fds, NULL, NULL, &timeout)) +      switch (select (_httpd_socket.sock + 1, &fds, NULL, NULL, &timeout))        {        case 0:          /* descriptor is not ready */ @@ -684,7 +747,7 @@ httpd_run ()          /* no nothing */          break;        } -      if (FD_ISSET (_httpd_socket, &fds)) +      if (FD_ISSET (_httpd_socket.sock, &fds))        {          break;        } @@ -696,7 +759,13 @@ httpd_run ()      /* Accept a socket */      err = hsocket_accept (_httpd_socket, &(conn->sock)); -    if (err != H_OK) +    if (err != H_OK && herror_code(err) == SSL_ERROR_INIT) { +      hsocket_close(conn->sock); +      conn->sock.sock = -1; +      conn->sock.ssl = NULL; +      log_error1(herror_message(err)); +      continue; +    } else if (err != H_OK)       {        log_error2 ("Can not accept socket: %s", herror_message(err));        return err;                /* this is hard core! */ @@ -746,10 +815,10 @@ void WSAReaper(void *x)  				(_httpd_connection[i].atime==0)) continue;  			log_verbose3("Reaping socket %u from (runtime ~= %d seconds)",   				_httpd_connection[i].sock, ctime-_httpd_connection[i].atime); -			shutdown(_httpd_connection[i].sock, 2); -			while (recv(_httpd_connection[i].sock, junk, sizeof(junk), 0)>0) { }; -			closesocket(_httpd_connection[i].sock); -			_httpd_connection[i].sock = 0; +			shutdown(_httpd_connection[i].sock.sock, 2); +			while (recv(_httpd_connection[i].sock.sock, junk, sizeof(junk), 0)>0) { }; +			closesocket(_httpd_connection[i].sock.sock); +			_httpd_connection[i].sock.sock = 0;  			TerminateThread(_httpd_connection[i].tid, (DWORD)&rc);  			CloseHandle(_httpd_connection[i].tid);  			memset((char *)&_httpd_connection[i], 0, sizeof(_httpd_connection[i])); @@ -849,9 +918,7 @@ httpd_mime_send_header (httpd_conn_t * conn,  	/*  	  using sprintf instead of snprintf because visual c does not support snprintf  	*/ -#ifdef WIN32 -#define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) -#endif +    sprintf (buffer, "multipart/related;");    if (related_type) | 
