Initial commit
This commit is contained in:
commit
ea3ff86b28
9 changed files with 648 additions and 0 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "http_parser"]
|
||||
path = http_parser
|
||||
url = https://github.com/ry/http-parser.git
|
37
CMakeLists.txt
Normal file
37
CMakeLists.txt
Normal file
|
@ -0,0 +1,37 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
project(reason)
|
||||
|
||||
set(PROJECT_MAJOR_VERSION 0)
|
||||
set(PROJECT_MINOR_VERSION 1)
|
||||
set(PROJECT_PATCH_VERSION 0)
|
||||
|
||||
set (PROJECT_VERSION ${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION})
|
||||
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
|
||||
|
||||
include(BaseConfig)
|
||||
|
||||
message("Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
message("Std CFLAGS: ${CMAKE_C_FLAGS}")
|
||||
message("Dbg CFLAGS: ${CMAKE_C_FLAGS_DEBUG}")
|
||||
message("Rel CFLAGS: ${CMAKE_C_FLAGS_RELEASE}")
|
||||
|
||||
find_package(LibEvent)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/http_parser
|
||||
)
|
||||
|
||||
set(LIBEVHTP_EXTERNAL_LIBS
|
||||
${LIBEVENT_LIBRARY}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/build
|
||||
)
|
||||
set(LIBEVHTP_SOURCES http_parser/http_parser.c evhtp.c)
|
||||
|
||||
add_library(libevhtp STATIC ${LIBEVHTP_SOURCES})
|
||||
set_target_properties(libevhtp PROPERTIES OUTPUT_NAME "evhtp")
|
||||
target_link_libraries(libevhtp ${LIVEVHTP_EXTERNAL_LIBS})
|
||||
|
||||
add_executable(test test.c)
|
||||
target_link_libraries(test libevhtp event)
|
20
CMakeModules/BaseConfig.cmake
Normal file
20
CMakeModules/BaseConfig.cmake
Normal file
|
@ -0,0 +1,20 @@
|
|||
if (CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
set(RSN_BASE_C_FLAGS "-std=c99 -Wall")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${RSN_BASE_C_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${RSN_BASE_C_FLAGS} -DDEBUG -ggdb")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${RSN_BASE_C_FLAGS}")
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshorten-64-to-32 -D_BSD_SOURCE")
|
||||
endif(APPLE)
|
||||
|
||||
if (UNIX)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_BSD_SOURCE -D_POSIX_C_SOURCE=199309L")
|
||||
endif(UNIX)
|
||||
|
||||
endif(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif(NOT CMAKE_BUILD_TYPE)
|
21
CMakeModules/FindLibEvent.cmake
Normal file
21
CMakeModules/FindLibEvent.cmake
Normal file
|
@ -0,0 +1,21 @@
|
|||
# - Try to find the LibEvent config processing library
|
||||
# Once done this will define
|
||||
#
|
||||
# LIBEVENT_FOUND - System has LibEvent
|
||||
# LIBEVENT_INCLUDE_DIR - the LibEvent include directory
|
||||
# LIBEVENT_LIBRARIES 0 The libraries needed to use LibEvent
|
||||
|
||||
FIND_PATH(LIBEVENT_INCLUDE_DIR NAMES event.h)
|
||||
FIND_LIBRARY(LIBEVENT_LIBRARY NAMES event)
|
||||
FIND_LIBRARY(LIBEVENT_CORE_LIBRARY NAMES event_core)
|
||||
FIND_LIBRARY(LIBEVENT_PTHREADS_LIBRARY NAMES event_pthreads)
|
||||
FIND_LIBRARY(LIBEVENT_EXTRA_LIBRARY NAMES event_extra)
|
||||
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEvent DEFAULT_MSG LIBEVENT_LIBRARY LIBEVENT_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEventPthreads DEFAULT_MSG LIBEVENT_PTHREADS_LIBRARY LIBEVENT_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEventCore DEFAULT_MSG LIBEVENT_CORE_LIBRARY LIBEVENT_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibEventExtra DEFAULT_MSG LIBEVENT_EXTRA_LIBRARY LIBEVENT_INCLUDE_DIR)
|
||||
|
||||
MARK_AS_ADVANCED(LIBEVENT_INCLUDE_DIR LIBEVENT_LIBRARY LIBEVENT_PTHREADS_LIBRARY LIBEVENT_CORE_LIBRARY LIBEVENT_EXTRA_LIBRARY)
|
0
build/placeholder
Normal file
0
build/placeholder
Normal file
374
evhtp.c
Normal file
374
evhtp.c
Normal file
|
@ -0,0 +1,374 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "evhtp.h"
|
||||
|
||||
evhtp_request_t *
|
||||
evhtp_request_new(void) {
|
||||
evhtp_request_t * request = NULL;
|
||||
|
||||
if (!(request = calloc(sizeof(evhtp_request_t), sizeof(char)))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&request->headers);
|
||||
return request;
|
||||
}
|
||||
|
||||
int
|
||||
evhtp_conn_hook(evhtp_connection_t * conn, evhtp_hook_type type, void * cb) {
|
||||
if (conn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->hooks == NULL) {
|
||||
if (!(conn->hooks = calloc(sizeof(evhtp_conn_hooks_t), sizeof(char)))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case EVHTP_HOOK_POST_HEADERS:
|
||||
conn->hooks->post_headers_cb = (evhtp_hook_post_headers)cb;
|
||||
break;
|
||||
case EVHTP_HOOK_SINGLE_HEADER:
|
||||
conn->hooks->single_header_cb = (evhtp_hook_single_header)cb;
|
||||
break;
|
||||
case EVHTP_HOOK_ON_PATH:
|
||||
conn->hooks->path_cb = (evhtp_hook_on_path)cb;
|
||||
break;
|
||||
case EVHTP_HOOK_ON_BODY_READ:
|
||||
conn->hooks->body_read_cb = (evhtp_hook_on_body_read)cb;
|
||||
break;
|
||||
case EVHTP_HOOK_COMPLETE:
|
||||
conn->hooks->complete_cb = (evhtp_hook_complete)cb;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
evhtp_headers_for_each(evhtp_headers_t * headers, evhtp_headers_iter_cb cb, void * arg) {
|
||||
evhtp_header_t * header = NULL;
|
||||
|
||||
if (!headers || !cb) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(header, headers, next) {
|
||||
int res;
|
||||
|
||||
if ((res = cb(header, arg))) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_start_cb(http_parser * p) {
|
||||
evhtp_connection_t * conn = NULL;
|
||||
|
||||
if (!(conn = (evhtp_connection_t *)p->data)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(conn->request = evhtp_request_new())) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_headers_complete_cb(http_parser * p) {
|
||||
evhtp_connection_t * conn = NULL;
|
||||
|
||||
if (!(conn = (evhtp_connection_t *)p->data)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->hooks && conn->hooks->post_headers_cb) {
|
||||
evhtp_headers_t * hdrs = &conn->request->headers;
|
||||
|
||||
if (conn->hooks->post_headers_cb(conn, hdrs, conn->arg) != EVHTP_RES_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
conn->request->method = p->method;
|
||||
conn->request->major = p->http_major;
|
||||
conn->request->minor = p->http_minor;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_end_cb(http_parser * p) {
|
||||
evhtp_connection_t * conn = NULL;
|
||||
|
||||
if (!(conn = (evhtp_connection_t *)p->data)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->hooks && conn->hooks->complete_cb) {
|
||||
if (conn->hooks->complete_cb(conn, conn->request, conn->arg) != EVHTP_RES_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_path_cb(http_parser * p, const char * buf, size_t len) {
|
||||
evhtp_connection_t * conn = NULL;
|
||||
char * uri;
|
||||
|
||||
if (len == 0 || buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(conn = (evhtp_connection_t *)p->data)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn->request->uri = malloc(len + 1);
|
||||
conn->request->uri[len] = '\0';
|
||||
|
||||
memcpy(conn->request->uri, buf, len);
|
||||
|
||||
if (conn->hooks && conn->hooks->path_cb) {
|
||||
if (conn->hooks->path_cb(conn, conn->request->uri, conn->arg) != EVHTP_RES_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_query_str_cb(http_parser * p, const char * buf, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_url_cb(http_parser * p, const char * buf, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_fragment_cb(http_parser * p, const char * buf, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_header_key_cb(http_parser * p, const char * buf, size_t len) {
|
||||
evhtp_header_t * header = NULL;
|
||||
evhtp_connection_t * conn = NULL;
|
||||
|
||||
if (!(conn = (evhtp_connection_t *)p->data)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(header = calloc(sizeof(evhtp_header_t), sizeof(char)))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
header->key = malloc(len + 1);
|
||||
header->key[len] = '\0';
|
||||
|
||||
memcpy(header->key, buf, len);
|
||||
|
||||
TAILQ_INSERT_TAIL(&conn->request->headers, header, next);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_header_val_cb(http_parser * p, const char * buf, size_t len) {
|
||||
evhtp_header_t * header = NULL;
|
||||
evhtp_connection_t * conn = NULL;
|
||||
|
||||
if (!(conn = (evhtp_connection_t *)p->data)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(header = TAILQ_LAST(&conn->request->headers, evhtp_headers))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
header->val = malloc(len + 1);
|
||||
header->val[len] = '\0';
|
||||
|
||||
memcpy(header->val, buf, len);
|
||||
|
||||
if (conn->hooks && conn->hooks->single_header_cb) {
|
||||
if (conn->hooks->single_header_cb(conn, header, conn->arg) != EVHTP_RES_OK) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_htp_body_cb(http_parser * p, const char * buf, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
evhtp_connection_free(evhtp_connection_t * conn) {
|
||||
if (conn == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn->hooks) {
|
||||
/* evhtp_conn_hooks_free() */
|
||||
free(conn->hooks);
|
||||
}
|
||||
|
||||
if (conn->parser) {
|
||||
free(conn->parser);
|
||||
}
|
||||
|
||||
if (conn->bev) {
|
||||
bufferevent_free(conn->bev);
|
||||
}
|
||||
|
||||
free(conn);
|
||||
}
|
||||
|
||||
static void
|
||||
_htp_recv_cb(evbev_t * bev, void * arg) {
|
||||
evhtp_connection_t * conn = NULL;
|
||||
|
||||
struct evbuffer * ibuf = NULL;
|
||||
size_t nread = 0;
|
||||
|
||||
if (!(conn = (evhtp_connection_t *)arg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ibuf = bufferevent_get_input(bev);
|
||||
nread = http_parser_execute(conn->parser, &conn->evhtp->psets,
|
||||
(const char *)evbuffer_pullup(ibuf, evbuffer_get_length(ibuf)),
|
||||
evbuffer_get_length(ibuf));
|
||||
|
||||
evbuffer_drain(ibuf, nread);
|
||||
}
|
||||
|
||||
static void
|
||||
_htp_accept_cb(evserv_t * serv, int fd, struct sockaddr * s, int sl, void * arg) {
|
||||
evhtp_t * htp = NULL;
|
||||
evbase_t * evbase = NULL;
|
||||
evbev_t * bev = NULL;
|
||||
evhtp_connection_t * conn = NULL;
|
||||
|
||||
if (!(htp = (evhtp_t *)arg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (htp->pre_accept_cb != NULL) {
|
||||
if (htp->pre_accept_cb(fd, s, sl, htp->arg) != EVHTP_RES_OK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
evbase = evconnlistener_get_base(serv);
|
||||
bev = bufferevent_socket_new(evbase, fd, BEV_OPT_CLOSE_ON_FREE);
|
||||
|
||||
if (!(conn = calloc(sizeof(evhtp_connection_t), sizeof(char)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
conn->bev = bev;
|
||||
conn->evhtp = htp;
|
||||
conn->parser = malloc(sizeof(http_parser));
|
||||
conn->parser->data = conn;
|
||||
|
||||
http_parser_init(conn->parser, HTTP_REQUEST);
|
||||
|
||||
if (htp->post_accept_cb != NULL) {
|
||||
if (htp->post_accept_cb(conn, htp->arg) != EVHTP_RES_OK) {
|
||||
evhtp_connection_free(conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bufferevent_setcb(bev, _htp_recv_cb, NULL, NULL, (void *)conn);
|
||||
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
||||
} /* _htp_accept_cb */
|
||||
|
||||
int
|
||||
evhtp_set_pre_accept_cb(evhtp_t * htp, evhtp_pre_accept cb) {
|
||||
if (htp == NULL || cb == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
htp->pre_accept_cb = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
evhtp_set_post_accept_cb(evhtp_t * htp, evhtp_post_accept cb) {
|
||||
if (htp == NULL || cb == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
htp->post_accept_cb = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
evhtp_t *
|
||||
evhtp_new(evbase_t * evbase, evhtp_cfg * cfg, void * arg) {
|
||||
struct sockaddr_in sin = { 0 };
|
||||
evhtp_t * htp = NULL;
|
||||
|
||||
if (evbase == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(htp = calloc(sizeof(evhtp_t), sizeof(char)))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(cfg->bind_port);
|
||||
sin.sin_addr.s_addr = inet_addr(cfg->bind_addr);
|
||||
|
||||
htp->psets.on_message_begin = _htp_start_cb;
|
||||
htp->psets.on_headers_complete = _htp_headers_complete_cb;
|
||||
htp->psets.on_message_complete = _htp_end_cb;
|
||||
htp->psets.on_path = _htp_path_cb;
|
||||
htp->psets.on_query_string = _htp_query_str_cb;
|
||||
htp->psets.on_url = _htp_url_cb;
|
||||
htp->psets.on_fragment = _htp_fragment_cb;
|
||||
htp->psets.on_header_field = _htp_header_key_cb;
|
||||
htp->psets.on_header_value = _htp_header_val_cb;
|
||||
htp->psets.on_body = _htp_body_cb;
|
||||
|
||||
htp->evbase = evbase;
|
||||
htp->config = cfg;
|
||||
htp->pre_accept_cb = NULL;
|
||||
htp->post_accept_cb = NULL;
|
||||
htp->arg = arg;
|
||||
|
||||
htp->serv = evconnlistener_new_bind(evbase,
|
||||
_htp_accept_cb, (void *)htp, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
|
||||
(struct sockaddr *)&sin, sizeof(sin));
|
||||
|
||||
return htp;
|
||||
} /* evhtp_new */
|
||||
|
116
evhtp.h
Normal file
116
evhtp.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
#ifndef __EVHTP_H__
|
||||
#define __EVHTP_H__
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <event.h>
|
||||
#include <event2/listener.h>
|
||||
#include <http_parser.h>
|
||||
|
||||
typedef enum http_method evhtp_method;
|
||||
typedef uint8_t evhtp_ver_major;
|
||||
typedef uint8_t evhtp_ver_minor;
|
||||
|
||||
typedef struct event_base evbase_t;
|
||||
typedef struct bufferevent evbev_t;
|
||||
typedef struct evconnlistener evserv_t;
|
||||
typedef struct evhtp_cfg evhtp_cfg;
|
||||
typedef struct evhtp evhtp_t;
|
||||
typedef struct evhtp_connection evhtp_connection_t;
|
||||
typedef struct evhtp_headers evhtp_headers_t;
|
||||
typedef struct evhtp_header evhtp_header_t;
|
||||
typedef struct evhtp_conn_hooks evhtp_conn_hooks_t;
|
||||
typedef struct evhtp_request evhtp_request_t;
|
||||
|
||||
typedef enum evhtp_hook_type evhtp_hook_type;
|
||||
typedef enum evhtp_res evhtp_res;
|
||||
|
||||
typedef evhtp_res (*evhtp_pre_accept)(int fd, struct sockaddr *, int, void *);
|
||||
typedef evhtp_res (*evhtp_post_accept)(evhtp_connection_t *, void *);
|
||||
|
||||
typedef evhtp_res (*evhtp_hook_post_headers)(evhtp_connection_t *, evhtp_headers_t *, void *);
|
||||
typedef evhtp_res (*evhtp_hook_single_header)(evhtp_connection_t *, evhtp_header_t *, void *);
|
||||
typedef evhtp_res (*evhtp_hook_on_path)(evhtp_connection_t *, const char *, void *);
|
||||
typedef evhtp_res (*evhtp_hook_on_body_read)(evhtp_connection_t *, const char *, size_t, void *);
|
||||
typedef evhtp_res (*evhtp_hook_complete)(evhtp_connection_t *, evhtp_request_t *, void *);
|
||||
|
||||
typedef int (*evhtp_headers_iter_cb)(evhtp_header_t * header, void * arg);
|
||||
|
||||
struct evhtp_request;
|
||||
struct evhtp_headers;
|
||||
struct evhtp_header;
|
||||
|
||||
struct evhtp_cfg {
|
||||
char * base_uri;
|
||||
char * bind_addr;
|
||||
uint16_t bind_port;
|
||||
};
|
||||
|
||||
struct evhtp {
|
||||
evhtp_cfg * config;
|
||||
evbase_t * evbase;
|
||||
evserv_t * serv;
|
||||
void * arg;
|
||||
evhtp_pre_accept pre_accept_cb;
|
||||
evhtp_post_accept post_accept_cb;
|
||||
http_parser_settings psets;
|
||||
};
|
||||
|
||||
struct evhtp_connection {
|
||||
evhtp_conn_hooks_t * hooks;
|
||||
evhtp_request_t * request;
|
||||
http_parser * parser;
|
||||
evbev_t * bev;
|
||||
evhtp_t * evhtp;
|
||||
void * arg;
|
||||
};
|
||||
|
||||
struct evhtp_header {
|
||||
char * key;
|
||||
char * val;
|
||||
|
||||
TAILQ_ENTRY(evhtp_header) next;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(evhtp_headers, evhtp_header);
|
||||
|
||||
struct evhtp_request {
|
||||
evhtp_headers_t headers;
|
||||
evhtp_method method;
|
||||
evhtp_ver_major major;
|
||||
evhtp_ver_minor minor;
|
||||
char * uri;
|
||||
};
|
||||
|
||||
enum evhtp_hook_type {
|
||||
EVHTP_HOOK_POST_HEADERS = 1,
|
||||
EVHTP_HOOK_SINGLE_HEADER,
|
||||
EVHTP_HOOK_ON_PATH,
|
||||
EVHTP_HOOK_ON_BODY_READ,
|
||||
EVHTP_HOOK_COMPLETE
|
||||
};
|
||||
|
||||
enum evhtp_res {
|
||||
EVHTP_RES_OK = 0,
|
||||
EVHTP_RES_DISCONNECT,
|
||||
EVHTP_RES_CORRUPTED,
|
||||
EVHTP_RES_ERROR,
|
||||
EVHTP_RES_CONTINUE
|
||||
};
|
||||
|
||||
struct evhtp_conn_hooks {
|
||||
evhtp_hook_post_headers post_headers_cb;
|
||||
evhtp_hook_single_header single_header_cb;
|
||||
evhtp_hook_on_path path_cb;
|
||||
evhtp_hook_on_body_read body_read_cb;
|
||||
evhtp_hook_complete complete_cb;
|
||||
};
|
||||
|
||||
evhtp_t * evhtp_new(evbase_t *, evhtp_cfg *, void *);
|
||||
evhtp_request_t * evhtp_request_new(void);
|
||||
int evhtp_set_post_accept_cb(evhtp_t *, evhtp_post_accept);
|
||||
int evhtp_set_pre_accept_cb(evhtp_t *, evhtp_pre_accept);
|
||||
int evhtp_conn_hook(evhtp_connection_t *, evhtp_hook_type, void * cb);
|
||||
int evhtp_headers_for_each(evhtp_headers_t *, evhtp_headers_iter_cb, void *);
|
||||
void evhtp_connection_free(evhtp_connection_t *);
|
||||
#endif /* __EVHTP_H__ */
|
||||
|
1
http_parser
Submodule
1
http_parser
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 9639c7c21c868cc743f5cce9ec1cffc1cbcafe01
|
76
test.c
Normal file
76
test.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <evhtp.h>
|
||||
|
||||
static int
|
||||
dump_hdrs_cb(evhtp_header_t * header, void * arg) {
|
||||
printf("key = '%s', val = '%s'\n", header->key, header->val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static evhtp_res
|
||||
test_post_headers_cb(evhtp_connection_t * conn, evhtp_headers_t * hdrs, void * arg) {
|
||||
printf("test_post_headers_cb()\n");
|
||||
|
||||
evhtp_headers_for_each(hdrs, dump_hdrs_cb, NULL);
|
||||
return EVHTP_RES_OK;
|
||||
}
|
||||
|
||||
static evhtp_res
|
||||
test_single_header_cb(evhtp_connection_t * conn, evhtp_header_t * hdr, void * arg) {
|
||||
printf("test_single_header_cb()\n");
|
||||
printf("key = '%s', val='%s'\n", hdr->key, hdr->val);
|
||||
return EVHTP_RES_OK;
|
||||
}
|
||||
|
||||
static evhtp_res
|
||||
test_on_path_cb(evhtp_connection_t * conn, const char * uri) {
|
||||
printf("test_on_path_cb()\n");
|
||||
printf("uri = '%s'\n", uri);
|
||||
return EVHTP_RES_OK;
|
||||
}
|
||||
|
||||
static evhtp_res
|
||||
test_complete_cb(evhtp_connection_t * conn, evhtp_request_t * req, void * arg) {
|
||||
printf("test_complete_cb()\n");
|
||||
printf("method: %d\n", req->method);
|
||||
printf("uri: %s\n", req->uri);
|
||||
printf("vmajor: %d\n", req->major);
|
||||
printf("vminor: %d\n", req->minor);
|
||||
|
||||
return EVHTP_RES_OK;
|
||||
}
|
||||
|
||||
static evhtp_res
|
||||
test_post_accept_cb(evhtp_connection_t * conn, void * arg) {
|
||||
printf("test_post_accept_cb()\n");
|
||||
|
||||
evhtp_conn_hook(conn, EVHTP_HOOK_SINGLE_HEADER, test_single_header_cb);
|
||||
evhtp_conn_hook(conn, EVHTP_HOOK_POST_HEADERS, test_post_headers_cb);
|
||||
evhtp_conn_hook(conn, EVHTP_HOOK_ON_PATH, test_on_path_cb);
|
||||
evhtp_conn_hook(conn, EVHTP_HOOK_COMPLETE, test_complete_cb);
|
||||
return EVHTP_RES_OK;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char ** argv) {
|
||||
int res = 0;
|
||||
evbase_t * evbase = NULL;
|
||||
evhtp_t * htp = NULL;
|
||||
evhtp_cfg cfg = {
|
||||
.base_uri = "/",
|
||||
.bind_addr = "0.0.0.0",
|
||||
.bind_port = 8080
|
||||
};
|
||||
|
||||
evbase = event_base_new();
|
||||
htp = evhtp_new(evbase, &cfg, NULL);
|
||||
res = evhtp_set_post_accept_cb(htp, test_post_accept_cb);
|
||||
|
||||
event_base_loop(evbase, 0);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue