Ejemplo n.º 1
0
static void signal_handling_worker(void* context) {
  enum signal_action action;
  uv_signal_t signal1a;
  uv_signal_t signal1b;
  uv_signal_t signal2;
  uv_loop_t loop;
  int r;

  action = (enum signal_action) (uintptr_t) context;

  ASSERT(0 == uv_loop_init(&loop));

  /* Setup the signal watchers and start them. */
  if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
    r = uv_signal_init(&loop, &signal1a);
    ASSERT(r == 0);
    r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1);
    ASSERT(r == 0);
    r = uv_signal_init(&loop, &signal1b);
    ASSERT(r == 0);
    r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1);
    ASSERT(r == 0);
  }

  if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
    r = uv_signal_init(&loop, &signal2);
    ASSERT(r == 0);
    r = uv_signal_start(&signal2, signal2_cb, SIGUSR2);
    ASSERT(r == 0);
  }

  /* Signal watchers are now set up. */
  uv_sem_post(&sem);

  /* Wait for all signals. The signal callbacks stop the watcher, so uv_run
   * will return when all signal watchers caught a signal.
   */
  r = uv_run(&loop, UV_RUN_DEFAULT);
  ASSERT(r == 0);

  /* Restart the signal watchers. */
  if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
    r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1);
    ASSERT(r == 0);
    r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1);
    ASSERT(r == 0);
  }

  if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
    r = uv_signal_start(&signal2, signal2_cb, SIGUSR2);
    ASSERT(r == 0);
  }

  /* Wait for signals once more. */
  uv_sem_post(&sem);

  r = uv_run(&loop, UV_RUN_DEFAULT);
  ASSERT(r == 0);

  /* Close the watchers. */
  if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
    uv_close((uv_handle_t*) &signal1a, NULL);
    uv_close((uv_handle_t*) &signal1b, NULL);
  }

  if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
    uv_close((uv_handle_t*) &signal2, NULL);
  }

  /* Wait for the signal watchers to close. */
  r = uv_run(&loop, UV_RUN_DEFAULT);
  ASSERT(r == 0);

  uv_loop_close(&loop);
}
Ejemplo n.º 2
0
 Signal():
     handle<uv_signal_t>()
 {
     uv_signal_init(uv_default_loop(), get());
 }
Ejemplo n.º 3
0
 Signal(loop& l):
     handle<uv_signal_t>()
 {
     uv_signal_init(l.get(), get());
 }
Ejemplo n.º 4
0
extern "C" int
rust_uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
  return uv_signal_init(loop, handle);
}
Ejemplo n.º 5
0
int main(int argc, char **argv)
{
	int forks = 1;
	array_t(char*) addr_set;
	array_init(addr_set);
	char *keyfile = NULL;
	const char *config = NULL;
	char *keyfile_buf = NULL;

	/* Long options. */
	int c = 0, li = 0, ret = 0;
	struct option opts[] = {
		{"addr", required_argument,   0, 'a'},
		{"config", required_argument, 0, 'c'},
		{"keyfile",required_argument, 0, 'k'},
		{"forks",required_argument,   0, 'f'},
		{"verbose",    no_argument,   0, 'v'},
		{"version",   no_argument,    0, 'V'},
		{"help",      no_argument,    0, 'h'},
		{0, 0, 0, 0}
	};
	while ((c = getopt_long(argc, argv, "a:c:f:k:vVh", opts, &li)) != -1) {
		switch (c)
		{
		case 'a':
			array_push(addr_set, optarg);
			break;
		case 'c':
			config = optarg;
			break;
		case 'f':
			g_interactive = 0;
			forks = atoi(optarg);
			if (forks == 0) {
				kr_log_error("[system] error '-f' requires number, not '%s'\n", optarg);
				return EXIT_FAILURE;
			}
#if (!defined(UV_VERSION_HEX)) || (!defined(SO_REUSEPORT))
			if (forks > 1) {
				kr_log_error("[system] libuv 1.7+ is required for SO_REUSEPORT support, multiple forks not supported\n");
				return EXIT_FAILURE;
			}
#endif
			break;
		case 'k':
			keyfile_buf = malloc(PATH_MAX);
			assert(keyfile_buf);
			/* Check if the path is absolute */
			if (optarg[0] == '/') {
				keyfile = strdup(optarg);
			} else {
				/* Construct absolute path, the file may not exist */
				keyfile = realpath(".", keyfile_buf);
				if (keyfile) {
					int len = strlen(keyfile);
					int namelen = strlen(optarg);
					if (len + namelen < PATH_MAX - 1) {
						keyfile[len] = '/';
						memcpy(keyfile + len + 1, optarg, namelen + 1);
						keyfile = strdup(keyfile); /* Duplicate */
					} else {
						keyfile = NULL; /* Invalidate */
					}
				}
			}
			free(keyfile_buf);
			if (!keyfile) {
				kr_log_error("[system] keyfile '%s': not writeable\n", optarg);
				return EXIT_FAILURE;
			}
			break;
		case 'v':
			kr_debug_set(true);
			break;
		case 'V':
			kr_log_info("%s, version %s\n", "Knot DNS Resolver", PACKAGE_VERSION);
			return EXIT_SUCCESS;
		case 'h':
		case '?':
			help(argc, argv);
			return EXIT_SUCCESS;
		default:
			help(argc, argv);
			return EXIT_FAILURE;
		}
	}

	/* Switch to rundir. */
	if (optind < argc) {
		const char *rundir = argv[optind];
		if (access(rundir, W_OK) != 0) {
			kr_log_error("[system] rundir '%s': %s\n", rundir, strerror(errno));
			return EXIT_FAILURE;
		}
		ret = chdir(rundir);
		if (ret != 0) {
			kr_log_error("[system] rundir '%s': %s\n", rundir, strerror(errno));
			return EXIT_FAILURE;
		}
		if(config && access(config, R_OK) != 0) {
			kr_log_error("[system] rundir '%s'\n", rundir);
			kr_log_error("[system] config '%s': %s\n", config, strerror(errno));
			return EXIT_FAILURE;
		}
	}

	kr_crypto_init();

	/* Fork subprocesses if requested */
	int fork_count = forks;
	while (--forks > 0) {
		int pid = fork();
		if (pid < 0) {
			perror("[system] fork");
			return EXIT_FAILURE;
		}
		/* Forked process */
		if (pid == 0) {
			kr_crypto_reinit();
			break;
		}
	}

	/* Block signals. */
	uv_loop_t *loop = uv_default_loop();
	uv_signal_t sigint, sigterm;
	uv_signal_init(loop, &sigint);
	uv_signal_init(loop, &sigterm);
	uv_signal_start(&sigint, signal_handler, SIGINT);
	uv_signal_start(&sigterm, signal_handler, SIGTERM);
	/* Create a server engine. */
	knot_mm_t pool = {
		.ctx = mp_new (4096),
		.alloc = (knot_mm_alloc_t) mp_alloc
	};
	struct engine engine;
	ret = engine_init(&engine, &pool);
	if (ret != 0) {
		kr_log_error("[system] failed to initialize engine: %s\n", kr_strerror(ret));
		return EXIT_FAILURE;
	}
	/* Create worker */
	struct worker_ctx *worker = init_worker(loop, &engine, &pool, forks, fork_count);
	if (!worker) {
		kr_log_error("[system] not enough memory\n");
		return EXIT_FAILURE;
	}
	/* Bind to sockets and run */
	for (size_t i = 0; i < addr_set.len; ++i) {
		int port = 53;
		const char *addr = set_addr(addr_set.at[i], &port);
		ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP);
		if (ret != 0) {
			kr_log_error("[system] bind to '%s#%d' %s\n", addr, port, knot_strerror(ret));
			ret = EXIT_FAILURE;
		}
	}
	/* Start the scripting engine */
	if (ret == 0) {
		ret = engine_start(&engine, config ? config : "config");
		if (ret == 0) {
			if (keyfile) {
				auto_free char *cmd = afmt("trust_anchors.file = '%s'", keyfile);
				if (!cmd) {
					kr_log_error("[system] not enough memory\n");
					return EXIT_FAILURE;
				}
				engine_cmd(&engine, cmd);
				lua_settop(engine.L, 0);
			}
			/* Run the event loop */
			ret = run_worker(loop, &engine);
		}
	}
	/* Cleanup. */
	array_clear(addr_set);
	engine_deinit(&engine);
	worker_reclaim(worker);
	mp_delete(pool.ctx);
	if (ret != 0) {
		ret = EXIT_FAILURE;
	}
	kr_crypto_cleanup();
	return ret;
}
Ejemplo n.º 6
0
bud_error_t bud_worker(bud_config_t* config) {
    int r;
    bud_error_t err;

    bud_log(config, kBudLogDebug, "worker starting");

    config->loop = uv_default_loop();
    config->ipc = malloc(sizeof(*config->ipc));
    config->signal.sighup = malloc(sizeof(*config->signal.sighup));
    if (config->ipc == NULL || config->signal.sighup == NULL) {
        err = bud_error_str(kBudErrNoMem, "config->ipc");
        goto fatal;
    }

    config->ipc->data = config;
    config->signal.sighup->data = config;

    r = uv_pipe_init(config->loop, config->ipc, 1);
    if (r != 0) {
        err = bud_error_num(kBudErrIPCPipeInit, r);
        goto fatal;
    }

    r = uv_pipe_open(config->ipc, 0);
    if (r != 0) {
        err = bud_error_num(kBudErrIPCPipeOpen, r);
        goto failed_pipe_open;
    }

    r = uv_read_start((uv_stream_t*) config->ipc,
                      bud_worker_alloc_cb,
                      bud_worker_read_cb);
    if (r != 0) {
        err = bud_error_num(kBudErrIPCReadStart, r);
        goto failed_pipe_open;
    }

#ifndef _WIN32
    /* Drop privileges */
    err = bud_config_drop_privileges(config);
    if (!bud_is_ok(err))
        goto failed_pipe_open;

    r = uv_signal_init(config->loop, config->signal.sighup);
    if (r != 0) {
        err = bud_error_num(kBudErrSignalInit, r);
        goto failed_pipe_open;
    }

    r = uv_signal_start(config->signal.sighup, bud_worker_signal_cb, SIGHUP);
    if (r != 0) {
        err = bud_error_num(kBudErrSignalInit, r);
        goto failed_signal_start;
    }
#endif  /* !_WIN32 */

    err = bud_ok();
    return err;

#ifndef _WIN32
failed_signal_start:
    uv_close((uv_handle_t*) config->signal.sighup, bud_worker_close_cb);
#endif  /* !_WIN32 */

failed_pipe_open:
    uv_close((uv_handle_t*) config->ipc, bud_worker_close_cb);
    goto cleanup;

fatal:
    free(config->ipc);

cleanup:
    config->ipc = NULL;
    return err;
}
Ejemplo n.º 7
0
int uv_loop_init(uv_loop_t* loop) {
  void* saved_data;
  int err;


  saved_data = loop->data;
  memset(loop, 0, sizeof(*loop));
  loop->data = saved_data;

  heap_init((struct heap*) &loop->timer_heap);
  QUEUE_INIT(&loop->wq);
  QUEUE_INIT(&loop->idle_handles);
  QUEUE_INIT(&loop->async_handles);
  QUEUE_INIT(&loop->check_handles);
  QUEUE_INIT(&loop->prepare_handles);
  QUEUE_INIT(&loop->handle_queue);

  loop->active_handles = 0;
  loop->active_reqs.count = 0;
  loop->nfds = 0;
  loop->watchers = NULL;
  loop->nwatchers = 0;
  QUEUE_INIT(&loop->pending_queue);
  QUEUE_INIT(&loop->watcher_queue);

  loop->closing_handles = NULL;
  uv__update_time(loop);
  loop->async_io_watcher.fd = -1;
  loop->async_wfd = -1;
  loop->signal_pipefd[0] = -1;
  loop->signal_pipefd[1] = -1;
  loop->backend_fd = -1;
  loop->emfile_fd = -1;

  loop->timer_counter = 0;
  loop->stop_flag = 0;

  err = uv__platform_loop_init(loop);
  if (err)
    return err;

  uv__signal_global_once_init();
  err = uv_signal_init(loop, &loop->child_watcher);
  if (err)
    goto fail_signal_init;

  uv__handle_unref(&loop->child_watcher);
  loop->child_watcher.flags |= UV_HANDLE_INTERNAL;
  QUEUE_INIT(&loop->process_handles);

  err = uv_rwlock_init(&loop->cloexec_lock);
  if (err)
    goto fail_rwlock_init;

  err = uv_mutex_init(&loop->wq_mutex);
  if (err)
    goto fail_mutex_init;

  err = uv_async_init(loop, &loop->wq_async, uv__work_done);
  if (err)
    goto fail_async_init;

  uv__handle_unref(&loop->wq_async);
  loop->wq_async.flags |= UV_HANDLE_INTERNAL;

  return 0;

fail_async_init:
  uv_mutex_destroy(&loop->wq_mutex);

fail_mutex_init:
  uv_rwlock_destroy(&loop->cloexec_lock);

fail_rwlock_init:
  uv__signal_loop_cleanup(loop);

fail_signal_init:
  uv__platform_loop_delete(loop);

  return err;
}
Ejemplo n.º 8
0
LWS_VISIBLE int
lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi)
{
	struct lws_context_per_thread *pt = &context->pt[tsi];
	struct lws_vhost *vh = context->vhost_list;
	int status = 0, n, ns, first = 1;

	if (!pt->io_loop_uv) {
		if (!loop) {
			loop = lws_malloc(sizeof(*loop));
			if (!loop) {
				lwsl_err("OOM\n");
				return -1;
			}
	#if UV_VERSION_MAJOR > 0
			uv_loop_init(loop);
	#else
			lwsl_err("This libuv is too old to work...\n");
			return 1;
	#endif
			pt->ev_loop_foreign = 0;
		} else {
			lwsl_notice(" Using foreign event loop...\n");
			pt->ev_loop_foreign = 1;
		}

		pt->io_loop_uv = loop;
		uv_idle_init(loop, &pt->uv_idle);

		ns = ARRAY_SIZE(sigs);
		if (lws_check_opt(context->options,
				  LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN))
			ns = 2;

		if (pt->context->use_ev_sigint) {
			assert(ns <= ARRAY_SIZE(pt->signals));
			for (n = 0; n < ns; n++) {
				uv_signal_init(loop, &pt->signals[n]);
				pt->signals[n].data = pt->context;
				uv_signal_start(&pt->signals[n],
						context->lws_uv_sigint_cb,
						sigs[n]);
			}
		}
	} else
		first = 0;

	/*
	 * Initialize the accept wsi read watcher with all the listening sockets
	 * and register a callback for read operations
	 *
	 * We have to do it here because the uv loop(s) are not
	 * initialized until after context creation.
	 */
	while (vh) {
		if (lws_uv_initvhost(vh, vh->lserv_wsi) == -1)
			return -1;
		vh = vh->vhost_next;
	}

	if (first) {
		uv_timer_init(pt->io_loop_uv, &pt->uv_timeout_watcher);
		uv_timer_start(&pt->uv_timeout_watcher, lws_uv_timeout_cb,
			       10, 1000);
	}

	return status;
}
Ejemplo n.º 9
0
int
main (int ac, char *av[])
{
    int ret, ch;
    char *logfile = NULL;
    int i, ok;
    char *tmp, *ptr;
    uv_signal_t *sigint;
    uv_signal_t *sigterm;
    char *pidfile = NULL;

    struct destination *destination = NULL;
    struct listener *listener;

    struct rlimit rl;
    rl.rlim_cur = 65535;
    rl.rlim_max = 65535;

    setrlimit (RLIMIT_NOFILE, &rl);

    rl.rlim_cur = RLIM_INFINITY;
    rl.rlim_max = RLIM_INFINITY;

    setrlimit (RLIMIT_CORE, &rl);

    signal (SIGPIPE, SIG_IGN);

    char *mysqltype = NULL;

    setenv ("TZ", ":/etc/localtime", 0);
    tzset ();

    memset (logstring, '\0', sizeof (logstring));
    for (i = 0; i < ac; i++) {
        if (strlen (logstring) + strlen (av[i]) >= sizeof (logstring)) {
            break;
        }
        strcat (logstring, av[i]);

        if (i != ac - 1) {
            strcat (logstring, " ");
        }
    }

    pool = malloc (sizeof (*pool));

    bufpool_init (pool, BUF_SIZE);

/*
    uv_timer_t *handle;
    handle = malloc (sizeof(uv_timer_t));
    uv_timer_init(uv_default_loop(),handle);
    uv_timer_start(handle, bufpool_print_stats, 1000, 1000);
*/


    sigint = malloc (sizeof (uv_signal_t));
    sigterm = malloc (sizeof (uv_signal_t));
    uv_signal_init (uv_default_loop (), sigint);
    uv_signal_init (uv_default_loop (), sigterm);
    uv_signal_start (sigint, signal_handler, SIGINT);
    uv_signal_start (sigterm, signal_handler, SIGTERM);

    openlog ("rum", LOG_NDELAY | LOG_PID, LOG_DAEMON);

    if (ac == 1) {
        usage ();
    }

    /* destination is global variable a pointer to struct destination
     * struct destination forms a linked list
     * first_destination is pointer to first struct
     * 
     * struct listener is the same
     */

    listener = NULL;

    int option_index = 0;
    static struct option long_options[] = {
        {"background", no_argument, 0, 'b'},
        {"destination", required_argument, 0, 'd'},
        {"source", required_argument, 0, 's'},
        {"stats", required_argument, 0, 'm'},
        {"logfile", required_argument, 0, 'l'},
        {"mysql-cdb", required_argument, 0, 'M'},
        {"postgresql-cdb", required_argument, 0, 'P'},
        {"mysqltype", required_argument, 0, 't'},
        {"failover-r", required_argument, 0, 'R'},
        {"failover", required_argument, 0, 'f'},
        {"read-timeout", required_argument, 0, 0},
        {"connect-timeout", required_argument, 0, 0},
        {"pidfile", required_argument, 0, 'p'},
        {"loglogins", no_argument, 0, 'L'},
        {0, 0, 0, 0}
    };


    while ((ch =
            getopt_long (ac, av, "bd:s:m:l:M:P:t:r:f:R:p:L", long_options,
                         &option_index)) != -1) {
        switch (ch) {
        case 0:
            if (strcmp (long_options[option_index].name, "read-timeout") == 0)
                read_timeout = atoi (optarg);
            if (strcmp (long_options[option_index].name, "connect-timeout") ==
                0)
                connect_timeout = atoi (optarg);

            break;

        case 'b':
            daemonize = 1;
            break;
        case 's':
        case 'm':
            if (listener == NULL) {
                first_listener = listener = malloc (sizeof (struct listener));
            } else {
                listener->next = malloc (sizeof (struct listener));
                listener = listener->next;
            }
            listener->s = strdup (optarg);
            listener->stream = NULL;
            listener->next = NULL;
            /* vynulujeme statistiky */
            listener->nr_conn = 0;
            listener->nr_allconn = 0;
            listener->input_bytes = 0;
            listener->output_bytes = 0;
            if (ch == 's') {
                listener->type = LISTENER_DEFAULT;
            } else if (ch == 'm') {
                listener->type = LISTENER_STATS;
            }
            break;
        case 'M':
            /* enable mysql module */
            mysql_cdb_file = strdup (optarg);
            break;
        case 'P':
            /* enable mysql module */
            postgresql_cdb_file = strdup (optarg);
            break;

        case 'd':
            first_destination = destination =
                malloc (sizeof (struct destination));
            prepare_upstream (optarg, destination);
            break;
        case 'l':
            logfile = strdup (optarg);
            break;
        case 'L':
            loglogins = 1;
            break;
        case 't':
            mysqltype = optarg;
            break;
        case 'f':
            mode = MODE_FAILOVER;
            ptr = tmp = strdup (optarg);
            i = 0;
            while (tmp[i] != '\0') {
                if (tmp[i] == ',') {
                    tmp[i] = '\0';
                    add_destination (ptr);
                    destinations++;
                    ptr = tmp + i + 1;
                }
                i++;
            }

            add_destination (ptr);
            destinations++;

            break;

        case 'R':
            mode = MODE_FAILOVER_R;
            ptr = tmp = strdup (optarg);
            i = 0;
            while (tmp[i] != '\0') {
                if (tmp[i] == ',') {
                    tmp[i] = '\0';
                    add_destination (ptr);
                    destinations++;
                    ptr = tmp + i + 1;
                }
                i++;
            }

            add_destination (ptr);
            destinations++;
            randomize_destinations ();

            break;

        case 'p':
            pidfile = strdup (optarg);
            break;

        }
    }

    /* if mysql module is enabled, open cdb file and create EV_SIGNAL event which call repoen_cdb().
     * if someone send SIGUSR1 cdb file is reopened, but this is automatically triggered by timeout with
     * CDB_RELOAD_TIME seconds (default 2s)
     *
     * reopen_cdb is called from main event loop, it is not called directly by signal,
     * so it is race condition free (safe to free and init global cdb variable)
     */
    if (mysql_cdb_file) {
        init_mysql_cdb_file (mysqltype);
    }

    if (postgresql_cdb_file) {
        init_postgresql_cdb_file (mysqltype);
    }


    if (daemonize) {
        if (logfile) {
            if (daemon (0, 1) < 0) {
                perror ("daemon()");
                exit (0);
            }
            close (0);
            close (1);
            close (2);
            ret =
                open (logfile, O_WRONLY | O_CREAT | O_APPEND,
                      S_IRUSR | S_IWUSR);
            if (ret != -1) {
                dup2 (ret, 1);
                dup2 (ret, 2);
            }
        } else {
            if (daemon (0, 0) < 0) {
                perror ("daemon()");
                exit (0);
            }
        }
    }

    /* add all listen (-s -m) ports to event_base, if someone connect: accept_connect is executed with struct listener argument */
    for (listener = first_listener; listener; listener = listener->next) {
        for (i = 0, ok = 0; i < 10; i++) {
            listener->stream = create_listen_socket (listener->s);
            listener->stream->data = listener;
            int r =
                uv_listen ((uv_stream_t *) listener->stream, -1,
                           on_incoming_connection);

            if (r) {
                logmsg ("listen to %s failed, retrying", listener->s);
                uv_close ((uv_handle_t *) listener->stream, on_close_listener);
                usleep (200 * 1000);
            } else {
                logmsg ("listening on %s", listener->s);
                ok = 1;
                break;
            }
        }

        if (ok == 0) {
            logmsg ("listen to %s failed, exiting", listener->s);
            _exit (-1);
        }

    }

    if (!first_destination && !mysql_cdb_file && !postgresql_cdb_file) {
        usage ();
    }

    if (daemonize) {
        if (pidfile) {
            FILE *fp = fopen(pidfile, "w");
            if (fp) {
                fprintf (fp, "%d", getpid());
                fclose (fp);
            } else {
                logmsg("cannot open pidfile %s (%s)", pidfile, strerror (errno));
            }
        }
    }

    /* main libuv loop */
    uv_run (uv_default_loop (), UV_RUN_DEFAULT);

    /* SIGINT || SIGTERM received, clean up */
    bufpool_done (pool);
    free (pool);

    if (mysql_cdb_file) {
        free (mysql_cdb_file);
    }

    if (postgresql_cdb_file) {
        free (postgresql_cdb_file);
    }


    struct destination *dst;
    dst = first_destination;
    while (dst) {
        destination = dst->next;
        free (dst->s);
        free (dst);
        dst = destination;
    }

    free (sigint);
    free (sigterm);

    exit (0);
}
Ejemplo n.º 10
0
 Signal(Loop& uvloop) {
     uv_signal_init(uvloop, phandle());
 }
Ejemplo n.º 11
0
int
main(int argc, char* argv[]) {
  char* ipaddr = "0.0.0.0";
  int port = 7000;
  int i;
  for (i = 1; i < argc; i++) {
    if (!strcmp(argv[i], "-a")) {
      if (i == argc-1) usage(argv[0]);
      ipaddr = argv[++i];
    } else
    if (!strcmp(argv[i], "-p")) {
      if (i == argc-1) usage(argv[0]);
      char* e = NULL;
      port = strtol(argv[++i], &e, 10);
      if ((e && *e) || port < 0 || port > 65535) usage(argv[0]);
    } else
    if (!strcmp(argv[i], "-d")) {
      if (i == argc-1) usage(argv[0]);
      static_dir = argv[++i];
    } else
      usage(argv[0]);
  }
  static_dir_len = strlen(static_dir);

  struct sockaddr_in addr;
  int r;

  mime_type = kh_init(mime_type);
  add_mime_type(".jpg", "image/jpeg");
  add_mime_type(".png", "image/png");
  add_mime_type(".gif", "image/gif");
  add_mime_type(".html", "text/html");
  add_mime_type(".txt", "text/plain");

  r = uv_ip4_addr(ipaddr, port, &addr);
  if (r) {
    fprintf(stderr, "Address error: %s: %s\n", uv_err_name(r), uv_strerror(r));
    return 1;
  }

  loop = uv_default_loop();

  uv_tcp_t server;
  r = uv_tcp_init(loop, &server);
  if (r) {
    fprintf(stderr, "Socket creation error: %s: %s\n", uv_err_name(r), uv_strerror(r));
    return 1;
  }

  r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
  if (r) {
    fprintf(stderr, "Bind error: %s: %s\n", uv_err_name(r), uv_strerror(r));
    return 1;
  }

  r = uv_tcp_simultaneous_accepts((uv_tcp_t*) &server, 1);
  if (r) {
    fprintf(stderr, "Accept error: %s: %s\n", uv_err_name(r), uv_strerror(r));
    return 1;
  }

  fprintf(stderr, "Listening %s:%d\n", ipaddr, port);

  r = uv_listen((uv_stream_t*)&server, SOMAXCONN, on_connection);
  if (r) {
    fprintf(stderr, "Listen error: %s: %s\n", uv_err_name(r), uv_strerror(r));
    return 1;
  }

  uv_signal_t sig;
  r = uv_signal_init(loop, &sig);
  if (r) {
    fprintf(stderr, "Signal error: %s: %s\n", uv_err_name(r), uv_strerror(r));
    return 1;
  }
  sig.data = loop;
  r = uv_signal_start(&sig, on_signal, SIGINT);
  if (r) {
    fprintf(stderr, "Signal error: %s: %s\n", uv_err_name(r), uv_strerror(r));
    return 1;
  }

  return uv_run(loop, UV_RUN_DEFAULT);
}
Ejemplo n.º 12
0
LWS_VISIBLE int
lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi)
{
	struct lws_context_per_thread *pt = &context->pt[tsi];
	struct lws_vhost *vh = context->vhost_list;
	int status = 0, n;

	if (!loop) {
		loop = lws_malloc(sizeof(*loop));
#if UV_VERSION_MAJOR > 0
		uv_loop_init(loop);
#else
		lwsl_err("This libuv is too old to work...\n");
		return 1;
#endif
		pt->ev_loop_foreign = 0;
	} else {
		lwsl_notice(" Using foreign event loop...\n");
		pt->ev_loop_foreign = 1;
	}

	pt->io_loop_uv = loop;
	uv_idle_init(loop, &pt->uv_idle);

	if (pt->context->use_ev_sigint) {
		assert(ARRAY_SIZE(sigs) <= ARRAY_SIZE(pt->signals));
		for (n = 0; n < ARRAY_SIZE(sigs); n++) {
			uv_signal_init(loop, &pt->signals[n]);
			pt->signals[n].data = pt->context;
			uv_signal_start(&pt->signals[n],
					context->lws_uv_sigint_cb, sigs[n]);
		}
	}

	/*
	 * Initialize the accept wsi read watcher with all the listening sockets
	 * and register a callback for read operations
	 *
	 * We have to do it here because the uv loop(s) are not
	 * initialized until after context creation.
	 */
	while (vh) {
		if (vh->lserv_wsi) {
			vh->lserv_wsi->w_read.context = context;
			n = uv_poll_init_socket(pt->io_loop_uv,
						&vh->lserv_wsi->w_read.uv_watcher,
						vh->lserv_wsi->sock);
			if (n) {
				lwsl_err("uv_poll_init failed %d, sockfd=%p\n",
					n, (void *)(long)vh->lserv_wsi->sock);

				return -1;
			}
			lws_libuv_io(vh->lserv_wsi, LWS_EV_START | LWS_EV_READ);
		}
		vh = vh->vhost_next;
	}

	uv_timer_init(pt->io_loop_uv, &pt->uv_timeout_watcher);
	uv_timer_start(&pt->uv_timeout_watcher, lws_uv_timeout_cb, 1000, 1000);

	return status;
}