Exemplo n.º 1
0
void mk_cache_worker_exit()
{
    char *cache_error;

    /* Cache header request -> last modified */
    mk_ptr_free(MK_TLS_GET(mk_tls_cache_header_lm));
    mk_mem_free(MK_TLS_GET(mk_tls_cache_header_lm));

    /* Cache header request -> content length */
    mk_ptr_free(MK_TLS_GET(mk_tls_cache_header_cl));
    mk_mem_free(MK_TLS_GET(mk_tls_cache_header_cl));

    /* Cache iov header struct */
    mk_iov_free(MK_TLS_GET(mk_tls_cache_iov_header));

    /* Cache gmtime buffer */
    mk_mem_free(MK_TLS_GET(mk_tls_cache_gmtime));

    /* Cache the most used text representations of utime2gmt */
    mk_mem_free(MK_TLS_GET(mk_tls_cache_gmtext));

    /* Cache buffer for strerror_r(2) */
    cache_error = pthread_getspecific(mk_utils_error_key);
    mk_mem_free(cache_error);
}
Exemplo n.º 2
0
void mk_server_listen_free()
{
    struct mk_list *list;
    struct mk_list *tmp;
    struct mk_list *head;
    struct mk_server_listen *listener;

    list = MK_TLS_GET(mk_tls_server_listen);
    mk_list_foreach_safe(head, tmp, list) {
        listener = mk_list_entry(head, struct mk_server_listen, _head);
        mk_list_del(&listener->_head);
        mk_mem_free(listener);
    }
Exemplo n.º 3
0
static void mk_utils_gmt_cache_add(char *data, time_t time)
{
    unsigned int i, min = 0;
    struct mk_gmt_cache *gcache = MK_TLS_GET(mk_tls_cache_gmtext);

    for (i = 1; i < MK_GMT_CACHES; i++) {
        if (gcache[i].hits < gcache[min].hits)
            min = i;
    }

    gcache[min].hits = 1;
    gcache[min].time = time;
    memcpy(gcache[min].text, data, 32);
}
Exemplo n.º 4
0
static int mk_utils_gmt_cache_get(char **data, time_t date)
{
    unsigned int i;
    struct mk_gmt_cache *gcache = MK_TLS_GET(mk_tls_cache_gmtext);

    if (mk_unlikely(!gcache)) {
        return MK_FALSE;
    }

    for (i = 0; i < MK_GMT_CACHES; i++) {
        if (date == gcache[i].time) {
            memcpy(*data, gcache[i].text, 32);
            gcache[i].hits++;
            return MK_TRUE;
        }
    }

    return MK_FALSE;
}
Exemplo n.º 5
0
/* Send response headers */
int mk_header_prepare(struct mk_http_session *cs, struct mk_http_request *sr,
                      struct mk_server *server)
{
    int i = 0;
    unsigned long len = 0;
    char *buffer = 0;
    mk_ptr_t response;
    struct response_headers *sh;
    struct mk_iov *iov;

    sh = &sr->headers;
    iov = &sh->headers_iov;

    /* HTTP Status Code */
    if (sh->status == MK_CUSTOM_STATUS) {
        response.data = sh->custom_status.data;
        response.len = sh->custom_status.len;
    }
    else {
        for (i = 0; i < status_response_len; i++) {
            if (status_response[i].status == sh->status) {
                response.data = status_response[i].response;
                response.len  = status_response[i].length;
                break;
            }
        }
    }

    /* Invalid status set */
    mk_bug(i == status_response_len);

    mk_iov_add(iov, response.data, response.len, MK_FALSE);

    /*
     * Preset headers (mk_clock.c):
     *
     * - Server
     * - Date
     */
    mk_iov_add(iov,
               headers_preset.data,
               headers_preset.len,
               MK_FALSE);

    /* Last-Modified */
    if (sh->last_modified > 0) {
        mk_ptr_t *lm = MK_TLS_GET(mk_tls_cache_header_lm);
        lm->len = mk_utils_utime2gmt(&lm->data, sh->last_modified);

        mk_iov_add(iov,
                   mk_header_last_modified.data,
                   mk_header_last_modified.len,
                   MK_FALSE);
        mk_iov_add(iov,
                   lm->data,
                   lm->len,
                   MK_FALSE);
    }

    /* Connection */
    if (sh->connection == 0) {
        if (cs->close_now == MK_FALSE) {
            if (sr->connection.len > 0) {
                if (sr->protocol != MK_HTTP_PROTOCOL_11) {
                    mk_iov_add(iov,
                               mk_header_conn_ka.data,
                               mk_header_conn_ka.len,
                               MK_FALSE);
                }
            }
        }
        else {
            mk_iov_add(iov,
                       mk_header_conn_close.data,
                       mk_header_conn_close.len,
                       MK_FALSE);
        }
    }
    else if (sh->connection == MK_HEADER_CONN_UPGRADED) {
             mk_iov_add(iov,
                        mk_header_conn_upgrade.data,
                        mk_header_conn_upgrade.len,
                        MK_FALSE);
    }

    /* Location */
    if (sh->location != NULL) {
        mk_iov_add(iov,
                   mk_header_short_location.data,
                   mk_header_short_location.len,
                   MK_FALSE);

        mk_iov_add(iov,
                   sh->location,
                   strlen(sh->location),
                   MK_TRUE);
    }

    /* allowed methods */
    if (sh->allow_methods.len > 0) {
        mk_iov_add(iov,
                   mk_header_allow.data,
                   mk_header_allow.len,
                   MK_FALSE);
        mk_iov_add(iov,
                   sh->allow_methods.data,
                   sh->allow_methods.len,
                   MK_FALSE);
    }

    /* Content type */
    if (sh->content_type.len > 0) {
        mk_iov_add(iov,
                   sh->content_type.data,
                   sh->content_type.len,
                   MK_FALSE);
    }

    /*
     * Transfer Encoding: the transfer encoding header is just sent when
     * the response has some content defined by the HTTP status response
     */
    switch (sh->transfer_encoding) {
    case MK_HEADER_TE_TYPE_CHUNKED:
        mk_iov_add(iov,
                   mk_header_te_chunked.data,
                   mk_header_te_chunked.len,
                   MK_FALSE);
        break;
    }

    /* E-Tag */
    if (sh->etag_len > 0) {
        mk_iov_add(iov, sh->etag_buf, sh->etag_len, MK_FALSE);
    }

    /* Content-Encoding */
    if (sh->content_encoding.len > 0) {
        mk_iov_add(iov, mk_header_content_encoding.data,
                   mk_header_content_encoding.len,
                   MK_FALSE);
        mk_iov_add(iov, sh->content_encoding.data,
                   sh->content_encoding.len,
                   MK_FALSE);
    }

    /* Content-Length */
    if (sh->content_length >= 0 && sh->transfer_encoding != 0) {
        /* Map content length to MK_POINTER */
        mk_ptr_t *cl = MK_TLS_GET(mk_tls_cache_header_cl);
        mk_string_itop(sh->content_length, cl);

        /* Set headers */
        mk_iov_add(iov,
                   mk_header_content_length.data,
                   mk_header_content_length.len,
                   MK_FALSE);
        mk_iov_add(iov,
                   cl->data,
                   cl->len,
                   MK_FALSE);
    }

    if ((sh->content_length != 0 && (sh->ranges[0] >= 0 || sh->ranges[1] >= 0)) &&
        server->resume == MK_TRUE) {
        buffer = 0;

        /* yyy- */
        if (sh->ranges[0] >= 0 && sh->ranges[1] == -1) {
            mk_string_build(&buffer,
                            &len,
                            "%s bytes %d-%ld/%ld\r\n",
                            RH_CONTENT_RANGE,
                            sh->ranges[0],
                            (sh->real_length - 1), sh->real_length);
            mk_iov_add(iov, buffer, len, MK_TRUE);
        }

        /* yyy-xxx */
        if (sh->ranges[0] >= 0 && sh->ranges[1] >= 0) {
            mk_string_build(&buffer,
                            &len,
                            "%s bytes %d-%d/%ld\r\n",
                            RH_CONTENT_RANGE,
                            sh->ranges[0], sh->ranges[1], sh->real_length);

            mk_iov_add(iov, buffer, len, MK_TRUE);
        }

        /* -xxx */
        if (sh->ranges[0] == -1 && sh->ranges[1] > 0) {
            mk_string_build(&buffer,
                            &len,
                            "%s bytes %ld-%ld/%ld\r\n",
                            RH_CONTENT_RANGE,
                            (sh->real_length - sh->ranges[1]),
                            (sh->real_length - 1), sh->real_length);
            mk_iov_add(iov, buffer, len, MK_TRUE);
        }
    }

    if (sh->upgrade == MK_HEADER_UPGRADED_H2C) {
        mk_iov_add(iov, mk_header_upgrade_h2c.data, mk_header_upgrade_h2c.len,
                   MK_FALSE);
    }


    if (sh->cgi == SH_NOCGI || sh->breakline == MK_HEADER_BREAKLINE) {
        if (!sr->headers._extra_rows) {
            mk_iov_add(iov, mk_iov_crlf.data, mk_iov_crlf.len,
                       MK_FALSE);
        }
        else {
            mk_iov_add(sr->headers._extra_rows, mk_iov_crlf.data,
                       mk_iov_crlf.len, MK_FALSE);
        }
    }

    /*
     * Configure the Stream to dispatch the headers
     */

    /* Set the IOV input stream */
    sr->in_headers.buffer      = iov;
    sr->in_headers.bytes_total = iov->total_len;
    sr->in_headers.cb_finished = mk_header_cb_finished;

    if (sr->headers._extra_rows) {
        /* Our main sr->stream contains the main headers (header_iov)
         * and 'may' have already some linked data. If we have some
         * extra headers rows we need to link this IOV right after
         * the main header_iov.
         */
        struct mk_stream_input *in = &sr->in_headers_extra;
        in->type        = MK_STREAM_IOV;
        in->dynamic     = MK_FALSE;
        in->cb_consumed = NULL;
        in->cb_finished = cb_stream_iov_extended_free;
        in->stream      = &sr->stream;
        in->buffer      = sr->headers._extra_rows;
        in->bytes_total = sr->headers._extra_rows->total_len;

        mk_list_add_after(&sr->in_headers_extra._head,
                          &sr->in_headers._head,
                          &sr->stream.inputs);
    }

    sh->sent = MK_TRUE;

    return 0;
}
Exemplo n.º 6
0
/*
 *This function given a unix time, set in a mk_ptr_t
 * the date in the RFC1123 format like:
 *
 *    Wed, 23 Jun 2010 22:32:01 GMT
 *
 * it also adds a 'CRLF' at the end
 */
int mk_utils_utime2gmt(char **data, time_t date)
{
    const int size = 31;
    unsigned short year, mday, hour, min, sec;
    char *buf=0;
    struct tm *gtm;

    if (date == 0) {
        if ((date = time(NULL)) == -1) {
            return -1;
        }
    }
    else {
        /* Maybe it's converted already? */
        if (mk_utils_gmt_cache_get(data, date) == MK_TRUE) {
            return size;
        }
    }

    /* Convert unix time to struct tm */
    gtm = MK_TLS_GET(mk_tls_cache_gmtime);

    /* If this function was invoked from a non-thread context it should exit */
    mk_bug(!gtm);
    gtm = gmtime_r(&date, gtm);
    if (!gtm) {
        return -1;
    }

    /* struct tm -> tm_year counts number of years after 1900 */
    year = gtm->tm_year + 1900;

    /* Signed division is slow, by using unsigned we gain 25% speed */
    mday = gtm->tm_mday;
    hour = gtm->tm_hour;
    min = gtm->tm_min;
    sec = gtm->tm_sec;

    /* Compose template */
    buf = *data;

    /* Week day */
    memcpy(buf, mk_date_wd[gtm->tm_wday], 5);
    buf += 5;

    /* Day of the month */
    *buf++ = ('0' + (mday / 10));
    *buf++ = ('0' + (mday % 10));
    *buf++ = ' ';

    /* Month */
    memcpy(buf, mk_date_ym[gtm->tm_mon], 4);
    buf += 4;

    /* Year */
    *buf++ = ('0' + (year / 1000) % 10);
    *buf++ = ('0' + (year / 100) % 10);
    *buf++ = ('0' + (year / 10) % 10);
    *buf++ = ('0' + (year % 10));
    *buf++ = ' ';

    /* Hour */
    *buf++ = ('0' + (hour / 10));
    *buf++ = ('0' + (hour % 10));
    *buf++ = ':';

    /* Minutes */
    *buf++ = ('0' + (min / 10));
    *buf++ = ('0' + (min % 10));
    *buf++ = ':';

    /* Seconds */
    *buf++ = ('0' + (sec / 10));
    *buf++ = ('0' + (sec % 10));

    /* GMT Time zone + CRLF */
    memcpy(buf, " GMT\r\n\0", 7);

    /* Add new entry to the cache */
    mk_utils_gmt_cache_add(*data, date);

    /* Set mk_ptr_t data len */
    return size;
}