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
76template <
typename Platform>
102 LOGI(
"RTSP session created");
114 LOGI(
"RTSP session destructor");
118 LOGI(
"Final cleanup: stopping streamer in destructor");
129 LOGI(
"RTSP session cleanup completed");
149 LOGD(
"handleRequests");
182 LOGI(
"Stopping streamer due to TEARDOWN");
190 }
else if (res == 0) {
191 LOGW(
"client closed socket, exiting");
196 LOGI(
"Stopping streamer due to client disconnect");
362 unsigned aRequestSize) {
404 LOGI(
"aRequest: ------------------------\n%s\n-------------------------",
408 const unsigned CurRequestSize = aRequestSize;
416 unsigned idxAfterCmd = 0;
439 char* ClientPortPtr = strstr(req,
"client_port");
440 if (!ClientPortPtr)
return;
441 char* lineEnd = strstr(ClientPortPtr,
"\r\n");
442 if (!lineEnd)
return;
445 char saved = lineEnd[0];
448 char* eq = strstr(CP,
"=");
451 char* dash = strstr(eq,
"-");
462 char* TransportPtr = strstr(req,
"Transport:");
463 if (!TransportPtr)
return;
464 char* lineEnd = strstr(TransportPtr,
"\r\n");
465 if (!lineEnd)
return;
468 char saved = lineEnd[0];
471 if (strstr(CP,
"RTP/AVP/TCP") || strstr(CP,
"/TCP"))
m_TransportIsTcp =
true;
472 char* inter = strstr(CP,
"interleaved=");
474 inter += strlen(
"interleaved=");
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) {
495 if (c ==
' ' || c ==
'\t') {
503 LOGE(
"failed to parse RTSP");
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] ==
'/') {
539 while (j < reqSize && req[j] !=
'/' && req[j] !=
' ' && uidx <
m_URLHostPort.
size() - 1) {
552 if (i < reqSize && req[i] ==
'/') {
555 while (k < reqSize && req[k] !=
' ' && p <
m_URLPath.
size() - 1) {
564 LOGW(
"Session rejected by onSessionPath callback");
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] ==
' ') {}
576 while (k1 > i && req[k1] !=
'=') --k1;
578 unsigned n = 0, k2 = k1 + 1;
593 LOGD(
"URL Suffix parse succeeded: %i", ok);
596 bool parseCSeq(
char* req,
unsigned reqSize,
unsigned startIdx) {
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] ==
':') {
601 while (j < reqSize && (req[j] ==
' ' || req[j] ==
'\t')) ++j;
603 for (n = 0; n <
m_CSeq.
size() - 1 && j < reqSize; ++n, ++j) {
605 if (c ==
'\r' || c ==
'\n') {
615 LOGD(
"Look for CSeq success: %i", ok);
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] ==
':') {
626 while (j < reqSize && (req[j] ==
' ' || req[j] ==
'\t')) ++j;
634 char* ua = strstr(req,
"User-Agent:");
635 bool want_rfc2250 =
false;
637 if (strcasestr(ua,
"ffmpeg") || strcasestr(ua,
"ffplay") || strcasestr(ua,
"libavformat") ||
638 strcasestr(ua,
"Lavf")) {
641 if (strcasestr(ua,
"vlc")) want_rfc2250 =
false;
643 char* qm = strchr(req,
'?');
645 if (strstr(qm,
"mpa_hdr=1")) want_rfc2250 =
true;
646 if (strstr(qm,
"mpa_hdr=0")) want_rfc2250 =
false;
659 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
660 "Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE\r\n\r\n",
683 if (ColonPtr !=
nullptr) ColonPtr[0] = 0x00;
688 "o=- %d 0 IN IP4 %s\r\n"
699 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
701 "Content-Base: %s/\r\n"
702 "Content-Type: application/sdp\r\n"
703 "Content-Length: %d\r\n\r\n"
709 Serial.println(
"------------------------------");
711 Serial.println(
"------------------------------");
728 "RTP/AVP/TCP;unicast;interleaved=%d-%d", ch0, ch1);
734 "RTP/AVP;unicast;client_port=%i-%i;server_port=%i-%i;ssrc=%08X",
740 "RTSP/1.0 200 OK\r\n"
748 Serial.println(
"------------------------------");
750 Serial.println(
"------------------------------");
770 "RTSP/1.0 200 OK\r\n"
772 "Range: npt=0.000-\r\n"
774 "RTP-Info: url=%s;seq=%u;rtptime=%u\r\n\r\n",
778 Serial.println(
"------------------------------");
780 Serial.println(
"------------------------------");
796 "RTSP/1.0 200 OK\r\n"
798 "Session: %i\r\n\r\n",
811 "RTSP/1.0 200 OK\r\n"
837 Platform::getSocketPeerAddr(
m_RtspClient, &clientIP, &clientPort);
839 LOGI(
"SETUP peer resolved: %s:%u (RTP client_port=%u)",
840 clientIP.
toString().c_str(), (
unsigned)clientPort,
858 inline int readSocket(
typename Platform::TcpClientType* sock,
char* buf,
859 size_t buflen,
int timeoutmsec) {
860 return Platform::readSocket(sock, buf, buflen, timeoutmsec);
870 inline ssize_t
sendSocket(
typename Platform::TcpClientType* sock,
871 const void* buf,
size_t len) {
872 return Platform::sendSocket(sock, buf, len);
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));
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