diff options
| -rw-r--r-- | configure.ac | 3 | ||||
| -rw-r--r-- | map-server/Makefile.am | 2 | ||||
| -rw-r--r-- | map-server/altos-map/.gitignore | 5 | ||||
| -rw-r--r-- | map-server/altos-map/Makefile.am | 64 | ||||
| -rw-r--r-- | map-server/altos-map/altos-map.c | 286 | ||||
| -rwxr-xr-x | map-server/altos-map/altos-mapc-fake (renamed from map-server/altos-map/altos-map-fake) | 2 | ||||
| -rw-r--r-- | map-server/altos-mapj/.gitignore | 6 | ||||
| -rw-r--r-- | map-server/altos-mapj/AltosMap.java (renamed from map-server/altos-map/AltosMap.java) | 0 | ||||
| -rw-r--r-- | map-server/altos-mapj/Makefile.am | 62 | ||||
| -rw-r--r-- | map-server/altos-mapj/Manifest.txt (renamed from map-server/altos-map/Manifest.txt) | 0 | ||||
| -rwxr-xr-x | map-server/altos-mapj/altos-mapj-fake | 6 | 
11 files changed, 369 insertions, 67 deletions
| diff --git a/configure.ac b/configure.ac index dae2499d..6e02f968 100644 --- a/configure.ac +++ b/configure.ac @@ -417,6 +417,8 @@ if test "x$HAVE_NICKLE" = "xno"; then  	AC_MSG_ERROR([Please install nickle to build AltOs])  fi +PKG_CHECK_MODULES([JANSSON], [jansson]) +  AC_ARG_WITH([readline],  	    [AS_HELP_STRING([--with-readline],  			      [enable readline functionality in ao-dbg @<:@default=auto@:>@])], @@ -574,6 +576,7 @@ ao-utils/Makefile  map-server/Makefile  map-server/altos-mapd/Makefile  map-server/altos-map/Makefile +map-server/altos-mapj/Makefile  src/Version  ]) diff --git a/map-server/Makefile.am b/map-server/Makefile.am index f9b8a727..39ff8014 100644 --- a/map-server/Makefile.am +++ b/map-server/Makefile.am @@ -1 +1 @@ -SUBDIRS=altos-mapd altos-map +SUBDIRS=altos-mapd altos-map altos-mapj diff --git a/map-server/altos-map/.gitignore b/map-server/altos-map/.gitignore index ea012eef..1158b56a 100644 --- a/map-server/altos-map/.gitignore +++ b/map-server/altos-map/.gitignore @@ -1,6 +1 @@  altos-map -altos-map-jdb -altos-map-test -*.jar -*.stamp -classes diff --git a/map-server/altos-map/Makefile.am b/map-server/altos-map/Makefile.am index f7c9bdc8..6925957b 100644 --- a/map-server/altos-map/Makefile.am +++ b/map-server/altos-map/Makefile.am @@ -1,62 +1,6 @@ -JAVAROOT=classes -AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6 +bin_PROGRAMS = altos-map -altoslibdir=$(libdir)/altos - -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../../altoslib/*" - -bin_SCRIPTS=altos-map - -altosmap_JAVA = \ -	AltosMap.java - -ALTOSLIB_CLASS=\ -	altoslib_$(ALTOSLIB_VERSION).jar - -JAR=altosmap.jar - -FATJAR=altosmap-fat.jar - -all-local: classes/altosmap $(JAR) altos-map altos-map-test altos-map-jdb - -install-altosmapJAVA: altosmap.jar -	@$(NORMAL_INSTALL) -	test -z "$(altosmapdir)" || $(MKDIR_P) "$(DESTDIR)$(altosmapdir)" -	echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosmapdir)/altosmap.jar'"; \ -	$(INSTALL_DATA) "$<" "$(DESTDIR)$(altosmapdir)" - -classes/altosmap: -	mkdir -p classes/altosmap - -$(JAR): classaltosmap.stamp Manifest.txt $(ALTOSLIB_CLASS) -	jar cfm $@ Manifest.txt \ -		-C classes altosmap - -altosmapdir=$(datadir)/java - -$(FATJAR): classaltosmap.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) -	jar cfm $@ Manifest-fat.txt \ -		-C classes altosmap - -altos-map: Makefile -	echo "#!/bin/sh" > $@ -	echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosmapdir)/altosmap.jar" "$$@"' >> $@ -	chmod +x $@ - -altos-map-test: Makefile -	echo '#!/bin/sh' > $@ -	echo 'dir="$$(dirname $$0)"' >> $@ -	echo 'cd "$$dir"' >> $@ -	echo 'altosmap="$$(pwd -P)"' >> $@ -	echo 'exec java -jar "$$altosmap/altosmap.jar" "$$@"' >> $@ -	chmod +x $@ - -altos-map-jdb: Makefile -	echo "#!/bin/sh" > $@ -	echo 'exec jdb altosmap/AltosMap "$$@"' >> $@ -	chmod +x $@ - -$(ALTOSLIB_CLASS): -	-rm -f "$@" -	$(LN_S) ../../altoslib/"$@" . +altos_map_SOURCES = altos-map.c +altos_map_LDADD = $(JANSSON_LIBS) +altos_map_CFLAGS = $(JANSSON_CFLAGS) $(WARN_CFLAGS) diff --git a/map-server/altos-map/altos-map.c b/map-server/altos-map/altos-map.c new file mode 100644 index 00000000..690ec728 --- /dev/null +++ b/map-server/altos-map/altos-map.c @@ -0,0 +1,286 @@ +/* + * Copyright © 2018 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + */ + +#include <jansson.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/ip.h> + +#define ALTOS_MAP_PORT	16717 + +#define MISSING		0x7fffffff + +#define ALTOS_MAP_PROTOCOL_VERSION	"1.0.0" + +static char * +reason_string(int code) +{ +	switch (code) { +	case 200: +		return "OK"; +	case 400: +		return "Bad Request"; +	case 403: +		return "Forbidden"; +	case 404: +		return "Not Found"; +	case 408: +		return "Request Timeout"; +	default: +		return "Failure"; +	} +} + +static void +write_status(int status) +{ +	printf("Status: %d %s\n", status, reason_string(status)); +} + +static void +write_type(char * type) +{ +	printf("Content-Type: %s\n", type); +} + +static void +fail(int status, char *format, ...) +{ +	va_list ap; + +	write_status(status); +	write_type("text/html"); +	printf("\n"); +	printf("<html>\n"); +	printf("<head><title>Map Fetch Failure</title></head>\n"); +	printf("<body>\n"); +	va_start(ap, format); +	vprintf(format, ap); +	va_end(ap); +	printf("</body>\n"); +	printf("</html>\n"); +	exit(1); +} + +static char * +getenv_copy(const char *name) +{ +	const char *value = getenv(name); + +	if (!value) +		return NULL; + +	return strdup(value); +} + +static double +parse_double(char *string) +{ +	char *end; +	double value; + +	value = strtod(string, &end); +	if (*end) +		fail(400, "Invalid double %s", string); +	return value; +} + +static int +parse_int(char *string) +{ +	char *end; +	long int value; + +	value = strtol(string, &end, 10); +	if (*end) +		fail(400, "Invalid int %s", string); +	if (value < INT_MIN || INT_MAX < value) +		fail(400, "Int value out of range %ld", value); +	return (int) value; +} + + +static int +connect_service(void) +{ +	struct sockaddr_in	altos_map_addr = { +		.sin_family = AF_INET, +		.sin_port = htons(ALTOS_MAP_PORT), +		.sin_addr = { +			.s_addr = htonl(INADDR_LOOPBACK), +		}, +	}; + +	int	s = socket(AF_INET, SOCK_STREAM, 0); + +	if (s < 0) +		return -1; + +	if (connect (s, (const struct sockaddr *) &altos_map_addr, sizeof (altos_map_addr)) < 0) { +		close (s); +		return -1; +	} + +	return s; +} + +int main(int argc, char **argv) +{ + +	char *query_string = getenv_copy("QUERY_STRING"); + +	if (query_string == NULL) +		fail(400, "%s", "Missing query string"); + +	char *remote_addr = getenv_copy("REMOTE_ADDR"); + +	if (remote_addr == NULL) +		fail(400, "%s", "Missing remote address"); + +	double	lon = MISSING; +	double	lat = MISSING; +	int	zoom = MISSING; +	char	*version = NULL; + +	char	*query, *query_save = NULL; +	char	*query_start = query_string; + +	while ((query = strtok_r(query_start, "&", &query_save)) != NULL) { +		query_start = NULL; + +		char	*token, *token_save = NULL; +		char	*token_start = query; + +		char	*name = NULL; +		char	*value = NULL; + +		while ((token = strtok_r(token_start, "=", &token_save)) != NULL) { +			token_start = NULL; +			if (name == NULL) +				name = token; +			else if (value == NULL) +				value = token; +			else +				break; +		} + +		if (name && value) { +			if (!strcmp(name, "lon")) +				lon = parse_double(value); +			else if (!strcmp(name, "lat")) +				lat = parse_double(value); +			else if (!strcmp(name, "zoom")) +				zoom = parse_int(value); +			else if (!strcmp(name, "version")) +				version = value; +			else +				fail(400, "Extra query param \"%s\"", query); +		} +	} + +	if (version != NULL) { +		printf("Content-Type: text/plain\n"); +		printf("\n"); +		printf("%s\n", ALTOS_MAP_PROTOCOL_VERSION); +		return 0; +	} +	if (lon == MISSING) +		fail(400, "Missing longitude"); +	if (lat == MISSING) +		fail(400, "Missing latitude"); +	if (zoom == MISSING) +		fail(400, "Missing zoom"); + +	int	s = -1; +	int	tries = 0; + +	while (tries < 10 && s < 0) { +		s = connect_service(); +		if (s < 0) { +			usleep(100 * 1000); +			tries++; +		} +	} + +	if (s < 0) +		fail(408, "Cannot connect AltOS map daemon"); + +	json_t *request = json_pack("{s:f s:f s:i s:s}", "lat", lat, "lon", lon, "zoom", zoom, "remote_addr", remote_addr); + +	if (request == NULL) +		fail(400, "Cannot create JSON request"); + +	if (json_dumpfd(request, s, 0) < 0) +		fail(400, "Cannot write JSON request"); + +	json_error_t	error; +	json_t 		*reply = json_loadfd(s, 0, &error); + +	if (!reply) +		fail(400, "Cannot read JSON reply"); + +	int	status; + +	if (json_unpack(reply, "{s:i}", "status", &status) < 0) +		fail(400, "No status returned"); + +	if (status != 200) +		fail(status, "Bad cache status"); + +	char	*filename, *content_type; + +	if (json_unpack(reply, "{s:s s:s}", "filename", &filename, "content_type", &content_type) < 0) +		fail(400, "JSON reply parse failure"); + +	int	fd = open(filename, O_RDONLY); + +	if (fd < 0) +		fail(400, "%s: %s", filename, strerror(errno)); + +	struct stat	statb; + +	if (fstat(fd, &statb) < 0) +		fail(400, "%s: %s", filename, strerror(errno)); + +	printf("Content-Type: %s\n", content_type); +	printf("Content-Length: %lu\n", (unsigned long) statb.st_size); +	printf("\n"); +	fflush(stdout); + +	char	buf[4096]; +	ssize_t	bytes_read; + +	while ((bytes_read = read(fd, buf, sizeof (buf))) > 0) { +		ssize_t total_write = 0; +		while (total_write < bytes_read) { +			ssize_t bytes_write = write(1, buf + total_write, bytes_read - total_write); +			if (bytes_write <= 0) +				return 1; +			total_write += bytes_write; +		} +	} +	if (bytes_read < 0) +		return 1; +	return 0; +} diff --git a/map-server/altos-map/altos-map-fake b/map-server/altos-map/altos-mapc-fake index a78bbd64..9e22f76f 100755 --- a/map-server/altos-map/altos-map-fake +++ b/map-server/altos-map/altos-mapc-fake @@ -2,5 +2,5 @@  # map-N43.799102,W120.586281-hybrid-20.jpg  export QUERY_STRING="lat=43.799102&lon=-120.586281&zoom=20"  export REMOTE_ADDR="127.0.0.1" -./altos-map-test +./altos-mapc diff --git a/map-server/altos-mapj/.gitignore b/map-server/altos-mapj/.gitignore new file mode 100644 index 00000000..c5d593e6 --- /dev/null +++ b/map-server/altos-mapj/.gitignore @@ -0,0 +1,6 @@ +altos-mapj +altos-mapj-jdb +altos-mapj-test +*.jar +*.stamp +classes diff --git a/map-server/altos-map/AltosMap.java b/map-server/altos-mapj/AltosMap.java index ad0a4f5f..ad0a4f5f 100644 --- a/map-server/altos-map/AltosMap.java +++ b/map-server/altos-mapj/AltosMap.java diff --git a/map-server/altos-mapj/Makefile.am b/map-server/altos-mapj/Makefile.am new file mode 100644 index 00000000..f447adb6 --- /dev/null +++ b/map-server/altos-mapj/Makefile.am @@ -0,0 +1,62 @@ +JAVAROOT=classes +AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6 + +altoslibdir=$(libdir)/altos + +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../../altoslib/*" + +bin_SCRIPTS=altos-mapj + +altosmap_JAVA = \ +	AltosMap.java + +ALTOSLIB_CLASS=\ +	altoslib_$(ALTOSLIB_VERSION).jar + +JAR=altosmap.jar + +FATJAR=altosmap-fat.jar + +all-local: classes/altosmap $(JAR) altos-mapj altos-mapj-test altos-mapj-jdb + +install-altosmapJAVA: altosmap.jar +	@$(NORMAL_INSTALL) +	test -z "$(altosmapdir)" || $(MKDIR_P) "$(DESTDIR)$(altosmapdir)" +	echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosmapdir)/altosmap.jar'"; \ +	$(INSTALL_DATA) "$<" "$(DESTDIR)$(altosmapdir)" + +classes/altosmap: +	mkdir -p classes/altosmap + +$(JAR): classaltosmap.stamp Manifest.txt $(ALTOSLIB_CLASS) +	jar cfm $@ Manifest.txt \ +		-C classes altosmap + +altosmapdir=$(datadir)/java + +$(FATJAR): classaltosmap.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) +	jar cfm $@ Manifest-fat.txt \ +		-C classes altosmap + +altos-mapj: Makefile +	echo "#!/bin/sh" > $@ +	echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosmapdir)/altosmap.jar" "$$@"' >> $@ +	chmod +x $@ + +altos-mapj-test: Makefile +	echo '#!/bin/sh' > $@ +	echo 'dir="$$(dirname $$0)"' >> $@ +	echo 'cd "$$dir"' >> $@ +	echo 'altosmap="$$(pwd -P)"' >> $@ +	echo 'exec java -jar "$$altosmap/altosmap.jar" "$$@"' >> $@ +	chmod +x $@ + +altos-mapj-jdb: Makefile +	echo "#!/bin/sh" > $@ +	echo 'exec jdb altosmap/AltosMap "$$@"' >> $@ +	chmod +x $@ + +$(ALTOSLIB_CLASS): +	-rm -f "$@" +	$(LN_S) ../../altoslib/"$@" . + diff --git a/map-server/altos-map/Manifest.txt b/map-server/altos-mapj/Manifest.txt index 1a285b40..1a285b40 100644 --- a/map-server/altos-map/Manifest.txt +++ b/map-server/altos-mapj/Manifest.txt diff --git a/map-server/altos-mapj/altos-mapj-fake b/map-server/altos-mapj/altos-mapj-fake new file mode 100755 index 00000000..f600fec7 --- /dev/null +++ b/map-server/altos-mapj/altos-mapj-fake @@ -0,0 +1,6 @@ +#!/bin/sh +# map-N43.799102,W120.586281-hybrid-20.jpg +export QUERY_STRING="lat=43.799102&lon=-120.586281&zoom=20" +export REMOTE_ADDR="127.0.0.1" +./altos-mapj-test + | 
