mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-19 01:22:34 -05:00
[httpd] Start adding libevhtp backend
This commit is contained in:
parent
96ce7c52c8
commit
8bdf4c778a
@ -258,6 +258,11 @@ OWNTONE_ARG_WITH_CHECK([OWNTONE_OPTS], [libevent_pthreads support],
|
|||||||
[libevent_pthreads], [LIBEVENT_PTHREADS], [libevent_pthreads],
|
[libevent_pthreads], [LIBEVENT_PTHREADS], [libevent_pthreads],
|
||||||
[evthread_use_pthreads], [event2/thread.h])
|
[evthread_use_pthreads], [event2/thread.h])
|
||||||
|
|
||||||
|
dnl Build with libevhtp
|
||||||
|
OWNTONE_ARG_WITH_CHECK([OWNTONE_OPTS], [libevhtp support], [libevhtp], [LIBEVHTP],
|
||||||
|
[evhtp])
|
||||||
|
AM_CONDITIONAL([COND_LIBEVHTP], [[test "x$with_libevhtp" = "xyes"]])
|
||||||
|
|
||||||
dnl Build with Avahi (or Bonjour if not)
|
dnl Build with Avahi (or Bonjour if not)
|
||||||
OWNTONE_ARG_WITH_CHECK([OWNTONE_OPTS], [Avahi mDNS], [avahi], [AVAHI],
|
OWNTONE_ARG_WITH_CHECK([OWNTONE_OPTS], [Avahi mDNS], [avahi], [AVAHI],
|
||||||
[avahi-client >= 0.6.24], [avahi_client_new], [avahi-client/client.h])
|
[avahi-client >= 0.6.24], [avahi_client_new], [avahi-client/client.h])
|
||||||
|
@ -46,6 +46,12 @@ if COND_LIBWEBSOCKETS
|
|||||||
LIBWEBSOCKETS_SRC=websocket.c websocket.h
|
LIBWEBSOCKETS_SRC=websocket.c websocket.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if COND_LIBEVHTP
|
||||||
|
HTTPDBACKEND_SRC=httpd_libevhtp.c
|
||||||
|
else
|
||||||
|
HTTPDBACKEND_SRC=httpd_libevhttp.c
|
||||||
|
endif
|
||||||
|
|
||||||
GPERF_FILES = \
|
GPERF_FILES = \
|
||||||
daap_query.gperf \
|
daap_query.gperf \
|
||||||
dacp_prop.gperf \
|
dacp_prop.gperf \
|
||||||
@ -92,8 +98,8 @@ owntone_SOURCES = main.c \
|
|||||||
library.c library.h \
|
library.c library.h \
|
||||||
$(MDNS_SRC) mdns.h \
|
$(MDNS_SRC) mdns.h \
|
||||||
remote_pairing.c remote_pairing.h \
|
remote_pairing.c remote_pairing.h \
|
||||||
|
$(HTTPDBACKEND_SRC) \
|
||||||
httpd.c httpd.h httpd_internal.h \
|
httpd.c httpd.h httpd_internal.h \
|
||||||
httpd_libevhttp.c \
|
|
||||||
httpd_rsp.c \
|
httpd_rsp.c \
|
||||||
httpd_daap.c httpd_daap.h \
|
httpd_daap.c httpd_daap.h \
|
||||||
httpd_dacp.c \
|
httpd_dacp.c \
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <event2/event.h>
|
#include <event2/event.h>
|
||||||
|
|
||||||
|
#include <regex.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
@ -295,11 +296,13 @@ request_unset(struct httpd_request *hreq)
|
|||||||
evbuffer_free(hreq->out_body);
|
evbuffer_free(hreq->out_body);
|
||||||
|
|
||||||
httpd_uri_parsed_free(hreq->uri_parsed);
|
httpd_uri_parsed_free(hreq->uri_parsed);
|
||||||
|
httpd_backend_data_free(hreq->backend_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
request_set(struct httpd_request *hreq, httpd_backend *backend, const char *uri, const char *user_agent)
|
request_set(struct httpd_request *hreq, httpd_backend *backend, const char *uri, const char *user_agent)
|
||||||
{
|
{
|
||||||
|
httpd_backend_data *backend_data;
|
||||||
struct httpd_uri_map *map;
|
struct httpd_uri_map *map;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -309,12 +312,14 @@ request_set(struct httpd_request *hreq, httpd_backend *backend, const char *uri,
|
|||||||
hreq->backend = backend;
|
hreq->backend = backend;
|
||||||
if (backend)
|
if (backend)
|
||||||
{
|
{
|
||||||
hreq->uri = httpd_backend_uri_get(backend);
|
backend_data = httpd_backend_data_create(backend);
|
||||||
|
hreq->backend_data = backend_data;
|
||||||
|
hreq->uri = httpd_backend_uri_get(backend, backend_data);
|
||||||
hreq->in_headers = httpd_backend_input_headers_get(backend);
|
hreq->in_headers = httpd_backend_input_headers_get(backend);
|
||||||
hreq->out_headers = httpd_backend_output_headers_get(backend);
|
hreq->out_headers = httpd_backend_output_headers_get(backend);
|
||||||
hreq->in_body = httpd_backend_input_buffer_get(backend);
|
hreq->in_body = httpd_backend_input_buffer_get(backend);
|
||||||
httpd_backend_method_get(&hreq->method, backend);
|
httpd_backend_method_get(&hreq->method, backend);
|
||||||
httpd_backend_peer_get(&hreq->peer_address, &hreq->peer_port, backend);
|
httpd_backend_peer_get(&hreq->peer_address, &hreq->peer_port, backend, backend_data);
|
||||||
|
|
||||||
hreq->user_agent = httpd_header_find(hreq->in_headers, "User-Agent");
|
hreq->user_agent = httpd_header_find(hreq->in_headers, "User-Agent");
|
||||||
}
|
}
|
||||||
|
@ -2372,12 +2372,9 @@ daap_deinit(void)
|
|||||||
{
|
{
|
||||||
update_requests = ur->next;
|
update_requests = ur->next;
|
||||||
|
|
||||||
|
httpd_request_closecb_set(ur->hreq, NULL, NULL);
|
||||||
conn = httpd_request_connection_get(ur->hreq);
|
conn = httpd_request_connection_get(ur->hreq);
|
||||||
if (conn)
|
httpd_connection_free(conn); // TODO necessary?
|
||||||
{
|
|
||||||
httpd_connection_closecb_set(conn, NULL, NULL);
|
|
||||||
httpd_connection_free(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_free(ur);
|
update_free(ur);
|
||||||
}
|
}
|
||||||
|
@ -2938,12 +2938,9 @@ dacp_deinit(void)
|
|||||||
{
|
{
|
||||||
update_requests = ur->next;
|
update_requests = ur->next;
|
||||||
|
|
||||||
|
httpd_request_closecb_set(ur->hreq, NULL, NULL);
|
||||||
conn = httpd_request_connection_get(ur->hreq);
|
conn = httpd_request_connection_get(ur->hreq);
|
||||||
if (conn)
|
httpd_connection_free(conn); // TODO necessary?
|
||||||
{
|
|
||||||
httpd_connection_closecb_set(conn, NULL, NULL);
|
|
||||||
httpd_connection_free(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ur);
|
free(ur);
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,27 @@
|
|||||||
|
|
||||||
struct httpd_request;
|
struct httpd_request;
|
||||||
|
|
||||||
#include <event2/http.h>
|
#ifdef HAVE_LIBEVHTP
|
||||||
#include <event2/keyvalq_struct.h>
|
struct evhtp_s;
|
||||||
#include <regex.h> // evhtp conflicts with regex since it brings it own
|
struct evhtp_connection_s;
|
||||||
|
struct evhtp_request_s;
|
||||||
|
struct evhtp_kvs_s;
|
||||||
|
struct httpd_uri_parsed;
|
||||||
|
struct httpd_backend_data;
|
||||||
|
|
||||||
|
typedef struct evhtp_s httpd_server;
|
||||||
|
typedef struct evhtp_connection_s httpd_connection;
|
||||||
|
typedef struct evhtp_request_s httpd_backend;
|
||||||
|
typedef struct evhtp_kvs_s httpd_headers;
|
||||||
|
typedef struct evhtp_kvs_s httpd_query;
|
||||||
|
typedef struct httpd_uri_parsed httpd_uri_parsed;
|
||||||
|
typedef struct httpd_backend_data httpd_backend_data;
|
||||||
|
#else
|
||||||
|
struct evhttp;
|
||||||
|
struct evhttp_connection;
|
||||||
|
struct evhttp_request;
|
||||||
|
struct evkeyvalq;
|
||||||
|
struct httpd_uri_parsed;
|
||||||
|
|
||||||
typedef struct evhttp httpd_server;
|
typedef struct evhttp httpd_server;
|
||||||
typedef struct evhttp_connection httpd_connection;
|
typedef struct evhttp_connection httpd_connection;
|
||||||
@ -22,6 +40,8 @@ typedef struct evhttp_request httpd_backend;
|
|||||||
typedef struct evkeyvalq httpd_headers;
|
typedef struct evkeyvalq httpd_headers;
|
||||||
typedef struct evkeyvalq httpd_query;
|
typedef struct evkeyvalq httpd_query;
|
||||||
typedef struct httpd_uri_parsed httpd_uri_parsed;
|
typedef struct httpd_uri_parsed httpd_uri_parsed;
|
||||||
|
typedef void httpd_backend_data; // Not used for evhttp
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef char *httpd_uri_path_parts[31];
|
typedef char *httpd_uri_path_parts[31];
|
||||||
typedef void (*httpd_general_cb)(httpd_backend *backend, void *arg);
|
typedef void (*httpd_general_cb)(httpd_backend *backend, void *arg);
|
||||||
@ -104,13 +124,14 @@ struct httpd_request {
|
|||||||
enum httpd_methods method;
|
enum httpd_methods method;
|
||||||
// Backend private request object
|
// Backend private request object
|
||||||
httpd_backend *backend;
|
httpd_backend *backend;
|
||||||
|
// For storing data that the actual backend doesn't have readily available
|
||||||
|
// e.g. peer address string for libevhtp
|
||||||
|
httpd_backend_data *backend_data;
|
||||||
// User-agent (if available)
|
// User-agent (if available)
|
||||||
const char *user_agent;
|
const char *user_agent;
|
||||||
// Source IP address (ipv4 or ipv6) and port of the request (if available)
|
// Source IP address (ipv4 or ipv6) and port of the request (if available)
|
||||||
const char *peer_address;
|
const char *peer_address;
|
||||||
unsigned short peer_port;
|
unsigned short peer_port;
|
||||||
// A pointer to extra data that the module handling the request might need
|
|
||||||
void *extra_data;
|
|
||||||
|
|
||||||
// The original, request URI. The URI may have been complete:
|
// The original, request URI. The URI may have been complete:
|
||||||
// scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
|
// scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
|
||||||
@ -141,6 +162,8 @@ struct httpd_request {
|
|||||||
struct httpd_module *module;
|
struct httpd_module *module;
|
||||||
// A pointer to the handler that will process the request
|
// A pointer to the handler that will process the request
|
||||||
int (*handler)(struct httpd_request *hreq);
|
int (*handler)(struct httpd_request *hreq);
|
||||||
|
// A pointer to extra data that the module handling the request might need
|
||||||
|
void *extra_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -239,12 +262,6 @@ httpd_header_add(httpd_headers *headers, const char *key, const char *val);
|
|||||||
void
|
void
|
||||||
httpd_headers_clear(httpd_headers *headers);
|
httpd_headers_clear(httpd_headers *headers);
|
||||||
|
|
||||||
int
|
|
||||||
httpd_connection_closecb_set(httpd_connection *conn, httpd_connection_closecb cb, void *arg);
|
|
||||||
|
|
||||||
int
|
|
||||||
httpd_connection_peer_get(const char **addr, uint16_t *port, httpd_connection *conn);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
httpd_connection_free(httpd_connection *conn);
|
httpd_connection_free(httpd_connection *conn);
|
||||||
|
|
||||||
@ -284,11 +301,17 @@ httpd_backend_reply_end_send(httpd_backend *backend);
|
|||||||
|
|
||||||
/*---------- Only called by httpd.c to populate struct httpd_request ---------*/
|
/*---------- Only called by httpd.c to populate struct httpd_request ---------*/
|
||||||
|
|
||||||
|
httpd_backend_data *
|
||||||
|
httpd_backend_data_create(httpd_backend *backend);
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_backend_data_free(httpd_backend_data *backend_data);
|
||||||
|
|
||||||
httpd_connection *
|
httpd_connection *
|
||||||
httpd_backend_connection_get(httpd_backend *backend);
|
httpd_backend_connection_get(httpd_backend *backend);
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
httpd_backend_uri_get(httpd_backend *backend);
|
httpd_backend_uri_get(httpd_backend *backend, httpd_backend_data *backend_data);
|
||||||
|
|
||||||
httpd_headers *
|
httpd_headers *
|
||||||
httpd_backend_input_headers_get(httpd_backend *backend);
|
httpd_backend_input_headers_get(httpd_backend *backend);
|
||||||
@ -300,7 +323,7 @@ struct evbuffer *
|
|||||||
httpd_backend_input_buffer_get(httpd_backend *backend);
|
httpd_backend_input_buffer_get(httpd_backend *backend);
|
||||||
|
|
||||||
int
|
int
|
||||||
httpd_backend_peer_get(const char **addr, uint16_t *port, httpd_backend *backend);
|
httpd_backend_peer_get(const char **addr, uint16_t *port, httpd_backend *backend, httpd_backend_data *backend_data);
|
||||||
|
|
||||||
int
|
int
|
||||||
httpd_backend_method_get(enum httpd_methods *method, httpd_backend *backend);
|
httpd_backend_method_get(enum httpd_methods *method, httpd_backend *backend);
|
||||||
|
372
src/httpd_libevhtp.c
Normal file
372
src/httpd_libevhtp.c
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <evhtp.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "httpd_internal.h"
|
||||||
|
|
||||||
|
struct httpd_backend_data
|
||||||
|
{
|
||||||
|
char peer_address[32];
|
||||||
|
uint16_t peer_port;
|
||||||
|
httpd_connection_closecb closecb;
|
||||||
|
void *closecb_arg;
|
||||||
|
char *uri;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct httpd_uri_parsed
|
||||||
|
{
|
||||||
|
evhtp_uri_t *ev_uri;
|
||||||
|
httpd_uri_path_parts path_parts;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
httpd_query_value_find(httpd_query *query, const char *key)
|
||||||
|
{
|
||||||
|
return evhtp_kv_find(query, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_query_iterate(httpd_query *query, httpd_query_iteratecb cb, void *arg)
|
||||||
|
{
|
||||||
|
evhtp_kv_t *param;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(param, query, next)
|
||||||
|
{
|
||||||
|
cb(param->key, param->val, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_query_clear(httpd_query *query)
|
||||||
|
{
|
||||||
|
evhtp_kvs_free(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
httpd_header_find(httpd_headers *headers, const char *key)
|
||||||
|
{
|
||||||
|
return evhtp_header_find(headers, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_header_remove(httpd_headers *headers, const char *key)
|
||||||
|
{
|
||||||
|
evhtp_header_rm_and_free(headers, evhtp_headers_find_header(headers, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_header_add(httpd_headers *headers, const char *key, const char *val)
|
||||||
|
{
|
||||||
|
evhtp_headers_add_header(headers, evhtp_header_new(key, val, 1, 1)); // Copy key/val
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_headers_clear(httpd_headers *headers)
|
||||||
|
{
|
||||||
|
evhtp_headers_free(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_connection_free(httpd_connection *conn)
|
||||||
|
{
|
||||||
|
if (!conn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
evhtp_connection_free(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_connection *
|
||||||
|
httpd_request_connection_get(struct httpd_request *hreq)
|
||||||
|
{
|
||||||
|
return evhtp_request_get_connection(hreq->backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_request_backend_free(struct httpd_request *hreq)
|
||||||
|
{
|
||||||
|
evhtp_request_free(hreq->backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
static short unsigned
|
||||||
|
closecb_wrapper(httpd_connection *conn, void *arg)
|
||||||
|
{
|
||||||
|
httpd_backend_data *backend_data = arg;
|
||||||
|
backend_data->closecb(conn, backend_data->closecb_arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
httpd_request_closecb_set(struct httpd_request *hreq, httpd_connection_closecb cb, void *arg)
|
||||||
|
{
|
||||||
|
httpd_connection *conn;
|
||||||
|
|
||||||
|
hreq->backend_data->closecb = cb;
|
||||||
|
hreq->backend_data->closecb_arg = arg;
|
||||||
|
|
||||||
|
conn = httpd_request_connection_get(hreq);
|
||||||
|
if (conn)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!cb)
|
||||||
|
return evhtp_connection_unset_hook(conn, evhtp_hook_on_connection_fini);
|
||||||
|
|
||||||
|
return evhtp_connection_set_hook(conn, evhtp_hook_on_connection_fini, closecb_wrapper, hreq->backend_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_server_free(httpd_server *server)
|
||||||
|
{
|
||||||
|
if (!server)
|
||||||
|
return;
|
||||||
|
|
||||||
|
evhtp_free(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_server *
|
||||||
|
httpd_server_new(struct event_base *evbase, unsigned short port, httpd_general_cb cb, void *arg)
|
||||||
|
{
|
||||||
|
evhtp_t *server;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
server = evhtp_new(evbase, NULL);
|
||||||
|
if (!server)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
fd = net_bind(&port, SOCK_STREAM, "httpd");
|
||||||
|
if (fd < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (evhtp_accept_socket(server, fd, 0) != 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
evhtp_set_gencb(server, cb, arg);
|
||||||
|
|
||||||
|
return server;
|
||||||
|
|
||||||
|
error:
|
||||||
|
httpd_server_free(server);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_server_allow_origin_set(httpd_server *server, bool allow)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_backend_data *
|
||||||
|
httpd_backend_data_create(httpd_backend *backend)
|
||||||
|
{
|
||||||
|
httpd_backend_data *backend_data;
|
||||||
|
|
||||||
|
backend_data = calloc(1, sizeof(httpd_backend_data));
|
||||||
|
if (!backend_data)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return backend_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_backend_data_free(httpd_backend_data *backend_data)
|
||||||
|
{
|
||||||
|
free(backend_data->uri);
|
||||||
|
free(backend_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_backend_reply_send(httpd_backend *backend, int code, const char *reason, struct evbuffer *evbuf)
|
||||||
|
{
|
||||||
|
evhtp_send_reply_start(backend, code);
|
||||||
|
evhtp_send_reply_body(backend, evbuf);
|
||||||
|
evhtp_send_reply_end(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_backend_reply_start_send(httpd_backend *backend, int code, const char *reason)
|
||||||
|
{
|
||||||
|
evhtp_send_reply_chunk_start(backend, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_backend_reply_chunk_send(httpd_backend *backend, struct evbuffer *evbuf, httpd_connection_chunkcb cb, void *arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_backend_reply_end_send(httpd_backend *backend)
|
||||||
|
{
|
||||||
|
evhtp_send_reply_chunk_end(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_connection *
|
||||||
|
httpd_backend_connection_get(httpd_backend *backend)
|
||||||
|
{
|
||||||
|
return evhtp_request_get_connection(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
httpd_backend_uri_get(httpd_backend *backend, httpd_backend_data *backend_data)
|
||||||
|
{
|
||||||
|
evhtp_uri_t *uri = backend->uri;
|
||||||
|
if (!uri || !uri->path)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
free(backend_data->uri);
|
||||||
|
backend_data->uri = safe_asprintf("%s?%s", uri->path->full, (char *)uri->query_raw);
|
||||||
|
|
||||||
|
return (const char *)backend_data->uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_headers *
|
||||||
|
httpd_backend_input_headers_get(httpd_backend *backend)
|
||||||
|
{
|
||||||
|
return backend->headers_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_headers *
|
||||||
|
httpd_backend_output_headers_get(httpd_backend *backend)
|
||||||
|
{
|
||||||
|
return backend->headers_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct evbuffer *
|
||||||
|
httpd_backend_input_buffer_get(httpd_backend *backend)
|
||||||
|
{
|
||||||
|
return backend->buffer_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
httpd_backend_peer_get(const char **addr, uint16_t *port, httpd_backend *backend, httpd_backend_data *backend_data)
|
||||||
|
{
|
||||||
|
httpd_connection *conn;
|
||||||
|
union net_sockaddr naddr;
|
||||||
|
|
||||||
|
*addr = NULL;
|
||||||
|
*port = 0;
|
||||||
|
|
||||||
|
conn = evhtp_request_get_connection(backend);
|
||||||
|
if (!conn)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
naddr.sa = *conn->saddr;
|
||||||
|
net_address_get(backend_data->peer_address, sizeof(backend_data->peer_address), &naddr);
|
||||||
|
net_port_get(&backend_data->peer_port, &naddr);
|
||||||
|
|
||||||
|
*addr = backend_data->peer_address;
|
||||||
|
*port = backend_data->peer_port;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
httpd_backend_method_get(enum httpd_methods *method, httpd_backend *backend)
|
||||||
|
{
|
||||||
|
htp_method cmd = evhtp_request_get_method(backend);
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case htp_method_GET: *method = HTTPD_METHOD_GET; break;
|
||||||
|
case htp_method_POST: *method = HTTPD_METHOD_POST; break;
|
||||||
|
case htp_method_HEAD: *method = HTTPD_METHOD_HEAD; break;
|
||||||
|
case htp_method_PUT: *method = HTTPD_METHOD_PUT; break;
|
||||||
|
case htp_method_DELETE: *method = HTTPD_METHOD_DELETE; break;
|
||||||
|
case htp_method_OPTIONS: *method = HTTPD_METHOD_OPTIONS; break;
|
||||||
|
case htp_method_TRACE: *method = HTTPD_METHOD_TRACE; break;
|
||||||
|
case htp_method_CONNECT: *method = HTTPD_METHOD_CONNECT; break;
|
||||||
|
case htp_method_PATCH: *method = HTTPD_METHOD_PATCH; break;
|
||||||
|
default: *method = HTTPD_METHOD_GET; return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_backend_preprocess(httpd_backend *backend)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_uri_parsed *
|
||||||
|
httpd_uri_parsed_create(const char *uri)
|
||||||
|
{
|
||||||
|
struct httpd_uri_parsed *parsed;
|
||||||
|
const char *query;
|
||||||
|
char *path = NULL;
|
||||||
|
char *path_part;
|
||||||
|
char *ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
parsed = calloc(1, sizeof(struct httpd_uri_parsed));
|
||||||
|
if (!parsed)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
parsed->ev_uri = evhttp_uri_parse_with_flags(uri, EVHTTP_URI_NONCONFORMANT);
|
||||||
|
if (!parsed->ev_uri)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
query = evhttp_uri_get_query(parsed->ev_uri);
|
||||||
|
if (query && strchr(query, '=') && evhttp_parse_query_str(query, &(parsed->query)) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
path = strdup(evhttp_uri_get_path(parsed->ev_uri));
|
||||||
|
if (!path || !(parsed->path = evhttp_uridecode(path, 0, NULL)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
path_part = strtok_r(path, "/", &ptr);
|
||||||
|
for (i = 0; (i < ARRAY_SIZE(parsed->path_parts) && path_part); i++)
|
||||||
|
{
|
||||||
|
parsed->path_parts[i] = evhttp_uridecode(path_part, 0, NULL);
|
||||||
|
path_part = strtok_r(NULL, "/", &ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If "path_part" is not NULL, we have path tokens that could not be parsed into the "parsed->path_parts" array
|
||||||
|
if (path_part)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
return parsed;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(path);
|
||||||
|
httpd_uri_parsed_free(parsed);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_uri_parsed_free(httpd_uri_parsed *parsed)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!parsed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
free(parsed->path);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(parsed->path_parts); i++)
|
||||||
|
free(parsed->path_parts[i]);
|
||||||
|
|
||||||
|
httpd_query_clear(&(parsed->query));
|
||||||
|
|
||||||
|
if (parsed->ev_uri)
|
||||||
|
evhttp_uri_free(parsed->ev_uri);
|
||||||
|
|
||||||
|
free(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_query *
|
||||||
|
httpd_uri_query_get(httpd_uri_parsed *parsed)
|
||||||
|
{
|
||||||
|
return parsed->ev_uri->query;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
httpd_uri_path_get(httpd_uri_parsed *parsed)
|
||||||
|
{
|
||||||
|
if (!parsed->ev_uri->path)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return parsed->ev_uri->path->full;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
httpd_uri_path_parts_get(httpd_uri_path_parts *path_parts, httpd_uri_parsed *parsed)
|
||||||
|
{
|
||||||
|
memcpy(path_parts, parsed->path_parts, sizeof(httpd_uri_path_parts));
|
||||||
|
}
|
@ -65,23 +65,12 @@ httpd_headers_clear(httpd_headers *headers)
|
|||||||
evhttp_clear_headers(headers);
|
evhttp_clear_headers(headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
httpd_connection_closecb_set(httpd_connection *conn, httpd_connection_closecb cb, void *arg)
|
|
||||||
{
|
|
||||||
evhttp_connection_set_closecb(conn, cb, arg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
httpd_connection_peer_get(const char **addr, uint16_t *port, httpd_connection *conn)
|
|
||||||
{
|
|
||||||
evhttp_connection_get_peer(conn, (char **)addr, port);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
httpd_connection_free(httpd_connection *conn)
|
httpd_connection_free(httpd_connection *conn)
|
||||||
{
|
{
|
||||||
|
if (!conn)
|
||||||
|
return;
|
||||||
|
|
||||||
evhttp_connection_free(conn);
|
evhttp_connection_free(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user