[spotify] Connection handling fixes

This commit is contained in:
ejurgensen 2025-01-25 16:02:53 +01:00
parent d02fc308ec
commit ec6403e1d0
4 changed files with 29 additions and 17 deletions

View File

@ -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;

View File

@ -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)
{

View File

@ -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));

View File

@ -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