+static void client_cb(EV_P_ struct ev_io *w, int events)
+{
+ server_t *server = (server_t*)w;
+
+ debug("Entering client_cb for %p, %d (%d | %d)", w, events, EV_WRITE, EV_READ);
+
+ if (events & EV_WRITE && server->obuf.len) {
+ if (buffer_write(&server->obuf, server->fd) < 0) {
+ server_release(server);
+ return;
+ }
+ if (!server->obuf.len) {
+ ev_io_set(&server->io, server->fd, EV_READ);
+ }
+ }
+
+ if (events & EV_READ) {
+ if (server->run(server, config_ptr) < 0) {
+ server_release(server);
+ return;
+ }
+ }
+}
+
+static int start_client(server_t *server, start_client_t starter,
+ run_client_t runner, delete_client_t deleter)
+{
+ server_t *tmp;
+ void* data = NULL;
+ int sock;
+
+ sock = accept_nonblock(server->fd);
+ if (sock < 0) {
+ UNIXERR("accept");
+ return -1;
+ }
+
+ if (starter) {
+ data = starter(server);
+ if (data == NULL) {
+ close(sock);
+ return -1;
+ }
+ }
+
+ tmp = server_acquire();
+ tmp->fd = sock;
+ tmp->data = data;
+ tmp->run = runner;
+ tmp->clear_data = deleter;
+ ev_io_init(&tmp->io, client_cb, tmp->fd, EV_READ);
+ ev_io_start(global_loop, &tmp->io);
+ return 0;
+}
+
+static void server_cb(EV_P_ struct ev_io *w, int events)
+{
+ server_t *server = (server_t*)w;
+ if (start_client(server, client_start, client_run, client_delete) != 0) {
+ ev_unloop(EV_A_ EVUNLOOP_ALL);
+ }
+}
+