Пример #1
0
int streamxmit_sendto(STREAM_RTP_DEST_T *pDest, const unsigned char *data, unsigned int len, 
                      int rtcp, int keyframe, int drop) {
  int rc = 0;
  NETIO_SOCK_T *pnetsock = NULL;
  const unsigned char *pData = data;
  PKTQ_EXTRADATA_T qXtra;
  STREAMXMIT_PKT_HDR_T pktHdr;
  unsigned char encBuf[PACKETGEN_PKT_UDP_DATA_SZ];

  //
  // If we're using DTLS-SRTP over audio/video mux (on same RTP port) then we need to choose
  // the right socket which has completed the DTLS handshake
  //
  if(rtcp) {
    pnetsock = STREAM_RTCP_PNETIOSOCK(*pDest);
  } else {
    pnetsock = STREAM_RTP_PNETIOSOCK(*pDest);
  }

  //LOG(X_DEBUG("STREAMXMIT_SENDTO len:%d, rtcp:%d, drop:%d, pDest: 0x%x, srtp:0x%x, pSrtpShared: 0x%x, 0x%x, lenK:%d"), len, rtcp, drop, pDest, &pDest->srtps[rtcp ? 1 : 0], pDest->srtps[rtcp ? 1 : 0].pSrtpShared, SRTP_CTXT_PTR(&pDest->srtps[rtcp ? 1 : 0]), SRTP_CTXT_PTR(&pDest->srtps[rtcp ? 1 : 0])->k.lenKey);LOGHEX_DEBUG(data, MIN(16, len));

  if((rc = srtp_dtls_protect(pnetsock, data, len, encBuf, sizeof(encBuf),
                      (const struct sockaddr *) (rtcp ? &pDest->saDstsRtcp : &pDest->saDsts), 
                      pDest->srtps[rtcp ? 1 : 0].pSrtpShared,
                      rtcp ? SENDTO_PKT_TYPE_RTCP : SENDTO_PKT_TYPE_RTP)) < 0) {
    if(rc == -2) {
      // DTLS handshake not complete
      return 0;
    } else {
      return -1;
    }
  } else if(rc > 0) {
    pData = encBuf;
    len = rc;
  }

  //
  // Queue the packet for async sending
  //
  if(pDest->asyncQ.pQ && (pDest->asyncQ.doAsyncXmit || (!rtcp && pDest->asyncQ.doRtcpNack))) {

    memset(&qXtra, 0, sizeof(qXtra));
    memset(&pktHdr, 0, sizeof(pktHdr));
    pktHdr.flags = 0;
    pktHdr.tvCreate = timer_GetTime();
    if(!pDest->asyncQ.doAsyncXmit) {
      pktHdr.tvXmit = pktHdr.tvCreate;
    }
    if(!(pktHdr.rtcp = rtcp)) {
      pktHdr.seqNum = htons(pDest->pRtpMulti->pRtp->sequence_num);
      pktHdr.timeStamp = htonl(pDest->pRtpMulti->pRtp->timeStamp);
      pktHdr.keyframe = keyframe;
    }
    qXtra.pQUserData = &pktHdr;

    pthread_mutex_lock(&pDest->asyncQ.mtx);

    if(!pDest->asyncQ.isCurPktKeyframe && keyframe) {
      pDest->asyncQ.haveLastKeyframeSeqNumStart = 1;
      pDest->asyncQ.lastKeyframeSeqNumStart = pktHdr.seqNum;
      //LOG(X_DEBUG("NACK - GOP start at packet %d"), pktHdr.seqNum);
    }

    if(pktqueue_addpkt(pDest->asyncQ.pQ, pData, len, &qXtra,
       (!pDest->asyncQ.isCurPktKeyframe && keyframe ? 1 : 0)) != PKTQUEUE_RC_OK) {
      pthread_mutex_unlock(&pDest->asyncQ.mtx);
      return -1;
    }
    //LOG(X_DEBUG("NACK q rd:[%d]/%d, wr:%d"), pDest->asyncQ.pQ->idxRd, pDest->asyncQ.pQ->cfg.maxPkts, pDest->asyncQ.pQ->idxWr);
    pDest->asyncQ.isCurPktKeyframe = keyframe;

    pthread_mutex_unlock(&pDest->asyncQ.mtx);
    rc = len;

    //pktqueue_dump(pDest->asyncQ.pQ,  pktqueue_cb_streamxmit_dump_pkthdr);
  } 

  if(!pDest->asyncQ.doAsyncXmit && !drop) {
    if((rc = srtp_sendto(pnetsock, (void *) pData, len, 0, 
                         (const struct sockaddr *) (rtcp ? &pDest->saDstsRtcp : &pDest->saDsts), NULL, 
                         rtcp ? SENDTO_PKT_TYPE_RTCP : SENDTO_PKT_TYPE_RTP, 1)) < 0) {
      return -1;
    }

  } else if(drop) {
    rc = len;
  }

  if(pDest->pstreamStats) {
    stream_stats_addPktSample(pDest->pstreamStats, &pDest->streamStatsMtx, len, !rtcp);
  }

  return rc;
}
Пример #2
0
static int do_dtls_handshakes(STREAM_XMIT_NODE_T *pStream, 
                              TIME_VAL tmstart,
                              TIME_VAL *ptmstartRtpHandshakeDone,
                              NET_PROGRESS_T *progRtp, 
                              NET_PROGRESS_T *progRtcp,
                              const DTLS_TIMEOUT_CFG_T *pdtlsTimeouts) {
  int idxDest, idxDestPrior;
  STREAM_RTP_DEST_T *pDest = NULL;
  STREAM_RTP_DEST_T *pDestPrior = NULL;
  STREAM_RTP_MULTI_T *pRtpMulti = NULL;
  STREAM_RTP_MULTI_T *pRtpMultiPrior = NULL;
  int sameRtpSock, sameRtcpSock;
  TIME_VAL tmnow;

  //LOG(X_DEBUG("do_dtls_handshakes"));
  if(progRtp) {
    memset(progRtp, 0, sizeof(NET_PROGRESS_T));
  }
  if(progRtcp) {
    memset(progRtcp, 0, sizeof(NET_PROGRESS_T));
  }

  pRtpMulti = pStream->pRtpMulti;
  while(pRtpMulti) {

    if(g_proc_exit) {
      return -1;
    } else if(*pStream->prunning != STREAMER_STATE_RUNNING) {
      continue; 
    }

    //
    // Check if the RTP socket is pending creation by the capture_socket  thread
    //
    if(progRtp && pRtpMulti->pStreamerCfg->sharedCtxt.state == STREAMER_SHARED_STATE_PENDING_CREATE) {
      progRtp->numTotal++;
      continue;
    }

    for(idxDest = 0; idxDest < pRtpMulti->numDests; idxDest++) {

      if(!(pDest = &pRtpMulti->pdests[idxDest]) || !pDest->isactive) {
        continue;
      }

      sameRtpSock = sameRtcpSock = 0;

      if(pRtpMultiPrior) {
        //
        // Check RTP video/audio multiplexing over the same port
        //
        for(idxDestPrior = 0; idxDestPrior < pRtpMultiPrior->numDests; idxDestPrior++) {

          if(!(pDestPrior = &pRtpMultiPrior->pdests[idxDestPrior]) || !pDestPrior->isactive) {
            continue;
          }

          if(pDestPrior->saDsts.sin_port == pDest->saDsts.sin_port) {
            sameRtpSock = 1;
          }
          if(pDestPrior->saDstsRtcp.sin_port == pDest->saDstsRtcp.sin_port) {
            sameRtcpSock = 1;
          }
        }
      }


      //if(pDest->pRtpMulti->pStreamerCfg->xcode.vid.pip.active) 
      //LOG(X_DEBUG("SAMERTPSOCK:%D, SAMERTCPSOCK:%d"), sameRtpSock, sameRtcpSock);

      if(progRtp && (STREAM_RTP_PNETIOSOCK(*pDest)->flags & NETIO_FLAG_SSL_DTLS) && !sameRtpSock &&
         STREAM_RTP_FD(*pDest) != INVALID_SOCKET) {
        //if(pDest->pRtpMulti->pStreamerCfg->xcode.vid.pip.active) 
        //LOG(X_DEBUG("DO_DTLS_HS RTP pnetsock.state: %d, flags:0x%x"), STREAM_RTP_PNETIOSOCK(*pDest)->ssl.state, STREAM_RTP_PNETIOSOCK(*pDest)->flags);

        do_dtls_handshake(STREAM_RTP_PNETIOSOCK(*pDest), &pDest->saDsts, progRtp);
      }

      if(progRtcp && STREAM_RTP_FD(*pDest) != STREAM_RTCP_FD(*pDest) &&
        (STREAM_RTCP_PNETIOSOCK(*pDest)->flags & NETIO_FLAG_SSL_DTLS) && !sameRtcpSock &&
         STREAM_RTCP_FD(*pDest) != INVALID_SOCKET) {
        //if(pDest->pRtpMulti->pStreamerCfg->xcode.vid.pip.active) 
        //LOG(X_DEBUG("DO_DTLS_HS RCTP pnetsock.state: %d, flags:0x%x"), STREAM_RTCP_PNETIOSOCK(*pDest)->ssl.state, STREAM_RTCP_PNETIOSOCK(*pDest)->flags);

        do_dtls_handshake(STREAM_RTCP_PNETIOSOCK(*pDest), &pDest->saDstsRtcp, progRtcp);
      }

    } // end of for(idxDest..

    pRtpMultiPrior = pRtpMulti;
    pRtpMulti = pRtpMulti->pnext;
  } // end of while(pRtpMulti...

  //LOG(X_DEBUG("streamer_do_dtls_handshake done rtp-numDtls:%d, rtp-numDtlsCompleted:%d, rtcp-numDtls:%d, rtcp-numDtlsCompleted:%d"), progRtp ? progRtp->numTotal : -1, progRtp ? progRtp->numCompleted : -1, progRtcp->numTotal, progRtcp->numCompleted);

  if(!progRtp) {
    return 0;
  } if(progRtp->numError > 0) {
    return -1;
  } else if(progRtp->numCompleted == progRtp->numTotal) {

    if(*ptmstartRtpHandshakeDone == 0) {
      *ptmstartRtpHandshakeDone = timer_GetTime();
    }

    if(progRtcp->numTotal - progRtcp->numCompleted > 0 &&
      ((tmnow = timer_GetTime()) - *ptmstartRtpHandshakeDone) / TIME_VAL_MS < pdtlsTimeouts->handshakeRtcpAdditionalMs) {
      return progRtcp->numTotal - progRtcp->numCompleted;
    } else {
      return 0;
    }

  } else {

    if(((tmnow = timer_GetTime()) - tmstart) / TIME_VAL_MS > pdtlsTimeouts->handshakeRtpTimeoutMs) {
      LOG(X_ERROR("Aborting DTLS RTP handshake(s) after %lld ms.  %d/%d completed"), 
          (tmnow - tmstart) / TIME_VAL_MS, progRtp->numCompleted, progRtp->numTotal);
      return -1;
    } else {
      return progRtp->numTotal - progRtp->numCompleted;
    }

  }

}