1.创建了一个 RTSPClientConnection 类型的实例 session
RTSPClientConnection
2. 调用该类的处理函数
session->incomingRequestHandler1();
2.1 读取 socket 发过来的数据 在 fRequestBuffer【RTSP_BUFFER_SIZE】数组中
int bytesRead = readSocket(envir(), fClientInputSocket, &fRequestBuffer[fRequestBytesAlreadySeen], fRequestBufferBytesLeft, dummy)
其中
fRequestBytesAlreadySeen 表示 已经读取到的地方 类似读指针
fRequestBufferBytesLeft 表示 剩余空间内容
2.2 解析并且处理数据
handleRequestBytes(bytesRead);
2.2.1 循环遍历接收数组找到\r\n
unsigned char* ptr = &fRequestBuffer[fRequestBytesAlreadySeen];
// Look for the end of the message: <CR><LF><CR><LF>
unsigned char *tmpPtr = fLastCRLF + 2;
if (tmpPtr < fRequestBuffer) tmpPtr = fRequestBuffer;
while (tmpPtr < &ptr[newBytesRead-1]) {
if (*tmpPtr == '\r' && *(tmpPtr+1) == '\n') {
if (tmpPtr - fLastCRLF == 2) { // This is it:
endOfMsg = True;
break;
}
fLastCRLF = tmpPtr;
}
++tmpPtr;
}
2.2.2 解析处理数据
Boolean parseSucceeded = parseRTSPRequestString((char*)fRequestBuffer, fLastCRLF+2 - fRequestBuffer,
cmdName, sizeof cmdName,
urlPreSuffix, sizeof urlPreSuffix,
urlSuffix, sizeof urlSuffix,
cseq, sizeof cseq,
sessionIdStr, sizeof sessionIdStr,
contentLength);
2.2.2.1得到结果后 判定命令是哪一种
if (strcmp(cmdName, "OPTIONS") == 0)
{
handleCmd_OPTIONS();
}
else if (urlPreSuffix[0] == '\0' && urlSuffix[0] == '*' && urlSuffix[1] == '\0')
{
// The special "*" URL means: an operation on the entire server. This works only for GET_PARAMETER and SET_PARAMETER:
if (strcmp(cmdName, "GET_PARAMETER") == 0)
{
handleCmd_GET_PARAMETER((char const*)fRequestBuffer);
}
else if (strcmp(cmdName, "SET_PARAMETER") == 0)
{
handleCmd_SET_PARAMETER((char const*)fRequestBuffer);
}
else
{
handleCmd_notSupported();
}
}
else if (strcmp(cmdName, "DESCRIBE") == 0)
{
handleCmd_DESCRIBE(urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
}
else if (strcmp(cmdName, "SETUP") == 0)
{
if (!requestIncludedSessionId)
{
// No session id was present in the request. So create a new "RTSPClientSession" object
// for this request. Choose a random (unused) 32-bit integer for the session id
// (it will be encoded as a 8-digit hex number). (We avoid choosing session id 0,
// because that has a special use (by "OnDemandServerMediaSubsession").)
u_int32_t sessionId;
do
{
sessionId = (u_int32_t)our_random32();
sprintf(sessionIdStr, "%08X", sessionId);
} while (sessionId == 0 || fOurServer.fClientSessions->Lookup(sessionIdStr) != NULL);
clientSession = fOurServer.createNewClientSession(sessionId);
fOurServer.fClientSessions->Add(sessionIdStr, clientSession);
}
if (clientSession != NULL)
{
clientSession->handleCmd_SETUP(this, urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
playAfterSetup = clientSession->fStreamAfterSETUP;
}
else
{
handleCmd_sessionNotFound();
}
}
else if (strcmp(cmdName, "TEARDOWN") == 0
|| strcmp(cmdName, "PLAY") == 0
|| strcmp(cmdName, "PAUSE") == 0
|| strcmp(cmdName, "GET_PARAMETER") == 0
|| strcmp(cmdName, "SET_PARAMETER") == 0)
{
if (clientSession != NULL)
{
clientSession->handleCmd_withinSession(this, cmdName, urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
}
else
{
handleCmd_sessionNotFound();
}
}
else if (strcmp(cmdName, "REGISTER") == 0)
{
// Because - unlike other commands - an implementation of this command needs
// the entire URL, we re-parse the command to get it:
char* url = strDupSize((char*)fRequestBuffer);
if (sscanf((char*)fRequestBuffer, "%*s %s", url) == 1)
{
// Check for special command-specific parameters in a "Transport:" header:
Boolean reuseConnection, deliverViaTCP;
char* proxyURLSuffix;
parseTransportHeaderForREGISTER((const char*)fRequestBuffer, reuseConnection, deliverViaTCP, proxyURLSuffix);
handleCmd_REGISTER(url, urlSuffix, (char const*)fRequestBuffer, reuseConnection, deliverViaTCP, proxyURLSuffix);
delete[] proxyURLSuffix;
}
else
{
handleCmd_bad();
}
delete[] url;
}
else
{
// The command is one that we don't handle:
handleCmd_notSupported();
}
2.2.2.2发送回复数据给客户端
send(fClientOutputSocket, (char const*)fResponseBuffer, strlen((char*)fResponseBuffer), 0)
2.2.2.3 清空RequestBuffer
handleRequestBytes(bytesRead);
流程图如下