int main (int argc, char **argv) { struct event evfifo; #ifdef WIN32 HANDLE socket; WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); // Open a file. socket = CreateFile("test.txt", // open File GENERIC_READ, // open for reading 0, // do not share NULL, // no security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if(socket == INVALID_HANDLE_VALUE) return 1; #else struct stat st; const char *fifo = "event.fifo"; int socket; if (lstat (fifo, &st) == 0) { if ((st.st_mode & S_IFMT) == S_IFREG) { errno = EEXIST; perror("lstat"); exit (1); } } unlink (fifo); if (mkfifo (fifo, 0600) == -1) { perror("mkfifo"); exit (1); } /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */ #ifdef __linux socket = open (fifo, O_RDWR | O_NONBLOCK, 0); #else socket = open (fifo, O_RDONLY | O_NONBLOCK, 0); #endif if (socket == -1) { perror("open"); exit (1); } fprintf(stderr, "Write data to %s\n", fifo); #endif /* Initalize the event library */ event_init(); /* Initalize one event */ #ifdef WIN32 event_set(&evfifo, (int)socket, EV_READ, fifo_read, &evfifo); #else event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo); #endif /* Add it to the active events, without a timeout */ event_add(&evfifo, NULL); event_dispatch(); #ifdef WIN32 CloseHandle(socket); #endif return (0); }
static struct http_connection * http_connection_new(struct http_server *hs, int fd, struct sockaddr *sin) { struct http_connection *hc = NULL; hc = (struct http_connection *)malloc(sizeof(struct http_connection)); if (!hc) { printf("Could not create new http connection\n"); return NULL; } memset(hc, 0, sizeof(struct http_connection)); hc->hs = hs; hc->fd = fd; memcpy(&(hc->sin), sin, sizeof(struct sockaddr_in)); hc->connection_status = HTTP_CONNECTION_STATUS_READ_HEADER; hc->status = HTTP_OK; if (fd >= 0) { /* init head node with fd<0 */ /* create a event for this fd */ hc->ev_read = event_new(hs->base, fd, EV_READ | EV_PERSIST, http_read_cb, hc); if (!hc->ev_read) { printf("Could not create event for http connection(fd %d)\n", fd); goto failed; } hc->ev_write = event_new(hs->base, fd, EV_WRITE, http_404_cb, hc); if (!hc->ev_write) { printf("Could not create event for http connection(fd %d)\n", fd); goto failed; } /* create a event buffer for read data */ hc->evbin = evbuffer_new(); if (!hc->evbin) { printf("Could not create input evbuffer for http connection(fd %d)\n", fd); goto failed; } /* create a event buffer for read data */ hc->evbout = evbuffer_new(); if (!hc->evbout) { printf("Could not create output evbuffer for http connection(fd %d)\n", fd); goto failed; } int i = 1; setsockopt(hc->fd, SOL_TCP, TCP_NODELAY, &i, sizeof(i)); /* close connection if not data received in 3 seconds */ struct timeval timeout = {10, 0}; event_add(hc->ev_read, &timeout); } /* init list node */ hc->prev = hc; hc->next = hc; dbprintf("http connection new %p\n", hc); return hc; failed: if (hc->evbout) evbuffer_free(hc->evbout); if (hc->evbin) evbuffer_free(hc->evbin); if (hc->ev_write) event_free(hc->ev_write); if (hc->ev_read) event_free(hc->ev_read); if (hc) free(hc); return NULL; }
int main(int argc, char *argv[]) { struct stat st; char *server = NULL; int c, fd, port = 0, use_ssl = 0; ctx->channel = "flood"; ctx->type = "text/html"; ctx->send_tv.tv_sec = 1; ctx->stats_tv.tv_sec = 5; while ((c = getopt(argc, argv, "c:f:l:p:r:sh?")) != -1) { switch (c) { case 'c': ctx->channel = optarg; break; case 'f': if ((fd = open(optarg, O_RDONLY, 0)) != -1) { if (fstat(fd, &st) == -1) err(1, "fstat"); ctx->len = st.st_size; ctx->data = malloc(st.st_size); if (read(fd, ctx->data, ctx->len) != ctx->len) err(1, "read"); close(fd); } else err(1, "open"); break; case 'l': server = optarg; break; case 'p': port = atoi(optarg); break; case 'r': ctx->send_tv.tv_sec = 0; ctx->send_tv.tv_usec = 1000000 / atoi(optarg); break; case 's': use_ssl = 1; break; case 't': ctx->type = optarg; break; default: usage(); break; } } argc -= optind; argv += optind; if (argc > 0) usage(); putenv("EVENT_SHOW_METHOD=1"); event_init(); evmsg_open(server, port, use_ssl); evmsg_set_auth(getenv("USER"), "foobar"); evtimer_set(&ctx->send_ev, send_msg, NULL); event_add(&ctx->send_ev, &ctx->send_tv); evtimer_set(&ctx->stats_ev, print_stats, NULL); event_add(&ctx->stats_ev, &ctx->stats_tv); event_dispatch(); evmsg_close(); exit(0); }
//******************************************************************************** // Main //******************************************************************************** int main(int argc, char **argv) { struct event_base *base; struct evconnlistener *listener; struct event *signal_event; struct sockaddr_in sin; #ifdef _WIN32 WSADATA wsa_data; WSAStartup(0x0201, &wsa_data); #endif // Setup libevent printf("Setting up\n");fflush(stdout); base = event_base_new(); if (!base) { fprintf(stderr, "Could not initialize libevent!\n"); return 1; } // Init RVM initRVM(); // Init group structure (TODO: how to do thisn, and to ensure it's only once. //theGroup = initRVMGroup(); // Init socket memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(PORT); // Setup listener for socket connections printf("Setting up listener\n");fflush(stdout); listener = evconnlistener_new_bind(base, accept_conn_cb, NULL, LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1, (struct sockaddr*)&sin, sizeof(sin)); if (!listener) { fprintf(stderr, "Could not create a listener!\n"); return 1; } // Setup signal event listener signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base); if (!signal_event || event_add(signal_event, NULL)<0) { fprintf(stderr, "Could not create/add a signal event!\n"); return 1; } // Start libevent event_base_dispatch(base); // Free resources when done evconnlistener_free(listener); event_free(signal_event); event_base_free(base); printf("done\n"); return 0; }
static int test_ratelimiting(void) { struct event_base *base; struct sockaddr_in sin; struct evconnlistener *listener; struct sockaddr_storage ss; ev_socklen_t slen; int i; struct timeval tv; ev_uint64_t total_received; double total_sq_persec, total_persec; double variance; double expected_total_persec = -1.0, expected_avg_persec = -1.0; int ok = 1; struct event_config *base_cfg; struct event *periodic_level_check; struct event *group_drain_event=NULL; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ sin.sin_port = 0; /* unspecified port */ if (0) event_enable_debug_mode(); base_cfg = event_config_new(); #ifdef _WIN32 if (cfg_enable_iocp) { evthread_use_windows_threads(); event_config_set_flag(base_cfg, EVENT_BASE_FLAG_STARTUP_IOCP); } #endif base = event_base_new_with_config(base_cfg); event_config_free(base_cfg); if (! base) { fprintf(stderr, "Couldn't create event_base"); return 1; } listener = evconnlistener_new_bind(base, echo_listenercb, base, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1, (struct sockaddr *)&sin, sizeof(sin)); if (! listener) { fprintf(stderr, "Couldn't create listener"); return 1; } slen = sizeof(ss); if (getsockname(evconnlistener_get_fd(listener), (struct sockaddr *)&ss, &slen) < 0) { perror("getsockname"); return 1; } if (cfg_connlimit > 0) { conn_bucket_cfg = ev_token_bucket_cfg_new( cfg_connlimit, cfg_connlimit * 4, cfg_connlimit, cfg_connlimit * 4, &cfg_tick); assert(conn_bucket_cfg); } if (cfg_grouplimit > 0) { group_bucket_cfg = ev_token_bucket_cfg_new( cfg_grouplimit, cfg_grouplimit * 4, cfg_grouplimit, cfg_grouplimit * 4, &cfg_tick); group = ratelim_group = bufferevent_rate_limit_group_new( base, group_bucket_cfg); expected_total_persec = cfg_grouplimit - (cfg_group_drain / seconds_per_tick); expected_avg_persec = cfg_grouplimit / cfg_n_connections; if (cfg_connlimit > 0 && expected_avg_persec > cfg_connlimit) expected_avg_persec = cfg_connlimit; if (cfg_min_share >= 0) bufferevent_rate_limit_group_set_min_share( ratelim_group, cfg_min_share); } if (expected_avg_persec < 0 && cfg_connlimit > 0) expected_avg_persec = cfg_connlimit; if (expected_avg_persec > 0) expected_avg_persec /= seconds_per_tick; if (expected_total_persec > 0) expected_total_persec /= seconds_per_tick; bevs = calloc(cfg_n_connections, sizeof(struct bufferevent *)); states = calloc(cfg_n_connections, sizeof(struct client_state)); for (i = 0; i < cfg_n_connections; ++i) { bevs[i] = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_THREADSAFE); assert(bevs[i]); bufferevent_setcb(bevs[i], discard_readcb, loud_writecb, write_on_connectedcb, &states[i]); bufferevent_enable(bevs[i], EV_READ|EV_WRITE); bufferevent_socket_connect(bevs[i], (struct sockaddr *)&ss, slen); } tv.tv_sec = cfg_duration - 1; tv.tv_usec = 995000; event_base_loopexit(base, &tv); tv.tv_sec = 0; tv.tv_usec = 100*1000; ms100_common = event_base_init_common_timeout(base, &tv); periodic_level_check = event_new(base, -1, EV_PERSIST, check_group_bucket_levels_cb, NULL); event_add(periodic_level_check, ms100_common); if (cfg_group_drain && ratelim_group) { group_drain_event = event_new(base, -1, EV_PERSIST, group_drain_cb, NULL); event_add(group_drain_event, &cfg_tick); } event_base_dispatch(base); ratelim_group = NULL; /* So no more responders get added */ event_free(periodic_level_check); if (group_drain_event) event_del(group_drain_event); for (i = 0; i < cfg_n_connections; ++i) { bufferevent_free(bevs[i]); } evconnlistener_free(listener); /* Make sure no new echo_conns get added to the group. */ ratelim_group = NULL; /* This should get _everybody_ freed */ while (n_echo_conns_open) { printf("waiting for %d conns\n", n_echo_conns_open); tv.tv_sec = 0; tv.tv_usec = 300000; event_base_loopexit(base, &tv); event_base_dispatch(base); } if (group) bufferevent_rate_limit_group_free(group); if (total_n_bev_checks) { printf("Average read bucket level: %f\n", (double)total_rbucket_level/total_n_bev_checks); printf("Average write bucket level: %f\n", (double)total_wbucket_level/total_n_bev_checks); printf("Highest read bucket level: %f\n", (double)max_bucket_level); printf("Highest write bucket level: %f\n", (double)min_bucket_level); printf("Average max-to-read: %f\n", ((double)total_max_to_read)/total_n_bev_checks); printf("Average max-to-write: %f\n", ((double)total_max_to_write)/total_n_bev_checks); } if (total_n_group_bev_checks) { printf("Average group read bucket level: %f\n", ((double)total_group_rbucket_level)/total_n_group_bev_checks); printf("Average group write bucket level: %f\n", ((double)total_group_wbucket_level)/total_n_group_bev_checks); } total_received = 0; total_persec = 0.0; total_sq_persec = 0.0; for (i=0; i < cfg_n_connections; ++i) { double persec = states[i].received; persec /= cfg_duration; total_received += states[i].received; total_persec += persec; total_sq_persec += persec*persec; printf("%d: %f per second\n", i+1, persec); } printf(" total: %f per second\n", ((double)total_received)/cfg_duration); if (expected_total_persec > 0) { double diff = expected_total_persec - ((double)total_received/cfg_duration); printf(" [Off by %lf]\n", diff); if (cfg_grouplimit_tolerance > 0 && fabs(diff) > cfg_grouplimit_tolerance) { fprintf(stderr, "Group bandwidth out of bounds\n"); ok = 0; } } printf(" average: %f per second\n", (((double)total_received)/cfg_duration)/cfg_n_connections); if (expected_avg_persec > 0) { double diff = expected_avg_persec - (((double)total_received)/cfg_duration)/cfg_n_connections; printf(" [Off by %lf]\n", diff); if (cfg_connlimit_tolerance > 0 && fabs(diff) > cfg_connlimit_tolerance) { fprintf(stderr, "Connection bandwidth out of bounds\n"); ok = 0; } } variance = total_sq_persec/cfg_n_connections - total_persec*total_persec/(cfg_n_connections*cfg_n_connections); printf(" stddev: %f per second\n", sqrt(variance)); if (cfg_stddev_tolerance > 0 && sqrt(variance) > cfg_stddev_tolerance) { fprintf(stderr, "Connection variance out of bounds\n"); ok = 0; } event_base_free(base); free(bevs); free(states); return ok ? 0 : 1; }
static int http_map_finish (struct rspamd_http_connection *conn, struct rspamd_http_message *msg) { struct http_callback_data *cbd = conn->ud; struct rspamd_map *map; struct rspamd_map_backend *bk; guchar *aux_data, *in = NULL; gsize inlen = 0, dlen = 0; map = cbd->map; bk = cbd->bk; if (msg->code == 200) { if (cbd->check) { cbd->periodic->need_modify = TRUE; /* Reset the whole chain */ cbd->periodic->cur_backend = 0; rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic); MAP_RELEASE (cbd, "http_callback_data"); return 0; } if (cbd->stage == map_load_file) { if (msg->last_modified) { cbd->data->last_checked = msg->last_modified; } else { cbd->data->last_checked = msg->date; } /* Maybe we need to check signature ? */ if (bk->is_signed) { if (bk->trusted_pubkey) { /* No need to load key */ cbd->stage = map_load_signature; cbd->pk = rspamd_pubkey_ref (bk->trusted_pubkey); } else { cbd->stage = map_load_pubkey; } cbd->shmem_data = rspamd_http_message_shmem_ref (msg); cbd->data_len = msg->body_buf.len; rspamd_http_connection_reset (cbd->conn); write_http_request (cbd); MAP_RELEASE (cbd, "http_callback_data"); return 0; } else { /* Unsinged version - just open file */ cbd->shmem_data = rspamd_http_message_shmem_ref (msg); cbd->data_len = msg->body_buf.len; goto read_data; } } else if (cbd->stage == map_load_pubkey) { /* We now can load pubkey */ cbd->shmem_pubkey = rspamd_http_message_shmem_ref (msg); cbd->pubkey_len = msg->body_buf.len; aux_data = rspamd_shmem_xmap (cbd->shmem_pubkey->shm_name, PROT_READ, &inlen); if (aux_data == NULL) { msg_err_map ("cannot map pubkey file %s: %s", cbd->shmem_pubkey->shm_name, strerror (errno)); goto err; } if (inlen < cbd->pubkey_len) { msg_err_map ("cannot map pubkey file %s: %s", cbd->shmem_pubkey->shm_name, strerror (errno)); munmap (aux_data, inlen); goto err; } cbd->pk = rspamd_pubkey_from_base32 (aux_data, cbd->pubkey_len, RSPAMD_KEYPAIR_SIGN, RSPAMD_CRYPTOBOX_MODE_25519); munmap (aux_data, inlen); if (cbd->pk == NULL) { msg_err_map ("cannot load pubkey file %s: bad pubkey", cbd->shmem_pubkey->shm_name); goto err; } cbd->stage = map_load_signature; rspamd_http_connection_reset (cbd->conn); write_http_request (cbd); MAP_RELEASE (cbd, "http_callback_data"); return 0; } else if (cbd->stage == map_load_signature) { /* We can now check signature */ cbd->shmem_sig = rspamd_http_message_shmem_ref (msg); cbd->sig_len = msg->body_buf.len; aux_data = rspamd_shmem_xmap (cbd->shmem_sig->shm_name, PROT_READ, &inlen); if (aux_data == NULL) { msg_err_map ("cannot map signature file %s: %s", cbd->shmem_sig->shm_name, strerror (errno)); goto err; } if (inlen < cbd->sig_len) { msg_err_map ("cannot map pubkey file %s: %s", cbd->shmem_pubkey->shm_name, strerror (errno)); munmap (aux_data, inlen); goto err; } in = rspamd_shmem_xmap (cbd->shmem_data->shm_name, PROT_READ, &dlen); if (in == NULL) { msg_err_map ("cannot read tempfile %s: %s", cbd->shmem_data->shm_name, strerror (errno)); munmap (aux_data, inlen); goto err; } if (!rspamd_map_check_sig_pk_mem (aux_data, cbd->sig_len, map, in, cbd->data_len, cbd->pk)) { munmap (aux_data, inlen); munmap (in, dlen); goto err; } munmap (in, dlen); } read_data: g_assert (cbd->shmem_data != NULL); in = rspamd_shmem_xmap (cbd->shmem_data->shm_name, PROT_READ, &dlen); if (in == NULL) { msg_err_map ("cannot read tempfile %s: %s", cbd->shmem_data->shm_name, strerror (errno)); goto err; } map->read_callback (in, cbd->data_len, &cbd->periodic->cbdata, TRUE); msg_info_map ("read map data from %s", cbd->data->host); /* * We know that a map is in the locked state */ if (g_atomic_int_compare_and_exchange (&map->cache->available, 0, 1)) { /* Store cached data */ struct rspamd_http_map_cached_cbdata *cache_cbd; struct timeval tv; rspamd_strlcpy (map->cache->shmem_name, cbd->shmem_data->shm_name, sizeof (map->cache->shmem_name)); map->cache->len = cbd->data_len; map->cache->last_checked = cbd->data->last_checked; cache_cbd = g_slice_alloc0 (sizeof (*cache_cbd)); cache_cbd->shm = cbd->shmem_data; cache_cbd->map = map; MAP_RETAIN (cache_cbd->shm, "shmem_data"); event_set (&cache_cbd->timeout, -1, EV_TIMEOUT, rspamd_map_cache_cb, cache_cbd); event_base_set (cbd->ev_base, &cache_cbd->timeout); double_to_tv (map->poll_timeout, &tv); event_add (&cache_cbd->timeout, &tv); } cbd->periodic->cur_backend ++; munmap (in, dlen); rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic); } else if (msg->code == 304 && (cbd->check && cbd->stage == map_load_file)) { msg_debug_map ("data is not modified for server %s", cbd->data->host); if (msg->last_modified) { cbd->data->last_checked = msg->last_modified; } else { cbd->data->last_checked = msg->date; } cbd->periodic->cur_backend ++; rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic); } else { msg_info_map ("cannot load map %s from %s: HTTP error %d", bk->uri, cbd->data->host, msg->code); } MAP_RELEASE (cbd, "http_callback_data"); return 0; err: cbd->periodic->errored = 1; rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic); MAP_RELEASE (cbd, "http_callback_data"); return 0; }
void init(int argc, char **argv){ if(argc < 2){ usage(argc, argv); exit(0); } signal(SIGPIPE, SIG_IGN); { struct timeval tv; if(gettimeofday(&tv, NULL) == -1){ srand(time(NULL) + getpid()); }else{ srand(tv.tv_sec + tv.tv_usec + getpid()); } } bool is_daemon = false; const char *conf_file = NULL; for(int i=1; i<argc; i++){ if(strcmp(argv[i], "-d") == 0){ is_daemon = true; }else{ conf_file = argv[i]; } } if(conf_file == NULL){ usage(argc, argv); exit(0); } if(!is_file(conf_file)){ fprintf(stderr, "'%s' is not a file or not exists!\n", conf_file); exit(0); } conf = Config::load(conf_file); if(!conf){ fprintf(stderr, "error loading conf file: '%s'\n", conf_file); exit(0); } { std::string conf_dir = real_dirname(conf_file); if(chdir(conf_dir.c_str()) == -1){ fprintf(stderr, "error chdir: %s\n", conf_dir.c_str()); exit(0); } } std::string log_output; int log_rotate_size = 0; { // logger int log_level = Logger::get_level(conf->get_str("logger.level")); log_rotate_size = conf->get_num("logger.rotate.size"); if(log_rotate_size < 1024 * 1024){ log_rotate_size = 1024 * 1024; } log_output = conf->get_str("logger.output"); if(log_output == ""){ log_output = "stdout"; } if(log_open(log_output.c_str(), log_level, true, log_rotate_size) == -1){ fprintf(stderr, "error open log file: %s\n", log_output.c_str()); exit(0); } } check_pidfile(); if(is_daemon){ daemonize(); } log_info("starting icomet %s...", ICOMET_VERSION); log_info("config file: %s", conf_file); log_info("log_level : %s", conf->get_str("logger.level")); log_info("log_output : %s", log_output.c_str()); log_info("log_rotate_size : %d", log_rotate_size); evbase = event_base_new(); if(!evbase){ fprintf(stderr, "create evbase error!\n"); exit(0); } admin_http = evhttp_new(evbase); if(!admin_http){ fprintf(stderr, "create admin_http error!\n"); exit(0); } front_http = evhttp_new(evbase); if(!front_http){ fprintf(stderr, "create front_http error!\n"); exit(0); } sigint_event = evsignal_new(evbase, SIGINT, signal_cb, NULL); if(!sigint_event || event_add(sigint_event, NULL)<0){ fprintf(stderr, "Could not create/add a signal event!\n"); exit(0); } sigterm_event = evsignal_new(evbase, SIGTERM, signal_cb, NULL); if(!sigterm_event || event_add(sigterm_event, NULL)<0){ fprintf(stderr, "Could not create/add a signal event!\n"); exit(0); } timer_event = event_new(evbase, -1, EV_PERSIST, timer_cb, NULL); { struct timeval tv; tv.tv_sec = CHANNEL_CHECK_INTERVAL; tv.tv_usec = 0; if(!timer_event || evtimer_add(timer_event, &tv)<0){ fprintf(stderr, "Could not create/add a timer event!\n"); exit(0); } } }
/* Thread: main */ int remote_pairing_init(void) { int ret; remote_list = NULL; #ifdef USE_EVENTFD pairing_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (pairing_efd < 0) { DPRINTF(E_FATAL, L_REMOTE, "Could not create eventfd: %s\n", strerror(errno)); return -1; } #else # if defined(__linux__) ret = pipe2(pairing_pipe, O_CLOEXEC | O_NONBLOCK); # else ret = pipe(pairing_pipe); # endif if (ret < 0) { DPRINTF(E_FATAL, L_REMOTE, "Could not create pairing pipe: %s\n", strerror(errno)); return -1; } # ifndef __linux__ ret = fcntl(pairing_pipe[0], F_SETFL, O_NONBLOCK); if (ret < 0) { DPRINTF(E_FATAL, L_REMOTE, "Could not set O_NONBLOCK: %s\n", strerror(errno)); goto pairing_pipe_fail; } # endif #endif /* USE_EVENTFD */ ret = mdns_browse("_touch-remote._tcp", touch_remote_cb); if (ret < 0) { DPRINTF(E_FATAL, L_REMOTE, "Could not browse for Remote services\n"); goto mdns_browse_fail; } #ifdef USE_EVENTFD event_set(&pairingev, pairing_efd, EV_READ, pairing_cb, NULL); #else event_set(&pairingev, pairing_pipe[0], EV_READ, pairing_cb, NULL); #endif event_base_set(evbase_main, &pairingev); event_add(&pairingev, NULL); return 0; #ifndef __linux__ pairing_pipe_fail: #endif mdns_browse_fail: #ifdef USE_EVENTFD close(pairing_efd); #else close(pairing_pipe[0]); close(pairing_pipe[1]); #endif return -1; }
int main (int argc, gchar **argv) { GOptionContext *context; GError *error = NULL; struct event_base *ev_base; GString *b32_key; pid_t *sfd; rspamd_inet_addr_t *addr; struct event term_ev, int_ev; struct in_addr ina = {INADDR_ANY}; rspamd_init_libs (); context = g_option_context_new ( "rspamd-http-server - test server for benchmarks"); g_option_context_set_summary (context, "Summary:\n Rspamd test HTTP server " RVERSION "\n Release id: " RID); g_option_context_add_main_entries (context, entries, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { rspamd_fprintf (stderr, "option parsing failed: %s\n", error->message); g_error_free (error); exit (1); } maps = g_hash_table_new (g_int_hash, g_int_equal); if (key == NULL) { server_key = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX, openssl_mode ? RSPAMD_CRYPTOBOX_MODE_NIST : RSPAMD_CRYPTOBOX_MODE_25519); b32_key = rspamd_keypair_print (server_key, RSPAMD_KEYPAIR_PUBKEY | RSPAMD_KEYPAIR_BASE32); rspamd_printf ("key: %v\n", b32_key); } else { /* TODO: add key loading */ } if (cache_size > 0) { c = rspamd_keypair_cache_new (cache_size); } sfd = g_alloca (sizeof (*sfd) * nworkers); addr = rspamd_inet_address_new (AF_INET, &ina); rspamd_inet_address_set_port (addr, port); rspamd_http_start_servers (sfd, addr); /* Just wait for workers */ ev_base = event_init (); event_set (&term_ev, SIGTERM, EV_SIGNAL, rspamd_http_server_term, sfd); event_base_set (ev_base, &term_ev); event_add (&term_ev, NULL); event_set (&int_ev, SIGINT, EV_SIGNAL, rspamd_http_server_term, sfd); event_base_set (ev_base, &int_ev); event_add (&int_ev, NULL); event_base_loop (ev_base, 0); return 0; }
int NetReactor::NetReactor::init() { event_init(); Log::NOTICE("Listen Port %d", _port); _listenFd = net_tcplisten(_port, 100); set_fd_noblock(_listenFd); event_set(&_listener, _listenFd, EV_READ|EV_PERSIST, ReactorAccept, this); event_add(&_listener, NULL); /********test app conn ********/ NetConnManager * cMag = NetConnManager::getInstance(); string appSvrIp("127.0.0.1"); struct sockaddr_in svr_address1, svr_address2; set_tcp_sockaddr(appSvrIp.c_str(), 1090, &svr_address1); set_tcp_sockaddr(appSvrIp.c_str(), 1090, &svr_address2); int appFd1 = socket(AF_INET, SOCK_STREAM, 0); int appFd2 = socket(AF_INET, SOCK_STREAM, 0); int res = net_connect_to_ms(appFd1, (struct sockaddr *)&svr_address1, sizeof(svr_address1), 1000, 1); if(res < 0) { Log::ERROR("INIT ERROR: CAN not connect to appSvr"); close(appFd1); return -1; } res = net_connect_to_ms(appFd2, (struct sockaddr *)&svr_address2, sizeof(svr_address2), 1000, 1); if(res < 0) { Log::ERROR("INIT ERROR: CAN not connect to appSvr"); close(appFd2); return -1; } vector<int> fdVec; vector<struct sockaddr_in> fdAddr; fdVec.push_back(appFd1); fdVec.push_back(appFd2); fdAddr.push_back(svr_address1); fdAddr.push_back(svr_address2); for(int i = 0; i < fdVec.size(); i++) { printf("init conn %d %d \n", fdVec[0],fdVec[1]); struct bufferevent * bev; bev = bufferevent_new(fdVec[i], EvReadCallback, NULL, EvErrorCallback, this); bev->timeout_read = 1800; bev->timeout_write = 1800; bufferevent_enable(bev, EV_READ|EV_WRITE); std::unique_ptr<Iconn> con(new AppConn(this, bev, appSvrIp, 1090)); cMag->setConn(fdVec[i], std::move(con)); cMag->addAppConnFd(fdVec[i]); } Log::NOTICE("Connect to App Svr succ"); /* end test app conn*/ }
bool LibEventHttpClient::send(const std::string &url, const std::vector<std::string> &headers, int timeoutSeconds, bool async, const void *data /* = NULL */, int size /* = 0 */) { clear(); m_url = url; if (m_conn == NULL) { m_conn = evhttp_connection_new(m_address.c_str(), m_port); evhttp_connection_set_closecb(m_conn, on_connection_closed, this); evhttp_connection_set_base(m_conn, m_eventBase); } m_request = evhttp_request_new(on_request_completed, this); // REVIEW: libevent never sends a Host header (nor does it properly send HTTP // 400 for HTTP/1.1 requests without such a header), in blatent violation of // RFC2616; this should perhaps be fixed in the library proper. if (m_port == 80) { evhttp_add_header(m_request->output_headers, "Host", m_address.c_str()); } else { std::ostringstream ss; ss << m_address << ":" << m_port; evhttp_add_header(m_request->output_headers, "Host", ss.str().c_str()); } // request headers bool keepalive = true; for (unsigned int i = 0; i < headers.size(); i++) { const std::string &header = headers[i]; size_t pos = header.find(':'); if (pos != string::npos && header[pos + 1] == ' ') { string name = header.substr(0, pos); if (strcasecmp(name.c_str(), "Connection") == 0) { keepalive = false; } int ret = evhttp_add_header(m_request->output_headers, name.c_str(), header.c_str() + pos + 2); if (ret >= 0) { continue; } } Logger::Error("invalid request header: [%s]", header.c_str()); } if (keepalive) { evhttp_add_header(m_request->output_headers, "Connection", "keep-alive"); } // post data if (data && size) { evbuffer_add(m_request->output_buffer, data, size); } // url evhttp_cmd_type cmd = data ? EVHTTP_REQ_POST : EVHTTP_REQ_GET; int ret = evhttp_make_request(m_conn, m_request, cmd, url.c_str()); if (ret != 0) { Logger::Error("evhttp_make_request failed"); return false; } if (timeoutSeconds > 0) { struct timeval timeout; timeout.tv_sec = timeoutSeconds; timeout.tv_usec = 0; event_set(&m_eventTimeout, -1, 0, timer_callback, m_eventBase); event_base_set(m_eventBase, &m_eventTimeout); event_add(&m_eventTimeout, &timeout); } if (async) { m_thread = new AsyncFunc<LibEventHttpClient> (this, &LibEventHttpClient::sendImpl); m_thread->start(); } else { sendImpl(); } return true; }
void client::handle_event(short evtype) { // connect() returning to us? normally we expect EV_WRITE, but for UNIX domain // sockets we workaround since connect() returned immediately, but we don't want // to do any I/O from the client::connect() call... if (!m_connected && (evtype == EV_WRITE || m_unix_sockaddr != NULL)) { int error = -1; socklen_t errsz = sizeof(error); if (getsockopt(m_sockfd, SOL_SOCKET, SO_ERROR, (void *) &error, &errsz) == -1) { benchmark_error_log("connect: error getting connect response (getsockopt): %s\n", strerror(errno)); return; } if (error != 0) { benchmark_error_log("connect: connection failed: %s\n", strerror(error)); return; } m_connected = true; if (!m_reqs_processed) { process_first_request(); } else { benchmark_debug_log("reconnection complete, proceeding with test\n"); fill_pipeline(); } } assert(m_connected == true); if ((evtype & EV_WRITE) == EV_WRITE && evbuffer_get_length(m_write_buf) > 0) { if (evbuffer_write(m_write_buf, m_sockfd) < 0) { if (errno != EWOULDBLOCK) { benchmark_error_log("write error: %s\n", strerror(errno)); disconnect(); return; } } } if ((evtype & EV_READ) == EV_READ) { int ret = 1; while (ret > 0) { ret = evbuffer_read(m_read_buf, m_sockfd, -1); } if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { benchmark_error_log("read error: %s\n", strerror(errno)); disconnect(); return; } if (ret == 0) { benchmark_error_log("connection dropped.\n"); disconnect(); return; } if (evbuffer_get_length(m_read_buf) > 0) { process_response(); // process_response may have disconnected, in which case // we just abort and wait for libevent to call us back sometime if (!m_connected) { return; } } } // update event short new_evtype = 0; if (!finished()) { new_evtype = EV_READ; } if (evbuffer_get_length(m_write_buf) > 0) { assert(finished() == false); new_evtype |= EV_WRITE; } if (new_evtype) { int ret = event_assign(m_event, m_event_base, m_sockfd, new_evtype, client_event_handler, (void *)this); assert(ret == 0); ret = event_add(m_event, NULL); assert(ret == 0); } else { benchmark_debug_log("nothing else to do, test is finished.\n"); m_stats.set_end_time(NULL); } }
int client::connect(void) { struct connect_info addr; // clean up existing socket/buffers if (m_sockfd != -1) close(m_sockfd); evbuffer_drain(m_read_buf, evbuffer_get_length(m_read_buf)); evbuffer_drain(m_write_buf, evbuffer_get_length(m_write_buf)); if (m_unix_sockaddr != NULL) { m_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (m_sockfd < 0) { return -errno; } } else { if (m_config->server_addr->get_connect_info(&addr) != 0) { benchmark_error_log("connect: resolve error: %s\n", m_config->server_addr->get_last_error()); return -1; } // initialize socket m_sockfd = socket(addr.ci_family, addr.ci_socktype, addr.ci_protocol); if (m_sockfd < 0) { return -errno; } // configure socket behavior struct linger ling = {0, 0}; int flags = 1; int error = setsockopt(m_sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)); assert(error == 0); error = setsockopt(m_sockfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling)); assert(error == 0); error = setsockopt(m_sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); assert(error == 0); } // set non-blocking behavior int flags = 1; if ((flags = fcntl(m_sockfd, F_GETFL, 0)) < 0 || fcntl(m_sockfd, F_SETFL, flags | O_NONBLOCK) < 0) { benchmark_error_log("connect: failed to set non-blocking flag.\n"); close(m_sockfd); m_sockfd = -1; return -1; } // set up event if (!m_event) { m_event = event_new(m_event_base, m_sockfd, EV_WRITE, client_event_handler, (void *)this); assert(m_event != NULL); } else { int ret = event_del(m_event); assert(ret == 0); ret = event_assign(m_event, m_event_base, m_sockfd, EV_WRITE, client_event_handler, (void *)this); assert(ret == 0); } int ret = event_add(m_event, NULL); assert(ret == 0); // call connect if (::connect(m_sockfd, m_unix_sockaddr ? (struct sockaddr *) m_unix_sockaddr : addr.ci_addr, m_unix_sockaddr ? sizeof(struct sockaddr_un) : addr.ci_addrlen) == -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; benchmark_error_log("connect failed, error = %s\n", strerror(errno)); return -1; } return 0; }
/** A work queue is a mechanism to allow thread-to-thread * communication in a libevent-based, multithreaded system. * * One thread can send work to another thread. The receiving thread * should be libevent-based, with a processing loop handled by * libevent. * * Use work_queue_init() to initialize a work_queue structure, * where the work_queue structure memory is owned by the caller. * * Returns true on success. */ bool work_queue_init(work_queue *m, struct event_base *event_base) { assert(m != NULL); memset(m, 0, sizeof(work_queue)); pthread_mutex_init(&m->work_lock, NULL); m->work_head = NULL; m->work_tail = NULL; m->num_items = 0; m->tot_sends = 0; m->tot_recvs = 0; m->event_base = event_base; assert(m->event_base != NULL); int fds[2] = {0}; #ifdef WIN32 struct sockaddr_in serv_addr; int sockfd; if ((sockfd = createLocalListSock(&serv_addr)) < 0 || createLocalSocketPair(sockfd,fds,&serv_addr) == -1) { fprintf(stderr, "Can't create notify pipe: %s", strerror(errno)); return false; } #else if (pipe(fds)) { perror("Can't create notify pipe"); return false; } #endif m->recv_fd = fds[0]; m->send_fd = fds[1]; event_set(&m->event, m->recv_fd, EV_READ | EV_PERSIST, work_recv, m); event_base_set(m->event_base, &m->event); if (event_add(&m->event, 0) == 0) { #ifdef WORK_DEBUG moxi_log_write("work_queue_init %x %x %x %d %d %u %llu\n", (int) pthread_self(), (int) m, (int) m->event_base, m->send_fd, m->recv_fd, m->work_head != NULL, m->tot_sends); #endif return true; } #ifdef WORK_DEBUG moxi_log_write("work_queue_init error\n"); #endif return false; }
int jsonrpc_send(str conn, jsonrpc_request_t* req, bool notify_only) { char* json = (char*)json_dumps(req->payload, JSON_COMPACT); char* ns; size_t bytes; bytes = netstring_encode_new(&ns, json, (size_t)strlen(json)); bool sent = false; jsonrpc_server_group_t* c_grp = NULL; if(global_server_group != NULL) c_grp = *global_server_group; jsonrpc_server_group_t* p_grp = NULL; jsonrpc_server_group_t* w_grp = NULL; jsonrpc_server_t* s = NULL; server_list_t* tried_servers = NULL; DEBUG("SENDING DATA\n"); for(; c_grp != NULL; c_grp = c_grp->next) { if(strncmp(conn.s, c_grp->conn.s, c_grp->conn.len) != 0) continue; for(p_grp = c_grp->sub_group; p_grp != NULL; p_grp = p_grp->next) { w_grp = p_grp->sub_group; while(!sent) { loadbalance_by_weight(&s, w_grp, tried_servers); if (s == NULL || s->status != JSONRPC_SERVER_CONNECTED) { break; } if(bufferevent_write(s->bev, ns, bytes) == 0) { sent = true; if(!notify_only) { s->req_count++; if (s->hwm > 0 && s->req_count >= s->hwm) { WARN("%.*s:%d in connection group %.*s has exceeded its high water mark (%d)\n", STR(s->addr), s->port, STR(s->conn), s->hwm); } } req->server = s; break; } else { addto_server_list(s, &tried_servers); } } if (sent) { break; } WARN("Failed to send to priority group, %d\n", p_grp->priority); if(p_grp->next != NULL) { INFO("Proceeding to next priority group, %d\n", p_grp->next->priority); } } if (sent) { break; } } if(!sent) { WARN("Failed to send to connection group, \"%.*s\"\n", STR(conn)); if(schedule_retry(req)<0) { fail_request(JRPC_ERR_RETRY, req, "Failed to schedule retry"); } } free_server_list(tried_servers); if(ns) pkg_free(ns); if(json) free(json); if (sent && notify_only == false) { const struct timeval tv = ms_to_tv(req->timeout); req->timeout_ev = evtimer_new(global_ev_base, timeout_cb, (void*)req); if(event_add(req->timeout_ev, &tv)<0) { ERR("event_add failed while setting request timer (%s).", strerror(errno)); return -1; } } return sent; }
int main(int argc, char *argv[]) { const char *cause = NULL; int ch, nsocks = 0, save_errno = 0; int inet4 = 0, inet6 = 0; char group[ICB_MAXGRPLEN], *grplist = NULL; char *ptr = NULL; /* init group lists before calling icb_addgroup */ icb_init(); while ((ch = getopt(argc, argv, "46CdG:M:nL:S:v")) != -1) switch (ch) { case '4': inet4++; break; case '6': inet6++; break; case 'C': creategroups++; break; case 'd': foreground++; break; case 'G': grplist = optarg; break; case 'L': strlcpy(logprefix, optarg, sizeof logprefix); dologging++; break; case 'M': strlcpy(modtabpath, optarg, sizeof modtabpath); break; case 'n': dodns = 0; break; case 'S': strlcpy(srvname, optarg, sizeof srvname); break; case 'v': verbose++; break; default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; /* add group "1" as it's a login group for most of the clients */ if (icb_addgroup(NULL, "1") == NULL) err(EX_UNAVAILABLE, NULL); if (grplist) { while (icb_token(grplist, strlen(grplist), &ptr, group, ICB_MAXGRPLEN, ',', 0) > 0) if (icb_addgroup(NULL, group) == NULL) err(EX_UNAVAILABLE, NULL); } if (argc == 0) argc++; if (inet4 && inet6) errx(EX_USAGE, "Can't specify both -4 and -6"); tzset(); (void)setlocale(LC_ALL, "C"); if (foreground) openlog("icbd", LOG_PID | LOG_PERROR, LOG_DAEMON); else openlog("icbd", LOG_PID | LOG_NDELAY, LOG_DAEMON); if (!foreground && daemon(0, 0) < 0) err(EX_OSERR, NULL); (void)event_init(); for (ch = 0; ch < argc; ch++) { struct addrinfo hints, *res, *res0; struct icbd_listener *l; char *addr, *port; int error, s, on = 1; addr = port = NULL; if (argv[ch] != NULL) { if (argv[ch][0] != ':') addr = argv[ch]; if ((port = strrchr(argv[ch], ':')) != NULL) *port++ = '\0'; } bzero(&hints, sizeof hints); if (inet4 || inet6) hints.ai_family = inet4 ? PF_INET : PF_INET6; else hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if ((error = getaddrinfo(addr, port ? port : "icb", &hints, &res0)) != 0) { syslog(LOG_ERR, "%s", gai_strerror(error)); return (EX_UNAVAILABLE); } for (res = res0; res != NULL; res = res->ai_next) { if ((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) { cause = "socket"; save_errno = errno; continue; } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) { cause = "SO_REUSEADDR"; save_errno = errno; (void)close(s); continue; } if (bind(s, res->ai_addr, res->ai_addrlen) < 0) { cause = "bind"; save_errno = errno; (void)close(s); continue; } (void)listen(s, TCP_BACKLOG); if ((l = calloc(1, sizeof *l)) == NULL) err(EX_UNAVAILABLE, NULL); event_set(&l->ev, s, EV_READ | EV_PERSIST, icbd_accept, l); if (event_add(&l->ev, NULL) < 0) { syslog(LOG_ERR, "event_add: %m"); return (EX_UNAVAILABLE); } evtimer_set(&l->pause, icbd_paused, l); nsocks++; } freeaddrinfo(res0); } if (nsocks == 0) { errno = save_errno; syslog(LOG_ERR, "%s: %m", cause); return (EX_UNAVAILABLE); } /* start the logger service */ logger_init(); /* initialize resolver */ res_init(); icbd_restrict(); icbd_modupdate(); (void)signal(SIGPIPE, SIG_IGN); (void)event_dispatch(); syslog(LOG_ERR, "event_dispatch: %m"); return (EX_UNAVAILABLE); }
/* 从对端 server 的 data 链路收到数据,把它放到对应的 kmod 节点中 */ void node_data_handler(evutil_socket_t fd, short event, void *args) { struct node *node; struct daemon *daemon; struct device_list *dev_list; struct device *dev; struct packet *pkt; struct packet *pkt_clone; int i, ret, full; cb_fn *cb; node = (struct node *)args; daemon = node->daemon; dev_list = daemon->dev_list; pkt = handler_recv(node->dfd); if (!pkt) { node_del_data_event(node); log_error("receive data from server node %d failed", node->id); return; } /* FIXME 如果某个device的queue满了,在这里就会等待,从而造成两个问题: * 1. 这是event的call back函数,如果等待会造成event base的阻塞 * 2. 单个device队列满而影响到所有其它device,不公平 * 是否可以这样? * 提前获取队列一个空位,如果失败的话,直接返回, * 当队列有剩余空间时再加入该event * 但是,device互相影响的问题还是没能解决,满了直接断连? */ full = 0; for (i = 0; i < dev_list->dev_num; i++) { //FIXME 查找效率很低,可考虑序号对应下标,并且判读是否是只有单个device dev = dev_list->devs[i]; if (!device_is_target(dev, pkt->kmod_to)) continue; if (!device_want_recv(dev)) continue; pkt_clone = packet_clone(pkt); if (!pkt_clone) { log_error("send to kmod node %d failed: no memory", dev->id); free_packet(pkt_clone); goto out; } cb = full ? NULL : node_data_handle_force_cb; ret = dev_put_data_packet_force(dev, pkt_clone, cb, node); if (ret < 0) { log_error("kmod node %d data queue is NOT start", dev->id); goto out; } else if (ret > 0) { log_info("%s force handle for node %d", __func__, node->id); full = 1; } } out: free_packet(pkt); if (!full) { ret = event_add(node->data_event, NULL); if (ret < 0) { log_error("failed to add data event on node %d", node->id); node_del_data_event(node); } } }
//Main int main(int argc, char *argv[]) { //Get args if (argc < 2) { fprintf(stderr, "Usage: %s <snapshot_file>\n", argv[0]); return 1; } snap_path = argv[1]; //Allocate memory fprintf(stderr, "Allocating arena with size %.2f MBytes ...\n", (float)m / CHAR_BIT / MEGA); Bloom = malloc( (m + ( CHAR_BIT - 1)) / CHAR_BIT ); // Ceil byte length: bytes = bits + 7 / 8 //Load or create snapshot file if (!access(snap_path, F_OK)) { fputs("Loading snapshot...\n", stderr); if (LoadSnap(Bloom, snap_path)) { fputs("Unable to load snapshot!\n", stderr); return -1; } fputs("Snapshot loaded.\n", stderr); } else { fputs("Initializing new file storage...\n", stderr); size_t shouldwrite = (m + (CHAR_BIT - 1)) / CHAR_BIT; memset(Bloom, 0, shouldwrite); if (SaveSnap(Bloom, snap_path)) { fputs("Unable to save initial snapshot!\n", stderr); return -1; } fputs("Initial snapshot written.\n", stderr); } void OnReq(struct evhttp_request *req, void *arg) { struct evbuffer *OutBuf = evhttp_request_get_output_buffer(req); if (!OutBuf) { evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf); return; } struct evkeyvalq *Headers = evhttp_request_get_output_headers(req); if (!Headers) { evhttp_send_reply(req, HTTP_INTERNAL, "Internal Error", OutBuf); return; } const struct evhttp_uri *HTTPURI = evhttp_request_get_evhttp_uri(req); if (!HTTPURI) { evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf); return; } const char *path = evhttp_uri_get_path(HTTPURI); if (!path) { evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf); } const char *query_string = evhttp_uri_get_query(HTTPURI); if (!query_string) { evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf); return; } struct evkeyvalq params; evhttp_parse_query_str(query_string, ¶ms); const char *element = evhttp_find_header(¶ms, "e"); if (!element) { evhttp_clear_headers(¶ms); evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf); return; } int i; const char* (*Operation)(bloom_cell *, size_t []) = NULL; for (i=0; i< sizeof HandlerTable/ sizeof HandlerTable[0] ; i++) if (strncmp(HandlerTable[i][0], path, STR_MAX) == 0) { Operation = HandlerTable[i][1]; break; } if (!Operation) { evhttp_clear_headers(¶ms); evhttp_send_reply(req, HTTP_NOTFOUND, "Not Found", OutBuf); return; } const char *response = Operation(Bloom, Hashes(element)); evhttp_add_header(Headers, MIME_TYPE); evbuffer_add_printf(OutBuf, response); evhttp_send_reply(req, HTTP_OK, "OK", OutBuf); evhttp_clear_headers(¶ms); }; if (!(base = event_base_new())) crash("Couldn't create an event_base: exiting\n", -1); if (!(http = evhttp_new(base))) crash("Couldn't create evhttp. Exiting.\n", -1); evhttp_set_gencb(http, OnReq, NULL); if (!(handle = evhttp_bind_socket_with_handle(http, BIND_ADDRESS, BIND_PORT))) crash("couldn't bind to port 8888. Exiting.\n", -1); if (signal(SIGINT, term_handler) == SIG_ERR) crash("Unable to set SIGINT handler!", -1); if (signal(SIGTERM, term_handler) == SIG_ERR) crash("Unable to set SIGTERM handler!", -1); if (signal(SIGCHLD, child_collector) == SIG_ERR) crash("Unable to set SIGCHLD handler!", -1); //This signal handled by event loop in order to avoid malloc deadlock if ((dump_event = evsignal_new(base, SIGUSR1, dump_handler, NULL)) == NULL) crash("Unable to create SIGUSR1 handler!", -1); else if (event_add(dump_event, NULL) == -1) crash("Unable to add SIGUSR1 handler!", -1); if (event_base_dispatch(base) == -1) crash("Failed to run message loop.\n", -1); fputs("Exiting...\n", stderr); SaveSnap(Bloom, snap_path); evhttp_del_accept_socket(http, handle); evhttp_free(http); event_free(dump_event); event_base_free(base); free(Bloom); return 0; }
void time_cb(int fd, short event, void* argc) { printf("timer wakeup\n"); event_add(&ev, &tv); }
/** * @name c_app_write_event_sched * @brief Schedule a write event */ static void c_app_write_event_sched(void *conn_arg) { c_conn_t *conn = conn_arg; event_add((struct event *)(conn->wr_event), NULL); }
int main(int argc, char **argv) { struct event* ev; struct event* timeout; struct event_base* base; evutil_socket_t pair[2]; struct timeval tv; struct cpu_usage_timer timer; double usage, secPassed, secUsed; #ifdef WIN32 WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 2); (void) WSAStartup(wVersionRequested, &wsaData); #endif if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) return (1); /* Initalize the event library */ base = event_base_new(); /* Initalize a timeout to terminate the test */ timeout = evtimer_new(base,timeout_cb,&timeout); /* and watch for writability on one end of the pipe */ ev = event_new(base,pair[1],EV_WRITE | EV_PERSIST, write_cb, &ev); tv.tv_sec = 5; tv.tv_usec = 0; evtimer_add(timeout, &tv); event_add(ev, NULL); start_cpu_usage_timer(&timer); event_base_dispatch(base); event_free(ev); event_free(timeout); event_base_free(base); get_cpu_usage(&timer, &secPassed, &secUsed, &usage); /* attempt to calculate our cpu usage over the test should be virtually nil */ printf("usec used=%d, usec passed=%d, cpu usage=%.2f%%\n", (int)(secUsed*1e6), (int)(secPassed*1e6), usage*100); if (usage > 50.0) /* way too high */ return 1; return 0; }
inline static void setup_relays(void) { if(!*options.relay_ports) { debug("relays: missing ports"); teardown_control(); return; } const char *w = options.relay_ports; for(context.relays_count = 1; *w; ++ w) context.relays_count += *w == ','; debug("relays: setting up tcp channels port"); evconnlistener_set_cb( context.listener.tcp, accept_tcp_channel, NULL); debug("relays: setting up %d relay ports", context.relays_count); context.relays = (struct RelayListener *) malloc( context.relays_count * sizeof(struct RelayListener)); w = options.relay_ports; struct RelayListener *cur = context.relays; uint8_t udp = 0; for(int c = 0; c < context.relays_count; ++ c) { char proto[4]; int32_t bytes; if(sscanf(w, "%[^:]:%hu,%n", proto, &cur->port, &bytes) != 2) { debug("relays: invalid relay ports format"); context.relays_count = c; teardown_control(); return; } if(!strcmp(proto, "tcp")) { debug("relays: setting up tcp relay %d", cur->port); cur->proto = IPPROTO_TCP; struct sockaddr_in relay; memset(&relay, 0, sizeof(relay)); relay.sin_family = AF_INET; if(options.address) { debug("relays: binding to address %s", options.address); inet_pton(AF_INET, options.address, &relay.sin_addr); } else relay.sin_addr.s_addr = INADDR_ANY; relay.sin_port = htons(cur->port); cur->tcp_listener = evconnlistener_new_bind( context.events, accept_tcp_peer, cur, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (struct sockaddr *) &relay, sizeof(relay)); if(!cur->tcp_listener) { perror("evconnlistener_new_bind"); context.relays_count = c; teardown_control(); return; } if(options.interface) { evutil_socket_t fd = evconnlistener_get_fd(cur->tcp_listener); debug( "relays: binding fd:%d to interface %s", fd, options.interface); assert(fd != -1); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, options.interface, sizeof(ifr.ifr_name)); if(setsockopt( fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) { perror("setsockopt"); context.relays_count = c; teardown_control(); return; } } evconnlistener_set_error_cb(cur->tcp_listener, error_on_tcp_peer_listener); ++ cur; w += bytes; } else if(!strcmp(proto, "udp")) { udp = 1; debug("relays: setting up udp relay %d", cur->port); cur->proto = IPPROTO_UDP; struct sockaddr_in relay; memset(&relay, 0, sizeof(relay)); relay.sin_family = AF_INET; if(options.address) { debug("relays: binding to address %s", options.address); inet_pton(AF_INET, options.address, &relay.sin_addr); } else relay.sin_addr.s_addr = INADDR_ANY; relay.sin_port = htons(cur->port); evutil_socket_t ufd = socket(AF_INET, SOCK_DGRAM, 0); assert(ufd != -1); //evutil_make_socket_nonblocking(ufd); maybe? if(options.interface) { debug( "relays: binding fd:%d to interface %s", ufd, options.interface); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, options.interface, sizeof(ifr.ifr_name)); if(setsockopt( ufd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) { perror("setsockopt"); context.relays_count = c; teardown_control(); return; } } if(bind(ufd, (struct sockaddr *) &relay, sizeof(relay)) == -1) { perror("bind"); context.relays_count = c; teardown_control(); return; } cur->udp_listener = event_new( context.events, ufd, EV_READ | EV_PERSIST, read_udp_peer, cur); event_add(cur->udp_listener, NULL); ++ cur; w += bytes; } else { debug("relays: unsupported protocol %s", proto); context.relays_count = c; teardown_control(); return; } } if(udp) { debug("relays: setting up udp channels port"); struct sockaddr_in relay; memset(&relay, 0, sizeof(relay)); relay.sin_family = AF_INET; if(options.address) { debug("relays: binding to address %s", options.address); inet_pton(AF_INET, options.address, &relay.sin_addr); } else relay.sin_addr.s_addr = INADDR_ANY; relay.sin_port = htons(options.control_port); evutil_socket_t ufd = socket(AF_INET, SOCK_DGRAM, 0); //evutil_make_socket_nonblocking(ufd); maybe? if(options.interface) { debug( "relays: binding fd:%d to interface %s", ufd, options.interface); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, options.interface, sizeof(ifr.ifr_name)); if(setsockopt( ufd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) { perror("setsockopt"); teardown_control(); return; } } if(bind(ufd, (struct sockaddr *) &relay, sizeof(relay)) == -1) { perror("bind"); teardown_control(); return; } context.listener.udp = event_new( context.events, ufd, EV_READ | EV_PERSIST, read_udp_channel, NULL); event_add(context.listener.udp, NULL); } }
int main(int argc, char **argv) { char *sip = NULL; char *cip = NULL; int i, opt; int ipver = 0; int port = 0; int buf_len = 0; int delay = DEF_DELAY; time_t tm_out = 0; int icount = DEF_INSTANCES; int len; int transport = 0; int background = 0; struct sockaddr_in sin; struct sockaddr_in6 sin6; struct event_base *e_base = NULL; struct event e_ki; event_timeout e_timeout; connection c; Client cl; connection *cons_p; /*traffic_gw tg;*/ while((opt = getopt(argc, argv, "4:6:p:t:S:d:T:i:hb")) != -1) { switch(opt) { case '4': ipver = AF_INET; if(get_ip_subopt(&sip, &cip, optarg) != 0) { print_usage(argv[0]); return (1); } break; case '6': ipver = AF_INET6; if(get_ip_subopt(&sip, &cip, optarg) != 0) { print_usage(argv[0]); return (1); } break; case 'p': port = (int) strtol(optarg, (char **)NULL, 10); break; case 'S': buf_len = (int) strtol(optarg, (char **)NULL, 10); break; case 'd': delay = (int) strtol(optarg, (char **)NULL, 10); break; case 't': len = strlen(argv[optind - 1]); if(!strncmp(argv[optind - 1], "tcp", len)) transport = SOCK_STREAM; else if(!strncmp(argv[optind - 1], "udp", len)) transport = SOCK_DGRAM; break; case 'T': tm_out = (time_t) strtol(optarg, (char **)NULL, 10); break; case 'i': icount = (int) strtol(optarg, (char **)NULL, 10); break; case 'b': background = 1; break; case 'h': print_usage(argv[0]); return (0); break; default: print_usage(argv[0]); return (1); break; } } if(cip == NULL || sip == NULL || port == 0 || buf_len == 0 || transport == 0) { DPRINT(DPRINT_ERROR,"parameters are not valid\n"); print_usage(argv[0]); return (1); } memset(&c, 0, sizeof(connection)); c.buffer = NULL; c.buf_len = buf_len; c.delay = delay; c.ipver = ipver; c.transport = transport; if(c.ipver == AF_INET) { memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; if(inet_pton(AF_INET, sip, (void *)&sin.sin_addr) < 0) { DPRINT(DPRINT_ERROR, "[%s] failed to convert [%s] address\n", __FUNCTION__, sip); return (1); } sin.sin_port = htons(port); memcpy(&c.servAddr, &sin, sizeof(struct sockaddr_storage)); if(inet_pton(AF_INET, cip, (void *)&sin.sin_addr) < 0) { DPRINT(DPRINT_ERROR, "[%s] failed to convert [%s] address\n", __FUNCTION__, cip); return (1); } sin.sin_port = htons(0); memcpy(&c.bindAddr, &sin, sizeof(struct sockaddr_storage)); c.bindAddrSize = sizeof(struct sockaddr_in); } else if (c.ipver == AF_INET6) { memset(&sin6, 0, sizeof(struct sockaddr_in6)); sin6.sin6_family = AF_INET6; if(inet_pton(AF_INET6, sip, (void *)&sin6.sin6_addr) < 0) { DPRINT(DPRINT_ERROR, "[%s] failed to convert [%s] address\n", __FUNCTION__, sip); return (1); } sin6.sin6_port = htons(port); memcpy(&c.servAddr, &sin6, sizeof(struct sockaddr_storage)); if(inet_pton(AF_INET6, cip, (void *)&sin6.sin6_addr) < 0) { DPRINT(DPRINT_ERROR, "[%s] failed to convert [%s] address\n", __FUNCTION__, cip); return (1); } sin6.sin6_port = htons(0); memcpy(&c.bindAddr, &sin6, sizeof(struct sockaddr_storage)); c.bindAddrSize = sizeof(struct sockaddr_in6); } if (background) daemon(0,0); e_base = event_base_new(); if(e_base == NULL) { DPRINT(DPRINT_ERROR, "[%s] unable to initialize event base\n", __FUNCTION__); return (1); } if(!background) { /* initialize keyboard interupt event handler */ event_set(&e_ki, STDIN_FILENO, (EV_READ | EV_PERSIST), cb_keyboard_int, e_base); event_base_set(e_base, &e_ki); event_add(&e_ki, NULL); } /* initialize timeout event handler */ e_timeout.tv.tv_usec = 0; e_timeout.tv.tv_sec = tm_out; event_set(&e_timeout.e, -1, 0, cb_timeout, e_base); event_base_set(e_base, &e_timeout.e); event_add(&e_timeout.e, &e_timeout.tv); bzero(&cl, sizeof(Client)); cl.cons = (connection *) calloc(icount, sizeof(connection)); cons_p = cl.cons; for(i = 0; i < icount; ++i) { memcpy(&cons_p[i], &c, sizeof(connection)); if(prep_connection(&cons_p[i]) < 0) { DPRINT(DPRINT_ERROR, "[%s] [%d] connection failed \n", __FUNCTION__, i); } else { ++cl.estcount; cons_p[i].established = 1; cons_p[i].buffer = (char *) malloc(cons_p[i].buf_len); event_set(&cons_p[i].r_event, cons_p[i].s, (EV_READ | EV_PERSIST), cb_rw, &cons_p[i]); event_base_set(e_base, &cons_p[i].r_event); event_add(&cons_p[i].r_event, NULL); event_set(&cons_p[i].w_event, cons_p[i].s, (EV_WRITE | EV_PERSIST), cb_rw, &cons_p[i]); event_base_set(e_base, &cons_p[i].w_event); event_add(&cons_p[i].w_event, NULL); } } DPRINT(DPRINT_DEBUG, "[%s] %d connections established\n", __FUNCTION__, cl.estcount); event_base_dispatch(e_base); DPRINT(DPRINT_DEBUG, "[%s] cleaning up...\n", __FUNCTION__); /* clean up */ event_del(&e_timeout.e); event_del(&e_ki); for(i = 0; i < icount; ++i) { if(cons_p[i].established) { event_del(&cons_p[i].r_event); event_del(&cons_p[i].w_event); close(cons_p[i].s); free(cons_p[i].buffer); } } event_base_free(e_base); free(cons_p); return (0); }
// only in child static void child(struct sockaddr_storage* addr, int addrLen, char* user, struct ChildContext* context) { context->dataFromParent = event_new(context->eventBase, context->inFd, EV_READ | EV_PERSIST, incomingFromParent, context); event_add(context->dataFromParent, NULL); if (!addr->ss_family) { addr->ss_family = AF_INET; // Apple gets mad if the length is wrong. addrLen = sizeof(struct sockaddr_in); } evutil_socket_t listener = socket(addr->ss_family, SOCK_STREAM, 0); if (listener < 0) { perror("socket()"); } evutil_make_listen_socket_reuseable(listener); if (bind(listener, (struct sockaddr*) addr, addrLen) < 0) { perror("bind()"); return; } if (getsockname(listener, (struct sockaddr*) addr, (socklen_t*) &addrLen)) { perror("getsockname()"); } if (listen(listener, 16)<0) { perror("listen"); return; } evutil_make_socket_nonblocking(listener); context->socketEvent = event_new(context->eventBase, listener, EV_READ | EV_PERSIST, acceptConn, context); event_add(context->socketEvent, NULL); if (!context->eventBase) { exit(-1); } // Write back the sockaddr_storage struct so the other end knows our port. uint8_t buff[sizeof(struct sockaddr_storage) + sizeof(int) + 8]; Bits_memcpyConst(buff, "abcd", 4); Bits_memcpyConst(&buff[4], &addrLen, sizeof(int)); Bits_memcpyConst(&buff[4 + sizeof(int)], addr, sizeof(struct sockaddr_storage)); Bits_memcpyConst(&buff[4 + sizeof(int) + sizeof(struct sockaddr_storage)], "wxyz", 4); write(context->outFd, buff, sizeof(buff)); event_base_dispatch(context->eventBase); }
static void lua_tcp_write_helper (struct lua_tcp_cbdata *cbd) { struct iovec *start; guint niov, i; gint flags = 0; gsize remain; gssize r; struct iovec *cur_iov; struct msghdr msg; if (cbd->pos == cbd->total) { goto call_finish_handler; } start = &cbd->iov[0]; niov = cbd->iovlen; remain = cbd->pos; /* We know that niov is small enough for that */ cur_iov = alloca (niov * sizeof (struct iovec)); memcpy (cur_iov, cbd->iov, niov * sizeof (struct iovec)); for (i = 0; i < cbd->iovlen && remain > 0; i++) { /* Find out the first iov required */ start = &cur_iov[i]; if (start->iov_len <= remain) { remain -= start->iov_len; start = &cur_iov[i + 1]; niov--; } else { start->iov_base = (void *)((char *)start->iov_base + remain); start->iov_len -= remain; remain = 0; } } memset (&msg, 0, sizeof (msg)); msg.msg_iov = start; msg.msg_iovlen = MIN (IOV_MAX, niov); g_assert (niov > 0); #ifdef MSG_NOSIGNAL flags = MSG_NOSIGNAL; #endif r = sendmsg (cbd->fd, &msg, flags); if (r == -1) { lua_tcp_push_error (cbd, "IO write error while trying to write %d " "bytes: %s", (gint)remain, strerror (errno)); lua_tcp_maybe_free (cbd); return; } else { cbd->pos += r; } if (cbd->pos >= cbd->total) { goto call_finish_handler; } else { /* Want to write more */ event_add (&cbd->ev, &cbd->tv); } return; call_finish_handler: if (!cbd->partial) { cbd->in = g_string_sized_new (BUFSIZ); rspamd_mempool_add_destructor (cbd->pool, rspamd_gstring_free_hard, cbd->in); } if (cbd->do_shutdown) { /* Half close the connection */ shutdown (cbd->fd, SHUT_WR); } event_del (&cbd->ev); #ifdef EV_CLOSED event_set (&cbd->ev, cbd->fd, EV_READ|EV_PERSIST|EV_CLOSED, lua_tcp_handler, cbd); #else event_set (&cbd->ev, cbd->fd, EV_READ|EV_PERSIST, lua_tcp_handler, cbd); #endif event_base_set (cbd->ev_base, &cbd->ev); event_add (&cbd->ev, &cbd->tv); }
void Admin_sendMessage(Dict* message, String* txid, struct Admin* admin) { if (!admin) { return; } Assert_true(txid); uint8_t buff[MAX_API_REQUEST_SIZE + TXID_LEN]; // Write the inter-process txid. Bits_memcpyConst(buff, txid->bytes, TXID_LEN); uint8_t allocBuff[256]; struct Allocator* allocator = BufferAllocator_new(allocBuff, 256); // Bounce back the user-supplied txid. String userTxid = { .bytes = txid->bytes + TXID_LEN, .len = txid->len - TXID_LEN }; if (txid->len > TXID_LEN) { Dict_putString(message, TXID, &userTxid, allocator); } struct Writer* w = ArrayWriter_new(buff + TXID_LEN, MAX_API_REQUEST_SIZE, allocator); StandardBencSerializer_get()->serializeDictionary(w, message); write(admin->outFd, buff, w->bytesWritten(w) + TXID_LEN); } struct Admin* Admin_new(struct sockaddr_storage* addr, int addrLen, String* password, char* user, struct event_base* eventBase, struct ExceptionHandler* eh, struct Log* logger, struct Allocator* allocator) { errno = 0; int pipes[2][2]; if (pipe(pipes[0]) || pipe(pipes[1])) { eh->exception(__FILE__ " Failed to create pipes.", errno, eh); } int pgid = getpid(); int pid = fork(); if (pid < 0) { eh->exception(__FILE__ " Failed to fork()", errno, eh); } bool isChild = (pid == 0); int inFd = pipes[isChild][0]; close(pipes[!isChild][0]); int outFd = pipes[!isChild][1]; close(pipes[isChild][1]); if (isChild) { // Set the process group so that children will not // become orphaned if the parent gets signal 11 err um 9. setpgid(0, pgid); if (user) { Security_setUser(user, NULL, AbortHandler_INSTANCE); } struct ChildContext context; memset(&context, 0, sizeof(struct ChildContext)); context.inFd = inFd; context.outFd = outFd; context.allocator = allocator; event_reinit(eventBase); context.eventBase = eventBase; child(addr, addrLen, user, &context); fprintf(stderr, "Admin process exiting."); exit(0); } setpgid(pid, pgid); struct Admin* admin = allocator->calloc(sizeof(struct Admin), 1, allocator); admin->inFd = inFd; admin->outFd = outFd; admin->allocator = allocator; admin->logger = logger; admin->functionCount = 0; admin->eventBase = eventBase; admin->password = password; Bits_memcpyConst(&admin->address, addr, sizeof(struct sockaddr_storage)); admin->addressLength = addrLen; admin->pipeEv = event_new(eventBase, inFd, EV_READ | EV_PERSIST, inFromChild, admin); event_add(admin->pipeEv, NULL); event_base_dispatch(eventBase); return admin; }
int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg) { event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg); return event_add(ev, 0); }
static void didaktik_set_intrq( struct wd_fdc *f ) { if( aux_register & INTRQ_ENABLED ) event_add( 0, z80_nmi_event ); }
int init_socket(async_http_worker_t *worker) { worker->socket_event = event_new(worker->evbase, worker->notication_socket[0], EV_READ|EV_PERSIST, notification_socket_cb, worker); event_add(worker->socket_event, NULL); return (0); }
/*** * @function rspamd_redis.make_request({params}) * Make request to redis server, params is a table of key=value arguments in any order * @param {task} task worker task object * @param {ip} host server address * @param {function} callback callback to be called in form `function (task, err, data)` * @param {string} cmd command to be sent to redis * @param {table} args numeric array of strings used as redis arguments * @param {number} timeout timeout in seconds for request (1.0 by default) * @return {boolean} `true` if a request has been scheduled */ static int lua_redis_make_request (lua_State *L) { struct lua_redis_userdata *ud; struct rspamd_lua_ip *addr = NULL; struct rspamd_task *task = NULL; const gchar *cmd = NULL; gint top, cbref = -1; struct timeval tv; gboolean ret = FALSE; gdouble timeout = REDIS_DEFAULT_TIMEOUT; if (lua_istable (L, 1)) { /* Table version */ lua_pushstring (L, "task"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TUSERDATA) { task = lua_check_task (L, -1); } lua_pop (L, 1); lua_pushstring (L, "callback"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TFUNCTION) { /* This also pops function from the stack */ cbref = luaL_ref (L, LUA_REGISTRYINDEX); } else { msg_err ("bad callback argument for lua redis"); lua_pop (L, 1); } lua_pushstring (L, "cmd"); lua_gettable (L, -2); cmd = lua_tostring (L, -1); lua_pop (L, 1); lua_pushstring (L, "host"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TUSERDATA) { addr = lua_check_ip (L, -1); } lua_pop (L, 1); lua_pushstring (L, "timeout"); lua_gettable (L, -2); timeout = lua_tonumber (L, -1); lua_pop (L, 1); if (task != NULL && addr != NULL && cbref != -1 && cmd != NULL) { ud = rspamd_mempool_alloc (task->task_pool, sizeof (struct lua_redis_userdata)); ud->task = task; ud->L = L; ud->cbref = cbref; lua_pushstring (L, "args"); lua_redis_parse_args (L, -1, cmd, ud); ret = TRUE; } else { if (cbref != -1) { luaL_unref (L, LUA_REGISTRYINDEX, cbref); } msg_err ("incorrect function invocation"); } } else if ((task = lua_check_task (L, 1)) != NULL) { addr = lua_check_ip (L, 2); top = lua_gettop (L); /* Now get callback */ if (lua_isfunction (L, 3) && addr != NULL && addr->addr && top >= 4) { /* Create userdata */ ud = rspamd_mempool_alloc (task->task_pool, sizeof (struct lua_redis_userdata)); ud->task = task; ud->L = L; /* Pop other arguments */ lua_pushvalue (L, 3); /* Get a reference */ ud->cbref = luaL_ref (L, LUA_REGISTRYINDEX); cmd = luaL_checkstring (L, 4); if (top > 4) { lua_redis_parse_args (L, 5, cmd, ud); } else { lua_redis_parse_args (L, 0, cmd, ud); } ret = TRUE; } else { msg_err ("incorrect function invocation"); } } if (ret) { ud->terminated = 0; ud->ctx = redisAsyncConnect (rspamd_inet_address_to_string (addr->addr), rspamd_inet_address_get_port (addr->addr)); redisAsyncSetConnectCallback (ud->ctx, lua_redis_connect_cb); if (ud->ctx == NULL || ud->ctx->err) { ud->terminated = 1; redisAsyncFree (ud->ctx); lua_redis_free_args (ud); luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref); lua_pushboolean (L, FALSE); return 1; } redisLibeventAttach (ud->ctx, ud->task->ev_base); ret = redisAsyncCommandArgv (ud->ctx, lua_redis_callback, ud, ud->nargs, (const gchar **)ud->args, NULL); if (ret == REDIS_OK) { rspamd_session_add_event (ud->task->s, lua_redis_fin, ud, g_quark_from_static_string ("lua redis")); double_to_tv (timeout, &tv); event_set (&ud->timeout, -1, EV_TIMEOUT, lua_redis_timeout, ud); event_base_set (ud->task->ev_base, &ud->timeout); event_add (&ud->timeout, &tv); } else { msg_info ("call to redis failed: %s", ud->ctx->errstr); ud->terminated = 1; lua_redis_free_args (ud); redisAsyncFree (ud->ctx); luaL_unref (ud->L, LUA_REGISTRYINDEX, ud->cbref); } } lua_pushboolean (L, ret); return 1; }