openRtsp分析2

在上一篇中分析了SingleStep,可以看到在openConnection的时候传给fSchedler的HandlerProc是connectionHandler。在SingleStep中看到检测到select中write准备就绪。即跳到connectionHandler

void RTSPClient::connectionHandler(void* instance, int /*mask*/) {
  RTSPClient* client = (RTSPClient*)instance;
  client->connectionHandler1();
}

void RTSPClient::connectionHandler1() {
  // Restore normal handling on our sockets:
  envir().taskScheduler().disableBackgroundHandling(fOutputSocketNum);
  envir().taskScheduler().setBackgroundHandling(fInputSocketNum, SOCKET_READABLE,
						(TaskScheduler::BackgroundHandlerProc*)&incomingDataHandler, this);

  // Move all requests awaiting connection into a new, temporary queue, to clear "fRequestsAwaitingConnection"
  // (so that "sendRequest()" doesn't get confused by "fRequestsAwaitingConnection" being nonempty, and enqueue them all over again).
  RequestQueue tmpRequestQueue(fRequestsAwaitingConnection);
  RequestRecord* request;

  // Find out whether the connection succeeded or failed:
  do {
    int err = 0;
    SOCKLEN_T len = sizeof err;
    if (getsockopt(fInputSocketNum, SOL_SOCKET, SO_ERROR, (char*)&err, &len) < 0 || err != 0) {
      envir().setResultErrMsg("Connection to server failed: ", err);
      if (fVerbosityLevel >= 1) envir() << "..." << envir().getResultMsg() << "\n";
      break;
    }

    // The connection succeeded.  If the connection came about from an attempt to set up RTSP-over-HTTP, finish this now:
    if (fVerbosityLevel >= 1) envir() << "...remote connection opened\n";
    if (fHTTPTunnelingConnectionIsPending && !setupHTTPTunneling2()) break;

    // Resume sending all pending requests:
    while ((request = tmpRequestQueue.dequeue()) != NULL) {
      sendRequest(request);
    }
    return;
  } while (0);

  // An error occurred.  Tell all pending requests about the error:
  resetTCPSockets(); // do this now, in case an error handler deletes "this"
  while ((request = tmpRequestQueue.dequeue()) != NULL) {
    handleRequestError(request);
    delete request;
  }
}

上面的代码中先清除掉connect Handing然后添加上read set ,检测到connect执行成功,将上次fRequestsAwaitingConnection出列,如果有未执行的request会重新执行sendRequest执行。在上次执行sendRequest的时候那个request是option的发送请求。这里就先再次进入sendRequest先通过commandName判断要发送什么命令。option中可以看到什么都没执行然后就是发送命令的拼接。然后就执行send将cmd发送出去。至此发送option的全部动作已经完成,下面我们再来看option命令respone的接收。

在connectionHandler1()中我们看到把fInputSocketNum加入到了SOCKET_READABLE集中,回调函数是incomingDataHandler。同样SingleStep 中select有read的时候会调用这个回调函数。现在来看看

void RTSPClient::incomingDataHandler(void* instance, int /*mask*/) {
  RTSPClient* client = (RTSPClient*)instance;
  client->incomingDataHandler1();
}

void RTSPClient::incomingDataHandler1() {
  struct sockaddr_in dummy; // 'from' address - not used

  int bytesRead = readSocket(envir(), fInputSocketNum, (unsigned char*)&fResponseBuffer[fResponseBytesAlreadySeen], fResponseBufferBytesLeft, dummy);
  handleResponseBytes(bytesRead);
}

readsocket没什么可看的,就是执行recvfrom接收字节到fResponseBuffer中。然后执行的就是handleResponseBytes,可以看到handleResponseBytes中的内容很多,主要是对response的分析。主要看到最后有这句代码:

if (foundRequest != NULL && foundRequest->handler() != NULL) {
      int resultCode;
      char* resultString;
      if (responseSuccess) {
	if (responseCode == 200) {
	  resultCode = 0;
	  resultString = numBodyBytes > 0 ? strDup(bodyStart) : strDup(publicParamsStr);
          // Note: The "strDup(bodyStart)" call assumes that the body is encoded without interior '\0' bytes
	} else {
	  resultCode = responseCode;
	  resultString = strDup(responseStr);
	  envir().setResultMsg(responseStr);
	}
	(*foundRequest->handler())(this, resultCode, resultString);
      } else {
	// An error occurred parsing the response, so call the handler, indicating an error:
	handleRequestError(foundRequest);
      }
    }

这里面的(*foundRequest->handler())(this, resultCode, resultString);就是执行 getOptions(continueAfterOPTIONS);中的continueAfterOPTIONS。

通过对option命令的发送和接收可以看到其他的命令的发送和接收是差不多的流程,详细过程就不一一列出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值