arduino-audio-tools
Loading...
Searching...
No Matches
RTSPSession.h
Go to the documentation of this file.
1/*
2 * Author: Phil Schatzmann
3 *
4 * Based on Micro-RTSP library:
5 * https://github.com/Tomp0801/Micro-RTSP-Audio
6 * https://github.com/geeksville/Micro-RTSP
7 *
8 */
9
10#pragma once
11
12#include <stdio.h>
13
14#include <ctime>
15
17#include "RTSPAudioStreamer.h"
18#include "RTSPPlatform.h"
19
21#define RTSP_BUFFER_SIZE 10000
23#define RTSP_PARAM_STRING_MAX 100
25#define MAX_HOSTNAME_LEN 256
27#define RTSP_RESPONSE_BUFFER_SIZE 2251
29#define RTSP_SDP_BUFFER_SIZE 1024
31#define RTSP_URL_BUFFER_SIZE 1024
33#define RTSP_SMALL_BUFFER_SIZE 256
34
35namespace audio_tools {
36
47
76template <typename Platform>
78 public:
97 RtspSession(typename Platform::TcpClientType& aClient,
101 m_RtspSessionID = random(65536); // create a session ID
102 LOGI("RTSP session created");
103 }
104
114 LOGI("RTSP session destructor");
115
116 // Ensure streaming is stopped and resources are released
117 if (m_streaming && m_Streamer) {
118 LOGI("Final cleanup: stopping streamer in destructor");
119 m_Streamer->stop();
120 m_Streamer->releaseUdpTransport();
121 m_streaming = false;
122 }
123
124 // Close the client socket (check connection using client method directly)
125 if (m_RtspClient && m_RtspClient->connected()) {
126 Platform::closeSocket(m_RtspClient);
127 }
128
129 LOGI("RTSP session cleanup completed");
130 }
131
149 LOGD("handleRequests");
150 // initlaize buffers and state if not already done
151 init();
152
153 if (!m_sessionOpen) {
154 delay(100); // give some time to close down
155 return false; // Already closed down
156 }
157
161 if (res > 0) {
162 // we filter away everything which seems not to be an RTSP command:
163 // O-ption, D-escribe, S-etup, P-lay, T-eardown
164 if ((mRecvBuf[0] == 'O') || (mRecvBuf[0] == 'D') ||
165 (mRecvBuf[0] == 'S') || (mRecvBuf[0] == 'P') ||
166 (mRecvBuf[0] == 'T')) {
168 if (!m_sessionOpen) {
169 // Session was aborted (e.g., rejected by callback); end quickly
170 return false;
171 }
172 // TODO this should go in the handling functions
173 if (C == RTSP_PLAY) {
174 m_streaming = true;
175 } else if (C == RTSP_PAUSE) {
176 m_streaming = false;
177 } else if (C == RTSP_TEARDOWN) {
178 m_sessionOpen = false; // Session ended by TEARDOWN
179
180 // Properly cleanup streaming on TEARDOWN command
181 if (m_streaming && m_Streamer) {
182 LOGI("Stopping streamer due to TEARDOWN");
183 m_Streamer->stop();
184 m_Streamer->releaseUdpTransport();
185 m_streaming = false;
186 }
187 }
188 }
189 return true;
190 } else if (res == 0) {
191 LOGW("client closed socket, exiting");
192 m_sessionOpen = false; // Session ended by client disconnect
193
194 // CRITICAL: Properly cleanup streaming when client disconnects
195 if (m_streaming && m_Streamer) {
196 LOGI("Stopping streamer due to client disconnect");
197 m_Streamer->stop();
198 m_Streamer->releaseUdpTransport();
199 m_streaming = false;
200 }
201
202 return false; // Return false to indicate session should end
203 } else {
204 // Timeout on read
205 // printf("RTSP read timeout\n");
206 return false;
207 }
208 }
209
210 bool isSessionOpen() { return m_sessionOpen; }
211
212 bool isStreaming() { return m_streaming; }
213
225 void setOnSessionPath(bool (*cb)(const char* path, void* ref), void* ref = nullptr) {
226 m_onSessionPath = cb;
227 m_onSessionPathRef = ref;
228 }
229
233 void closeSession() { m_sessionOpen = false; }
234
235
236
237 protected:
238 const char* STD_URL_PRE_SUFFIX = "trackID";
239
240 // global session state parameters
242 typename Platform::TcpClientType m_Client;
243 typename Platform::TcpClientType* m_RtspClient =
244 nullptr; // RTSP socket of session
245 int m_StreamID = -1; // number of simulated stream of that session
246 uint16_t m_ClientRTPPort; // client port for UDP based RTP transport
247 uint16_t m_ClientRTCPPort; // client port for UDP based RTCP transport
249 nullptr; // the UDP streamer of that session
250
251 // parameters of the last received RTSP request
252 RTSP_CMD_TYPES m_RtspCmdType; // command type (if any) of the current request
253 audio_tools::Vector<char> m_URLPreSuffix; // stream name pre suffix
255 audio_tools::Vector<char> m_CSeq; // RTSP command sequence number
256 audio_tools::Vector<char> m_URLHostPort; // host:port part of the URL
257 audio_tools::Vector<char> m_URLPath; // full RTSP path (starting with '/')
258 unsigned m_ContentLength; // SDP string size
260 0; // RTP receiver port on client (in host byte order!)
262 0; // RTCP receiver port on client (in host byte order!)
263 // Transport parsing (TCP interleaved)
264 bool m_TransportIsTcp = false;
268 m_Response; // Note: we assume single threaded, this large buf we
269 // keep off of the tiny stack
277 bool m_is_init = false;
278 bool m_streaming = false;
279 volatile bool m_sessionOpen = true;
280 bool m_pathNotified = false;
281 bool (*m_onSessionPath)(const char* path, void* ref) = nullptr;
282 void* m_onSessionPathRef = nullptr;
283
291 void init() {
292 if (m_is_init) return;
293 LOGD("init");
294
295 // Reset session state for clean initialization
296 m_streaming = false;
297 m_sessionOpen = true;
298
299 // initialize buffers if not already done
300 if (mRecvBuf.size() == 0) {
302 }
303 if (mCurRequest.size() == 0) {
305 }
306 if (m_URLPreSuffix.size() == 0) {
308 }
309 if (m_URLSuffix.size() == 0) {
311 }
312 if (m_CSeq.size() == 0) {
314 }
315 if (m_URLHostPort.size() == 0) {
317 }
318 if (m_URLPath.size() == 0) {
320 }
321 if (m_Response.size() == 0) {
323 }
324 if (m_SDPBuf.size() == 0) {
326 }
327 if (m_URLBuf.size() == 0) {
329 }
330 if (m_Buf1.size() == 0) {
332 }
333 if (m_Buf2.size() == 0) {
335 }
336 if (m_CmdName.size() == 0) {
338 }
339
343 memset(m_CSeq.data(), 0x00, m_CSeq.size());
345 if (m_URLPath.size() > 0) memset(m_URLPath.data(), 0x00, m_URLPath.size());
346 m_ContentLength = 0;
347 m_TransportIsTcp = false;
348 m_InterleavedRtp = -1;
350 m_is_init = true;
351 m_pathNotified = false;
352 }
353
362 unsigned aRequestSize) {
364 switch (m_RtspCmdType) {
365 case RTSP_OPTIONS: {
367 break;
368 }
369 case RTSP_DESCRIBE: {
371 break;
372 }
373 case RTSP_SETUP: {
375 break;
376 }
377 case RTSP_PLAY: {
379 break;
380 }
381 case RTSP_PAUSE: {
383 break;
384 }
385 case RTSP_TEARDOWN: {
387 break;
388 }
389 default: {
390 }
391 }
392 }
393 return m_RtspCmdType;
394 }
395
403 bool parseRtspRequest(char const* aRequest, unsigned aRequestSize) {
404 LOGI("aRequest: ------------------------\n%s\n-------------------------",
405 aRequest);
406
407 if (aRequestSize > mCurRequest.size()) return false;
408 const unsigned CurRequestSize = aRequestSize;
410
411 // 1) Ports and transport
414
415 // 2) Command + URL host/parts
416 unsigned idxAfterCmd = 0;
418 return false;
421 if (!m_sessionOpen) {
422 // Aborted by callback during URL parse; don't proceed further
423 return false;
424 }
425
426 // 3) CSeq and Content-Length
428 return false;
430
431 // 4) Client preference toggle (User-Agent / URL)
433
434 return true;
435 }
436
437 // ---- Parsing helpers ----
438 void parseClientPorts(char* req) {
439 char* ClientPortPtr = strstr(req, "client_port");
440 if (!ClientPortPtr) return;
441 char* lineEnd = strstr(ClientPortPtr, "\r\n");
442 if (!lineEnd) return;
443 char* CP = m_Response.data();
444 memset(CP, 0, m_Response.size());
445 char saved = lineEnd[0];
446 lineEnd[0] = '\0';
448 char* eq = strstr(CP, "=");
449 if (eq) {
450 ++eq;
451 char* dash = strstr(eq, "-");
452 if (dash) {
453 dash[0] = '\0';
456 }
457 }
458 lineEnd[0] = saved;
459 }
460
461 void parseTransportHeader(char* req) {
462 char* TransportPtr = strstr(req, "Transport:");
463 if (!TransportPtr) return;
464 char* lineEnd = strstr(TransportPtr, "\r\n");
465 if (!lineEnd) return;
466 char* CP = m_Response.data();
467 memset(CP, 0, m_Response.size());
468 char saved = lineEnd[0];
469 lineEnd[0] = '\0';
471 if (strstr(CP, "RTP/AVP/TCP") || strstr(CP, "/TCP")) m_TransportIsTcp = true;
472 char* inter = strstr(CP, "interleaved=");
473 if (inter) {
474 inter += strlen("interleaved=");
475 int a = -1, b = -1;
476 if (sscanf(inter, "%d-%d", &a, &b) == 2) {
479 } else if (sscanf(inter, "%d,%d", &a, &b) == 2) {
482 } else if (sscanf(inter, "%d", &a) == 1) {
484 m_InterleavedRtcp = a + 1;
485 }
486 }
487 lineEnd[0] = saved;
488 }
489
490 bool parseCommandName(char* req, unsigned reqSize, unsigned& outIdx) {
491 bool ok = false;
492 unsigned i;
493 for (i = 0; i < m_CmdName.size() - 1 && i < reqSize; ++i) {
494 char c = req[i];
495 if (c == ' ' || c == '\t') {
496 ok = true;
497 break;
498 }
499 m_CmdName[i] = c;
500 }
501 m_CmdName[i] = '\0';
502 if (!ok) {
503 LOGE("failed to parse RTSP");
504 return false;
505 }
506 LOGI("RTSP received %s", m_CmdName.data());
507 outIdx = i;
508 return true;
509 }
510
512 if (strstr(m_CmdName.data(), "OPTIONS"))
514 else if (strstr(m_CmdName.data(), "DESCRIBE"))
516 else if (strstr(m_CmdName.data(), "SETUP"))
518 else if (strstr(m_CmdName.data(), "PLAY"))
520 else if (strstr(m_CmdName.data(), "PAUSE"))
522 else if (strstr(m_CmdName.data(), "TEARDOWN"))
524 else
525 LOGE("Error: Unsupported Command received (%s)!", m_CmdName.data());
526 }
527
528 void parseUrlHostPortAndSuffix(char* req, unsigned reqSize, unsigned& i) {
529 unsigned j = i + 1;
530 while (j < reqSize && (req[j] == ' ' || req[j] == '\t')) ++j;
531 for (; (int)j < (int)(reqSize - 8); ++j) {
532 if ((req[j] == 'r' || req[j] == 'R') && (req[j + 1] == 't' || req[j + 1] == 'T') &&
533 (req[j + 2] == 's' || req[j + 2] == 'S') && (req[j + 3] == 'p' || req[j + 3] == 'P') &&
534 req[j + 4] == ':' && req[j + 5] == '/') {
535 j += 6;
536 if (req[j] == '/') {
537 ++j;
538 unsigned uidx = 0;
539 while (j < reqSize && req[j] != '/' && req[j] != ' ' && uidx < m_URLHostPort.size() - 1) {
540 m_URLHostPort[uidx++] = req[j++];
541 }
542 } else {
543 --j;
544 }
545 i = j;
546 break;
547 }
548 }
549 LOGD("m_URLHostPort: %s", m_URLHostPort.data());
550
551 // Extract full RTSP path starting at current index i up to next space
552 if (i < reqSize && req[i] == '/') {
553 unsigned p = 0;
554 unsigned k = i;
555 while (k < reqSize && req[k] != ' ' && p < m_URLPath.size() - 1) {
556 m_URLPath[p++] = req[k++];
557 }
558 m_URLPath[p] = '\0';
559 LOGD("m_URLPath: %s", m_URLPath.data());
562 m_pathNotified = true;
563 if (!ok) {
564 LOGW("Session rejected by onSessionPath callback");
565 m_sessionOpen = false;
566 // Early exit: abort further parsing of this request
567 }
568 }
569 }
570
571 bool ok = false;
572 for (unsigned k = i + 1; (int)k < (int)(reqSize - 5); ++k) {
573 if (req[k] == 'R' && req[k + 1] == 'T' && req[k + 2] == 'S' && req[k + 3] == 'P' && req[k + 4] == '/') {
574 while (--k >= i && req[k] == ' ') {}
575 unsigned k1 = k;
576 while (k1 > i && req[k1] != '=') --k1;
577 if (k - k1 + 1 <= m_URLSuffix.size()) {
578 unsigned n = 0, k2 = k1 + 1;
579 while (k2 <= k) m_URLSuffix[n++] = req[k2++];
580 m_URLSuffix[n] = '\0';
581 if (k1 - i <= m_URLPreSuffix.size()) ok = true;
582 n = 0;
583 k2 = i + 1;
584 while (k2 <= k1 - 1) m_URLPreSuffix[n++] = req[k2++];
585 m_URLPreSuffix[n] = '\0';
586 i = k + 7;
587 }
588 break;
589 }
590 }
591 LOGD("m_URLSuffix: %s", m_URLSuffix.data());
592 LOGD("m_URLPreSuffix: %s", m_URLPreSuffix.data());
593 LOGD("URL Suffix parse succeeded: %i", ok);
594 }
595
596 bool parseCSeq(char* req, unsigned reqSize, unsigned startIdx) {
597 bool ok = false;
598 for (unsigned j = startIdx; (int)j < (int)(reqSize - 5); ++j) {
599 if (req[j] == 'C' && req[j + 1] == 'S' && req[j + 2] == 'e' && req[j + 3] == 'q' && req[j + 4] == ':') {
600 j += 5;
601 while (j < reqSize && (req[j] == ' ' || req[j] == '\t')) ++j;
602 unsigned n;
603 for (n = 0; n < m_CSeq.size() - 1 && j < reqSize; ++n, ++j) {
604 char c = req[j];
605 if (c == '\r' || c == '\n') {
606 ok = true;
607 break;
608 }
609 m_CSeq[n] = c;
610 }
611 m_CSeq[n] = '\0';
612 break;
613 }
614 }
615 LOGD("Look for CSeq success: %i", ok);
616 return ok;
617 }
618
619 void parseContentLength(char* req, unsigned reqSize, unsigned startIdx) {
620 for (unsigned j = startIdx; (int)j < (int)(reqSize - 15); ++j) {
621 if (req[j] == 'C' && req[j + 1] == 'o' && req[j + 2] == 'n' && req[j + 3] == 't' &&
622 req[j + 4] == 'e' && req[j + 5] == 'n' && req[j + 6] == 't' && req[j + 7] == '-' &&
623 (req[j + 8] == 'L' || req[j + 8] == 'l') && req[j + 9] == 'e' && req[j + 10] == 'n' &&
624 req[j + 11] == 'g' && req[j + 12] == 't' && req[j + 13] == 'h' && req[j + 14] == ':') {
625 j += 15;
626 while (j < reqSize && (req[j] == ' ' || req[j] == '\t')) ++j;
627 unsigned num;
628 if (sscanf(&req[j], "%u", &num) == 1) m_ContentLength = num;
629 }
630 }
631 }
632
634 char* ua = strstr(req, "User-Agent:");
635 bool want_rfc2250 = false;
636 if (ua) {
637 if (strcasestr(ua, "ffmpeg") || strcasestr(ua, "ffplay") || strcasestr(ua, "libavformat") ||
638 strcasestr(ua, "Lavf")) {
639 want_rfc2250 = true;
640 }
641 if (strcasestr(ua, "vlc")) want_rfc2250 = false;
642 }
643 char* qm = strchr(req, '?');
644 if (qm) {
645 if (strstr(qm, "mpa_hdr=1")) want_rfc2250 = true;
646 if (strstr(qm, "mpa_hdr=0")) want_rfc2250 = false;
647 }
648 if (m_Streamer && m_Streamer->getAudioSource()) {
649 RTSPFormat& fmt = m_Streamer->getAudioSource()->getFormat();
651 }
652 }
653
659 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
660 "Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE\r\n\r\n",
661 m_CSeq.data());
662
664 }
665
670 // check whether we know a stream with the URL which is requested
671 m_StreamID = -1; // invalid URL
672 // find Stream ID
674 char* end;
675 m_StreamID = strtol(m_URLSuffix.data(), &end, 10);
676 if (*end != '\0') m_StreamID = -1;
677 }
678
679 // simulate DESCRIBE server response
680 char* ColonPtr;
682 ColonPtr = strstr(m_Buf1.data(), ":");
683 if (ColonPtr != nullptr) ColonPtr[0] = 0x00;
684
685 snprintf(
687 "v=0\r\n" // SDP Version
688 "o=- %d 0 IN IP4 %s\r\n"
689 "%s"
690 "a=control:%s=0",
691 rand() & 0xFF, m_Buf1.data(),
692 m_Streamer->getAudioSource()->getFormat().format(m_Buf2.data(), 256),
694
695 snprintf(m_URLBuf.data(), m_URLBuf.size(), "rtsp://%s",
697
699 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
700 "%s\r\n"
701 "Content-Base: %s/\r\n"
702 "Content-Type: application/sdp\r\n"
703 "Content-Length: %d\r\n\r\n"
704 "%s",
706 (int)strlen(m_SDPBuf.data()), m_SDPBuf.data());
707
708 // LOGI("handleRtspDescribe: %s", (const char*)m_Response.data());
709 Serial.println("------------------------------");
710 Serial.println((const char*)m_Response.data());
711 Serial.println("------------------------------");
713 }
714
719 // Build response depending on requested transport
720 if (m_TransportIsTcp) {
721 // Initialize TCP interleaved transport on same RTSP TCP socket
722 int ch0 = (m_InterleavedRtp >= 0) ? m_InterleavedRtp : 0;
723 int ch1 = (m_InterleavedRtcp >= 0) ? m_InterleavedRtcp : (ch0 + 1);
724 m_Streamer->initTcpInterleavedTransport(m_RtspClient, ch0, ch1);
725
726 // Reply with interleaved channels
728 "RTP/AVP/TCP;unicast;interleaved=%d-%d", ch0, ch1);
729 } else {
730 // init RTSP Session transport type (UDP) and ports for UDP transport
732 // UDP Transport response with client/server ports and ssrc
734 "RTP/AVP;unicast;client_port=%i-%i;server_port=%i-%i;ssrc=%08X",
736 m_Streamer->getRtpServerPort(), m_Streamer->getRtcpServerPort(),
737 (unsigned)m_Streamer->currentSsrc());
738 }
740 "RTSP/1.0 200 OK\r\n"
741 "CSeq: %s\r\n"
742 "%s\r\n"
743 "Session: %i\r\n"
744 "Transport: %s\r\n"
745 "\r\n",
747
748 Serial.println("------------------------------");
749 Serial.println((char*)m_Response.data());
750 Serial.println("------------------------------");
751
753 }
754
759 // Build RTP-Info to help clients (e.g., VLC) synchronize
760 // URL base
761 snprintf(m_URLBuf.data(), m_URLBuf.size(), "rtsp://%s/%s=0",
763
764 // Current seq/timestamp from streamer (values used for next packet)
765 uint16_t seq = m_Streamer ? m_Streamer->currentSeq() : 0;
766 uint32_t rtptime = m_Streamer ? m_Streamer->currentRtpTimestamp() : 0;
767
768 // PLAY response with Range, Session and RTP-Info
770 "RTSP/1.0 200 OK\r\n"
771 "CSeq: %s\r\n"
772 "Range: npt=0.000-\r\n"
773 "Session: %i\r\n"
774 "RTP-Info: url=%s;seq=%u;rtptime=%u\r\n\r\n",
775 m_CSeq.data(), m_RtspSessionID, m_URLBuf.data(), (unsigned)seq,
776 (unsigned)rtptime);
777
778 Serial.println("------------------------------");
779 Serial.println((char*)m_Response.data());
780 Serial.println("------------------------------");
781
783
784 m_Streamer->start();
785 }
786
792 if (m_streaming && m_Streamer) {
793 m_Streamer->stop();
794 }
796 "RTSP/1.0 200 OK\r\n"
797 "CSeq: %s\r\n"
798 "Session: %i\r\n\r\n",
801 }
802
807 m_Streamer->stop();
808
809 // simulate SETUP server response
811 "RTSP/1.0 200 OK\r\n"
812 "CSeq: %s\r\n\r\n",
813 m_CSeq.data());
814
816
817 m_sessionOpen = false;
818 }
819
824 int getStreamID() { return m_StreamID; }
825
834
837 Platform::getSocketPeerAddr(m_RtspClient, &clientIP, &clientPort);
838
839 LOGI("SETUP peer resolved: %s:%u (RTP client_port=%u)",
840 clientIP.toString().c_str(), (unsigned)clientPort,
841 (unsigned)m_RtpClientPort);
842
843 m_Streamer->initUdpTransport(clientIP, m_RtpClientPort);
844 }
845
846 typename Platform::TcpClientType*& getClient() { return m_RtspClient; }
847
849
858 inline int readSocket(typename Platform::TcpClientType* sock, char* buf,
859 size_t buflen, int timeoutmsec) {
860 return Platform::readSocket(sock, buf, buflen, timeoutmsec);
861 }
862
870 inline ssize_t sendSocket(typename Platform::TcpClientType* sock,
871 const void* buf, size_t len) {
872 return Platform::sendSocket(sock, buf, len);
873 }
874
879 char const* dateHeader() {
880 static char buf[200];
881 time_t tt = time(NULL);
882 strftime(buf, sizeof(buf), "Date: %a, %b %d %Y %H:%M:%S GMT", gmtime(&tt));
883 return buf;
884 }
885};
886
887} // namespace audio_tools
static HardwareSerial Serial
Definition Arduino.h:179
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define RTSP_SDP_BUFFER_SIZE
Size of SDP buffer (previously hardcoded 1024*2)
Definition RTSPSession.h:29
#define RTSP_PARAM_STRING_MAX
Size of RTSP parameter buffers.
Definition RTSPSession.h:23
#define RTSP_RESPONSE_BUFFER_SIZE
Size of response buffer (previously hardcoded 2251)
Definition RTSPSession.h:27
#define RTSP_SMALL_BUFFER_SIZE
Generic small temp buffer size (previously hardcoded 256)
Definition RTSPSession.h:33
#define RTSP_URL_BUFFER_SIZE
Size of URL buffer (previously hardcoded 1024)
Definition RTSPSession.h:31
#define MAX_HOSTNAME_LEN
Buffer size for RTSP host name.
Definition RTSPSession.h:25
#define RTSP_BUFFER_SIZE
Buffer size for incoming requests, and outgoing responses.
Definition RTSPSession.h:21
Arduino-compatible IPAddress class implemented in pure C++.
Definition IPAddress.h:28
RTSPAudioStreamerBase - Core RTP Audio Streaming Engine.
Definition RTSPAudioStreamer.h:50
Audio Format Definition - Base class for RTSP audio formats.
Definition RTSPFormat.h:48
virtual void setUseRfc2250Header(bool)
Optional: Configure RFC2250 header usage (default: no-op)
Definition RTSPFormat.h:95
RTSP Session Handler - Individual Client Protocol Management.
Definition RTSPSession.h:77
bool m_pathNotified
Definition RTSPSession.h:280
audio_tools::Vector< char > m_URLSuffix
Definition RTSPSession.h:254
void init()
Definition RTSPSession.h:291
int m_InterleavedRtcp
Definition RTSPSession.h:266
void parseTransportHeader(char *req)
Definition RTSPSession.h:461
audio_tools::Vector< char > m_URLBuf
Definition RTSPSession.h:271
bool parseCommandName(char *req, unsigned reqSize, unsigned &outIdx)
Definition RTSPSession.h:490
const char * STD_URL_PRE_SUFFIX
Definition RTSPSession.h:238
unsigned m_ContentLength
Definition RTSPSession.h:258
int readSocket(typename Platform::TcpClientType *sock, char *buf, size_t buflen, int timeoutmsec)
Inline helper to read from socket.
Definition RTSPSession.h:858
bool(* m_onSessionPath)(const char *path, void *ref)
Definition RTSPSession.h:281
void closeSession()
Mark session as closed (for server timeout/teardown)
Definition RTSPSession.h:233
void initTransport(u_short aRtpPort, u_short aRtcpPort)
Definition RTSPSession.h:831
uint16_t m_RtpClientPort
Definition RTSPSession.h:259
Platform::TcpClientType *& getClient()
Definition RTSPSession.h:846
ssize_t sendSocket(typename Platform::TcpClientType *sock, const void *buf, size_t len)
Inline helper to send data over socket.
Definition RTSPSession.h:870
bool m_streaming
Definition RTSPSession.h:278
void parseClientPorts(char *req)
Definition RTSPSession.h:438
audio_tools::Vector< char > m_URLHostPort
Definition RTSPSession.h:256
void handleRtspSetup()
Definition RTSPSession.h:718
void handleRtspDescribe()
Definition RTSPSession.h:669
bool parseRtspRequest(char const *aRequest, unsigned aRequestSize)
Definition RTSPSession.h:403
void determineCommandType()
Definition RTSPSession.h:511
int m_StreamID
Definition RTSPSession.h:245
uint16_t m_RtcpClientPort
Definition RTSPSession.h:261
RtspSession(typename Platform::TcpClientType &aClient, RTSPAudioStreamerBase< Platform > &aStreamer)
Construct RTSP session for a connected client.
Definition RTSPSession.h:97
int getStreamID()
Definition RTSPSession.h:824
void * m_onSessionPathRef
Definition RTSPSession.h:282
int m_RtspSessionID
Definition RTSPSession.h:241
audio_tools::Vector< char > mCurRequest
Definition RTSPSession.h:275
int m_InterleavedRtp
Definition RTSPSession.h:265
Platform::TcpClientType * m_RtspClient
Definition RTSPSession.h:243
void detectClientHeaderPreference(char *req)
Definition RTSPSession.h:633
uint16_t m_ClientRTPPort
Definition RTSPSession.h:246
audio_tools::Vector< char > m_URLPreSuffix
Definition RTSPSession.h:253
void handleRtspTeardown()
Definition RTSPSession.h:806
bool m_is_init
Definition RTSPSession.h:277
RTSP_CMD_TYPES handleRtspRequest(char const *aRequest, unsigned aRequestSize)
Definition RTSPSession.h:361
~RtspSession()
Destructor - cleanup session resources.
Definition RTSPSession.h:113
bool isSessionOpen()
Definition RTSPSession.h:210
void handleRtspPlay()
Definition RTSPSession.h:758
volatile bool m_sessionOpen
Definition RTSPSession.h:279
audio_tools::Vector< char > m_Buf1
Definition RTSPSession.h:272
void handleRtspOption()
Definition RTSPSession.h:657
uint16_t m_ClientRTCPPort
Definition RTSPSession.h:247
RTSPAudioStreamerBase< Platform > * m_Streamer
Definition RTSPSession.h:248
bool handleRequests(uint32_t readTimeoutMs)
Process incoming RTSP requests from the client.
Definition RTSPSession.h:148
audio_tools::Vector< char > m_Buf2
Definition RTSPSession.h:273
char const * dateHeader()
Definition RTSPSession.h:879
void parseContentLength(char *req, unsigned reqSize, unsigned startIdx)
Definition RTSPSession.h:619
uint16_t getRtpClientPort()
Definition RTSPSession.h:848
bool parseCSeq(char *req, unsigned reqSize, unsigned startIdx)
Definition RTSPSession.h:596
audio_tools::Vector< char > mRecvBuf
Definition RTSPSession.h:274
audio_tools::Vector< char > m_CmdName
Definition RTSPSession.h:276
Platform::TcpClientType m_Client
Definition RTSPSession.h:242
void setOnSessionPath(bool(*cb)(const char *path, void *ref), void *ref=nullptr)
Set a callback to receive the RTSP URL path that opened the session. The callback is invoked once,...
Definition RTSPSession.h:225
audio_tools::Vector< char > m_Response
Definition RTSPSession.h:268
audio_tools::Vector< char > m_URLPath
Definition RTSPSession.h:257
bool isStreaming()
Definition RTSPSession.h:212
void handleRtspPause()
Definition RTSPSession.h:791
RTSP_CMD_TYPES m_RtspCmdType
Definition RTSPSession.h:252
audio_tools::Vector< char > m_CSeq
Definition RTSPSession.h:255
void parseUrlHostPortAndSuffix(char *req, unsigned reqSize, unsigned &i)
Definition RTSPSession.h:528
bool m_TransportIsTcp
Definition RTSPSession.h:264
audio_tools::Vector< char > m_SDPBuf
Definition RTSPSession.h:270
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
T * data()
Definition Vector.h:316
int size()
Definition Vector.h:178
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
void delay(uint32_t ms)
Definition Arduino.h:255
RTSP_CMD_TYPES
Supported RTSP command types.
Definition RTSPSession.h:38
@ RTSP_SETUP
Definition RTSPSession.h:41
@ RTSP_PLAY
Definition RTSPSession.h:42
@ RTSP_OPTIONS
Definition RTSPSession.h:39
@ RTSP_TEARDOWN
Definition RTSPSession.h:44
@ RTSP_UNKNOWN
Definition RTSPSession.h:45
@ RTSP_PAUSE
Definition RTSPSession.h:43
@ RTSP_DESCRIBE
Definition RTSPSession.h:40
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:508