CDHTTPd* CD_CreateHTTPd (CDServer* server) { CDHTTPd* self = CD_malloc(sizeof(CDHTTPd)); if (pthread_attr_init(&self->attributes) != 0) { CD_abort("pthread attribute failed to initialize"); } if (pthread_attr_setdetachstate(&self->attributes, PTHREAD_CREATE_DETACHED) != 0) { CD_abort("pthread attribute failed to set in detach state"); } self->server = server; self->event.base = event_base_new(); self->event.httpd = evhttp_new(self->event.base); evhttp_set_cb(self->event.httpd, "/rpc/json", (void (*)(struct evhttp_request*, void*)) cd_JSONRequest, server); evhttp_set_gencb(self->event.httpd, (void (*)(struct evhttp_request*, void*)) cd_StaticRequest, server); return self; }
CDWorkers* CD_CreateWorkers (CDServer* server) { CDWorkers* self = CD_malloc(sizeof(CDWorkers)); assert(self); self->server = server; self->last = 0; self->length = 0; self->item = NULL; self->jobs = CD_CreateList(); if (pthread_attr_init(&self->attributes) != 0) { CD_abort("pthread attribute failed to initialize"); } if (pthread_attr_setdetachstate(&self->attributes, PTHREAD_CREATE_DETACHED) != 0) { CD_abort("pthread attribute failed to set in detach state"); } if (pthread_attr_setstacksize(&self->attributes, CD_THREAD_STACK) != 0) { CD_abort("pthread attribute failed to set stack size"); } if (pthread_mutex_init(&self->lock.mutex, NULL) != 0) { CD_abort("pthread mutex failed to initialize"); } if (pthread_cond_init(&self->lock.condition, NULL) != 0) { CD_abort("pthread cond failed to initialize"); } return self; }
CDList* CD_CreateList (void) { CDList* self = CD_malloc(sizeof(CDList)); self->head = NULL; self->tail = NULL; self->changed = false; self->length = 0; if (pthread_rwlock_init(&self->lock, NULL) != 0) { CD_abort("pthread rwlock failed to initialize"); } return self; }
CDClient* CD_CreateClient (CDServer* server) { CDClient* self = CD_malloc(sizeof(CDClient)); if (pthread_rwlock_init(&self->lock.status, NULL) != 0) { CD_abort("pthread rwlock failed to initialize"); } self->server = server; self->status = CDClientConnect; self->jobs = 0; self->buffers = NULL; DYNAMIC(self) = CD_CreateDynamic(); ERROR(self) = CDNull; return self; }
int main (int argc, char** argv) { CDServer* server; int opt; bool noFork = false; bool debugging = false; char* config = NULL; static const char* configSearchPath[] = { "%s/.craftd/craftd.conf", // %s is replaced with $HOME "/etc/craftd/craftd.conf", "/usr/local/etc/craftd/craftd.conf", "craftd.conf", // Current working directory (for devs) NULL }; CDDefaultLogger = CDConsoleLogger; LOG(LOG_INFO, "%s " CRAFTD_NOTICE_MESSAGE, argv[0]); while ((opt = getopt(argc, argv, "c:dhnv")) != -1) { switch (opt) { case 'd': { // debugging mode debugging = true; } break; case 'v': { // print version exit(EXIT_SUCCESS); // Version header already printed } break; case 'n': { // don't fork or daemonize, use stdout for logging noFork = true; } break; case 'c': { // use the specified config file config = optarg; } break; case 'h': // print help message default: { fprintf(stderr, "\nUsage: %s [OPTION]...\n" "-c <conf file> specify a conf file location\n" "-d enable verbose debugging messages\n" "-h display this help and exit\n" "-n don't fork/daemonize (overrides config file)\n" "-v output version information and exit\n" "\n" "For complete documentation, visit the wiki.\n\n", argv[0]); exit((opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE); } } } if (!config) { char path[FILENAME_MAX] = { 0 }; const char** current = configSearchPath; do { snprintf(path, FILENAME_MAX, *current, getenv("HOME")); current++; } while (*current != NULL && !CD_PathExists(path)); if (!CD_PathExists(path)) { CD_abort("The config file could not be found"); } else { config = path; } } if (!CD_IsReadable(config)) { CD_abort("%s could not be read", config); } #ifdef WIN32 evthread_use_windows_threads(); #else evthread_use_pthreads(); #endif if (debugging) { evthread_enable_lock_debuging(); } CDMainServer = server = CD_CreateServer(config); if (!server) { CD_abort("Server couldn't be instantiated"); } /* By default, mask debugging messages */ if (!debugging) { server->logger.setlogmask(LOG_MASK(LOG_DEBUG)); } CD_RunServer(server); LOG(LOG_INFO, "Exiting."); LOG_CLOSE(); CD_DestroyServer(server); }