#include "ServerEvents.h" #include "CurlResult.h" void ServerEvents_init(struct ServerEvents* this) { Buffer_init(&this->buffer); this->callbacks = List_create(); this->handle = NULL; } void ServerEvents_destroyMembers(struct ServerEvents* this) { Buffer_destroyMembers(&this->buffer); if (this->handle) { curl_easy_cleanup(this->handle); } List_destroyWithContent(this->callbacks, free); } void ServerEvents_connect(struct ServerEvents* this, const char* baseUrl, CURLM* multiHandle) { char url[512]; sprintf(url, "%s/api/events/all", baseUrl); CURL* handle = curl_easy_init(); curl_easy_setopt(handle, CURLOPT_URL, url); /* curl_easy_setopt(handle, CURLOPT_TIMEOUT, 0); */ /* curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1); */ curl_easy_setopt(handle, CURLOPT_WRITEDATA, this); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, ServerEvents_write); if (this->handle) { curl_easy_cleanup(handle); } this->handle = handle; curl_multi_add_handle(multiHandle, handle); } void ServerEvents_addCallback(struct ServerEvents* this, void(*fn)(const char*,const char*,void*), void* userdata) { size_t size = sizeof(struct ServerEventCallback); struct ServerEventCallback* cb = malloc(size); cb->fn = fn; cb->userdata = userdata; List_pushBack(this->callbacks, cb); } /* event: name */ /* data: asdjflokjpa */ /* data: kljasdklafkjsdfl continues n times */ /* */ size_t ServerEvents_write(void* buffer, size_t charSize, size_t bufferSize, void* userdata) { if (!userdata) { return 0; } struct ServerEvents* this = userdata; size_t result = Buffer_append(&this->buffer, buffer, (bufferSize*charSize)); if (/* result > 0 && */ /* TODO correct error check */ this->buffer.bufferUsed > 2 && ((this->buffer.buffer[this->buffer.bufferUsed-1] == '\n' && this->buffer.buffer[this->buffer.bufferUsed-2] == '\n') || (this->buffer.buffer[this->buffer.bufferUsed-2] == '\n' && this->buffer.buffer[this->buffer.bufferUsed-3] == '\n'))) { ServerEvents_parseMessage(this); Buffer_destroyMembers(&this->buffer); Buffer_init(&this->buffer); } return result; } void ServerEvents_parseMessage(struct ServerEvents* this) { char* message = this->buffer.buffer; char* event = NULL; if (0 == strncmp(message, "event: ", sizeof("event: ")-1)) { const char* eventNameStart = message + sizeof("event: ")-1; while(*message != '\0' && *message != '\n') { ++message; } event = copy_string(eventNameStart, (message-eventNameStart)); } ++message; struct Buffer dataBuffer; Buffer_init(&dataBuffer); while ((message < this->buffer.buffer + this->buffer.bufferUsed) && 0 == strncmp(message, "data: ", sizeof("data: ")-1)) { const char* dataStart = message + sizeof("data: ")-1; while(*message != '\0' && *message != '\n') { ++message; } Buffer_append(&dataBuffer, dataStart, (message-dataStart)+1); ++message; } for (ListNode* it = this->callbacks->first; it; it=it->next) { struct ServerEventCallback* cb = it->data; Buffer_append(&dataBuffer, "\0", 1); cb->fn(event, dataBuffer.buffer, cb->userdata); } safe_free(event); Buffer_destroyMembers(&dataBuffer); }