diff -r 1fdbf4170ef4 -r b8bf95b39952 src/server/httprequest.c --- a/src/server/httprequest.c Sun Jan 08 15:46:47 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,532 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2011 Olaf Wintermann. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - - -#include "nsapi.h" -#include "pool.h" -#include "pblock.h" -#include "io.h" -#include "util.h" -#include "httprequest.h" -#include "conf.h" -#include "vserver.h" - -HTTPRequest *http_request_new() { - HTTPRequest *req = malloc(sizeof(HTTPRequest)); - req->connection = NULL; - req->uri.ptr = NULL; - - HeaderArray *hd = malloc(sizeof(HeaderArray)); - hd->next = NULL; - hd->len = 0; - hd->headers = calloc(16, sizeof(Header)); - hd->alloc = 16; - - req->headers = hd; - - return req; -} - -int handle_request(HTTPRequest *request) { - // handle nsapi request - - // create pool - request->pool = pool_create(); - - // create nsapi data structures - NSAPISession *sn = malloc(sizeof(NSAPISession)); - NSAPIRequest *rq = malloc(sizeof(NSAPIRequest)); - request->rq = rq; - rq->phase = NSAPIAuthTrans; - - // fill session structure - sn->sys_fd = request->connection->fd; - sn->sn.pool = pool_create(); - sn->sn.csd = stream_new_from_fd(request->connection->fd); - sn->sn.client = pblock_create_pool(sn->sn.pool, 8); - sn->sn.next = NULL; - sn->sn.fill = 1; - sn->sn.subject = NULL; - - /* add ip to sn->client pblock */ - char ip_str[INET_ADDRSTRLEN]; - if(inet_ntop( - AF_INET, - &request->connection->address.sin_addr, - ip_str, - INET_ADDRSTRLEN) != NULL) - { - pblock_kvinsert(pb_key_ip, ip_str, INET_ADDRSTRLEN, sn->sn.client); - } - - // init NSAPI request structure - if(request_initialize(request->pool, request, rq) != 0) { - printf("Cannot initialize request structure\n"); - return 1; - } - - // set default virtual server - rq->vs = conf_get_default_vs(); - - - /* Pass request line as "clf-request" */ - pblock_kvinsert( - pb_key_clf_request, - request->request_line.ptr, - request->request_line.length, - rq->rq.reqpb); - - /* Pass method as "method" in reqpb, and also as method_num */ - pblock_kvinsert( - pb_key_method, - request->method.ptr, - request->method.length, - rq->rq.reqpb); - // TODO: method num - //rqRq.rq.method_num = rqHdr->GetMethodNumber(); - //PR_ASSERT(rqRq.rq.method_num != -1 || iStatus); - - /* Pass protocol as "protocol" in reqpb, and also in protv_num */ - pblock_kvinsert( - pb_key_protocol, - request->httpv.ptr, - request->httpv.length, - rq->rq.reqpb); - // TODO: protocol num - - /* Pass any query as "query" in reqpb */ - // TODO: query - - /* Get abs_path part of request URI, and canonicalize the path */ - sstr_t absPath = request->uri; - // TODO: get abs_path - absPath.ptr = util_canonicalize_uri( - request->pool, - absPath.ptr, - absPath.length, - (int*)&absPath.length); - - /* Decode the abs_path */ - // TODO: decode abs_path - - /* Pass the abs_path as "uri" in reqpb */ - // TODO: pass abs_path to reqpb - // TODO: replace this code - pblock_kvinsert( - pb_key_uri, - absPath.ptr, - absPath.length, - rq->rq.reqpb); - - // pass http header to the NSAPI request structure - int hlen = request->headers->len; - HeaderArray *ha = request->headers; - for(int i=0;i<=hlen;i++) { - if(i == hlen) { - ha = ha->next; - if(ha == NULL) { - break; - } - i = 0; - hlen = ha->len; - } - - if(ha->headers[i].name[0] < 90) { - ha->headers[i].name[0] += 32; - } - pblock_nvinsert(ha->headers[i].name, ha->headers[i].value, rq->rq.headers); - } - - /* check for request body and prepare input buffer */ - char *ctlen_str = pblock_findkeyval(pb_key_content_length, rq->rq.headers); - if(ctlen_str) { - int ctlen = atoi(ctlen_str); - - printf("request body length: %d\n", ctlen); - - netbuf *nb = request->netbuf; - - /* create new netbuf */ - NetIOStream *net_io = (NetIOStream*)net_stream_from_fd( - request->connection->fd); - net_io->max_read = ctlen; - - sn->sn.inbuf = malloc(sizeof(netbuf)); - sn->sn.inbuf->sd = net_io; - sn->sn.inbuf->pos = 0; - - /* prepare buffer */ - int cur_input_len = nb->cursize - nb->pos; - if(cur_input_len >= ctlen) { - - /* - * all data is already in the primary input buffer - * just link the new netbuf to the primary buffer - */ - sn->sn.inbuf->maxsize = ctlen; - sn->sn.inbuf->cursize = ctlen; - sn->sn.inbuf->inbuf = nb->inbuf + nb->pos; - } else { - sn->sn.inbuf->maxsize = (ctlen > 2048) ? (2048) : (ctlen); - sn->sn.inbuf->inbuf = malloc(sizeof(sn->sn.inbuf->maxsize)); - - if(cur_input_len > 0) { - /* we have read a part of the request body -> copy to netbuf */ - memcpy(sn->sn.inbuf->inbuf, nb->inbuf+nb->pos, cur_input_len); - } - - sn->sn.inbuf->cursize = cur_input_len; - } - } else { - sn->sn.inbuf = NULL; - } - - - // Send the request to the NSAPI system - nsapi_handle_request(sn, rq); - - return 0; -} - - - -void header_add(HeaderArray *hd, char *name, char *value) { - while(hd->len >= hd->alloc) { - if(hd->next == NULL) { - HeaderArray *block = malloc(sizeof(HeaderArray)); - block->next = NULL; - block->len = 0; - block->headers = calloc(16, sizeof(Header)); - block->alloc = 16; - hd->next = block; - } - hd = hd->next; - } - hd->headers[hd->len].name = name; - hd->headers[hd->len].value = value; - hd->len++; -} - - -/* - * NSAPI Processing - * TODO: add this to new file - */ - -int nsapi_handle_request(NSAPISession *sn, NSAPIRequest *rq) { - // TODO: threadpool - - int r = REQ_NOACTION; - - do { - switch(rq->phase) { - case NSAPIAuthTrans: { - rq->phase++; - nsapi_context_next_stage(&rq->context); - } - case NSAPINameTrans: { - printf(">>> NameTrans\n"); - r = nsapi_nametrans(sn, rq); - if(r != REQ_PROCEED) { - break; - } - rq->phase++; - nsapi_context_next_stage(&rq->context); - } - case NSAPIPathCheck: { - printf(">>> PathCheck\n"); - rq->phase++; - nsapi_context_next_stage(&rq->context); - } - case NSAPIObjectType: { - printf(">>> ObjectType\n"); - r = nsapi_objecttype(sn, rq); - if(r != REQ_PROCEED) { - break; - } - rq->phase++; - nsapi_context_next_stage(&rq->context); - } - case NSAPIService: { - printf(">>> Service\n"); - r = nsapi_service(sn, rq); - if(r != REQ_PROCEED) { - break; - } - rq->phase++; - nsapi_context_next_stage(&rq->context); - } - case NSAPIAddLog: { - printf(">>> AddLog\n"); - rq->phase++; - nsapi_context_next_stage(&rq->context); - } - case REQ_FINISH: { - printf(">>> Finish\n"); - r = nsapi_finish_request(sn, rq); - } - } - } while (r == REQ_RESTART); - - - return r; -} - -int nsapi_finish_request(NSAPISession *sn, NSAPIRequest *rq) { - // TODO: free memory - close(sn->sys_fd); - - return 0; -} - -int nsapi_nametrans(NSAPISession *sn, NSAPIRequest *rq) { - HTTPObjectConfig *objconf = rq->vs->objects; - printf("nsapi_nametrans\n"); - httpd_objset *objset = objset_create(sn->sn.pool); - rq->rq.os = objset; - /* first object in objconf is the default object TODO: make sure it is */ - objset_add_object(sn->sn.pool, objset, objconf->objects[0]); - - httpd_object *obj = objset->obj[0]; /* nametrans only in default object */ - dtable *dt = object_get_dtable(obj, NSAPINameTrans); - - /* execute directives */ - int ret = rq->context.last_req_code; - char *name = NULL; - char *ppath = NULL; - for(int i=NCX_DI(rq);indir;i++) { - directive *d = dt->dirs[i]; - - ret = d->func->func(d->param, (Session*)sn, (Request*)rq); - - /* check for name or ppath */ - name = pblock_findkeyval(pb_key_name, rq->rq.vars); - ppath = pblock_findkeyval(pb_key_ppath, rq->rq.vars); - - /* add additional objects to the objset */ - if(add_objects(objconf, objset, sn, rq, name, ppath) == REQ_ABORTED) { - fprintf(stderr, "add_objects failed\n"); - return REQ_ABORTED; - } - - if(ret != REQ_NOACTION) { - /* - * if a saf is still processing, we need to save the context, to - * process this object at a later time - */ - if(ret == REQ_PROCESSING) { - /* save nsapi context */ - /* add +1 to start next round with next function */ - rq->context.dtable_index = i + 1; - } - - return ret; - } - } - - /* if no function has set the ppath var, translate it to docroot */ - if(ret == REQ_NOACTION && ppath == NULL) { - sstr_t docroot = rq->vs->document_root; - if(docroot.length < 1) { - printf("docroot too short\n"); - return REQ_ABORTED; /* docroot too short */ - } - /* if there is a trailing '/', remove it */ - if(docroot.ptr[docroot.length - 1] == '/') { - docroot.length--; - } - - sstr_t uri = sstr(pblock_findkeyval(pb_key_uri, rq->rq.reqpb)); - - sstr_t translated; - translated.length = docroot.length + uri.length; - translated.ptr = alloca(translated.length + 1); - translated = sstrncat(2, translated, docroot, uri); - - pblock_kvinsert( - pb_key_ppath, - translated.ptr, - translated.length, - rq->rq.vars); - } - - return REQ_PROCEED; -} - -int nsapi_objecttype(NSAPISession *sn, NSAPIRequest *rq) { - printf("nsapi_objecttype\n"); - httpd_objset *objset = rq->rq.os; - - if(NCX_OI(rq) == -1) { - /* object index is undefined -> define correct object index */ - NCX_OI(rq) = objset->pos - 1; - } - - int ret = rq->context.last_req_code; - for(int i=NCX_OI(rq);i>=0;i--) { - httpd_object *obj = objset->obj[i]; - dtable *dt = object_get_dtable(obj, NSAPIObjectType); - - // execute directives - for(int j=0;jndir;j++) { - directive *d = dt->dirs[j]; - - ret = d->func->func(d->param, (Session*)sn, (Request*)rq); - switch(ret) { - case REQ_PROCEED: { - char *type = pblock_findkeyval( - pb_key_content_type, - rq->rq.srvhdrs); - if(type == NULL) { - ret = REQ_NOACTION; - break; - } - return ret; - } - case REQ_PROCESSING: { - /* save nsapi context */ - rq->context.objset_index = i; - - /* add +1 to start next round with next function */ - rq->context.dtable_index = j + 1; - return ret; - } - case REQ_NOACTION: { - break; - } - default: { - return ret; - } - } - } - } - - /* - * No function returned with REQ_PROCEED, but we need a content type. - * If the path ends with a '/', we set the content type to - * 'internal/directory' so that 'index-common' can serve the content. - * Otherwise we set the content type to text/plain - */ - sstr_t path = sstr(pblock_findkeyval(pb_key_ppath, rq->rq.vars)); - sstr_t ct; - if(path.ptr[path.length - 1] == '/') { - /* directory */ - ct = sstrn("internal/directory", 18); - } else { - ct = sstrn("text/plain", 10); - } - pblock_kvinsert(pb_key_content_type, ct.ptr, ct.length, rq->rq.srvhdrs); - - return REQ_PROCEED; -} - -int nsapi_service(NSAPISession *sn, NSAPIRequest *rq) { - printf("nsapi_service\n"); - httpd_objset *objset = rq->rq.os; - - if(NCX_OI(rq) == -1) { - NCX_OI(rq) = objset->pos - 1; - } - - int ret = rq->context.last_req_code; - char *content_type = NULL; - for(int i=NCX_OI(rq);i>=0;i--) { - httpd_object *obj = objset->obj[i]; - dtable *dt = object_get_dtable(obj, NSAPIService); - - // execute directives - for(int j=0;jndir;j++) { - directive *d = dt->dirs[j]; - - /* check type parameter */ - char *dtp = pblock_findkeyval(pb_key_type, d->param); - if(dtp) { - /* type parameter for directive */ - if(!content_type) { - content_type = pblock_findkeyval( - pb_key_content_type, - rq->rq.srvhdrs); - } - /* compare types */ - if(strcmp(dtp, content_type) != 0) { - continue; - } - } - - ret = d->func->func(d->param, (Session*)sn, (Request*)rq); - if(ret != REQ_NOACTION) { - if(ret == REQ_PROCESSING) { - /* save nsapi context */ - rq->context.objset_index = i; - - /* add +1 to start next round with next function */ - rq->context.dtable_index = j + 1; - } - - return ret; - } - } - } - - return ret; -} - -/* - * adds objects with specific name or path to the httpd_objset - */ -int add_objects( - HTTPObjectConfig *objs, - httpd_objset *os, - NSAPISession *sn, - NSAPIRequest *rq, - char *name, - char *path) -{ - /* first, add all objects with a matching path */ - /* TODO */ - - - /* add object with object with matching name */ - if(name == NULL) { - return REQ_PROCEED; - } - - for(int i=0;inobj;i++) { - httpd_object *obj = objs->objects[i]; - - if(obj->name && !strcmp(name, obj->name)) { - printf("name is %s -> add object %s\n", name, obj->name); - objset_add_object(sn->sn.pool, os, obj); - } - } - - return REQ_PROCEED; -}