/* * Process an I/O event. */ static void multi_process_io_udp (struct multi_context *m) { const unsigned int status = m->top.c2.event_set_status; const unsigned int mpp_flags = m->top.c2.fast_io ? (MPP_CONDITIONAL_PRE_SELECT | MPP_CLOSE_ON_SIGNAL) : (MPP_PRE_SELECT | MPP_CLOSE_ON_SIGNAL); #ifdef MULTI_DEBUG_EVENT_LOOP char buf[16]; buf[0] = 0; if (status & SOCKET_READ) strcat (buf, "SR/"); else if (status & SOCKET_WRITE) strcat (buf, "SW/"); else if (status & TUN_READ) strcat (buf, "TR/"); else if (status & TUN_WRITE) strcat (buf, "TW/"); printf ("IO %s\n", buf); #endif #ifdef ENABLE_MANAGEMENT if (status & (MANAGEMENT_READ|MANAGEMENT_WRITE)) { ASSERT (management); management_io (management); } #endif /* UDP port ready to accept write */ if (status & SOCKET_WRITE) { multi_process_outgoing_link (m, mpp_flags); } /* TUN device ready to accept write */ else if (status & TUN_WRITE) { multi_process_outgoing_tun (m, mpp_flags); } /* Incoming data on UDP port */ else if (status & SOCKET_READ) { read_incoming_link (&m->top); multi_release_io_lock (m); if (!IS_SIG (&m->top)) multi_process_incoming_link (m, NULL, mpp_flags); } /* Incoming data on TUN device */ else if (status & TUN_READ) { read_incoming_tun (&m->top); multi_release_io_lock (m); if (!IS_SIG (&m->top)) multi_process_incoming_tun (m, mpp_flags); } }
static struct multi_instance * multi_tcp_dispatch(struct multi_context *m, struct multi_instance *mi, const int action) { const unsigned int mpp_flags = MPP_PRE_SELECT|MPP_RECORD_TOUCH; struct multi_instance *touched = mi; m->mpp_touched = &touched; dmsg(D_MULTI_DEBUG, "MULTI TCP: multi_tcp_dispatch a=%s mi=" ptr_format, pract(action), (ptr_type)mi); switch (action) { case TA_TUN_READ: read_incoming_tun(&m->top); if (!IS_SIG(&m->top)) { multi_process_incoming_tun(m, mpp_flags); } break; case TA_SOCKET_READ: case TA_SOCKET_READ_RESIDUAL: ASSERT(mi); ASSERT(mi->context.c2.link_socket); set_prefix(mi); read_incoming_link(&mi->context); clear_prefix(); if (!IS_SIG(&mi->context)) { multi_process_incoming_link(m, mi, mpp_flags); if (!IS_SIG(&mi->context)) { stream_buf_read_setup(mi->context.c2.link_socket); } } break; case TA_TIMEOUT: multi_process_timeout(m, mpp_flags); break; case TA_TUN_WRITE: multi_process_outgoing_tun(m, mpp_flags); break; case TA_TUN_WRITE_TIMEOUT: multi_process_drop_outgoing_tun(m, mpp_flags); break; case TA_SOCKET_WRITE_READY: ASSERT(mi); multi_tcp_process_outgoing_link_ready(m, mi, mpp_flags); break; case TA_SOCKET_WRITE: multi_tcp_process_outgoing_link(m, false, mpp_flags); break; case TA_SOCKET_WRITE_DEFERRED: multi_tcp_process_outgoing_link(m, true, mpp_flags); break; case TA_INITIAL: ASSERT(mi); multi_tcp_set_global_rw_flags(m, mi); multi_process_post(m, mi, mpp_flags); break; default: msg(M_FATAL, "MULTI TCP: multi_tcp_dispatch, unhandled action=%d", action); } m->mpp_touched = NULL; return touched; }