Skip to content
This repository has been archived by the owner on Jun 30, 2021. It is now read-only.

Commit

Permalink
added example request pausing app
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFrench committed Nov 30, 2017
1 parent 3467382 commit 282a1c9
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 1 deletion.
4 changes: 3 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ add_executable(test_client EXCLUDE_FROM_ALL test_client.c)
add_executable(test_query EXCLUDE_FROM_ALL test_query.c)
add_executable(test_perf EXCLUDE_FROM_ALL test_perf.c)
add_executable(example_vhost EXCLUDE_FROM_ALL example_vhost.c)
add_executable(example_pause EXCLUDE_FROM_ALL example_pause.c)

if (NOT EVHTP_DISABLE_EVTHR)
add_executable(test_proxy EXCLUDE_FROM_ALL test_proxy.c)
Expand All @@ -21,7 +22,8 @@ target_link_libraries(test_client evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
target_link_libraries(test_query evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
target_link_libraries(test_perf evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
target_link_libraries(example_vhost evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
target_link_libraries(example_pause evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})

add_dependencies(examples example_vhost test_extensive test_basic test_vhost test_client test_query test_perf)
add_dependencies(examples example_pause example_vhost test_extensive test_basic test_vhost test_client test_query test_perf)


125 changes: 125 additions & 0 deletions examples/example_pause.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Quick example of how to pause a request, and in this case, simply
* set a timer to emit the response 10 seconds later.
*
* This is a good way to long running tasks before responding (thus
* not blocking any other processing).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>

#include "../log.h"
#include "internal.h"
#include "evhtp/evhtp.h"

struct paused_request_ {
struct event * _timeoutev;
struct timeval _timeout;
evhtp_request_t * _request;
};

/* once 10 seconds has passed, this function is called, it will
* resume the request, and send the final response back to the
* client.
*/
static void
http_resume__callback_(int sock, short events, void * arg) {
struct paused_request_ * preq;
evhtp_request_t * req;

evhtp_assert(arg != NULL);

preq = (struct paused_request_ *)arg;
req = preq->_request;
evhtp_assert(req != NULL);

event_free(preq->_timeoutev);
free(preq);

/* add the current time to our output buffer to the client */
evbuffer_add_printf(req->buffer_out, "time end %ld\n", time(NULL));

/* inform the evhtp API to resume this connection request */
evhtp_request_resume(req);

/* finally send the response to the client, YAY! */
evhtp_send_reply(req, EVHTP_RES_OK);
}

/* this is our default callback, it is the one who sets up the evtimer
* that triggers the response after 10 seconds.
*/
static void
http_pause__callback_(evhtp_request_t * req, void * arg) {
struct timeval * tv = (struct timeval *)arg;
struct paused_request_ * preq;

/* allocate a little structure that holds our evtimer and the
* pending request, se the timeout to 10 seconds.
*/
preq = malloc(sizeof(*preq));
evhtp_alloc_assert(preq);

preq->_request = req;
preq->_timeout.tv_sec = tv->tv_sec;
preq->_timeout.tv_usec = tv->tv_usec;

/* when 10 seconds is up, the function http_resume__callback_ will
* be called, this function will actually send the response.
*/
preq->_timeoutev = evtimer_new(req->htp->evbase, http_resume__callback_, preq);
evhtp_alloc_assert(preq->_timeoutev);

/* just for debugging, add the time the request was first seen */
evbuffer_add_printf(req->buffer_out, "time start %ld\n", time(NULL));

/* add the timer to the event loop */
evtimer_add(preq->_timeoutev, &preq->_timeout);

/* notify the evhtp API to "pause" this request (meaning it will no
* longer do any work on this connection until it is "resumed".
*/
evhtp_request_pause(req);
}

int
main(int argc, char ** argv) {
evhtp_t * htp;
struct event_base * evbase;
struct timeval timeo = { 10, 0 };

evbase = event_base_new();
evhtp_alloc_assert(evbase);

htp = evhtp_new(evbase, NULL);
evhtp_alloc_assert(htp);

/* we just set the default callback for any requests to
* the function that pauses the session, sets a timer,
* and 10 seconds later, sends the response.
*/
evhtp_set_gencb(htp, http_pause__callback_, &timeo);

evhtp_bind_socket(htp, "127.0.0.1", 0, 128);
{
struct sockaddr_in sin;
socklen_t len = sizeof(struct sockaddr);
uint16_t port;

getsockname(
evconnlistener_get_fd(htp->server),
(struct sockaddr *)&sin, &len);

port = ntohs(sin.sin_port);

log_info("request will be delayed for 10 seconds with: curl http://127.0.0.1:%d/", port);
}

event_base_loop(evbase, 0);


return 0;
}

0 comments on commit 282a1c9

Please sign in to comment.