#include #include #include #include #include #include #include #include #include "poller.h" #include "control.h" #include "control_udp.h" #include "aux.h" #include "log.h" #include "call.h" #include "kernel.h" #define die(x...) do { fprintf(stderr, x); exit(-1); } while(0) static char *pidfile; static gboolean foreground; static u_int32_t ip; static u_int32_t listenp; static u_int16_t listenport; static u_int32_t udp_listenp; static u_int16_t udp_listenport; static int tos; static int table; static int timeout; static int silent_timeout; static void signals(void) { signal(SIGPIPE, SIG_IGN); } static int rlim(int res, rlim_t val) { struct rlimit rlim; ZERO(rlim); rlim.rlim_cur = rlim.rlim_max = val; return setrlimit(res, &rlim); } static void resources(void) { int tryv; rlim(RLIMIT_CORE, RLIM_INFINITY); for (tryv = ((1<<16) - 1); tryv && rlim(RLIMIT_NOFILE, tryv) == -1; tryv >>= 1) ; rlim(RLIMIT_DATA, RLIM_INFINITY); rlim(RLIMIT_RSS, RLIM_INFINITY); rlim(RLIMIT_AS, RLIM_INFINITY); } static int parse_ip_port(u_int32_t *ip, u_int16_t *port, char *s) { char *p = NULL; int ret = -1; p = strchr(s, ':'); if (p) { *p++ = 0; *ip = inet_addr(s); if (*ip == -1) goto out; *port = atoi(p); } else { *ip = 0; if (strchr(s, '.')) goto out; *port = atoi(s); } if (!*port) goto out; ret = 0; out: if (p) *--p = ':'; return ret; } static void options(int *argc, char ***argv) { static char *ips; static char *listenps; static char *listenudps; static GOptionEntry e[] = { { "table", 't', 0, G_OPTION_ARG_INT, &table, "Kernel table to use", "INT" }, { "ip", 'i', 0, G_OPTION_ARG_STRING, &ips, "Local IP address", "IP" }, { "listen", 'l', 0, G_OPTION_ARG_STRING, &listenps, "TCP port to listen on", "[IP:]PORT" }, { "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP:]PORT" }, { "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "TOS value to set on streams", "INT" }, { "timeout", 'o', 0, G_OPTION_ARG_INT, &timeout, "RTP timeout", "SECS" }, { "silent-timeout",'s',0,G_OPTION_ARG_INT, &silent_timeout,"RTP timeout for muted", "SECS" }, { "pidfile", 'p', 0, G_OPTION_ARG_STRING, &pidfile, "Write PID to file", "FILE" }, { "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Don't fork to background", NULL }, { NULL, } }; GOptionContext *c; GError *er = NULL; c = g_option_context_new(" - next-generation media proxy"); g_option_context_add_main_entries(c, e, NULL); if (!g_option_context_parse(c, argc, argv, &er)) die("Bad command line: %s\n", er->message); if (!ips) die("Missing option IP\n"); if (!listenps || !listenudps) die("Missing option LISTEN or LISTEN-UDP\n"); ip = inet_addr(ips); if (ip == -1) die("Invalid IP\n"); if (listenps) { if (parse_ip_port(&listenp, &listenport, listenps)) die("Invalid IP or port"); } if (listenudps) { if (parse_ip_port(&udp_listenp, &udp_listenport, listenudps)) die("Invalid IP or port"); } if (tos < 0 || tos > 255) die("Invalid TOS value"); if (timeout <= 0) timeout = 60; if (silent_timeout <= 0) silent_timeout = 3600; } static void daemonize(void) { printf("Going to background...\n"); if (fork()) _exit(0); freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); freopen("/dev/null", "w", stderr); setpgrp(); } static void wpidfile(void) { FILE *fp; if (!pidfile) return; fp = fopen(pidfile, "w"); if (fp) { fprintf(fp, "%u\n", getpid()); fclose(fp); } } int main(int argc, char **argv) { struct poller *p; struct callmaster *m; struct control *c; struct control_udp *cu; int kfd; int ret; options(&argc, &argv); signals(); resources(); if (kernel_create_table(table)) die("Failed to create kernel table %i\n", table); kfd = kernel_open_table(table); if (kfd == -1) die("Failed to open kernel table %i\n", table); p = poller_new(); if (!p) die("poller creation failed\n"); m = callmaster_new(p); if (!m) return -1; m->kernelfd = kfd; m->kernelid = table; m->ip = ip; m->timeout = timeout; m->silent_timeout = silent_timeout; m->tos = tos; c = NULL; if (listenport) { c = control_new(p, listenp, listenport, m); if (!c) die("Failed to open TCP control connection port\n"); } cu = NULL; if (udp_listenport) { cu = control_udp_new(p, udp_listenp, udp_listenport, m); if (!cu) die("Failed to open UDP control connection port\n"); } mylog(LOG_INFO, "Startup complete"); if (!foreground) daemonize(); wpidfile(); for (;;) { ret = poller_poll(p, 100); if (ret == -1) break; } return 0; }