lifo-dijkstraserv/src/dijkstraserv.c

173 lines
4.3 KiB
C
Raw Normal View History

2020-05-03 19:59:05 +02:00
#include "dijkstraserv.h"
static int dijkstra_serv_perform_search(struct dijkstra_serv *serv,
struct position *pos_start,
struct position *pos_destination,
char **result) {
struct dijkstra_node *start = NULL;
struct dijkstra_node *destination = NULL;
struct dijkstra_search *search;
int iterations;
GList *route;
report(LL_INFO, "Requested route from %f,%f to %f,%f.",
pos_start->x, pos_start->y,
pos_destination->x, pos_destination->y);
/* Find closest node */ // TODO: This should be closest point on path, but for now this'll do.
start = dijkstra_node_find_closest_node(serv->solver, pos_start);
if (!start)
return 0;
destination = dijkstra_node_find_closest_node(serv->solver, pos_destination);
if (!destination)
return 0;
report(LL_DEBUG, "Searching route from %f,%f to %f,%f.",
start->position.x, start->position.y,
destination->position.x, destination->position.y);
search = dijkstra_search_new(serv->solver);
if (!search) {
report(LL_CRITICAL, "Error allocating dijkstra_search");
return 0;
}
dijkstra_search_set_start(search, start);
if ((iterations = dijkstra_search_find_path(search, destination)) > 0) {
report(LL_INFO, " Found path from %d to %d after %d iterations.", start->uid, destination->uid, iterations);
route = dijkstra_search_get_route(search, destination);
return dijkstra_search_route_to_geojson(search, route, result);
} else {
report(LL_INFO, " Couldn't find path.");
}
return 0;
}
static void dijkstra_serv_soup_callback (SoupServer *server,
SoupMessage *msg,
const char *path,
GHashTable *query,
SoupClientContext *client,
gpointer user_data)
{
struct dijkstra_serv *serv = (struct dijkstra_serv *) user_data;
GError *err = NULL;
GMatchInfo *matchInfo;
GRegex *regex;
char *body;
int body_len;
int i = 0;
struct position pos_start, pos_destination;
report(LL_INFO, "New request: %s", path);
if (msg->method != SOUP_METHOD_GET) {
soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
return;
}
if (strlen(path) > 20) {
soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
return;
}
regex = g_regex_new("([\\-0-9]+)", 0, 0, &err);
g_regex_match (regex, path, 0, &matchInfo);
while (g_match_info_matches(matchInfo)) {
float result_num;
gchar *result;
result = g_match_info_fetch(matchInfo, 0);
if (!result)
break;
result_num = atof(result);
switch (i) {
case 0:
pos_start.x = result_num;
break;
case 1:
pos_start.y = result_num;
break;
case 2:
pos_destination.x = result_num;
break;
case 3:
pos_destination.y = result_num;
break;
}
g_match_info_next(matchInfo, &err);
g_free(result);
i++;
if (i >= 4)
break;
}
g_regex_unref(regex);
if (i == 4) {
body_len = dijkstra_serv_perform_search(serv, &pos_start, &pos_destination, &body);
if (!body_len) {
body = strdup("Not found.");
body_len = 9;
soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
} else {
soup_message_set_status (msg, SOUP_STATUS_OK);
}
soup_message_set_response (msg, "application/json", SOUP_MEMORY_COPY,
body, body_len);
free(body);
} else {
report(LL_WARNING, " Invalid request.");
soup_message_set_status (msg, SOUP_STATUS_MALFORMED);
soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY,
"Invalid request", 15);
}
}
struct dijkstra_serv *dijkstra_serv_new(
struct dijkstra_solver *solver,
int port)
{
struct dijkstra_serv *serv;
serv = (struct dijkstra_serv*) malloc(sizeof(*serv));
if (serv) {
serv->solver = solver;
serv->port = port;
serv->soupserver = soup_server_new(NULL, NULL);
if (!serv->soupserver) {
free(serv);
return NULL;
}
soup_server_add_handler (serv->soupserver,
"/", dijkstra_serv_soup_callback,
serv, NULL); // TODO: The last arg here should probably not be NULL...
}
return serv;
}
int dijkstra_serv_run(struct dijkstra_serv *serv)
{
GError *err = NULL;
if (!soup_server_listen_all(serv->soupserver, serv->port, 0, &err)) {
report(LL_CRITICAL, "Couldn't start server: %s", err->message);
g_error_free(err);
return -1;
}
report(LL_INFO, "Listening on port %d.", serv->port);
GMainLoop *loop;
loop = g_main_loop_new(NULL, TRUE);
g_main_loop_run(loop); // TODO: Add way to gracefully exit loop
return 0;
}