No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

conf.c 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /* tsiproxy server configuration */
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <sys/time.h>
  7. #include <fcntl.h>
  8. #include <errno.h>
  9. #include <regex.h>
  10. #include <pthread.h>
  11. #include "libfuncs/libfuncs.h"
  12. #include "data.h"
  13. #include "conf.h"
  14. extern LIST *netconf, *chanconf, *restreamer;
  15. static pthread_mutex_t networks_lock = PTHREAD_MUTEX_INITIALIZER;
  16. static pthread_mutex_t channels_lock = PTHREAD_MUTEX_INITIALIZER;
  17. int load_channels(CONFIG *config) {
  18. regex_t re;
  19. regmatch_t res[3];
  20. char line[1024];
  21. int fd;
  22. int num_channels = 0;
  23. if (pthread_mutex_trylock(&channels_lock) != 0)
  24. return -1;
  25. fd = open(config->channels_file, O_RDONLY);
  26. if (fd != -1) {
  27. struct timeval tv;
  28. gettimeofday(&tv, NULL);
  29. unsigned int randstate = tv.tv_usec;
  30. int cookie = rand_r(&randstate);
  31. regcomp(&re, "^([A-Za-z0-9/\\.]+)\t+([A-Za-z0-9/\\.:-]+)", REG_EXTENDED);
  32. time_t curtime = time(NULL);
  33. LIST *old_chanconf;
  34. LIST *new_chanconf = list_new("chanconf");
  35. while (fdgetline(fd,line,sizeof(line)) > 0) {
  36. chomp(line);
  37. if (regexec(&re,line,3,res,0)==0) {
  38. char *name, *source;
  39. char *org = strdup(line);
  40. name = org+res[1].rm_so; org[res[1].rm_eo]=0;
  41. source = org+res[2].rm_so; org[res[2].rm_eo]=0;
  42. if (!is_valid_url(source)) {
  43. LOGf("CCONF: Invalid url: %s\n", source);
  44. FREE(org);
  45. goto report_error;
  46. }
  47. /* Search for already added channel */
  48. LNODE *l, *tmp;
  49. CHANNEL *chan = NULL;
  50. list_for_each_reverse(new_chanconf, l, tmp) {
  51. if (strcmp(name, ((CHANNEL *)l->data)->name)==0) {
  52. chan = l->data;
  53. break;
  54. }
  55. }
  56. if (!chan) {
  57. list_add(new_chanconf, new_channel(name, source));
  58. num_channels++;
  59. } else {
  60. add_channel_source(chan, source);
  61. }
  62. FREE(org);
  63. } else {
  64. report_error:
  65. if (strlen(line) > 2 && line[0] != '#') {
  66. LOGf("CCONF: Invalid config line: %s\n", line);
  67. }
  68. }
  69. if (time(NULL) - curtime > CONFIG_LOAD_TIMEOUT) {
  70. LOGf("CCONF: Read timeout after %d lines on %s\n", num_channels, line);
  71. break;
  72. }
  73. }
  74. regfree(&re);
  75. shutdown_fd(&fd);
  76. /* Save current chanconf */
  77. old_chanconf = chanconf;
  78. /* Switch chanconf */
  79. chanconf = new_chanconf;
  80. /* Rewrite restreamer channels */
  81. LNODE *lc, *lr, *lctmp, *lrtmp;
  82. CHANNEL *chan;
  83. list_lock(restreamer); // Unlocked after second list_for_each(restreamer)
  84. list_lock(chanconf);
  85. list_for_each(chanconf, lc, lctmp) {
  86. chan = lc->data;
  87. list_for_each(restreamer, lr, lrtmp) {
  88. if (strcmp(chan->name, ((RESTREAMER *)lr->data)->name)==0) {
  89. RESTREAMER *restr = lr->data;
  90. /* Mark the restreamer as valid */
  91. restr->cookie = cookie;
  92. /* Check if current source exists in new channel configuration */
  93. int i, src_found = -1;
  94. char *old_source = restr->channel->source;
  95. for (i=0; i<chan->num_src; i++) {
  96. if (strcmp(old_source, chan->sources[i]) == 0) {
  97. src_found = i;
  98. }
  99. }
  100. if (src_found > -1) {
  101. /* New configuration contains existing source, just update the reference */
  102. set_channel_source(chan, src_found);
  103. restr->channel = chan;
  104. } else {
  105. /* New configuration *DO NOT* contain existing source. Force reconnect */
  106. LOGf("RESTR: Source changed | Channel: %s srv_fd: %d Old:%s New:%s\n", chan->name, restr->sock, restr->channel->source, chan->source);
  107. /* The order is important! */
  108. set_channel_source(chan, chan->num_src-1); /* Set source to last one. On reconnect next source will be used. */
  109. restr->channel = chan;
  110. restr->reconnect = 1;
  111. }
  112. break;
  113. }
  114. }
  115. }
  116. list_unlock(chanconf);
  117. /* Kill restreamers that serve channels that no longer exist */
  118. list_for_each(restreamer, lr, lrtmp) {
  119. RESTREAMER *r = lr->data;
  120. /* This restreamer should no longer serve clients */
  121. if (r->cookie != cookie) {
  122. LOGf("RESTR: Channel removed | Channel: %s Source: %s\n", r->channel->name, r->channel->source);
  123. /* Replace channel reference with real object and instruct free_restreamer to free it */
  124. r->channel = new_channel(r->channel->name, r->channel->source);
  125. r->freechannel = 1;
  126. r->dienow = 1;
  127. }
  128. }
  129. list_unlock(restreamer);
  130. /* Free old_chanconf */
  131. list_free(&old_chanconf, (void (*)(void *))free_channel, NULL);
  132. } else {
  133. num_channels = -1;
  134. }
  135. pthread_mutex_unlock(&channels_lock);
  136. return num_channels;
  137. }
  138. int load_networks(CONFIG *config) {
  139. char line[1024];
  140. regex_t re;
  141. regmatch_t res[8];
  142. int fd;
  143. int num_networks = 0;
  144. if (pthread_mutex_trylock(&networks_lock) != 0)
  145. return -1;
  146. fd = open(config->networks_file, O_RDONLY);
  147. if (fd != -1) {
  148. 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);
  149. time_t curtime = time(NULL);
  150. LIST *new_netconf = list_new("netconf");
  151. while (fdgetline(fd,line,sizeof(line))>0){
  152. if (regexec(&re,line,4,res,0)==0){
  153. chomp(line);
  154. char *_net, *_mask, *_flags;
  155. _net = line+res[1].rm_so; line[res[1].rm_eo]=0;
  156. _mask = line+res[2].rm_so; line[res[2].rm_eo]=0;
  157. _flags= line+res[3].rm_so; line[res[3].rm_eo]=0;
  158. uint32_t net, mask;
  159. inet_pton(AF_INET, _net, &net);
  160. inet_pton(AF_INET,_mask, &mask);
  161. net = net & mask;
  162. acl_t acl;
  163. acl.reconf = strchr(_flags,'F') != NULL;
  164. acl.stats = strchr(_flags,'S') != NULL;
  165. acl.access = strchr(_flags,'A') != NULL; // bg network?
  166. list_add(new_netconf, new_network(net, mask, acl));
  167. num_networks++;
  168. } else {
  169. if (strlen(line) > 2 && line[0] != '#') {
  170. LOGf("NCONF: Invalid config line: %s\n", line);
  171. }
  172. }
  173. if (time(NULL) - curtime > CONFIG_LOAD_TIMEOUT) {
  174. LOGf("NCONF: Read timeout after %d lines on %s\n", num_networks, line);
  175. break;
  176. }
  177. }
  178. regfree(&re);
  179. shutdown_fd(&fd);
  180. /* Save current netconf */
  181. LIST *old_netconf = netconf;
  182. /* Switch chanconf */
  183. netconf = new_netconf;
  184. /* Free old_netconf */
  185. list_free(&old_netconf, (void (*)(void *))free_network, NULL);
  186. } else {
  187. num_networks = -1;
  188. }
  189. pthread_mutex_unlock(&networks_lock);
  190. return num_networks;
  191. }
  192. CONFIG *config_alloc(void) {
  193. CONFIG *c = calloc(1, sizeof(CONFIG));
  194. c->server_port = 8080;
  195. return c;
  196. }
  197. int config_redirect_enabled(CONFIG *conf, int clientsock, char *path) {
  198. char *url;
  199. if (!conf->redirect_url)
  200. return 0;
  201. asprintf(&url, "%s%s", conf->redirect_url, path);
  202. send_302_redirect(clientsock, url);
  203. free(url);
  204. return 1;
  205. }
  206. void config_free(CONFIG **pconf) {
  207. CONFIG *conf = *pconf;
  208. if (conf) {
  209. if (conf->pidfile)
  210. unlink(conf->pidfile);
  211. FREE(conf->host_ptr);
  212. FREE(conf->logident);
  213. FREE(conf->redirect_url);
  214. FREE(*pconf);
  215. }
  216. }