static void cd_JSONRequest (struct evhttp_request* request, CDServer* server) { struct evbuffer* buffer = evhttp_request_get_input_buffer(request); char* text = CD_alloc(evbuffer_get_length(buffer) + 1); evbuffer_remove(buffer, text, evbuffer_get_length(buffer)); json_error_t error; json_t* input = json_loads(text, 0, &error); json_t* output = json_object(); printf("%s\n", text); if (evhttp_request_get_command(request) != EVHTTP_REQ_POST) { goto error; } if (input == NULL) { SERR(server, "RPC.JSON: error on line %d: %s", error.line, error.text); goto error; } CD_EventDispatch(server, "RPC.JSON", input, output); done: { char* outString = json_dumps(output, JSON_INDENT(2)); struct evbuffer* outBuffer = evbuffer_new(); evbuffer_add_printf(outBuffer, "%s", outString); evhttp_send_reply(request, HTTP_OK, "OK", outBuffer); evbuffer_free(outBuffer); free(outString); json_delete(output); json_delete(input); CD_free(text); return; } error: { evhttp_send_error(request, HTTP_INTERNAL, "Internal server error"); CD_free(text); if (input) { json_delete(input); } if (output) { json_delete(output); } return; } }
void CD_DestroyClient (CDClient* self) { assert(self); CD_EventDispatch(self->server, "Client.destroy", self); if (self->buffers) { bufferevent_flush(self->buffers->raw, EV_READ | EV_WRITE, BEV_FINISHED); bufferevent_disable(self->buffers->raw, EV_READ | EV_WRITE); bufferevent_free(self->buffers->raw); CD_DestroyBuffers(self->buffers); } CD_DestroyDynamic(DYNAMIC(self)); pthread_rwlock_destroy(&self->lock.status); CD_free(self); }
bool CD_RunWorker (CDWorker* self) { assert(self); SLOG(self->server, LOG_INFO, "worker %d started", self->id); while (self->working) { self->job = NULL; if (!CD_HasJobs(self->workers)) { pthread_mutex_lock(&self->workers->lock.mutex); SDEBUG(self->server, "worker %d ready", self->id); pthread_cond_wait(&self->workers->lock.condition, &self->workers->lock.mutex); pthread_mutex_unlock(&self->workers->lock.mutex); } if (!self->working) { break; } self->job = CD_NextJob(self->workers); if (!self->job) { SDEBUG(self->server, "no jobs for %d :<", self->id); continue; } SDEBUG(self->server, "worker %d running", self->id); if (self->job->type == CDCustomJob) { CDCustomJobData* data = (CDCustomJobData*) self->job->data; data->callback(data->data); CD_DestroyJob(self->job); } else if (CD_JOB_IS_PLAYER(self->job)) { CDClient* client; if (self->job->type == CDClientProcessJob) { client = ((CDClientProcessJobData*) self->job->data)->client; } else { client = (CDClient*) self->job->data; } if (!client) { CD_DestroyJob(self->job); continue; } pthread_rwlock_rdlock(&client->lock.status); if (client->status == CDClientDisconnect) { if (self->job->type != CDClientDisconnectJob) { CD_DestroyJob(self->job); self->job = NULL; client->jobs--; } } pthread_rwlock_unlock(&client->lock.status); if (!self->job) { continue; } if (self->job->type == CDClientConnectJob) { CD_EventDispatch(self->server, "Client.connect", client); pthread_rwlock_wrlock(&client->lock.status); if (client->status != CDClientDisconnect) { client->status = CDClientIdle; } pthread_rwlock_unlock(&client->lock.status); CD_DestroyJob(self->job); if (CD_BufferLength(client->buffers->input) > 0) { CD_ReadFromClient(client); } } else if (self->job->type == CDClientProcessJob) { CD_EventDispatch(self->server, "Client.process", client, ((CDClientProcessJobData*) self->job->data)->packet); CD_EventDispatch(self->server, "Client.processed", client, ((CDClientProcessJobData*) self->job->data)->packet); pthread_rwlock_wrlock(&client->lock.status); if (client->status != CDClientDisconnect) { client->status = CDClientIdle; } client->jobs--; pthread_rwlock_unlock(&client->lock.status); CD_DestroyJob(self->job); if (CD_BufferLength(client->buffers->input) > 0) { CD_ReadFromClient(client); } } else if (self->job->type == CDClientDisconnectJob) { while (true) { pthread_rwlock_rdlock(&client->lock.status); if (client->jobs < 1) { pthread_rwlock_unlock(&client->lock.status); break; } pthread_rwlock_unlock(&client->lock.status); } CD_EventDispatch(self->server, "Client.disconnect", client, (bool) ERROR(client)); CD_ListPush(self->server->disconnecting, (CDPointer) client); CD_ServerFlush(client->server, false); CD_DestroyJob(self->job); } } self->job = NULL; } return true; }