int rtspsrv_init(STREAM_RTSP_SESSIONS_T *pRtsp) { pthread_t ptdMonitor; struct sockaddr_storage sa; pthread_attr_t attrMonitor; RTSP_MONITOR_CTXT_T startCtxt; const char *s; if(!pRtsp || pRtsp->max <= 0) { return -1; } if(pRtsp->psessions) { avc_free((void *) &pRtsp->psessions); } destroy_rtspgetsessions(pRtsp); if(!(pRtsp->psessions = (RTSP_SESSION_T *) avc_calloc(pRtsp->max, sizeof(RTSP_SESSION_T)))) { return -1; } pRtsp->numRtspGetSessions = pRtsp->max * 2; if(!(pRtsp->pRtspGetSessionsBuf = (RTSP_HTTP_SESSION_T *) avc_calloc(pRtsp->numRtspGetSessions, sizeof(RTSP_HTTP_SESSION_T)))) { avc_free((void *) &pRtsp->psessions); pRtsp->numRtspGetSessions = 0; return -1; } pthread_mutex_init(&pRtsp->mtx, NULL); // // If all UDP / RTP sockets are bound to the same port then establish // the listener of this port prior to any RTSP interaction because some app // gateways may send some UDP polling data to the base port - and returning // an ICMP port unreachable would prevent such app gateways from allocating // UDP proxy ports // pRtsp->sockStaticLocalPort = INVALID_SOCKET; if(pRtsp->staticLocalPort > 0) { memset(&sa, 0, sizeof(sa)); sa.ss_family = AF_INET; ((struct sockaddr_in *) &sa)->sin_addr.s_addr = INADDR_ANY; INET_PORT(sa) = htons(pRtsp->staticLocalPort); if((pRtsp->sockStaticLocalPort = net_opensocket(SOCK_DGRAM, 0, 0, (struct sockaddr *) &sa)) == INVALID_SOCKET) { LOG(X_ERROR("Failed to open RTSP static local RTP port %d"), pRtsp->staticLocalPort); } else { if(net_setsocknonblock(pRtsp->sockStaticLocalPort, 1) < 0) { LOG(X_ERROR("Failed to listen on RTSP static local RTP port %d"), pRtsp->staticLocalPort); net_closesocket(&pRtsp->sockStaticLocalPort); } } //if(pRtsp->sockStaticLocalPort != INVALID_SOCKET) { // sain.sin_addr.s_addr = inet_addr("127.0.0.1"); // rc = sendto(pRtsp->sockStaticLocalPort, &sain, 1, 0, (struct sockaddr *) &sain, sizeof(sain)); // fprintf(stderr, "SENDTO:%d\n", rc); //} } // // Parse any CSV of quoted User-Agent matches which should try to force TCP interleaved mode // pRtsp->rtspForceTcpUAList.count = 0; if(pRtsp->rtspForceTcpUAList.str) { strutil_parse_csv(cbparse_entry_rtspua, pRtsp, pRtsp->rtspForceTcpUAList.str); } pRtsp->runMonitor = 2; memset(&startCtxt, 0, sizeof(startCtxt)); startCtxt.pRtsp = pRtsp; if((s = logutil_tid_lookup(pthread_self(), 0)) && s[0] != '\0') { snprintf(startCtxt.tid_tag, sizeof(startCtxt.tid_tag), "%s-rtspmon", s); } pthread_attr_init(&attrMonitor); pthread_attr_setdetachstate(&attrMonitor, PTHREAD_CREATE_DETACHED); if(pthread_create(&ptdMonitor, &attrMonitor, (void *) rtsp_monitor_proc, (void *) &startCtxt) != 0) { LOG(X_ERROR("Unable to create RTP monitor thread")); pRtsp->runMonitor = 0; if(pRtsp->psessions) { avc_free((void *) &pRtsp->psessions); } destroy_rtspgetsessions(pRtsp); pthread_mutex_destroy(&pRtsp->mtx); } while(pRtsp->runMonitor != 1 && pRtsp->runMonitor != -1) { usleep(5000); } return 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; }