Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

http.c

00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: http.c,v 1.51 2007/10/26 10:01:09 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <sys/types.h>
00013 #include <stdlib.h>
00014 #include <unistd.h>
00015 #ifdef HAVE_LIBOPENSSL
00016 #include <openssl/ssl.h>
00017 #include <openssl/err.h>
00018 #endif  /* HAVE_LIBOPENSSL */
00019 #include <u/libu.h>
00020 #include <klone/utils.h>
00021 #include <klone/os.h>
00022 #include <klone/server.h>
00023 #include <klone/context.h>
00024 #include <klone/broker.h>
00025 #include <klone/request.h>
00026 #include <klone/ses_prv.h>
00027 #include <klone/response.h>
00028 #include <klone/backend.h>
00029 #include <klone/io.h>
00030 #include <klone/timer.h>
00031 #include <klone/tls.h>
00032 #include <klone/ses_prv.h>
00033 #include <klone/hook.h>
00034 #include <klone/hookprv.h>
00035 #include "http_s.h"
00036 
00037 struct http_status_map_s
00038 {
00039     int status;
00040     const char *desc;
00041 } http_status_map[] = {
00042     { HTTP_STATUS_OK                    , "OK"                      },
00043     { HTTP_STATUS_NOT_MODIFIED          , "Not Modified"            },
00044     { HTTP_STATUS_NOT_FOUND             , "Not Found"               },
00045     { HTTP_STATUS_INTERNAL_SERVER_ERROR , "Internal Server Error"   },
00046     { HTTP_STATUS_MOVED_PERMANENTLY     , "Moved Permanently"       },
00047     { HTTP_STATUS_MOVED_TEMPORARILY     , "Moved Temporarily"       },
00048     { HTTP_STATUS_CREATED               , "Created"                 },
00049     { HTTP_STATUS_ACCEPTED              , "Accepted"                },
00050     { HTTP_STATUS_NO_CONTENT            , "No Content"              },
00051     { HTTP_STATUS_BAD_REQUEST           , "Bad Request"             },
00052     { HTTP_STATUS_UNAUTHORIZED          , "Unauthorized"            },
00053     { HTTP_STATUS_FORBIDDEN             , "Forbidden"               },
00054     { HTTP_STATUS_LENGTH_REQUIRED       , "Content-Length required" },
00055     { HTTP_STATUS_REQUEST_TOO_LARGE     , "Request data too big"    },
00056     { HTTP_STATUS_NOT_IMPLEMENTED       , "Not Implemented"         },
00057     { HTTP_STATUS_BAD_GATEWAY           , "Bad Gateway"             },
00058     { HTTP_STATUS_SERVICE_UNAVAILABLE   , "Service Unavailable"     },
00059     { 0                                 , NULL                      }
00060 };
00061 
00062 /* in cgi.c */
00063 int cgi_set_request(request_t *rq);
00064 
00065 session_opt_t *http_get_session_opt(http_t *http)
00066 {
00067     dbg_return_if (http == NULL, NULL);
00068 
00069     return http->sess_opt;
00070 }
00071 
00072 u_config_t *http_get_config(http_t* http)
00073 {
00074     dbg_return_if (http == NULL, NULL);
00075 
00076     return http->config;
00077 }
00078 
00079 const char *http_get_status_desc(int status)
00080 {
00081     struct http_status_map_s *map = http_status_map;
00082     const char *msg = "Unknown Status Code";
00083 
00084     for( ; map->status; ++map)
00085         if(map->status == status)
00086         {
00087             msg = map->desc;
00088             break;
00089         }
00090 
00091     return msg;
00092 }
00093 
00094 static int http_try_resolv(const char *alias, char *dst, const char *uri, 
00095         size_t sz)
00096 {
00097     static const char *WP = " \t";
00098     char *src, *res, *v = NULL, *pp = NULL;
00099 
00100     dbg_err_if(dst == NULL);
00101     dbg_err_if(uri == NULL);
00102     dbg_err_if(alias == NULL);
00103 
00104     /* dup to use it in strtok */
00105     v = u_strdup(alias);
00106     dbg_err_if(v == NULL);
00107 
00108     /* src is the source directory */
00109     src = strtok_r(v, WP, &pp); 
00110     dbg_err_if(src == NULL);
00111 
00112     /* exit if the URI doesn't match this alias */
00113     nop_err_if(strncmp(src, uri, strlen(src)));
00114 
00115     /* if src doesn't end with a slash check that the next char in uri is a / */
00116     if(src[strlen(src)-1] != '/')
00117         nop_err_if(uri[strlen(src)] != '/');
00118 
00119     /* alias found, get the resolved prefix */
00120     res = strtok_r(NULL, WP, &pp);
00121     dbg_err_if(res == NULL);
00122 
00123     /* copy-out the resolved uri to dst */
00124     dbg_err_if(u_path_snprintf(dst, sz, '/', "%s/%s", res, uri + strlen(src)));
00125 
00126     U_FREE(v);
00127 
00128     return 0;
00129 err:
00130     U_FREE(v);
00131     return ~0;
00132 }
00133 
00134 const char *http_vhost_config_value(http_t *h, request_t *rq, const char *key)
00135 {
00136     u_config_t *config;
00137 
00138     if(http_get_vhost_config(h, rq, &config))
00139         return NULL;
00140 
00141     return u_config_get_subkey_value(config, key);
00142 }
00143 
00144 int http_get_vhost_config(http_t *h, request_t *rq, u_config_t **pc)
00145 {
00146     u_config_t *config = NULL;;
00147     const char *host;
00148     char *p, hostcp[128];
00149 
00150     dbg_err_if (h == NULL);
00151     dbg_err_if (rq == NULL);
00152     dbg_err_if (pc == NULL);
00153 
00154     /* if there's not Host: field or there's not config associated to this host
00155      * then use the default config values */
00156     nop_err_if((host = request_get_field_value(rq, "Host")) == NULL);
00157 
00158     strlcpy(hostcp, host, sizeof(hostcp));
00159 
00160     /* remove :port part */   
00161     if((p = strrchr(hostcp, ':')) != NULL)
00162         *p = 0;
00163 
00164     /* get Host related config */
00165     nop_err_if((config = u_config_get_child(h->config, hostcp)) == NULL);
00166 
00167     *pc = config;
00168 
00169     return 0;
00170 err:
00171     return ~0;
00172 }
00173 
00174 int http_alias_resolv(http_t *h, request_t *rq, char *dst, const char *uri, 
00175         size_t sz)
00176 {
00177     u_config_t *config, *cgi, *base = NULL;
00178     const char *host, *dir_root = NULL;
00179     char *p, hostcp[128];
00180     int i;
00181 
00182     dbg_err_if (h == NULL);
00183     dbg_err_if (dst == NULL);
00184     dbg_err_if (uri == NULL);
00185 
00186     /* defaults */
00187     base = h->config;
00188     dir_root = h->dir_root;
00189 
00190     /* virtual host config overwrites httpd config */
00191     if(!http_get_vhost_config(h, rq, &base))
00192         dir_root = u_config_get_subkey_value(base, "dir_root");
00193 
00194     /* for each dir_alias config item */
00195     for(i = 0; !u_config_get_subkey_nth(base, "dir_alias", i, &config); 
00196         ++i)
00197     {
00198         if(!http_try_resolv(u_config_get_value(config), dst, uri, sz))
00199             return 0;   /* alias found, uri resolved */
00200     }
00201 
00202     /* if there's a cgi tree also try to resolv script_alias rules */
00203     if(!u_config_get_subkey(base, "cgi", &cgi))
00204     {
00205         for(i = 0; !u_config_get_subkey_nth(cgi, "script_alias", i, &config);
00206             ++i)
00207         {
00208             if(!http_try_resolv(u_config_get_value(config), dst, uri, sz))
00209                 return 0;   /* alias found, uri resolved */
00210         }
00211     }
00212 
00213     /* not alias found, prepend dir_root to the uri */
00214     dbg_err_if(u_path_snprintf(dst, sz, '/', "%s/%s", dir_root, uri));
00215 
00216     return 0;
00217 err:
00218     return ~0;
00219 }
00220 
00221 static int http_is_valid_uri(void *arg, const char *buf, size_t len)
00222 {
00223     enum { URI_MAX = 2048 };
00224     char resolved[U_FILENAME_MAX], uri[URI_MAX];
00225     request_t *rq = (request_t*)arg;
00226     http_t *h = NULL;
00227 
00228     dbg_err_if (arg == NULL);
00229     dbg_err_if (buf == NULL);
00230 
00231     h = request_get_http(rq);
00232     dbg_err_if (h == NULL);
00233     
00234     strncpy(uri, buf, len);
00235     uri[len] = 0;
00236 
00237     dbg_err_if(http_alias_resolv(h, rq, resolved, uri, URI_MAX));
00238 
00239     return broker_is_valid_uri(h->broker, h, rq, resolved, strlen(resolved));
00240 err:
00241     return ~0;
00242 }
00243 
00244 static void http_resolv_request(http_t *h, request_t *rq)
00245 {
00246     const char *cstr;
00247     char resolved[U_FILENAME_MAX];
00248 
00249     dbg_ifb(h == NULL) return;
00250     dbg_ifb(rq == NULL) return;
00251     
00252     /* unalias rq->filename */
00253     cstr = request_get_filename(rq);
00254     if(cstr && !http_alias_resolv(h, rq, resolved, cstr, U_FILENAME_MAX))
00255         request_set_resolved_filename(rq, resolved);
00256 
00257     /* unalias rq->path_info */
00258     cstr = request_get_path_info(rq);
00259     if(cstr && !http_alias_resolv(h, rq, resolved, cstr, U_FILENAME_MAX))
00260         request_set_resolved_path_info(rq, resolved);
00261 }
00262 
00263 static int http_is_valid_index(http_t *h, request_t *rq, const char *uri)
00264 {
00265     char resolved[U_FILENAME_MAX] = { 0 };
00266 
00267     dbg_err_if(u_path_snprintf(resolved, U_FILENAME_MAX, '/', "%s/%s", 
00268             request_get_resolved_filename(rq), uri));
00269 
00270     if(broker_is_valid_uri(h->broker, h, rq, resolved, strlen(resolved)))
00271         return 1; /* index found */
00272 
00273 err:
00274     return 0; /* index not found */
00275 }
00276 
00277 static int http_get_config_index(http_t *h, request_t *rq, char *idx, size_t sz)
00278 {
00279     char buf[256], *tok, *src, *pp = NULL;
00280     const char *index = NULL;
00281     u_config_t *config;
00282 
00283     dbg_err_if (h == NULL);
00284     dbg_err_if (rq == NULL);
00285 
00286     if((index = http_vhost_config_value(h, rq, "index")) == NULL)
00287         index = h->index;
00288 
00289     if(!index)
00290         return ~0; /* index config key missing */
00291 
00292     /* copy the string (u_tokenize will modify it) */
00293     dbg_err_if(strlcpy(buf, index, sizeof(buf)) >= sizeof(buf));
00294 
00295     for(src = buf; (tok = strtok_r(src, " \t", &pp)) != NULL; src = NULL)
00296     {
00297         if(!strcmp(tok, ""))
00298             continue; 
00299 
00300         if(http_is_valid_index(h, rq, tok))
00301         {
00302             dbg_err_if(strlcpy(idx, tok, sz) >= sz);
00303             return 0; /* index page found */
00304         }
00305     }
00306 
00307     /* fall through */
00308 err:
00309     return ~0;
00310 }
00311 
00312 static int http_get_default_index(http_t *h, request_t *rq, char *index, 
00313         size_t sz)
00314 {
00315     static const char *indexes[] = { "/index.klone", "/index.kl1",
00316         "/index.html", "/index.htm", NULL };
00317     const char **pg;
00318 
00319     dbg_err_if (h == NULL);
00320     dbg_err_if (rq == NULL);
00321 
00322     /* try to find an index page between default index uris */
00323     for(pg = indexes; *pg; ++pg)
00324     {
00325         if(http_is_valid_index(h, rq, *pg))
00326         {
00327             dbg_err_if(strlcpy(index, *pg, sz) >= sz);
00328             return 0; /* index page found */
00329         }
00330     }
00331 
00332     /* fall through */
00333 err:
00334     return ~0;
00335 }
00336 
00337 static int http_set_index_request(http_t *h, request_t *rq)
00338 {
00339     char idx[128], uri[1024];
00340 
00341     dbg_err_if (h == NULL);
00342     dbg_err_if (rq == NULL);
00343 
00344     /* find an index page; try first config options then static index names */
00345     if(!http_get_config_index(h, rq, idx, sizeof(idx)) || 
00346             !http_get_default_index(h, rq, idx, sizeof(idx)))
00347     {
00348         dbg_err_if(u_snprintf(uri, sizeof(uri), "%s%s", 
00349                     request_get_filename(rq), idx));
00350 
00351         dbg_if(request_set_filename(rq, uri));
00352     }
00353 
00354     http_resolv_request(h, rq);
00355 
00356     return 0;
00357 err:
00358     return ~0;
00359 }
00360 
00361 static int http_add_default_header(http_t *h, response_t *rs)
00362 {
00363     time_t now;
00364 
00365     dbg_err_if (h == NULL);
00366     dbg_err_if (rs == NULL);
00367     
00368     /* set server signature */
00369     dbg_err_if(response_set_field(rs, "Server", h->server_sig));
00370 
00371     now = time(NULL);
00372     dbg_err_if(response_set_date(rs, now));
00373 
00374     return 0;
00375 err:
00376     return ~0;
00377 }
00378 
00379 static int http_print_error_page(http_t *h, request_t *rq, response_t *rs, 
00380     int http_status)
00381 {
00382     enum { BUFSZ = 64 };
00383     const char *err_page;
00384     char buf[BUFSZ];
00385     int rc;
00386 
00387     dbg_err_if (h == NULL);
00388     dbg_err_if (rq == NULL);
00389     dbg_err_if (rs == NULL);
00390     dbg_err_if (http_status == 0);
00391     
00392     /* clean dirty header fields (not for redirects) */
00393     if(http_status != 302)
00394         dbg_err_if(header_clear(response_get_header(rs)));
00395 
00396     /* add default header fields */
00397     dbg_err_if(http_add_default_header(h, rs));
00398 
00399     /* disable page caching */
00400     dbg_err_if(response_disable_caching(rs));
00401 
00402     /* looking for user provided error page */
00403     dbg_err_if(u_snprintf(buf, BUFSZ, "error.%d", http_status));
00404     err_page = u_config_get_subkey_value(h->config, buf);
00405 
00406     if(err_page && !request_set_uri(rq, err_page, NULL, NULL))
00407     {
00408         http_resolv_request(h, rq);
00409         if((rc = broker_serve(h->broker, h, rq, rs)) == 0)
00410             return 0; 
00411         else {
00412             /* configured error page not found */
00413             http_status = rc;
00414         }
00415     }
00416 
00417     /* be sure that the status code is properly set */
00418     response_set_status(rs, http_status);
00419 
00420     response_print_header(rs);
00421 
00422     if(request_get_method(rq) == HM_HEAD)
00423         return 0; /* just the header is requested */
00424 
00425     /* print default error page */
00426     dbg_err_if(io_printf(response_io(rs), 
00427         "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
00428         "<html><head><title>%d %s</title></head>\n"
00429         "<body><h1>%s</h1><p>URL: %s</p><hr>"
00430         "<address>KLone/%s web server - www.koanlogic.com</address>"
00431         "</body></html>", 
00432         http_status, http_get_status_desc(http_status), 
00433         http_get_status_desc(http_status), 
00434         (request_get_uri(rq) ? request_get_uri(rq) : ""),
00435         KLONE_VERSION
00436         ) < 0);
00437 
00438     return 0;
00439 err:
00440     return ~0;
00441 }
00442 
00443 static int http_serve(http_t *h, int fd)
00444 {
00445     request_t *rq = NULL;
00446     response_t *rs = NULL;
00447     io_t *in = NULL, *out = NULL;
00448     int cgi = 0, port, rc = HTTP_STATUS_INTERNAL_SERVER_ERROR;
00449     const char *gwi = NULL, *cstr;
00450     talarm_t *al = NULL;
00451     addr_t *addr;
00452     struct sockaddr sa;
00453     size_t sasz;
00454 
00455     u_unused_args(al);
00456 
00457     dbg_err_if (h == NULL);
00458     dbg_err_if (fd < 0);
00459     
00460     if(fd == 0 && (gwi = getenv("GATEWAY_INTERFACE")) != NULL)
00461         cgi++; /* klone is being used as a CGI */
00462 
00463     /* create a request object */
00464     dbg_err_if(request_create(h, &rq));
00465     request_set_cgi(rq, cgi);
00466 
00467     /* save local and peer address into the request object */
00468     dbg_err_if(addr_create(&addr));
00469 
00470     if(cgi)
00471     {
00472         if(getenv("REMOTE_ADDR") && getenv("REMOTE_PORT"))
00473         {
00474             port = atoi(getenv("REMOTE_PORT"));
00475             dbg_err_if(addr_set(addr, getenv("REMOTE_ADDR"), port));
00476             dbg_err_if(request_set_addr(rq, addr));
00477         }
00478 
00479         if(getenv("SERVER_ADDR"))
00480         {
00481             if(getenv("SERVER_PORT"))
00482                 port = atoi(getenv("SERVER_PORT"));
00483             else
00484                 port = 80;
00485             dbg_err_if(addr_set(addr, getenv("SERVER_ADDR"), port));
00486             dbg_err_if(request_set_peer_addr(rq, addr));
00487         }
00488     } else {
00489         /* set local addr */
00490         sasz = sizeof(struct sockaddr);
00491         dbg_err_if(getsockname(fd, &sa, &sasz));
00492         dbg_err_if(addr_set_from_sa(addr, &sa, sasz));
00493         dbg_err_if(request_set_addr(rq, addr));
00494 
00495         /* set peer addr */
00496         sasz = sizeof(struct sockaddr);
00497         dbg_err_if(getpeername(fd, &sa, &sasz));
00498         dbg_err_if(addr_set_from_sa(addr, &sa, sasz));
00499         dbg_err_if(request_set_peer_addr(rq, addr));
00500     }
00501 
00502     addr_free(addr);
00503     addr = NULL;
00504 
00505 #ifdef HAVE_LIBOPENSSL
00506     /* create input io buffer (no IO_FD_CLOSE used because 'out' 
00507        will close it */
00508     if(h->ssl && !cgi)
00509         dbg_err_if(io_ssl_create(fd, IO_FD_CLOSE, h->ssl_ctx, &in));
00510     else
00511         dbg_err_if(io_fd_create(fd, IO_FD_CLOSE, &in));
00512 #else
00513     /* create input io buffer */
00514     dbg_err_if(io_fd_create(fd, IO_FD_CLOSE, &in));
00515 #endif
00516 
00517     /* bind the request object to the 'in' io_t */
00518     dbg_err_if(request_bind(rq, in));
00519     in = NULL; 
00520 
00521     /* create a response object */
00522     dbg_err_if(response_create(h, &rs));
00523 
00524     response_set_cgi(rs, cgi);
00525 
00526     if(cgi)
00527         dbg_err_if(cgi_set_request(rq));
00528 
00529     /* create the output io_t */
00530     if(cgi)
00531         dbg_err_if(io_fd_create((cgi ? 1 : fd), IO_FD_CLOSE, &out));
00532     else
00533         /* create the response io_t dup'ping the request io_t object */
00534         dbg_err_if(io_dup(request_io(rq), &out));
00535 
00536     /* default method used if we cannot parse the request (bad request) */
00537     response_set_method(rs, HM_GET);
00538 
00539     /* bind the response to the connection c */
00540     dbg_err_if(response_bind(rs, out));
00541     out = NULL;
00542 
00543     dbg_err_if(response_set_status(rs, HTTP_STATUS_BAD_REQUEST));
00544 
00545     /* parse request. may fail on timeout */
00546     dbg_err_if(rc = request_parse_header(rq, http_is_valid_uri, rq));
00547 
00548     response_set_method(rs, request_get_method(rq));
00549 
00550     /* if we're running in server mode then resolv aliases and dir_root */
00551     http_resolv_request(h, rq);
00552 
00553     /* if the uri end with a slash then return an index page */
00554     if((cstr = request_get_filename(rq)) != NULL && cstr[strlen(cstr)-1] == '/')
00555         dbg_err_if(http_set_index_request(h, rq)); /* set the index page */
00556 
00557     /* add default header fields */
00558     dbg_err_if(http_add_default_header(h, rs));
00559 
00560     /* set default successfull status code */
00561     dbg_err_if(response_set_status(rs, HTTP_STATUS_OK));
00562 
00563     /* serve the page; on error write out a simple error page */
00564     nop_err_if((rc = broker_serve(h->broker, h, rq, rs)) != 0);
00565 
00566     /* call the hook that fires on each request */
00567     hook_call(request, rq, rs);
00568 
00569     /* page successfully served */
00570 
00571     request_free(rq);
00572     response_free(rs); /* must be free'd after the request object because
00573                           the rsfilter references the response object during
00574                           the flush of the codec (so the response object must
00575                           not be free'd) that happens during the io_free call */
00576     return 0;
00577 err:
00578     /* hook get fired also on error */
00579     hook_call(request, rq, rs);
00580 
00581     if(rc && rq && rs && response_io(rs))
00582         http_print_error_page(h, rq, rs, rc); /* print the error page */
00583     if(in)
00584         io_free(in);
00585     if(out)
00586         io_free(out);
00587     if(rq)
00588         request_free(rq);
00589     if(rs)
00590         response_free(rs);
00591     return ~0;
00592 }
00593 
00594 static int http_free(http_t *h)
00595 {
00596     dbg_return_if (h == NULL, 0);   /* it's ok */
00597 
00598     if(h->broker)
00599         broker_free(h->broker);
00600 
00601     U_FREE(h);
00602 
00603     return 0;
00604 }
00605 
00606 static int http_set_config_opt(http_t *http)
00607 {
00608     u_config_t *c = http->config;
00609     const char *v;
00610 
00611     dbg_err_if (http == NULL);
00612     
00613     /* defaults */
00614     http->server_sig = "klone/" KLONE_VERSION;
00615     http->dir_root = "";
00616     http->index = NULL;
00617     http->send_enc_deflate = 0; 
00618 
00619     /* send_enc_deflate (disable if not configured) */
00620     dbg_err_if(u_config_get_subkey_value_b(c, "send_enc_deflate", 0, 
00621         &http->send_enc_deflate));
00622 
00623     /* server signature */
00624     if((v = u_config_get_subkey_value(c, "server_sig")) != NULL)
00625         http->server_sig = v;
00626 
00627     /* html dir root */
00628     if((v = u_config_get_subkey_value(c, "dir_root")) != NULL)
00629         http->dir_root = v;
00630     else
00631         crit_err("dir_root must be set");
00632 
00633     /* index page */
00634     if((v = u_config_get_subkey_value(c, "index")) != NULL)
00635         http->index = v;
00636 
00637     return 0;
00638 err:
00639     return ~0;
00640 }
00641 
00642 
00643 static int http_create(u_config_t *config, http_t **ph)
00644 {
00645     http_t *h = NULL;
00646 
00647     dbg_err_if (config == NULL);
00648     dbg_err_if (ph == NULL);
00649 
00650     h = u_zalloc(sizeof(http_t));
00651     dbg_err_if(h == NULL);
00652 
00653     h->config = config;
00654 
00655     /* init page broker (and page suppliers) */
00656     dbg_err_if(broker_create(&h->broker));
00657 
00658     /* set http struct config opt reading from http->config */
00659     dbg_err_if(http_set_config_opt(h));
00660 
00661     *ph = h;
00662 
00663     return 0;
00664 err:
00665     if(h)
00666         http_free(h);
00667     return ~0;
00668 }
00669 
00670 static int http_backend_serve(struct backend_s *be, int fd)
00671 {
00672     http_t *h;
00673     int rc;
00674 
00675     dbg_err_if (be == NULL);
00676     dbg_err_if (be->arg == NULL);
00677     dbg_err_if (fd < 0);
00678     
00679     h = (http_t *) be->arg;
00680     
00681     /* new connection accepted on http listening socket, handle it */
00682     rc = http_serve(h, fd);
00683 
00684     return rc;
00685 err:
00686     return ~0;
00687 }
00688 
00689 static int http_backend_term(struct backend_s *be)
00690 {
00691     http_t *http;
00692 
00693     dbg_return_if (be == NULL, 0);
00694     dbg_return_if (be->arg == NULL, 0);
00695 
00696     http = (http_t *) be->arg;
00697 
00698     dbg_err_if(session_module_term(http->sess_opt));
00699 
00700     http_free(http);
00701 
00702     return 0;
00703 err:
00704     return ~0;
00705 }
00706 
00707 static int http_backend_init(struct backend_s *be)
00708 {
00709     http_t *http = NULL;
00710     broker_t *broker = NULL;
00711 
00712     dbg_err_if (be == NULL);
00713  
00714     dbg_err_if(http_create(be->config, &http));
00715 
00716     be->arg = http;
00717 
00718     dbg_err_if(session_module_init(http->config, &http->sess_opt));
00719 
00720     return 0;
00721 err:
00722     if(http)
00723         http_free(http);
00724     if(broker)
00725         broker_free(broker);
00726     return ~0;
00727 }
00728 
00729 #ifdef HAVE_LIBOPENSSL
00730 static int https_backend_init(struct backend_s *be)
00731 {
00732     http_t *https;
00733 
00734     dbg_err_if (be == NULL);
00735 
00736     dbg_err_if(http_backend_init(be));
00737 
00738     https = (http_t *) be->arg;
00739 
00740     /* turn on SSL encryption */
00741     https->ssl = 1;
00742 
00743     /* load config values and set SSL_CTX accordingly */
00744     https->ssl_ctx = tls_load_init_ctx(http_get_config(https));
00745     warn_err_ifm (https->ssl_ctx == NULL, "bad or missing HTTPS credentials");
00746 
00747     dbg_err_if(session_module_init(https->config, &https->sess_opt));
00748 
00749     return 0;
00750 err:
00751     return ~0;
00752 }
00753 
00754 static int https_backend_term(struct backend_s *be)
00755 {
00756     http_t *https;
00757 
00758     dbg_err_if (be == NULL);
00759 
00760     https = (http_t *) be->arg;
00761     if (https == NULL)
00762         return 0;
00763 
00764     SSL_CTX_free(https->ssl_ctx);
00765 
00766     return http_backend_term(be); 
00767 err:
00768     return ~0;
00769 }
00770 
00771 /* same http functions but different '_init' */
00772 backend_t be_https =
00773     BACKEND_STATIC_INITIALIZER( "https", 
00774         https_backend_init, 
00775         http_backend_serve, 
00776         https_backend_term );
00777 #endif /* HAVE_LIBOPENSSL */
00778 
00779 backend_t be_http =
00780     BACKEND_STATIC_INITIALIZER( "http", 
00781         http_backend_init, 
00782         http_backend_serve, 
00783         http_backend_term );
00784