int cbparse_entry_devtype(void *pArg, const char *p) { int rc = 0; PARSE_ENTRY_DATA_T *pEntryData = (PARSE_ENTRY_DATA_T *) pArg; //fprintf(stderr, "entry '%s'\n", p); if(!strncasecmp(p, DEVFILE_KEY_DEVICE, strlen(DEVFILE_KEY_DEVICE))) { if((p = strutil_skip_key(p, strlen(DEVFILE_KEY_DEVICE)))) { p = avc_dequote(p, NULL, 0); strncpy(pEntryData->devname, p, sizeof(pEntryData->devname) - 1); pEntryData->flags |= PARSE_FLAG_HAVE_DEVNAME; } } else if(!strncasecmp(p, DEVFILE_KEY_METHODS, strlen(DEVFILE_KEY_METHODS))) { if((p = strutil_skip_key(p, strlen(DEVFILE_KEY_METHODS)))) { p = avc_dequote(p, NULL, 0); if(strutil_parse_csv(cbparse_entry_devtype_method, pEntryData, p) < 0) { LOG(X_WARNING("Failed to parse device type method(s) '%s'"), p); } //fprintf(stderr, "%s %d %d %d %d\n", pEntryData->devname, pEntryData->methods[0], pEntryData->methods[1], pEntryData->methods[2], pEntryData->methods[3]); pEntryData->flags |= PARSE_FLAG_HAVE_METHOD; } } else if(!strncasecmp(p, DEVFILE_KEY_METHOD, strlen(DEVFILE_KEY_METHOD))) { if((p = strutil_skip_key(p, strlen(DEVFILE_KEY_METHOD)))) { p = avc_dequote(p, NULL, 0); pEntryData->methods[0] = devtype_methodfromstr(p); pEntryData->flags |= PARSE_FLAG_HAVE_METHOD; } } else if(!strncasecmp(p, DEVFILE_KEY_TYPE, strlen(DEVFILE_KEY_TYPE))) { if((p = strutil_skip_key(p, strlen(DEVFILE_KEY_TYPE)))) { p = avc_dequote(p, NULL, 0); pEntryData->devtype = devtype_typefromstr(p); pEntryData->flags |= PARSE_FLAG_HAVE_DEVTYPE; } } else if(!strncasecmp(p, DEVFILE_KEY_MATCH, strlen(DEVFILE_KEY_MATCH))) { if((p = strutil_skip_key(p, strlen(DEVFILE_KEY_MATCH)))) { p = avc_dequote(p, NULL, 0); strncpy(pEntryData->strmatch, p, sizeof(pEntryData->strmatch) - 1); pEntryData->flags |= PARSE_FLAG_HAVE_MATCH; } } return rc; }
int metafile_open(const char *path, META_FILE_T *pMetaFile, int readIgnores, int readTitles) { int rc = 0; FILE_HANDLE fp; char *p; int match = 0; PARSE_ENTRY_DATA_T parseData; ENTRY_IGNORE_T *pIgnore; ENTRY_IGNORE_T *pIgnorePrev = NULL; ENTRY_META_DESCRIPTION_T *pDesc; ENTRY_META_DESCRIPTION_T *pDescPrev = NULL; char buf[1024]; if(!path || !pMetaFile) { return -1; } if((fp = fileops_Open(path, O_RDONLY)) == FILEOPS_INVALID_FP) { LOG(X_ERROR("Unable to open metafile for reading: %s (ignore list:%d)"), path, readIgnores); return -1; } VSX_DEBUG_METAFILE( LOG(X_DEBUG("META - metafile_open: '%s', readIgnores: %d, readTitles: %d"), path, readIgnores, readTitles)); pMetaFile->filestr[0] = '\0'; pMetaFile->linkstr[0] = '\0'; pMetaFile->instr[0] = '\0'; pMetaFile->xcodestr[0] = '\0'; pMetaFile->userpass[0] = '\0'; pMetaFile->methodBits = 0; memset(&parseData, 0, sizeof(parseData)); parseData.path = path; while(fileops_fgets(buf, sizeof(buf) - 1, fp)) { parseData.linenum++; p = buf; while(*p == ' ' || *p == '\t') { p++; } if(*p == '#' || *p == '\r' || *p == '\n') { continue; } // // Reset the parse context storage // reset_parsedata_ctxt(&parseData); // // We allow multiple configuration items on one line, separated by comma // rc = strutil_parse_csv(cbparse_entry_metafile, &parseData, p); if(parseData.flags == 0) { continue; } if(!(readIgnores || readTitles)) { handle_parsed_line(&parseData, pMetaFile, path, &match); } // // We're only interested in reading the ignore list // if(readIgnores && parseData.ignore[0] != '\0') { if(!(pIgnore = (ENTRY_IGNORE_T *) avc_calloc(1, sizeof(ENTRY_IGNORE_T)))) { rc = -1; break; } strncpy(pIgnore->filename, parseData.ignore, sizeof(pIgnore->filename)); if(pIgnorePrev) { pIgnorePrev->pnext = pIgnore; } else { pMetaFile->pignoreList = pIgnore; } pIgnorePrev = pIgnore; } // // We're only interested in reading the resource title name // if(readTitles && parseData.title[0] != '\0' && parseData.filename[0] != '\0') { if(!(pDesc = (ENTRY_META_DESCRIPTION_T *) avc_calloc(1, sizeof(ENTRY_META_DESCRIPTION_T)))) { rc = -1; break; } strncpy(pDesc->title, parseData.title, sizeof(pDesc->title)); strncpy(pDesc->filename, parseData.filename, sizeof(pDesc->filename)); if(pDescPrev) { pDescPrev->pnext = pDesc; } else { pMetaFile->pDescriptionList = pDesc; } pDescPrev = pDesc; } } fileops_Close(fp); VSX_DEBUG_METAFILE( LOG(X_DEBUG("META - metafile_open done '%s', meta-devicefilter:'%s', meta-profilefilter: '%s' returning rc: %d, " "file: '%s', link: '%s', input: '%s', xcode: '%s', digestauth: '%s', methods: '%s', id: '%s'" ), path, pMetaFile->devicefilterstr, pMetaFile->profilefilterstr, rc, pMetaFile->filestr, pMetaFile->linkstr, pMetaFile->instr, pMetaFile->xcodestr, pMetaFile->userpass, devtype_dump_methods(pMetaFile->methodBits, buf, sizeof(buf)), pMetaFile->id)); return rc; }
int metafile_findprofs(const char *path, const char *devname, char profs[][META_FILE_PROFILESTR_MAX], unsigned int max) { int rc = 0; FILE_HANDLE fp; char *p; unsigned int idx = 0; PARSE_ENTRY_DATA_T parseData; char buf[2048]; PROFILE_LIST_ALL_T foundProfs; if(!path || !profs) { return -1; } if((fp = fileops_Open(path, O_RDONLY)) == FILEOPS_INVALID_FP) { LOG(X_ERROR("Unable to open metafile for reading profiles: %s"), path); return -1; } VSX_DEBUG_METAFILE( LOG(X_DEBUG("META - metafile_findprofs: '%s', devname: '%s'"), path, devname)); memset(&foundProfs, 0, sizeof(foundProfs)); memset(&parseData, 0, sizeof(parseData)); parseData.path = path; while(fileops_fgets(buf, sizeof(buf) - 1, fp)) { parseData.linenum++; p = buf; while(*p == ' ' || *p == '\t') { p++; } if(*p == '#') { continue; } // // Reset the parse context storage // reset_parsedata_ctxt(&parseData); strutil_parse_csv(cbparse_entry_metafile, &parseData, p); if(parseData.flags == 0) { continue; } check_profs(&parseData, devname, &foundProfs, path); } fileops_Close(fp); rc = 0; for(idx = 0; idx < foundProfs.profs_devmatch.count && idx < max; idx++) { if(!find_prof(foundProfs.profs_devmatch.profiles[idx], profs, rc)) { strncpy(profs[rc], foundProfs.profs_devmatch.profiles[idx], META_FILE_PROFILESTR_MAX); //fprintf(stderr, "ADDING DEVMATCH[%d] '%s'\n", rc, profs[rc]); rc++; } } if(foundProfs.profs_devmatch.count == 0 || !foundProfs.profs_devmatch.haveCatchAll) { for(idx = 0; idx < foundProfs.profs_nodevmatch.count && idx < max; idx++) { if(!find_prof(foundProfs.profs_nodevmatch.profiles[idx], profs, rc)) { strncpy(profs[rc], foundProfs.profs_nodevmatch.profiles[idx], META_FILE_PROFILESTR_MAX); //fprintf(stderr, "ADDING NODEVMATCH[%d] '%s'\n", rc, profs[rc]); rc++; } } } return rc; }
int cbparse_entry_metafile(void *pArg, const char *p) { int rc = 0; PARSE_ENTRY_DATA_T *pEntryData = (PARSE_ENTRY_DATA_T *) pArg; if(!strncasecmp(p, METAFILE_KEY_FILE, strlen(METAFILE_KEY_FILE))) { store_parse_entry(p, METAFILE_KEY_FILE, &pEntryData->flags, PARSE_FLAG_HAVE_FILENAME, pEntryData->filename, sizeof(pEntryData->filename)); } else if(!strncasecmp(p, METAFILE_KEY_RTMP_PROXY, strlen(METAFILE_KEY_RTMP_PROXY))) { store_parse_entry(p, METAFILE_KEY_RTMP_PROXY, &pEntryData->flags, PARSE_FLAG_HAVE_RTMP_PROXY, pEntryData->rtmpproxy, sizeof(pEntryData->rtmpproxy)); } else if(!strncasecmp(p, METAFILE_KEY_RTSP_PROXY, strlen(METAFILE_KEY_RTSP_PROXY))) { store_parse_entry(p, METAFILE_KEY_RTSP_PROXY, &pEntryData->flags, PARSE_FLAG_HAVE_RTSP_PROXY, pEntryData->rtspproxy, sizeof(pEntryData->rtspproxy)); } else if(!strncasecmp(p, METAFILE_KEY_HTTP_PROXY, strlen(METAFILE_KEY_HTTP_PROXY))) { store_parse_entry(p, METAFILE_KEY_HTTP_PROXY, &pEntryData->flags, PARSE_FLAG_HAVE_HTTP_PROXY, pEntryData->httpproxy, sizeof(pEntryData->httpproxy)); } else if(!strncasecmp(p, METAFILE_KEY_HTTPLINK, strlen(METAFILE_KEY_HTTPLINK))) { store_parse_entry(p, METAFILE_KEY_HTTPLINK, &pEntryData->flags, PARSE_FLAG_HAVE_HTTPLINK, pEntryData->link, sizeof(pEntryData->link)); } else if(!strncasecmp(p, METAFILE_KEY_INPUT, strlen(METAFILE_KEY_INPUT))) { store_parse_entry(p, METAFILE_KEY_INPUT, &pEntryData->flags, PARSE_FLAG_HAVE_INPUT, pEntryData->input, sizeof(pEntryData->input)); } else if(!strncasecmp(p, METAFILE_KEY_DEVICE, strlen(METAFILE_KEY_DEVICE))) { store_parse_entry(p, METAFILE_KEY_DEVICE, &pEntryData->flags, PARSE_FLAG_HAVE_DEVNAME, pEntryData->devname, sizeof(pEntryData->devname)); } else if(!strncasecmp(p, METAFILE_KEY_PROFILE, strlen(METAFILE_KEY_PROFILE))) { store_parse_entry(p, METAFILE_KEY_PROFILE, &pEntryData->flags, PARSE_FLAG_HAVE_PROFILE, pEntryData->profile, sizeof(pEntryData->profile)); } else if(!strncasecmp(p, METAFILE_KEY_SHARED, strlen(METAFILE_KEY_SHARED))) { if((p = store_parse_entry(p, METAFILE_KEY_SHARED, &pEntryData->flags, PARSE_FLAG_HAVE_SHARED, NULL, 0))) { if(IS_CONF_VAL_TRUE(p)) { pEntryData->shared = BOOL_ENABLED_OVERRIDE; } else if(IS_CONF_VAL_FALSE(p)) { pEntryData->shared = BOOL_DISABLED_OVERRIDE; } } } else if(!strncasecmp(p, METAFILE_KEY_SECURE, strlen(METAFILE_KEY_SECURE))) { if((p = store_parse_entry(p, METAFILE_KEY_SECURE, &pEntryData->flags, PARSE_FLAG_HAVE_SECURE, NULL, 0))) { if(IS_CONF_VAL_TRUE(p)) { pEntryData->secure = BOOL_ENABLED_OVERRIDE; } else if(IS_CONF_VAL_FALSE(p)) { pEntryData->secure = BOOL_DISABLED_OVERRIDE; } } } else if(!strncasecmp(p, METAFILE_KEY_XCODEARGS, strlen(METAFILE_KEY_XCODEARGS))) { store_parse_entry(p, METAFILE_KEY_XCODEARGS, &pEntryData->flags, PARSE_FLAG_HAVE_XCODEARGS, pEntryData->xcodestr, sizeof(pEntryData->xcodestr)); } else if(!strncasecmp(p, METAFILE_KEY_DIGESTAUTH, strlen(METAFILE_KEY_DIGESTAUTH))) { store_parse_entry(p, METAFILE_KEY_DIGESTAUTH, &pEntryData->flags, PARSE_FLAG_HAVE_DIGESTAUTH, pEntryData->userpass, sizeof(pEntryData->userpass)); //TODO: verify ascii chars delimited by colon... } else if(!strncasecmp(p, METAFILE_KEY_TOKEN, strlen(METAFILE_KEY_TOKEN))) { store_parse_entry(p, METAFILE_KEY_TOKEN, &pEntryData->flags, PARSE_FLAG_HAVE_TOKEN, pEntryData->tokenId, sizeof(pEntryData->tokenId)); } else if(!strncasecmp(p, METAFILE_KEY_METHODS, strlen(METAFILE_KEY_METHODS))) { p = store_parse_entry(p, METAFILE_KEY_METHODS, &pEntryData->flags, PARSE_FLAG_HAVE_METHODS, NULL, 0); strutil_parse_csv(cbparse_methods_csv, pEntryData, p); } else if(!strncasecmp(p, METAFILE_KEY_ID, strlen(METAFILE_KEY_ID))) { store_parse_entry(p, METAFILE_KEY_ID, &pEntryData->flags, PARSE_FLAG_HAVE_ID, pEntryData->id, sizeof(pEntryData->id)); } else if(!strncasecmp(p, METAFILE_KEY_IGNORE, strlen(METAFILE_KEY_IGNORE))) { store_parse_entry(p, METAFILE_KEY_IGNORE, &pEntryData->flags, PARSE_FLAG_HAVE_IGNORE, pEntryData->ignore, sizeof(pEntryData->ignore)); } else if(!strncasecmp(p, METAFILE_KEY_TITLE, strlen(METAFILE_KEY_TITLE))) { store_parse_entry(p, METAFILE_KEY_TITLE, &pEntryData->flags, PARSE_FLAG_HAVE_TITLE, pEntryData->title, sizeof(pEntryData->title)); // // 'description' has been deprecated in favor of 'title' // } else if(!strncasecmp(p, METAFILE_KEY_DESCRIPTION, strlen(METAFILE_KEY_DESCRIPTION))) { store_parse_entry(p, METAFILE_KEY_DESCRIPTION, &pEntryData->flags, PARSE_FLAG_HAVE_TITLE, pEntryData->title, sizeof(pEntryData->title)); } else { LOG(X_WARNING("Unhandled metafile parameter '%s' in %s line:%d"), p, pEntryData->path, pEntryData->linenum); } return rc; }
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; }
int devtype_loadcfg(const char *path) { STREAM_DEVICE_T *pdev = NULL; STREAM_DEVICE_T *pdevprev = NULL; FILE_HANDLE fp; char buf[1024]; const char *p; int linenum = 1; int count = 0; PARSE_ENTRY_DATA_T parseData; if(!path) { return -1; } if(g_devtypes) { devtype_free(g_devtypes); g_devtypes = NULL; } if((fp = fileops_Open(path, O_RDONLY)) == FILEOPS_INVALID_FP) { LOG(X_ERROR("Unable to open metafile for reading: %s"), path); return -1; } while(fileops_fgets(buf, sizeof(buf) - 1, fp)) { p = buf; while(*p == ' ' || *p == '\t') { p++; } if(*p == '#') { continue; } memset(&parseData, 0, sizeof(parseData)); if(strutil_parse_csv(cbparse_entry_devtype, &parseData, p) < 0) { LOG(X_ERROR("Failed to parse line %d in file %s"), linenum, path); devtype_free(g_devtypes); break; } else if((parseData.flags & PARSE_FLAG_HAVE_ALL)) { if(!(pdev = create_device(parseData.devname, parseData.strmatch, parseData.strmatch2, parseData.methods, parseData.devtype))) { LOG(X_ERROR("Failed to create device config from line %d"), linenum); devtype_free(g_devtypes); break; } else if(pdevprev) { pdevprev->pnext = pdev; } else { g_devtypes = pdev; } pdevprev = pdev; count++; } else if(strlen(p) > 1) { LOG(X_WARNING("Incomplete line %d in file %s"), linenum, path); } linenum++; } fileops_Close(fp); LOG(X_DEBUG("Read %d device profiles from %s"), count, path); //devtype_dump(g_devtypes); return count; }