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

📄 rtspclient.cpp

📁 H.264 RTSP 串流(live 555)視窗版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	unsigned extraHeadersSize = strlen(extraHeadersFmt)	  + strlen(fSessionCookie);	extraHeaders = new char[extraHeadersSize];	extraHeadersWereAllocated = True;	sprintf(extraHeaders, extraHeadersFmt,		fSessionCookie);      } else { // "POST"	protocolStr = "HTTP/1.0";		char const* const extraHeadersFmt =	  "x-sessioncookie: %s\r\n"	  "Content-Type: application/x-rtsp-tunnelled\r\n"	  "Pragma: no-cache\r\n"	  "Cache-Control: no-cache\r\n"	  "Content-Length: 32767\r\n"	  "Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n";	unsigned extraHeadersSize = strlen(extraHeadersFmt)	  + strlen(fSessionCookie);	extraHeaders = new char[extraHeadersSize];	extraHeadersWereAllocated = True;	sprintf(extraHeaders, extraHeadersFmt,		fSessionCookie);      }    } else { // "PLAY", "PAUSE", "TEARDOWN", "RECORD", "SET_PARAMETER", "GET_PARAMETER"      // 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;      }      char const* sessionId;      float originalScale;      if (request->session() != NULL) {	// Session-level operation	cmdURL = (char*)sessionURL(*request->session());	sessionId = fLastSessionId;	originalScale = request->session()->scale();      } else {	// Media-level operation	char const *prefix, *separator, *suffix;	constructSubsessionURL(*request->subsession(), prefix, separator, suffix);	cmdURL = new char[strlen(prefix) + strlen(separator) + strlen(suffix) + 1];	cmdURLWasAllocated = True;	sprintf(cmdURL, "%s%s%s", prefix, separator, suffix);		sessionId = request->subsession()->sessionId;	originalScale = request->subsession()->scale();      }      if (strcmp(request->commandName(), "PLAY") == 0) {	// Create "Session:", "Scale:", and "Range:" headers; these make up the 'extra headers':	char* sessionStr = createSessionString(sessionId);	char* scaleStr = createScaleString(request->scale(), originalScale);	char* rangeStr = createRangeString(request->start(), request->end());	extraHeaders = new char[strlen(sessionStr) + strlen(scaleStr) + strlen(rangeStr) + 1];	extraHeadersWereAllocated = True;	sprintf(extraHeaders, "%s%s%s", sessionStr, scaleStr, rangeStr);	delete[] sessionStr; delete[] scaleStr; delete[] rangeStr;      } else {	// Create a "Session:" header; this makes up our 'extra headers':	extraHeaders = createSessionString(sessionId);	extraHeadersWereAllocated = True;      }    }    char* authenticatorStr = createAuthenticatorString(request->commandName(), fBaseURL);    char const* const cmdFmt =      "%s %s %s\r\n"      "CSeq: %d\r\n"      "%s"      "%s"      "%s"      "%s"      "\r\n"      "%s";    unsigned cmdSize = strlen(cmdFmt)      + strlen(request->commandName()) + strlen(cmdURL) + strlen(protocolStr)      + 20 /* max int len */      + strlen(authenticatorStr)      + fUserAgentHeaderStrLen      + strlen(extraHeaders)      + strlen(contentLengthHeader)      + contentStrLen;    cmd = new char[cmdSize];    sprintf(cmd, cmdFmt,	    request->commandName(), cmdURL, protocolStr,	    request->cseq(),	    authenticatorStr,	    fUserAgentHeaderStr,            extraHeaders,	    contentLengthHeader,	    contentStr);    delete[] authenticatorStr;    if (cmdURLWasAllocated) delete[] cmdURL;    if (extraHeadersWereAllocated) delete[] extraHeaders;    if (contentLengthHeaderWasAllocated) delete[] contentLengthHeader;    if (fVerbosityLevel >= 1) envir() << "Sending request: " << cmd << "\n";    if (fTunnelOverHTTPPortNum != 0 && strcmp(request->commandName(), "GET") != 0 && strcmp(request->commandName(), "POST") != 0) {      // When we're tunneling RTSP-over-HTTP, we Base-64-encode the request before we send it.      // (However, we don't do this for the HTTP "GET" and "POST" commands that we use to set up the tunnel.)      char* origCmd = cmd;      cmd = base64Encode(origCmd, strlen(cmd));      if (fVerbosityLevel >= 1) envir() << "\tThe request was base-64 encoded to: " << cmd << "\n\n";      delete[] origCmd;    }    if (send(fOutputSocketNum, cmd, strlen(cmd), 0) < 0) {      char const* errFmt = "%s send() failed: ";      unsigned const errLength = strlen(errFmt) + strlen(request->commandName());      char* err = new char[errLength];      sprintf(err, errFmt, request->commandName());      envir().setResultErrMsg(err);      delete[] err;      break;    }    // The command send succeeded, so enqueue the request record, so that its response (when it comes) can be handled:    fRequestsAwaitingResponse.enqueue(request);    delete[] cmd;    return request->cseq();  } while (0);  // An error occurred, so call the response handler immediately (indicating the error):  delete[] cmd;  handleRequestError(request);  delete request;  return 0;}void RTSPClient::handleRequestError(RequestRecord* request) {  int resultCode = -envir().getErrno();  if (resultCode == 0) {    // Choose some generic error code instead:#if defined(__WIN32__) || defined(_WIN32) || defined(_QNX4)    resultCode = -WSAENOTCONN;#else    resultCode = -ENOTCONN;#endif  }  if (request->handler() != NULL) (*request->handler())(this, resultCode, strDup(envir().getResultMsg()));}Boolean RTSPClient::parseResponseCode(char const* line, unsigned& responseCode, char const*& responseString, Boolean& responseIsHTTP) {  responseIsHTTP = False; // by default  if (sscanf(line, "RTSP/%*s%u", &responseCode) != 1) {    if (sscanf(line, "HTTP/%*s%u", &responseCode) != 1) return False;    responseIsHTTP = True;    // Note: We check for HTTP responses as well as RTSP responses, both in order to setup RTSP-over-HTTP tunneling,    // and so that we get back a meaningful error if the client tried to mistakenly send a RTSP command to a HTTP-only server.  }  // Use everything after the RTSP/* as the response string:  responseString = line;  while (responseString[0] != '\0' && responseString[0] != ' '  && responseString[0] != '\t') ++responseString;  while (responseString[0] != '\0' && (responseString[0] == ' '  || responseString[0] == '\t')) ++responseString; // skip whitespace  return True;}void RTSPClient::handleIncomingRequest() {  // Parse the request string into command name and 'CSeq', then 'handle' the command (by responding that we don't support it):  char cmdName[RTSP_PARAM_STRING_MAX];  char urlPreSuffix[RTSP_PARAM_STRING_MAX];  char urlSuffix[RTSP_PARAM_STRING_MAX];  char cseq[RTSP_PARAM_STRING_MAX];  if (!parseRTSPRequestString(fResponseBuffer, fResponseBytesAlreadySeen,			      cmdName, sizeof cmdName,			      urlPreSuffix, sizeof urlPreSuffix,			      urlSuffix, sizeof urlSuffix,			      cseq, sizeof cseq)) {    return;  } else {    if (fVerbosityLevel >= 1) {      envir() << "Received incoming RTSP request: " << fResponseBuffer << "\n";    }    char tmpBuf[2*RTSP_PARAM_STRING_MAX];    snprintf((char*)tmpBuf, sizeof tmpBuf,             "RTSP/1.0 405 Method Not Allowed\r\nCSeq: %s\r\n\r\n", cseq);    send(fOutputSocketNum, tmpBuf, strlen(tmpBuf), 0);  }}Boolean RTSPClient::checkForHeader(char const* line, char const* headerName, unsigned headerNameLength, char const*& headerParams) {  if (_strncasecmp(line, headerName, headerNameLength) != 0) return False;  // The line begins with the desired header name.  Trim off any whitespace, and return the header parameters:  unsigned paramIndex = headerNameLength;  while (line[paramIndex] != '\0' && (line[paramIndex] == ' ' || line[paramIndex] == '\t')) ++paramIndex;  if (&line[paramIndex] == '\0') return False; // the header is assumed to be bad if it has no parameters  headerParams = &line[paramIndex];  return True;}Boolean RTSPClient::parseTransportParams(char const* paramsStr,					 char*& serverAddressStr, portNumBits& serverPortNum,					 unsigned char& rtpChannelId, unsigned char& rtcpChannelId) {  // Initialize the return parameters to 'not found' values:  serverAddressStr = NULL;  serverPortNum = 0;  rtpChannelId = rtcpChannelId = 0xFF;  char* foundServerAddressStr = NULL;  Boolean foundServerPortNum = False;  portNumBits clientPortNum = 0;  Boolean foundClientPortNum = False;  Boolean foundChannelIds = False;  unsigned rtpCid, rtcpCid;  Boolean isMulticast = True; // by default  char* foundDestinationStr = NULL;  portNumBits multicastPortNumRTP, multicastPortNumRTCP;  Boolean foundMulticastPortNum = False;  // Run through each of the parameters, looking for ones that we handle:  char const* fields = paramsStr;  char* field = strDupSize(fields);  while (sscanf(fields, "%[^;]", field) == 1) {    if (sscanf(field, "server_port=%hu", &serverPortNum) == 1) {      foundServerPortNum = True;    } else if (sscanf(field, "client_port=%hu", &clientPortNum) == 1) {      foundClientPortNum = True;    } else if (_strncasecmp(field, "source=", 7) == 0) {      delete[] foundServerAddressStr;      foundServerAddressStr = strDup(field+7);    } else if (sscanf(field, "interleaved=%u-%u", &rtpCid, &rtcpCid) == 2) {      rtpChannelId = (unsigned char)rtpCid;      rtcpChannelId = (unsigned char)rtcpCid;      foundChannelIds = True;    } else if (strcmp(field, "unicast") == 0) {      isMulticast = False;    } else if (_strncasecmp(field, "destination=", 12) == 0) {      delete[] foundDestinationStr;      foundDestinationStr = strDup(field+12);    } else if (sscanf(field, "port=%hu-%hu",		      &multicastPortNumRTP, &multicastPortNumRTCP) == 2) {      foundMulticastPortNum = True;    }    fields += strlen(field);    while (fields[0] == ';') ++fields; // skip over all leading ';' chars    if (fields[0] == '\0') break;  }  delete[] field;  // If we're multicast, and have a "destination=" (multicast) address, then use this  // as the 'server' address (because some weird servers don't specify the multicast  // address earlier, in the "DESCRIBE" response's SDP:  if (isMulticast && foundDestinationStr != NULL && foundMulticastPortNum) {    delete[] foundServerAddressStr;    serverAddressStr = foundDestinationStr;    serverPortNum = multicastPortNumRTP;    return True;  }  delete[] foundDestinationStr;  // We have a valid "Transport:" header if any of the following are true:  //   - We saw a "interleaved=" field, indicating RTP/RTCP-over-TCP streaming, or  //   - We saw a "server_port=" field, or  //   - We saw a "client_port=" field.  //     If we didn't also see a "server_port=" field, then the server port is assumed to be the same as the client port.  if (foundChannelIds || foundServerPortNum || foundClientPortNum) {    if (foundClientPortNum && !foundServerPortNum) {      serverPortNum = clientPortNum;    }    serverAddressStr = foundServerAddressStr;    return True;  }  delete[] foundServerAddressStr;  return False;}Boolean RTSPClient::parseScaleParam(char const* paramStr, float& scale) {  Locale l("C", LC_NUMERIC);  return sscanf(paramStr, "%f", &scale) == 1;}Boolean RTSPClient::parseRTPInfoParams(char const*& paramsStr, u_int16_t& seqNum, u_int32_t& timestamp) {  while (paramsStr[0] == ',') ++paramsStr;  // "paramsStr" now consists of a ';'-separated list of parameters, ending with ',' or '\0'.  char* field = strDupSize(paramsStr);  while (sscanf(paramsStr, "%[^;,]", field) == 1) {    if (sscanf(field, "seq=%hu", &seqNum) == 1 ||	sscanf(field, "rtptime=%u", &timestamp) == 1) {    }    paramsStr += strlen(field);    if (paramsStr[0] == '\0' || paramsStr[0] == ',') break;    // ASSERT: paramsStr[0] == ';'    ++paramsStr; // skip over the ';'  }  delete[] field;  return True;}Boolean RTSPClient::handleSETUPResponse(MediaSubsession& subsession, char const* sessionParamsStr, char const* transportParamsStr,                                        Boolean streamUsingTCP) {  char* sessionId = new char[responseBufferSize]; // ensures we have enough space  Boolean success = False;  do {    // Check for a session id:    if (sessionParamsStr == NULL || sscanf(sessionParamsStr, "%[^;]", sessionId) != 1) {      envir().setResultMsg("Missing or bad \"Session:\" header");      break;    }    subsession.sessionId = strDup(sessionId);    delete[] fLastSessionId; fLastSessionId = strDup(sessionId);    // Also look for an optional "; timeout = " parameter following this:    char const* afterSessionId = sessionParamsStr + strlen(sessionId);    int timeoutVal;    if (sscanf(afterSessionId, "; timeout = %d", &timeoutVal) == 1) {      fSessionTimeoutParameter = timeoutVal;    }    // Parse the "Transport:" header parameters:    char* serverAddressStr;    portNumBits serverPortNum;    unsigned char rtpChannelId, rtcpChannelId;    if (!parseTransportParams(transportParamsStr, serverAddressStr, serverPortNum, rtpChannelId, rtcpChannelId)) {

⌨️ 快捷键说明

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