http.c
author Tero Marttila <terom@fixme.fi>
Wed, 27 Aug 2008 21:30:32 +0300
changeset 41 540737bf6bac
parent 27 1e79b4cc8f1b
permissions -rw-r--r--
sending requests, and partial support for receiving -- incomplete, not tested
#include <sys/queue.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>

#include <event2/event_struct.h>

#include "http.h"
#include "common.h"

int http_qarg_parse (struct evhttp_request *request, struct http_qarg *qarg_spec) {
    // our return code
    int error = -1;

    // get the uri from the request
    const char *uri = evhttp_request_get_uri(request);
    
    // the keyval list that we get from evhttp_parse_query
    struct evkeyval *qarg;
    struct evkeyvalq qargs;
    
    // parse the uri into a list
    evhttp_parse_query(uri, &qargs);
    
    // the http_qarg that we iterate with
    struct http_qarg *qarg_info;

    // iterate over the list of given query arugments
    TAILQ_FOREACH(qarg, &qargs, next) {
        
        // match them against our http_qarg structs
        for (qarg_info = qarg_spec; qarg_info->hqa_type != QARG_END; qarg_info++) {
            if (strcmp(qarg->key, qarg_info->hqa_key) == 0) {
                // found a match
                
                // extract a value from the qarg
                char *cptr = NULL;
                unsigned long long int uint_val;

                switch (qarg_info->hqa_type) {
                    case QARG_UINT16 :
                    case QARG_UINT32 :
                    case QARG_UINT64 :
                        uint_val = strtoull(qarg->value, &cptr, 10);

                        if (
                                (*qarg->value == '\0' || *cptr != '\0')
                            ||  (qarg_info->hqa_type == QARG_UINT16 && uint_val > SHRT_MAX)
                            ||  (qarg_info->hqa_type == QARG_UINT32 && uint_val > UINT_MAX)
                            ||  (qarg_info->hqa_type == QARG_UINT64 && uint_val > ULLONG_MAX)
                        )
                            ERROR("invalid QARG_UINT: %s: %s -> %lld", qarg->key, qarg->value, uint_val);
                        
                        if (qarg_info->hqa_type == QARG_UINT16)
                            *((unsigned short int *) qarg_info->hqa_addr) = (unsigned short int) uint_val;
                        else if (qarg_info->hqa_type == QARG_UINT32)
                            *((unsigned int *) qarg_info->hqa_addr) = (unsigned int) uint_val;
                        else if (qarg_info->hqa_type == QARG_UINT64)
                            *((unsigned long long int *) qarg_info->hqa_addr) = (unsigned long long int) uint_val;
                        else
                            assert(0);

                        break;
                    
                    case QARG_INVALID :
                        ERROR("QARG_INVALID: %s: %s", qarg->key, qarg->value);

                    default :
                        FATAL("invalid qarg_info->hqa_type: %d", qarg_info->hqa_type);
                }

                // clear the QARG_REQUIRED flag
                qarg_info->hqa_flags &= ~QARG_REQUIRED;
            }
        }
    }

    // missing qargs?
    for (qarg_info = qarg_spec; qarg_info->hqa_type != QARG_END; qarg_info++) {
        if (qarg_info->hqa_flags & QARG_REQUIRED)
            ERROR("missing value for required qarg: %s", qarg_info->hqa_key);
    }

    // success
    error = 0;
error:    

    // clean up the qargs (badly named functions :< )
    evhttp_clear_headers(&qargs);
    
    return error;
}