#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) > 40) { 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; }