#include #include #include "common/debug.h" #include "common/queue.h" #include "common/threading.h" #include "boss.h" #include "client.h" /* The id of the listening socket. */ static socket_t m_listening_socket = -1; /* Child count */ static int child_count = 0; /* List of child threads. */ static pthread_t* m_children = NULL; /* The queue of client sockets. */ static queue_t m_client_sockets; int boss_initialize(port_t pnum, int thread_count) { int index = 0; int result = 0; #ifdef WIN32 /* Have to also initialize WinSock */ WSADATA uselessData; result = WSAStartup(MAKEWORD(2, 2), &uselessData); if (result) { fprintf(stderr, "[BOSS] Could not initialize WinSock.\n"); net_report_error(); return result; } #endif child_count = thread_count; /* Make a listening socket: */ m_listening_socket = net_listen_on_port(pnum); if (IS_BAD_SOCKET(m_listening_socket)) { return 1; } /* Initialize the queue */ queue_initialize(&m_client_sockets); /* Spawn children threads. */ m_children = (pthread_t*) calloc(thread_count, sizeof(pthread_t)); if (!m_children) { fprintf(stderr, "[BOSS] Could not allocate memory.\n"); net_report_error(); return 1; } for (index = 0; index < thread_count; index++) { result = pthread_create(m_children + index, NULL, client_run, &m_client_sockets); if (result) { fprintf(stderr, "[BOSS] Could not create child thread.\n"); net_report_error(); return result; } } return 0; } void* boss_run(void* param) { /* Loop infinitely accepting connections: */ while (1) { /* Accept connection */ socket_t client_socket = -1; sockaddress_t caddr; socklen_t sizeof_caddr = sizeof(sockaddress_t); DEBUG_PRINTF(("[BOSS] Waiting for a client connection...\n")); client_socket = accept(m_listening_socket, (struct sockaddr*) &caddr, &sizeof_caddr); if (IS_BAD_SOCKET(client_socket)) { fprintf(stderr, "[BOSS] Could not accept client on listening socket\n"); net_report_error(); continue; } DEBUG_PRINTF(("[BOSS] Got client on port %d.\n", ntohs(caddr.sin_port))); /* Enqueue socket to be picked up by a client thread. */ queue_enqueue(&m_client_sockets, (void*) client_socket); } return NULL; } int boss_clean() { /* Kill children */ int index; for (index = 0; index < child_count; index++) { pthread_kill(m_children[index], SIGINT); } DEBUG_PRINTF(("[BOSS] Shutting down...\n\n")); return net_close_socket(m_listening_socket); }