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 + -
显示快捷键?