Example #1
0
File: HTTPd.c Project: Youx/craftd
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;
    }
}
Example #2
0
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);
}
Example #3
0
File: Worker.c Project: Youx/craftd
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;
}