diff --git a/src/inputs/librespot-c/src/channel.c b/src/inputs/librespot-c/src/channel.c index 7b3aef31..659fe61d 100644 --- a/src/inputs/librespot-c/src/channel.c +++ b/src/inputs/librespot-c/src/channel.c @@ -247,14 +247,14 @@ channel_pause(struct sp_channel *channel) channel->state = SP_CHANNEL_STATE_PAUSED; } -// After a disconnect we connect to another one and try to resume. To make that -// work some data elements need to be reset. +// After a disconnect we connect to another AP and try to resume. To make that +// work during playback some data elements need to be reset. void channel_retry(struct sp_channel *channel) { size_t pos; - if (!channel) + if (!channel || channel->state != SP_CHANNEL_STATE_PLAYING) return; channel->is_data_mode = false; diff --git a/src/inputs/librespot-c/src/connection.c b/src/inputs/librespot-c/src/connection.c index 4ad88a2e..776ec3af 100644 --- a/src/inputs/librespot-c/src/connection.c +++ b/src/inputs/librespot-c/src/connection.c @@ -314,6 +314,14 @@ tcp_connection_make(struct sp_connection *conn, struct sp_server *server, struct return ret; } +static int +must_resolve(struct sp_server *server) +{ + time_t now = time(NULL); + + return (server->last_resolved_ts == 0) || (server->last_failed_ts + SP_AP_AVOID_SECS > now); +} + void ap_disconnect(struct sp_connection *conn) { @@ -329,6 +337,9 @@ ap_connect(struct sp_connection *conn, struct sp_server *server, time_t *cooldow int ret; time_t now; + if (must_resolve(server)) + RETURN_ERROR(SP_ERR_NOCONNECTION, "Cannot connect to access point, it has recently failed"); + // Protection against flooding the access points with reconnection attempts // Note that cooldown_ts can't be part of the connection struct because // the struct is reset between connection attempts. @@ -549,7 +560,13 @@ prepare_tcp_handshake(struct sp_seq_request *request, struct sp_conn_callbacks * if (!session->conn.is_connected) { ret = ap_connect(&session->conn, &session->accesspoint, &session->cooldown_ts, cb, session); - if (ret < 0) + if (ret == SP_ERR_NOCONNECTION) + { + seq_next_set(session, request->seq_type); + session->request = seq_request_get(SP_SEQ_LOGIN, 0, session->use_legacy); + return SP_OK_WAIT; + } + else if (ret < 0) RETURN_ERROR(ret, sp_errmsg); } @@ -565,8 +582,8 @@ prepare_tcp(struct sp_seq_request *request, struct sp_conn_callbacks *cb, struct int ret; ret = prepare_tcp_handshake(request, cb, session); - if (ret < 0) - return ret; + if (ret != SP_OK_DONE) + return ret; // SP_OK_WAIT if the current AP failed and we need to try a new one if (!session->conn.handshake_completed) { @@ -582,8 +599,6 @@ prepare_tcp(struct sp_seq_request *request, struct sp_conn_callbacks *cb, struct /* --------------------------- Incoming messages ---------------------------- */ -#define SP_AP_RESOLVE_AVOID_SECS 3600 - static enum sp_error resolve_server_info_set(struct sp_server *server, const char *key, json_object *jresponse) { @@ -597,7 +612,7 @@ resolve_server_info_set(struct sp_server *server, const char *key, json_object * int n; int i; - has_failed = (server->last_failed_ts + SP_AP_RESOLVE_AVOID_SECS > time(NULL)); + has_failed = (server->last_failed_ts + SP_AP_AVOID_SECS > time(NULL)); if (! (json_object_object_get_ex(jresponse, key, &list) || json_object_get_type(list) == json_type_array)) RETURN_ERROR(SP_ERR_NOCONNECTION, "No address list in response from access point resolver"); @@ -1300,14 +1315,6 @@ msg_tcp_read_one(struct sp_tcp_message *tmsg, struct sp_connection *conn) /* --------------------------- Outgoing messages ---------------------------- */ -static int -must_resolve(struct sp_server *server) -{ - time_t now = time(NULL); - - return (server->last_resolved_ts == 0) || (server->last_failed_ts + SP_AP_RESOLVE_AVOID_SECS > now); -} - static int msg_make_ap_resolve(struct sp_message *msg, struct sp_session *session) { diff --git a/src/inputs/librespot-c/src/crypto.c b/src/inputs/librespot-c/src/crypto.c index 28cd974b..e1a2135f 100644 --- a/src/inputs/librespot-c/src/crypto.c +++ b/src/inputs/librespot-c/src/crypto.c @@ -355,6 +355,8 @@ crypto_aes_seek(struct crypto_aes_cipher *cipher, size_t seek, const char **errm size_t num_blocks; size_t offset; + assert(cipher->aes); + iv_len = gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES128); assert(iv_len == sizeof(iv)); diff --git a/src/inputs/librespot-c/src/librespot-c-internal.h b/src/inputs/librespot-c/src/librespot-c-internal.h index e05fdb2e..a481e06b 100644 --- a/src/inputs/librespot-c/src/librespot-c-internal.h +++ b/src/inputs/librespot-c/src/librespot-c-internal.h @@ -51,6 +51,9 @@ // we get the hint and won't try reconnecting again until after this cooldown #define SP_AP_COOLDOWN_SECS 30 +// How long after a connection failure we try to avoid an AP +#define SP_AP_AVOID_SECS 3600 + // If client hasn't requested anything in particular #define SP_BITRATE_DEFAULT SP_BITRATE_320