rtspclient.cpp
来自「Live media server used to transfer mpeg 」· C++ 代码 · 共 2,060 行 · 第 1/5 页
CPP
2,060 行
"CSeq: %d\r\n" "Session: %s\r\n" "Range: npt=0-\r\n" "%s" "%s" "\r\n"; char const *prefix, *separator, *suffix; constructSubsessionURL(subsession, prefix, separator, suffix); unsigned cmdSize = strlen(cmdFmt) + strlen(prefix) + strlen(separator) + strlen(suffix) + 20 /* max int len */ + strlen(subsession.sessionId) + strlen(authenticatorStr) + fUserAgentHeaderStrSize; cmd = new char[cmdSize]; sprintf(cmd, cmdFmt, prefix, separator, suffix, ++fCSeq, subsession.sessionId, authenticatorStr, fUserAgentHeaderStr); delete[] authenticatorStr; if (!sendRequest(cmd, "RECORD")) break; // Get the response from the server: unsigned bytesRead; unsigned responseCode; char* firstLine; char* nextLineStart; if (!getResponse("RECORD", bytesRead, responseCode, firstLine, nextLineStart)) break; delete[] cmd; return True; } while (0); delete[] cmd; return False;}Boolean RTSPClient::setMediaSessionParameter(MediaSession& /*session*/, char const* parameterName, char const* parameterValue) { char* cmd = NULL; do { // First, make sure that we have a RTSP session in progress if (fLastSessionId == NULL) { envir().setResultMsg("No RTSP session is currently in progress\n"); break; } // Send the SET_PARAMETER command: // First, construct an authenticator string: char* authenticatorStr = createAuthenticatorString(&fCurrentAuthenticator, "SET_PARAMETER", fBaseURL); char* const cmdFmt = "SET_PARAMETER %s RTSP/1.0\r\n" "CSeq: %d\r\n" "Session: %s\r\n" "%s" "%s" "%s: %s\r\n" "\r\n"; unsigned cmdSize = strlen(cmdFmt) + strlen(fBaseURL) + 20 /* max int len */ + strlen(fLastSessionId) + strlen(authenticatorStr) + fUserAgentHeaderStrSize + strlen(parameterName) + strlen(parameterValue); cmd = new char[cmdSize]; sprintf(cmd, cmdFmt, fBaseURL, ++fCSeq, fLastSessionId, authenticatorStr, fUserAgentHeaderStr, parameterName, parameterValue); delete[] authenticatorStr; if (!sendRequest(cmd, "SET_PARAMETER")) break; // Get the response from the server: unsigned bytesRead; unsigned responseCode; char* firstLine; char* nextLineStart; if (!getResponse("SET_PARAMETER", bytesRead, responseCode, firstLine, nextLineStart)) break; delete[] cmd; return True; } while (0); delete[] cmd; return False;}Boolean RTSPClient::teardownMediaSession(MediaSession& /*session*/) { char* cmd = NULL; do { // First, make sure that we have a RTSP session in progreee if (fLastSessionId == NULL) { envir().setResultMsg("No RTSP session is currently in progress\n"); break; } // Send the TEARDOWN command: // First, construct an authenticator string: char* authenticatorStr = createAuthenticatorString(&fCurrentAuthenticator, "TEARDOWN", fBaseURL); char* const cmdFmt = "TEARDOWN %s RTSP/1.0\r\n" "CSeq: %d\r\n" "Session: %s\r\n" "%s" "%s" "\r\n"; unsigned cmdSize = strlen(cmdFmt) + strlen(fBaseURL) + 20 /* max int len */ + strlen(fLastSessionId) + strlen(authenticatorStr) + fUserAgentHeaderStrSize; cmd = new char[cmdSize]; sprintf(cmd, cmdFmt, fBaseURL, ++fCSeq, fLastSessionId, authenticatorStr, fUserAgentHeaderStr); delete[] authenticatorStr; if (!sendRequest(cmd, "TEARDOWN")) break; if (fTCPStreamIdCount == 0) { // When TCP streaming, don't look for a response // Get the response from the server: unsigned bytesRead; unsigned responseCode; char* firstLine; char* nextLineStart; if (!getResponse("TEARDOWN", bytesRead, responseCode, firstLine, nextLineStart)) break; delete[] fLastSessionId; fLastSessionId = NULL; // we're done with this session } delete[] cmd; return True; } while (0); delete[] cmd; return False;}Boolean RTSPClient::teardownMediaSubsession(MediaSubsession& subsession) { char* cmd = NULL; do { // First, make sure that we have a RTSP session in progreee if (subsession.sessionId == NULL) { envir().setResultMsg("No RTSP session is currently in progress\n"); break; } // Send the TEARDOWN command: // First, construct an authenticator string: char* authenticatorStr = createAuthenticatorString(&fCurrentAuthenticator, "TEARDOWN", fBaseURL); char* const cmdFmt = "TEARDOWN %s%s%s RTSP/1.0\r\n" "CSeq: %d\r\n" "Session: %s\r\n" "%s" "%s" "\r\n"; char const *prefix, *separator, *suffix; constructSubsessionURL(subsession, prefix, separator, suffix); unsigned cmdSize = strlen(cmdFmt) + strlen(prefix) + strlen(separator) + strlen(suffix) + 20 /* max int len */ + strlen(subsession.sessionId) + strlen(authenticatorStr) + fUserAgentHeaderStrSize; cmd = new char[cmdSize]; sprintf(cmd, cmdFmt, prefix, separator, suffix, ++fCSeq, subsession.sessionId, authenticatorStr, fUserAgentHeaderStr); delete[] authenticatorStr; if (!sendRequest(cmd, "TEARDOWN")) break; if (fTCPStreamIdCount == 0) { // When TCP streaming, don't look for a response // Get the response from the server: unsigned bytesRead; unsigned responseCode; char* firstLine; char* nextLineStart; if (!getResponse("TEARDOWN", bytesRead, responseCode, firstLine, nextLineStart)) break; } delete[] (char*)subsession.sessionId; subsession.sessionId = NULL; // we're done with this session delete[] cmd; return True; } while (0); delete[] cmd; return False;}Boolean RTSPClient::openConnectionFromURL(char const* url) { do { // Set this as our base URL: delete[] fBaseURL; fBaseURL = strDup(url); if (fBaseURL == NULL) break; // Begin by parsing the URL: NetAddress destAddress; portNumBits urlPortNum; char const* urlSuffix; if (!parseRTSPURL(envir(), url, destAddress, urlPortNum, &urlSuffix)) break; portNumBits destPortNum = fTunnelOverHTTPPortNum == 0 ? urlPortNum : fTunnelOverHTTPPortNum; if (fInputSocketNum < 0) { // We don't yet have a TCP socket. Set one up (blocking) now: fInputSocketNum = fOutputSocketNum = setupStreamSocket(envir(), 0, False /* =>blocking */); if (fInputSocketNum < 0) break; // Connect to the remote endpoint: struct sockaddr_in remoteName; remoteName.sin_family = AF_INET; remoteName.sin_port = htons(destPortNum); remoteName.sin_addr.s_addr = fServerAddress = *(unsigned*)(destAddress.data()); if (connect(fInputSocketNum, (struct sockaddr*)&remoteName, sizeof remoteName) != 0) { envir().setResultErrMsg("connect() failed: "); break; } if (fTunnelOverHTTPPortNum != 0 && !setupHTTPTunneling(urlSuffix)) break; } return True; } while (0); fDescribeStatusCode = 1; resetTCPSockets(); return False;}Boolean RTSPClient::parseRTSPURL(UsageEnvironment& env, char const* url, NetAddress& address, portNumBits& portNum, char const** urlSuffix) { do { // Parse the URL as "rtsp://<address>:<port>/<etc>" // (with ":<port>" and "/<etc>" optional) // Also, skip over any "<username>[:<password>]@" preceding <address> char const* prefix = "rtsp://"; unsigned const prefixLength = 7; if (_strncasecmp(url, prefix, prefixLength) != 0) { env.setResultMsg("URL is not of the form \"", prefix, "\""); break; } unsigned const parseBufferSize = 100; char parseBuffer[parseBufferSize]; char const* from = &url[prefixLength]; // Skip over any "<username>[:<password>]@" char const* from1 = from; while (*from1 != '\0' && *from1 != '/') { if (*from1 == '@') { from = ++from1; break; } ++from1; } char* to = &parseBuffer[0]; unsigned i; for (i = 0; i < parseBufferSize; ++i) { if (*from == '\0' || *from == ':' || *from == '/') { // We've completed parsing the address *to = '\0'; break; } *to++ = *from++; } if (i == parseBufferSize) { env.setResultMsg("URL is too long"); break; } NetAddressList addresses(parseBuffer); if (addresses.numAddresses() == 0) { env.setResultMsg("Failed to find network address for \"", parseBuffer, "\""); break; } address = *(addresses.firstAddress()); portNum = 554; // default value char nextChar = *from; if (nextChar == ':') { int portNumInt; if (sscanf(++from, "%d", &portNumInt) != 1) { env.setResultMsg("No port number follows ':'"); break; } if (portNumInt < 1 || portNumInt > 65535) { env.setResultMsg("Bad port number"); break; } portNum = (portNumBits)portNumInt; while (*from >= '0' && *from <= '9') ++from; // skip over port number } // The remainder of the URL is the suffix: if (urlSuffix != NULL) *urlSuffix = from; return True; } while (0); return False;}Boolean RTSPClient::parseRTSPURLUsernamePassword(char const* url, char*& username, char*& password) { username = password = NULL; // by default do { // Parse the URL as "rtsp://<username>[:<password>]@<whatever>" char const* prefix = "rtsp://"; unsigned const prefixLength = 7; if (_strncasecmp(url, prefix, prefixLength) != 0) break; // Look for the ':' and '@': unsigned usernameIndex = prefixLength; unsigned colonIndex = 0, atIndex = 0; for (unsigned i = usernameIndex; url[i] != '\0' && url[i] != '/'; ++i) { if (url[i] == ':' && colonIndex == 0) { colonIndex = i; } else if (url[i] == '@') { atIndex = i; break; // we're done } } if (atIndex == 0) break; // no '@' found char* urlCopy = strDup(url); urlCopy[atIndex] = '\0'; if (colonIndex > 0) { urlCopy[colonIndex] = '\0'; password = strDup(&urlCopy[colonIndex+1]); } else { password = strDup(""); } username = strDup(&urlCopy[usernameIndex]); delete[] urlCopy; return True; } while (0); return False;}char*RTSPClient::createAuthenticatorString(Authenticator const* authenticator, char const* cmd, char const* url) { if (authenticator != NULL && authenticator->realm() != NULL && authenticator->nonce() != NULL && authenticator->username() != NULL && authenticator->password() != NULL) { // We've been provided a filled-in authenticator, so use it: char* const authFmt = "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n"; char const* response = authenticator->computeDigestResponse(cmd, url); unsigned authBufSize = strlen(authFmt) + strlen(authenticator->username()) + strlen(authenticator->realm()) + strlen(authenticator->nonce()) + strlen(url) + strlen(response); char* authenticatorStr = new char[authBufSize]; sprintf(authenticatorStr, authFmt, authenticator->username(), authenticator->realm(), authenticator->nonce(), url, response); authenticator->reclaimDigestResponse(response); return authenticatorStr; } return strDup("");}void RTSPClient::checkForAuthenticationFailure(unsigned responseCode, char*& nextLineStart, Authenticator* authenticator) { if (responseCode == 401 && authenticator != NULL) { // We have an authentication failure, so fill in "authenticator" // using the contents of a following "WWW-Authenticate:" line. // (Once we compute a 'response' for "authenticator", it can be
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?