⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtspclient.cpp

📁 c++实现的流媒体库,和mplayer结合就可以实现多媒体的网络播放,属于开源项目,很值得研究.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    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* sessURL = sessionURL(session);    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(sessURL)      + 20 /* max int len */      + strlen(fLastSessionId)      + strlen(authenticatorStr)      + fUserAgentHeaderStrSize;    cmd = new char[cmdSize];    sprintf(cmd, cmdFmt,	    sessURL,	    ++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;            // Run through each subsession, deleting its "sessionId":      MediaSubsessionIterator iter(session);      MediaSubsession* subsession;      while ((subsession = iter.next()) != NULL) {	delete[] (char*)subsession->sessionId;	subsession->sessionId = NULL;      }      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, Authenticator* authenticator) {  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:      fServerAddress = *(unsigned*)(destAddress.data());      MAKE_SOCKADDR_IN(remoteName, fServerAddress, htons(destPortNum));      if (connect(fInputSocketNum, (struct sockaddr*)&remoteName, sizeof remoteName)	  != 0) {	envir().setResultErrMsg("connect() failed: ");	break;      }            if (fTunnelOverHTTPPortNum != 0 && !setupHTTPTunneling(urlSuffix, authenticator)) 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>]@"    // (Note that this code fails if <password> contains '@' or '/', but    // given that these characters can also appear in <etc>, there seems to    // be no way of unambiguously parsing that situation.)    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->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";      char const* response = authenticator->computeDigestResponse(cmd, url);      unsigned authBufSize = strlen(authFmt)	+ strlen(authenticator->username()) + strlen(authenticator->realm())	+ strlen(authenticator->nonce()) + strlen(url) + strlen(response);      authenticatorStr = new char[authBufSize];      sprintf(authenticatorStr, authFmt,	      authenticator->username(), authenticator->realm(),	      authenticator->nonce(), url, response);      authenticator->reclaimDigestResponse(response);    } else { // Basic authentication      char* const authFmt = "Authorization: Basic %s\r\n";      unsigned usernamePasswordLength = strlen(authenticator->username()) + 1 + strlen(authenticator->password());      char* usernamePassword = new char[usernamePasswordLength+1];      sprintf(usernamePassword, "%s:%s", authenticator->username(), authenticator->password());      char* response = base64Encode(usernamePassword, usernamePasswordLength);      unsigned authBufSize = strlen(authFmt) + strlen(response);      authenticatorStr = new char[authBufSize];      sprintf(authenticatorStr, authFmt, response);      delete[] response; delete[] usernamePassword;    }    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    //  used in a subsequent request - that will hopefully succeed.)    char* lineStart;    while (1) {      lineStart = nextLineStart;      if (lineStart == NULL) break;      nextLineStart = getLine(lineStart);      if (lineStart[0] == '\0') break; // this is a blank line      char* realm = strDupSize(lineStart);      char* nonce = strDupSize(lineStart);      Boolean foundAuthenticateHeader = False;      if (sscanf(lineStart, "WWW-Authenticate: Digest realm=\"%[^\"]\", nonce=\"%[^\"]\"",		 realm, nonce) == 2) {	authenticator->setRealmAndNonce(realm, nonce);	foundAuthenticateHeader = True;      } else if (sscanf(lineStart, "WWW-Authenticate: Basic realm=\"%[^\"]\"",		 realm) == 1) {	authenticator->setRealmAndNonce(realm, NULL); // Basic authentication	foundAuthenticateHeader = True;      }      delete[] realm; delete[] nonce;      if (foundAuthenticateHeader) break;    }   }}Boolean RTSPClient::sendRequest(char const* requestString, char const* tag,				Boolean base64EncodeIfOverHTTP) {  if (fVerbosityLevel >= 1) {    envir() << "Sending request: " << requestString << "\n";  }  char* newRequestString = NULL;  if (fTunnelOverHTTPPortNum != 0 && base64EncodeIfOverHTTP) {    requestString = newRequestString = base64Encode(requestString, strlen(requestString));    if (fVerbosityLevel >= 1) {      envir() << "\tThe request was base-64 encoded to: " << requestString << "\n\n";    }  }  Boolean result    = send(fOutputSocketNum, requestString, strlen(requestString), 0) >= 0;  delete[] newRequestString;  if (!result) {    if (tag == NULL) tag = "";    char const* errFmt = "%s send() failed: ";    unsigned const errLength = strlen(errFmt) + strlen(tag);    char* err = new char[errLength];    sprintf(err, errFmt, tag);    envir().setResultErrMsg(err);    delete[] err;  }  return result;}Boolean RTSPClient::getResponse(char const* tag,				unsigned& bytesRead, unsigned& responseCode,				char*& firstLine, char*& nextLineStart,				Boolean checkFor200Response) {  do {    char* readBuf = fResponseBuffer;    bytesRead = getResponse1(readBuf, fResponseBufferSize);    if (bytesRead == 0) {      envir().setResultErrMsg("Failed to read response: ");      break;    }    if (fVerbosityLevel >= 1) { 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -