怎麼理解p2p 打洞 stun ICE SDP rtp 協議之間的關係(二)

借用Licdoe的代碼來分析下ICE的實現

首先licode 用了兩套ice庫,不知道爲啥,nicer 和Libnicer ,但感覺比較偏重於libnicer,所有着重以Libnice爲主

 二者分家的地方在 DtlsTransport類的構造函數中

licode 的底層傳輸採用了dtls的協議,這塊不着重分析,知道就可以了。

下面開始

第一個問題:

ICE的線程模型

ICE代碼還沒看,但從Licode的應用來看,線程是由外面給出的,這個從ICE的使用說明可以看到:

具體使用情況也是需要傳進一個Loop,

第二個問題:

ICE的底層傳輸用的那一套

現在看來,ICE的底層庫,應該是本身自帶的Udp庫

第三個問題: ICE是數據封裝層,它和應用層的關係如何

ICE的上層應用是dtls ,證據如下

listerner被設置爲了dtls的實例,

dtl也是個中間層,主要負責數據加密解密,如果輸在從上層傳過來,dtls會直接給ice,代碼如下

當有數據從ICE上來是,會首先給dtls

void DtlsTransport::onIceData(packetPtr packet) {
  if (!running_) {
    return;
  }
  int len = packet->length;
  char *data = packet->data;
  unsigned int component_id = packet->comp;

  int length = len;
  SrtpChannel *srtp = srtp_.get();
  if (DtlsTransport::isDtlsPacket(data, len)) {
    ELOG_DEBUG("%s message: Received DTLS message, transportName: %s, componentId: %u",
               toLog(), transport_name.c_str(), component_id);
    if (component_id == 1) {
      std::lock_guard<std::mutex> guard(dtls_mutex);
      dtlsRtp->read(reinterpret_cast<unsigned char*>(data), len);
    } else {
      std::lock_guard<std::mutex> guard(dtls_mutex);
      dtlsRtcp->read(reinterpret_cast<unsigned char*>(data), len);
    }
    return;
  } else if (this->getTransportState() == TRANSPORT_READY) {
    std::shared_ptr<DataPacket> unprotect_packet = std::make_shared<DataPacket>(component_id,
      data, len, VIDEO_PACKET, packet->received_time_ms);

    if (dtlsRtcp != NULL && component_id == 2) {
      srtp = srtcp_.get();
    }
    if (srtp != NULL) {
      RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(unprotect_packet->data);
      if (chead->isRtcp()) {
        if (srtp->unprotectRtcp(unprotect_packet->data, &unprotect_packet->length) < 0) {
          return;
        }
      } else {
        if (srtp->unprotectRtp(unprotect_packet->data, &unprotect_packet->length) < 0) {
          return;
        }
      }
    } else {
      return;
    }

    if (length <= 0) {
      return;
    }
    if (auto listener = getTransportListener().lock()) {
      listener->onTransportData(unprotect_packet, this);
    }
  }
}

 

這段代碼首先判斷是否屬於dtls的包,如果是,那麼處理dtls,奇怪爲啥這裏分爲rtp和rtcp兩個動作

如果不是dtls的包,那麼首先解密rtp 

然後把解析出來的數據,傳給listener 

這個listener是什麼意思呢?

這個listerner是webrtcconnection的實例,這樣數據就流入到了webrtc裏面

可以看到數據進入到了media_stream裏面

這樣這個流程就結束了

所以,licode裏的協議棧順序爲:

UDP---ICE---DTLS----SRTP----RTP 

這樣的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章