Beispiel #1
0
/* There is no way to get `EVLIST_INSERTED` event flag outside of libevent, so
 * here are tracking functions. */
static void tracked_event_set(
        struct tracked_event *tev, evutil_socket_t fd, short events,
        void (*callback)(evutil_socket_t, short, void *), void *arg)
{
    event_assign(&tev->ev, get_event_base(), fd, events, callback, arg);
    timerclear(&tev->inserted);
}
Beispiel #2
0
    virtual void signal_cb()
    {	
        struct timeval delay = { 1, 0 };

        LOG_DEBUG("Caught an interrupt signal; exiting cleanly in 1 second.\n");
        event_base_loopexit( get_event_base(), &delay);
    }
Beispiel #3
0
static void
test_real_constructor(void)
{
	auto libevent = IghtLibevent();
	auto calls = 0;

	std::cout << "test real_constructor... ";

	libevent.bufferevent_socket_new = [&](
	    event_base *b, evutil_socket_t s, int o) {
		++calls;
		return (::bufferevent_socket_new(b, s, o));
	};
	libevent.bufferevent_free = [&](bufferevent *b) {
		++calls;
		::bufferevent_free(b);
	};

	{
		auto poller = IghtGlobalPoller::get();
		auto b = IghtBuffereventSocket(poller->get_event_base(),
		    -1, 0, &libevent);
	}

	if (calls != 2)
		throw std::runtime_error("FAIL");

	std::cout << "ok" << std::endl;
}
Beispiel #4
0
/**
    Given a smartlist of listener configs; launch them all and print
    method lines as appropriate.  Return 0 if at least a listener was
    spawned, -1 otherwise.
*/
static int
open_listeners_managed(const managed_proxy_t *proxy)
{
  int ret=-1;
  const char *transport;

  /* Open listeners for each configuration. */
  SMARTLIST_FOREACH_BEGIN(proxy->configs, config_t *, cfg) {
    transport = get_transport_name_from_config(cfg);

    if (open_listeners(get_event_base(), cfg)) {
      ret=0; /* success! launched at least one listener. */
      print_method_line(transport, proxy, cfg);
    } else { /* fail. print a method error line. */
      print_method_error_line(transport, proxy, ST_LAUNCH_FAIL_LSN);
    }
  } SMARTLIST_FOREACH_END(cfg);

  return ret;
}
Beispiel #5
0
void base_net_thread::init()
{
    _base_net_thread_map[get_thread_index()] = this;
    for (int i = 0; i < _channel_num; i++) {

        int fd[2];
        int ret = socketpair(AF_UNIX,SOCK_STREAM,0,fd);
        if (ret < 0) {
            return ;
        }   

        event_channel_msg * msg = new event_channel_msg();
        msg->_net_thread = this;
        _channel_msg_vec.push_back(msg);
        msg->_channelid = fd[1];

        struct event *_event = event_new(get_event_base(), fd[0], EV_TIMEOUT | EV_READ | EV_PERSIST, on_cb, msg);

        event_add(_event, 0);
    }
}
Beispiel #6
0
static void ss_connect_relay(redudp_client *client)
{
    ss_client *ssclient = (void*)(client + 1);
    struct sockaddr_in * addr = &client->instance->config.relayaddr;
    int fd = -1;
    int error;

    fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (fd == -1) {
        redudp_log_errno(client, LOG_ERR, "socket");
        goto fail;
    }

    error = evutil_make_socket_nonblocking(fd);
    if (error) {
        redudp_log_errno(client, LOG_ERR, "evutil_make_socket_nonblocking");
        goto fail;
    }

    error = connect(fd, (struct sockaddr*)addr, sizeof(*addr));
    if (error) {
        redudp_log_errno(client, LOG_NOTICE, "connect");
        goto fail;
    }

    event_assign(&ssclient->udprelay, get_event_base(), fd, EV_READ | EV_PERSIST, ss_pkt_from_server, client);
    error = event_add(&ssclient->udprelay, NULL);
    if (error) {
        redudp_log_errno(client, LOG_ERR, "event_add");
        goto fail;
    }

    redudp_flush_queue(client);
    return;

fail:
    if (fd != -1)
        close(fd);
    redudp_drop_client(client);
}
Beispiel #7
0
static void
test_move_assignment(void)
{
	std::cout << "test move_assignment... ";

	auto libevent1 = IghtLibevent();
	auto underlying = (bufferevent *) NULL;

	libevent1.bufferevent_socket_new = [&](event_base *b,
	    evutil_socket_t s, int o) {
		return (underlying = ::bufferevent_socket_new(b, s, o));
	};

	auto poller = IghtGlobalPoller::get();
	auto b1 = IghtBuffereventSocket(poller->get_event_base(),
	    0, 0, &libevent1);
	auto libevent2 = IghtLibevent();
	auto b2 = IghtBuffereventSocket(&libevent2);
	b2 = std::move(b1);

	if (b2.get_libevent() != &libevent1)
		throw std::runtime_error("FAIL");
	if (underlying != (bufferevent *) b2)
		throw std::runtime_error("FAIL");
	if (b1.get_libevent() != &libevent2)
		throw std::runtime_error("FAIL");

	auto raised = 0;
	try {
		auto ppp = (bufferevent *) b1;
		(void) ppp;
	} catch (std::runtime_error&) {
		++raised;
	}
	if (!raised)
		throw std::runtime_error("FAIL");

	std::cout << "ok" << std::endl;
}
Beispiel #8
0
static void
test_access_underlying_bev_ok(void)
{
	auto libevent = IghtLibevent();
	auto underlying = (bufferevent *) NULL;

	std::cout << "test access_underlying_bev_ok... ";

	libevent.bufferevent_socket_new = [&](event_base *b,
	    evutil_socket_t s, int o) {
		return (underlying = ::bufferevent_socket_new(b, s, o));
	};

	auto poller = IghtGlobalPoller::get();
	auto b = IghtBuffereventSocket(poller->get_event_base(), -1, 0,
	    &libevent);

	if (underlying != (bufferevent *) b)
		throw std::runtime_error("FAIL");

	std::cout << "ok" << std::endl;
}
Beispiel #9
0
int main(int argc, char **argv)
{
	int error;
	app_subsys **ss;
	int exit_signals[2] = {SIGTERM, SIGINT};
	struct event terminators[2];
    struct event dumper;
	bool conftest = false;
	int opt;
	int i;

	red_srand();
	while ((opt = getopt(argc, argv, "h?vtc:p:")) != -1) {
		switch (opt) {
		case 't':
			conftest = true;
			break;
		case 'c':
			confname = optarg;
			break;
		case 'p':
			pidfile = optarg;
			break;
		case 'v':
			puts(redsocks_version);
			return EXIT_SUCCESS;
		default:
			printf(
				"Usage: %s [-?hvt] [-c config] [-p pidfile]\n"
				"  -h, -?       this message\n"
				"  -v           print version\n"
				"  -t           test config syntax\n"
				"  -p           write pid to pidfile\n",
				argv[0]);
			return (opt == '?' || opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE;
		}
	}


	FILE *f = fopen(confname, "r");
	if (!f) {
		perror("Unable to open config file");
		return EXIT_FAILURE;
	}

	parser_context* parser = parser_start(f, NULL);
	if (!parser) {
		perror("Not enough memory for parser");
		return EXIT_FAILURE;
	}

	FOREACH(ss, subsystems)
		if ((*ss)->conf_section)
			parser_add_section(parser, (*ss)->conf_section);
	error = parser_run(parser);
	parser_stop(parser);
	fclose(f);

	if (error)
		return EXIT_FAILURE;

	if (conftest)
		return EXIT_SUCCESS;

	// Initialize global event base
	g_event_base = event_base_new();
	if (!g_event_base)
		return EXIT_FAILURE;
		
	memset(&dumper, 0, sizeof(dumper));
	memset(terminators, 0, sizeof(terminators));

	FOREACH(ss, subsystems) {
		if ((*ss)->init) {
			error = (*ss)->init();
			if (error)
				goto shutdown;
		}
	}

	if (pidfile) {
		f = fopen(pidfile, "w");
		if (!f) {
			perror("Unable to open pidfile for write");
			return EXIT_FAILURE;
		}
		fprintf(f, "%d\n", getpid());
		fclose(f);
	}

	assert(SIZEOF_ARRAY(exit_signals) == SIZEOF_ARRAY(terminators));
	for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) {
		evsignal_assign(&terminators[i], get_event_base(), exit_signals[i], terminate, NULL);
		if (evsignal_add(&terminators[i], NULL) != 0) {
			log_errno(LOG_ERR, "signal_add");
			goto shutdown;
		}
	}

    evsignal_assign(&dumper, get_event_base(), SIGUSR1, dump_handler, NULL);
    if (evsignal_add(&dumper, NULL) != 0) {
        log_errno(LOG_ERR, "evsignal_add");
        goto shutdown;
    }

	log_error(LOG_NOTICE, "redsocks started");

	event_base_dispatch(g_event_base);

	log_error(LOG_NOTICE, "redsocks goes down");

shutdown:
    if (evsignal_initialized(&dumper)) {
        if (evsignal_del(&dumper) != 0)
		    log_errno(LOG_WARNING, "signal_del");
        memset(&dumper, 0, sizeof(dumper));
    }

	for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) {
		if (evsignal_initialized(&terminators[i])) {
			if (evsignal_del(&terminators[i]) != 0)
				log_errno(LOG_WARNING, "signal_del");
			memset(&terminators[i], 0, sizeof(terminators[i]));
		}
	}

	for (--ss; ss >= subsystems; ss--)
		if ((*ss)->fini)
			(*ss)->fini();

	if (g_event_base)
		event_base_free(g_event_base);
	
	return !error ? EXIT_SUCCESS : EXIT_FAILURE;
}
Beispiel #10
0
struct bufferevent* red_prepare_relay(const char *ifname,
                                bufferevent_data_cb readcb,
                                bufferevent_data_cb writecb,
                                bufferevent_event_cb errorcb,
                                void *cbarg)
{
    struct bufferevent *retval = NULL;
    int relay_fd = -1;
    int error;

    relay_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (relay_fd == -1) {
        log_errno(LOG_ERR, "socket");
        goto fail;
    }
    if (ifname && strlen(ifname)) {
#ifdef USE_PF // BSD
        error = setsockopt(relay_fd, SOL_SOCKET, IP_RECVIF, ifname, strlen(ifname));
#else // Linux
        error = setsockopt(relay_fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
#endif
        if (error) {
            log_errno(LOG_ERR, "setsockopt");
            goto fail;
        }
    }
    error = evutil_make_socket_nonblocking(relay_fd);
    if (error) {
        log_errno(LOG_ERR, "evutil_make_socket_nonblocking");
        goto fail;
    }

    retval = bufferevent_socket_new(get_event_base(), relay_fd, 0);
    if (!retval) {
        log_errno(LOG_ERR, "bufferevent_socket_new");
        goto fail;
    }

    bufferevent_setcb(retval, readcb, writecb, errorcb, cbarg);
    if (writecb) {
        error = bufferevent_enable(retval, EV_WRITE); // we wait for connection...
        if (error) {
            log_errno(LOG_ERR, "bufferevent_enable");
            goto fail;
        }
    }

    if (apply_tcp_keepalive(relay_fd))
        goto fail;

    return retval;

fail:
    if (retval){
        bufferevent_disable(retval, EV_READ|EV_WRITE);
        bufferevent_free(retval);
    }
    if (relay_fd != -1)
        redsocks_close(relay_fd);
    return NULL;
}
Beispiel #11
0
struct bufferevent* red_connect_relay2(struct sockaddr_in *addr,
                                    evbuffercb readcb,
                                    evbuffercb writecb,
                                    everrorcb errorcb,
                                    void *cbarg,
                                    const struct timeval *timeout_write)
{
    struct bufferevent *retval = NULL;
    int on = 1;
    int relay_fd = -1;
    int error;

    relay_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (relay_fd == -1) {
        log_errno(LOG_ERR, "socket");
        goto fail;
    }

    error = evutil_make_socket_nonblocking(relay_fd);
    if (error) {
        log_errno(LOG_ERR, "fcntl");
        goto fail;
    }

    error = setsockopt(relay_fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
    if (error) {
        log_errno(LOG_WARNING, "setsockopt");
        goto fail;
    }

    retval = bufferevent_socket_new(get_event_base(), relay_fd, 0);
    if (!retval) {
        log_errno(LOG_ERR, "bufferevent_socket_new");
        goto fail;
    }

    bufferevent_setcb(retval, readcb, writecb, errorcb, cbarg);

    error = bufferevent_enable(retval, EV_WRITE); // we wait for connection...
    if (error) {
        log_errno(LOG_ERR, "bufferevent_enable");
        goto fail;
    }
    bufferevent_set_timeouts(retval, NULL, timeout_write);

//  error = bufferevent_socket_connect(retval, (struct sockaddr*)addr, sizeof(*addr));
//  if (error) {
    error = connect(relay_fd, (struct sockaddr*)addr, sizeof(*addr));
    if (error && errno != EINPROGRESS) {
        log_errno(LOG_NOTICE, "bufferevent_socket_connect");
        goto fail;
    }

    return retval;

fail:
    if (relay_fd != -1)
        redsocks_close(relay_fd);
    if (retval)
        bufferevent_free(retval);
    return NULL;
}