[httpd] Start making http modules agnostic to evhttp

This commit is contained in:
ejurgensen 2022-12-21 19:11:03 +01:00
parent 3e9482e9a5
commit 2b4ff98652
8 changed files with 315 additions and 326 deletions

View File

@ -291,15 +291,70 @@ modules_search(const char *path)
/* --------------------------- REQUEST HELPERS ------------------------------ */ /* --------------------------- REQUEST HELPERS ------------------------------ */
static int
request_set(struct httpd_request *hreq, struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed, const char *user_agent, struct httpd_uri_map *uri_map)
{
;
struct evhttp_connection *evcon;
struct evkeyvalq *headers;
struct httpd_uri_map *uri;
int req_method;
int ret;
memset(hreq, 0, sizeof(struct httpd_request));
// Note req is allowed to be NULL
hreq->req = req;
hreq->uri = uri_parsed->uri;
hreq->uri_parsed = uri_parsed;
hreq->query = &(uri_parsed->ev_query);
req_method = 0;
if (req)
{
headers = evhttp_request_get_input_headers(req);
hreq->user_agent = evhttp_find_header(headers, "User-Agent");
evcon = evhttp_request_get_connection(req);
if (evcon)
evhttp_connection_get_peer(evcon, &hreq->peer_address, &hreq->peer_port);
else
DPRINTF(E_LOG, L_HTTPD, "Connection to client lost or missing\n");
req_method = evhttp_request_get_command(req);
}
if (user_agent)
hreq->user_agent = user_agent;
// Find a handler for the path
for (uri = uri_map; uri->handler; uri++)
{
// Check if handler supports the current http request method
if (uri->method && req_method && !(req_method & uri->method))
continue;
ret = regexec(uri->preg, uri_parsed->path, 0, NULL, 0);
if (ret != 0)
continue;
hreq->handler = uri->handler;
return 0; // Success
}
// Handler not found, that's an error
return -1;
}
void void
httpd_redirect_to(struct evhttp_request *req, const char *path) httpd_redirect_to(struct httpd_request *hreq, const char *path)
{ {
struct evkeyvalq *headers; struct evkeyvalq *headers;
headers = evhttp_request_get_output_headers(req); headers = evhttp_request_get_output_headers(hreq->req);
evhttp_add_header(headers, "Location", path); evhttp_add_header(headers, "Location", path);
httpd_send_reply(req, HTTP_MOVETEMP, "Moved", NULL, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_MOVETEMP, "Moved", NULL, HTTPD_SEND_NO_GZIP);
} }
/* /*
@ -314,13 +369,13 @@ httpd_redirect_to(struct evhttp_request *req, const char *path)
* @return True if the given ETag matches the request-header-value "If-None-Match", otherwise false * @return True if the given ETag matches the request-header-value "If-None-Match", otherwise false
*/ */
bool bool
httpd_request_etag_matches(struct evhttp_request *req, const char *etag) httpd_request_etag_matches(struct httpd_request *hreq, const char *etag)
{ {
struct evkeyvalq *input_headers; struct evkeyvalq *input_headers;
struct evkeyvalq *output_headers; struct evkeyvalq *output_headers;
const char *none_match; const char *none_match;
input_headers = evhttp_request_get_input_headers(req); input_headers = evhttp_request_get_input_headers(hreq->req);
none_match = evhttp_find_header(input_headers, "If-None-Match"); none_match = evhttp_find_header(input_headers, "If-None-Match");
// Return not modified, if given timestamp matches "If-Modified-Since" request header // Return not modified, if given timestamp matches "If-Modified-Since" request header
@ -328,7 +383,7 @@ httpd_request_etag_matches(struct evhttp_request *req, const char *etag)
return true; return true;
// Add cache headers to allow client side caching // Add cache headers to allow client side caching
output_headers = evhttp_request_get_output_headers(req); output_headers = evhttp_request_get_output_headers(hreq->req);
evhttp_add_header(output_headers, "Cache-Control", "private,no-cache,max-age=0"); evhttp_add_header(output_headers, "Cache-Control", "private,no-cache,max-age=0");
evhttp_add_header(output_headers, "ETag", etag); evhttp_add_header(output_headers, "ETag", etag);
@ -347,7 +402,7 @@ httpd_request_etag_matches(struct evhttp_request *req, const char *etag)
* @return True if the given timestamp matches the request-header-value "If-Modified-Since", otherwise false * @return True if the given timestamp matches the request-header-value "If-Modified-Since", otherwise false
*/ */
bool bool
httpd_request_not_modified_since(struct evhttp_request *req, time_t mtime) httpd_request_not_modified_since(struct httpd_request *hreq, time_t mtime)
{ {
struct evkeyvalq *input_headers; struct evkeyvalq *input_headers;
struct evkeyvalq *output_headers; struct evkeyvalq *output_headers;
@ -355,7 +410,7 @@ httpd_request_not_modified_since(struct evhttp_request *req, time_t mtime)
const char *modified_since; const char *modified_since;
struct tm timebuf; struct tm timebuf;
input_headers = evhttp_request_get_input_headers(req); input_headers = evhttp_request_get_input_headers(hreq->req);
modified_since = evhttp_find_header(input_headers, "If-Modified-Since"); modified_since = evhttp_find_header(input_headers, "If-Modified-Since");
strftime(last_modified, sizeof(last_modified), "%a, %d %b %Y %H:%M:%S %Z", gmtime_r(&mtime, &timebuf)); strftime(last_modified, sizeof(last_modified), "%a, %d %b %Y %H:%M:%S %Z", gmtime_r(&mtime, &timebuf));
@ -365,7 +420,7 @@ httpd_request_not_modified_since(struct evhttp_request *req, time_t mtime)
return true; return true;
// Add cache headers to allow client side caching // Add cache headers to allow client side caching
output_headers = evhttp_request_get_output_headers(req); output_headers = evhttp_request_get_output_headers(hreq->req);
evhttp_add_header(output_headers, "Cache-Control", "private,no-cache,max-age=0"); evhttp_add_header(output_headers, "Cache-Control", "private,no-cache,max-age=0");
evhttp_add_header(output_headers, "Last-Modified", last_modified); evhttp_add_header(output_headers, "Last-Modified", last_modified);
@ -373,11 +428,11 @@ httpd_request_not_modified_since(struct evhttp_request *req, time_t mtime)
} }
void void
httpd_response_not_cachable(struct evhttp_request *req) httpd_response_not_cachable(struct httpd_request *hreq)
{ {
struct evkeyvalq *output_headers; struct evkeyvalq *output_headers;
output_headers = evhttp_request_get_output_headers(req); output_headers = evhttp_request_get_output_headers(hreq->req);
// Remove potentially set cache control headers // Remove potentially set cache control headers
evhttp_remove_header(output_headers, "Cache-Control"); evhttp_remove_header(output_headers, "Cache-Control");
@ -389,7 +444,7 @@ httpd_response_not_cachable(struct evhttp_request *req)
} }
static void static void
serve_file(struct evhttp_request *req, const char *uri) serve_file(struct httpd_request *hreq, const char *uri)
{ {
char *ext; char *ext;
char path[PATH_MAX]; char path[PATH_MAX];
@ -405,7 +460,7 @@ serve_file(struct evhttp_request *req, const char *uri)
int ret; int ret;
/* Check authentication */ /* Check authentication */
if (!httpd_admin_check_auth(req)) if (!httpd_admin_check_auth(hreq))
return; return;
ret = snprintf(path, sizeof(path), "%s%s", webroot_directory, uri); ret = snprintf(path, sizeof(path), "%s%s", webroot_directory, uri);
@ -413,7 +468,7 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_LOG, L_HTTPD, "Request exceeds PATH_MAX: %s\n", uri); DPRINTF(E_LOG, L_HTTPD, "Request exceeds PATH_MAX: %s\n", uri);
httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return; return;
} }
@ -422,7 +477,7 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not dereference %s: %s\n", path, strerror(errno)); DPRINTF(E_LOG, L_HTTPD, "Could not dereference %s: %s\n", path, strerror(errno));
httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return; return;
} }
@ -430,7 +485,7 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_LOG, L_HTTPD, "Dereferenced path exceeds PATH_MAX: %s\n", path); DPRINTF(E_LOG, L_HTTPD, "Dereferenced path exceeds PATH_MAX: %s\n", path);
httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return; return;
} }
@ -440,7 +495,7 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_WARN, L_HTTPD, "Could not lstat() %s: %s\n", deref, strerror(errno)); DPRINTF(E_WARN, L_HTTPD, "Could not lstat() %s: %s\n", deref, strerror(errno));
httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return; return;
} }
@ -454,7 +509,7 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not dereference %s: %s\n", path, strerror(errno)); DPRINTF(E_LOG, L_HTTPD, "Could not dereference %s: %s\n", path, strerror(errno));
httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return; return;
} }
@ -462,7 +517,7 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_LOG, L_HTTPD, "Dereferenced path exceeds PATH_MAX: %s\n", path); DPRINTF(E_LOG, L_HTTPD, "Dereferenced path exceeds PATH_MAX: %s\n", path);
httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return; return;
} }
@ -471,7 +526,7 @@ serve_file(struct evhttp_request *req, const char *uri)
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", path, strerror(errno)); DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", path, strerror(errno));
httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return; return;
} }
} }
@ -480,14 +535,14 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_WARN, L_HTTPD, "Access to file outside the web root dir forbidden: %s\n", deref); DPRINTF(E_WARN, L_HTTPD, "Access to file outside the web root dir forbidden: %s\n", deref);
httpd_send_error(req, 403, "Forbidden"); httpd_send_error(hreq, 403, "Forbidden");
return; return;
} }
if (httpd_request_not_modified_since(req, sb.st_mtime)) if (httpd_request_not_modified_since(hreq, sb.st_mtime))
{ {
httpd_send_reply(req, HTTP_NOTMODIFIED, NULL, NULL, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOTMODIFIED, NULL, NULL, HTTPD_SEND_NO_GZIP);
return; return;
} }
@ -496,7 +551,7 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not create evbuffer\n"); DPRINTF(E_LOG, L_HTTPD, "Could not create evbuffer\n");
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal error");
return; return;
} }
@ -505,7 +560,7 @@ serve_file(struct evhttp_request *req, const char *uri)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", deref, strerror(errno)); DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", deref, strerror(errno));
httpd_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
evbuffer_free(evbuf); evbuffer_free(evbuf);
return; return;
} }
@ -540,17 +595,17 @@ serve_file(struct evhttp_request *req, const char *uri)
} }
} }
output_headers = evhttp_request_get_output_headers(req); output_headers = evhttp_request_get_output_headers(hreq->req);
evhttp_add_header(output_headers, "Content-Type", ctype); evhttp_add_header(output_headers, "Content-Type", ctype);
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
evbuffer_free(evbuf); evbuffer_free(evbuf);
close(fd); close(fd);
return; return;
out_fail: out_fail:
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal error");
evbuffer_free(evbuf); evbuffer_free(evbuf);
close(fd); close(fd);
} }
@ -783,7 +838,7 @@ httpd_gen_cb(struct evhttp_request *req, void *arg)
{ {
struct evkeyvalq *input_headers; struct evkeyvalq *input_headers;
struct evkeyvalq *output_headers; struct evkeyvalq *output_headers;
struct httpd_request hreq; struct httpd_request hreq = { .req = req }; // TODO clean this up
struct httpd_uri_parsed *parsed; struct httpd_uri_parsed *parsed;
struct httpd_module *m; struct httpd_module *m;
const char *uri; const char *uri;
@ -814,14 +869,14 @@ httpd_gen_cb(struct evhttp_request *req, void *arg)
if (!uri) if (!uri)
{ {
DPRINTF(E_WARN, L_HTTPD, "No URI in request\n"); DPRINTF(E_WARN, L_HTTPD, "No URI in request\n");
httpd_redirect_to(req, "/"); httpd_redirect_to(&hreq, "/");
return; return;
} }
parsed = httpd_uri_parse(uri); parsed = httpd_uri_parse(uri);
if (!parsed || !parsed->path) if (!parsed || !parsed->path)
{ {
httpd_redirect_to(req, "/"); httpd_redirect_to(&hreq, "/");
goto out; goto out;
} }
@ -833,7 +888,7 @@ httpd_gen_cb(struct evhttp_request *req, void *arg)
m = modules_search(parsed->path); m = modules_search(parsed->path);
if (m) if (m)
{ {
httpd_request_parse(&hreq, req, parsed, NULL, m->handlers); request_set(&hreq, req, parsed, NULL, m->handlers);
m->request(&hreq); m->request(&hreq);
goto out; goto out;
} }
@ -842,7 +897,7 @@ httpd_gen_cb(struct evhttp_request *req, void *arg)
/* Serve web interface files */ /* Serve web interface files */
serve_file: serve_file:
serve_file(req, parsed->path); serve_file(&hreq, parsed->path);
out: out:
httpd_uri_free(parsed); httpd_uri_free(parsed);
@ -953,63 +1008,14 @@ httpd_uri_parse(const char *uri)
} }
int int
httpd_request_parse(struct httpd_request *hreq, struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed, const char *user_agent, struct httpd_uri_map *uri_map) httpd_request_set(struct httpd_request *hreq, struct httpd_uri_parsed *uri_parsed, const char *user_agent, struct httpd_uri_map *uri_map)
{ {
; return request_set(hreq, NULL, uri_parsed, user_agent, uri_map);
struct evhttp_connection *evcon;
struct evkeyvalq *headers;
struct httpd_uri_map *uri;
int req_method;
int ret;
memset(hreq, 0, sizeof(struct httpd_request));
// Note req is allowed to be NULL
hreq->req = req;
hreq->uri = uri_parsed->uri;
hreq->uri_parsed = uri_parsed;
hreq->query = &(uri_parsed->ev_query);
req_method = 0;
if (req)
{
headers = evhttp_request_get_input_headers(req);
hreq->user_agent = evhttp_find_header(headers, "User-Agent");
evcon = evhttp_request_get_connection(req);
if (evcon)
evhttp_connection_get_peer(evcon, &hreq->peer_address, &hreq->peer_port);
else
DPRINTF(E_LOG, L_HTTPD, "Connection to client lost or missing\n");
req_method = evhttp_request_get_command(req);
}
if (user_agent)
hreq->user_agent = user_agent;
// Find a handler for the path
for (uri = uri_map; uri->handler; uri++)
{
// Check if handler supports the current http request method
if (uri->method && req_method && !(req_method & uri->method))
continue;
ret = regexec(uri->preg, uri_parsed->path, 0, NULL, 0);
if (ret != 0)
continue;
hreq->handler = uri->handler;
return 0; // Success
}
// Handler not found, that's an error
return -1;
} }
/* Thread: httpd */ /* Thread: httpd */
void void
httpd_stream_file(struct evhttp_request *req, int id) httpd_stream_file(struct httpd_request *hreq, int id)
{ {
struct media_quality quality = { HTTPD_STREAM_SAMPLE_RATE, HTTPD_STREAM_BPS, HTTPD_STREAM_CHANNELS, 0 }; struct media_quality quality = { HTTPD_STREAM_SAMPLE_RATE, HTTPD_STREAM_BPS, HTTPD_STREAM_CHANNELS, 0 };
struct media_file_info *mfi; struct media_file_info *mfi;
@ -1034,7 +1040,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
offset = 0; offset = 0;
end_offset = 0; end_offset = 0;
input_headers = evhttp_request_get_input_headers(req); input_headers = evhttp_request_get_input_headers(hreq->req);
param = evhttp_find_header(input_headers, "Range"); param = evhttp_find_header(input_headers, "Range");
if (param) if (param)
@ -1075,7 +1081,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Item %d not found\n", id); DPRINTF(E_LOG, L_HTTPD, "Item %d not found\n", id);
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return; return;
} }
@ -1083,7 +1089,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not serve '%s' to client, not a file\n", mfi->path); DPRINTF(E_LOG, L_HTTPD, "Could not serve '%s' to client, not a file\n", mfi->path);
evhttp_send_error(req, 500, "Cannot stream non-file content"); httpd_send_error(hreq, 500, "Cannot stream non-file content");
goto out_free_mfi; goto out_free_mfi;
} }
@ -1092,7 +1098,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Out of memory for struct stream_ctx\n"); DPRINTF(E_LOG, L_HTTPD, "Out of memory for struct stream_ctx\n");
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_free_mfi; goto out_free_mfi;
} }
memset(st, 0, sizeof(struct stream_ctx)); memset(st, 0, sizeof(struct stream_ctx));
@ -1103,7 +1109,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
transcode = transcode_needed(ua, client_codecs, mfi->codectype); transcode = transcode_needed(ua, client_codecs, mfi->codectype);
output_headers = evhttp_request_get_output_headers(req); output_headers = evhttp_request_get_output_headers(hreq->req);
if (transcode) if (transcode)
{ {
@ -1116,8 +1122,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_WARN, L_HTTPD, "Transcoding setup failed, aborting streaming\n"); DPRINTF(E_WARN, L_HTTPD, "Transcoding setup failed, aborting streaming\n");
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_free_st; goto out_free_st;
} }
@ -1134,8 +1139,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Out of memory for raw streaming buffer\n"); DPRINTF(E_LOG, L_HTTPD, "Out of memory for raw streaming buffer\n");
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_free_st; goto out_free_st;
} }
@ -1146,8 +1150,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", mfi->path, strerror(errno)); DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", mfi->path, strerror(errno));
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
goto out_cleanup; goto out_cleanup;
} }
@ -1156,8 +1159,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", mfi->path, strerror(errno)); DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", mfi->path, strerror(errno));
evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
goto out_cleanup; goto out_cleanup;
} }
st->size = sb.st_size; st->size = sb.st_size;
@ -1167,8 +1169,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not seek into %s: %s\n", mfi->path, strerror(errno)); DPRINTF(E_LOG, L_HTTPD, "Could not seek into %s: %s\n", mfi->path, strerror(errno));
evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
goto out_cleanup; goto out_cleanup;
} }
st->offset = offset; st->offset = offset;
@ -1209,9 +1210,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not allocate an evbuffer for streaming\n"); DPRINTF(E_LOG, L_HTTPD, "Could not allocate an evbuffer for streaming\n");
evhttp_clear_headers(output_headers); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_cleanup; goto out_cleanup;
} }
@ -1220,9 +1219,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not expand evbuffer for streaming\n"); DPRINTF(E_LOG, L_HTTPD, "Could not expand evbuffer for streaming\n");
evhttp_clear_headers(output_headers); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_cleanup; goto out_cleanup;
} }
@ -1232,16 +1229,14 @@ httpd_stream_file(struct evhttp_request *req, int id)
{ {
DPRINTF(E_LOG, L_HTTPD, "Could not add one-shot event for streaming\n"); DPRINTF(E_LOG, L_HTTPD, "Could not add one-shot event for streaming\n");
evhttp_clear_headers(output_headers); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_cleanup; goto out_cleanup;
} }
st->id = mfi->id; st->id = mfi->id;
st->start_offset = offset; st->start_offset = offset;
st->stream_size = st->size; st->stream_size = st->size;
st->req = req; st->req = hreq->req;
if ((offset == 0) && (end_offset == 0)) if ((offset == 0) && (end_offset == 0))
{ {
@ -1258,7 +1253,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
evhttp_add_header(output_headers, "Content-Length", buf); evhttp_add_header(output_headers, "Content-Length", buf);
} }
evhttp_send_reply_start(req, HTTP_OK, "OK"); evhttp_send_reply_start(hreq->req, HTTP_OK, "OK");
} }
else else
{ {
@ -1282,7 +1277,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
else else
evhttp_add_header(output_headers, "Content-Length", buf); evhttp_add_header(output_headers, "Content-Length", buf);
evhttp_send_reply_start(req, 206, "Partial Content"); evhttp_send_reply_start(hreq->req, 206, "Partial Content");
} }
#ifdef HAVE_POSIX_FADVISE #ifdef HAVE_POSIX_FADVISE
@ -1296,7 +1291,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
} }
#endif #endif
evcon = evhttp_request_get_connection(req); evcon = evhttp_request_get_connection(hreq->req);
evhttp_connection_set_closecb(evcon, stream_fail_cb, st); evhttp_connection_set_closecb(evcon, stream_fail_cb, st);
@ -1389,7 +1384,7 @@ httpd_gzip_deflate(struct evbuffer *in)
} }
void void
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags) httpd_send_reply(struct httpd_request *hreq, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags)
{ {
struct evbuffer *gzbuf; struct evbuffer *gzbuf;
struct evkeyvalq *input_headers; struct evkeyvalq *input_headers;
@ -1397,11 +1392,11 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
const char *param; const char *param;
int do_gzip; int do_gzip;
if (!req) if (!hreq->req)
return; return;
input_headers = evhttp_request_get_input_headers(req); input_headers = evhttp_request_get_input_headers(hreq->req);
output_headers = evhttp_request_get_output_headers(req); output_headers = evhttp_request_get_output_headers(hreq->req);
do_gzip = ( (!(flags & HTTPD_SEND_NO_GZIP)) && do_gzip = ( (!(flags & HTTPD_SEND_NO_GZIP)) &&
evbuf && (evbuffer_get_length(evbuf) > 512) && evbuf && (evbuffer_get_length(evbuf) > 512) &&
@ -1417,7 +1412,7 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
DPRINTF(E_DBG, L_HTTPD, "Gzipping response\n"); DPRINTF(E_DBG, L_HTTPD, "Gzipping response\n");
evhttp_add_header(output_headers, "Content-Encoding", "gzip"); evhttp_add_header(output_headers, "Content-Encoding", "gzip");
evhttp_send_reply(req, code, reason, gzbuf); evhttp_send_reply(hreq->req, code, reason, gzbuf);
evbuffer_free(gzbuf); evbuffer_free(gzbuf);
// Drain original buffer, as would be after evhttp_send_reply() // Drain original buffer, as would be after evhttp_send_reply()
@ -1425,24 +1420,24 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
} }
else else
{ {
evhttp_send_reply(req, code, reason, evbuf); evhttp_send_reply(hreq->req, code, reason, evbuf);
} }
} }
// This is a modified version of evhttp_send_error (credit libevent) // This is a modified version of evhttp_send_error (credit libevent)
void void
httpd_send_error(struct evhttp_request* req, int error, const char* reason) httpd_send_error(struct httpd_request *hreq, int error, const char *reason)
{ {
struct evkeyvalq *output_headers; struct evkeyvalq *output_headers;
struct evbuffer *evbuf; struct evbuffer *evbuf;
if (!allow_origin) if (!allow_origin)
{ {
evhttp_send_error(req, error, reason); evhttp_send_error(hreq->req, error, reason);
return; return;
} }
output_headers = evhttp_request_get_output_headers(req); output_headers = evhttp_request_get_output_headers(hreq->req);
evhttp_clear_headers(output_headers); evhttp_clear_headers(output_headers);
@ -1456,14 +1451,14 @@ httpd_send_error(struct evhttp_request* req, int error, const char* reason)
else else
evbuffer_add_printf(evbuf, ERR_PAGE, error, reason, reason); evbuffer_add_printf(evbuf, ERR_PAGE, error, reason, reason);
evhttp_send_reply(req, error, reason, evbuf); evhttp_send_reply(hreq->req, error, reason, evbuf);
if (evbuf) if (evbuf)
evbuffer_free(evbuf); evbuffer_free(evbuf);
} }
bool bool
httpd_admin_check_auth(struct evhttp_request *req) httpd_admin_check_auth(struct httpd_request *hreq)
{ {
struct evhttp_connection *evcon; struct evhttp_connection *evcon;
char *addr; char *addr;
@ -1471,7 +1466,7 @@ httpd_admin_check_auth(struct evhttp_request *req)
const char *passwd; const char *passwd;
int ret; int ret;
evcon = evhttp_request_get_connection(req); evcon = evhttp_request_get_connection(hreq->req);
if (!evcon) if (!evcon)
{ {
DPRINTF(E_LOG, L_HTTPD, "Connection to client lost or missing\n"); DPRINTF(E_LOG, L_HTTPD, "Connection to client lost or missing\n");
@ -1486,18 +1481,18 @@ httpd_admin_check_auth(struct evhttp_request *req)
passwd = cfg_getstr(cfg_getsec(cfg, "general"), "admin_password"); passwd = cfg_getstr(cfg_getsec(cfg, "general"), "admin_password");
if (!passwd) if (!passwd)
{ {
DPRINTF(E_LOG, L_HTTPD, "Web interface request to '%s' denied: No password set in the config\n", evhttp_request_get_uri(req)); DPRINTF(E_LOG, L_HTTPD, "Web interface request to '%s' denied: No password set in the config\n", evhttp_request_get_uri(hreq->req));
httpd_send_error(req, 403, "Forbidden"); httpd_send_error(hreq, 403, "Forbidden");
return false; return false;
} }
DPRINTF(E_DBG, L_HTTPD, "Checking web interface authentication\n"); DPRINTF(E_DBG, L_HTTPD, "Checking web interface authentication\n");
ret = httpd_basic_auth(req, "admin", passwd, PACKAGE " web interface"); ret = httpd_basic_auth(hreq, "admin", passwd, PACKAGE " web interface");
if (ret != 0) if (ret != 0)
{ {
DPRINTF(E_LOG, L_HTTPD, "Web interface request to '%s' denied: Incorrect password\n", evhttp_request_get_uri(req)); DPRINTF(E_LOG, L_HTTPD, "Web interface request to '%s' denied: Incorrect password\n", evhttp_request_get_uri(hreq->req));
// httpd_basic_auth has sent a reply // httpd_basic_auth has sent a reply
return false; return false;
@ -1509,7 +1504,7 @@ httpd_admin_check_auth(struct evhttp_request *req)
} }
int int
httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passwd, const char *realm) httpd_basic_auth(struct httpd_request *hreq, const char *user, const char *passwd, const char *realm)
{ {
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq *headers; struct evkeyvalq *headers;
@ -1519,7 +1514,7 @@ httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passw
char *authpwd; char *authpwd;
int ret; int ret;
headers = evhttp_request_get_input_headers(req); headers = evhttp_request_get_input_headers(hreq->req);
auth = evhttp_find_header(headers, "Authorization"); auth = evhttp_find_header(headers, "Authorization");
if (!auth) if (!auth)
{ {
@ -1584,23 +1579,23 @@ httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passw
ret = snprintf(header, sizeof(header), "Basic realm=\"%s\"", realm); ret = snprintf(header, sizeof(header), "Basic realm=\"%s\"", realm);
if ((ret < 0) || (ret >= sizeof(header))) if ((ret < 0) || (ret >= sizeof(header)))
{ {
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
return -1; return -1;
} }
evbuf = evbuffer_new(); evbuf = evbuffer_new();
if (!evbuf) if (!evbuf)
{ {
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
return -1; return -1;
} }
headers = evhttp_request_get_output_headers(req); headers = evhttp_request_get_output_headers(hreq->req);
evhttp_add_header(headers, "WWW-Authenticate", header); evhttp_add_header(headers, "WWW-Authenticate", header);
evbuffer_add_printf(evbuf, ERR_PAGE, 401, "Unauthorized", "Authorization required"); evbuffer_add_printf(evbuf, ERR_PAGE, 401, "Unauthorized", "Authorization required");
httpd_send_reply(req, 401, "Unauthorized", evbuf, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, 401, "Unauthorized", evbuf, HTTPD_SEND_NO_GZIP);
evbuffer_free(evbuf); evbuffer_free(evbuf);

View File

@ -157,14 +157,14 @@ artworkapi_request(struct httpd_request *hreq)
DPRINTF(E_DBG, L_WEB, "Artwork api request: '%s'\n", hreq->uri); DPRINTF(E_DBG, L_WEB, "Artwork api request: '%s'\n", hreq->uri);
if (!httpd_admin_check_auth(hreq->req)) if (!httpd_admin_check_auth(hreq))
return; return;
if (!hreq->handler) if (!hreq->handler)
{ {
DPRINTF(E_LOG, L_WEB, "Unrecognized path in artwork api request: '%s'\n", hreq->uri); DPRINTF(E_LOG, L_WEB, "Unrecognized path in artwork api request: '%s'\n", hreq->uri);
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return; return;
} }
@ -175,23 +175,23 @@ artworkapi_request(struct httpd_request *hreq)
switch (status_code) switch (status_code)
{ {
case HTTP_OK: /* 200 OK */ case HTTP_OK: /* 200 OK */
httpd_send_reply(hreq->req, status_code, "OK", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, status_code, "OK", hreq->reply, HTTPD_SEND_NO_GZIP);
break; break;
case HTTP_NOCONTENT: /* 204 No Content */ case HTTP_NOCONTENT: /* 204 No Content */
httpd_send_reply(hreq->req, status_code, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, status_code, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
break; break;
case HTTP_NOTMODIFIED: /* 304 Not Modified */ case HTTP_NOTMODIFIED: /* 304 Not Modified */
httpd_send_reply(hreq->req, HTTP_NOTMODIFIED, NULL, NULL, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOTMODIFIED, NULL, NULL, HTTPD_SEND_NO_GZIP);
break; break;
case HTTP_BADREQUEST: /* 400 Bad Request */ case HTTP_BADREQUEST: /* 400 Bad Request */
httpd_send_error(hreq->req, status_code, "Bad Request"); httpd_send_error(hreq, status_code, "Bad Request");
break; break;
case HTTP_NOTFOUND: /* 404 Not Found */ case HTTP_NOTFOUND: /* 404 Not Found */
httpd_send_error(hreq->req, status_code, "Not Found"); httpd_send_error(hreq, status_code, "Not Found");
break; break;
case HTTP_INTERNAL: /* 500 Internal Server Error */ case HTTP_INTERNAL: /* 500 Internal Server Error */
default: default:
httpd_send_error(hreq->req, HTTP_INTERNAL, "Internal Server Error"); httpd_send_error(hreq, HTTP_INTERNAL, "Internal Server Error");
} }
evbuffer_free(hreq->reply); evbuffer_free(hreq->reply);

View File

@ -99,7 +99,7 @@ struct daap_session {
}; };
struct daap_update_request { struct daap_update_request {
struct evhttp_request *req; struct httpd_request *hreq;
/* Refresh tiemout */ /* Refresh tiemout */
struct event *timeout; struct event *timeout;
@ -301,10 +301,10 @@ update_refresh_cb(int fd, short event, void *arg)
dmap_add_int(reply, "mstt", 200); /* 12 */ dmap_add_int(reply, "mstt", 200); /* 12 */
dmap_add_int(reply, "musr", current_rev); /* 12 */ dmap_add_int(reply, "musr", current_rev); /* 12 */
evcon = evhttp_request_get_connection(ur->req); evcon = evhttp_request_get_connection(ur->hreq->req);
evhttp_connection_set_closecb(evcon, NULL, NULL); evhttp_connection_set_closecb(evcon, NULL, NULL);
httpd_send_reply(ur->req, HTTP_OK, "OK", reply, 0); httpd_send_reply(ur->hreq, HTTP_OK, "OK", reply, 0);
update_remove(ur); update_remove(ur);
} }
@ -319,11 +319,11 @@ update_fail_cb(struct evhttp_connection *evcon, void *arg)
DPRINTF(E_DBG, L_DAAP, "Update request: client closed connection\n"); DPRINTF(E_DBG, L_DAAP, "Update request: client closed connection\n");
evc = evhttp_request_get_connection(ur->req); evc = evhttp_request_get_connection(ur->hreq->req);
if (evc) if (evc)
evhttp_connection_set_closecb(evc, NULL, NULL); evhttp_connection_set_closecb(evc, NULL, NULL);
evhttp_request_free(ur->req); evhttp_request_free(ur->hreq->req);
update_remove(ur); update_remove(ur);
} }
@ -675,26 +675,26 @@ daap_reply_send(struct httpd_request *hreq, enum daap_reply_result result)
switch (result) switch (result)
{ {
case DAAP_REPLY_LOGOUT: case DAAP_REPLY_LOGOUT:
httpd_send_reply(hreq->req, 204, "Logout Successful", hreq->reply, 0); httpd_send_reply(hreq, 204, "Logout Successful", hreq->reply, 0);
break; break;
case DAAP_REPLY_NO_CONTENT: case DAAP_REPLY_NO_CONTENT:
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
break; break;
case DAAP_REPLY_OK: case DAAP_REPLY_OK:
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
break; break;
case DAAP_REPLY_OK_NO_GZIP: case DAAP_REPLY_OK_NO_GZIP:
case DAAP_REPLY_ERROR: case DAAP_REPLY_ERROR:
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, HTTPD_SEND_NO_GZIP);
break; break;
case DAAP_REPLY_FORBIDDEN: case DAAP_REPLY_FORBIDDEN:
httpd_send_error(hreq->req, 403, "Forbidden"); httpd_send_error(hreq, 403, "Forbidden");
break; break;
case DAAP_REPLY_BAD_REQUEST: case DAAP_REPLY_BAD_REQUEST:
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
break; break;
case DAAP_REPLY_SERVUNAVAIL: case DAAP_REPLY_SERVUNAVAIL:
httpd_send_error(hreq->req, HTTP_SERVUNAVAIL, "Internal Server Error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
break; break;
case DAAP_REPLY_NO_CONNECTION: case DAAP_REPLY_NO_CONNECTION:
case DAAP_REPLY_NONE: case DAAP_REPLY_NONE:
@ -728,7 +728,7 @@ daap_request_authorize(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DAAP, "Unauthorized request from '%s', DAAP session not found: '%s'\n", hreq->peer_address, hreq->uri_parsed->uri); DPRINTF(E_LOG, L_DAAP, "Unauthorized request from '%s', DAAP session not found: '%s'\n", hreq->peer_address, hreq->uri_parsed->uri);
httpd_send_error(hreq->req, 401, "Unauthorized"); httpd_send_error(hreq, 401, "Unauthorized");
return -1; return -1;
} }
@ -750,7 +750,7 @@ daap_request_authorize(struct httpd_request *hreq)
DPRINTF(E_DBG, L_DAAP, "Checking authentication for library\n"); DPRINTF(E_DBG, L_DAAP, "Checking authentication for library\n");
// We don't care about the username // We don't care about the username
ret = httpd_basic_auth(hreq->req, NULL, passwd, cfg_getstr(cfg_getsec(cfg, "library"), "name")); ret = httpd_basic_auth(hreq, NULL, passwd, cfg_getstr(cfg_getsec(cfg, "library"), "name"));
if (ret != 0) if (ret != 0)
{ {
DPRINTF(E_LOG, L_DAAP, "Unsuccessful library authorization attempt from '%s'\n", hreq->peer_address); DPRINTF(E_LOG, L_DAAP, "Unsuccessful library authorization attempt from '%s'\n", hreq->peer_address);
@ -1062,7 +1062,7 @@ daap_reply_update(struct httpd_request *hreq)
} }
/* NOTE: we may need to keep reqd_rev in there too */ /* NOTE: we may need to keep reqd_rev in there too */
ur->req = hreq->req; ur->hreq = hreq;
ur->next = update_requests; ur->next = update_requests;
update_requests = ur; update_requests = ur;
@ -2048,7 +2048,7 @@ daap_stream(struct httpd_request *hreq)
if (ret < 0) if (ret < 0)
return DAAP_REPLY_BAD_REQUEST; return DAAP_REPLY_BAD_REQUEST;
httpd_stream_file(hreq->req, id); httpd_stream_file(hreq, id);
return DAAP_REPLY_NONE; return DAAP_REPLY_NONE;
} }
@ -2243,7 +2243,7 @@ daap_request(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DAAP, "Unrecognized path in DAAP request: '%s'\n", hreq->uri); DPRINTF(E_LOG, L_DAAP, "Unrecognized path in DAAP request: '%s'\n", hreq->uri);
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return; return;
} }
@ -2290,7 +2290,7 @@ daap_request(struct httpd_request *hreq)
{ {
// The cache will return the data gzipped, so httpd_send_reply won't need to do it // The cache will return the data gzipped, so httpd_send_reply won't need to do it
evhttp_add_header(headers, "Content-Encoding", "gzip"); evhttp_add_header(headers, "Content-Encoding", "gzip");
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, HTTPD_SEND_NO_GZIP); // TODO not all want this reply httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, HTTPD_SEND_NO_GZIP); // TODO not all want this reply
evbuffer_free(hreq->reply); evbuffer_free(hreq->reply);
return; return;
@ -2345,7 +2345,7 @@ daap_reply_build(const char *uri, const char *user_agent, int is_remote)
if (!uri_parsed) if (!uri_parsed)
return NULL; return NULL;
ret = httpd_request_parse(&hreq, NULL, uri_parsed, user_agent, daap_handlers); ret = httpd_request_set(&hreq, uri_parsed, user_agent, daap_handlers);
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_LOG, L_DAAP, "Cannot build reply, unrecognized path '%s' in request: '%s'\n", uri_parsed->path, uri_parsed->uri); DPRINTF(E_LOG, L_DAAP, "Cannot build reply, unrecognized path '%s' in request: '%s'\n", uri_parsed->path, uri_parsed->uri);
@ -2401,7 +2401,7 @@ daap_deinit(void)
{ {
update_requests = ur->next; update_requests = ur->next;
evcon = evhttp_request_get_connection(ur->req); evcon = evhttp_request_get_connection(ur->hreq->req);
if (evcon) if (evcon)
{ {
evhttp_connection_set_closecb(evcon, NULL, NULL); evhttp_connection_set_closecb(evcon, NULL, NULL);

View File

@ -54,7 +54,7 @@
extern struct event_base *evbase_httpd; extern struct event_base *evbase_httpd;
struct dacp_update_request { struct dacp_update_request {
struct evhttp_request *req; struct httpd_request *hreq;
struct dacp_update_request *next; struct dacp_update_request *next;
}; };
@ -155,11 +155,11 @@ static struct db_queue_item dummy_queue_item;
/* -------------------------------- HELPERS --------------------------------- */ /* -------------------------------- HELPERS --------------------------------- */
static void static void
dacp_send_error(struct evhttp_request *req, const char *container, const char *errmsg) dacp_send_error(struct httpd_request *hreq, const char *container, const char *errmsg)
{ {
struct evbuffer *evbuf; struct evbuffer *evbuf;
if (!req) if (!hreq)
return; return;
evbuf = evbuffer_new(); evbuf = evbuffer_new();
@ -167,13 +167,13 @@ dacp_send_error(struct evhttp_request *req, const char *container, const char *e
{ {
DPRINTF(E_LOG, L_DACP, "Could not allocate evbuffer for DMAP error\n"); DPRINTF(E_LOG, L_DACP, "Could not allocate evbuffer for DMAP error\n");
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
return; return;
} }
dmap_error_make(evbuf, container, errmsg); dmap_error_make(evbuf, container, errmsg);
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
evbuffer_free(evbuf); evbuffer_free(evbuf);
} }
@ -658,7 +658,7 @@ dacp_request_authorize(struct httpd_request *hreq)
invalid: invalid:
DPRINTF(E_LOG, L_DACP, "Unauthorized request '%s' from '%s' (is peer trusted in your config?)\n", hreq->uri_parsed->uri, hreq->peer_address); DPRINTF(E_LOG, L_DACP, "Unauthorized request '%s' from '%s' (is peer trusted in your config?)\n", hreq->uri_parsed->uri, hreq->peer_address);
httpd_send_error(hreq->req, 403, "Forbidden"); httpd_send_error(hreq, 403, "Forbidden");
return -1; return -1;
} }
@ -776,7 +776,7 @@ playstatusupdate_cb(int fd, short what, void *arg)
{ {
update_requests = ur->next; update_requests = ur->next;
evcon = evhttp_request_get_connection(ur->req); evcon = evhttp_request_get_connection(ur->hreq->req);
if (evcon) if (evcon)
evhttp_connection_set_closecb(evcon, NULL, NULL); evhttp_connection_set_closecb(evcon, NULL, NULL);
@ -785,10 +785,10 @@ playstatusupdate_cb(int fd, short what, void *arg)
{ {
buf = evbuffer_pullup(update, -1); buf = evbuffer_pullup(update, -1);
evbuffer_add(evbuf, buf, len); evbuffer_add(evbuf, buf, len);
httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf, 0); httpd_send_reply(ur->hreq, HTTP_OK, "OK", evbuf, 0);
} }
else else
httpd_send_reply(ur->req, HTTP_OK, "OK", update, 0); httpd_send_reply(ur->hreq, HTTP_OK, "OK", update, 0);
free(ur); free(ur);
} }
@ -832,7 +832,7 @@ update_fail_cb(struct evhttp_connection *evcon, void *arg)
DPRINTF(E_DBG, L_DACP, "Update request: client closed connection\n"); DPRINTF(E_DBG, L_DACP, "Update request: client closed connection\n");
evc = evhttp_request_get_connection(ur->req); evc = evhttp_request_get_connection(ur->hreq->req);
if (evc) if (evc)
evhttp_connection_set_closecb(evc, NULL, NULL); evhttp_connection_set_closecb(evc, NULL, NULL);
@ -852,7 +852,7 @@ update_fail_cb(struct evhttp_connection *evcon, void *arg)
p->next = ur->next; p->next = ur->next;
} }
evhttp_request_free(ur->req); evhttp_request_free(ur->hreq->req);
free(ur); free(ur);
} }
@ -1218,7 +1218,7 @@ dacp_reply_ctrlint(struct httpd_request *hreq)
dmap_add_char(hreq->reply, "cmrl", 1); /* 9, unknown */ dmap_add_char(hreq->reply, "cmrl", 1); /* 9, unknown */
dmap_add_long(hreq->reply, "ceSX", (1 << 1 | 1)); /* 16, unknown dacp - lowest bit announces support for playqueue-contents/-edit */ dmap_add_long(hreq->reply, "ceSX", (1 << 1 | 1)); /* 16, unknown dacp - lowest bit announces support for playqueue-contents/-edit */
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
return 0; return 0;
} }
@ -1264,7 +1264,7 @@ dacp_reply_cue_play(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n"); DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
dacp_send_error(hreq->req, "cacr", "Could not build song queue"); dacp_send_error(hreq, "cacr", "Could not build song queue");
return -1; return -1;
} }
} }
@ -1304,7 +1304,7 @@ dacp_reply_cue_play(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not start playback from history\n"); DPRINTF(E_LOG, L_DACP, "Could not start playback from history\n");
dacp_send_error(hreq->req, "cacr", "Playback failed to start"); dacp_send_error(hreq, "cacr", "Playback failed to start");
return -1; return -1;
} }
} }
@ -1312,7 +1312,7 @@ dacp_reply_cue_play(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not start playback from history\n"); DPRINTF(E_LOG, L_DACP, "Could not start playback from history\n");
dacp_send_error(hreq->req, "cacr", "Playback failed to start"); dacp_send_error(hreq, "cacr", "Playback failed to start");
return -1; return -1;
} }
} }
@ -1327,7 +1327,7 @@ dacp_reply_cue_play(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not fetch item from queue: pos=%d, now playing=%d\n", pos, status.item_id); DPRINTF(E_LOG, L_DACP, "Could not fetch item from queue: pos=%d, now playing=%d\n", pos, status.item_id);
dacp_send_error(hreq->req, "cacr", "Playback failed to start"); dacp_send_error(hreq, "cacr", "Playback failed to start");
return -1; return -1;
} }
} }
@ -1339,7 +1339,7 @@ dacp_reply_cue_play(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not fetch item from queue: pos=%d\n", pos); DPRINTF(E_LOG, L_DACP, "Could not fetch item from queue: pos=%d\n", pos);
dacp_send_error(hreq->req, "cacr", "Playback failed to start"); dacp_send_error(hreq, "cacr", "Playback failed to start");
return -1; return -1;
} }
} }
@ -1350,7 +1350,7 @@ dacp_reply_cue_play(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not start playback\n"); DPRINTF(E_LOG, L_DACP, "Could not start playback\n");
dacp_send_error(hreq->req, "cacr", "Playback failed to start"); dacp_send_error(hreq, "cacr", "Playback failed to start");
return -1; return -1;
} }
@ -1362,7 +1362,7 @@ dacp_reply_cue_play(struct httpd_request *hreq)
dmap_add_int(hreq->reply, "mstt", 200); /* 12 */ dmap_add_int(hreq->reply, "mstt", 200); /* 12 */
dmap_add_int(hreq->reply, "miid", status.id);/* 12 */ dmap_add_int(hreq->reply, "miid", status.id);/* 12 */
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
return 0; return 0;
} }
@ -1382,7 +1382,7 @@ dacp_reply_cue_clear(struct httpd_request *hreq)
dmap_add_int(hreq->reply, "mstt", 200); /* 12 */ dmap_add_int(hreq->reply, "mstt", 200); /* 12 */
dmap_add_int(hreq->reply, "miid", 0); /* 12 */ dmap_add_int(hreq->reply, "miid", 0); /* 12 */
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
return 0; return 0;
} }
@ -1402,7 +1402,7 @@ dacp_reply_cue(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "No command in cue request\n"); DPRINTF(E_LOG, L_DACP, "No command in cue request\n");
dacp_send_error(hreq->req, "cacr", "No command in cue request"); dacp_send_error(hreq, "cacr", "No command in cue request");
return -1; return -1;
} }
@ -1414,7 +1414,7 @@ dacp_reply_cue(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Unknown cue command %s\n", param); DPRINTF(E_LOG, L_DACP, "Unknown cue command %s\n", param);
dacp_send_error(hreq->req, "cacr", "Unknown command in cue request"); dacp_send_error(hreq, "cacr", "Unknown command in cue request");
return -1; return -1;
} }
} }
@ -1431,12 +1431,12 @@ dacp_reply_play(struct httpd_request *hreq)
ret = player_playback_start(); ret = player_playback_start();
if (ret < 0) if (ret < 0)
{ {
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1568,11 +1568,11 @@ dacp_reply_playspec(struct httpd_request *hreq)
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
out_fail: out_fail:
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
@ -1589,7 +1589,7 @@ dacp_reply_stop(struct httpd_request *hreq)
player_playback_stop(); player_playback_stop();
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1606,7 +1606,7 @@ dacp_reply_pause(struct httpd_request *hreq)
player_playback_pause(); player_playback_pause();
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1633,13 +1633,13 @@ dacp_reply_playpause(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Player returned an error for start after pause\n"); DPRINTF(E_LOG, L_DACP, "Player returned an error for start after pause\n");
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1658,7 +1658,7 @@ dacp_reply_nextitem(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Player returned an error for nextitem\n"); DPRINTF(E_LOG, L_DACP, "Player returned an error for nextitem\n");
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
@ -1667,12 +1667,12 @@ dacp_reply_nextitem(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Player returned an error for start after nextitem\n"); DPRINTF(E_LOG, L_DACP, "Player returned an error for start after nextitem\n");
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1691,7 +1691,7 @@ dacp_reply_previtem(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Player returned an error for previtem\n"); DPRINTF(E_LOG, L_DACP, "Player returned an error for previtem\n");
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
@ -1700,12 +1700,12 @@ dacp_reply_previtem(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Player returned an error for start after previtem\n"); DPRINTF(E_LOG, L_DACP, "Player returned an error for start after previtem\n");
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1722,7 +1722,7 @@ dacp_reply_beginff(struct httpd_request *hreq)
/* TODO */ /* TODO */
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1739,7 +1739,7 @@ dacp_reply_beginrew(struct httpd_request *hreq)
/* TODO */ /* TODO */
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1756,7 +1756,7 @@ dacp_reply_playresume(struct httpd_request *hreq)
/* TODO */ /* TODO */
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -1908,7 +1908,7 @@ dacp_reply_playqueuecontents(struct httpd_request *hreq)
dmap_add_char(hreq->reply, "apsm", status.shuffle); /* 9, daap.playlistshufflemode - not part of mlcl container */ dmap_add_char(hreq->reply, "apsm", status.shuffle); /* 9, daap.playlistshufflemode - not part of mlcl container */
dmap_add_char(hreq->reply, "aprm", status.repeat); /* 9, daap.playlistrepeatmode - not part of mlcl container */ dmap_add_char(hreq->reply, "aprm", status.repeat); /* 9, daap.playlistrepeatmode - not part of mlcl container */
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
return 0; return 0;
@ -1916,7 +1916,7 @@ dacp_reply_playqueuecontents(struct httpd_request *hreq)
DPRINTF(E_LOG, L_DACP, "Database error in dacp_reply_playqueuecontents\n"); DPRINTF(E_LOG, L_DACP, "Database error in dacp_reply_playqueuecontents\n");
evbuffer_free(songlist); evbuffer_free(songlist);
dacp_send_error(hreq->req, "ceQR", "Database error"); dacp_send_error(hreq, "ceQR", "Database error");
return -1; return -1;
} }
@ -1946,7 +1946,7 @@ dacp_reply_playqueueedit_clear(struct httpd_request *hreq)
dmap_add_int(hreq->reply, "mstt", 200); /* 12 */ dmap_add_int(hreq->reply, "mstt", 200); /* 12 */
dmap_add_int(hreq->reply, "miid", 0); /* 12 */ dmap_add_int(hreq->reply, "miid", 0); /* 12 */
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
return 0; return 0;
} }
@ -1986,7 +1986,7 @@ dacp_reply_playqueueedit_add(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Invalid mode value in playqueue-edit request\n"); DPRINTF(E_LOG, L_DACP, "Invalid mode value in playqueue-edit request\n");
dacp_send_error(hreq->req, "cacr", "Invalid request"); dacp_send_error(hreq, "cacr", "Invalid request");
return -1; return -1;
} }
} }
@ -2005,7 +2005,7 @@ dacp_reply_playqueueedit_add(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not add song queue, DACP query missing\n"); DPRINTF(E_LOG, L_DACP, "Could not add song queue, DACP query missing\n");
dacp_send_error(hreq->req, "cacr", "Invalid request"); dacp_send_error(hreq, "cacr", "Invalid request");
return -1; return -1;
} }
@ -2034,7 +2034,7 @@ dacp_reply_playqueueedit_add(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Invalid playlist id in request: %s\n", editquery); DPRINTF(E_LOG, L_DACP, "Invalid playlist id in request: %s\n", editquery);
dacp_send_error(hreq->req, "cacr", "Invalid request"); dacp_send_error(hreq, "cacr", "Invalid request");
return -1; return -1;
} }
@ -2046,7 +2046,7 @@ dacp_reply_playqueueedit_add(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not build song queue\n"); DPRINTF(E_LOG, L_DACP, "Could not build song queue\n");
dacp_send_error(hreq->req, "cacr", "Invalid request"); dacp_send_error(hreq, "cacr", "Invalid request");
return -1; return -1;
} }
@ -2079,12 +2079,12 @@ dacp_reply_playqueueedit_add(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not start playback\n"); DPRINTF(E_LOG, L_DACP, "Could not start playback\n");
dacp_send_error(hreq->req, "cacr", "Playback failed to start"); dacp_send_error(hreq, "cacr", "Playback failed to start");
return -1; return -1;
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -2114,7 +2114,7 @@ dacp_reply_playqueueedit_move(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Invalid edit-params move-from value in playqueue-edit request\n"); DPRINTF(E_LOG, L_DACP, "Invalid edit-params move-from value in playqueue-edit request\n");
dacp_send_error(hreq->req, "cacr", "Invalid request"); dacp_send_error(hreq, "cacr", "Invalid request");
return -1; return -1;
} }
@ -2123,7 +2123,7 @@ dacp_reply_playqueueedit_move(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Invalid edit-params move-to value in playqueue-edit request\n"); DPRINTF(E_LOG, L_DACP, "Invalid edit-params move-to value in playqueue-edit request\n");
dacp_send_error(hreq->req, "cacr", "Invalid request"); dacp_send_error(hreq, "cacr", "Invalid request");
return -1; return -1;
} }
@ -2132,7 +2132,7 @@ dacp_reply_playqueueedit_move(struct httpd_request *hreq)
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -2158,7 +2158,7 @@ dacp_reply_playqueueedit_remove(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Invalid edit-params remove item value in playqueue-edit request\n"); DPRINTF(E_LOG, L_DACP, "Invalid edit-params remove item value in playqueue-edit request\n");
dacp_send_error(hreq->req, "cacr", "Invalid request"); dacp_send_error(hreq, "cacr", "Invalid request");
return -1; return -1;
} }
@ -2168,7 +2168,7 @@ dacp_reply_playqueueedit_remove(struct httpd_request *hreq)
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -2231,7 +2231,7 @@ dacp_reply_playqueueedit(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "No command in playqueue-edit request\n"); DPRINTF(E_LOG, L_DACP, "No command in playqueue-edit request\n");
dacp_send_error(hreq->req, "cmst", "Invalid request"); dacp_send_error(hreq, "cmst", "Invalid request");
return -1; return -1;
} }
@ -2249,7 +2249,7 @@ dacp_reply_playqueueedit(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Unknown playqueue-edit command %s\n", param); DPRINTF(E_LOG, L_DACP, "Unknown playqueue-edit command %s\n", param);
dacp_send_error(hreq->req, "cmst", "Invalid request"); dacp_send_error(hreq, "cmst", "Invalid request");
return -1; return -1;
} }
} }
@ -2272,7 +2272,7 @@ dacp_reply_playstatusupdate(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Missing revision-number in update request\n"); DPRINTF(E_LOG, L_DACP, "Missing revision-number in update request\n");
dacp_send_error(hreq->req, "cmst", "Invalid request"); dacp_send_error(hreq, "cmst", "Invalid request");
return -1; return -1;
} }
@ -2281,7 +2281,7 @@ dacp_reply_playstatusupdate(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Parameter revision-number not an integer\n"); DPRINTF(E_LOG, L_DACP, "Parameter revision-number not an integer\n");
dacp_send_error(hreq->req, "cmst", "Invalid request"); dacp_send_error(hreq, "cmst", "Invalid request");
return -1; return -1;
} }
@ -2292,9 +2292,9 @@ dacp_reply_playstatusupdate(struct httpd_request *hreq)
{ {
ret = make_playstatusupdate(hreq->reply); ret = make_playstatusupdate(hreq->reply);
if (ret < 0) if (ret < 0)
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
else else
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
return ret; return ret;
} }
@ -2305,11 +2305,11 @@ dacp_reply_playstatusupdate(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Out of memory for update request\n"); DPRINTF(E_LOG, L_DACP, "Out of memory for update request\n");
dacp_send_error(hreq->req, "cmst", "Out of memory"); dacp_send_error(hreq, "cmst", "Out of memory");
return -1; return -1;
} }
ur->req = hreq->req; ur->hreq = hreq;
ur->next = update_requests; ur->next = update_requests;
update_requests = ur; update_requests = ur;
@ -2399,15 +2399,15 @@ dacp_reply_nowplayingartwork(struct httpd_request *hreq)
snprintf(clen, sizeof(clen), "%ld", (long)len); snprintf(clen, sizeof(clen), "%ld", (long)len);
evhttp_add_header(headers, "Content-Length", clen); evhttp_add_header(headers, "Content-Length", clen);
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
no_artwork: no_artwork:
httpd_send_error(hreq->req, HTTP_NOTFOUND, "Not Found"); httpd_send_error(hreq, HTTP_NOTFOUND, "Not Found");
return 0; return 0;
error: error:
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return -1; return -1;
} }
@ -2434,7 +2434,7 @@ dacp_reply_getproperty(struct httpd_request *hreq)
{ {
DPRINTF(E_WARN, L_DACP, "Invalid DACP getproperty request, no properties\n"); DPRINTF(E_WARN, L_DACP, "Invalid DACP getproperty request, no properties\n");
dacp_send_error(hreq->req, "cmgt", "Invalid request"); dacp_send_error(hreq, "cmgt", "Invalid request");
return -1; return -1;
} }
@ -2443,7 +2443,7 @@ dacp_reply_getproperty(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not duplicate properties parameter; out of memory\n"); DPRINTF(E_LOG, L_DACP, "Could not duplicate properties parameter; out of memory\n");
dacp_send_error(hreq->req, "cmgt", "Out of memory"); dacp_send_error(hreq, "cmgt", "Out of memory");
return -1; return -1;
} }
@ -2452,7 +2452,7 @@ dacp_reply_getproperty(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not allocate evbuffer for properties list\n"); DPRINTF(E_LOG, L_DACP, "Could not allocate evbuffer for properties list\n");
dacp_send_error(hreq->req, "cmgt", "Out of memory"); dacp_send_error(hreq, "cmgt", "Out of memory");
goto out_free_propstr; goto out_free_propstr;
} }
@ -2465,7 +2465,7 @@ dacp_reply_getproperty(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Could not fetch queue_item for item-id %d\n", status.item_id); DPRINTF(E_LOG, L_DACP, "Could not fetch queue_item for item-id %d\n", status.item_id);
dacp_send_error(hreq->req, "cmgt", "Server error"); dacp_send_error(hreq, "cmgt", "Server error");
goto out_free_proplist; goto out_free_proplist;
} }
} }
@ -2500,7 +2500,7 @@ dacp_reply_getproperty(struct httpd_request *hreq)
evbuffer_free(proplist); evbuffer_free(proplist);
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
return 0; return 0;
@ -2553,7 +2553,7 @@ dacp_reply_setproperty(struct httpd_request *hreq)
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -2581,7 +2581,7 @@ dacp_reply_getspeakers(struct httpd_request *hreq)
evbuffer_free(spklist); evbuffer_free(spklist);
httpd_send_reply(hreq->req, HTTP_OK, "OK", hreq->reply, 0); httpd_send_reply(hreq, HTTP_OK, "OK", hreq->reply, 0);
return 0; return 0;
} }
@ -2605,7 +2605,7 @@ dacp_reply_setspeakers(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Missing speaker-id parameter in DACP setspeakers request\n"); DPRINTF(E_LOG, L_DACP, "Missing speaker-id parameter in DACP setspeakers request\n");
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return -1; return -1;
} }
@ -2663,15 +2663,15 @@ dacp_reply_setspeakers(struct httpd_request *hreq)
/* Password problem */ /* Password problem */
if (ret == -2) if (ret == -2)
httpd_send_error(hreq->req, 902, ""); httpd_send_error(hreq, 902, "");
else else
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -2685,19 +2685,19 @@ dacp_reply_volumeup(struct httpd_request *hreq)
ret = speaker_get(&speaker_info, hreq, "volumeup"); ret = speaker_get(&speaker_info, hreq, "volumeup");
if (ret < 0) if (ret < 0)
{ {
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return -1; return -1;
} }
ret = speaker_volume_step(&speaker_info, DACP_VOLUME_STEP); ret = speaker_volume_step(&speaker_info, DACP_VOLUME_STEP);
if (ret < 0) if (ret < 0)
{ {
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return -1; return -1;
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -2711,19 +2711,19 @@ dacp_reply_volumedown(struct httpd_request *hreq)
ret = speaker_get(&speaker_info, hreq, "volumedown"); ret = speaker_get(&speaker_info, hreq, "volumedown");
if (ret < 0) if (ret < 0)
{ {
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return -1; return -1;
} }
ret = speaker_volume_step(&speaker_info, -DACP_VOLUME_STEP); ret = speaker_volume_step(&speaker_info, -DACP_VOLUME_STEP);
if (ret < 0) if (ret < 0)
{ {
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return -1; return -1;
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -2737,7 +2737,7 @@ dacp_reply_mutetoggle(struct httpd_request *hreq)
ret = speaker_get(&speaker_info, hreq, "mutetoggle"); ret = speaker_get(&speaker_info, hreq, "mutetoggle");
if (ret < 0) if (ret < 0)
{ {
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return -1; return -1;
} }
@ -2745,12 +2745,12 @@ dacp_reply_mutetoggle(struct httpd_request *hreq)
ret = speaker_info.selected ? player_speaker_disable(speaker_info.id) : player_speaker_enable(speaker_info.id); ret = speaker_info.selected ? player_speaker_disable(speaker_info.id) : player_speaker_enable(speaker_info.id);
if (ret < 0) if (ret < 0)
{ {
httpd_send_error(hreq->req, 500, "Internal Server Error"); httpd_send_error(hreq, 500, "Internal Server Error");
return -1; return -1;
} }
/* 204 No Content is the canonical reply */ /* 204 No Content is the canonical reply */
httpd_send_reply(hreq->req, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOCONTENT, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
return 0; return 0;
} }
@ -2873,7 +2873,7 @@ dacp_request(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_DACP, "Unrecognized path in DACP request: '%s'\n", hreq->uri); DPRINTF(E_LOG, L_DACP, "Unrecognized path in DACP request: '%s'\n", hreq->uri);
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return; return;
} }
@ -2957,7 +2957,7 @@ dacp_deinit(void)
{ {
update_requests = ur->next; update_requests = ur->next;
evcon = evhttp_request_get_connection(ur->req); evcon = evhttp_request_get_connection(ur->hreq->req);
if (evcon) if (evcon)
{ {
evhttp_connection_set_closecb(evcon, NULL, NULL); evhttp_connection_set_closecb(evcon, NULL, NULL);

View File

@ -123,25 +123,19 @@ struct httpd_uri_parsed *
httpd_uri_parse(const char *uri); httpd_uri_parse(const char *uri);
void void
httpd_stream_file(struct evhttp_request *req, int id); httpd_stream_file(struct httpd_request *hreq, int id);
/*
* Parse a request into the httpd_request struct. Nothing is copied, so the
* pointers in the returned struct are only valid as long as the inputs are
* still valid. If req is not null, then we will find the user-agent from the
* request headers, except if provided as an argument to this function.
*/
int int
httpd_request_parse(struct httpd_request *hreq, struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed, const char *user_agent, struct httpd_uri_map *uri_map); httpd_request_set(struct httpd_request *hreq, struct httpd_uri_parsed *uri_parsed, const char *user_agent, struct httpd_uri_map *uri_map);
bool bool
httpd_request_not_modified_since(struct evhttp_request *req, time_t mtime); httpd_request_not_modified_since(struct httpd_request *hreq, time_t mtime);
bool bool
httpd_request_etag_matches(struct evhttp_request *req, const char *etag); httpd_request_etag_matches(struct httpd_request *hreq, const char *etag);
void void
httpd_response_not_cachable(struct evhttp_request *req); httpd_response_not_cachable(struct httpd_request *hreq);
/* /*
* This wrapper around evhttp_send_reply should be used whenever a request may * This wrapper around evhttp_send_reply should be used whenever a request may
@ -149,7 +143,7 @@ httpd_response_not_cachable(struct evhttp_request *req);
* may direct it not to. It will set CORS headers as appropriate. Should be * may direct it not to. It will set CORS headers as appropriate. Should be
* thread safe. * thread safe.
* *
* @in req The evhttp request struct * @in req The http request struct
* @in code HTTP code, e.g. 200 * @in code HTTP code, e.g. 200
* @in reason A brief explanation of the error - if NULL the standard meaning * @in reason A brief explanation of the error - if NULL the standard meaning
of the error code will be used of the error code will be used
@ -157,7 +151,7 @@ httpd_response_not_cachable(struct evhttp_request *req);
* @in flags See flags above * @in flags See flags above
*/ */
void void
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags); httpd_send_reply(struct httpd_request *hreq, int code, const char *reason, struct evbuffer *evbuf, enum httpd_send_flags flags);
/* /*
* This is a substitute for evhttp_send_error that should be used whenever an * This is a substitute for evhttp_send_error that should be used whenever an
@ -165,24 +159,24 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
* which is not possible with evhttp_send_error, because it clears the headers. * which is not possible with evhttp_send_error, because it clears the headers.
* Should be thread safe. * Should be thread safe.
* *
* @in req The evhttp request struct * @in req The http request struct
* @in error HTTP code, e.g. 200 * @in error HTTP code, e.g. 200
* @in reason A brief explanation of the error - if NULL the standard meaning * @in reason A brief explanation of the error - if NULL the standard meaning
of the error code will be used of the error code will be used
*/ */
void void
httpd_send_error(struct evhttp_request *req, int error, const char *reason); httpd_send_error(struct httpd_request *hreq, int error, const char *reason);
/* /*
* Redirects to the given path * Redirects to the given path
*/ */
void void
httpd_redirect_to(struct evhttp_request *req, const char *path); httpd_redirect_to(struct httpd_request *hreq, const char *path);
bool bool
httpd_admin_check_auth(struct evhttp_request *req); httpd_admin_check_auth(struct httpd_request *hreq);
int int
httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passwd, const char *realm); httpd_basic_auth(struct httpd_request *hreq, const char *user, const char *passwd, const char *realm);
#endif /* !__HTTPD_INTERNAL_H__ */ #endif /* !__HTTPD_INTERNAL_H__ */

View File

@ -68,13 +68,13 @@ static char *default_playlist_directory;
/* -------------------------------- HELPERS --------------------------------- */ /* -------------------------------- HELPERS --------------------------------- */
static bool static bool
is_modified(struct evhttp_request *req, const char *key) is_modified(struct httpd_request *hreq, const char *key)
{ {
int64_t db_update = 0; int64_t db_update = 0;
db_admin_getint64(&db_update, key); db_admin_getint64(&db_update, key);
return (!db_update || !httpd_request_not_modified_since(req, (time_t)db_update)); return (!db_update || !httpd_request_not_modified_since(hreq, (time_t)db_update));
} }
static inline void static inline void
@ -2697,7 +2697,7 @@ jsonapi_reply_queue(struct httpd_request *hreq)
db_queue_get_count(&count); db_queue_get_count(&count);
snprintf(etag, sizeof(etag), "%d", version); snprintf(etag, sizeof(etag), "%d", version);
if (httpd_request_etag_matches(hreq->req, etag)) if (httpd_request_etag_matches(hreq, etag))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
memset(&query_params, 0, sizeof(struct query_params)); memset(&query_params, 0, sizeof(struct query_params));
@ -2953,7 +2953,7 @@ jsonapi_reply_library_artists(struct httpd_request *hreq)
int total; int total;
int ret = 0; int ret = 0;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
media_kind = 0; media_kind = 0;
@ -3014,7 +3014,7 @@ jsonapi_reply_library_artist(struct httpd_request *hreq)
int ret = 0; int ret = 0;
bool notfound = false; bool notfound = false;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
artist_id = hreq->uri_parsed->path_parts[3]; artist_id = hreq->uri_parsed->path_parts[3];
@ -3049,7 +3049,7 @@ jsonapi_reply_library_artist_albums(struct httpd_request *hreq)
int total; int total;
int ret = 0; int ret = 0;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
artist_id = hreq->uri_parsed->path_parts[3]; artist_id = hreq->uri_parsed->path_parts[3];
@ -3102,7 +3102,7 @@ jsonapi_reply_library_albums(struct httpd_request *hreq)
int total; int total;
int ret = 0; int ret = 0;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
media_kind = 0; media_kind = 0;
@ -3163,7 +3163,7 @@ jsonapi_reply_library_album(struct httpd_request *hreq)
int ret = 0; int ret = 0;
bool notfound = false; bool notfound = false;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
album_id = hreq->uri_parsed->path_parts[3]; album_id = hreq->uri_parsed->path_parts[3];
@ -3198,7 +3198,7 @@ jsonapi_reply_library_album_tracks(struct httpd_request *hreq)
int total; int total;
int ret = 0; int ret = 0;
if (!is_modified(hreq->req, DB_ADMIN_DB_MODIFIED)) if (!is_modified(hreq, DB_ADMIN_DB_MODIFIED))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
album_id = hreq->uri_parsed->path_parts[3]; album_id = hreq->uri_parsed->path_parts[3];
@ -3282,7 +3282,7 @@ jsonapi_reply_library_tracks_get_byid(struct httpd_request *hreq)
int ret = 0; int ret = 0;
bool notfound = false; bool notfound = false;
if (!is_modified(hreq->req, DB_ADMIN_DB_MODIFIED)) if (!is_modified(hreq, DB_ADMIN_DB_MODIFIED))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
track_id = hreq->uri_parsed->path_parts[3]; track_id = hreq->uri_parsed->path_parts[3];
@ -3481,7 +3481,7 @@ jsonapi_reply_library_track_playlists(struct httpd_request *hreq)
int total; int total;
int ret = 0; int ret = 0;
if (!is_modified(hreq->req, DB_ADMIN_DB_MODIFIED)) if (!is_modified(hreq, DB_ADMIN_DB_MODIFIED))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
track_id = hreq->uri_parsed->path_parts[3]; track_id = hreq->uri_parsed->path_parts[3];
@ -3543,7 +3543,7 @@ jsonapi_reply_library_playlists(struct httpd_request *hreq)
int total; int total;
int ret = 0; int ret = 0;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
reply = json_object_new_object(); reply = json_object_new_object();
@ -3591,7 +3591,7 @@ jsonapi_reply_library_playlist_get(struct httpd_request *hreq)
int ret = 0; int ret = 0;
bool notfound = false; bool notfound = false;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
ret = safe_atou32(hreq->uri_parsed->path_parts[3], &playlist_id); ret = safe_atou32(hreq->uri_parsed->path_parts[3], &playlist_id);
@ -3694,7 +3694,7 @@ jsonapi_reply_library_playlist_tracks(struct httpd_request *hreq)
int ret = 0; int ret = 0;
// Due to smart playlists possibly changing their tracks between rescans, disable caching in clients // Due to smart playlists possibly changing their tracks between rescans, disable caching in clients
httpd_response_not_cachable(hreq->req); httpd_response_not_cachable(hreq);
ret = safe_atoi32(hreq->uri_parsed->path_parts[3], &playlist_id); ret = safe_atoi32(hreq->uri_parsed->path_parts[3], &playlist_id);
if (ret < 0) if (ret < 0)
@ -3768,7 +3768,7 @@ jsonapi_reply_library_playlist_playlists(struct httpd_request *hreq)
int total; int total;
int ret = 0; int ret = 0;
if (!is_modified(hreq->req, DB_ADMIN_DB_MODIFIED)) if (!is_modified(hreq, DB_ADMIN_DB_MODIFIED))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
@ -3907,7 +3907,7 @@ jsonapi_reply_library_browse(struct httpd_request *hreq)
int total; int total;
int ret; int ret;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
browse_type = hreq->uri_parsed->path_parts[2]; browse_type = hreq->uri_parsed->path_parts[2];
@ -3988,7 +3988,7 @@ jsonapi_reply_library_browseitem(struct httpd_request *hreq)
json_object *reply; json_object *reply;
int ret; int ret;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
browse_type = hreq->uri_parsed->path_parts[2]; browse_type = hreq->uri_parsed->path_parts[2];
@ -4063,7 +4063,7 @@ jsonapi_reply_library_count(struct httpd_request *hreq)
json_object *jreply; json_object *jreply;
int ret; int ret;
if (!is_modified(hreq->req, DB_ADMIN_DB_UPDATE)) if (!is_modified(hreq, DB_ADMIN_DB_UPDATE))
return HTTP_NOTMODIFIED; return HTTP_NOTMODIFIED;
memset(&qp, 0, sizeof(struct query_params)); memset(&qp, 0, sizeof(struct query_params));
@ -4725,7 +4725,7 @@ jsonapi_request(struct httpd_request *hreq)
DPRINTF(E_DBG, L_WEB, "JSON api request: '%s'\n", hreq->uri); DPRINTF(E_DBG, L_WEB, "JSON api request: '%s'\n", hreq->uri);
if (!httpd_admin_check_auth(hreq->req)) if (!httpd_admin_check_auth(hreq))
{ {
return; return;
} }
@ -4733,7 +4733,7 @@ jsonapi_request(struct httpd_request *hreq)
if (!hreq->handler) if (!hreq->handler)
{ {
DPRINTF(E_LOG, L_WEB, "Unrecognized JSON API request: '%s'\n", hreq->uri); DPRINTF(E_LOG, L_WEB, "Unrecognized JSON API request: '%s'\n", hreq->uri);
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return; return;
} }
@ -4749,29 +4749,29 @@ jsonapi_request(struct httpd_request *hreq)
case HTTP_OK: /* 200 OK */ case HTTP_OK: /* 200 OK */
headers = evhttp_request_get_output_headers(hreq->req); headers = evhttp_request_get_output_headers(hreq->req);
evhttp_add_header(headers, "Content-Type", "application/json"); evhttp_add_header(headers, "Content-Type", "application/json");
httpd_send_reply(hreq->req, status_code, "OK", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, status_code, "OK", hreq->reply, HTTPD_SEND_NO_GZIP);
break; break;
case HTTP_NOCONTENT: /* 204 No Content */ case HTTP_NOCONTENT: /* 204 No Content */
httpd_send_reply(hreq->req, status_code, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, status_code, "No Content", hreq->reply, HTTPD_SEND_NO_GZIP);
break; break;
case HTTP_NOTMODIFIED: /* 304 Not Modified */ case HTTP_NOTMODIFIED: /* 304 Not Modified */
httpd_send_reply(hreq->req, HTTP_NOTMODIFIED, NULL, NULL, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_NOTMODIFIED, NULL, NULL, HTTPD_SEND_NO_GZIP);
break; break;
case HTTP_BADREQUEST: /* 400 Bad Request */ case HTTP_BADREQUEST: /* 400 Bad Request */
httpd_send_error(hreq->req, status_code, "Bad Request"); httpd_send_error(hreq, status_code, "Bad Request");
break; break;
case 403: case 403:
httpd_send_error(hreq->req, status_code, "Forbidden"); httpd_send_error(hreq, status_code, "Forbidden");
break; break;
case HTTP_NOTFOUND: /* 404 Not Found */ case HTTP_NOTFOUND: /* 404 Not Found */
httpd_send_error(hreq->req, status_code, "Not Found"); httpd_send_error(hreq, status_code, "Not Found");
break; break;
case HTTP_SERVUNAVAIL: /* 503 */ case HTTP_SERVUNAVAIL: /* 503 */
httpd_send_error(hreq->req, status_code, "Service Unavailable"); httpd_send_error(hreq, status_code, "Service Unavailable");
break; break;
case HTTP_INTERNAL: /* 500 Internal Server Error */ case HTTP_INTERNAL: /* 500 Internal Server Error */
default: default:
httpd_send_error(hreq->req, HTTP_INTERNAL, "Internal Server Error"); httpd_send_error(hreq, HTTP_INTERNAL, "Internal Server Error");
break; break;
} }

View File

@ -55,7 +55,7 @@ oauth_reply_spotify(struct httpd_request *hreq)
if (ret < 0) if (ret < 0)
{ {
DPRINTF(E_LOG, L_WEB, "Could not parse Spotify OAuth callback '%s': %s\n", hreq->uri_parsed->uri, errmsg); DPRINTF(E_LOG, L_WEB, "Could not parse Spotify OAuth callback '%s': %s\n", hreq->uri_parsed->uri, errmsg);
httpd_send_error(hreq->req, HTTP_INTERNAL, errmsg); httpd_send_error(hreq, HTTP_INTERNAL, errmsg);
return -1; return -1;
} }
@ -69,7 +69,7 @@ oauth_reply_spotify(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_WEB, "This version was built without support for Spotify\n"); DPRINTF(E_LOG, L_WEB, "This version was built without support for Spotify\n");
httpd_send_error(hreq->req, HTTP_NOTFOUND, "This version was built without support for Spotify"); httpd_send_error(hreq, HTTP_NOTFOUND, "This version was built without support for Spotify");
return -1; return -1;
} }
@ -99,7 +99,7 @@ oauth_request(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_WEB, "Unrecognized path in OAuth request: '%s'\n", hreq->uri); DPRINTF(E_LOG, L_WEB, "Unrecognized path in OAuth request: '%s'\n", hreq->uri);
httpd_send_error(hreq->req, HTTP_NOTFOUND, NULL); httpd_send_error(hreq, HTTP_NOTFOUND, NULL);
return; return;
} }

View File

@ -157,7 +157,7 @@ mxml_to_evbuf(mxml_node_t *tree)
} }
static void static void
rsp_send_error(struct evhttp_request *req, char *errmsg) rsp_send_error(struct httpd_request *hreq, char *errmsg)
{ {
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq *headers; struct evkeyvalq *headers;
@ -191,16 +191,16 @@ rsp_send_error(struct evhttp_request *req, char *errmsg)
if (!evbuf) if (!evbuf)
{ {
httpd_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); httpd_send_error(hreq, HTTP_SERVUNAVAIL, "Internal Server Error");
return; return;
} }
headers = evhttp_request_get_output_headers(req); headers = evhttp_request_get_output_headers(hreq->req);
evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8"); evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
evhttp_add_header(headers, "Connection", "close"); evhttp_add_header(headers, "Connection", "close");
httpd_send_reply(req, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP); httpd_send_reply(hreq, HTTP_OK, "OK", evbuf, HTTPD_SEND_NO_GZIP);
evbuffer_free(evbuf); evbuffer_free(evbuf);
} }
@ -220,7 +220,7 @@ query_params_set(struct query_params *qp, struct httpd_request *hreq)
ret = safe_atoi32(param, &qp->offset); ret = safe_atoi32(param, &qp->offset);
if (ret < 0) if (ret < 0)
{ {
rsp_send_error(hreq->req, "Invalid offset"); rsp_send_error(hreq, "Invalid offset");
return -1; return -1;
} }
} }
@ -232,7 +232,7 @@ query_params_set(struct query_params *qp, struct httpd_request *hreq)
ret = safe_atoi32(param, &qp->limit); ret = safe_atoi32(param, &qp->limit);
if (ret < 0) if (ret < 0)
{ {
rsp_send_error(hreq->req, "Invalid limit"); rsp_send_error(hreq, "Invalid limit");
return -1; return -1;
} }
} }
@ -277,7 +277,7 @@ query_params_set(struct query_params *qp, struct httpd_request *hreq)
} }
static void static void
rsp_send_reply(struct evhttp_request *req, mxml_node_t *reply) rsp_send_reply(struct httpd_request *hreq, mxml_node_t *reply)
{ {
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq *headers; struct evkeyvalq *headers;
@ -287,16 +287,16 @@ rsp_send_reply(struct evhttp_request *req, mxml_node_t *reply)
if (!evbuf) if (!evbuf)
{ {
rsp_send_error(req, "Could not finalize reply"); rsp_send_error(hreq, "Could not finalize reply");
return; return;
} }
headers = evhttp_request_get_output_headers(req); headers = evhttp_request_get_output_headers(hreq->req);
evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8"); evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
evhttp_add_header(headers, "Connection", "close"); evhttp_add_header(headers, "Connection", "close");
httpd_send_reply(req, HTTP_OK, "OK", evbuf, 0); httpd_send_reply(hreq, HTTP_OK, "OK", evbuf, 0);
evbuffer_free(evbuf); evbuffer_free(evbuf);
} }
@ -317,7 +317,7 @@ rsp_request_authorize(struct httpd_request *hreq)
DPRINTF(E_DBG, L_RSP, "Checking authentication for library\n"); DPRINTF(E_DBG, L_RSP, "Checking authentication for library\n");
// We don't care about the username // We don't care about the username
ret = httpd_basic_auth(hreq->req, NULL, passwd, cfg_getstr(cfg_getsec(cfg, "library"), "name")); ret = httpd_basic_auth(hreq, NULL, passwd, cfg_getstr(cfg_getsec(cfg, "library"), "name"));
if (ret != 0) if (ret != 0)
{ {
DPRINTF(E_LOG, L_RSP, "Unsuccessful library authorization attempt from '%s'\n", hreq->peer_address); DPRINTF(E_LOG, L_RSP, "Unsuccessful library authorization attempt from '%s'\n", hreq->peer_address);
@ -381,7 +381,7 @@ rsp_reply_info(struct httpd_request *hreq)
node = mxmlNewElement(info, "name"); node = mxmlNewElement(info, "name");
mxmlNewText(node, 0, library); mxmlNewText(node, 0, library);
rsp_send_reply(hreq->req, reply); rsp_send_reply(hreq, reply);
return 0; return 0;
} }
@ -410,7 +410,7 @@ rsp_reply_db(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_RSP, "Could not start query\n"); DPRINTF(E_LOG, L_RSP, "Could not start query\n");
rsp_send_error(hreq->req, "Could not start query"); rsp_send_error(hreq, "Could not start query");
return -1; return -1;
} }
@ -464,7 +464,7 @@ rsp_reply_db(struct httpd_request *hreq)
mxmlDelete(reply); mxmlDelete(reply);
db_query_end(&qp); db_query_end(&qp);
rsp_send_error(hreq->req, "Error fetching query results"); rsp_send_error(hreq, "Error fetching query results");
return -1; return -1;
} }
@ -478,7 +478,7 @@ rsp_reply_db(struct httpd_request *hreq)
db_query_end(&qp); db_query_end(&qp);
rsp_send_reply(hreq->req, reply); rsp_send_reply(hreq, reply);
return 0; return 0;
} }
@ -510,7 +510,7 @@ rsp_reply_playlist(struct httpd_request *hreq)
ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &qp.id); ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &qp.id);
if (ret < 0) if (ret < 0)
{ {
rsp_send_error(hreq->req, "Invalid playlist ID"); rsp_send_error(hreq, "Invalid playlist ID");
return -1; return -1;
} }
@ -546,7 +546,7 @@ rsp_reply_playlist(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_RSP, "Could not start query\n"); DPRINTF(E_LOG, L_RSP, "Could not start query\n");
rsp_send_error(hreq->req, "Could not start query"); rsp_send_error(hreq, "Could not start query");
if (qp.filter) if (qp.filter)
free(qp.filter); free(qp.filter);
@ -657,7 +657,7 @@ rsp_reply_playlist(struct httpd_request *hreq)
mxmlDelete(reply); mxmlDelete(reply);
db_query_end(&qp); db_query_end(&qp);
rsp_send_error(hreq->req, "Error fetching query results"); rsp_send_error(hreq, "Error fetching query results");
return -1; return -1;
} }
@ -671,7 +671,7 @@ rsp_reply_playlist(struct httpd_request *hreq)
db_query_end(&qp); db_query_end(&qp);
rsp_send_reply(hreq->req, reply); rsp_send_reply(hreq, reply);
return 0; return 0;
} }
@ -710,14 +710,14 @@ rsp_reply_browse(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_RSP, "Unsupported browse type '%s'\n", hreq->uri_parsed->path_parts[3]); DPRINTF(E_LOG, L_RSP, "Unsupported browse type '%s'\n", hreq->uri_parsed->path_parts[3]);
rsp_send_error(hreq->req, "Unsupported browse type"); rsp_send_error(hreq, "Unsupported browse type");
return -1; return -1;
} }
ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &qp.id); ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &qp.id);
if (ret < 0) if (ret < 0)
{ {
rsp_send_error(hreq->req, "Invalid playlist ID"); rsp_send_error(hreq, "Invalid playlist ID");
return -1; return -1;
} }
@ -730,7 +730,7 @@ rsp_reply_browse(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_RSP, "Could not start query\n"); DPRINTF(E_LOG, L_RSP, "Could not start query\n");
rsp_send_error(hreq->req, "Could not start query"); rsp_send_error(hreq, "Could not start query");
if (qp.filter) if (qp.filter)
free(qp.filter); free(qp.filter);
@ -783,7 +783,7 @@ rsp_reply_browse(struct httpd_request *hreq)
mxmlDelete(reply); mxmlDelete(reply);
db_query_end(&qp); db_query_end(&qp);
rsp_send_error(hreq->req, "Error fetching query results"); rsp_send_error(hreq, "Error fetching query results");
return -1; return -1;
} }
@ -797,7 +797,7 @@ rsp_reply_browse(struct httpd_request *hreq)
db_query_end(&qp); db_query_end(&qp);
rsp_send_reply(hreq->req, reply); rsp_send_reply(hreq, reply);
return 0; return 0;
} }
@ -811,11 +811,11 @@ rsp_stream(struct httpd_request *hreq)
ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &id); ret = safe_atoi32(hreq->uri_parsed->path_parts[2], &id);
if (ret < 0) if (ret < 0)
{ {
httpd_send_error(hreq->req, HTTP_BADREQUEST, "Bad Request"); httpd_send_error(hreq, HTTP_BADREQUEST, "Bad Request");
return -1; return -1;
} }
httpd_stream_file(hreq->req, id); httpd_stream_file(hreq, id);
return 0; return 0;
} }
@ -873,14 +873,14 @@ rsp_request(struct httpd_request *hreq)
{ {
DPRINTF(E_LOG, L_RSP, "Unrecognized path in RSP request: '%s'\n", hreq->uri); DPRINTF(E_LOG, L_RSP, "Unrecognized path in RSP request: '%s'\n", hreq->uri);
rsp_send_error(hreq->req, "Server error"); rsp_send_error(hreq, "Server error");
return; return;
} }
ret = rsp_request_authorize(hreq); ret = rsp_request_authorize(hreq);
if (ret < 0) if (ret < 0)
{ {
rsp_send_error(hreq->req, "Access denied"); rsp_send_error(hreq, "Access denied");
free(hreq); free(hreq);
return; return;
} }