CDPointer CD_BufferContent (CDBuffer* self) { CDPointer data = (CDPointer) CD_malloc(CD_BufferLength(self)); evbuffer_copyout(self->raw, (void*) data, CD_BufferLength(self)); return data; }
void CD_BufferAddBuffer (CDBuffer* self, CDBuffer* data) { CDPointer stuff = CD_BufferContent(data); evbuffer_add(self->raw, (void*) stuff, CD_BufferLength(data)); CD_free((void*) stuff); }
CDBuffer* CD_BufferRemoveBuffer (CDBuffer* self) { struct evbuffer* buffer = evbuffer_new(); CDBuffer* result; evbuffer_remove_buffer(self->raw, buffer, CD_BufferLength(self)); result = CD_WrapBuffer(buffer); result->external = false; return result; }
bool CD_BufferEmpty (CDBuffer* self) { return CD_BufferLength(self) == 0; }
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; }