aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.c
blob: 36df30aeae17e670dd4825489f713d24ece7dbcb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>

#include <microhttpd.h>
#include <sqlite3.h>

#include <log.h>
#define COMMON_IMPLEMENTATION
#include <common.h>

/* 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 = "<!DOCTYPE html><html><body>Temporary server error: could not open database</body></html>";
		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 = "<!DOCTYPE html><html><body>Page does not exist</body></html>"; */
		/* 	res = MHD_create_response_from_buffer(strlen(response), (void*)response, MHD_RESPMEM_PERSISTENT); */
		/* 	status = MHD_HTTP_NOT_FOUND; */
		/* 	goto response; */
		/* } */
		response = "<!DOCTYPE html><html><body>Recirecting...</body></html>";
		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;
}