123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /* tsiproxy server configuration */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/time.h>
-
- #include <fcntl.h>
- #include <errno.h>
- #include <regex.h>
- #include <pthread.h>
-
- #include "libfuncs/libfuncs.h"
-
- #include "data.h"
- #include "conf.h"
-
- extern LIST *netconf, *chanconf, *restreamer;
-
- static pthread_mutex_t networks_lock = PTHREAD_MUTEX_INITIALIZER;
- static pthread_mutex_t channels_lock = PTHREAD_MUTEX_INITIALIZER;
-
- int load_channels(CONFIG *config) {
- regex_t re;
- regmatch_t res[3];
- char line[1024];
- int fd;
- int num_channels = 0;
-
- if (pthread_mutex_trylock(&channels_lock) != 0)
- return -1;
-
- fd = open(config->channels_file, O_RDONLY);
-
- if (fd != -1) {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- unsigned int randstate = tv.tv_usec;
- int cookie = rand_r(&randstate);
-
- regcomp(&re, "^([A-Za-z0-9/\\.]+)\t+([A-Za-z0-9/\\.:-]+)", REG_EXTENDED);
- time_t curtime = time(NULL);
- LIST *old_chanconf;
- LIST *new_chanconf = list_new("chanconf");
- while (fdgetline(fd,line,sizeof(line)) > 0) {
- chomp(line);
- if (regexec(&re,line,3,res,0)==0) {
- char *name, *source;
- char *org = strdup(line);
- name = org+res[1].rm_so; org[res[1].rm_eo]=0;
- source = org+res[2].rm_so; org[res[2].rm_eo]=0;
- if (!is_valid_url(source)) {
- LOGf("CCONF: Invalid url: %s\n", source);
- FREE(org);
- goto report_error;
- }
- /* Search for already added channel */
- LNODE *l, *tmp;
- CHANNEL *chan = NULL;
- list_for_each_reverse(new_chanconf, l, tmp) {
- if (strcmp(name, ((CHANNEL *)l->data)->name)==0) {
- chan = l->data;
- break;
- }
- }
- if (!chan) {
- list_add(new_chanconf, new_channel(name, source));
- num_channels++;
- } else {
- add_channel_source(chan, source);
- }
- FREE(org);
- } else {
- report_error:
- if (strlen(line) > 2 && line[0] != '#') {
- LOGf("CCONF: Invalid config line: %s\n", line);
- }
- }
- if (time(NULL) - curtime > CONFIG_LOAD_TIMEOUT) {
- LOGf("CCONF: Read timeout after %d lines on %s\n", num_channels, line);
- break;
- }
- }
- regfree(&re);
- shutdown_fd(&fd);
- /* Save current chanconf */
- old_chanconf = chanconf;
- /* Switch chanconf */
- chanconf = new_chanconf;
- /* Rewrite restreamer channels */
- LNODE *lc, *lr, *lctmp, *lrtmp;
- CHANNEL *chan;
- list_lock(restreamer); // Unlocked after second list_for_each(restreamer)
-
- list_lock(chanconf);
- list_for_each(chanconf, lc, lctmp) {
- chan = lc->data;
- list_for_each(restreamer, lr, lrtmp) {
- if (strcmp(chan->name, ((RESTREAMER *)lr->data)->name)==0) {
- RESTREAMER *restr = lr->data;
- /* Mark the restreamer as valid */
- restr->cookie = cookie;
- /* Check if current source exists in new channel configuration */
- int i, src_found = -1;
- char *old_source = restr->channel->source;
- for (i=0; i<chan->num_src; i++) {
- if (strcmp(old_source, chan->sources[i]) == 0) {
- src_found = i;
- }
- }
- if (src_found > -1) {
- /* New configuration contains existing source, just update the reference */
- set_channel_source(chan, src_found);
- restr->channel = chan;
- } else {
- /* New configuration *DO NOT* contain existing source. Force reconnect */
- LOGf("RESTR: Source changed | Channel: %s srv_fd: %d Old:%s New:%s\n", chan->name, restr->sock, restr->channel->source, chan->source);
- /* The order is important! */
- set_channel_source(chan, chan->num_src-1); /* Set source to last one. On reconnect next source will be used. */
- restr->channel = chan;
- restr->reconnect = 1;
- }
- break;
- }
- }
- }
- list_unlock(chanconf);
-
- /* Kill restreamers that serve channels that no longer exist */
- list_for_each(restreamer, lr, lrtmp) {
- RESTREAMER *r = lr->data;
- /* This restreamer should no longer serve clients */
- if (r->cookie != cookie) {
- LOGf("RESTR: Channel removed | Channel: %s Source: %s\n", r->channel->name, r->channel->source);
- /* Replace channel reference with real object and instruct free_restreamer to free it */
- r->channel = new_channel(r->channel->name, r->channel->source);
- r->freechannel = 1;
- r->dienow = 1;
- }
- }
- list_unlock(restreamer);
-
- /* Free old_chanconf */
- list_free(&old_chanconf, (void (*)(void *))free_channel, NULL);
- } else {
- num_channels = -1;
- }
- pthread_mutex_unlock(&channels_lock);
- return num_channels;
- }
-
- int load_networks(CONFIG *config) {
- char line[1024];
- regex_t re;
- regmatch_t res[8];
- int fd;
- int num_networks = 0;
-
- if (pthread_mutex_trylock(&networks_lock) != 0)
- return -1;
-
- fd = open(config->networks_file, O_RDONLY);
-
- if (fd != -1) {
- regcomp(&re,"^([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})/([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})\t*([CFNSA]*)", REG_EXTENDED);
- time_t curtime = time(NULL);
- LIST *new_netconf = list_new("netconf");
- while (fdgetline(fd,line,sizeof(line))>0){
- if (regexec(&re,line,4,res,0)==0){
- chomp(line);
- char *_net, *_mask, *_flags;
- _net = line+res[1].rm_so; line[res[1].rm_eo]=0;
- _mask = line+res[2].rm_so; line[res[2].rm_eo]=0;
- _flags= line+res[3].rm_so; line[res[3].rm_eo]=0;
-
- uint32_t net, mask;
- inet_pton(AF_INET, _net, &net);
- inet_pton(AF_INET,_mask, &mask);
- net = net & mask;
-
- acl_t acl;
- acl.reconf = strchr(_flags,'F') != NULL;
- acl.stats = strchr(_flags,'S') != NULL;
- acl.access = strchr(_flags,'A') != NULL; // bg network?
-
- list_add(new_netconf, new_network(net, mask, acl));
- num_networks++;
- } else {
- if (strlen(line) > 2 && line[0] != '#') {
- LOGf("NCONF: Invalid config line: %s\n", line);
- }
- }
- if (time(NULL) - curtime > CONFIG_LOAD_TIMEOUT) {
- LOGf("NCONF: Read timeout after %d lines on %s\n", num_networks, line);
- break;
- }
- }
- regfree(&re);
- shutdown_fd(&fd);
- /* Save current netconf */
- LIST *old_netconf = netconf;
- /* Switch chanconf */
- netconf = new_netconf;
- /* Free old_netconf */
- list_free(&old_netconf, (void (*)(void *))free_network, NULL);
- } else {
- num_networks = -1;
- }
- pthread_mutex_unlock(&networks_lock);
- return num_networks;
- }
-
- CONFIG *config_alloc(void) {
- CONFIG *c = calloc(1, sizeof(CONFIG));
- c->server_port = 8080;
- return c;
- }
-
- int config_redirect_enabled(CONFIG *conf, int clientsock, char *path) {
- char *url;
- if (!conf->redirect_url)
- return 0;
- asprintf(&url, "%s%s", conf->redirect_url, path);
- send_302_redirect(clientsock, url);
- free(url);
- return 1;
- }
-
- void config_free(CONFIG **pconf) {
- CONFIG *conf = *pconf;
- if (conf) {
- if (conf->pidfile)
- unlink(conf->pidfile);
- FREE(conf->host_ptr);
- FREE(conf->logident);
- FREE(conf->redirect_url);
- FREE(*pconf);
- }
- }
|