static inline int multi_tcp_wait(const struct context *c, struct multi_tcp *mtcp) { int status; socket_set_listen_persistent(c->c2.link_socket, mtcp->es, MTCP_SOCKET); tun_set(c->c1.tuntap, mtcp->es, EVENT_READ, MTCP_TUN, &mtcp->tun_rwflags); #ifdef ENABLE_MANAGEMENT if (management) { management_socket_set(management, mtcp->es, MTCP_MANAGEMENT, &mtcp->management_persist_flags); } #endif #ifdef ENABLE_ASYNC_PUSH /* arm inotify watcher */ event_ctl(mtcp->es, c->c2.inotify_fd, EVENT_READ, MTCP_FILE_CLOSE_WRITE); #endif status = event_wait(mtcp->es, &c->c2.timeval, mtcp->esr, mtcp->maxevents); update_time(); mtcp->n_esr = 0; if (status > 0) { mtcp->n_esr = status; } return status; }
static inline void proxy_connection_io_requeue (struct proxy_connection *pc, const int rwflags_new, struct event_set *es) { if (socket_defined (pc->sd) && pc->rwflags != rwflags_new) { /*dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: requeue[%d] rwflags=%d", (int)pc->sd, rwflags_new);*/ event_ctl (es, pc->sd, rwflags_new, (void*)pc); pc->rwflags = rwflags_new; } }
/* * This is the main function for the port share proxy background process. */ static void port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descriptor_t sd_control, const int max_initial_buf, const char *journal_dir) { if (send_control (sd_control, RESPONSE_INIT_SUCCEEDED) >= 0) { void *sd_control_marker = (void *)1; int maxevents = 256; struct event_set *es; struct event_set_return esr[64]; struct proxy_connection *list = NULL; time_t last_housekeeping = 0; msg (D_PS_PROXY, "PORT SHARE PROXY: proxy starting"); es = event_set_init (&maxevents, 0); event_ctl (es, sd_control, EVENT_READ, sd_control_marker); while (true) { int n_events; struct timeval tv; time_t current; tv.tv_sec = 10; tv.tv_usec = 0; n_events = event_wait (es, &tv, esr, SIZE(esr)); /*dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: event_wait returned %d", n_events);*/ current = time(NULL); if (n_events > 0) { int i; for (i = 0; i < n_events; ++i) { const struct event_set_return *e = &esr[i]; if (e->arg == sd_control_marker) { if (!control_message_from_parent (sd_control, &list, es, hostaddr, port, max_initial_buf, journal_dir)) goto done; } else { struct proxy_connection *pc = (struct proxy_connection *)e->arg; if (pc->defined) proxy_connection_io_dispatch (pc, e->rwflags, es); } } } else if (n_events < 0) { dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: event_wait failed"); } if (current > last_housekeeping) { proxy_list_housekeeping (&list); last_housekeeping = current; } } done: proxy_list_close (&list); event_free (es); } msg (M_INFO, "PORT SHARE PROXY: proxy exiting"); }
void io_wait_dowork (struct context *c, const unsigned int flags) { unsigned int socket = 0; unsigned int tuntap = 0; struct event_set_return esr[4]; /* These shifts all depend on EVENT_READ and EVENT_WRITE */ static int socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */ static int tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */ static int err_shift = 4; /* depends on ES_ERROR */ #ifdef ENABLE_MANAGEMENT static int management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */ #endif #ifdef ENABLE_ASYNC_PUSH static int file_shift = 8; /* listening inotify events */ #endif /* * Decide what kind of events we want to wait for. */ event_reset (c->c2.event_set); /* * On win32 we use the keyboard or an event object as a source * of asynchronous signals. */ if (flags & IOW_WAIT_SIGNAL) wait_signal (c->c2.event_set, (void*)&err_shift); /* * If outgoing data (for TCP/UDP port) pending, wait for ready-to-send * status from TCP/UDP port. Otherwise, wait for incoming data on * TUN/TAP device. */ if (flags & IOW_TO_LINK) { if (flags & IOW_SHAPER) { /* * If sending this packet would put us over our traffic shaping * quota, don't send -- instead compute the delay we must wait * until it will be OK to send the packet. */ #ifdef ENABLE_FEATURE_SHAPER int delay = 0; /* set traffic shaping delay in microseconds */ if (c->options.shaper) delay = max_int (delay, shaper_delay (&c->c2.shaper)); if (delay < 1000) { socket |= EVENT_WRITE; } else { shaper_soonest_event (&c->c2.timeval, delay); } #else /* ENABLE_FEATURE_SHAPER */ socket |= EVENT_WRITE; #endif /* ENABLE_FEATURE_SHAPER */ } else { socket |= EVENT_WRITE; } } else if (!((flags & IOW_FRAG) && TO_LINK_FRAG (c))) { if (flags & IOW_READ_TUN) tuntap |= EVENT_READ; } /* * If outgoing data (for TUN/TAP device) pending, wait for ready-to-send status * from device. Otherwise, wait for incoming data on TCP/UDP port. */ if (flags & IOW_TO_TUN) { tuntap |= EVENT_WRITE; } else { if (flags & IOW_READ_LINK) socket |= EVENT_READ; } /* * outgoing bcast buffer waiting to be sent? */ if (flags & IOW_MBUF) socket |= EVENT_WRITE; /* * Force wait on TUN input, even if also waiting on TCP/UDP output */ if (flags & IOW_READ_TUN_FORCE) tuntap |= EVENT_READ; /* * Configure event wait based on socket, tuntap flags. */ socket_set (c->c2.link_socket, c->c2.event_set, socket, (void*)&socket_shift, NULL); tun_set (c->c1.tuntap, c->c2.event_set, tuntap, (void*)&tun_shift, NULL); #ifdef ENABLE_MANAGEMENT if (management) management_socket_set (management, c->c2.event_set, (void*)&management_shift, NULL); #endif #ifdef ENABLE_ASYNC_PUSH /* arm inotify watcher */ event_ctl (c->c2.event_set, c->c2.inotify_fd, EVENT_READ, (void*)&file_shift); #endif /* * Possible scenarios: * (1) tcp/udp port has data available to read * (2) tcp/udp port is ready to accept more data to write * (3) tun dev has data available to read * (4) tun dev is ready to accept more data to write * (5) we received a signal (handler sets signal_received) * (6) timeout (tv) expired */ c->c2.event_set_status = ES_ERROR; if (!c->sig->signal_received) { if (!(flags & IOW_CHECK_RESIDUAL) || !socket_read_residual (c->c2.link_socket)) { int status; #ifdef ENABLE_DEBUG if (check_debug_level (D_EVENT_WAIT)) show_wait_status (c); #endif /* * Wait for something to happen. */ status = event_wait (c->c2.event_set, &c->c2.timeval, esr, SIZE(esr)); check_status (status, "event_wait", NULL, NULL); if (status > 0) { int i; c->c2.event_set_status = 0; for (i = 0; i < status; ++i) { const struct event_set_return *e = &esr[i]; c->c2.event_set_status |= ((e->rwflags & 3) << *((int*)e->arg)); } } else if (status == 0) { c->c2.event_set_status = ES_TIMEOUT; } } else { c->c2.event_set_status = SOCKET_READ; } } /* 'now' should always be a reasonably up-to-date timestamp */ update_time (); /* set signal_received if a signal was received */ if (c->c2.event_set_status & ES_ERROR) get_signal (&c->sig->signal_received); dmsg (D_EVENT_WAIT, "I/O WAIT status=0x%04x", c->c2.event_set_status); }
Ret event_del(Event* event) { return event_ctl(event, COMMAND_DEL); }
Ret event_add(Event* event) { return event_ctl(event, COMMAND_ADD); }