Example #1
0
static void srvlisten_rtmplive_proc(void *pArg) {

  SRV_LISTENER_CFG_T *pListenCfg = (SRV_LISTENER_CFG_T *) pArg;
  NETIO_SOCK_T netsocksrv;
  struct sockaddr_in  sa;
  int rc = 0;
  char buf[SAFE_INET_NTOA_LEN_MAX];

  logutil_tid_add(pthread_self(), pListenCfg->tid_tag);

  memset(&sa, 0, sizeof(sa));
  memset(&netsocksrv, 0, sizeof(netsocksrv));
  sa.sin_family = PF_INET;
  sa.sin_addr = pListenCfg->sain.sin_addr;
  sa.sin_port = pListenCfg->sain.sin_port;
  netsocksrv.flags = pListenCfg->netflags;

  if((NETIOSOCK_FD(netsocksrv) = net_listen(&sa, 5)) == INVALID_SOCKET) {
    logutil_tid_remove(pthread_self());
    return;
  }

  pthread_mutex_lock(&pListenCfg->mtx);
  pListenCfg->pnetsockSrv = &netsocksrv; 
  pthread_mutex_unlock(&pListenCfg->mtx);

  LOG(X_INFO("rtmp %sserver available at rtmp://%s:%d max:%d"), 
           ((pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ? "(SSL) " : ""), 
           net_inet_ntoa(sa.sin_addr, buf), ntohs(sa.sin_port), pListenCfg->max);

  //
  // Service any client connections on the live listening port
  //
  rc = srvlisten_loop(pListenCfg, srv_rtmp_proc);

  pthread_mutex_lock(&pListenCfg->mtx);
  pListenCfg->pnetsockSrv = NULL; 
  netio_closesocket(&netsocksrv);
  pthread_mutex_unlock(&pListenCfg->mtx);

  LOG(X_WARNING("rtmp listener thread exiting with code: %d"), rc);

  logutil_tid_remove(pthread_self());

  return;
}
Example #2
0
int capture_parseLocalAddr(const char *localAddrStr, SOCKET_LIST_T *pSockList) {

  int numPorts = 0;
  struct sockaddr_storage localAddr;
  unsigned short localPorts[SOCKET_LIST_MAX];
  size_t idx;
  int rc = -1;

  if(!localAddrStr || !pSockList) {
    return -1; 
  }

  memset(pSockList, 0, sizeof(SOCKET_LIST_T));
  memset(&localAddr, 0, sizeof(localAddr));

  if((numPorts = parseIpPortStr(localAddrStr, &localAddr, localPorts, SOCKET_LIST_MAX, 1)) > 0) {

    for(idx = 0; idx < sizeof(pSockList->netsockets) / sizeof(pSockList->netsockets[0]); idx++) {

      memset(&pSockList->salist[idx], 0, sizeof(pSockList->salist[idx]));
      NETIOSOCK_FD(pSockList->netsockets[idx]) = INVALID_SOCKET;  

      if(idx < (size_t) numPorts) {
        memcpy(&pSockList->salist[idx], &localAddr, sizeof(pSockList->salist[idx]));
        INET_PORT(pSockList->salist[idx]) = htons(localPorts[idx]);
 
        //if(rtcp) {
        //  memcpy(&pSockList->salistRtcp[idx], &pSockList->salist[idx], sizeof(pSockList->salistRtcp[idx]));
        //  pSockList->salistRtcp[idx].sin_port =
        //                RTCP_PORT_FROM_RTP(htons(pSockList->salistRtcp[idx].sin_port));
        //}
      }
    }
    pSockList->numSockets = numPorts;

    rc = 1;
  } else if(numPorts == 0) {

    // The given localAddrStr string could be a name of a local interface
    rc = 0;
  } 

  return rc;
}
Example #3
0
int srvlisten_loop(SRV_LISTENER_CFG_T *pListenCfg, void *thread_func) {

  int salen;
  THREAD_FUNC_WRAPPER_ARG_T wrapArg;
  CLIENT_CONN_T *pConn;
  SOCKET_DESCR_T sdclient;
  int rc = -1;
  const char *s;
  //pthread_cond_t cond;
  pthread_mutex_t mtx;
  TIME_VAL tv0, tv1;
  char tmp[128];

#if defined(__APPLE__) 
  int sockopt = 0;
#endif // __APPLE__

  if(!pListenCfg || !pListenCfg->pnetsockSrv || !pListenCfg->pConnPool || !thread_func || 
     pListenCfg->pConnPool->numElements <= 0) {
    return -1;
  }

  //memset(&saSrv, 0, sizeof(saSrv));
  memset(&sdclient.netsocket, 0, sizeof(sdclient.netsocket));
  //salen = sizeof(saSrv);

  //if(getsockname(pListenCfg->pnetsockSrv->sock, (struct sockaddr *) &saSrv,  (socklen_t *) &salen) != 0) {
  //  LOG(X_ERROR("getsockopt failed on server socket"));
  //}

  pthread_mutex_init(&mtx, NULL);
  //pthread_cond_init(&cond, NULL);

  while(!g_proc_exit) {

    salen = sizeof(sdclient.sa);
    if((NETIOSOCK_FD(sdclient.netsocket) = 
                 accept(PNETIOSOCK_FD(pListenCfg->pnetsockSrv), (struct sockaddr *) &sdclient.sa, 
                                      (socklen_t *) &salen)) == INVALID_SOCKET) {
      if(!g_proc_exit) {
        LOG(X_ERROR("%saccept failed on %s:%d"), 
             ((pListenCfg->pnetsockSrv->flags & NETIO_FLAG_SSL_TLS) ? "SSL " : ""),
                 //inet_ntoa(saSrv.sin_addr), ntohs(saSrv.sin_port));
                 FORMAT_NETADDR(pListenCfg->sa, tmp, sizeof(tmp)), ntohs(INET_PORT(pListenCfg->sa)));
      }
      break;
    }

    if(g_proc_exit) {
      break;
    }

    sdclient.netsocket.flags = pListenCfg->pnetsockSrv->flags;

    //
    // Find an available client thread to process the client request
    //
    if((pConn = (CLIENT_CONN_T *) pool_get(pListenCfg->pConnPool)) == NULL) {
      LOG(X_WARNING("No available connection for %s:%d (max:%d) on port %d"), 
           FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)), ntohs(INET_PORT(sdclient.sa)), 
           pListenCfg->pConnPool->numElements, ntohs(INET_PORT(pListenCfg->sa)));

      netio_closesocket(&sdclient.netsocket);
      continue;
    }

#if defined(__APPLE__) 
    sockopt = 1;
    if(setsockopt(NETIOSOCK_FD(sdclient.netsocket), SOL_SOCKET, SO_NOSIGPIPE,
                 (char*) &sockopt, sizeof(sockopt)) != 0) {
      LOG(X_ERROR("Failed to set SO_NOSIGPIPE"));
    }
#endif // __APPLE__

    //pConn->psrvsaListen = &saSrv;
    //memcpy(&pConn->srvsaListen, &saSrv, sizeof(pConn->srvsaListen));

    LOG(X_DEBUG("Accepted connection on port %d from %s:%d"), htons(INET_PORT(pListenCfg->sa)), 
        FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)), htons(INET_PORT(sdclient.sa)));

    pthread_attr_init(&pConn->attr);
    pthread_attr_setdetachstate(&pConn->attr, PTHREAD_CREATE_DETACHED);
    memset(&pConn->sd.netsocket, 0, sizeof(pConn->sd.netsocket));
    NETIO_SET(pConn->sd.netsocket, sdclient.netsocket);
    memcpy(&pConn->sd.sa, &sdclient.sa, INET_SIZE(sdclient));
    pConn->pListenCfg = pListenCfg;
    NETIOSOCK_FD(sdclient.netsocket) = INVALID_SOCKET;

    wrapArg.thread_func = thread_func;
    wrapArg.pConnPool = pListenCfg->pConnPool;
    wrapArg.pConn = pConn;
    wrapArg.flags = 1;
    wrapArg.tid_tag[0] = '\0';
    if((s = logutil_tid_lookup(pthread_self(), 0)) && s[0] != '\0') {
      snprintf(wrapArg.tid_tag, sizeof(wrapArg.tid_tag), "%s-%u", s, pConn->pool.id);
    }
    //wrapArg.pcond = &cond;

  //fprintf(stderr, "%d CALLING wrap: 0x%x pConn:0x%x\n", pthread_self(), &wrapArg, wrapArg.pConn);

    if((rc = pthread_create(&pConn->ptd,
                    &pConn->attr,
                    (void *) thread_func_wrapper,
                    (void *) &wrapArg)) != 0) {
      LOG(X_ERROR("Unable to create connection handler thread on port %d from %s:%d (%d %s)"), 
          htons(INET_PORT(pListenCfg->sa)), FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)),
          htons(INET_PORT(sdclient.sa)), rc, strerror(rc));
      netio_closesocket(&pConn->sd.netsocket);
      pool_return(pListenCfg->pConnPool, &pConn->pool);
      wrapArg.flags = 0;
      //pthread_cond_broadcast(&cond);
      break;
    }

    pthread_attr_destroy(&pConn->attr);

    //
    // be careful not to reuse the same wrapArg instance 
    // since the stack variable arguments could get
    // overwritten by the next loop iteration, before the thread proc is 
    // invoked
    //
    //fprintf(stderr, "wait start\n");
    tv0 = timer_GetTime();
    //if(wrapArg.flags == 1) {

      //
      // It seems that calling pthread_cond_wait here to check if the thread creation is
      // complete is not completely reliable and portable, so we do the lame way 
      // of sleeping and polling.
      //
      //pthread_cond_wait(&cond, &mtx);

      while(wrapArg.flags == 1) {
        usleep(100);
        if(((tv1 = timer_GetTime()) - tv0) / TIME_VAL_MS > 1000) {
          LOG(X_WARNING("Abandoning wait for connection thread start on port %d from %s:%d"),
               htons(INET_PORT(pListenCfg->sa)),
              FORMAT_NETADDR(pListenCfg->sa, tmp, sizeof(tmp)), ntohs(INET_PORT(pListenCfg->sa)));
          break;
        } 
      }
      //fprintf(stderr, "THREAD STARTED AFTER %lld ns\n", (timer_GetTime() - tv0));
    //}

    //fprintf(stderr, "wait done\n");

    //while(wrapArg.flag == 1) {
    //  usleep(10000); 
    //}

  }

  //pthread_cond_destroy(&cond);
  pthread_mutex_destroy(&mtx);

  return rc;
}
Example #4
0
static void srvlisten_media_proc(void *pArg) {

  SRV_LISTENER_CFG_T *pListenCfg = (SRV_LISTENER_CFG_T *) pArg;
  NETIO_SOCK_T netsocksrv;
  struct sockaddr_storage sa;
  CLIENT_CONN_T *pConnTmp;
  char tmp[128];
  char bufses[32];
  const int backlog = NET_BACKLOG_DEFAULT;
  unsigned int tsMax = 0;
  unsigned int flvMax = 0;
  unsigned int mkvMax = 0;
  unsigned int rtmpMax = 0;
  unsigned int rtspMax = 0;
  int haveAuth = 0;
  int haveRtmpAuth = 0;
  int haveRtspAuth = 0;
  int haveToken = 0;
  int rc = 0;

  logutil_tid_add(pthread_self(), pListenCfg->tid_tag);

  if((pListenCfg->urlCapabilities & (URL_CAP_TSLIVE | URL_CAP_TSHTTPLIVE | URL_CAP_FLVLIVE |
                                     URL_CAP_MKVLIVE | URL_CAP_LIVE | URL_CAP_STATUS | URL_CAP_MOOFLIVE |
                                     URL_CAP_PIP | URL_CAP_CONFIG | URL_CAP_BROADCAST |
                                     URL_CAP_RTMPLIVE | URL_CAP_RTMPTLIVE | URL_CAP_RTSPLIVE)) == 0) {

    LOG(X_WARNING("Server listener exiting because no capabilities enabled on %s:%d"),
         FORMAT_NETADDR(pListenCfg->sa, tmp, sizeof(tmp)), ntohs(INET_PORT(pListenCfg->sa)));
    logutil_tid_remove(pthread_self());
    return;
  } else if(!(pConnTmp = (CLIENT_CONN_T *) pListenCfg->pConnPool->pElements)) {
    return;
  }

  memset(&netsocksrv, 0, sizeof(netsocksrv));
  memcpy(&sa, &pListenCfg->sa, sizeof(pListenCfg->sa));
  netsocksrv.flags = pListenCfg->netflags;

  if((NETIOSOCK_FD(netsocksrv) = net_listen((const struct sockaddr *) &sa, backlog)) == INVALID_SOCKET) {
    logutil_tid_remove(pthread_self());
    return;
  }

  pthread_mutex_lock(&pListenCfg->mtx);
  pListenCfg->pnetsockSrv = &netsocksrv;
  pthread_mutex_unlock(&pListenCfg->mtx);

  if(pListenCfg->pAuthStore && IS_AUTH_CREDENTIALS_SET(pListenCfg->pAuthStore)) {
    haveAuth = 1;
  }
  if(pListenCfg->pAuthTokenId && pListenCfg->pAuthTokenId[0] != '\0') {
    haveToken = 1;
  }

  tsMax = pConnTmp->pStreamerCfg0->liveQs[0].max;
  flvMax = pConnTmp->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_FLV].max;
  mkvMax = pConnTmp->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_MKV].max;
  rtmpMax = pConnTmp->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_RTMP].max;
  rtspMax = pConnTmp->pStreamerCfg0->pRtspSessions->max;

  if(HAVE_URL_CAP_RTMP(pListenCfg->urlCapabilities)) {

    if(IS_AUTH_CREDENTIALS_SET(&pConnTmp->pStreamerCfg0->creds[STREAMER_AUTH_IDX_RTMP].stores[pListenCfg->idxCfg])) {
      //
      // RTMP server streaming credentials not implemented 
      //
      //haveRtmpAuth = 1;
    }

    LOG(X_INFO("rtmp %s%s available at "URL_RTMP_FMT_STR"%s max:%d"),
       ((pListenCfg->netflags & NETIO_FLAG_PLAINTEXT) && (pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ) ? "(SSL) " :
       ((pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ? "(SSL only) " : ""),
           ((pListenCfg->urlCapabilities & URL_CAP_RTMPTLIVE) && !(pListenCfg->urlCapabilities & URL_CAP_RTMPLIVE) ?
            "(tunneled only) " : ((pListenCfg->urlCapabilities & URL_CAP_RTMPTLIVE) ? "(tunneled) " : "")),
           URL_PROTO_FMT2_ARGS(
               (pListenCfg->netflags & NETIO_FLAG_SSL_TLS),
                 FORMAT_NETADDR(sa, tmp, sizeof(tmp))), ntohs(INET_PORT(sa)),
           (haveRtmpAuth ? " (Using auth)" : ""), rtmpMax);
  }

  if(pListenCfg->urlCapabilities & URL_CAP_RTSPLIVE) {

    if(IS_AUTH_CREDENTIALS_SET(&pConnTmp->pStreamerCfg0->creds[STREAMER_AUTH_IDX_RTSP].stores[pListenCfg->idxCfg])) {
      haveRtspAuth = 1;
    }

    if(pListenCfg->pCfg->prtspsessiontimeout && *pListenCfg->pCfg->prtspsessiontimeout != 0) {
      snprintf(bufses, sizeof(bufses), ", timeout:%u sec", *pListenCfg->pCfg->prtspsessiontimeout);
    } else {
      bufses[0] = '\0';
    }

    LOG(X_INFO("rtsp %s available at "URL_RTSP_FMT_STR"%s max:%d%s"),
       ((pListenCfg->netflags & NETIO_FLAG_PLAINTEXT) && (pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ) ? "(SSL) " :
       ((pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ? "(SSL only) " : ""),
             URL_PROTO_FMT2_ARGS(
                 (pListenCfg->netflags & NETIO_FLAG_SSL_TLS),
                   FORMAT_NETADDR(sa, tmp, sizeof(tmp))), ntohs(INET_PORT(sa)),
             (haveRtspAuth ? " (Using auth)" : ""), rtspMax, bufses);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_ROOTHTML)) {
    LOG(X_INFO("broadcast interface available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_ROOT_URL,
           (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_LIVE)) {
    LOG(X_INFO("live available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_LIVE_URL,
           (haveAuth ? " (Using auth)" : ""),
           (haveToken ? " (Using token)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_TSLIVE)) {
    LOG(X_INFO("tslive available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_TSLIVE_URL,
           (haveAuth ? " (Using auth)" : ""),
           (haveToken ? " (Using token)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), tsMax);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_TSHTTPLIVE)) {
    LOG(X_INFO("httplive available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_HTTPLIVE_URL,
           (haveAuth ? " (Using auth)" : ""),
           (haveToken ? " (Using token)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_FLVLIVE)) {
    LOG(X_INFO("flvlive available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_FLVLIVE_URL,
           (haveAuth ? " (Using auth)" : ""),
           (haveToken ? " (Using token)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), flvMax);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_MKVLIVE)) {
    LOG(X_INFO("mkvlive available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_MKVLIVE_URL,
           (haveAuth ? " (Using auth)" : ""),
           (haveToken ? " (Using token)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), mkvMax);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_MOOFLIVE)) {
    LOG(X_INFO("dash available at "URL_HTTP_FMT_STR"%s%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_DASH_URL,
           (haveAuth ? " (Using auth)" : ""),
           (haveToken ? " (Using token)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_STATUS)) {
    LOG(X_INFO("status available at "URL_HTTP_FMT_STR"%s%s%s"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_STATUS_URL,
            (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""));
  }

  if((pListenCfg->urlCapabilities & URL_CAP_PIP)) {
    LOG(X_INFO("pip available at "URL_HTTP_FMT_STR"%s%s%s"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_PIP_URL,
            (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""));
  }

  if((pListenCfg->urlCapabilities & URL_CAP_CONFIG)) {
    LOG(X_INFO("config available at "URL_HTTP_FMT_STR"%s%s%s"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, FORMAT_NETADDR(sa, tmp, sizeof(tmp))), VSX_CONFIG_URL,
            (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""));
  }

  //fprintf(stderr, "LISTENER THREAD %s %s:%d active:%d cap: 0x%x\n", pListenCfg->netflags & NETIO_FLAG_SSL_TLS ? "SSL" : "", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port), pListenCfg->active, pListenCfg->urlCapabilities);

  //
  // Service any client connections on the live listening port
  //
  rc = srvlisten_loop(pListenCfg, srv_cmd_proc);

  pthread_mutex_lock(&pListenCfg->mtx);
  pListenCfg->pnetsockSrv = NULL; 
  netio_closesocket(&netsocksrv);
  pthread_mutex_unlock(&pListenCfg->mtx);

  LOG(X_WARNING("HTTP listener thread exiting with code: %d"), rc);

  logutil_tid_remove(pthread_self());

  return;
}
Example #5
0
static void srvlisten_rtsplive_proc(void *pArg) {

  SRV_LISTENER_CFG_T *pListenCfg = (SRV_LISTENER_CFG_T *) pArg;
  CLIENT_CONN_T *pConn = NULL;
  NETIO_SOCK_T netsocksrv;
  struct sockaddr_in  sa;
  int haveRtspAuth = 0;
  char buf[SAFE_INET_NTOA_LEN_MAX];
  char bufses[32];
  int rc = 0;

  logutil_tid_add(pthread_self(), pListenCfg->tid_tag);

  memset(&sa, 0, sizeof(sa));
  memset(&netsocksrv, 0, sizeof(netsocksrv));
  sa.sin_family = PF_INET;
  sa.sin_addr = pListenCfg->sain.sin_addr;
  sa.sin_port = pListenCfg->sain.sin_port;
  netsocksrv.flags = pListenCfg->netflags;

  if((NETIOSOCK_FD(netsocksrv) = net_listen(&sa, 5)) == INVALID_SOCKET) {
    logutil_tid_remove(pthread_self());
    return;
  }

   pConn = (CLIENT_CONN_T *) pListenCfg->pConnPool->pElements;
    if(pConn) {
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_RTSP].stores[pListenCfg->idxCfg])) {
      haveRtspAuth = 1;
    }
  }

  pthread_mutex_lock(&pListenCfg->mtx);
  pListenCfg->pnetsockSrv = &netsocksrv;
  pthread_mutex_unlock(&pListenCfg->mtx);

  if(pListenCfg->pCfg->prtspsessiontimeout && *pListenCfg->pCfg->prtspsessiontimeout != 0) {
    snprintf(bufses, sizeof(bufses), ", timeout:%u sec", *pListenCfg->pCfg->prtspsessiontimeout);
  } else {
    bufses[0] = '\0';
  }

  LOG(X_INFO("rtsp %sserver available at "URL_RTSP_FMT_STR"%s max:%d%s"),
           ((pListenCfg->netflags & NETIO_FLAG_SSL_TLS) ? "(SSL) " : ""),
           URL_RTSP_FMT2_ARGS(
               (pListenCfg->netflags & NETIO_FLAG_SSL_TLS),
                 net_inet_ntoa(sa.sin_addr, buf)), ntohs(sa.sin_port), 
           (haveRtspAuth ? " (Using auth)" : ""),
           pListenCfg->max, bufses);

  //
  // Service any client connections on the rtsp listening port
  //
  rc = srvlisten_loop(pListenCfg, srv_rtsp_proc);

  pthread_mutex_lock(&pListenCfg->mtx);
  pListenCfg->pnetsockSrv = NULL; 
  netio_closesocket(&netsocksrv);
  pthread_mutex_unlock(&pListenCfg->mtx);

  LOG(X_DEBUG("rtsp listener thread exiting with code: %d"), rc);

  logutil_tid_remove(pthread_self());

  return ;
}
Example #6
0
RTSP_HTTP_SESSION_T *rtspsrv_newHttpSession(STREAM_RTSP_SESSIONS_T *pRtsp, const char *sessionCookie,
                                               const struct sockaddr *psa) {
  RTSP_HTTP_SESSION_T *pRtspGetSession = NULL; 
  size_t szCookie;
  unsigned int idx;

  if(!pRtsp || !pRtsp->pRtspGetSessionsBuf || !sessionCookie || sessionCookie[0] == '\0') {
    return NULL;
  }

  if((szCookie = strlen(sessionCookie)) > RTSP_HTTP_SESSION_COOKIE_MAX - 1) {
    LOG(X_ERROR("Client RTSP HTTP session cookie length %d exceeds %d"), szCookie, 
        RTSP_HTTP_SESSION_COOKIE_MAX - 1);
    return NULL;
  }

  pthread_mutex_lock(&pRtsp->mtx);

  for(idx = 0; idx < pRtsp->numRtspGetSessions; idx++) {

    if(!pRtsp->pRtspGetSessionsBuf[idx].inuse) {

      pRtspGetSession = &pRtsp->pRtspGetSessionsBuf[idx];

      if(!pRtspGetSession->pRequestBufWr) {
        if(!(pRtspGetSession->pRequestBufWr = (char *) avc_calloc(2, RTSP_HTTP_POST_BUFFER_SZ))) {
          pthread_mutex_unlock(&pRtsp->mtx);
          return NULL;
        }
        pRtspGetSession->pRequestBufRd = pRtspGetSession->pRequestBufWr + RTSP_HTTP_POST_BUFFER_SZ;

        pthread_mutex_init(&pRtspGetSession->cond.mtx, NULL);
        pthread_cond_init(&pRtspGetSession->cond.cond, NULL);
        pthread_mutex_init(&pRtspGetSession->mtx, NULL);
      }

      pRtspGetSession->inuse = 1;
      memset(&pRtspGetSession->netsocketPost, 0, sizeof(pRtspGetSession->netsocketPost));
      NETIOSOCK_FD(pRtspGetSession->netsocketPost) = INVALID_SOCKET;
      pRtspGetSession->expired = 0;
      strncpy(pRtspGetSession->cookie.sessionCookie, sessionCookie, RTSP_HTTP_SESSION_COOKIE_MAX - 1);
      if(psa) {
        memcpy(&pRtspGetSession->cookie.sa, psa, INET_SIZE(*psa));
      }
      gettimeofday(&pRtspGetSession->tvCreate, NULL);
      pRtspGetSession->tvLastMsg.tv_sec = 0;
      pRtspGetSession->requestSz = 0;
      pRtspGetSession->requestIdxWr = 0;
      pRtspGetSession->pRequestBufWr[0] = '\0';
      pRtspGetSession->pRequestBufRd[0] = '\0';
      pRtspGetSession->pnext = NULL;

      if(pRtsp->pRtspGetSessionsTail) {
        pRtsp->pRtspGetSessionsTail->pnext = pRtspGetSession;
      } else {
        pRtsp->pRtspGetSessionsHead = pRtspGetSession;
      }

      pRtsp->pRtspGetSessionsTail = pRtspGetSession;

      break;
    }

  }

  pthread_mutex_unlock(&pRtsp->mtx);

  return pRtspGetSession;
}
Example #7
0
static void srvlisten_http_proc(void *pArg) {

  SRV_LISTENER_CFG_T *pListenCfg = (SRV_LISTENER_CFG_T *) pArg;
  NETIO_SOCK_T netsocksrv;
  struct sockaddr_in  sa;
  CLIENT_CONN_T *pConn;
  unsigned int tsMax = 0;
  unsigned int flvMax = 0;
  unsigned int mkvMax = 0;
/*
  int haveMkvAuth = 0; 
  int haveFlvAuth = 0; 
  int haveTsliveAuth = 0; 
  int haveHttpliveAuth = 0; 
  int haveMoofAuth = 0; 
  int haveConfigAuth = 0; 
  int havePipAuth = 0; 
  int haveStatusAuth = 0; 
  int haveRootAuth = 0; 
*/
  int haveAuth = 0;
  int rc = 0;
  char buf[SAFE_INET_NTOA_LEN_MAX];

  logutil_tid_add(pthread_self(), pListenCfg->tid_tag);

  if((pListenCfg->urlCapabilities & (URL_CAP_TSLIVE | URL_CAP_TSHTTPLIVE | URL_CAP_FLVLIVE |
                                     URL_CAP_MKVLIVE | URL_CAP_LIVE | URL_CAP_STATUS | URL_CAP_MOOFLIVE |
                                     URL_CAP_PIP | URL_CAP_CONFIG | URL_CAP_BROADCAST)) == 0) {
    LOG(X_WARNING("http listener exiting because no capabilities enabled on %s:%d"),
        inet_ntoa(pListenCfg->sain.sin_addr), ntohs(pListenCfg->sain.sin_port));
    logutil_tid_remove(pthread_self());
    return;
  }

  memset(&sa, 0, sizeof(sa));
  memset(&netsocksrv, 0, sizeof(netsocksrv));
  sa.sin_family = PF_INET;
  sa.sin_addr = pListenCfg->sain.sin_addr;
  sa.sin_port = pListenCfg->sain.sin_port;
  netsocksrv.flags = pListenCfg->netflags;

  if((NETIOSOCK_FD(netsocksrv) = net_listen(&sa, 5)) == INVALID_SOCKET) {
    logutil_tid_remove(pthread_self());
    return;
  }

  pthread_mutex_lock(&pListenCfg->mtx);
  pListenCfg->pnetsockSrv = &netsocksrv;
  pthread_mutex_unlock(&pListenCfg->mtx);

  if(pListenCfg->pAuthStore && IS_AUTH_CREDENTIALS_SET(pListenCfg->pAuthStore)) {
    haveAuth = 1;
  }

  pConn = (CLIENT_CONN_T *) pListenCfg->pConnPool->pElements;
  if(pConn) {
    tsMax = pConn->pStreamerCfg0->liveQs[0].max;
    flvMax = pConn->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_FLV].max;
    mkvMax = pConn->pStreamerCfg0->action.liveFmts.out[STREAMER_OUTFMT_IDX_MKV].max;

/*
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_FLV].stores[pListenCfg->idxCfg])) {
      haveFlvAuth = 1;
    }
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_MKV].stores[pListenCfg->idxCfg])) {
      haveMkvAuth = 1;
    }
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_TSLIVE].stores[pListenCfg->idxCfg])) {
      haveTsliveAuth = 1;
    }
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_HTTPLIVE].stores[pListenCfg->idxCfg])) {
      haveHttpliveAuth = 1; 
    }
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_MOOFLIVE].stores[pListenCfg->idxCfg])) {
      haveMoofAuth = 1; 
    }
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_CONFIG].stores[pListenCfg->idxCfg])) {
      haveConfigAuth = 1; 
    }
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_PIP].stores[pListenCfg->idxCfg])) {
      havePipAuth = 1; 
    }
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_STATUS].stores[pListenCfg->idxCfg])) {
      haveStatusAuth = 1; 
    }
    if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds[STREAMER_AUTH_IDX_ROOT].stores[pListenCfg->idxCfg])) {
      haveRootAuth = 1; 
    }
*/

    //if(IS_AUTH_CREDENTIALS_SET(&pConn->pStreamerCfg0->creds.auths[STREAMER_AUTH_IDX_ROOT])) {
    //  LOG(X_DEBUG("LIVE/ROOT AUTH ON")); 
    //}
  }

  if((pListenCfg->urlCapabilities & URL_CAP_ROOTHTML)) {
    LOG(X_INFO("broadcast interface available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_ROOT_URL,
           //(haveRootAuth ? " (Using auth)" : ""),
           (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_LIVE)) {
    LOG(X_INFO("live available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_LIVE_URL,
           //(haveRootAuth ? " (Using auth)" : ""),
           (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_TSLIVE)) {
    LOG(X_INFO("tslive available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_TSLIVE_URL,
           //(haveTsliveAuth ? " (Using auth)" : ""),
           (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), tsMax);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_TSHTTPLIVE)) {
    LOG(X_INFO("httplive available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_HTTPLIVE_URL,
           //(haveHttpliveAuth ? " (Using auth)" : ""),
           (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_FLVLIVE)) {
    LOG(X_INFO("flvlive available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_FLVLIVE_URL,
           //(haveFlvAuth ? " (Using auth)" : ""),
           (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), flvMax);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_MKVLIVE)) {
    LOG(X_INFO("mkvlive available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_MKVLIVE_URL,
           //(haveMkvAuth ? " (Using auth)" : ""),
           (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), mkvMax);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_MOOFLIVE)) {
    LOG(X_INFO("dash available at "URL_HTTP_FMT_STR"%s%s%s max:%d"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_DASH_URL,
           // (haveMoofAuth ? " (Using auth)" : ""),
           (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""), pListenCfg->max);
  }

  if((pListenCfg->urlCapabilities & URL_CAP_STATUS)) {
    LOG(X_INFO("status available at "URL_HTTP_FMT_STR"%s%s%s"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_STATUS_URL,
            //(haveStatusAuth ? " (Using auth)" : ""),
            (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""));
  }

  if((pListenCfg->urlCapabilities & URL_CAP_PIP)) {
    LOG(X_INFO("pip available at "URL_HTTP_FMT_STR"%s%s%s"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_PIP_URL,
            //(havePipAuth ? " (Using auth)" : ""),
            (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""));
  }

  if((pListenCfg->urlCapabilities & URL_CAP_CONFIG)) {
    LOG(X_INFO("config available at "URL_HTTP_FMT_STR"%s%s%s"), 
           URL_HTTP_FMT_ARGS2(pListenCfg, net_inet_ntoa(sa.sin_addr, buf)), VSX_CONFIG_URL,
            //(haveConfigAuth ? " (Using auth)" : ""),
            (haveAuth ? " (Using auth)" : ""),
           (pListenCfg->pCfg->cfgShared.livepwd ? " (Using password)" : ""));
  }

  //fprintf(stderr, "LISTENER THREAD %s %s:%d active:%d cap: 0x%x\n", pListenCfg->netflags & NETIO_FLAG_SSL_TLS ? "SSL" : "", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port), pListenCfg->active, pListenCfg->urlCapabilities);

  //
  // Service any client connections on the live listening port
  //
  rc = srvlisten_loop(pListenCfg, srv_cmd_proc);

  pthread_mutex_lock(&pListenCfg->mtx);
  pListenCfg->pnetsockSrv = NULL; 
  netio_closesocket(&netsocksrv);
  pthread_mutex_unlock(&pListenCfg->mtx);

  LOG(X_WARNING("HTTP listener thread exiting with code: %d"), rc);

  logutil_tid_remove(pthread_self());

  return;
}
Example #8
0
static const char *get_m3u8(CAP_ASYNC_DESCR_T *pCfg,
                         const char *puri,
                         HTTP_RESP_T *pHttpResp,
                         HTTP_PARSE_CTXT_T *pHdrCtxt,
                         unsigned char *pbuf, unsigned int szbuf) {
  int sz = 0;
  struct timeval tv0, tv1;
  unsigned int consumed = 0;
  unsigned int contentLen = 0;
  unsigned int tmtms = 0;
  unsigned char *pdata = NULL;

  gettimeofday(&tv0, NULL);

  //fprintf(stderr, "GET M3U... puri:'%s', hdrslen:%d\n", puri, pHdrCtxt->hdrslen);

  if(pHdrCtxt->hdrslen == 0) {

    if((httpcli_gethdrs(pHdrCtxt, pHttpResp, &pCfg->pSockList->salist[0], puri,
          http_getConnTypeStr(HTTP_CONN_TYPE_CLOSE), 0, 0, pCfg->pcommon->addrsExtHost[0], NULL)) < 0) {
      return NULL;
    }

  }

  if((pdata = http_get_contentlen_start(pHttpResp, pHdrCtxt, pbuf, szbuf, 1, &contentLen))) {
    consumed = pHdrCtxt->idxbuf - pHdrCtxt->hdrslen;
  }

  if(pdata && net_setsocknonblock(NETIOSOCK_FD(pCfg->pSockList->netsockets[0]), 1) < 0) {
 
    pdata = NULL;
  }

//fprintf(stderr, "NET_RECV in m3u... %d < %d idxbuf:%d hdrslen:%d pdata:0x%x\n", consumed, contentLen, pHdrCtxt->idxbuf, pHdrCtxt->hdrslen, pdata);

  while(pdata && consumed < contentLen && !g_proc_exit) {

    if((sz = netio_recvnb(&pCfg->pSockList->netsockets[0],
                          (unsigned char *) &pdata[consumed],
                          contentLen - consumed, 500)) > 0) {
      consumed += sz;
    }
//fprintf(stderr, "NET REceiving... %d < %d, %d tmtms:%d\n", consumed, contentLen, sz, tmtms);
    gettimeofday(&tv1, NULL);
    if(tmtms > 0 && consumed < contentLen && TIME_TV_DIFF_MS(tv1, tv0) > (unsigned int) tmtms) {
      LOG(X_WARNING("HTTP %s:%d%s timeout %d ms exceeded"),
           inet_ntoa(pCfg->pSockList->salist[0].sin_addr),
           ntohs(pCfg->pSockList->salist[0].sin_port), puri, tmtms);
      pdata = NULL;
      break;
    }
  }

  if(pdata && contentLen > 0 && consumed >= contentLen) {
    pdata[consumed] = '\0';
  } else {
    pdata = NULL;
  }

  //fprintf(stderr, "GOT m3u...0x%x %d < %d\n", pdata, consumed, contentLen);avc_dumpHex(stderr, pdata, consumed, 1);
  return (const char *) pdata;
}
Example #9
0
int http_gethttplive(CAP_ASYNC_DESCR_T *pCfg,
                         CAPTURE_CBDATA_T *pStreamsOut,
                         CAPTURE_STREAM_T *pStream,
                         const char *puri,
                         HTTP_RESP_T *pHttpResp,
                         HTTP_PARSE_CTXT_T *pHdrCtxt) {
  int rc = 0;
  char *path;
  const char *pbuf = pHdrCtxt->pbuf;
  unsigned int szbuf = pHdrCtxt->szbuf;
  const char *pm3ubuf;
  pthread_t ptd;
  pthread_attr_t attr;
  HTTPLIVE_CLIENT_T client;
  int highestIdx, lowestIdx, firstIdx;

  memset(&client, 0, sizeof(client));
  client.pCfg = pCfg;
  NETIOSOCK_FD(client.netsock) = INVALID_SOCKET;
  client.netsock.flags = pCfg->pSockList->netsockets[0].flags;
  client.pStreamsOut = pStreamsOut;
  client.pStream = pStream;
  client.running = -1;

  pthread_mutex_init(&client.mtx, NULL);

  do {

    //fprintf(stderr, "HTTP_GETHTTPLIVE sock: %d\n", NETIOSOCK_FD(pCfg->pSockList->netsockets[0]));

    if(NETIOSOCK_FD(pCfg->pSockList->netsockets[0]) == INVALID_SOCKET) {

//fprintf(stderr, "GOING TO CONNECT FOR M3U...\n");
      if((rc = httpcli_connect(&pCfg->pSockList->netsockets[0], &pCfg->pSockList->salist[0], 
                               "HTTPLive playlist thread")) < 0) {
        break;
      }

      memset(pHdrCtxt, 0, sizeof(HTTP_PARSE_CTXT_T));
      memset(pHttpResp, 0, sizeof(HTTP_RESP_T));
      pHdrCtxt->pnetsock = &pCfg->pSockList->netsockets[0];
      pHdrCtxt->pbuf = pbuf;
      pHdrCtxt->szbuf = szbuf;
      pHdrCtxt->tmtms = 0;
    }

    if((rc = mediadb_getdirlen(puri)) > 0) {
      if(rc >= sizeof(client.uriprefix)) {
        rc = sizeof(client.uriprefix) - 1;
      }
      memcpy(client.uriprefix, puri, rc);
    }

    if((pm3ubuf = get_m3u8(pCfg, puri, pHttpResp, pHdrCtxt, (unsigned char *) pbuf, 
                           szbuf))) {
      m3u_free(&client.pl, 0);
      memset(&client.pl, 0, sizeof(client.pl));

/*
pm3ubuf="#EXTM3U\r\n"
        "#EXT-X-VERSION:3\r\n"
        "#EXT-X-ALLOW-CACHE:NO\r\n"
        "#EXT-X-TARGETDURATION:14\r\n"
        "#EXT-X-MEDIA-SEQUENCE:2699\r\n"
        "#EXTINF:10,\r\n"
        "media_2699.ts?wowzasessionid=1144297750\r\n"
        "#EXTINF:10,\r\n"
        "media_2700.ts?wowzasessionid=1144297750\r\n"
        "#EXTINF:7,\r\n"
        "media_2701.ts?wowzasessionid=1144297750\r\n";
*/

      VSX_DEBUGLOG("Got m3u contents '%s'", pm3ubuf);
      //fprintf(stderr, "Got m3u contents '%s'\n", pm3ubuf);

      pthread_mutex_lock(&client.mtx);
      rc = m3u_create_buf(&client.pl, pm3ubuf);
      pthread_mutex_unlock(&client.mtx);

      if(rc > 0) {

        path = NULL;
        lowestIdx = find_lowest_idx(&client.pl, NULL);
        highestIdx = find_highest_idx(&client.pl, NULL);

        if(!client.insession) {

          if(highestIdx < 0) {
            LOG(X_WARNING("Unable to find httplive starting index from %s"), puri);
          } else {

            //
            // Some segmentors may write the last chunk to the playlist file even though
            // the chunk is still being appended on disk
            //
            //if(highestIdx > lowestIdx) {
            //  firstIdx = highestIdx - 1;
            //} else {
              firstIdx = highestIdx;
            //}

            client.curidx  = firstIdx;
            client.nextidx = client.curidx;
            client.insession = 1;

            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
            client.running = 1;

            if(pthread_create(&ptd, &attr, (void *) httplive_mediaproc, 
                              &client) != 0) {
              LOG(X_ERROR("Unable to create httplive media download thread"));
              rc = -1; 
              client.running = -1;
            }
          }

        } else { // client.insession

          //fprintf(stderr, "check playlist falling behind curidx:%d nextidx:%d, lowestIdx:%d, highestIdx:%d\n", client.curidx, client.nextidx, lowestIdx, highestIdx);
          //
          // Prevent falling behind playlist, a warning will be printed in the ts get thread
          //
          pthread_mutex_lock(&client.mtx);
          if(client.nextidx < lowestIdx) {
            client.nextidx = lowestIdx;
          }
          pthread_mutex_unlock(&client.mtx);
        }

        //if(rc >= 0) {
        //  m3u_dump(&client.pl);
        //}

      }

    } else { // get_m3u8
      rc = -1;
    }

    netio_closesocket(&pCfg->pSockList->netsockets[0]);

    if(rc >= 0) {
//fprintf(stderr, "M3U SLEEPING FOR %d\n", client.pl.targetDuration);
      if(client.pl.targetDuration > 0) {
        sleep(client.pl.targetDuration);
      } else {
        sleep(9);
      }
    }

  } while(rc >= 0);

  client.insession = 0;

  while(client.running != -1) {
    usleep(20000);
  } 

  m3u_free(&client.pl, 0);
  pthread_mutex_destroy(&client.mtx);

  return rc;
}
Example #10
0
static void httplive_mediaproc(void *pArg) {
  HTTPLIVE_CLIENT_T *pClient = (HTTPLIVE_CLIENT_T *) pArg;
  int rc = 0;
  const char *p;
  const char *puri = NULL;
  char path[VSX_MAX_PATH_LEN];

  pClient->running = 0;

  LOG(X_DEBUG("Starting HTTPLive client media thread"));

  path[sizeof(path) - 1] = '\0';

  while(rc >= 0 && pClient->pCfg->running == 0 && pClient->insession) {

    path[0] = '\0';

    pthread_mutex_lock(&pClient->mtx);

    if(pClient->nextidx > pClient->curidx) {
      LOG(X_WARNING("HTTPLive skipping playlist media chunk index %d - %d"),
                     pClient->curidx, pClient->nextidx - 1);
      pClient->curidx = pClient->nextidx;
      //pClient->nextidx++;
    }

    if((p = find_path(&pClient->pl, pClient->curidx))) {
      strncpy(path, p, sizeof(path) - 1);
    } else {

    }
    pthread_mutex_unlock(&pClient->mtx);

    if(!(puri = get_uri_from_path(pClient, path))) {
      rc = -1;
      break;
    }

    if(puri && puri[0] != '\0') {

      // TODO: create httplive retrieval flag forcing new socket... lame
      if(NETIOSOCK_FD(pClient->netsock) != INVALID_SOCKET && net_issockremotelyclosed(NETIOSOCK_FD(pClient->netsock), 1)) {
        LOG(X_DEBUG("HTTPLive media socket has been closed")); 
        netio_closesocket(&pClient->netsock);
      }

      if(NETIOSOCK_FD(pClient->netsock) == INVALID_SOCKET) {

      //fprintf(stderr, "----MEDIA GET for '%s' '%s'\n", path, puri);

        if((rc = httpcli_connect(&pClient->netsock, &pClient->sa, "HTTPLive media thread")) < 0) {
          break;
        }

      }

      //fprintf(stderr, "may call get_ts puri:'%s', idx:%d, next:%d\n", puri, pClient->curidx, pClient->nextidx);

      if((rc = get_ts(pClient, puri)) >= 0) {

        //fprintf(stderr, "HTTPLive ts retrieval '%s' returned %d\n", puri, rc);

        pthread_mutex_lock(&pClient->mtx);
        pClient->nextidx++;
        pClient->curidx = pClient->nextidx;
        pthread_mutex_unlock(&pClient->mtx);
      }

    } // end of if(puri && puri[0] != '\0' ...

    sleep(1);

  }

  netio_closesocket(&pClient->netsock);

  pClient->insession = 0;
  pClient->running = -1;

  LOG(X_DEBUG("HTTPLive media download thread exiting with code %d"), rc);
}
Example #11
0
int http_flv_recvloop(CAP_ASYNC_DESCR_T *pCfg,
                  unsigned int offset,
                  int sz, 
                  FILE_OFFSET_T contentLen,
                  unsigned char *pbuf,
                  unsigned int szbuf,
                  CAPTURE_STREAM_T *pStream) {

  CAP_HTTP_FLV_T ctxt;
  FLV_TAG_HDR_T *pTagHdr;
  unsigned char *pdata;
  unsigned int ts0 = 0;
  unsigned int ts;
  unsigned int tsoffset = 0;
  int havets0 = 0;
  TIME_VAL tm0, tm;
  unsigned int msElapsed;
  int do_sleep;
  int rc;

  memset(&ctxt, 0, sizeof(ctxt));
  ctxt.common.pCfg = pCfg;
  ctxt.common.pdata = pbuf;
  ctxt.common.dataoffset = offset;
  ctxt.common.datasz = offset + sz;
  ctxt.pStream = pStream;

  //if(sz > 0) {
  //  LOG(X_WARNING("Partial FLV HTTP Content-Header read offset %d not implemented. (offset:%d)"), sz, offset);
  //}

  if(net_setsocknonblock(NETIOSOCK_FD(pCfg->pSockList->netsockets[0]), 1) < 0) {
    return -1;
  }

  if(http_flv_init(&ctxt) < 0) {
    return -1;
  }

  //
  // Read 'FLV' 9 byte header
  //
  if(!(pdata = read_net_flv(&ctxt, 9))) {
    http_flv_close(&ctxt);
    return -1;
  }

  memcpy(&ctxt.flvhdr, pdata, 9);

  if(!(ctxt.flvhdr.type[0] == 'F' && ctxt.flvhdr.type[1] == 'L' && 
       ctxt.flvhdr.type[2] == 'V' && ctxt.flvhdr.ver == FLV_HDR_VER_1)) {
    LOG(X_ERROR("Invalid HTTP FLV start sequence 0x%x 0x%x 0x%x 0x%x"),
               pdata[0], pdata[1], pdata[2], pdata[3]); 
    http_flv_close(&ctxt);
    return -1;
  }

  if((FLV_HDR_HAVE_VIDEO((&ctxt.flvhdr)) && !ctxt.client.pQVid) ||
     (FLV_HDR_HAVE_AUDIO((&ctxt.flvhdr)) && !ctxt.client.pQAud)) {

    LOG(X_ERROR("FLV capture input queue(s) not propery configured: video: %d, audio: %d"),
                ctxt.client.pQVid ? 1 : 0, ctxt.client.pQAud ? 1 : 0);
    http_flv_close(&ctxt);
    return -1;
  }

  tm0 = timer_GetTime();

  if(pCfg->pcommon->caprealtime) {
    LOG(X_DEBUG("Treating capture as real-time."));
  }

  do {

    if(!(pTagHdr = (FLV_TAG_HDR_T *) read_net_flv(&ctxt, FLV_TAG_HDR_SZ))) {
      return -1;
    }

    ctxt.taghdr.szprev = htonl(pTagHdr->szprev);
    ctxt.taghdr.type = pTagHdr->type;
    memcpy(&ctxt.taghdr.size32, &pTagHdr->size, 3);
    ctxt.taghdr.size32 = htonl(ctxt.taghdr.size32 << 8);
    memcpy(&ctxt.taghdr.timestamp32, &pTagHdr->timestamp, 3);
    ctxt.taghdr.timestamp32 = htonl(ctxt.taghdr.timestamp32 << 8);
    ctxt.taghdr.timestamp32 |= (pTagHdr->tsext << 24);

    //
    // For live content, initial timestamp may not always begin at 0
    //
    if(!havets0) {
      if((ts0 = ctxt.taghdr.timestamp32) > 0) {
        havets0 = 1;
      }
    } else if(ctxt.taghdr.timestamp32 < ts0) {
      LOG(X_WARNING("HTTP FLV timestamp anamoly ts:%u, initial ts:%u (offset:%u)"),
          ctxt.taghdr.timestamp32, ts0, tsoffset);
      tsoffset += ts0;
      ts0 = ctxt.taghdr.timestamp32;
    }
    ts = ctxt.taghdr.timestamp32 - ts0 + tsoffset;

    //fprintf(stderr, "flv hdr type:0x%x sz:%d ts:%u(ts0:%u+%u) pkt_ts:%u\n", ctxt.taghdr.type, ctxt.taghdr.size32, ts, ts0, tsoffset, ctxt.taghdr.timestamp32);

    if(!(pdata = read_net_flv(&ctxt, ctxt.taghdr.size32))) {
      return -1;
    }

    //
    // For non-live content, throttle download rate inline with timestamps for real-time
    // restreaming
    //
    if(pCfg->pcommon->caprealtime) {
      do {
        do_sleep = 0;
        tm = timer_GetTime();
        msElapsed = (unsigned int) (tm - tm0) / TIME_VAL_MS;
//fprintf(stderr, "msElapsed:%d  ts:%d %lld %lld\n", msElapsed, ctxt.taghdr.timestamp32, tm, tm0);
        if(msElapsed < ts) {
          if((do_sleep = ts - msElapsed) > 500) {
            do_sleep = 500;
          }
//fprintf(stderr, "zzzz %d ms\n", do_sleep);
          usleep(do_sleep * 1000);
        }
      } while(do_sleep);
    }

    rc = 0;
    switch(ctxt.taghdr.type) {
      case FLV_TAG_VIDEODATA: 
        rc = rtmp_handle_vidpkt(&ctxt.client, pdata, ctxt.taghdr.size32, ts);
        break;
      case FLV_TAG_AUDIODATA: 
        rc = rtmp_handle_audpkt(&ctxt.client, pdata, ctxt.taghdr.size32, ts); 
      case FLV_TAG_SCRIPTDATA: 

        break;
      default:
        rc = -1;
        break;
    }

    if(rc < 0) {
      LOG(X_ERROR("Failed to process FLV packet type: 0x%x, len:%d"), 
                  ctxt.taghdr.type, ctxt.taghdr.size32);
      break;
    }


  } while(pCfg->running == 0 && 
          (contentLen == 0 || ctxt.client.ctxt.bytesRead < contentLen) &&
         !g_proc_exit);

  http_flv_close(&ctxt);

  return ctxt.client.ctxt.bytesRead;
}
Example #12
0
//TODO: move this to http files
int http_getpage(const char *addr, uint16_t port, const char *uri,
                 char *buf, unsigned int szbuf, unsigned int tmtms) {
  int rc = 0;
  NETIO_SOCK_T netsock;
  struct sockaddr_in sa;
  HTTP_PARSE_CTXT_T hdrCtxt;
  HTTP_RESP_T httpResp;
  unsigned int contentLen = 0;
  const char *p;
  unsigned int consumed = 0;
  struct timeval tv0, tv1;
  char hdr[1024];

  if(!addr || !buf || szbuf <= 0) {
    return -1;
  }
  if(!uri) {
    uri = "/";
  }

  memset(&netsock, 0, sizeof(netsock));
  if((NETIOSOCK_FD(netsock) = net_opensocket(SOCK_STREAM, 0, 0, NULL)) == INVALID_SOCKET) {
    return -1;
  }

  memset(&sa, 0, sizeof(sa));
  sa.sin_addr.s_addr = inet_addr(addr);
  sa.sin_port = htons(port);

  if((rc = net_connect(NETIOSOCK_FD(netsock), &sa)) != 0) {
    return rc;
  }

  gettimeofday(&tv0, NULL);

  memset(&hdrCtxt, 0, sizeof(hdrCtxt));
  memset(&httpResp, 0, sizeof(httpResp));
  hdrCtxt.pnetsock = &netsock;
  hdrCtxt.pbuf = hdr;
  hdrCtxt.szbuf = sizeof(hdr);
  hdrCtxt.tmtms = tmtms;

  VSX_DEBUG_MGR(LOG(X_DEBUG("MGR - Sending local status command: '%s' to: %d"), uri, htons(sa.sin_port)));

  if((httpcli_gethdrs(&hdrCtxt, &httpResp, &sa, uri, NULL, 0, 0, NULL, NULL)) < 0) {
    return -1;
  }

  if(rc >= 0 && (p = conf_find_keyval(httpResp.hdrPairs, HTTP_HDR_CONTENT_LEN))) {
    contentLen = atoi(p);  
  } 

  if(rc >= 0) {
    if(contentLen <= 0) {
      LOG(X_ERROR("Content-Length not found in response"));
      rc = -1;
    } else if(contentLen > szbuf) {
      LOG(X_ERROR("Input buffer size too small %d / %d"), szbuf, contentLen);
      rc = -1;
    } else if(hdrCtxt.idxbuf > hdrCtxt.hdrslen) {
      if((consumed = hdrCtxt.idxbuf - hdrCtxt.hdrslen) < szbuf) {
        memcpy(buf, &hdr[hdrCtxt.hdrslen], consumed);
      } else {
        LOG(X_ERROR("Input buffer size too small %d / %d"), szbuf, contentLen);
        rc = -1;
      }
    }
  }

  if(rc >= 0 && net_setsocknonblock(NETIOSOCK_FD(netsock), 1) < 0) {
    rc = -1;
  } 

    //fprintf(stderr, "GET PAGE OK idx:%d hdrs:%d conentlen:%d\n", hdrCtxt.idxbuf, hdrCtxt.hdrslen, contentLen);

  while(rc >= 0 && consumed < contentLen) {
    if((rc = netio_recvnb(&netsock, (unsigned char *) &buf[consumed], 
                          contentLen - consumed, 500)) > 0) {
      consumed += rc;
    } 

    gettimeofday(&tv1, NULL);
    if(tmtms > 0 && consumed < contentLen && TIME_TV_DIFF_MS(tv1, tv0) > tmtms) {
      LOG(X_WARNING("HTTP %s:%d%s timeout %d ms exceeded"), net_inet_ntoa(sa.sin_addr, hdr), 
           ntohs(sa.sin_port), uri, tmtms);
      break;
      rc = -1;
    }
  }

  if(contentLen > 0 && consumed >= contentLen) {
    rc = consumed;
  } else {
    rc = -1;
  }

  netio_closesocket(&netsock);

  return rc;
}