AirPlay co-existence improvements, couple of display issues

This commit is contained in:
philippe44
2020-02-18 00:57:33 -08:00
parent fe5f9feeaf
commit 4e7ff0a37a
9 changed files with 203 additions and 142 deletions

View File

@@ -55,7 +55,7 @@ typedef struct raop_ctx_s {
short unsigned port; // RTSP port for AirPlay
int sock; // socket of the above
struct in_addr peer; // IP of the iDevice (airplay sender)
bool running;
bool running, abort;
#ifdef WIN32
pthread_t thread, search_thread;
#else
@@ -83,6 +83,7 @@ typedef struct raop_ctx_s {
TaskHandle_t thread, joiner;
StaticTask_t *xTaskBuffer;
StackType_t xStack[SEARCH_STACK_SIZE] __attribute__ ((aligned (4)));;
SemaphoreHandle_t destroy_mutex;
#endif
} active_remote;
void *owner;
@@ -93,6 +94,7 @@ extern log_level raop_loglevel;
static log_level *loglevel = &raop_loglevel;
static void* rtsp_thread(void *arg);
static void abort_rtsp(raop_ctx_t *ctx);
static bool handle_rtsp(raop_ctx_t *ctx, int sock);
static char* rsa_apply(unsigned char *input, int inlen, int *outlen, int mode);
@@ -198,6 +200,12 @@ struct raop_ctx_s *raop_create(struct in_addr host, char *name,
ESP_ERROR_CHECK( mdns_service_add(id, "_raop", "_tcp", ctx->port, txt, sizeof(txt) / sizeof(mdns_txt_item_t)) );
ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
ctx->thread = xTaskCreateStatic( (TaskFunction_t) rtsp_thread, "RTSP_thread", RTSP_STACK_SIZE, ctx, ESP_TASK_PRIO_MIN + 1, ctx->xStack, ctx->xTaskBuffer);
#endif
return ctx;
}
/*----------------------------------------------------------------------------*/
void raop_abort(struct raop_ctx_s *ctx) {
LOG_INFO("[%p]: aborting RTSP session at next select() wakeup", ctx);
@@ -270,7 +278,7 @@ if (!ctx) return;
NFREE(ctx->rtsp.aeskey);
NFREE(ctx->rtsp.aesiv);
NFREE(ctx->rtsp.fmtp);
NFREE(ctx->rtsp.fmtp);
free(ctx);
}
@@ -323,7 +331,7 @@ void raop_cmd(struct raop_ctx_s *ctx, raop_event_t event, void *param) {
break;
}
default:
break;
break;
}
// no command to send to remote or no remote found yet
@@ -354,6 +362,8 @@ void raop_cmd(struct raop_ctx_s *ctx, raop_event_t event, void *param) {
LOG_INFO("[%p]: sending airplay remote\n%s<== received ==>\n%s", ctx, buf, resp);
NFREE(method);
NFREE(buf);
kd_free(headers);
}
free(command);
@@ -373,6 +383,7 @@ static void *rtsp_thread(void *arg) {
int n;
bool res = false;
if (sock == -1) {
struct sockaddr_in peer;
socklen_t addrlen = sizeof(struct sockaddr_in);
@@ -383,12 +394,13 @@ static void *rtsp_thread(void *arg) {
if (sock != -1 && ctx->running) {
LOG_INFO("got RTSP connection %u", sock);
} else continue;
}
}
FD_ZERO(&rfds);
FD_SET(sock, &rfds);
n = select(sock + 1, &rfds, NULL, NULL, &timeout);
n = select(sock + 1, &rfds, NULL, NULL, &timeout);
if (!n && !ctx->abort) continue;
if (n > 0) res = handle_rtsp(ctx, sock);
@@ -460,27 +472,6 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
kd_add(resp, "Public", "ANNOUNCE, SETUP, RECORD, PAUSE, FLUSH, TEARDOWN, OPTIONS, GET_PARAMETER, SET_PARAMETER");
} else if (!strcmp(method, "ANNOUNCE")) {
char *padded, *p;
NFREE(ctx->rtsp.aeskey);
NFREE(ctx->rtsp.aesiv);
NFREE(ctx->rtsp.fmtp);
// LMS might has taken over the player, leaving us with a running RTP session (should not happen)
if (ctx->rtp) {
LOG_WARN("[%p]: closing unfinished RTP session", ctx);
rtp_end(ctx->rtp);
}
// same, should not happen unless we have missed a teardown ...
if (ctx->active_remote.running) {
ctx->active_remote.joiner = xTaskGetCurrentTaskHandle();
ctx->active_remote.running = false;
vTaskResume(ctx->active_remote.thread);
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
vTaskDelete(ctx->active_remote.thread);
} else if (!strcmp(method, "ANNOUNCE")) {
char *padded, *p;
@@ -522,6 +513,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
// on announce, search remote
if ((buf = kd_lookup(headers, "DACP-ID")) != NULL) strcpy(ctx->active_remote.DACPid, buf);
if ((buf = kd_lookup(headers, "Active-Remote")) != NULL) strcpy(ctx->active_remote.id, buf);
#ifdef WIN32
ctx->active_remote.handle = init_mDNS(false, ctx->host);
pthread_create(&ctx->search_thread, NULL, &search_remote, ctx);
@@ -600,11 +592,10 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
// need to make sure no search is on-going and reclaim pthread memory
#ifdef WIN32
if (ctx->active_remote.handle) close_mDNS(ctx->active_remote.handle);
pthread_join(ctx->search_thread, NULL);
#else
if (ctx->active_remote.handle) close_mDNS(ctx->active_remote.handle);
pthread_join(ctx->search_thread, NULL);
ctx->active_remote.running = false;
#else
ctx->active_remote.joiner = xTaskGetCurrentTaskHandle();
ctx->active_remote.running = false;
xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY);
@@ -681,6 +672,35 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
NFREE(body);
NFREE(buf);
kd_free(resp);
kd_free(headers);
return true;
}
/*----------------------------------------------------------------------------*/
void abort_rtsp(raop_ctx_t *ctx) {
// first stop RTP process
if (ctx->rtp) {
rtp_end(ctx->rtp);
ctx->rtp = NULL;
LOG_INFO("[%p]: RTP thread aborted", ctx);
}
if (ctx->active_remote.running) {
// need to make sure no search is on-going and reclaim task memory
ctx->active_remote.joiner = xTaskGetCurrentTaskHandle();
ctx->active_remote.running = false;
xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY);
vTaskDelete(ctx->active_remote.thread);
vSemaphoreDelete(ctx->active_remote.thread);
heap_caps_free(ctx->active_remote.xTaskBuffer);
memset(&ctx->active_remote, 0, sizeof(ctx->active_remote));
LOG_INFO("[%p]: Remote search thread aborted", ctx);
}
NFREE(ctx->rtsp.aeskey);
NFREE(ctx->rtsp.aesiv);
@@ -746,20 +766,10 @@ static void* search_remote(void *args) {
ctx->active_remote.host.s_addr = a->addr.u_addr.ip4.addr;
ctx->active_remote.port = r->port;
LOG_INFO("found remote %s %s:%hu", r->instance_name, inet_ntoa(ctx->active_remote.host), ctx->active_remote.port);
}
}
mdns_query_results_free(results);
}
/*
for some reason which is beyond me, if that tasks gives the semaphore
before the RTSP tasks waits for it, then freeRTOS crashes in queue
management caused by LWIP stack once the RTSP socket is closed. I have
no clue why, but so we'll suspend the tasks as soon as we're done with
search and wait for the resume then give the semaphore
}
}
// PS: I know this is not fully race-condition free
mdns_query_results_free(results);
}
// can't use xNotifyGive as it seems LWIP is using it as well