X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/ffac51d73ab97c4c9c1e6c43b18d54d716000bf6..64c12487df48a8b90f663fefda6b82980fd3a059:/server/state.c diff --git a/server/state.c b/server/state.c index 16fc1a3..9a93dc9 100644 --- a/server/state.c +++ b/server/state.c @@ -1,82 +1,61 @@ /* * This file is part of DisOrder. - * Copyright (C) 2004, 2005 Richard Kettlewell + * Copyright (C) 2004, 2005, 2007-2009 Richard Kettlewell * - * This program is free software; you can redistribute it and/or modify + * 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 + * the Free Software Foundation, either version 3 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. - * + * 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 + * along with this program. If not, see . */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "event.h" -#include "play.h" -#include "rights.h" -#include "trackdb.h" -#include "state.h" -#include "configuration.h" -#include "log.h" -#include "queue.h" -#include "server-queue.h" -#include "server.h" -#include "printf.h" -#include "addr.h" +/** @file server/state.c + * @brief Global server state + */ +#include "disorder-server.h" static const char *current_unix; static int current_unix_fd; -static struct addrinfo *current_listen_addrinfo; -static int current_listen_fd; +/** @brief TCP listener definition */ +struct listener { + struct listener *next; + struct sockaddr *sa; + int fd; +}; + +/** @brief Current listeners */ +static struct listener *listeners; + +/** @brief Current audio API */ +const struct uaudio *api; void quit(ev_source *ev) { + info("shutting down..."); quitting(ev); trackdb_close(); trackdb_deinit(); - info("terminating"); + info("exiting"); exit(0); } +static struct sockaddr *copy_sockaddr(const struct addrinfo *addr) { + struct sockaddr *sa = xmalloc_noptr(addr->ai_addrlen); + memcpy(sa, addr->ai_addr, addr->ai_addrlen); + return sa; +} + static void reset_socket(ev_source *ev) { const char *new_unix; - struct addrinfo *res; + struct addrinfo *res, *r; + struct listener *l, **ll; struct sockaddr_un sun; - char *name; - - static const struct addrinfo pref = { - AI_PASSIVE, - PF_INET, - SOCK_STREAM, - IPPROTO_TCP, - 0, - 0, - 0, - 0 - }; /* unix first */ new_unix = config_get_file("socket"); @@ -107,28 +86,42 @@ static void reset_socket(ev_source *ev) { } /* get the new listen config */ - if(config->listen.n) - res = get_address(&config->listen, &pref, &name); + if(config->listen.af != -1) + res = netaddress_resolve(&config->listen, 1, IPPROTO_TCP); else res = 0; - if((res && !current_listen_addrinfo) - || (current_listen_addrinfo - && (!res - || addrinfocmp(res, current_listen_addrinfo)))) { - /* something has to change */ - if(current_listen_addrinfo) { - /* delete the old listener */ - server_stop(ev, current_listen_fd); - freeaddrinfo(current_listen_addrinfo); - current_listen_addrinfo = 0; + /* Close any current listeners that aren't required any more */ + ll = &listeners; + while((l = *ll)) { + for(r = res; r; r = r->ai_next) + if(!sockaddrcmp(r->ai_addr, l->sa)) + break; + if(!r) { + /* Didn't find a match, remove this one */ + server_stop(ev, l->fd); + *ll = l->next; + } else { + /* This address is still wanted */ + ll = &l->next; } - if(res) { - /* start the new listener */ - if((current_listen_fd = server_start(ev, res->ai_family, res->ai_addrlen, - res->ai_addr, name)) >= 0) { - current_listen_addrinfo = res; - res = 0; + } + + /* Open any new listeners that are required */ + for(r = res; r; r = r->ai_next) { + for(l = listeners; l; l = l->next) + if(!sockaddrcmp(r->ai_addr, l->sa)) + break; + if(!l) { + /* Didn't find a match, need a new listener */ + int fd = server_start(ev, r->ai_family, r->ai_addrlen, r->ai_addr, + format_sockaddr(r->ai_addr)); + if(fd >= 0) { + l = xmalloc(sizeof *l); + l->next = listeners; + l->sa = copy_sockaddr(r); + l->fd = fd; + listeners = l; } } } @@ -142,6 +135,11 @@ int reconfigure(ev_source *ev, int reload) { int ret = 0; D(("reconfigure(%d)", reload)); + if(api) { + if(api->close_mixer) + api->close_mixer(); + api = NULL; + } if(reload) { need_another_rescan = trackdb_rescan_cancel(); trackdb_close(); @@ -156,8 +154,15 @@ int reconfigure(ev_source *ev, int reload) { } else /* We only allow for upgrade at startup */ trackdb_open(TRACKDB_CAN_UPGRADE); + api = uaudio_find(config->api); + if(api->configure) + api->configure(); + if(api->open_mixer) + api->open_mixer(); if(need_another_rescan) - trackdb_rescan(ev, 1/*check*/); + trackdb_rescan(ev, 1/*check*/, 0, 0); + /* Arrange timeouts for schedule actions */ + schedule_init(ev); if(!ret) { queue_read(); recent_read();