Beispiel #1
0
/*
 * @METHOD_NAME: end
 * @METHOD_DESC: It indicate that the full response for the request has been ended. No
 * extra calls will take place after invoke this method as it contains an implicit return
 * for the active callback.
 *
 * Internally, this function send the HTTP response headers, flush the enqueued body content
 * and release the resources used by the service. The connection could keep open depending
 * of the HTTP transaction.
 *
 * @METHOD_PARAM: dr the request context information hold by a duda_request_t type
 * @METHOD_PARAM: end_cb Defines a callback function to be invoked once the response object
 * finish flushing the pending data and clearing up the resources used.
 * @METHOD_RETURN: Upon successful completion it returns 0, otherwise it can generate an explicit
 * program exit due to bad API usage.
 */
int duda_response_end(duda_request_t *dr, void (*end_cb) (duda_request_t *))
{
    int ret;

    /* Make sure the caller set a valid HTTP response code */
    if (dr->sr->headers.status == 0 && dr->_st_http_headers_off == MK_FALSE) {
        duda_api_exception(dr, "Callback did not set the HTTP response status");
        abort();
    }

    dr->end_callback = end_cb;
    ret = duda_response_send_headers(dr);
    if (ret == -1) {
        return -1;
    }

    /* flush some enqueued content */
    ret = duda_queue_flush(dr);

    /*
     * The lesson of the day Feb 2, 2013: I must NEVER forget that when sending the
     * HTTP headers, Monkey sets the TCP_CORK flag ON in the socket in case the caller
     * wanted to send more data so we let know the Kernel to buffer a little more bytes.
     * If we do not set TCP_CORK to OFF we will face some delays in the response.
     *
     * KeepAlive was very slow due to this bug. More than 4 hours to found this silly bug.
     */
    mk_api->socket_cork_flag(dr->cs->socket, TCP_CORK_OFF);

    if (ret == 0) {
        duda_service_end(dr);
    }

    return 0;
}
Beispiel #2
0
/*
 * @METHOD_NAME: send_headers
 * @METHOD_DESC: Send the HTTP response headers
 * @METHOD_PARAM: dr the request context information hold by a duda_request_t type
 * @METHOD_RETURN: Upon successful completion it returns 0, on error returns -1.
 */
int duda_response_send_headers(duda_request_t *dr)
{
    int r;
    size_t bytes = 0;
    struct mk_list *head;
    struct mk_stream *stream;

    if (dr->_st_http_headers_off == MK_TRUE) {
        dr->_st_http_headers_sent = MK_TRUE;
        return 0;
    }

    if (dr->_st_http_headers_sent == MK_TRUE) {
        return -1;
    }

    if (dr->_st_body_writes > 0) {
        /* FIXME: Console error */
        return -1;
    }

    /* Calculate body length */
    if (dr->_st_http_content_length == -2) {
        /* FIXME
        mk_list_foreach(head, &dr->channel.streams) {
            stream = mk_list_entry(head, struct mk_stream, _head);
            bytes += stream->bytes_total;
        }
        dr->request->headers.content_length = bytes;
        */
    }
    else if (dr->_st_http_content_length >= 0) {
        dr->request->headers.content_length = dr->_st_http_content_length;
    }

    if (dr->request->headers.status <= 0) {
        duda_api_exception(dr, "Callback did not set the HTTP response status");
        abort();
    }

    r = mk_api->header_prepare(dr->session, dr->request);
    if (r != 0) {
        /* FIXME: Console error */
        return -1;
    }

    /* Change flag status */
    dr->_st_http_headers_sent = MK_TRUE;

    /*
     * Concatenate list, link temporal dr->channel nodes to parent channel
     * streams list.
     */

    /* FIXME: dst-2 */
    //mk_list_cat(&dr->channel.streams, &(dr->session->channel)->streams);

    return 0;
}