2#include "../../../Defines.h"
4#ifdef USE_CAMERA_MODULE
9CRtspSession::CRtspSession(SOCKET aRtspClient, CStreamer * aStreamer) : m_RtspClient(aRtspClient),m_Streamer(aStreamer)
11 printf(
"Creating RTSP session\n");
14 m_RtspSessionID = getRandom();
15 m_RtspSessionID |= 0x80000000;
19 m_TcpTransport =
false;
24CRtspSession::~CRtspSession()
26 closesocket(m_RtspClient);
29void CRtspSession::Init()
31 m_RtspCmdType = RTSP_UNKNOWN;
32 memset(m_URLPreSuffix, 0x00,
sizeof(m_URLPreSuffix));
33 memset(m_URLSuffix, 0x00,
sizeof(m_URLSuffix));
34 memset(m_CSeq, 0x00,
sizeof(m_CSeq));
35 memset(m_URLHostPort, 0x00,
sizeof(m_URLHostPort));
39bool CRtspSession::ParseRtspRequest(
char const * aRequest,
unsigned aRequestSize)
41 char CmdName[RTSP_PARAM_STRING_MAX];
42 static char CurRequest[RTSP_BUFFER_SIZE];
43 unsigned CurRequestSize;
46 CurRequestSize = aRequestSize;
47 memcpy(CurRequest,aRequest,aRequestSize);
55 ClientPortPtr = strstr(CurRequest,
"client_port");
56 if (ClientPortPtr !=
nullptr)
58 TmpPtr = strstr(ClientPortPtr,
"\r\n");
59 if (TmpPtr !=
nullptr)
62 strcpy(CP,ClientPortPtr);
72 m_ClientRTPPort = atoi(CP);
73 m_ClientRTCPPort = m_ClientRTPPort + 1;
80 bool parseSucceeded =
false;
82 for (i = 0; i <
sizeof(CmdName)-1 && i < CurRequestSize; ++i)
84 char c = CurRequest[i];
85 if (c ==
' ' || c ==
'\t')
87 parseSucceeded =
true;
93 if (!parseSucceeded) {
94 printf(
"failed to parse RTSP\n");
98 printf(
"RTSP received %s\n", CmdName);
101 if (strstr(CmdName,
"OPTIONS") !=
nullptr) m_RtspCmdType = RTSP_OPTIONS;
else
102 if (strstr(CmdName,
"DESCRIBE") !=
nullptr) m_RtspCmdType = RTSP_DESCRIBE;
else
103 if (strstr(CmdName,
"SETUP") !=
nullptr) m_RtspCmdType = RTSP_SETUP;
else
104 if (strstr(CmdName,
"PLAY") !=
nullptr) m_RtspCmdType = RTSP_PLAY;
else
105 if (strstr(CmdName,
"TEARDOWN") !=
nullptr) m_RtspCmdType = RTSP_TEARDOWN;
108 if (m_RtspCmdType == RTSP_SETUP)
110 TmpPtr = strstr(CurRequest,
"RTP/AVP/TCP");
111 if (TmpPtr !=
nullptr) m_TcpTransport =
true;
else m_TcpTransport =
false;
116 while (j < CurRequestSize && (CurRequest[j] ==
' ' || CurRequest[j] ==
'\t')) ++j;
117 for (; (int)j < (
int)(CurRequestSize-8); ++j)
119 if ((CurRequest[j] ==
'r' || CurRequest[j] ==
'R') &&
120 (CurRequest[j+1] ==
't' || CurRequest[j+1] ==
'T') &&
121 (CurRequest[j+2] ==
's' || CurRequest[j+2] ==
'S') &&
122 (CurRequest[j+3] ==
'p' || CurRequest[j+3] ==
'P') &&
123 CurRequest[j+4] ==
':' && CurRequest[j+5] ==
'/')
126 if (CurRequest[j] ==
'/')
130 while (j < CurRequestSize && CurRequest[j] !=
'/' && CurRequest[j] !=
' ' && uidx <
sizeof(m_URLHostPort) - 1)
132 m_URLHostPort[uidx] = CurRequest[j];
144 parseSucceeded =
false;
145 for (
unsigned k = i+1; (int)k < (
int)(CurRequestSize-5); ++k)
147 if (CurRequest[k] ==
'R' && CurRequest[k+1] ==
'T' &&
148 CurRequest[k+2] ==
'S' && CurRequest[k+3] ==
'P' &&
149 CurRequest[k+4] ==
'/')
151 while (--k >= i && CurRequest[k] ==
' ') {}
153 while (k1 > i && CurRequest[k1] !=
'/') --k1;
154 if (k - k1 + 1 >
sizeof(m_URLSuffix))
return false;
155 unsigned n = 0, k2 = k1+1;
157 while (k2 <= k) m_URLSuffix[n++] = CurRequest[k2++];
158 m_URLSuffix[n] =
'\0';
160 if (k1 - i >
sizeof(m_URLPreSuffix))
return false;
162 while (k2 <= k1 - 1) m_URLPreSuffix[n++] = CurRequest[k2++];
163 m_URLPreSuffix[n] =
'\0';
165 parseSucceeded =
true;
169 if (!parseSucceeded)
return false;
172 parseSucceeded =
false;
173 for (j = i; (int)j < (
int)(CurRequestSize-5); ++j)
175 if (CurRequest[j] ==
'C' && CurRequest[j+1] ==
'S' &&
176 CurRequest[j+2] ==
'e' && CurRequest[j+3] ==
'q' &&
177 CurRequest[j+4] ==
':')
180 while (j < CurRequestSize && (CurRequest[j] ==
' ' || CurRequest[j] ==
'\t')) ++j;
182 for (n = 0; n <
sizeof(m_CSeq)-1 && j < CurRequestSize; ++n,++j)
184 char c = CurRequest[j];
185 if (c ==
'\r' || c ==
'\n')
187 parseSucceeded =
true;
196 if (!parseSucceeded)
return false;
199 for (j = i; (int)j < (
int)(CurRequestSize-15); ++j)
201 if (CurRequest[j] ==
'C' && CurRequest[j+1] ==
'o' &&
202 CurRequest[j+2] ==
'n' && CurRequest[j+3] ==
't' &&
203 CurRequest[j+4] ==
'e' && CurRequest[j+5] ==
'n' &&
204 CurRequest[j+6] ==
't' && CurRequest[j+7] ==
'-' &&
205 (CurRequest[j+8] ==
'L' || CurRequest[j+8] ==
'l') &&
206 CurRequest[j+9] ==
'e' && CurRequest[j+10] ==
'n' &&
207 CurRequest[j+11] ==
'g' && CurRequest[j+12] ==
't' &&
208 CurRequest[j+13] ==
'h' && CurRequest[j+14] ==
':')
211 while (j < CurRequestSize && (CurRequest[j] ==
' ' || CurRequest[j] ==
'\t')) ++j;
213 if (sscanf(&CurRequest[j],
"%u", &num) == 1) m_ContentLength = num;
219RTSP_CMD_TYPES CRtspSession::Handle_RtspRequest(
char const * aRequest,
unsigned aRequestSize)
221 if (ParseRtspRequest(aRequest,aRequestSize))
223 switch (m_RtspCmdType)
225 case RTSP_OPTIONS: { Handle_RtspOPTION();
break; };
226 case RTSP_DESCRIBE: { Handle_RtspDESCRIBE();
break; };
227 case RTSP_SETUP: { Handle_RtspSETUP();
break; };
228 case RTSP_PLAY: { Handle_RtspPLAY();
break; };
232 return m_RtspCmdType;
235void CRtspSession::Handle_RtspOPTION()
237 static char Response[1024];
239 snprintf(Response,
sizeof(Response),
240 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
241 "Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE\r\n\r\n",m_CSeq);
243 socketsend(m_RtspClient,Response,strlen(Response));
246void CRtspSession::Handle_RtspDESCRIBE()
248 static char Response[1024];
249 static char SDPBuf[1024];
250 static char URLBuf[1024];
254 if ((strcmp(m_URLPreSuffix,
"mjpeg") == 0) && (strcmp(m_URLSuffix,
"1") == 0)) m_StreamID = 0;
else
255 if ((strcmp(m_URLPreSuffix,
"mjpeg") == 0) && (strcmp(m_URLSuffix,
"2") == 0)) m_StreamID = 1;
256 if (m_StreamID == -1)
258 snprintf(Response,
sizeof(Response),
259 "RTSP/1.0 404 Stream Not Found\r\nCSeq: %s\r\n%s\r\n",
263 socketsend(m_RtspClient,Response,strlen(Response));
268 static char OBuf[256];
270 strcpy(OBuf,m_URLHostPort);
271 ColonPtr = strstr(OBuf,
":");
272 if (ColonPtr !=
nullptr) ColonPtr[0] = 0x00;
274 snprintf(SDPBuf,
sizeof(SDPBuf),
276 "o=- %d 1 IN IP4 %s\r\n"
279 "m=video 0 RTP/AVP 26\r\n"
281 "c=IN IP4 0.0.0.0\r\n",
287 case 0: strcpy(StreamName,
"mjpeg/1");
break;
288 case 1: strcpy(StreamName,
"mjpeg/2");
break;
290 snprintf(URLBuf,
sizeof(URLBuf),
294 snprintf(Response,
sizeof(Response),
295 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
297 "Content-Base: %s/\r\n"
298 "Content-Type: application/sdp\r\n"
299 "Content-Length: %d\r\n\r\n"
304 (
int) strlen(SDPBuf),
307 socketsend(m_RtspClient,Response,strlen(Response));
310void CRtspSession::Handle_RtspSETUP()
312 static char Response[1024];
313 static char Transport[255];
316 m_Streamer->InitTransport(m_ClientRTPPort,m_ClientRTCPPort,m_TcpTransport);
320 snprintf(Transport,
sizeof(Transport),
"RTP/AVP/TCP;unicast;interleaved=0-1");
322 snprintf(Transport,
sizeof(Transport),
323 "RTP/AVP;unicast;destination=127.0.0.1;source=127.0.0.1;client_port=%i-%i;server_port=%i-%i",
326 m_Streamer->GetRtpServerPort(),
327 m_Streamer->GetRtcpServerPort());
328 snprintf(Response,
sizeof(Response),
329 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
332 "Session: %i\r\n\r\n",
338 socketsend(m_RtspClient,Response,strlen(Response));
341void CRtspSession::Handle_RtspPLAY()
343 static char Response[1024];
346 snprintf(Response,
sizeof(Response),
347 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
349 "Range: npt=0.000-\r\n"
351 "RTP-Info: url=rtsp://127.0.0.1:8554/mjpeg/1/track1\r\n\r\n",
356 socketsend(m_RtspClient,Response,strlen(Response));
359char const * CRtspSession::DateHeader()
361 static char buf[200];
362 time_t tt = time(NULL);
363 strftime(buf,
sizeof buf,
"Date: %a, %b %d %Y %H:%M:%S GMT", gmtime(&tt));
367int CRtspSession::GetStreamID()
377bool CRtspSession::handleRequests(uint32_t readTimeoutMs)
382 static char RecvBuf[RTSP_BUFFER_SIZE];
384 memset(RecvBuf,0x00,
sizeof(RecvBuf));
385 int res = socketread(m_RtspClient,RecvBuf,
sizeof(RecvBuf), readTimeoutMs);
388 if ((RecvBuf[0] ==
'O') || (RecvBuf[0] ==
'D') || (RecvBuf[0] ==
'S') || (RecvBuf[0] ==
'P') || (RecvBuf[0] ==
'T'))
390 RTSP_CMD_TYPES C = Handle_RtspRequest(RecvBuf,res);
393 else if (C == RTSP_TEARDOWN)
399 printf(
"client closed socket, exiting\n");
410void CRtspSession::broadcastCurrentFrame(uint32_t curMsec) {
412 if (m_streaming && !m_stopped) {
414 m_Streamer->streamImage(curMsec);