static int csrv_thread_routine(void *data) { struct socket *lsock = NULL; struct socket *con_sock = NULL; struct csrv_con *con = NULL; int error = 0; while (!kthread_should_stop()) { if (!csrv_sock) { error = ksock_listen(&lsock, INADDR_ANY, 9111, 5); if (error) { klog(KL_ERR, "csock_listen err=%d", error); msleep_interruptible(LISTEN_RESTART_TIMEOUT_MS); continue; } else { mutex_lock(&csrv_lock); csrv_sock = lsock; mutex_unlock(&csrv_lock); } } if (csrv_sock && !csrv_stopping) { klog(KL_DEBUG, "accepting"); error = ksock_accept(&con_sock, csrv_sock); if (error) { if (error == -EAGAIN) klog(KL_WARN, "csock_accept err=%d", error); else klog(KL_ERR, "csock_accept err=%d", error); continue; } klog(KL_DEBUG, "accepted con_sock=%p", con_sock); if (!csrv_con_start(con_sock)) { klog(KL_ERR, "csrv_con_start failed"); ksock_release(con_sock); continue; } } } error = 0; klog(KL_INFO, "releasing listen socket"); mutex_lock(&csrv_lock); lsock = csrv_sock; csrv_sock = NULL; mutex_unlock(&csrv_lock); if (lsock) ksock_release(lsock); klog(KL_INFO, "releasing cons"); for (;;) { con = NULL; mutex_lock(&con_list_lock); if (!list_empty(&con_list)) { con = list_first_entry(&con_list, struct csrv_con, con_list); list_del_init(&con->con_list); } mutex_unlock(&con_list_lock); if (!con) break; csrv_con_wait(con); csrv_con_free(con); }
/* This function accepts a connection from a client in the listener loop. */ static void kcd_frontend_loop_accept_conn(int *nb_child, int listen_sock) { int error = 0; int pid; struct sockaddr_in sock_addr; socklen_t sock_len; struct kcd_client *client = kcd_client_new(); kmod_log_msg(KCD_LOG_MISC, "kcd_frontend_accept_conn() called.\n"); do { /* Try to accept a connection. */ error = ksock_accept(listen_sock, &client->sock); if (error == -2) { error = 0; break; } if (error) break; /* Get the client address. */ sock_len = sizeof(sock_addr); error = getpeername(client->sock, (struct sockaddr *) &sock_addr, &sock_len); if (error) { kmod_set_error("cannot get peer name: %s", strerror(errno)); break; } kstr_assign_cstr(&client->addr, inet_ntoa(sock_addr.sin_addr)); client->port = ntohs(sock_addr.sin_port); /* Set the socket to non-blocking mode. */ error = ksock_set_unblocking(client->sock); if (error) break; /* Enable keepalives. */ error = ksock_enable_keepalive(client->sock, KCD_TCP_KEEPALIVE_TIME, KCD_TCP_KEEPALIVE_INTVl, KCD_TCP_KEEPALIVE_PROBES); if (error) break; /* We got the connection. Dispatch it. */ kmod_log_msg(KCD_LOG_BRIEF, "Accepted connection from %s on port %u.\n", client->addr.data, client->port); /* Fork to handle the connection. */ error = kcd_fork("Service ID", &pid, 1); if (error) break; /* Child. */ else if (!pid) { kcd_frontend_handle_conn(client); exit(0); } /* Parent. */ else { (*nb_child)++; } } while (0); if (error) { kmod_log_msg(KCD_LOG_BRIEF, "Error accepting connection: %s.\n", kmod_strerror()); } kcd_client_destroy(client); }