rtsp_server.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. #include "rtsp_server.h"
  2. #include <errno.h>
  3. #include <netinet/in.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/socket.h>
  7. #include <unistd.h>
  8. #include "audio_receiver.h"
  9. #include "audio_output.h"
  10. #include "esp_heap_caps.h"
  11. #include "esp_log.h"
  12. #include "freertos/FreeRTOS.h"
  13. #include "freertos/task.h"
  14. #include "rtsp_conn.h"
  15. #include "rtsp_crypto.h"
  16. #include "rtsp_handlers.h"
  17. #include "rtsp_message.h"
  18. #include "ntp_clock.h"
  19. #include "ptp_clock.h"
  20. #include "rtsp_events.h"
  21. #include "dacp_client.h"
  22. static const char *TAG = "rtsp_server";
  23. #define RTSP_PORT 7000
  24. #define RTSP_BUFFER_INITIAL 4096
  25. #define RTSP_BUFFER_LARGE ((size_t)256 * 1024)
  26. #define CLIENT_STACK_SIZE 8192
  27. #define SERVER_STACK_SIZE 4096
  28. static int server_socket = -1;
  29. static TaskHandle_t server_task_handle = NULL;
  30. static bool server_running = false;
  31. // RTSP tasks are restartable. Use dynamic TCB allocation so
  32. // reconnect/start-stop paths cannot reuse static task memory before FreeRTOS
  33. // idle finishes deletion.
  34. // Client slot for tracking connections
  35. typedef struct {
  36. rtsp_conn_t *conn;
  37. TaskHandle_t task;
  38. int socket;
  39. volatile bool should_stop;
  40. volatile bool is_old; // Marked as old client being killed
  41. } client_slot_t;
  42. static client_slot_t clients[2] = {0}; // Current and old
  43. static int current_slot = 0;
  44. // Flag set by the play/pause button to tell the grace period loop
  45. // to send a DACP resume command and keep waiting for reconnect.
  46. static volatile bool s_resume_requested = false;
  47. // Public API for volume control
  48. void airplay_set_volume(float volume_db) {
  49. client_slot_t *c = &clients[current_slot];
  50. if (c->conn && !c->is_old) {
  51. rtsp_conn_set_volume(c->conn, volume_db);
  52. }
  53. }
  54. int32_t airplay_get_volume_q15(void) {
  55. client_slot_t *c = &clients[current_slot];
  56. if (c->conn && !c->is_old) {
  57. return rtsp_conn_get_volume_q15(c->conn);
  58. }
  59. return 16384; // 50% volume for new clients
  60. }
  61. void rtsp_server_request_resume(void) {
  62. s_resume_requested = true;
  63. }
  64. // Helper to grow buffer
  65. static uint8_t *grow_buffer(uint8_t *old_buf, size_t old_size, size_t new_size,
  66. size_t data_len) {
  67. (void)old_size;
  68. uint8_t *new_buf =
  69. heap_caps_malloc(new_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  70. if (!new_buf) {
  71. new_buf = malloc(new_size);
  72. }
  73. if (!new_buf) {
  74. return NULL;
  75. }
  76. if (old_buf && data_len > 0) {
  77. memcpy(new_buf, old_buf, data_len);
  78. }
  79. free(old_buf);
  80. return new_buf;
  81. }
  82. // Process buffered RTSP requests
  83. static void process_rtsp_buffer(client_slot_t *slot, uint8_t *buffer,
  84. size_t *buf_len) {
  85. while (*buf_len > 0 && !slot->should_stop) {
  86. const uint8_t *header_end = rtsp_find_header_end(buffer, *buf_len);
  87. if (!header_end) {
  88. break;
  89. }
  90. size_t header_len = (size_t)(header_end - buffer) + 4;
  91. char *header_str = malloc(header_len + 1);
  92. if (!header_str) {
  93. *buf_len = 0;
  94. break;
  95. }
  96. memcpy(header_str, buffer, header_len);
  97. header_str[header_len] = '\0';
  98. int content_len = rtsp_parse_content_length(header_str);
  99. if (content_len < 0) {
  100. content_len = 0;
  101. }
  102. size_t total_len = header_len + (size_t)content_len;
  103. if (total_len > RTSP_BUFFER_LARGE || *buf_len < total_len) {
  104. free(header_str);
  105. if (total_len > RTSP_BUFFER_LARGE) {
  106. *buf_len = 0;
  107. }
  108. break;
  109. }
  110. // Null-terminate so strcasestr in parse_raw_header won't read past
  111. // the message boundary (buffer capacity > total_len).
  112. uint8_t saved = buffer[total_len];
  113. buffer[total_len] = '\0';
  114. rtsp_dispatch(slot->socket, slot->conn, buffer, total_len);
  115. buffer[total_len] = saved;
  116. free(header_str);
  117. if (*buf_len > total_len) {
  118. memmove(buffer, buffer + total_len, *buf_len - total_len);
  119. }
  120. *buf_len -= total_len;
  121. }
  122. }
  123. // Client task
  124. static void client_task(void *pvParameters) {
  125. int slot_idx = (int)(intptr_t)pvParameters;
  126. client_slot_t *slot = &clients[slot_idx];
  127. // Create connection state
  128. rtsp_conn_t *conn = rtsp_conn_create();
  129. if (!conn) {
  130. ESP_LOGE(TAG, "Failed to create connection state");
  131. close(slot->socket);
  132. slot->socket = -1;
  133. slot->task = NULL;
  134. vTaskDelete(NULL);
  135. return;
  136. }
  137. slot->conn = conn;
  138. // Get client IP address for timing requests
  139. struct sockaddr_in peer_addr;
  140. socklen_t peer_len = sizeof(peer_addr);
  141. if (getpeername(slot->socket, (struct sockaddr *)&peer_addr, &peer_len) ==
  142. 0) {
  143. conn->client_ip = peer_addr.sin_addr.s_addr;
  144. ESP_LOGI(TAG, "Client IP: %u.%u.%u.%u",
  145. (unsigned int)(conn->client_ip & 0xFF),
  146. (unsigned int)((conn->client_ip >> 8) & 0xFF),
  147. (unsigned int)((conn->client_ip >> 16) & 0xFF),
  148. (unsigned int)((conn->client_ip >> 24) & 0xFF));
  149. }
  150. // Allocate buffer
  151. size_t buf_capacity = RTSP_BUFFER_INITIAL;
  152. uint8_t *buffer = malloc(buf_capacity);
  153. if (!buffer) {
  154. ESP_LOGE(TAG, "Failed to allocate buffer");
  155. rtsp_conn_free(conn);
  156. slot->conn = NULL;
  157. close(slot->socket);
  158. slot->socket = -1;
  159. slot->task = NULL;
  160. vTaskDelete(NULL);
  161. return;
  162. }
  163. size_t buf_len = 0;
  164. // Socket timeout for stop signal responsiveness
  165. struct timeval tv = {.tv_sec = 1, .tv_usec = 0};
  166. setsockopt(slot->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  167. while (server_running && !slot->should_stop) {
  168. if (conn->encrypted_mode) {
  169. // Encrypted mode
  170. while (server_running && conn->encrypted_mode && !slot->should_stop) {
  171. if (buf_len >= buf_capacity - 1024) {
  172. size_t new_cap = buf_capacity < RTSP_BUFFER_LARGE ? RTSP_BUFFER_LARGE
  173. : buf_capacity * 2;
  174. if (new_cap > RTSP_BUFFER_LARGE) {
  175. goto cleanup;
  176. }
  177. uint8_t *new_buf =
  178. grow_buffer(buffer, buf_capacity, new_cap, buf_len);
  179. if (!new_buf) {
  180. goto cleanup;
  181. }
  182. buffer = new_buf;
  183. buf_capacity = new_cap;
  184. }
  185. int block_len = rtsp_crypto_read_block(
  186. slot->socket, conn, buffer + buf_len, buf_capacity - buf_len);
  187. if (block_len <= 0) {
  188. if (slot->should_stop || (errno != EAGAIN && errno != EWOULDBLOCK)) {
  189. goto cleanup;
  190. }
  191. continue;
  192. }
  193. buf_len += (size_t)block_len;
  194. process_rtsp_buffer(slot, buffer, &buf_len);
  195. }
  196. goto cleanup;
  197. }
  198. // Plain-text mode
  199. if (buf_len >= buf_capacity - 1024) {
  200. size_t new_cap = buf_capacity < RTSP_BUFFER_LARGE ? RTSP_BUFFER_LARGE
  201. : buf_capacity * 2;
  202. if (new_cap > RTSP_BUFFER_LARGE) {
  203. break;
  204. }
  205. uint8_t *new_buf = grow_buffer(buffer, buf_capacity, new_cap, buf_len);
  206. if (!new_buf) {
  207. break;
  208. }
  209. buffer = new_buf;
  210. buf_capacity = new_cap;
  211. }
  212. ssize_t recv_len =
  213. recv(slot->socket, buffer + buf_len, buf_capacity - buf_len, 0);
  214. if (recv_len <= 0) {
  215. if (recv_len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
  216. continue;
  217. }
  218. break;
  219. }
  220. buf_len += (size_t)recv_len;
  221. process_rtsp_buffer(slot, buffer, &buf_len);
  222. }
  223. cleanup:
  224. ESP_LOGI(TAG, "Client slot %d disconnected", slot_idx);
  225. free(buffer);
  226. close(slot->socket);
  227. slot->socket = -1;
  228. // Immediate: stop audio and NTP
  229. audio_receiver_stop();
  230. audio_output_flush();
  231. ntp_clock_stop();
  232. bool has_dacp_remote = conn && conn->protocol_version == 1 &&
  233. conn->dacp_id[0] != '\0' &&
  234. conn->active_remote[0] != '\0';
  235. // iOS v1 pause handling needs DACP to distinguish pause from disconnect.
  236. // Third-party RAOP clients often have no DACP remote; disconnect them
  237. // immediately instead of delaying slot cleanup with an iOS-only grace path.
  238. if (has_dacp_remote) {
  239. if (!slot->should_stop) {
  240. s_resume_requested = false;
  241. rtsp_events_emit(RTSP_EVENT_PAUSED, NULL);
  242. // Phase 1: let mDNS settle (3 s), but exit early on resume or reconnect
  243. for (int i = 0; i < 6 && !slot->should_stop; i++) {
  244. vTaskDelay(pdMS_TO_TICKS(500));
  245. if (s_resume_requested) {
  246. ESP_LOGI(TAG,
  247. "Resume requested during Phase 1 — skipping to Phase 2");
  248. break;
  249. }
  250. }
  251. // Phase 2: wait for reconnect as long as DACP service is advertised.
  252. // Re-probe every ~5 s. The phone unadvertises the service when the
  253. // user switches away, so disappearance = genuine disconnect.
  254. if (!slot->should_stop) {
  255. bool stay = dacp_probe_service() || s_resume_requested;
  256. if (s_resume_requested) {
  257. s_resume_requested = false;
  258. ESP_LOGI(TAG, "Resume requested via button — waiting for reconnect");
  259. stay = true;
  260. }
  261. if (stay) {
  262. ESP_LOGI(TAG, "DACP still advertised — waiting for reconnect");
  263. }
  264. while (stay && !slot->should_stop) {
  265. // Wait 5 s between probes (10 × 500 ms), checking flags each tick
  266. for (int i = 0; i < 10 && !slot->should_stop; i++) {
  267. vTaskDelay(pdMS_TO_TICKS(500));
  268. if (s_resume_requested) {
  269. s_resume_requested = false;
  270. ESP_LOGI(TAG,
  271. "Resume requested via button — extending grace period");
  272. }
  273. }
  274. if (slot->should_stop) {
  275. break;
  276. }
  277. // Re-probe: still advertised?
  278. stay = dacp_probe_service();
  279. if (stay) {
  280. ESP_LOGD(TAG, "DACP still advertised — continuing wait");
  281. } else {
  282. ESP_LOGI(TAG, "DACP service gone — genuine disconnect");
  283. }
  284. }
  285. }
  286. if (slot->is_old) {
  287. // New client connected during grace period — treat as reconnect
  288. ESP_LOGI(TAG, "Client reconnected during grace period");
  289. } else {
  290. ESP_LOGI(TAG, "Grace period expired — full disconnect");
  291. dacp_clear_session();
  292. rtsp_events_emit(RTSP_EVENT_DISCONNECTED, NULL);
  293. }
  294. } else {
  295. // Forcefully stopped (server shutdown or replaced by new client)
  296. dacp_clear_session();
  297. rtsp_events_emit(RTSP_EVENT_DISCONNECTED, NULL);
  298. }
  299. } else {
  300. // v2 / unknown — no grace period, clear immediately.
  301. dacp_clear_session();
  302. rtsp_events_emit(RTSP_EVENT_DISCONNECTED, NULL);
  303. }
  304. // When being replaced by a new client (is_old), skip global state changes —
  305. // the new session's SETUP already manages PTP and the event port task.
  306. if (!slot->is_old) {
  307. ptp_clock_init(); // Restart PTP (stopped during v1 SETUP to free sockets)
  308. rtsp_stop_event_port_task();
  309. } else if (rtsp_event_port_listen_socket() >= 0 &&
  310. rtsp_event_port_listen_socket() == conn->event_socket) {
  311. // Old task still using our socket — stop it before closing
  312. rtsp_stop_event_port_task();
  313. }
  314. if (conn->event_socket >= 0) {
  315. close(conn->event_socket);
  316. conn->event_socket = -1;
  317. }
  318. rtsp_conn_cleanup(conn);
  319. rtsp_conn_free(conn);
  320. slot->conn = NULL;
  321. slot->socket = -1;
  322. slot->task = NULL;
  323. slot->should_stop = false;
  324. slot->is_old = false;
  325. vTaskDelete(NULL);
  326. }
  327. // Signal old client to stop (non-blocking)
  328. static void signal_old_client_stop(int old_slot) {
  329. client_slot_t *old = &clients[old_slot];
  330. if (old->task == NULL) {
  331. return;
  332. }
  333. ESP_LOGI(TAG, "Signaling old client to stop");
  334. old->is_old = true;
  335. old->should_stop = true;
  336. // Shutdown socket to unblock recv
  337. if (old->socket >= 0) {
  338. shutdown(old->socket, SHUT_RDWR);
  339. }
  340. // Task will clean itself up
  341. }
  342. static void server_task(void *pvParameters) {
  343. (void)pvParameters;
  344. struct sockaddr_in server_addr, client_addr;
  345. socklen_t client_addr_len = sizeof(client_addr);
  346. // Initialize slots
  347. for (int i = 0; i < 2; i++) {
  348. clients[i].socket = -1;
  349. clients[i].conn = NULL;
  350. clients[i].task = NULL;
  351. clients[i].should_stop = false;
  352. clients[i].is_old = false;
  353. }
  354. server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  355. if (server_socket < 0) {
  356. ESP_LOGE(TAG, "Failed to create socket: %d", errno);
  357. server_task_handle = NULL;
  358. vTaskDelete(NULL);
  359. return;
  360. }
  361. int opt = 1;
  362. setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  363. memset(&server_addr, 0, sizeof(server_addr));
  364. server_addr.sin_family = AF_INET;
  365. server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  366. server_addr.sin_port = htons(RTSP_PORT);
  367. if (bind(server_socket, (struct sockaddr *)&server_addr,
  368. sizeof(server_addr)) < 0) {
  369. ESP_LOGE(TAG, "Failed to bind: %d", errno);
  370. close(server_socket);
  371. server_socket = -1;
  372. server_task_handle = NULL;
  373. vTaskDelete(NULL);
  374. return;
  375. }
  376. if (listen(server_socket, 5) < 0) {
  377. ESP_LOGE(TAG, "Failed to listen: %d", errno);
  378. close(server_socket);
  379. server_socket = -1;
  380. server_task_handle = NULL;
  381. vTaskDelete(NULL);
  382. return;
  383. }
  384. ESP_LOGI(TAG, "RTSP server listening on port %d", RTSP_PORT);
  385. server_running = true;
  386. while (server_running) {
  387. int new_socket = accept(server_socket, (struct sockaddr *)&client_addr,
  388. &client_addr_len);
  389. if (new_socket < 0) {
  390. if (server_running) {
  391. ESP_LOGE(TAG, "Failed to accept: %d", errno);
  392. }
  393. continue;
  394. }
  395. ESP_LOGI(TAG, "New client connected");
  396. rtsp_events_emit(RTSP_EVENT_CLIENT_CONNECTED, NULL);
  397. // Find slot for new client (alternate between 0 and 1)
  398. int new_slot = 1 - current_slot;
  399. // If new slot still has a running task, wait for it to fully exit.
  400. // With static TCBs we MUST NOT reuse until the old task is deleted.
  401. if (clients[new_slot].task != NULL) {
  402. clients[new_slot].should_stop = true;
  403. if (clients[new_slot].socket >= 0) {
  404. shutdown(clients[new_slot].socket, SHUT_RDWR);
  405. }
  406. int timeout = 30; // 3 seconds max
  407. while (clients[new_slot].task != NULL && timeout > 0) {
  408. vTaskDelay(pdMS_TO_TICKS(100));
  409. timeout--;
  410. }
  411. if (clients[new_slot].task != NULL) {
  412. ESP_LOGE(TAG, "Slot %d task did not exit in time", new_slot);
  413. close(new_socket);
  414. continue;
  415. }
  416. }
  417. // Signal old client to stop (in background)
  418. signal_old_client_stop(current_slot);
  419. // Setup new slot
  420. clients[new_slot].socket = new_socket;
  421. clients[new_slot].should_stop = false;
  422. clients[new_slot].is_old = false;
  423. // Start new client task immediately.
  424. clients[new_slot].task = NULL;
  425. BaseType_t task_ret =
  426. xTaskCreate(client_task, "rtsp_client", CLIENT_STACK_SIZE,
  427. (void *)(intptr_t)new_slot, 5, &clients[new_slot].task);
  428. if (task_ret != pdPASS || clients[new_slot].task == NULL) {
  429. ESP_LOGE(TAG, "Failed to create client task");
  430. close(new_socket);
  431. clients[new_slot].socket = -1;
  432. } else {
  433. current_slot = new_slot;
  434. }
  435. }
  436. // Stop all clients
  437. for (int i = 0; i < 2; i++) {
  438. if (clients[i].task != NULL) {
  439. clients[i].should_stop = true;
  440. if (clients[i].socket >= 0) {
  441. shutdown(clients[i].socket, SHUT_RDWR);
  442. }
  443. }
  444. }
  445. vTaskDelay(pdMS_TO_TICKS(500));
  446. if (server_socket >= 0) {
  447. close(server_socket);
  448. server_socket = -1;
  449. }
  450. server_task_handle = NULL;
  451. vTaskDelete(NULL);
  452. }
  453. static bool rtsp_server_wait_for_task_stopped(int timeout_ticks) {
  454. while (server_task_handle != NULL && timeout_ticks-- > 0) {
  455. vTaskDelay(pdMS_TO_TICKS(50));
  456. }
  457. return server_task_handle == NULL;
  458. }
  459. esp_err_t rtsp_server_start(void) {
  460. if (server_task_handle != NULL) {
  461. if (server_running) {
  462. return ESP_ERR_INVALID_STATE;
  463. }
  464. ESP_LOGW(TAG, "RTSP server task still stopping, waiting");
  465. if (!rtsp_server_wait_for_task_stopped(40)) {
  466. ESP_LOGE(TAG, "Previous RTSP server task did not stop");
  467. return ESP_ERR_INVALID_STATE;
  468. }
  469. }
  470. BaseType_t task_ret =
  471. xTaskCreate(server_task, "rtsp_server", SERVER_STACK_SIZE, NULL, 5,
  472. &server_task_handle);
  473. if (task_ret != pdPASS || server_task_handle == NULL) {
  474. return ESP_FAIL;
  475. }
  476. return ESP_OK;
  477. }
  478. void rtsp_server_stop(void) {
  479. server_running = false;
  480. if (server_socket >= 0) {
  481. shutdown(server_socket, SHUT_RDWR);
  482. close(server_socket);
  483. server_socket = -1;
  484. }
  485. if (server_task_handle != NULL) {
  486. if (!rtsp_server_wait_for_task_stopped(40)) {
  487. ESP_LOGW(TAG, "RTSP server task did not exit within timeout");
  488. }
  489. }
  490. }