diff --git a/lib/httpd.c b/lib/httpd.c index aae0f10..7140e2e 100644 --- a/lib/httpd.c +++ b/lib/httpd.c @@ -214,21 +214,6 @@ httpd_accept_connection(httpd_t *httpd, int server_fd, int is_ipv6) remote = netutils_get_address(&remote_saddr, &remote_len, &remote_zone_id); assert (local_zone_id == remote_zone_id); - /* remove existing connections to make way for new connections, if http->nohold is set: - * this will only occur if open_connections >= 2 and a connection with CONNECTION_TYPE_RAOP already exists */ - if (httpd->nohold && httpd->open_connections >= 2) { - if (httpd_count_connection_type(httpd, CONNECTION_TYPE_RAOP)) { - logger_log(httpd->logger, LOGGER_INFO, "Destroying current connections to allow connection by new client"); - for (int i = 0; imax_connections; i++) { - http_connection_t *connection = &httpd->connections[i]; - if (!connection->connected) { - continue; - } - httpd_remove_connection(httpd, connection); - } - } - } - ret = httpd_add_connection(httpd, fd, local, local_len, remote, remote_len, local_zone_id); if (ret == -1) { shutdown(fd, SHUT_RDWR); @@ -238,6 +223,22 @@ httpd_accept_connection(httpd_t *httpd, int server_fd, int is_ipv6) return 1; } +bool +httpd_nohold(httpd_t *httpd) { + return (httpd->nohold ? true: false); +} + +void +httpd_remove_known_connections(httpd_t *httpd) { + for (int i = 0; i < httpd->max_connections; i++) { + http_connection_t *connection = &httpd->connections[i]; + if (!connection->connected || connection->type == CONNECTION_TYPE_UNKNOWN) { + continue; + } + httpd_remove_connection(httpd, connection); + } +} + static THREAD_RETVAL httpd_thread(void *arg) { diff --git a/lib/httpd.h b/lib/httpd.h index 3ebde2f..f64d166 100644 --- a/lib/httpd.h +++ b/lib/httpd.h @@ -34,6 +34,8 @@ struct httpd_callbacks_s { void (*conn_destroy)(void *ptr); }; typedef struct httpd_callbacks_s httpd_callbacks_t; +bool httpd_nohold(httpd_t *httpd); +void httpd_remove_known_connections(httpd_t *httpd); int httpd_set_connection_type (httpd_t *http, void *user_data, connection_type_t type); int httpd_count_connection_type (httpd_t *http, connection_type_t type); diff --git a/lib/raop.c b/lib/raop.c index b3c7921..af14baf 100644 --- a/lib/raop.c +++ b/lib/raop.c @@ -174,10 +174,20 @@ conn_request(void *ptr, http_request_t *request, http_response_t **response) { if (httpd_count_connection_type(conn->raop->httpd, CONNECTION_TYPE_RAOP)) { char ipaddr[40]; utils_ipaddress_to_string(conn->remotelen, conn->remote, conn->zone_id, ipaddr, (int) (sizeof(ipaddr))); - logger_log(conn->raop->logger, LOGGER_WARNING, "rejecting new connection request from %s", ipaddr); - *response = http_response_create(); - http_response_init(*response, protocol, 409, "Conflict: Server is connected to another client"); - goto finish; + if (httpd_nohold(conn->raop->httpd)) { + logger_log(conn->raop->logger, LOGGER_INFO, "\"nohold\" feature: switch to new connection request from %s", ipaddr); + if (conn->raop->callbacks.video_reset) { + printf("**************************video_reset*************************\n"); + conn->raop->callbacks.video_reset(conn->raop->callbacks.cls); + } + httpd_remove_known_connections(conn->raop->httpd); + + } else { + logger_log(conn->raop->logger, LOGGER_WARNING, "rejecting new connection request from %s", ipaddr); + *response = http_response_create(); + http_response_init(*response, protocol, 409, "Conflict: Server is connected to another client"); + goto finish; + } } httpd_set_connection_type(conn->raop->httpd, ptr, CONNECTION_TYPE_RAOP); conn->connection_type = CONNECTION_TYPE_RAOP; diff --git a/lib/raop.h b/lib/raop.h index 63a8ef0..dc1f767 100644 --- a/lib/raop.h +++ b/lib/raop.h @@ -63,6 +63,7 @@ struct raop_callbacks_s { void (*register_client) (void *cls, const char *device_id, const char *pk_str, const char *name); bool (*check_register) (void *cls, const char *pk_str); void (*export_dacp) (void *cls, const char *active_remote, const char *dacp_id); + void (*video_reset) (void *cls); }; typedef struct raop_callbacks_s raop_callbacks_t; raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote, diff --git a/uxplay.cpp b/uxplay.cpp index fde2bd2..ddf7af9 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -1450,6 +1450,14 @@ static bool check_blocked_client(char *deviceid) { // Server callbacks +extern "C" void video_reset(void *cls) { + reset_loop = true; + remote_clock_offset = 0; + relaunch_video = true; +} + + + extern "C" void display_pin(void *cls, char *pin) { int margin = 10; int spacing = 3; @@ -1817,6 +1825,7 @@ static int start_raop_server (unsigned short display[5], unsigned short tcp[3], raop_cbs.register_client = register_client; raop_cbs.check_register = check_register; raop_cbs.export_dacp = export_dacp; + raop_cbs.video_reset = video_reset; raop = raop_init(&raop_cbs); if (raop == NULL) {