/** * Reads the thread specific userdata to figure out what * we need to handle. Things that purely effect the network * stack should be handled here, but otherwise we should defer * to the connection handlers. */ static void invoke_event_handler(worker_ev_userdata* data) { // Get the offending handle ev_io *watcher = data->watcher; int fd = watcher->fd; // Check if this is either of the listeners if (watcher == &data->netconf->tcp_client) { // Accept the new client handle_new_client(fd, data); // Reschedule the listener schedule_async(data->netconf, SCHEDULE_WATCHER, watcher); return; // If it is write ready, dispatch the write handler } else if (data->ready_events & EV_WRITE) { handle_client_writebuf(watcher, data); return; } // Check for UDP inbound if (watcher == &data->netconf->udp_client) { // Read the message and process if (!handle_udp_message(watcher, data)) { statsite_proxy_conn_handler handle = {data->netconf->config, data->netconf->proxy, watcher->data}; handle_client_connect(&handle); } // Reschedule the listener schedule_async(data->netconf, SCHEDULE_WATCHER, watcher); return; } /* * If it is not a listener, it must be a connected * client. We should just read all the available data, * append it to the buffers, and then invoke the * connection handlers. */ conn_info *conn = watcher->data; incref_client_connection(conn); if (!handle_client_data(watcher, data)) { statsite_proxy_conn_handler handle = {data->netconf->config, data->netconf->proxy, watcher->data}; handle_client_connect(&handle); } // Reschedule the watcher, unless told otherwise. if (conn->should_schedule) { schedule_async(data->netconf, SCHEDULE_WATCHER, watcher); } decref_client_connection(conn); }
/** * Invoked when a UDP connection has a message ready to be read. * We need to take care to add the data to our buffers, and then * invoke the connection handlers who have the business logic * of what to do. */ static void handle_udp_message(ev_io *watch, int ready_events) { while (1) { // Get the associated connection struct conn_info *conn = watch->data; // Clear the input buffer circbuf_clear(&conn->input); // Build the IO vectors to perform the read struct iovec vectors[2]; int num_vectors; circbuf_setup_readv_iovec(&conn->input, (struct iovec*)&vectors, &num_vectors); /* * Issue the read, always use the first vector. * since we just cleared the buffer, and it should * be a contiguous buffer. */ assert(num_vectors == 1); ssize_t read_bytes = recv(watch->fd, vectors[0].iov_base, vectors[0].iov_len, 0); // Make sure we actually read something if (read_bytes == 0) { syslog(LOG_DEBUG, "Got empty UDP packet. [%d]\n", watch->fd); return; } else if (read_bytes == -1) { if (errno != EAGAIN && errno != EINTR) { syslog(LOG_ERR, "Failed to recv() from connection [%d]! %s.", watch->fd, strerror(errno)); } return; } // Update the write cursor circbuf_advance_write(&conn->input, read_bytes); // UDP clients don't need to append newlines to the messages like // TCP clients do, but our parser requires them. Append one if // it's not present. if (conn->input.buffer[conn->input.write_cursor - 1] != '\n') circbuf_write(&conn->input, "\n", 1); // Get the user data worker_ev_userdata *data = ev_userdata(); // Invoke the connection handler statsite_conn_handler handle = {data->netconf->config, watch->data}; handle_client_connect(&handle); } }
/** * Reads the thread specific userdata to figure out what * we need to handle. Things that purely effect the network * stack should be handled here, but otherwise we should defer * to the connection handlers. */ static void invoke_event_handler(ev_io *watcher, int ready_events) { // Get the user data worker_ev_userdata *data = ev_userdata(); // Read in the data, and close on issues conn_info *conn = watcher->data; if (read_client_data(conn)) { close_client_connection(conn); return; } // Invoke the connection handler, and close connection on error statsite_conn_handler handle = {data->netconf->config, watcher->data}; if (handle_client_connect(&handle)) close_client_connection(conn); }
/* * Invoked when client read data is ready. * We just read all the available data, * append it to the buffers, and then invoke the * connection handlers. */ static void invoke_event_handler(ev_loop *lp, ev_io *watcher, int ready_events) { // Get the user data worker_ev_userdata *data = ev_userdata(lp); // Read in the data, and close on issues conn_info *conn = watcher->data; if (read_client_data(conn)) { close_client_connection(conn); return; } // Prepare to invoke the handler bloom_conn_handler handle; handle.config = data->netconf->config; handle.mgr = data->netconf->mgr; handle.conn = conn; // Reschedule the watcher, unless it's non-active now if (handle_client_connect(&handle) || !conn->active) close_client_connection(conn); }