123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- /* tsiproxy data functions */
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <sys/utsname.h>
- #include <sys/resource.h>
-
- #include <fcntl.h>
- #include <errno.h>
- #include <regex.h>
-
- #include "libfuncs/libfuncs.h"
-
- #include "conf.h"
- #include "data.h"
-
- extern int clean_on_exit;
- extern LIST *clients;
- extern STATS allstats;
- extern CONFIG *config;
-
- channel_source get_sproto(char *url) {
- return strncmp(url, "http", 4)==0 ? tcp_sock : udp_sock;
- }
-
- CHANSRC *init_chansrc(char *url) {
- regex_t re;
- regmatch_t res[5];
- regcomp(&re, "^([a-z]+)://([^:/?]+):?([0-9]*)/?(.*)", REG_EXTENDED);
- if (regexec(&re,url,5,res,0)==0) {
- char *data = strdup(url);
- char *proto, *host, *port, *path;
- int iport;
- proto= data+res[1].rm_so; data[res[1].rm_eo]=0;
- host = data+res[2].rm_so; data[res[2].rm_eo]=0;
- port = data+res[3].rm_so; data[res[3].rm_eo]=0;
- path = data+res[4].rm_so; data[res[4].rm_eo]=0;
- iport = atoi(port);
- /* Setup */
- CHANSRC *src = calloc(1, sizeof(CHANSRC));
- src->proto = strdup(proto);
- src->sproto= get_sproto(url);
- src->host = strdup(host);
- src->port = iport ? iport : 80;
- src->path = strdup(path);
- FREE(data);
- regfree(&re);
- return src;
- }
- regfree(&re);
- return NULL;
- }
-
- void free_chansrc(CHANSRC *url) {
- if (url) {
- FREE(url->proto);
- FREE(url->host);
- FREE(url->path);
- FREE(url);
- }
- };
-
- int is_valid_url(char *url) {
- regex_t re;
- regmatch_t res[5];
- int ret;
- regcomp(&re, "^([a-z]+)://([^:/?]+):?([0-9]*)/?(.*)", REG_EXTENDED);
- ret = regexec(&re,url,5,res,0);
- regfree(&re);
- return ret == 0;
- }
-
- void add_channel_source(CHANNEL *c, char *src) {
- if (c->num_src >= MAX_CHANNEL_SOURCES-1)
- return;
- c->sources[c->num_src] = strdup(src);
- if (c->num_src == 0) /* Set default source to first one */
- c->source = c->sources[c->num_src];
- c->num_src++;
- }
-
- void next_channel_source(CHANNEL *c) {
- if (c->num_src <= 1)
- return;
- // uint8_t old_src = c->curr_src;
- c->curr_src++;
- if (c->curr_src >= MAX_CHANNEL_SOURCES-1 || c->sources[c->curr_src] == NULL)
- c->curr_src = 0;
- c->source = c->sources[c->curr_src];
- // 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);
- }
-
- void set_channel_source(CHANNEL *c, uint8_t src_id) {
- if (src_id >= MAX_CHANNEL_SOURCES-1 || c->sources[src_id] == NULL)
- return;
- // uint8_t old_src = c->curr_src;
- c->curr_src = src_id;
- c->source = c->sources[c->curr_src];
- // 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);
- }
-
- CHANNEL * new_channel(char *name, char *source) {
- CHANNEL *c = calloc(1, sizeof(CHANNEL));
- c->name = strdup(name);
- add_channel_source(c, source);
- return c;
- }
-
- void free_channel(CHANNEL *c) {
- int i;
- for (i=c->num_src-1; i>=0; i--) {
- FREE(c->sources[i]);
- }
- FREE(c->name);
- c->source = NULL;
- FREE(c);
- }
-
- int channel_search(LIST *channels_list, char *name, CHANNEL **found_channel) {
- int found = 0;
- LNODE *l, *tmp;
- list_for_each(channels_list, l, tmp) {
- CHANNEL *c = l->data;
- if (strcmp(c->name, name) == 0) {
- *found_channel = c;
- found = 1;
- break;
- }
- }
- return found;
- }
-
-
- NETWORK * new_network(uint32_t net, uint32_t mask, acl_t acl) {
- NETWORK *n = calloc(1, sizeof(NETWORK));
- n->net = net;
- n->mask = mask;
- n->acl = acl;
- return n;
- }
-
- void free_network(NETWORK *n) {
- FREE(n);
- }
-
- int acl_search(LIST *acl_list, uint32_t search_ip, acl_t *found_acl) {
- int found = 0;
- LNODE *l, *tmp;
- list_lock(acl_list);
- list_for_each(acl_list, l, tmp) {
- NETWORK *n = l->data;
- if ((search_ip & n->mask) == n->net) {
- *found_acl = n->acl;
- found = 1;
- break;
- }
- }
- list_unlock(acl_list);
- return found;
- }
-
- RESTREAMER * new_restreamer(const char *name, CHANNEL *channel) {
- RESTREAMER *r = calloc(1, sizeof(RESTREAMER));
- r->started = time(NULL);
- r->name = strdup(name);
- r->sock = -1;
- r->queue = queue_new();
- r->clients = list_new("r->clients");
- r->channel = channel;
- return r;
- }
-
- void free_restreamer(RESTREAMER *r) {
- if (r->sock > -1)
- shutdown_fd(&(r->sock));
- if (r->freechannel)
- free_channel(r->channel);
- queue_free(&r->queue);
- list_free(&r->clients, (void (*)(void *))stop_client_shutdown, NULL);
- FREE(r->name);
- FREE(r);
- }
-
- int restreamer_stop(LIST *proxys, char *channel) {
- int matched = 0;
- LNODE *l, *tmp;
- list_lock(proxys);
- list_for_each(proxys, l, tmp) {
- RESTREAMER *r = l->data;
- int doit = !channel || strcmp(channel, r->channel->name) == 0;
- if (doit) {
- matched++;
- r->dienow = 1;
- }
- }
- list_unlock(proxys);
- return matched;
- }
-
- int restreamer_reconnect(LIST *proxys, char *channel) {
- int matched = 0;
- LNODE *l, *tmp;
- list_lock(proxys);
- list_for_each(proxys, l, tmp) {
- RESTREAMER *r = l->data;
- int doit = !channel || strcmp(channel, r->channel->name) == 0;
- if (doit) {
- matched++;
- r->reconnect = 1;
- }
- }
- list_unlock(proxys);
- return matched;
- }
-
- void restreamer_stop_all(LIST *proxys) {
- if (restreamer_stop(proxys, NULL)) {
- int max_loops = 30; // 3 seconds
- while (proxys->items > 0 && max_loops-- > 0)
- usleep(100000);
- if (proxys->items)
- clean_on_exit = 0;
- }
- }
-
-
- /* CLIENT FUNCTIONS */
-
- int is_child_server(char *user_agent, unsigned int client_id) {
- if (!user_agent)
- return 0;
- return client_id == 0 && strcasestr(user_agent,"iptvd") == user_agent;
- }
-
- int is_ext(char *path, char *ext) {
- return strncmp(ext, (path+strlen(path)-strlen(ext)), strlen(ext)) == 0;
- }
-
- 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) {
- CLIENT *nc = calloc(sizeof(CLIENT),1);
-
- nc->fno = fd;
- nc->start = time(NULL);
- nc->ts = nc->start;
- nc->expire = expire;
- nc->chan = strdup(chan);
- nc->IP = strdup(IP);
- inet_pton(AF_INET, IP, &(nc->ip));
- nc->acl = acl;
- nc->clientid = clientid;
- nc->client_port = client_port;
- if (agent) {
- nc->agent = strdup(agent);
- nc->is_child_server = is_child_server(agent, clientid);
- }
- if (nc->is_child_server || smart_client)
- nc->smart_client = 1;
- list_add(clients, nc);
- set_sock_nonblock(fd);
- allstats.clients_all++;
- return nc;
- }
-
- static void __client_log_connect(CLIENT *c) {
- c->logged = 1;
- if (c->client_port == 0) {
- LOGf("NEW : fd: %i Valid: %li | Client: %lu IP: %s Channel: %s Agent: %s\n",
- c->fno,
- (c->expire < 0 ? c->expire : -(c->start - c->expire)),
- c->clientid, c->IP, c->chan, c->agent);
- } else {
- LOGf("NEW : fd: %i Valid: %li Port: %u | Client: %lu IP: %s Channel: %s Agent: %s\n",
- c->fno,
- (c->expire < 0 ? c->expire : -(c->start - c->expire)),
- c->client_port,
- c->clientid, c->IP, c->chan, c->agent);
- }
- allstats.clients_current++;
- if (c->is_child_server)
- allstats.child_servers++;
- else
- allstats.clients++;
- }
-
- void client_log_connect(CLIENT *c) {
- if (c->logged)
- return;
- __client_log_connect(c);
- }
-
- void client_log_disconnect(CLIENT *c, char mark) {
- if (!c->logged)
- return;
- allstats.clients_current--;
- allstats.clients_gone++;
- LOGf("STOP%c: fd: %i Bytes: %llu Seconds: %li | Client: %lu IP: %s Channel: %s Agent: %s\n",
- mark, c->fno, c->traffic_out, time(NULL)-c->start,
- c->clientid, c->IP, c->chan, c->agent);
- time_t now = time(NULL);
- if (now - c->start > NO_LOG_END_SECONDS) {
- if (c->traffic_out > 0) {
- char date[256];
- struct tm tmres;
- strftime(date,sizeof(date),"%d/%b/%Y:%H:%M:%S %z",localtime_r(&c->start, &tmres));
- LOGf("LOG{%s %li - [%s] \"%s %lu %s\" 200 %llu \"%lu\" \"%s\"}\n",c->IP,now-c->start,date,
- "-", c->clientid, c->chan, c->traffic_out, c->start, c->agent);
- }
- }
- }
-
- void free_client(CLIENT *c) {
- FREE(c->chan);
- FREE(c->IP);
- FREE(c->agent);
- FREE(c);
- }
-
- void stop_client(CLIENT *c, int socket_shutdown, char mark) {
- if (!c || c->stopping)
- return;
- c->stopping = 1;
- int client_socket = c->fno;
- client_log_disconnect(c, mark);
- list_del_entry(clients, c);
- free_client(c);
- if (socket_shutdown)
- shutdown_fd(&client_socket);
- }
-
- void stop_client_noshutdown(CLIENT *c) {
- stop_client(c, 0, ' ');
- }
-
- void stop_client_shutdown(CLIENT *c) {
- stop_client(c, 1, ' ');
- }
-
- void stop_client_shutdown_mark(CLIENT *c, char mark) {
- stop_client(c, 1, mark);
- }
-
- int control_client_stop(long clientid) {
- int found = 0;
- LNODE *l, *tmp;
- list_lock(clients);
- list_for_each(clients, l, tmp) {
- CLIENT *c = l->data;
- if (clientid == -1 || clientid == (long)c->clientid) {
- c->dienow = 1;
- found++;
- }
- }
- list_unlock(clients);
- return found;
- }
-
- int control_client_extend(unsigned long clientid, char *chan, time_t expire) {
- int found = 0;
- LNODE *l, *tmp;
- list_lock(clients);
- list_for_each(clients, l, tmp) {
- CLIENT *c = l->data;
- if (c->clientid == clientid && strcmp(chan, c->chan)==0) {
- c->expire = expire;
- found++;
- }
- }
- list_unlock(clients);
- return found;
- }
-
- int netmsg_send(long client_id, char *channel, char *netmsg) {
- int found = 0;
- LNODE *l, *tmp;
- list_lock(clients);
- list_for_each(clients, l, tmp) {
- CLIENT *c = l->data;
- int nsend = (client_id == -1 && !channel) || // Send to all clients
- (client_id == -1 && channel && strcmp(channel, c->chan)==0) || // Send to all clients on the channel X
- (client_id == (long)c->clientid && !channel) || // Send to client X
- (client_id == (long)c->clientid && channel && strcmp(channel, c->chan)==0); // Send to client X on the channel X
- if (nsend) {
- strncpy(c->netmsg, netmsg, sizeof(c->netmsg)-1);
- c->netmsg[sizeof(c->netmsg)-1] = 0;
- found++;
- }
- }
- list_unlock(clients);
- return found;
- }
-
- extern char TS_NULL_FRAME[FRAME_PACKET_SIZE];
-
- char *get_netmsg_packet(const char *msg) {
- if (!strlen(msg) || strlen(msg) > 60)
- return NULL;
- char *ret = (char *)calloc(1, FRAME_PACKET_SIZE);
- memcpy(ret, TS_NULL_FRAME, FRAME_PACKET_SIZE);
- int i;
- for (i=0; i<7; i++) {
- int ofs = i * 188;
- ret[ofs + 60] = 0x78;
- ret[ofs + 61] = 0x55;
- ret[ofs + 62] = 0x58;
- ret[ofs + 63] = 0x78;
- strcpy(ret + ofs + 64, msg);
- }
- return ret;
- }
-
- int is_netmsg_packet(const unsigned char *buf, int bufsize) {
- if (bufsize < 64 || bufsize > FRAME_PACKET_SIZE)
- return 0;
- if (buf[1] != 0x1f && buf[2] != 0xff) // Look only at NULL packets
- return 0;
- // xUXx
- if (buf[60] == 0x78 && buf[61] == 0x55 && buf[62] == 0x58 && buf[63] == 0x78)
- return 1;
- return 0;
- }
|