Migrate all evhttp to non-deprecated libevent2

- well except a troublemaker in httpd_daap.c (req->flags &= ~EVHTTP_PROXY_REQUEST)
This commit is contained in:
ejurgensen 2014-05-29 23:22:00 +02:00
parent 22d37f240b
commit 5b4ef31758
16 changed files with 234 additions and 99 deletions

View File

@ -34,7 +34,7 @@ endif
if COND_LIBEVENT2 if COND_LIBEVENT2
RTSP_SRC=evrtsp/rtsp.c evrtp/evrtsp.h evrtsp/rtsp-internal.h evrtsp/log.h RTSP_SRC=evrtsp/rtsp.c evrtp/evrtsp.h evrtsp/rtsp-internal.h evrtsp/log.h
else else
EVHTTP_SRC=evhttp/http.c evhttp/evhttp.h evhttp/http-internal.h evhttp/log.h EVHTTP_SRC=evhttp/http.c evhttp/evhttp.h evhttp/evhttp_compat.c evhttp/evhttp_compat.h evhttp/http-internal.h evhttp/log.h
RTSP_SRC=evrtsp/rtsp-libevent1.c evrtp/evrtsp.h evrtsp/rtsp-internal.h evrtsp/log.h RTSP_SRC=evrtsp/rtsp-libevent1.c evrtp/evrtsp.h evrtsp/rtsp-internal.h evrtsp/log.h
endif endif

View File

@ -4,7 +4,7 @@
#include <event.h> #include <event.h>
#ifdef HAVE_LIBEVENT2 #ifdef HAVE_LIBEVENT2
# include <evhttp.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp.h"
#endif #endif

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2009-2010 Julien BLACHE <jb@jblache.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include "evhttp_compat.h"
struct evhttp_connection *
evhttp_connection_base_new(struct event_base *base, void *ignore, const char *address, unsigned short port)
{
struct evhttp_connection *evcon;
if (!base || !address || !port)
return NULL;
evcon = evhttp_connection_new(address, port);
if (evcon)
evhttp_connection_set_base(evcon, base);
return evcon;
}
void
evhttp_request_set_header_cb(struct evhttp_request *req, int (*cb)(struct evhttp_request *, void *))
{
req->header_cb = cb;
}

View File

@ -0,0 +1,27 @@
#include "evhttp.h"
/* This file should only be included if using libevent 1
*
* The following adds libevent 2 evhttp functions to libevent 1, so we avoid
* the need of having many HAVE_LIBEVENT2 conditions inside the code
*/
#define evhttp_request_get_response_code(x) x->response_code
#define evhttp_request_get_input_headers(x) x->input_headers
#define evhttp_request_get_output_headers(x) x->output_headers
#define evhttp_request_get_input_buffer(x) x->input_buffer
#define evhttp_request_get_output_buffer(x) x->output_buffer
#define evhttp_request_get_host(x) x->remote_host
#define evhttp_request_get_uri evhttp_request_uri
struct evhttp_connection *
evhttp_connection_base_new(struct event_base *base, void *ignore, const char *address, unsigned short port);
void
evhttp_request_set_header_cb(struct evhttp_request *req, int (*cb)(struct evhttp_request *, void *));

View File

@ -44,7 +44,7 @@
#if defined HAVE_LIBEVENT2 #if defined HAVE_LIBEVENT2
# include <event2/http.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp_compat.h"
#endif #endif
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
@ -138,12 +138,7 @@ scan_icy_header_cb(struct evhttp_request *req, void *arg)
DPRINTF(E_DBG, L_SCAN, "ICY metadata request: Headers received\n"); DPRINTF(E_DBG, L_SCAN, "ICY metadata request: Headers received\n");
#ifdef HAVE_LIBEVENT2
headers = evhttp_request_get_input_headers(req); headers = evhttp_request_get_input_headers(req);
#else
headers = req->input_headers;
#endif
if ( (ptr = evhttp_find_header(headers, "icy-name")) ) if ( (ptr = evhttp_find_header(headers, "icy-name")) )
{ {
ctx->icy_name = strdup(ptr); ctx->icy_name = strdup(ptr);
@ -255,13 +250,9 @@ scan_metadata_icy(char *url, struct media_file_info *mfi)
goto no_icy; goto no_icy;
} }
#ifdef HAVE_LIBEVENT2
evhttp_request_set_header_cb(req, scan_icy_header_cb); evhttp_request_set_header_cb(req, scan_icy_header_cb);
headers = evhttp_request_get_output_headers(req); headers = evhttp_request_get_output_headers(req);
#else
req->header_cb = scan_icy_header_cb;
headers = req->output_headers;
#endif
snprintf(s, PATH_MAX, "%s:%d", ctx->hostname, ctx->port); snprintf(s, PATH_MAX, "%s:%d", ctx->hostname, ctx->port);
evhttp_add_header(headers, "Host", s); evhttp_add_header(headers, "Host", s);
evhttp_add_header(headers, "Icy-MetaData", "1"); evhttp_add_header(headers, "Icy-MetaData", "1");

View File

@ -38,7 +38,7 @@
#include <plist/plist.h> #include <plist/plist.h>
#ifdef HAVE_LIBEVENT2 #ifdef HAVE_LIBEVENT2
# include <evhttp.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp.h"
#endif #endif

View File

@ -53,7 +53,6 @@
#include "httpd_dacp.h" #include "httpd_dacp.h"
#include "transcode.h" #include "transcode.h"
/* /*
* HTTP client quirks by User-Agent, from mt-daapd * HTTP client quirks by User-Agent, from mt-daapd
* *
@ -127,8 +126,12 @@ static pthread_t tid_httpd;
static void static void
stream_end(struct stream_ctx *st, int failed) stream_end(struct stream_ctx *st, int failed)
{ {
if (st->req->evcon) struct evhttp_connection *evcon;
evhttp_connection_set_closecb(st->req->evcon, NULL, NULL);
evcon = evhttp_request_get_connection(st->req);
if (evcon)
evhttp_connection_set_closecb(evcon, NULL, NULL);
if (!failed) if (!failed)
evhttp_send_reply_end(st->req); evhttp_send_reply_end(st->req);
@ -312,6 +315,9 @@ httpd_stream_file(struct evhttp_request *req, int id)
void (*stream_cb)(int fd, short event, void *arg); void (*stream_cb)(int fd, short event, void *arg);
struct stat sb; struct stat sb;
struct timeval tv; struct timeval tv;
struct evhttp_connection *evcon;
struct evkeyvalq *input_headers;
struct evkeyvalq *output_headers;
const char *param; const char *param;
const char *param_end; const char *param_end;
char buf[64]; char buf[64];
@ -323,7 +329,10 @@ httpd_stream_file(struct evhttp_request *req, int id)
offset = 0; offset = 0;
end_offset = 0; end_offset = 0;
param = evhttp_find_header(req->input_headers, "Range");
input_headers = evhttp_request_get_input_headers(req);
param = evhttp_find_header(input_headers, "Range");
if (param) if (param)
{ {
DPRINTF(E_DBG, L_HTTPD, "Found Range header: %s\n", param); DPRINTF(E_DBG, L_HTTPD, "Found Range header: %s\n", param);
@ -385,7 +394,9 @@ httpd_stream_file(struct evhttp_request *req, int id)
memset(st, 0, sizeof(struct stream_ctx)); memset(st, 0, sizeof(struct stream_ctx));
st->fd = -1; st->fd = -1;
transcode = transcode_needed(req->input_headers, mfi->codectype); transcode = transcode_needed(input_headers, mfi->codectype);
output_headers = evhttp_request_get_output_headers(req);
if (transcode) if (transcode)
{ {
@ -403,8 +414,8 @@ httpd_stream_file(struct evhttp_request *req, int id)
goto out_free_st; goto out_free_st;
} }
if (!evhttp_find_header(req->output_headers, "Content-Type")) if (!evhttp_find_header(output_headers, "Content-Type"))
evhttp_add_header(req->output_headers, "Content-Type", "audio/wav"); evhttp_add_header(output_headers, "Content-Type", "audio/wav");
} }
else else
{ {
@ -468,21 +479,21 @@ httpd_stream_file(struct evhttp_request *req, int id)
DPRINTF(E_LOG, L_HTTPD, "Content-Type too large for buffer, dropping\n"); DPRINTF(E_LOG, L_HTTPD, "Content-Type too large for buffer, dropping\n");
else else
{ {
evhttp_remove_header(req->output_headers, "Content-Type"); evhttp_remove_header(output_headers, "Content-Type");
evhttp_add_header(req->output_headers, "Content-Type", buf); evhttp_add_header(output_headers, "Content-Type", buf);
} }
} }
/* If no Content-Type has been set and we're streaming audio, add a proper /* If no Content-Type has been set and we're streaming audio, add a proper
* Content-Type for the file we're streaming. Remember DAAP streams audio * Content-Type for the file we're streaming. Remember DAAP streams audio
* with application/x-dmap-tagged as the Content-Type (ugh!). * with application/x-dmap-tagged as the Content-Type (ugh!).
*/ */
else if (!evhttp_find_header(req->output_headers, "Content-Type") && mfi->type) else if (!evhttp_find_header(output_headers, "Content-Type") && mfi->type)
{ {
ret = snprintf(buf, sizeof(buf), "audio/%s", mfi->type); ret = snprintf(buf, sizeof(buf), "audio/%s", mfi->type);
if ((ret < 0) || (ret >= sizeof(buf))) if ((ret < 0) || (ret >= sizeof(buf)))
DPRINTF(E_LOG, L_HTTPD, "Content-Type too large for buffer, dropping\n"); DPRINTF(E_LOG, L_HTTPD, "Content-Type too large for buffer, dropping\n");
else else
evhttp_add_header(req->output_headers, "Content-Type", buf); evhttp_add_header(output_headers, "Content-Type", buf);
} }
} }
@ -491,7 +502,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(req->output_headers); evhttp_clear_headers(output_headers);
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_cleanup; goto out_cleanup;
@ -502,7 +513,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(req->output_headers); evhttp_clear_headers(output_headers);
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_cleanup; goto out_cleanup;
@ -516,7 +527,7 @@ 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(req->output_headers); evhttp_clear_headers(output_headers);
evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
goto out_cleanup; goto out_cleanup;
@ -539,7 +550,7 @@ httpd_stream_file(struct evhttp_request *req, int id)
if ((ret < 0) || (ret >= sizeof(buf))) if ((ret < 0) || (ret >= sizeof(buf)))
DPRINTF(E_LOG, L_HTTPD, "Content-Length too large for buffer, dropping\n"); DPRINTF(E_LOG, L_HTTPD, "Content-Length too large for buffer, dropping\n");
else else
evhttp_add_header(req->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(req, HTTP_OK, "OK");
@ -558,13 +569,13 @@ httpd_stream_file(struct evhttp_request *req, int id)
if ((ret < 0) || (ret >= sizeof(buf))) if ((ret < 0) || (ret >= sizeof(buf)))
DPRINTF(E_LOG, L_HTTPD, "Content-Range too large for buffer, dropping\n"); DPRINTF(E_LOG, L_HTTPD, "Content-Range too large for buffer, dropping\n");
else else
evhttp_add_header(req->output_headers, "Content-Range", buf); evhttp_add_header(output_headers, "Content-Range", buf);
ret = snprintf(buf, sizeof(buf), "%" PRIi64, ((end_offset) ? end_offset + 1 : (int64_t)st->size) - offset); ret = snprintf(buf, sizeof(buf), "%" PRIi64, ((end_offset) ? end_offset + 1 : (int64_t)st->size) - offset);
if ((ret < 0) || (ret >= sizeof(buf))) if ((ret < 0) || (ret >= sizeof(buf)))
DPRINTF(E_LOG, L_HTTPD, "Content-Length too large for buffer, dropping\n"); DPRINTF(E_LOG, L_HTTPD, "Content-Length too large for buffer, dropping\n");
else else
evhttp_add_header(req->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(req, 206, "Partial Content");
} }
@ -579,7 +590,9 @@ httpd_stream_file(struct evhttp_request *req, int id)
} }
#endif #endif
evhttp_connection_set_closecb(req->evcon, stream_fail_cb, st); evcon = evhttp_request_get_connection(req);
evhttp_connection_set_closecb(evcon, stream_fail_cb, st);
DPRINTF(E_INFO, L_HTTPD, "Kicking off streaming for %s\n", mfi->path); DPRINTF(E_INFO, L_HTTPD, "Kicking off streaming for %s\n", mfi->path);
@ -609,6 +622,7 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
unsigned char outbuf[128 * 1024]; unsigned char outbuf[128 * 1024];
z_stream strm; z_stream strm;
struct evbuffer *gzbuf; struct evbuffer *gzbuf;
struct evkeyvalq *headers;
const char *param; const char *param;
int flush; int flush;
int zret; int zret;
@ -621,7 +635,9 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
goto no_gzip; goto no_gzip;
} }
param = evhttp_find_header(req->input_headers, "Accept-Encoding"); headers = evhttp_request_get_input_headers(req);
param = evhttp_find_header(headers, "Accept-Encoding");
if (!param) if (!param)
{ {
DPRINTF(E_DBG, L_HTTPD, "Not gzipping; no Accept-Encoding header\n"); DPRINTF(E_DBG, L_HTTPD, "Not gzipping; no Accept-Encoding header\n");
@ -702,7 +718,9 @@ httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struc
deflateEnd(&strm); deflateEnd(&strm);
evhttp_add_header(req->output_headers, "Content-Encoding", "gzip"); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(headers, "Content-Encoding", "gzip");
evhttp_send_reply(req, code, reason, gzbuf); evhttp_send_reply(req, code, reason, gzbuf);
evbuffer_free(gzbuf); evbuffer_free(gzbuf);
@ -731,6 +749,7 @@ path_is_legal(char *path)
static void static void
redirect_to_index(struct evhttp_request *req, char *uri) redirect_to_index(struct evhttp_request *req, char *uri)
{ {
struct evkeyvalq *headers;
char buf[256]; char buf[256];
int slashed; int slashed;
int ret; int ret;
@ -746,7 +765,9 @@ redirect_to_index(struct evhttp_request *req, char *uri)
return; return;
} }
evhttp_add_header(req->output_headers, "Location", buf); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(headers, "Location", buf);
evhttp_send_reply(req, HTTP_MOVETEMP, "Moved", NULL); evhttp_send_reply(req, HTTP_MOVETEMP, "Moved", NULL);
} }
@ -754,12 +775,14 @@ redirect_to_index(struct evhttp_request *req, char *uri)
static void static void
serve_file(struct evhttp_request *req, char *uri) serve_file(struct evhttp_request *req, char *uri)
{ {
const char *host;
char *ext; char *ext;
char path[PATH_MAX]; char path[PATH_MAX];
char *deref; char *deref;
char *ctype; char *ctype;
char *passwd; char *passwd;
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq *headers;
struct stat sb; struct stat sb;
int fd; int fd;
int i; int i;
@ -779,8 +802,9 @@ serve_file(struct evhttp_request *req, char *uri)
} }
else else
{ {
if ((strcmp(req->remote_host, "::1") != 0) host = evhttp_request_get_host(req);
&& (strcmp(req->remote_host, "127.0.0.1") != 0)) if ((strcmp(host, "::1") != 0)
&& (strcmp(host, "127.0.0.1") != 0))
{ {
DPRINTF(E_LOG, L_HTTPD, "Remote web interface request denied; no password set\n"); DPRINTF(E_LOG, L_HTTPD, "Remote web interface request denied; no password set\n");
@ -910,8 +934,9 @@ serve_file(struct evhttp_request *req, char *uri)
} }
} }
evhttp_add_header(req->output_headers, "Content-Type", ctype); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(headers, "Content-Type", ctype);
evhttp_send_reply(req, HTTP_OK, "OK", evbuf); evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
evbuffer_free(evbuf); evbuffer_free(evbuf);
@ -925,7 +950,7 @@ httpd_gen_cb(struct evhttp_request *req, void *arg)
char *uri; char *uri;
char *ptr; char *ptr;
req_uri = evhttp_request_uri(req); req_uri = evhttp_request_get_uri(req);
if (!req_uri) if (!req_uri)
{ {
redirect_to_index(req, "/"); redirect_to_index(req, "/");
@ -1011,6 +1036,7 @@ exit_cb(int fd, short event, void *arg)
char * char *
httpd_fixup_uri(struct evhttp_request *req) httpd_fixup_uri(struct evhttp_request *req)
{ {
struct evkeyvalq *headers;
const char *ua; const char *ua;
const char *uri; const char *uri;
const char *u; const char *u;
@ -1019,7 +1045,7 @@ httpd_fixup_uri(struct evhttp_request *req)
char *f; char *f;
int len; int len;
uri = evhttp_request_uri(req); uri = evhttp_request_get_uri(req);
if (!uri) if (!uri)
return NULL; return NULL;
@ -1028,7 +1054,8 @@ httpd_fixup_uri(struct evhttp_request *req)
if (!q) if (!q)
return strdup(uri); return strdup(uri);
ua = evhttp_find_header(req->input_headers, "User-Agent"); headers = evhttp_request_get_input_headers(req);
ua = evhttp_find_header(headers, "User-Agent");
if (!ua) if (!ua)
return strdup(uri); return strdup(uri);
@ -1093,6 +1120,7 @@ int
httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *realm) httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *realm)
{ {
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq *headers;
char *header; char *header;
const char *auth; const char *auth;
char *authuser; char *authuser;
@ -1100,7 +1128,8 @@ httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *rea
int len; int len;
int ret; int ret;
auth = evhttp_find_header(req->input_headers, "Authorization"); headers = evhttp_request_get_input_headers(req);
auth = evhttp_find_header(headers, "Authorization");
if (!auth) if (!auth)
{ {
DPRINTF(E_DBG, L_HTTPD, "No Authorization header\n"); DPRINTF(E_DBG, L_HTTPD, "No Authorization header\n");
@ -1183,7 +1212,8 @@ httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *rea
return -1; return -1;
} }
evhttp_add_header(req->output_headers, "WWW-Authenticate", header); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(headers, "WWW-Authenticate", header);
evbuffer_add(evbuf, http_reply_401, strlen(http_reply_401)); evbuffer_add(evbuf, http_reply_401, strlen(http_reply_401));
evhttp_send_reply(req, 401, "Unauthorized", evbuf); evhttp_send_reply(req, 401, "Unauthorized", evbuf);

View File

@ -4,9 +4,9 @@
#include <event.h> #include <event.h>
#ifdef HAVE_LIBEVENT2 #ifdef HAVE_LIBEVENT2
# include <evhttp.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp_compat.h"
#endif #endif
void void

View File

@ -51,6 +51,10 @@
#include "daap_query.h" #include "daap_query.h"
#include "dmap_common.h" #include "dmap_common.h"
#ifdef HAVE_LIBEVENT2
# include <event2/http_struct.h>
#endif
/* httpd event base, from httpd.c */ /* httpd event base, from httpd.c */
extern struct event_base *evbase_httpd; extern struct event_base *evbase_httpd;
@ -313,6 +317,7 @@ static void
update_refresh_cb(int fd, short event, void *arg) update_refresh_cb(int fd, short event, void *arg)
{ {
struct daap_update_request *ur; struct daap_update_request *ur;
struct evhttp_connection *evcon;
struct evbuffer *evbuf; struct evbuffer *evbuf;
int ret; int ret;
@ -339,7 +344,8 @@ update_refresh_cb(int fd, short event, void *arg)
dmap_add_int(evbuf, "mstt", 200); /* 12 */ dmap_add_int(evbuf, "mstt", 200); /* 12 */
dmap_add_int(evbuf, "musr", current_rev); /* 12 */ dmap_add_int(evbuf, "musr", current_rev); /* 12 */
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL); evcon = evhttp_request_get_connection(ur->req);
evhttp_connection_set_closecb(evcon, NULL, NULL);
httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf); httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf);
@ -350,14 +356,16 @@ update_refresh_cb(int fd, short event, void *arg)
static void static void
update_fail_cb(struct evhttp_connection *evcon, void *arg) update_fail_cb(struct evhttp_connection *evcon, void *arg)
{ {
struct evhttp_connection *evc;
struct daap_update_request *ur; struct daap_update_request *ur;
ur = (struct daap_update_request *)arg; ur = (struct daap_update_request *)arg;
DPRINTF(E_DBG, L_DAAP, "Update request: client closed connection\n"); DPRINTF(E_DBG, L_DAAP, "Update request: client closed connection\n");
if (ur->req->evcon) evc = evhttp_request_get_connection(ur->req);
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL); if (evc)
evhttp_connection_set_closecb(evc, NULL, NULL);
update_remove(ur); update_remove(ur);
update_free(ur); update_free(ur);
@ -725,6 +733,7 @@ static void
daap_reply_server_info(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query) daap_reply_server_info(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
{ {
struct evbuffer *content; struct evbuffer *content;
struct evkeyvalq *headers;
cfg_t *lib; cfg_t *lib;
char *name; char *name;
char *passwd; char *passwd;
@ -748,7 +757,8 @@ daap_reply_server_info(struct evhttp_request *req, struct evbuffer *evbuf, char
mpro = 2 << 16 | 10; mpro = 2 << 16 | 10;
apro = 3 << 16 | 12; apro = 3 << 16 | 12;
clientver = evhttp_find_header(req->input_headers, "Client-DAAP-Version"); headers = evhttp_request_get_input_headers(req);
clientver = evhttp_find_header(headers, "Client-DAAP-Version");
if (clientver) if (clientver)
{ {
if (strcmp(clientver, "1.0") == 0) if (strcmp(clientver, "1.0") == 0)
@ -859,6 +869,7 @@ daap_reply_login(struct evhttp_request *req, struct evbuffer *evbuf, char **uri,
{ {
struct pairing_info pi; struct pairing_info pi;
struct daap_session *s; struct daap_session *s;
struct evkeyvalq *headers;
const char *ua; const char *ua;
const char *param; const char *param;
int request_session_id; int request_session_id;
@ -873,7 +884,8 @@ daap_reply_login(struct evhttp_request *req, struct evbuffer *evbuf, char **uri,
return; return;
} }
ua = evhttp_find_header(req->input_headers, "User-Agent"); headers = evhttp_request_get_input_headers(req);
ua = evhttp_find_header(headers, "User-Agent");
if (ua && (strncmp(ua, "Remote", strlen("Remote")) == 0)) if (ua && (strncmp(ua, "Remote", strlen("Remote")) == 0))
{ {
param = evhttp_find_header(query, "pairing-guid"); param = evhttp_find_header(query, "pairing-guid");
@ -949,6 +961,7 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
struct timeval tv; struct timeval tv;
struct daap_session *s; struct daap_session *s;
struct daap_update_request *ur; struct daap_update_request *ur;
struct evhttp_connection *evcon;
const char *param; const char *param;
int reqd_rev; int reqd_rev;
int ret; int ret;
@ -1035,7 +1048,9 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
/* If the connection fails before we have an update to push out /* If the connection fails before we have an update to push out
* to the client, we need to know. * to the client, we need to know.
*/ */
evhttp_connection_set_closecb(req->evcon, update_fail_cb, ur); evcon = evhttp_request_get_connection(req);
if (evcon)
evhttp_connection_set_closecb(evcon, update_fail_cb, ur);
} }
static void static void
@ -1107,6 +1122,7 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf,
struct db_media_file_info dbmfi; struct db_media_file_info dbmfi;
struct evbuffer *song; struct evbuffer *song;
struct evbuffer *songlist; struct evbuffer *songlist;
struct evkeyvalq *headers;
const struct dmap_field **meta; const struct dmap_field **meta;
struct sort_ctx *sctx; struct sort_ctx *sctx;
const char *param; const char *param;
@ -1244,7 +1260,8 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf,
{ {
nsongs++; nsongs++;
transcode = transcode_needed(req->input_headers, dbmfi.codectype); headers = evhttp_request_get_input_headers(req);
transcode = transcode_needed(headers, dbmfi.codectype);
ret = dmap_encode_file_metadata(songlist, song, &dbmfi, meta, nmeta, sort_headers, transcode); ret = dmap_encode_file_metadata(songlist, song, &dbmfi, meta, nmeta, sort_headers, transcode);
if (ret < 0) if (ret < 0)
@ -2121,6 +2138,7 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char *
{ {
char clen[32]; char clen[32];
struct daap_session *s; struct daap_session *s;
struct evkeyvalq *headers;
const char *param; const char *param;
char *ctype; char *ctype;
int id; int id;
@ -2191,10 +2209,11 @@ daap_reply_extra_data(struct evhttp_request *req, struct evbuffer *evbuf, char *
goto no_artwork; goto no_artwork;
} }
evhttp_remove_header(req->output_headers, "Content-Type"); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(req->output_headers, "Content-Type", ctype); evhttp_remove_header(headers, "Content-Type");
evhttp_add_header(headers, "Content-Type", ctype);
snprintf(clen, sizeof(clen), "%ld", (long)EVBUFFER_LENGTH(evbuf)); snprintf(clen, sizeof(clen), "%ld", (long)EVBUFFER_LENGTH(evbuf));
evhttp_add_header(req->output_headers, "Content-Length", clen); evhttp_add_header(headers, "Content-Length", clen);
/* No gzip compression for artwork */ /* No gzip compression for artwork */
evhttp_send_reply(req, HTTP_OK, "OK", evbuf); evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
@ -2435,6 +2454,7 @@ daap_request(struct evhttp_request *req)
char *uri_parts[7]; char *uri_parts[7];
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq query; struct evkeyvalq query;
struct evkeyvalq *headers;
const char *ua; const char *ua;
cfg_t *lib; cfg_t *lib;
char *libname; char *libname;
@ -2532,7 +2552,8 @@ daap_request(struct evhttp_request *req)
* valid session-id that Remote can only obtain if its pairing-guid is in * valid session-id that Remote can only obtain if its pairing-guid is in
* our database. So HTTP authentication is waived for Remote. * our database. So HTTP authentication is waived for Remote.
*/ */
ua = evhttp_find_header(req->input_headers, "User-Agent"); headers = evhttp_request_get_input_headers(req);
ua = evhttp_find_header(headers, "User-Agent");
if ((ua) && (strncmp(ua, "Remote", strlen("Remote")) == 0)) if ((ua) && (strncmp(ua, "Remote", strlen("Remote")) == 0))
passwd = NULL; passwd = NULL;
@ -2587,13 +2608,14 @@ daap_request(struct evhttp_request *req)
evhttp_parse_query(full_uri, &query); evhttp_parse_query(full_uri, &query);
evhttp_add_header(req->output_headers, "Accept-Ranges", "bytes"); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(req->output_headers, "DAAP-Server", "forked-daapd/" VERSION); evhttp_add_header(headers, "Accept-Ranges", "bytes");
evhttp_add_header(headers, "DAAP-Server", "forked-daapd/" VERSION);
/* Content-Type for all replies, even the actual audio streaming. Note that /* Content-Type for all replies, even the actual audio streaming. Note that
* video streaming will override this Content-Type with a more appropriate * video streaming will override this Content-Type with a more appropriate
* video/<type> Content-Type as expected by clients like Front Row. * video/<type> Content-Type as expected by clients like Front Row.
*/ */
evhttp_add_header(req->output_headers, "Content-Type", "application/x-dmap-tagged"); evhttp_add_header(headers, "Content-Type", "application/x-dmap-tagged");
daap_handlers[handler].handler(req, evbuf, uri_parts, &query); daap_handlers[handler].handler(req, evbuf, uri_parts, &query);
@ -2679,6 +2701,7 @@ void
daap_deinit(void) daap_deinit(void)
{ {
struct daap_update_request *ur; struct daap_update_request *ur;
struct evhttp_connection *evcon;
int i; int i;
for (i = 0; daap_handlers[i].handler; i++) for (i = 0; daap_handlers[i].handler; i++)
@ -2690,10 +2713,11 @@ daap_deinit(void)
{ {
update_requests = ur->next; update_requests = ur->next;
if (ur->req->evcon) evcon = evhttp_request_get_connection(ur->req);
if (evcon)
{ {
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL); evhttp_connection_set_closecb(evcon, NULL, NULL);
evhttp_connection_free(ur->req->evcon); evhttp_connection_free(evcon);
} }
update_free(ur); update_free(ur);

View File

@ -4,9 +4,9 @@
#include <event.h> #include <event.h>
#ifdef HAVE_LIBEVENT2 #ifdef HAVE_LIBEVENT2
# include <evhttp.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp_compat.h"
#endif #endif
int int

View File

@ -47,7 +47,6 @@
#include "db.h" #include "db.h"
#include "player.h" #include "player.h"
/* httpd event base, from httpd.c */ /* httpd event base, from httpd.c */
extern struct event_base *evbase_httpd; extern struct event_base *evbase_httpd;
@ -268,6 +267,7 @@ playstatusupdate_cb(int fd, short what, void *arg)
struct dacp_update_request *ur; struct dacp_update_request *ur;
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evbuffer *update; struct evbuffer *update;
struct evhttp_connection *evcon;
int ret; int ret;
#ifdef USE_EVENTFD #ifdef USE_EVENTFD
@ -313,7 +313,9 @@ playstatusupdate_cb(int fd, short what, void *arg)
{ {
update_requests = ur->next; update_requests = ur->next;
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL); evcon = evhttp_request_get_connection(ur->req);
if (evcon)
evhttp_connection_set_closecb(evcon, NULL, NULL);
evbuffer_add(evbuf, EVBUFFER_DATA(update), EVBUFFER_LENGTH(update)); evbuffer_add(evbuf, EVBUFFER_DATA(update), EVBUFFER_LENGTH(update));
@ -358,13 +360,15 @@ update_fail_cb(struct evhttp_connection *evcon, void *arg)
{ {
struct dacp_update_request *ur; struct dacp_update_request *ur;
struct dacp_update_request *p; struct dacp_update_request *p;
struct evhttp_connection *evc;
ur = (struct dacp_update_request *)arg; ur = (struct dacp_update_request *)arg;
DPRINTF(E_DBG, L_DACP, "Update request: client closed connection\n"); DPRINTF(E_DBG, L_DACP, "Update request: client closed connection\n");
if (ur->req->evcon) evc = evhttp_request_get_connection(ur->req);
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL); if (evc)
evhttp_connection_set_closecb(evc, NULL, NULL);
if (ur == update_requests) if (ur == update_requests)
update_requests = ur->next; update_requests = ur->next;
@ -1678,6 +1682,7 @@ dacp_reply_playstatusupdate(struct evhttp_request *req, struct evbuffer *evbuf,
{ {
struct daap_session *s; struct daap_session *s;
struct dacp_update_request *ur; struct dacp_update_request *ur;
struct evhttp_connection *evcon;
const char *param; const char *param;
int reqd_rev; int reqd_rev;
int ret; int ret;
@ -1733,7 +1738,9 @@ dacp_reply_playstatusupdate(struct evhttp_request *req, struct evbuffer *evbuf,
/* If the connection fails before we have an update to push out /* If the connection fails before we have an update to push out
* to the client, we need to know. * to the client, we need to know.
*/ */
evhttp_connection_set_closecb(req->evcon, update_fail_cb, ur); evcon = evhttp_request_get_connection(req);
if (evcon)
evhttp_connection_set_closecb(evcon, update_fail_cb, ur);
} }
static void static void
@ -1741,6 +1748,7 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf,
{ {
char clen[32]; char clen[32];
struct daap_session *s; struct daap_session *s;
struct evkeyvalq *headers;
const char *param; const char *param;
char *ctype; char *ctype;
uint32_t id; uint32_t id;
@ -1810,10 +1818,11 @@ dacp_reply_nowplayingartwork(struct evhttp_request *req, struct evbuffer *evbuf,
goto no_artwork; goto no_artwork;
} }
evhttp_remove_header(req->output_headers, "Content-Type"); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(req->output_headers, "Content-Type", ctype); evhttp_remove_header(headers, "Content-Type");
evhttp_add_header(headers, "Content-Type", ctype);
snprintf(clen, sizeof(clen), "%ld", (long)EVBUFFER_LENGTH(evbuf)); snprintf(clen, sizeof(clen), "%ld", (long)EVBUFFER_LENGTH(evbuf));
evhttp_add_header(req->output_headers, "Content-Length", clen); evhttp_add_header(headers, "Content-Length", clen);
/* No gzip compression for artwork */ /* No gzip compression for artwork */
evhttp_send_reply(req, HTTP_OK, "OK", evbuf); evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
@ -2216,6 +2225,7 @@ dacp_request(struct evhttp_request *req)
char *uri_parts[7]; char *uri_parts[7];
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq query; struct evkeyvalq query;
struct evkeyvalq *headers;
int handler; int handler;
int ret; int ret;
int i; int i;
@ -2307,9 +2317,10 @@ dacp_request(struct evhttp_request *req)
evhttp_parse_query(full_uri, &query); evhttp_parse_query(full_uri, &query);
evhttp_add_header(req->output_headers, "DAAP-Server", "forked-daapd/" VERSION); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(headers, "DAAP-Server", "forked-daapd/" VERSION);
/* Content-Type for all DACP replies; can be overriden as needed */ /* Content-Type for all DACP replies; can be overriden as needed */
evhttp_add_header(req->output_headers, "Content-Type", "application/x-dmap-tagged"); evhttp_add_header(headers, "Content-Type", "application/x-dmap-tagged");
dacp_handlers[handler].handler(req, evbuf, uri_parts, &query); dacp_handlers[handler].handler(req, evbuf, uri_parts, &query);
@ -2401,6 +2412,7 @@ void
dacp_deinit(void) dacp_deinit(void)
{ {
struct dacp_update_request *ur; struct dacp_update_request *ur;
struct evhttp_connection *evcon;
int i; int i;
player_set_update_handler(NULL); player_set_update_handler(NULL);
@ -2412,10 +2424,11 @@ dacp_deinit(void)
{ {
update_requests = ur->next; update_requests = ur->next;
if (ur->req->evcon) evcon = evhttp_request_get_connection(ur->req);
if (evcon)
{ {
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL); evhttp_connection_set_closecb(evcon, NULL, NULL);
evhttp_connection_free(ur->req->evcon); evhttp_connection_free(evcon);
} }
free(ur); free(ur);

View File

@ -4,9 +4,9 @@
#include <event.h> #include <event.h>
#ifdef HAVE_LIBEVENT2 #ifdef HAVE_LIBEVENT2
# include <evhttp.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp_compat.h"
#endif #endif
int int

View File

@ -42,7 +42,6 @@
#include "httpd_rsp.h" #include "httpd_rsp.h"
#include "rsp_query.h" #include "rsp_query.h"
#define RSP_VERSION "1.0" #define RSP_VERSION "1.0"
#define RSP_XML_ROOT "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?" #define RSP_XML_ROOT "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?"
@ -219,6 +218,7 @@ static void
rsp_send_error(struct evhttp_request *req, char *errmsg) rsp_send_error(struct evhttp_request *req, char *errmsg)
{ {
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq *headers;
mxml_node_t *reply; mxml_node_t *reply;
mxml_node_t *status; mxml_node_t *status;
mxml_node_t *node; mxml_node_t *node;
@ -254,8 +254,9 @@ rsp_send_error(struct evhttp_request *req, char *errmsg)
return; return;
} }
evhttp_add_header(req->output_headers, "Content-Type", "text/xml; charset=utf-8"); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(req->output_headers, "Connection", "close"); evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
evhttp_add_header(headers, "Connection", "close");
evhttp_send_reply(req, HTTP_OK, "OK", evbuf); evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
evbuffer_free(evbuf); evbuffer_free(evbuf);
@ -265,6 +266,7 @@ static void
rsp_send_reply(struct evhttp_request *req, mxml_node_t *reply) rsp_send_reply(struct evhttp_request *req, mxml_node_t *reply)
{ {
struct evbuffer *evbuf; struct evbuffer *evbuf;
struct evkeyvalq *headers;
evbuf = mxml_to_evbuf(reply); evbuf = mxml_to_evbuf(reply);
mxmlDelete(reply); mxmlDelete(reply);
@ -276,8 +278,9 @@ rsp_send_reply(struct evhttp_request *req, mxml_node_t *reply)
return; return;
} }
evhttp_add_header(req->output_headers, "Content-Type", "text/xml; charset=utf-8"); headers = evhttp_request_get_output_headers(req);
evhttp_add_header(req->output_headers, "Connection", "close"); evhttp_add_header(headers, "Content-Type", "text/xml; charset=utf-8");
evhttp_add_header(headers, "Connection", "close");
httpd_send_reply(req, HTTP_OK, "OK", evbuf); httpd_send_reply(req, HTTP_OK, "OK", evbuf);
evbuffer_free(evbuf); evbuffer_free(evbuf);
@ -434,6 +437,7 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que
{ {
struct query_params qp; struct query_params qp;
struct db_media_file_info dbmfi; struct db_media_file_info dbmfi;
struct evkeyvalq *headers;
const char *param; const char *param;
char **strval; char **strval;
mxml_node_t *reply; mxml_node_t *reply;
@ -526,7 +530,8 @@ rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *que
/* Items block (all items) */ /* Items block (all items) */
while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id)) while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
{ {
transcode = transcode_needed(req->input_headers, dbmfi.codectype); headers = evhttp_request_get_input_headers(req);
transcode = transcode_needed(headers, dbmfi.codectype);
/* Item block (one item) */ /* Item block (one item) */
item = mxmlNewElement(items, "item"); item = mxmlNewElement(items, "item");

View File

@ -4,9 +4,9 @@
#include <event.h> #include <event.h>
#ifdef HAVE_LIBEVENT2 #ifdef HAVE_LIBEVENT2
# include <evhttp.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp_compat.h"
#endif #endif
int int

View File

@ -48,9 +48,9 @@
#include <event.h> #include <event.h>
#ifdef HAVE_LIBEVENT2 #ifdef HAVE_LIBEVENT2
# include <evhttp.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp_compat.h"
#endif #endif
#include <gcrypt.h> #include <gcrypt.h>
@ -414,8 +414,10 @@ static void
pairing_request_cb(struct evhttp_request *req, void *arg) pairing_request_cb(struct evhttp_request *req, void *arg)
{ {
struct remote_info *ri; struct remote_info *ri;
struct evbuffer *input_buffer;
uint8_t *response; uint8_t *response;
char guid[17]; char guid[17];
int response_code;
int len; int len;
int i; int i;
int ret; int ret;
@ -429,21 +431,24 @@ pairing_request_cb(struct evhttp_request *req, void *arg)
goto cleanup; goto cleanup;
} }
if (req->response_code != HTTP_OK) response_code = evhttp_request_get_response_code(req);
if (response_code != HTTP_OK)
{ {
DPRINTF(E_LOG, L_REMOTE, "Pairing failed with Remote %s/%s, HTTP response code %d\n", ri->pi.remote_id, ri->pi.name, req->response_code); DPRINTF(E_LOG, L_REMOTE, "Pairing failed with Remote %s/%s, HTTP response code %d\n", ri->pi.remote_id, ri->pi.name, response_code);
goto cleanup; goto cleanup;
} }
if (EVBUFFER_LENGTH(req->input_buffer) < 8) input_buffer = evhttp_request_get_input_buffer(req);
if (EVBUFFER_LENGTH(input_buffer) < 8)
{ {
DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response too short\n", ri->pi.remote_id, ri->pi.name); DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response too short\n", ri->pi.remote_id, ri->pi.name);
goto cleanup; goto cleanup;
} }
response = EVBUFFER_DATA(req->input_buffer); response = EVBUFFER_DATA(input_buffer);
if ((response[0] != 'c') || (response[1] != 'm') || (response[2] != 'p') || (response[3] != 'a')) if ((response[0] != 'c') || (response[1] != 'm') || (response[2] != 'p') || (response[3] != 'a'))
{ {
@ -453,10 +458,10 @@ pairing_request_cb(struct evhttp_request *req, void *arg)
} }
len = (response[4] << 24) | (response[5] << 16) | (response[6] << 8) | (response[7]); len = (response[4] << 24) | (response[5] << 16) | (response[6] << 8) | (response[7]);
if (EVBUFFER_LENGTH(req->input_buffer) < 8 + len) if (EVBUFFER_LENGTH(input_buffer) < 8 + len)
{ {
DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response truncated (got %d expected %d)\n", DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response truncated (got %d expected %d)\n",
ri->pi.remote_id, ri->pi.name, (int)EVBUFFER_LENGTH(req->input_buffer), len + 8); ri->pi.remote_id, ri->pi.name, (int)EVBUFFER_LENGTH(input_buffer), len + 8);
goto cleanup; goto cleanup;
} }
@ -536,7 +541,7 @@ send_pairing_request(struct remote_info *ri, char *req_uri, int family)
return -1; return -1;
} }
evcon = evhttp_connection_new(address, port); evcon = evhttp_connection_base_new(evbase_main, NULL, address, port);
if (!evcon) if (!evcon)
{ {
DPRINTF(E_LOG, L_REMOTE, "Could not create connection for pairing with %s\n", ri->pi.name); DPRINTF(E_LOG, L_REMOTE, "Could not create connection for pairing with %s\n", ri->pi.name);
@ -544,8 +549,6 @@ send_pairing_request(struct remote_info *ri, char *req_uri, int family)
return -1; return -1;
} }
evhttp_connection_set_base(evcon, evbase_main);
req = evhttp_request_new(pairing_request_cb, ri); req = evhttp_request_new(pairing_request_cb, ri);
if (!req) if (!req)
{ {

View File

@ -4,7 +4,7 @@
#include <event.h> #include <event.h>
#ifdef HAVE_LIBEVENT2 #ifdef HAVE_LIBEVENT2
# include <evhttp.h> # include <event2/http.h>
#else #else
# include "evhttp/evhttp.h" # include "evhttp/evhttp.h"
#endif #endif