/* tsiproxy server commands */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libfuncs/libfuncs.h" #include "data.h" #include "conf.h" extern CONFIG *config; extern char *server_ver; extern LIST *netconf, *clients, *chanconf, *restreamer; extern STATS allstats; static void std_headers(int clientsock, char *IP) { fdputsf(clientsock, "X-IP: %s\n", IP); send_header_textplain(clientsock); fdputs(clientsock, "\n"); } void run_ping(unsigned int clientsock, acl_t acl, uint32_t src_ip, char *IP) { unused(src_ip); char flags[6] = "-----"; send_200_ok(clientsock); if (acl.stats ) flags[1] = 'S'; if (acl.reconf) flags[2] = 'F'; if (acl.access) flags[3] = 'A'; fdputsf(clientsock, "X-Access: %s\n", flags); std_headers(clientsock, IP); fdputs(clientsock, "PONG\n"); } int __show_stats(unsigned int clientsock, acl_t acl, char *IP) { if (!acl.stats) { LOGf("DENY : Stats access denied | IP: %s\n", IP); send_403_forbidden(clientsock); return 0; } send_200_ok(clientsock); std_headers(clientsock, IP); return 1; } void show_stats(unsigned int clientsock, acl_t acl, char *IP) { if (!__show_stats(clientsock, acl, IP)) return; time_t now = time(NULL); LNODE *l, *tmp; list_lock(clients); list_for_each_reverse(clients, l, tmp) { CLIENT *c = l->data; // Workaround for unknown bug that leaves records in clients list but not in restreamerX->clients list // Such a client hangs forever taking memory. The bug was seen on snaps server if (now - c->ts >= NO_TRAFFIC_SECONDS + 5) { list_unlock(clients); stop_client_shutdown(c); list_lock(clients); continue; } if (c->traffic_out == 0) continue; // IP A FD PROV CID TRA TM CHAN AGENT fdputsf(clientsock,"%s\t%c\t%i\t%-12s\t%lu\t%14llu\t%6lu\t%-22s\t%s\n", c->IP, '-', c->fno, "-", c->clientid, c->traffic_out, now - c->start, c->chan, c->agent); } list_unlock(clients); } int __show_info(unsigned int clientsock, acl_t acl, char *IP, unsigned long total_clients, unsigned long clients_current, unsigned long clients_gone, unsigned long long traffic_in, unsigned long long traffic_out) { int used_fds = -1; if (!acl.stats) { LOGf("DENY : Info access denied | IP: %s\n", IP); send_403_forbidden(clientsock); return 0; } time_t now = time(NULL); time_t uptime = now - allstats.start_ts; unsigned int t_sec,t_min,t_hour,t_days; struct rlimit limit; double load_avg[3]; t_sec = uptime % 60; t_min = (uptime - t_sec) / 60; t_hour = (t_min - t_min % 60) / 60; t_min = t_min - t_hour * 60; t_days = (t_hour - t_hour % 24) / 24; t_hour = t_hour - t_days * 24; getrlimit(RLIMIT_NOFILE, &limit); getloadavg(load_avg, 3); send_200_ok(clientsock); std_headers(clientsock, IP); fdputs (clientsock, "Server info\n"); fdputsf(clientsock, " Ident : %s\n", config->ident); fdputsf(clientsock, " Version : %s\n", server_ver); fdputsf(clientsock, " Server : %s %s %s %s %s\n", allstats.utsdata.sysname, allstats.utsdata.nodename, allstats.utsdata.release, allstats.utsdata.version, allstats.utsdata.machine); fdputsf(clientsock, " Cores : %ld\n", (long)sysconf(_SC_NPROCESSORS_ONLN)); DIR *d = opendir("/proc/self/fd"); if (d) { struct dirent *dir; while ((dir = readdir(d))) { if (dir->d_name[0] == '.') // Ignore . and .. continue; used_fds++; } closedir(d); } fdputsf(clientsock, " Max FDs : %ld\n",(long)limit.rlim_max); fdputsf(clientsock, " Used FDs : %ld\n",(long)used_fds); fdputsf(clientsock, " Load average : %4.2f %4.2f %4.2f\n",load_avg[0],load_avg[1],load_avg[2]); fdputsf(clientsock, " Localtime : %s", ctime(&now)); fdputsf(clientsock, " Uptime : %d %02d:%02d:%02d\n", t_days, t_hour, t_min, t_sec); fdputsf(clientsock, " Redirect : %s %s\n\n", config->redirect_url ? "enabled" : "disabled", config->redirect_url ? config->redirect_url : "" ); fdputs (clientsock, "Statistics\n"); fdputsf(clientsock, " Clients current : %lu\n", clients_current); fdputsf(clientsock, " Clients cur+gone : %lu\n", clients_current + clients_gone); fdputsf(clientsock, " Traffic in : %llu MB\n", traffic_in / (1024*1024)); fdputsf(clientsock, " Traffic out : %llu MB\n", traffic_out / (1024*1024)); fdputsf(clientsock, " Total clients : %lu\n\n", total_clients); return 1; } void show_info(unsigned int clientsock, acl_t acl, char *IP) { if (!__show_info(clientsock, acl, IP, allstats.clients, allstats.clients_current, allstats.clients_gone, allstats.traffic_in, allstats.traffic_out)) return; time_t now = time(NULL); time_t uptime = now - allstats.start_ts; fdputs (clientsock, "IPTVD statistics\n"); fdputsf(clientsock, " Proxies current : %u\n", restreamer->items); fdputsf(clientsock, " Restreamers : %lu\n", allstats.child_servers); fdputsf(clientsock, " Connects : %lu\n", allstats.clients_all); fdputsf(clientsock, " Errors : %lu\n", allstats.errors); fdputs (clientsock, " current cur+gone trafic_in traffic_out clients servers connects errors localtime uptime\n"); fdputsf(clientsock, "AllStats : %lu %lu %llu %llu %lu %lu %lu %lu %lu %lu\n\n", allstats.clients_current, allstats.clients_current + allstats.clients_gone, allstats.traffic_in, allstats.traffic_out, allstats.clients, allstats.child_servers, allstats.clients_all, allstats.errors, now, uptime); LNODE *l, *tmp; unsigned int t_sec,t_min,t_hour,t_days; fdputs(clientsock, "Running restreamers\n"); list_lock(restreamer); list_for_each_reverse(restreamer, l, tmp) { RESTREAMER *r = l->data; uptime = time(NULL) - r->started; t_sec = uptime % 60; t_min = (uptime - t_sec) / 60; t_hour = (t_min - t_min % 60) / 60; t_min = t_min - t_hour * 60; t_days = (t_hour - t_hour % 24) / 24; t_hour = t_hour - t_days * 24; fdputsf(clientsock," %-27sClients: %i Served: %li Conn: %li Uptime: %d %02d:%02d:%02d In: %lli %lli MB Out: %lli %lli MB\n", r->name, r->clients->items, r->served, r->connects, t_days, t_hour, t_min, t_sec, r->traffic_in, r->traffic_in / (1024*1024), r->traffic_out, r->traffic_out / (1024*1024) ); } list_unlock(restreamer); fdputs(clientsock,"\n"); } void run_livecheck(unsigned int clientsock, acl_t acl, char *IP) { if (!acl.reconf) { LOGf("DENY : LiveCheck access denied | IP: %s\n", IP); send_403_forbidden(clientsock); return; } send_200_ok(clientsock); std_headers(clientsock, IP); do { char outbuf[128]; int size; memset(outbuf, ' ', sizeof(outbuf)); outbuf[sizeof(outbuf)-1] = '\n'; STATS ls = allstats; sleep(1); time_t now = time(NULL); time_t uptime = now - allstats.start_ts; /* The traffic passed in the 1 second sleep above */ ls.traffic_in = allstats.traffic_in - ls.traffic_in; ls.traffic_out = allstats.traffic_out - ls.traffic_out; size = sprintf(outbuf, "%lu %lu %lu %u %llu %llu", now, uptime, allstats.clients_current, restreamer ? restreamer->items : 0, ls.traffic_in, ls.traffic_out); outbuf[size]=' '; if (fdwrite(clientsock, outbuf, sizeof(outbuf)) <= 0) break; } while (1); } void read_info(unsigned int clientsock, acl_t acl, char *IP) { if (!acl.stats) { LOGf("DENY : Info access denied | IP: %s\n", IP); send_403_forbidden(clientsock); return; } time_t now = time(NULL); time_t uptime = now - allstats.start_ts; send_200_ok(clientsock); std_headers(clientsock, IP); unsigned int gone = allstats.clients_gone; /* Reset it first because fdputsf can block */ allstats.clients_gone = 0; fdputsf(clientsock, "%lu %lu %llu %llu %lu %lu %lu %lu %lu %lu\n", allstats.clients_current, allstats.clients_current + gone, allstats.traffic_in, allstats.traffic_out, allstats.clients, allstats.child_servers, allstats.clients_all, allstats.errors, now, uptime); } void run_netconf(unsigned int clientsock, acl_t acl, char *IP) { if (!acl.reconf) { LOGf("DENY : NetConf access denied | IP: %s\n", IP); send_403_forbidden(clientsock); return; } int nets = load_networks(config); if (nets > -1) LOGf("CONF : NetConf reloaded | IP: %s Loaded: %i\n", IP, nets); send_200_ok(clientsock); std_headers(clientsock, IP); if (nets > -1) fdputsf(clientsock,"OK %i networks read\n", nets); else fdputs(clientsock,"Networks are already up to date\n"); } void run_chanconf(unsigned int clientsock, acl_t acl, char *IP) { if (!acl.reconf) { LOGf("DENY : ChanConf access denied | IP: %s\n", IP); send_403_forbidden(clientsock); return; } int j = load_channels(config); if (j > -1) LOGf("CONF : ChanConf reloaded | IP: %s Loaded: %i\n", IP, j); send_200_ok(clientsock); std_headers(clientsock, IP); if (j > -1) fdputsf(clientsock,"OK %i channels read\n",j); else fdputs(clientsock,"Channels are already up to date\n"); } void run_getnetconf(unsigned int clientsock, acl_t acl, char *IP) { if (!acl.reconf) { send_403_forbidden(clientsock); return; } send_200_ok(clientsock); std_headers(clientsock, IP); LNODE *l, *tmp; list_lock(netconf); list_for_each(netconf, l, tmp) { NETWORK *n = l->data; fdputsf(clientsock,"%d.%d.%d.%d/%d.%d.%d.%d\t%s%s%s\n", (n->net >> 0 ) & 0xFF, (n->net >> 8 ) & 0xFF, (n->net >> 16) & 0xFF, (n->net >> 24) & 0xFF, (n->mask >> 0 ) & 0xFF, (n->mask >> 8 ) & 0xFF, (n->mask >> 16) & 0xFF, (n->mask >> 24) & 0xFF, n->acl.stats ? "S" : "", n->acl.reconf ? "F" : "", n->acl.access ? "A" : "" ); } list_unlock(netconf); } void run_getchanconf(unsigned int clientsock, acl_t acl, char *IP) { if (!acl.reconf) { send_403_forbidden(clientsock); return; } send_200_ok(clientsock); std_headers(clientsock, IP); LNODE *l, *tmp; list_lock(chanconf); list_for_each(chanconf, l, tmp) { CHANNEL *c = l->data; int r = 0; while (c->sources[r] && r < MAX_CHANNEL_SOURCES) { fdputsf(clientsock,"%s\t%s\n", c->name, c->sources[r]); r++; } } list_unlock(chanconf); } void run_channels(unsigned int clientsock, acl_t acl, char *IP) { time_t now = time(NULL); LNODE *l, *tmp; if (!acl.stats) { LOGf("DENY : Channels access denied | IP: %s\n", IP); send_403_forbidden(clientsock); return; } send_200_ok(clientsock); std_headers(clientsock, IP); list_lock(restreamer); list_for_each_reverse(restreamer, l, tmp) { RESTREAMER *r = l->data; time_t uptime = now - r->started; fdputsf(clientsock,"%-20s\t%5i\t%5li\t%5li\t%7ld\t%12lli\t%12lli\n", r->name, r->clients->items, r->served, r->connects, uptime, r->traffic_in, r->traffic_out ); } list_unlock(restreamer); }