mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-27 15:45:56 -05:00
Revert "Fix 30 minute iTunes/DAAP time-out problem"
This reverts commit 7a021b2332
.
This commit is contained in:
parent
4eb416a3b3
commit
e9cdf88102
363
src/httpd_daap.c
363
src/httpd_daap.c
@ -59,17 +59,7 @@ extern struct event_base *evbase_httpd;
|
||||
|
||||
/* Session timeout in seconds */
|
||||
#define DAAP_SESSION_TIMEOUT 1800
|
||||
/* Amount of time update request can pending before we
|
||||
send a forced response to keep the channel alive */
|
||||
#define DAAP_UPDATE_TIMEOUT 1500
|
||||
/* How often we poll for database changes */
|
||||
#define DAAP_UPDATE_MONITOR_TIMEOUT 10
|
||||
|
||||
/* XXX Workaround before adding revision support in db.c;
|
||||
Client will not get dynamic updates. The state of the
|
||||
database at the time of connection is all the client
|
||||
gets. */
|
||||
#define db_revision_number() (2)
|
||||
|
||||
struct uri_map {
|
||||
regex_t preg;
|
||||
@ -77,27 +67,14 @@ struct uri_map {
|
||||
void (*handler)(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query);
|
||||
};
|
||||
|
||||
struct daap_update_request; /* Forward */
|
||||
struct daap_session {
|
||||
int id;
|
||||
|
||||
struct event timeout;
|
||||
/* A pending request, if active */
|
||||
struct daap_update_request *update_request;
|
||||
};
|
||||
|
||||
struct daap_update_request {
|
||||
|
||||
/* Currently pending request */
|
||||
struct evhttp_request *req;
|
||||
/* Time-out when an update *must* be sent */
|
||||
struct event timeout;
|
||||
/* Session that this request belongs to */
|
||||
struct daap_session *session;
|
||||
|
||||
/* Current revision number client is reporting */
|
||||
int revision_number;
|
||||
int session_id;
|
||||
|
||||
struct daap_update_request *next;
|
||||
};
|
||||
@ -122,16 +99,6 @@ static int next_session_id;
|
||||
|
||||
/* Update requests */
|
||||
static struct daap_update_request *update_requests;
|
||||
/* Global persistent timer that triggers periodically (10 secs).
|
||||
Checks the database to see if it has changed, and if so,
|
||||
pushes a response to all outstanding client update requests. */
|
||||
static struct event update_monitor_timer;
|
||||
|
||||
/* Forward declaration */
|
||||
static void
|
||||
daap_update_timeout_cb(int fd, short what, void *arg);
|
||||
static void
|
||||
update_request_free(struct daap_update_request *ur, int free_conn);
|
||||
|
||||
|
||||
/* Session handling */
|
||||
@ -150,9 +117,6 @@ daap_session_compare(const void *aa, const void *bb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* daap_session_free - called by avl_delete()
|
||||
*/
|
||||
static void
|
||||
daap_session_free(void *item)
|
||||
{
|
||||
@ -160,37 +124,16 @@ daap_session_free(void *item)
|
||||
|
||||
s = (struct daap_session *)item;
|
||||
|
||||
/* If there is a pending request, then close it out */
|
||||
if (s->update_request)
|
||||
update_request_free(s->update_request, 1 /* Close connection */);
|
||||
evtimer_del(&s->timeout);
|
||||
free(s);
|
||||
|
||||
/* XXX does not handle the case the connection being open but no
|
||||
pending request. The connection stays silently open but
|
||||
httpd_daapd refuses to acknowledge stale requests on the
|
||||
connection.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* daap_session_kill - recover when connection dies
|
||||
*/
|
||||
static void
|
||||
daap_session_kill(struct daap_session *s)
|
||||
{
|
||||
/* NOTE: automatically calls daap_session_free() */
|
||||
avl_delete(daap_sessions, s);
|
||||
}
|
||||
|
||||
/*
|
||||
* daap_session_timeout_cb - event callback when session inactivity timeout is triggered
|
||||
*
|
||||
* fd - dummy
|
||||
* what - time event fired
|
||||
* arg - session pointer
|
||||
*/
|
||||
static void
|
||||
daap_session_timeout_cb(int fd, short what, void *arg)
|
||||
{
|
||||
@ -206,10 +149,14 @@ daap_session_timeout_cb(int fd, short what, void *arg)
|
||||
static struct daap_session *
|
||||
daap_session_register(void)
|
||||
{
|
||||
#if 0
|
||||
struct timeval tv;
|
||||
#endif
|
||||
struct daap_session *s;
|
||||
avl_node_t *node;
|
||||
#if 0
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
s = (struct daap_session *)malloc(sizeof(struct daap_session));
|
||||
if (!s)
|
||||
@ -221,6 +168,7 @@ daap_session_register(void)
|
||||
memset(s, 0, sizeof(struct daap_session));
|
||||
|
||||
s->id = next_session_id;
|
||||
|
||||
next_session_id++;
|
||||
|
||||
evtimer_set(&s->timeout, daap_session_timeout_cb, s);
|
||||
@ -235,12 +183,14 @@ daap_session_register(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
evutil_timerclear(&tv);
|
||||
tv.tv_sec = DAAP_SESSION_TIMEOUT;
|
||||
|
||||
ret = evtimer_add(&s->timeout, &tv);
|
||||
if (ret < 0)
|
||||
DPRINTF(E_LOG, L_DAAP, "Could not add session timeout event for session %d\n", s->id);
|
||||
#endif /* 0 */
|
||||
|
||||
return s;
|
||||
}
|
||||
@ -249,7 +199,9 @@ struct daap_session *
|
||||
daap_session_find(struct evhttp_request *req, struct evkeyvalq *query, struct evbuffer *evbuf)
|
||||
{
|
||||
struct daap_session needle;
|
||||
#if 0
|
||||
struct timeval tv;
|
||||
#endif
|
||||
struct daap_session *s;
|
||||
avl_node_t *node;
|
||||
const char *param;
|
||||
@ -275,6 +227,7 @@ daap_session_find(struct evhttp_request *req, struct evkeyvalq *query, struct ev
|
||||
|
||||
s = (struct daap_session *)node->item;
|
||||
|
||||
#if 0
|
||||
event_del(&s->timeout);
|
||||
|
||||
evutil_timerclear(&tv);
|
||||
@ -283,6 +236,7 @@ daap_session_find(struct evhttp_request *req, struct evkeyvalq *query, struct ev
|
||||
ret = evtimer_add(&s->timeout, &tv);
|
||||
if (ret < 0)
|
||||
DPRINTF(E_LOG, L_DAAP, "Could not add session timeout event for session %d\n", s->id);
|
||||
#endif /* 0 */
|
||||
|
||||
return s;
|
||||
|
||||
@ -291,19 +245,21 @@ daap_session_find(struct evhttp_request *req, struct evkeyvalq *query, struct ev
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* update_request_free - delete update request and remove from list of pending updates
|
||||
*
|
||||
* ur - pointer to update request to remove
|
||||
* free_con - if set, then close the associated HTTP connection
|
||||
*
|
||||
*/
|
||||
|
||||
/* Update requests helpers */
|
||||
static void
|
||||
update_request_free(struct daap_update_request *ur, int free_conn)
|
||||
update_fail_cb(struct evhttp_connection *evcon, void *arg)
|
||||
{
|
||||
struct daap_update_request *ur;
|
||||
struct daap_update_request *p;
|
||||
|
||||
if (ur == 0) return;
|
||||
ur = (struct daap_update_request *)arg;
|
||||
|
||||
DPRINTF(E_DBG, L_DAAP, "Update request: client closed connection\n");
|
||||
|
||||
if (ur->req->evcon)
|
||||
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL);
|
||||
|
||||
if (ur == update_requests)
|
||||
update_requests = ur->next;
|
||||
else
|
||||
@ -320,34 +276,10 @@ update_request_free(struct daap_update_request *ur, int free_conn)
|
||||
p->next = ur->next;
|
||||
}
|
||||
|
||||
if (ur->session)
|
||||
ur->session->update_request = 0;
|
||||
|
||||
evtimer_del(&ur->timeout);
|
||||
if (ur->req && ur->req->evcon)
|
||||
{
|
||||
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL);
|
||||
if (free_conn) evhttp_connection_free(ur->req->evcon);
|
||||
}
|
||||
|
||||
free(ur);
|
||||
}
|
||||
|
||||
|
||||
/* Update requests helpers */
|
||||
static void
|
||||
update_fail_cb(struct evhttp_connection *evcon, void *arg)
|
||||
{
|
||||
struct daap_update_request *ur;
|
||||
|
||||
ur = (struct daap_update_request *)arg;
|
||||
|
||||
DPRINTF(E_DBG, L_DAAP, "Update request: client closed connection\n");
|
||||
|
||||
update_request_free(ur, 1 /* Close connection */);
|
||||
}
|
||||
|
||||
|
||||
/* DAAP sort headers helpers */
|
||||
static struct sort_ctx *
|
||||
daap_sort_context_new(void)
|
||||
@ -700,12 +632,12 @@ daap_reply_server_info(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
dmap_add_int(evbuf, "mpro", mpro); /* 12 */
|
||||
dmap_add_int(evbuf, "apro", apro); /* 12 */
|
||||
dmap_add_string(evbuf, "minm", name); /* 8 + strlen(name) */
|
||||
|
||||
#if 0
|
||||
/* XXX Strangely, if these are enabled, then the client does
|
||||
not poll for updates, even if msup == 1 */
|
||||
dmap_add_int(evbuf, "mstm", DAAP_SESSION_TIMEOUT); /* 12 */
|
||||
dmap_add_char(evbuf, "msal", 1); /* 9 */
|
||||
#endif
|
||||
|
||||
dmap_add_char(evbuf, "mslr", 1); /* 9 */
|
||||
dmap_add_char(evbuf, "msau", (passwd) ? 2 : 0); /* 9 */
|
||||
dmap_add_char(evbuf, "msex", 1); /* 9 */
|
||||
@ -716,6 +648,7 @@ daap_reply_server_info(struct evhttp_request *req, struct evbuffer *evbuf, char
|
||||
dmap_add_char(evbuf, "mspi", 1); /* 9 */
|
||||
dmap_add_int(evbuf, "msdc", 1); /* 12 */
|
||||
|
||||
/* Advertise updates support even though we don't send updates */
|
||||
dmap_add_char(evbuf, "msup", 1); /* 9 */
|
||||
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
@ -844,144 +777,13 @@ daap_reply_logout(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
||||
httpd_send_reply(req, 204, "Logout Successful", evbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send update response
|
||||
* s - current DAAP session
|
||||
* req - evhttp_request we are responding to
|
||||
* force - whether we are forcing a reply even if the database is unchanged
|
||||
* Return value:
|
||||
* -1: error
|
||||
* 0: did not send
|
||||
* 1: reply sent OK
|
||||
*/
|
||||
static int
|
||||
daap_update_response(struct daap_update_request *ur, int force)
|
||||
{
|
||||
int db_rev = db_revision_number();
|
||||
struct evbuffer *evbuf;
|
||||
|
||||
DPRINTF(E_DBG, L_DAAP, " (update, session-id=%d, old_rev=%d, current_rev=%d, force=%d)\n",
|
||||
ur->session_id, ur->revision_number, db_rev, force);
|
||||
if (!force && ur->revision_number == db_rev) return 0;
|
||||
|
||||
evbuf = evbuffer_new();
|
||||
if (evbuffer_expand(evbuf, 32) < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Could not expand evbuffer for DAAP update reply\n");
|
||||
|
||||
dmap_send_error(ur->req, "mupd", "Out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Send back current revision */
|
||||
dmap_add_container(evbuf, "mupd", 24);
|
||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||
dmap_add_int(evbuf, "musr", db_rev); /* 12 */
|
||||
|
||||
httpd_send_reply(ur->req, HTTP_OK, "OK", evbuf);
|
||||
evbuffer_free(evbuf);
|
||||
DPRINTF(E_DBG, L_DAAP, " (reply OK, session-id=%d, old_rev=%d, current_rev=%d)\n",
|
||||
ur->session_id, ur->revision_number, db_rev);
|
||||
|
||||
ur->revision_number = db_rev;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* daap_update_monitor_cb - global database monitor callback
|
||||
*
|
||||
* This function is called periodically, to monitor for database updates
|
||||
* that need to be sent out.
|
||||
*
|
||||
* fd - dummy
|
||||
* what - timer event
|
||||
* arg - dummy
|
||||
*/
|
||||
static void
|
||||
daap_update_monitor_cb(int fd, short what, void *arg)
|
||||
{
|
||||
struct timeval tv;
|
||||
int db_rev = db_revision_number();
|
||||
int ret;
|
||||
struct daap_update_request *ur = 0, *next = 0;
|
||||
|
||||
DPRINTF(E_DBG, L_DAAP, "Periodic update monitor event (db-rev=%d)\n", db_rev);
|
||||
ur = update_requests;
|
||||
while (ur)
|
||||
{
|
||||
next = ur->next; /* Cache a local copy of "next" */
|
||||
DPRINTF(E_DBG, L_DAAP,
|
||||
" (session-id=%d, request=%d, rev=%d)\n",
|
||||
ur->session_id, ur->req ? 1 : 0, ur->revision_number);
|
||||
if (! ur->req ) continue;
|
||||
|
||||
/* Send update to client now */
|
||||
ret = 0;
|
||||
if (db_rev != ur->revision_number)
|
||||
ret = daap_update_response(ur, 1);
|
||||
|
||||
/* If we sent a reply, remove this update request from the linked list */
|
||||
if (ret > 0) update_request_free(ur, 0);
|
||||
|
||||
ur = next; /* Advance to next request */
|
||||
}
|
||||
|
||||
/* Reset the timer for next monitor cycle */
|
||||
evutil_timerclear(&tv);
|
||||
tv.tv_sec = DAAP_UPDATE_MONITOR_TIMEOUT;
|
||||
evtimer_add(&update_monitor_timer, &tv);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* daap_update_timeout_cb - single update timeout callback
|
||||
*
|
||||
* Called when an individual session update has timed out
|
||||
*
|
||||
* fd - dummy
|
||||
* what - timer event
|
||||
* arg - pointer to update request
|
||||
*/
|
||||
static void
|
||||
daap_update_timeout_cb(int fd, short what, void *arg)
|
||||
{
|
||||
struct daap_update_request *ur;
|
||||
|
||||
ur = (struct daap_update_request *) arg;
|
||||
|
||||
if (ur && ur->req)
|
||||
{
|
||||
DPRINTF(E_DBG, L_DAAP, "Session update timeout (session-id=%d)\n", ur->session_id);
|
||||
daap_update_response(ur, 1);
|
||||
}
|
||||
|
||||
/* Remove update_request from list */
|
||||
update_request_free(ur, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* daap_reply_update - accept DAAP update request and respond or queue response
|
||||
*
|
||||
* Is passed an update request from HTTP server. If an update is available
|
||||
* already, then it is responded to immediately, otherwise the request is
|
||||
* queued with other update_requests for later response.
|
||||
*
|
||||
* req - HTTP request
|
||||
* evbuf - response buffer
|
||||
* uri - parsed URI
|
||||
* query - parsed query parameters
|
||||
*
|
||||
*/
|
||||
static void
|
||||
daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query)
|
||||
{
|
||||
struct daap_session *s;
|
||||
struct daap_update_request *ur, update;
|
||||
struct daap_update_request *ur;
|
||||
const char *param;
|
||||
int current_rev = 2;
|
||||
int reqd_rev;
|
||||
int ret;
|
||||
|
||||
@ -1007,64 +809,47 @@ daap_reply_update(struct evhttp_request *req, struct evbuffer *evbuf, char **uri
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG, L_DAAP, "DAAP update request (revision=%d)\n", reqd_rev);
|
||||
|
||||
memset(&update, 0, sizeof(update));
|
||||
update.revision_number = reqd_rev;
|
||||
update.session_id = s->id;
|
||||
update.req = req;
|
||||
|
||||
ret = daap_update_response(&update, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
if (ret == 0)
|
||||
if (reqd_rev == 1) /* Or revision is not valid */
|
||||
{
|
||||
struct timeval tv;
|
||||
/* We did not send a reply immediately because the database is unchanged,
|
||||
so queue this request for pushing later. */
|
||||
|
||||
DPRINTF(E_DBG, L_DAAP, "Queuing update request for session-id=%d\n", s->id);
|
||||
|
||||
/* Create daap_update_request structure */
|
||||
ur = (struct daap_update_request *)malloc(sizeof(struct daap_update_request));
|
||||
if (!ur)
|
||||
ret = evbuffer_expand(evbuf, 32);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Out of memory for update request\n");
|
||||
|
||||
DPRINTF(E_LOG, L_DAAP, "Could not expand evbuffer for DAAP update reply\n");
|
||||
|
||||
dmap_send_error(req, "mupd", "Out of memory");
|
||||
return;
|
||||
}
|
||||
*ur = update; /* Copy temporary request info into malloc'd structure */
|
||||
ur->req = req;
|
||||
ur->next = update_requests;
|
||||
update_requests = ur; /* Add to master list */
|
||||
|
||||
/* Link the session and the request */
|
||||
ur->session = s;
|
||||
s->update_request = ur;
|
||||
/* Send back current revision */
|
||||
dmap_add_container(evbuf, "mupd", 24);
|
||||
dmap_add_int(evbuf, "mstt", 200); /* 12 */
|
||||
dmap_add_int(evbuf, "musr", current_rev); /* 12 */
|
||||
|
||||
/* Set the time-out timer */
|
||||
evtimer_set(&ur->timeout, daap_update_timeout_cb, ur);
|
||||
event_base_set(evbase_httpd, &ur->timeout);
|
||||
evutil_timerclear(&tv);
|
||||
tv.tv_sec = DAAP_UPDATE_TIMEOUT;
|
||||
|
||||
ret = evtimer_add(&ur->timeout, &tv);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Could not add update timeout event for session %d\n", s->id);
|
||||
dmap_send_error(req, "mupd", "Timer setting failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the connection fails before we have an update to push out
|
||||
* to the client, we need to know.
|
||||
*/
|
||||
evhttp_connection_set_closecb(req->evcon, update_fail_cb, ur);
|
||||
httpd_send_reply(req, HTTP_OK, "OK", evbuf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
/* Else, just let the request hang until we have changes to push back */
|
||||
ur = (struct daap_update_request *)malloc(sizeof(struct daap_update_request));
|
||||
if (!ur)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DAAP, "Out of memory for update request\n");
|
||||
|
||||
dmap_send_error(req, "mupd", "Out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: we may need to keep reqd_rev in there too */
|
||||
ur->req = req;
|
||||
|
||||
ur->next = update_requests;
|
||||
update_requests = ur;
|
||||
|
||||
/* If the connection fails before we have an update to push out
|
||||
* to the client, we need to know.
|
||||
*/
|
||||
evhttp_connection_set_closecb(req->evcon, update_fail_cb, ur);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2641,25 +2426,10 @@ daap_init(void)
|
||||
char buf[64];
|
||||
int i;
|
||||
int ret;
|
||||
struct timeval tv;
|
||||
|
||||
next_session_id = 100; /* gotta start somewhere, right? */
|
||||
update_requests = NULL;
|
||||
|
||||
/* Add a monitor timer which periodically polls the database revision number */
|
||||
evtimer_set(&update_monitor_timer, daap_update_monitor_cb, 0);
|
||||
event_base_set(evbase_httpd, &update_monitor_timer);
|
||||
|
||||
evutil_timerclear(&tv);
|
||||
tv.tv_sec = DAAP_UPDATE_MONITOR_TIMEOUT;
|
||||
ret = evtimer_add(&update_monitor_timer, &tv);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_FATAL, L_DAAP, "Could not add update monitor timer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize handlers */
|
||||
for (i = 0; daap_handlers[i].handler; i++)
|
||||
{
|
||||
ret = regcomp(&daap_handlers[i].preg, daap_handlers[i].regexp, REG_EXTENDED | REG_NOSUB);
|
||||
@ -2672,7 +2442,6 @@ daap_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize session tree */
|
||||
daap_sessions = avl_alloc_tree(daap_session_compare, daap_session_free);
|
||||
if (!daap_sessions)
|
||||
{
|
||||
@ -2701,10 +2470,16 @@ daap_deinit(void)
|
||||
|
||||
avl_free_tree(daap_sessions);
|
||||
|
||||
/* Free any update requests, starting at the beginning */
|
||||
while ( (ur = update_requests) )
|
||||
for (ur = update_requests; update_requests; ur = update_requests)
|
||||
{
|
||||
update_request_free(ur, 1 /* Close connection */);
|
||||
/* Note: update_requests changes */
|
||||
update_requests = ur->next;
|
||||
|
||||
if (ur->req->evcon)
|
||||
{
|
||||
evhttp_connection_set_closecb(ur->req->evcon, NULL, NULL);
|
||||
evhttp_connection_free(ur->req->evcon);
|
||||
}
|
||||
|
||||
free(ur);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user