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.

data.c 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /* tsiproxy data functions */
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <arpa/inet.h>
  7. #include <netinet/in.h>
  8. #include <sys/utsname.h>
  9. #include <sys/resource.h>
  10. #include <fcntl.h>
  11. #include <errno.h>
  12. #include <regex.h>
  13. #include "libfuncs/libfuncs.h"
  14. #include "conf.h"
  15. #include "data.h"
  16. extern int clean_on_exit;
  17. extern LIST *clients;
  18. extern STATS allstats;
  19. extern CONFIG *config;
  20. channel_source get_sproto(char *url) {
  21. return strncmp(url, "http", 4)==0 ? tcp_sock : udp_sock;
  22. }
  23. CHANSRC *init_chansrc(char *url) {
  24. regex_t re;
  25. regmatch_t res[5];
  26. regcomp(&re, "^([a-z]+)://([^:/?]+):?([0-9]*)/?(.*)", REG_EXTENDED);
  27. if (regexec(&re,url,5,res,0)==0) {
  28. char *data = strdup(url);
  29. char *proto, *host, *port, *path;
  30. int iport;
  31. proto= data+res[1].rm_so; data[res[1].rm_eo]=0;
  32. host = data+res[2].rm_so; data[res[2].rm_eo]=0;
  33. port = data+res[3].rm_so; data[res[3].rm_eo]=0;
  34. path = data+res[4].rm_so; data[res[4].rm_eo]=0;
  35. iport = atoi(port);
  36. /* Setup */
  37. CHANSRC *src = calloc(1, sizeof(CHANSRC));
  38. src->proto = strdup(proto);
  39. src->sproto= get_sproto(url);
  40. src->host = strdup(host);
  41. src->port = iport ? iport : 80;
  42. src->path = strdup(path);
  43. FREE(data);
  44. regfree(&re);
  45. return src;
  46. }
  47. regfree(&re);
  48. return NULL;
  49. }
  50. void free_chansrc(CHANSRC *url) {
  51. if (url) {
  52. FREE(url->proto);
  53. FREE(url->host);
  54. FREE(url->path);
  55. FREE(url);
  56. }
  57. };
  58. int is_valid_url(char *url) {
  59. regex_t re;
  60. regmatch_t res[5];
  61. int ret;
  62. regcomp(&re, "^([a-z]+)://([^:/?]+):?([0-9]*)/?(.*)", REG_EXTENDED);
  63. ret = regexec(&re,url,5,res,0);
  64. regfree(&re);
  65. return ret == 0;
  66. }
  67. void add_channel_source(CHANNEL *c, char *src) {
  68. if (c->num_src >= MAX_CHANNEL_SOURCES-1)
  69. return;
  70. c->sources[c->num_src] = strdup(src);
  71. if (c->num_src == 0) /* Set default source to first one */
  72. c->source = c->sources[c->num_src];
  73. c->num_src++;
  74. }
  75. void next_channel_source(CHANNEL *c) {
  76. if (c->num_src <= 1)
  77. return;
  78. // uint8_t old_src = c->curr_src;
  79. c->curr_src++;
  80. if (c->curr_src >= MAX_CHANNEL_SOURCES-1 || c->sources[c->curr_src] == NULL)
  81. c->curr_src = 0;
  82. c->source = c->sources[c->curr_src];
  83. // LOGf("CHAN : Switch source | Channel: %s OldSrc: %d %s NewSrc: %d %s\n", c->name, old_src, c->sources[old_src], c->curr_src, c->source);
  84. }
  85. void set_channel_source(CHANNEL *c, uint8_t src_id) {
  86. if (src_id >= MAX_CHANNEL_SOURCES-1 || c->sources[src_id] == NULL)
  87. return;
  88. // uint8_t old_src = c->curr_src;
  89. c->curr_src = src_id;
  90. c->source = c->sources[c->curr_src];
  91. // LOGf("CHAN : Set source | Channel: %s OldSrc: %d %s NewSrc: %d %s\n", c->name, old_src, c->sources[old_src], c->curr_src, c->source);
  92. }
  93. CHANNEL * new_channel(char *name, char *source) {
  94. CHANNEL *c = calloc(1, sizeof(CHANNEL));
  95. c->name = strdup(name);
  96. add_channel_source(c, source);
  97. return c;
  98. }
  99. void free_channel(CHANNEL *c) {
  100. int i;
  101. for (i=c->num_src-1; i>=0; i--) {
  102. FREE(c->sources[i]);
  103. }
  104. FREE(c->name);
  105. c->source = NULL;
  106. FREE(c);
  107. }
  108. int channel_search(LIST *channels_list, char *name, CHANNEL **found_channel) {
  109. int found = 0;
  110. LNODE *l, *tmp;
  111. list_for_each(channels_list, l, tmp) {
  112. CHANNEL *c = l->data;
  113. if (strcmp(c->name, name) == 0) {
  114. *found_channel = c;
  115. found = 1;
  116. break;
  117. }
  118. }
  119. return found;
  120. }
  121. NETWORK * new_network(uint32_t net, uint32_t mask, acl_t acl) {
  122. NETWORK *n = calloc(1, sizeof(NETWORK));
  123. n->net = net;
  124. n->mask = mask;
  125. n->acl = acl;
  126. return n;
  127. }
  128. void free_network(NETWORK *n) {
  129. FREE(n);
  130. }
  131. int acl_search(LIST *acl_list, uint32_t search_ip, acl_t *found_acl) {
  132. int found = 0;
  133. LNODE *l, *tmp;
  134. list_lock(acl_list);
  135. list_for_each(acl_list, l, tmp) {
  136. NETWORK *n = l->data;
  137. if ((search_ip & n->mask) == n->net) {
  138. *found_acl = n->acl;
  139. found = 1;
  140. break;
  141. }
  142. }
  143. list_unlock(acl_list);
  144. return found;
  145. }
  146. RESTREAMER * new_restreamer(const char *name, CHANNEL *channel) {
  147. RESTREAMER *r = calloc(1, sizeof(RESTREAMER));
  148. r->started = time(NULL);
  149. r->name = strdup(name);
  150. r->sock = -1;
  151. r->queue = queue_new();
  152. r->clients = list_new("r->clients");
  153. r->channel = channel;
  154. return r;
  155. }
  156. void free_restreamer(RESTREAMER *r) {
  157. if (r->sock > -1)
  158. shutdown_fd(&(r->sock));
  159. if (r->freechannel)
  160. free_channel(r->channel);
  161. queue_free(&r->queue);
  162. list_free(&r->clients, (void (*)(void *))stop_client_shutdown, NULL);
  163. FREE(r->name);
  164. FREE(r);
  165. }
  166. int restreamer_stop(LIST *proxys, char *channel) {
  167. int matched = 0;
  168. LNODE *l, *tmp;
  169. list_lock(proxys);
  170. list_for_each(proxys, l, tmp) {
  171. RESTREAMER *r = l->data;
  172. int doit = !channel || strcmp(channel, r->channel->name) == 0;
  173. if (doit) {
  174. matched++;
  175. r->dienow = 1;
  176. }
  177. }
  178. list_unlock(proxys);
  179. return matched;
  180. }
  181. int restreamer_reconnect(LIST *proxys, char *channel) {
  182. int matched = 0;
  183. LNODE *l, *tmp;
  184. list_lock(proxys);
  185. list_for_each(proxys, l, tmp) {
  186. RESTREAMER *r = l->data;
  187. int doit = !channel || strcmp(channel, r->channel->name) == 0;
  188. if (doit) {
  189. matched++;
  190. r->reconnect = 1;
  191. }
  192. }
  193. list_unlock(proxys);
  194. return matched;
  195. }
  196. void restreamer_stop_all(LIST *proxys) {
  197. if (restreamer_stop(proxys, NULL)) {
  198. int max_loops = 30; // 3 seconds
  199. while (proxys->items > 0 && max_loops-- > 0)
  200. usleep(100000);
  201. if (proxys->items)
  202. clean_on_exit = 0;
  203. }
  204. }
  205. /* CLIENT FUNCTIONS */
  206. int is_child_server(char *user_agent, unsigned int client_id) {
  207. if (!user_agent)
  208. return 0;
  209. return client_id == 0 && strcasestr(user_agent,"iptvd") == user_agent;
  210. }
  211. int is_ext(char *path, char *ext) {
  212. return strncmp(ext, (path+strlen(path)-strlen(ext)), strlen(ext)) == 0;
  213. }
  214. CLIENT * new_client(int fd, time_t expire, char *chan, char *IP, char *agent, unsigned long clientid, acl_t acl, uint16_t client_port, int smart_client) {
  215. CLIENT *nc = calloc(sizeof(CLIENT),1);
  216. nc->fno = fd;
  217. nc->start = time(NULL);
  218. nc->ts = nc->start;
  219. nc->expire = expire;
  220. nc->chan = strdup(chan);
  221. nc->IP = strdup(IP);
  222. inet_pton(AF_INET, IP, &(nc->ip));
  223. nc->acl = acl;
  224. nc->clientid = clientid;
  225. nc->client_port = client_port;
  226. if (agent) {
  227. nc->agent = strdup(agent);
  228. nc->is_child_server = is_child_server(agent, clientid);
  229. }
  230. if (nc->is_child_server || smart_client)
  231. nc->smart_client = 1;
  232. list_add(clients, nc);
  233. set_sock_nonblock(fd);
  234. allstats.clients_all++;
  235. return nc;
  236. }
  237. static void __client_log_connect(CLIENT *c) {
  238. c->logged = 1;
  239. if (c->client_port == 0) {
  240. LOGf("NEW : fd: %i Valid: %li | Client: %lu IP: %s Channel: %s Agent: %s\n",
  241. c->fno,
  242. (c->expire < 0 ? c->expire : -(c->start - c->expire)),
  243. c->clientid, c->IP, c->chan, c->agent);
  244. } else {
  245. LOGf("NEW : fd: %i Valid: %li Port: %u | Client: %lu IP: %s Channel: %s Agent: %s\n",
  246. c->fno,
  247. (c->expire < 0 ? c->expire : -(c->start - c->expire)),
  248. c->client_port,
  249. c->clientid, c->IP, c->chan, c->agent);
  250. }
  251. allstats.clients_current++;
  252. if (c->is_child_server)
  253. allstats.child_servers++;
  254. else
  255. allstats.clients++;
  256. }
  257. void client_log_connect(CLIENT *c) {
  258. if (c->logged)
  259. return;
  260. __client_log_connect(c);
  261. }
  262. void client_log_disconnect(CLIENT *c, char mark) {
  263. if (!c->logged)
  264. return;
  265. allstats.clients_current--;
  266. allstats.clients_gone++;
  267. LOGf("STOP%c: fd: %i Bytes: %llu Seconds: %li | Client: %lu IP: %s Channel: %s Agent: %s\n",
  268. mark, c->fno, c->traffic_out, time(NULL)-c->start,
  269. c->clientid, c->IP, c->chan, c->agent);
  270. time_t now = time(NULL);
  271. if (now - c->start > NO_LOG_END_SECONDS) {
  272. if (c->traffic_out > 0) {
  273. char date[256];
  274. struct tm tmres;
  275. strftime(date,sizeof(date),"%d/%b/%Y:%H:%M:%S %z",localtime_r(&c->start, &tmres));
  276. LOGf("LOG{%s %li - [%s] \"%s %lu %s\" 200 %llu \"%lu\" \"%s\"}\n",c->IP,now-c->start,date,
  277. "-", c->clientid, c->chan, c->traffic_out, c->start, c->agent);
  278. }
  279. }
  280. }
  281. void free_client(CLIENT *c) {
  282. FREE(c->chan);
  283. FREE(c->IP);
  284. FREE(c->agent);
  285. FREE(c);
  286. }
  287. void stop_client(CLIENT *c, int socket_shutdown, char mark) {
  288. if (!c || c->stopping)
  289. return;
  290. c->stopping = 1;
  291. int client_socket = c->fno;
  292. client_log_disconnect(c, mark);
  293. list_del_entry(clients, c);
  294. free_client(c);
  295. if (socket_shutdown)
  296. shutdown_fd(&client_socket);
  297. }
  298. void stop_client_noshutdown(CLIENT *c) {
  299. stop_client(c, 0, ' ');
  300. }
  301. void stop_client_shutdown(CLIENT *c) {
  302. stop_client(c, 1, ' ');
  303. }
  304. void stop_client_shutdown_mark(CLIENT *c, char mark) {
  305. stop_client(c, 1, mark);
  306. }
  307. int control_client_stop(long clientid) {
  308. int found = 0;
  309. LNODE *l, *tmp;
  310. list_lock(clients);
  311. list_for_each(clients, l, tmp) {
  312. CLIENT *c = l->data;
  313. if (clientid == -1 || clientid == (long)c->clientid) {
  314. c->dienow = 1;
  315. found++;
  316. }
  317. }
  318. list_unlock(clients);
  319. return found;
  320. }
  321. int control_client_extend(unsigned long clientid, char *chan, time_t expire) {
  322. int found = 0;
  323. LNODE *l, *tmp;
  324. list_lock(clients);
  325. list_for_each(clients, l, tmp) {
  326. CLIENT *c = l->data;
  327. if (c->clientid == clientid && strcmp(chan, c->chan)==0) {
  328. c->expire = expire;
  329. found++;
  330. }
  331. }
  332. list_unlock(clients);
  333. return found;
  334. }
  335. int netmsg_send(long client_id, char *channel, char *netmsg) {
  336. int found = 0;
  337. LNODE *l, *tmp;
  338. list_lock(clients);
  339. list_for_each(clients, l, tmp) {
  340. CLIENT *c = l->data;
  341. int nsend = (client_id == -1 && !channel) || // Send to all clients
  342. (client_id == -1 && channel && strcmp(channel, c->chan)==0) || // Send to all clients on the channel X
  343. (client_id == (long)c->clientid && !channel) || // Send to client X
  344. (client_id == (long)c->clientid && channel && strcmp(channel, c->chan)==0); // Send to client X on the channel X
  345. if (nsend) {
  346. strncpy(c->netmsg, netmsg, sizeof(c->netmsg)-1);
  347. c->netmsg[sizeof(c->netmsg)-1] = 0;
  348. found++;
  349. }
  350. }
  351. list_unlock(clients);
  352. return found;
  353. }
  354. extern char TS_NULL_FRAME[FRAME_PACKET_SIZE];
  355. char *get_netmsg_packet(const char *msg) {
  356. if (!strlen(msg) || strlen(msg) > 60)
  357. return NULL;
  358. char *ret = (char *)calloc(1, FRAME_PACKET_SIZE);
  359. memcpy(ret, TS_NULL_FRAME, FRAME_PACKET_SIZE);
  360. int i;
  361. for (i=0; i<7; i++) {
  362. int ofs = i * 188;
  363. ret[ofs + 60] = 0x78;
  364. ret[ofs + 61] = 0x55;
  365. ret[ofs + 62] = 0x58;
  366. ret[ofs + 63] = 0x78;
  367. strcpy(ret + ofs + 64, msg);
  368. }
  369. return ret;
  370. }
  371. int is_netmsg_packet(const unsigned char *buf, int bufsize) {
  372. if (bufsize < 64 || bufsize > FRAME_PACKET_SIZE)
  373. return 0;
  374. if (buf[1] != 0x1f && buf[2] != 0xff) // Look only at NULL packets
  375. return 0;
  376. // xUXx
  377. if (buf[60] == 0x78 && buf[61] == 0x55 && buf[62] == 0x58 && buf[63] == 0x78)
  378. return 1;
  379. return 0;
  380. }