#include #include #include #include #include #include #include #define COMMON_IMPLEMENTATION #include /* sqlite leastunused implementation */ struct slidid { sqlite3_int64 il, in, res; }; void step_leastunused(sqlite3_context* ctx, int argc, sqlite3_value** argv) { struct slidid *idx = sqlite3_aggregate_context(ctx, sizeof *idx); if (idx->res) return; idx->in = sqlite3_value_int64(argv[0]); if (idx->il + 1 != idx->in) idx->res = idx->il + 1; idx->il = idx->in; } void final_leastunused(sqlite3_context* ctx) { struct slidid *idx = sqlite3_aggregate_context(ctx, 0); sqlite3_result_int(ctx, idx->res); } sqlite3 *sqlite_init(const char *db) { sqlite3 *ret; sqlite3_open_v2(db, &ret, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL); if (ret == NULL) LCRIT(1, "could not open sqlite3 database"); sqlite3_create_function(ret, "leastunused", 1, SQLITE_UTF8, NULL, NULL, step_leastunused, final_leastunused); return ret; } enum MHD_Result process_connection(void *dylib, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **req_cls) { LDEBUGF("\nurl: %s\nmethod:%s\nversion:%s\nupload_data:%s\nsize:%zu\n", url, method, version, upload_data, *upload_data_size); /* Load function with the name of the url from shared library */ endpoint handler = dlsym(dylib, url); query_func query = dlsym(dylib, "db_get_url"); struct MHD_Response *res; int status = MHD_HTTP_OK; const char *response; char *newurl; if (query == NULL) { response = "Temporary server error: could not open database"; res = MHD_create_response_from_buffer(strlen(response), (void*)response, MHD_RESPMEM_PERSISTENT); status = MHD_HTTP_INTERNAL_SERVER_ERROR; goto response; } if (strcasecmp(method, "GET")) { status = MHD_HTTP_METHOD_NOT_ALLOWED; res = MHD_create_response_from_buffer(18, "Method not allowed", MHD_RESPMEM_PERSISTENT); goto response; } if (handler != NULL) { /* endpoint access */ LINFOF("Accessed endpoint at url %s", url); res = handler(connection, &status); } else if ((newurl = query(url)) != NULL) { LINFOF("Redirect from %s to %s", url, newurl); /* if (newurl == NULL) { */ /* free(newurl); */ /* response = "Page does not exist"; */ /* res = MHD_create_response_from_buffer(strlen(response), (void*)response, MHD_RESPMEM_PERSISTENT); */ /* status = MHD_HTTP_NOT_FOUND; */ /* goto response; */ /* } */ response = "Recirecting..."; res = MHD_create_response_from_buffer(strlen(response), (void*)response, MHD_RESPMEM_PERSISTENT); MHD_add_response_header(res, "Location", newurl); status = MHD_HTTP_FOUND; } else if ((res = get_from_file(url + 1)) != NULL) { /* fallback file access */ LINFOF("Accessed file at url %s", url); } else { /* error */ LINFOF("Failed access to endpoint\t%s", url); const char* error = "\"resource does not exist\""; res = MHD_create_response_from_buffer(strlen(error), (void*)error, MHD_RESPMEM_PERSISTENT); status = MHD_HTTP_NOT_FOUND; } response: MHD_queue_response(connection, status, res); MHD_destroy_response(res); return MHD_YES; } int main(int argc, char *argv[]){ void* dylib = dlopen("./endpoints.so", RTLD_NOW); if (!dylib) LCRITF(1, "Could not open dynamic library: %s\n", dlerror()); struct MHD_Daemon *daemon = MHD_start_daemon(MHD_USE_POLL | MHD_USE_INTERNAL_POLLING_THREAD, 8080, NULL, NULL, process_connection, dylib, MHD_OPTION_END); if (daemon == NULL) LCRITV(1, "could not initialize daemon"); getchar(); dlclose(dylib); MHD_stop_daemon(daemon); return 0; }