📄 rtspclient.cpp
字号:
+ 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(NoSessionErr); 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(NoSessionErr); 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(NoSessionErr); 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;}static const char base64Char[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";static char* base64Encode(char const* orig) { if (orig == NULL) return NULL; unsigned const origLength = strlen(orig); unsigned const numOrig24BitValues = origLength/3; Boolean havePadding = origLength > numOrig24BitValues*3; Boolean havePadding2 = origLength == numOrig24BitValues*3 + 2; unsigned const numResultBytes = 4*(numOrig24BitValues + havePadding); char* result = new char[numResultBytes+1]; // allow for trailing '\0' // Map each full group of 3 input bytes into 4 output base-64 characters: unsigned i; for (i = 0; i < numOrig24BitValues; ++i) { result[4*i+0] = base64Char[(orig[3*i]>>2)&0x3F]; result[4*i+1] = base64Char[(((orig[3*i]&0x3)<<4) | (orig[3*i+1]>>4))&0x3F]; result[4*i+2] = base64Char[((orig[3*i+1]<<2) | (orig[3*i+2]>>6))&0x3F]; result[4*i+3] = base64Char[orig[3*i+2]&0x3F]; } // Now, take padding into account. (Note: i == numOrig24BitValues) if (havePadding) { result[4*i+0] = base64Char[(orig[3*i]>>2)&0x3F]; result[4*i+1] = base64Char[(((orig[3*i]&0x3)<<4) | (orig[3*i+1]>>4))&0x3F]; if (havePadding2) { result[4*i+2] = base64Char[(orig[3*i+1]<<2)&0x3F]; } else { result[4*i+2] = '='; } result[4*i+3] = '='; } result[numResultBytes] = '\0'; return result;}char*RTSPClient::createAuthenticatorString(Authenticator const* authenticator, char const* cmd, char const* url) { if (authenticator != NULL && authenticator->realm() != NULL && authenticator->username() != NULL && authenticator->password() != NULL) { // We've been provided a filled-in authenticator, so use it: char* authenticatorStr; if (authenticator->nonce() != NULL) { // Digest authentication char* const authFmt = "Authorization: Digest username=\"%s\", realm=\"%s\", " "nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -