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 const unsigned CurRequestSize = aRequestSize;
409
410 // 1) Ports and transport
413
414 // 2) Command + URL host/parts
415 unsigned idxAfterCmd = 0;
417 return false;
420 if (!m_sessionOpen) {
421 // Aborted by callback during URL parse; don't proceed further
422 return false;
423 }
424
425 // 3) CSeq and Content-Length
427 return false;
429
430 // 4) Client preference toggle (User-Agent / URL)
432
433 return true;
434 }
435
436 // ---- Parsing helpers ----
437 void parseClientPorts(char* req) {
438 char* ClientPortPtr = strstr(req, "client_port");
439 if (!ClientPortPtr) return;
440 char* lineEnd = strstr(ClientPortPtr, "\r\n");
441 if (!lineEnd) return;
442 char* CP = m_Response.data();
443 memset(CP, 0, m_Response.size());
444 char saved = lineEnd[0];
445 lineEnd[0] = '\0';
447 char* eq = strstr(CP, "=");
448 if (eq) {
449 ++eq;
450 strcpy(CP, eq);
451 char* dash = strstr(CP, "-");
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 CP[m_Response.size() - 1] = '\0';
472 if (strstr(CP, "RTP/AVP/TCP") || strstr(CP, "/TCP")) m_TransportIsTcp = true;
473 char* inter = strstr(CP, "interleaved=");
474 if (inter) {
475 inter += strlen("interleaved=");
476 int a = -1, b = -1;
477 if (sscanf(inter, "%d-%d", &a, &b) == 2) {
480 } else if (sscanf(inter, "%d,%d", &a, &b) == 2) {
483 } else if (sscanf(inter, "%d", &a) == 1) {
485 m_InterleavedRtcp = a + 1;
486 }
487 }
488 lineEnd[0] = saved;
489 }
490
491 bool parseCommandName(char* req, unsigned reqSize, unsigned& outIdx) {
492 bool ok = false;
493 unsigned i;
494 for (i = 0; i < m_CmdName.size() - 1 && i < reqSize; ++i) {
495 char c = req[i];
496 if (c == ' ' || c == '\t') {
497 ok = true;
498 break;
499 }
500 m_CmdName[i] = c;
501 }
502 m_CmdName[i] = '\0';
503 if (!ok) {
504 LOGE("failed to parse RTSP");
505 return false;
506 }
507 LOGI("RTSP received %s", m_CmdName.data());
508 outIdx = i;
509 return true;
510 }
511
513 if (strstr(m_CmdName.data(), "OPTIONS"))
515 else if (strstr(m_CmdName.data(), "DESCRIBE"))
517 else if (strstr(m_CmdName.data(), "SETUP"))
519 else if (strstr(m_CmdName.data(), "PLAY"))
521 else if (strstr(m_CmdName.data(), "PAUSE"))
523 else if (strstr(m_CmdName.data(), "TEARDOWN"))
525 else
526 LOGE("Error: Unsupported Command received (%s)!", m_CmdName.data());
527 }
528
529 void parseUrlHostPortAndSuffix(char* req, unsigned reqSize, unsigned& i) {
530 unsigned j = i + 1;
531 while (j < reqSize && (req[j] == ' ' || req[j] == '\t')) ++j;
532 for (; (int)j < (int)(reqSize - 8); ++j) {
533 if ((req[j] == 'r' || req[j] == 'R') && (req[j + 1] == 't' || req[j + 1] == 'T') &&
534 (req[j + 2] == 's' || req[j + 2] == 'S') && (req[j + 3] == 'p' || req[j + 3] == 'P') &&
535 req[j + 4] == ':' && req[j + 5] == '/') {
536 j += 6;
537 if (req[j] == '/') {
538 ++j;
539 unsigned uidx = 0;
540 while (j < reqSize && req[j] != '/' && req[j] != ' ' && uidx < m_URLHostPort.size() - 1) {
541 m_URLHostPort[uidx++] = req[j++];
542 }
543 } else {
544 --j;
545 }
546 i = j;
547 break;
548 }
549 }
550 LOGD("m_URLHostPort: %s", m_URLHostPort.data());
551
552 // Extract full RTSP path starting at current index i up to next space
553 if (i < reqSize && req[i] == '/') {
554 unsigned p = 0;
555 unsigned k = i;
556 while (k < reqSize && req[k] != ' ' && p < m_URLPath.size() - 1) {
557 m_URLPath[p++] = req[k++];
558 }
559 m_URLPath[p] = '\0';
560 LOGD("m_URLPath: %s", m_URLPath.data());
563 m_pathNotified = true;
564 if (!ok) {
565 LOGW("Session rejected by onSessionPath callback");
566 m_sessionOpen = false;
567 // Early exit: abort further parsing of this request
568 }
569 }
570 }
571
572 bool ok = false;
573 for (unsigned k = i + 1; (int)k < (int)(reqSize - 5); ++k) {
574 if (req[k] == 'R' && req[k + 1] == 'T' && req[k + 2] == 'S' && req[k + 3] == 'P' && req[k + 4] == '/') {
575 while (--k >= i && req[k] == ' ') {}
576 unsigned k1 = k;
577 while (k1 > i && req[k1] != '=') --k1;
578 if (k - k1 + 1 <= m_URLSuffix.size()) {
579 unsigned n = 0, k2 = k1 + 1;
580 while (k2 <= k) m_URLSuffix[n++] = req[k2++];
581 m_URLSuffix[n] = '\0';
582 if (k1 - i <= m_URLPreSuffix.size()) ok = true;
583 n = 0;
584 k2 = i + 1;
585 while (k2 <= k1 - 1) m_URLPreSuffix[n++] = req[k2++];
586 m_URLPreSuffix[n] = '\0';
587 i = k + 7;
588 }
589 break;
590 }
591 }
592 LOGD("m_URLSuffix: %s", m_URLSuffix.data());
593 LOGD("m_URLPreSuffix: %s", m_URLPreSuffix.data());
594 LOGD("URL Suffix parse succeeded: %i", ok);
595 }
596
597 bool parseCSeq(char* req, unsigned reqSize, unsigned startIdx) {
598 bool ok = false;
599 for (unsigned j = startIdx; (int)j < (int)(reqSize - 5); ++j) {
600 if (req[j] == 'C' && req[j + 1] == 'S' && req[j + 2] == 'e' && req[j + 3] == 'q' && req[j + 4] == ':') {
601 j += 5;
602 while (j < reqSize && (req[j] == ' ' || req[j] == '\t')) ++j;
603 unsigned n;
604 for (n = 0; n < m_CSeq.size() - 1 && j < reqSize; ++n, ++j) {
605 char c = req[j];
606 if (c == '\r' || c == '\n') {
607 ok = true;
608 break;
609 }
610 m_CSeq[n] = c;
611 }
612 m_CSeq[n] = '\0';
613 break;
614 }
615 }
616 LOGD("Look for CSeq success: %i", ok);
617 return ok;
618 }
619
620 void parseContentLength(char* req, unsigned reqSize, unsigned startIdx) {
621 for (unsigned j = startIdx; (int)j < (int)(reqSize - 15); ++j) {
622 if (req[j] == 'C' && req[j + 1] == 'o' && req[j + 2] == 'n' && req[j + 3] == 't' &&
623 req[j + 4] == 'e' && req[j + 5] == 'n' && req[j + 6] == 't' && req[j + 7] == '-' &&
624 (req[j + 8] == 'L' || req[j + 8] == 'l') && req[j + 9] == 'e' && req[j + 10] == 'n' &&
625 req[j + 11] == 'g' && req[j + 12] == 't' && req[j + 13] == 'h' && req[j + 14] == ':') {
626 j += 15;
627 while (j < reqSize && (req[j] == ' ' || req[j] == '\t')) ++j;
628 unsigned num;
629 if (sscanf(&req[j], "%u", &num) == 1) m_ContentLength = num;
630 }
631 }
632 }
633
635 char* ua = strstr(req, "User-Agent:");
636 bool want_rfc2250 = false;
637 if (ua) {
638 if (strcasestr(ua, "ffmpeg") || strcasestr(ua, "ffplay") || strcasestr(ua, "libavformat") ||
639 strcasestr(ua, "Lavf")) {
640 want_rfc2250 = true;
641 }
642 if (strcasestr(ua, "vlc")) want_rfc2250 = false;
643 }
644 char* qm = strchr(req, '?');
645 if (qm) {
646 if (strstr(qm, "mpa_hdr=1")) want_rfc2250 = true;
647 if (strstr(qm, "mpa_hdr=0")) want_rfc2250 = false;
648 }
649 if (m_Streamer && m_Streamer->getAudioSource()) {
650 RTSPFormat& fmt = m_Streamer->getAudioSource()->getFormat();
652 }
653 }
654
660 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
661 "Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE\r\n\r\n",
662 m_CSeq.data());
663
665 }
666
671 // check whether we know a stream with the URL which is requested
672 m_StreamID = -1; // invalid URL
673 // find Stream ID
675 char* end;
676 m_StreamID = strtol(m_URLSuffix.data(), &end, 10);
677 if (*end != '\0') m_StreamID = -1;
678 }
679
680 // simulate DESCRIBE server response
681 char* ColonPtr;
683 ColonPtr = strstr(m_Buf1.data(), ":");
684 if (ColonPtr != nullptr) ColonPtr[0] = 0x00;
685
686 snprintf(
688 "v=0\r\n" // SDP Version
689 "o=- %d 0 IN IP4 %s\r\n"
690 "%s"
691 "a=control:%s=0",
692 rand() & 0xFF, m_Buf1.data(),
693 m_Streamer->getAudioSource()->getFormat().format(m_Buf2.data(), 256),
695
696 snprintf(m_URLBuf.data(), m_URLBuf.size(), "rtsp://%s",
698
700 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
701 "%s\r\n"
702 "Content-Base: %s/\r\n"
703 "Content-Type: application/sdp\r\n"
704 "Content-Length: %d\r\n\r\n"
705 "%s",
707 (int)strlen(m_SDPBuf.data()), m_SDPBuf.data());
708
709 // LOGI("handleRtspDescribe: %s", (const char*)m_Response.data());
710 Serial.println("------------------------------");
711 Serial.println((const char*)m_Response.data());
712 Serial.println("------------------------------");
714 }
715
720 // Build response depending on requested transport
721 if (m_TransportIsTcp) {
722 // Initialize TCP interleaved transport on same RTSP TCP socket
723 int ch0 = (m_InterleavedRtp >= 0) ? m_InterleavedRtp : 0;
724 int ch1 = (m_InterleavedRtcp >= 0) ? m_InterleavedRtcp : (ch0 + 1);
725 m_Streamer->initTcpInterleavedTransport(m_RtspClient, ch0, ch1);
726
727 // Reply with interleaved channels
729 "RTP/AVP/TCP;unicast;interleaved=%d-%d", ch0, ch1);
730 } else {
731 // init RTSP Session transport type (UDP) and ports for UDP transport
733 // UDP Transport response with client/server ports and ssrc
735 "RTP/AVP;unicast;client_port=%i-%i;server_port=%i-%i;ssrc=%08X",
737 m_Streamer->getRtpServerPort(), m_Streamer->getRtcpServerPort(),
738 (unsigned)m_Streamer->currentSsrc());
739 }
741 "RTSP/1.0 200 OK\r\n"
742 "CSeq: %s\r\n"
743 "%s\r\n"
744 "Session: %i\r\n"
745 "Transport: %s\r\n"
746 "\r\n",
748
749 Serial.println("------------------------------");
750 Serial.println((char*)m_Response.data());
751 Serial.println("------------------------------");
752
754 }
755
760 // Build RTP-Info to help clients (e.g., VLC) synchronize
761 // URL base
762 snprintf(m_URLBuf.data(), m_URLBuf.size(), "rtsp://%s/%s=0",
764
765 // Current seq/timestamp from streamer (values used for next packet)
766 uint16_t seq = m_Streamer ? m_Streamer->currentSeq() : 0;
767 uint32_t rtptime = m_Streamer ? m_Streamer->currentRtpTimestamp() : 0;
768
769 // PLAY response with Range, Session and RTP-Info
771 "RTSP/1.0 200 OK\r\n"
772 "CSeq: %s\r\n"
773 "Range: npt=0.000-\r\n"
774 "Session: %i\r\n"
775 "RTP-Info: url=%s;seq=%u;rtptime=%u\r\n\r\n",
776 m_CSeq.data(), m_RtspSessionID, m_URLBuf.data(), (unsigned)seq,
777 (unsigned)rtptime);
778
779 Serial.println("------------------------------");
780 Serial.println((char*)m_Response.data());
781 Serial.println("------------------------------");
782
784
785 m_Streamer->start();
786 }
787
793 if (m_streaming && m_Streamer) {
794 m_Streamer->stop();
795 }
797 "RTSP/1.0 200 OK\r\n"
798 "CSeq: %s\r\n"
799 "Session: %i\r\n\r\n",
802 }
803
808 m_Streamer->stop();
809
810 // simulate SETUP server response
812 "RTSP/1.0 200 OK\r\n"
813 "CSeq: %s\r\n\r\n",
814 m_CSeq.data());
815
817
818 m_sessionOpen = false;
819 }
820
825 int getStreamID() { return m_StreamID; }
826
835
838 Platform::getSocketPeerAddr(m_RtspClient, &clientIP, &clientPort);
839
840 LOGI("SETUP peer resolved: %s:%u (RTP client_port=%u)",
841 clientIP.toString().c_str(), (unsigned)clientPort,
842 (unsigned)m_RtpClientPort);
843
844 m_Streamer->initUdpTransport(clientIP, m_RtpClientPort);
845 }
846
847 typename Platform::TcpClientType*& getClient() { return m_RtspClient; }
848
850
859 inline int readSocket(typename Platform::TcpClientType* sock, char* buf,
860 size_t buflen, int timeoutmsec) {
861 return Platform::readSocket(sock, buf, buflen, timeoutmsec);
862 }
863
871 inline ssize_t sendSocket(typename Platform::TcpClientType* sock,
872 const void* buf, size_t len) {
873 return Platform::sendSocket(sock, buf, len);
874 }
875
880 char const* dateHeader() {
881 static char buf[200];
882 time_t tt = time(NULL);
883 strftime(buf, sizeof(buf), "Date: %a, %b %d %Y %H:%M:%S GMT", gmtime(&tt));
884 return buf;
885 }
886};
887
888} // namespace audio_tools
#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
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:491
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:859
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:832
uint16_t m_RtpClientPort
Definition RTSPSession.h:259
Platform::TcpClientType *& getClient()
Definition RTSPSession.h:847
ssize_t sendSocket(typename Platform::TcpClientType *sock, const void *buf, size_t len)
Inline helper to send data over socket.
Definition RTSPSession.h:871
bool m_streaming
Definition RTSPSession.h:278
void parseClientPorts(char *req)
Definition RTSPSession.h:437
audio_tools::Vector< char > m_URLHostPort
Definition RTSPSession.h:256
void handleRtspSetup()
Definition RTSPSession.h:719
void handleRtspDescribe()
Definition RTSPSession.h:670
bool parseRtspRequest(char const *aRequest, unsigned aRequestSize)
Definition RTSPSession.h:403
void determineCommandType()
Definition RTSPSession.h:512
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:825
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:634
uint16_t m_ClientRTPPort
Definition RTSPSession.h:246
audio_tools::Vector< char > m_URLPreSuffix
Definition RTSPSession.h:253
void handleRtspTeardown()
Definition RTSPSession.h:807
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:759
volatile bool m_sessionOpen
Definition RTSPSession.h:279
audio_tools::Vector< char > m_Buf1
Definition RTSPSession.h:272
void handleRtspOption()
Definition RTSPSession.h:658
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:880
void parseContentLength(char *req, unsigned reqSize, unsigned startIdx)
Definition RTSPSession.h:620
uint16_t getRtpClientPort()
Definition RTSPSession.h:849
bool parseCSeq(char *req, unsigned reqSize, unsigned startIdx)
Definition RTSPSession.h:597
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:792
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:529
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(int 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(unsigned long ms)
Definition Time.h:23
static HardwareSerial Serial
Definition NoArduino.h:186
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:512