怎么理解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 

这样的


版权声明:本文为ddr77原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。