From 3b817a2b854065af23c9ec8e849150e6930f51e9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 16:04:39 -0700 Subject: map-server: Add maps proxy server This creates a map proxy server to handle the new Google Maps API requirements Signed-off-by: Keith Packard --- map-server/Makefile.am | 1 + map-server/altos-map/.gitignore | 6 + map-server/altos-map/AltosMap.java | 156 ++++++++++++++++++++++++ map-server/altos-map/Makefile.am | 56 +++++++++ map-server/altos-map/Manifest.txt | 2 + map-server/altos-map/altos-map-fake | 6 + map-server/altos-mapd/.gitignore | 6 + map-server/altos-mapd/AltosMapd.java | 50 ++++++++ map-server/altos-mapd/AltosMapdClient.java | 148 ++++++++++++++++++++++ map-server/altos-mapd/AltosMapdPreferences.java | 85 +++++++++++++ map-server/altos-mapd/AltosMapdServer.java | 37 ++++++ map-server/altos-mapd/Makefile.am | 59 +++++++++ map-server/altos-mapd/Manifest.txt | 2 + 13 files changed, 614 insertions(+) create mode 100644 map-server/Makefile.am create mode 100644 map-server/altos-map/.gitignore create mode 100644 map-server/altos-map/AltosMap.java create mode 100644 map-server/altos-map/Makefile.am create mode 100644 map-server/altos-map/Manifest.txt create mode 100755 map-server/altos-map/altos-map-fake create mode 100644 map-server/altos-mapd/.gitignore create mode 100644 map-server/altos-mapd/AltosMapd.java create mode 100644 map-server/altos-mapd/AltosMapdClient.java create mode 100644 map-server/altos-mapd/AltosMapdPreferences.java create mode 100644 map-server/altos-mapd/AltosMapdServer.java create mode 100644 map-server/altos-mapd/Makefile.am create mode 100644 map-server/altos-mapd/Manifest.txt (limited to 'map-server') diff --git a/map-server/Makefile.am b/map-server/Makefile.am new file mode 100644 index 00000000..f9b8a727 --- /dev/null +++ b/map-server/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=altos-mapd altos-map diff --git a/map-server/altos-map/.gitignore b/map-server/altos-map/.gitignore new file mode 100644 index 00000000..ea012eef --- /dev/null +++ b/map-server/altos-map/.gitignore @@ -0,0 +1,6 @@ +altos-map +altos-map-jdb +altos-map-test +*.jar +*.stamp +classes diff --git a/map-server/altos-map/AltosMap.java b/map-server/altos-map/AltosMap.java new file mode 100644 index 00000000..83bc7cea --- /dev/null +++ b/map-server/altos-map/AltosMap.java @@ -0,0 +1,156 @@ +/* + * Copyright © 2018 Keith Packard + * + * 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. + */ + +package altosmap; + +import java.net.*; +import java.io.*; +import java.util.*; +import java.text.*; + +import org.altusmetrum.altoslib_13.*; + +public class AltosMap { + + public final static int port = 16717; + + String query_string; + String remote_addr; + + public String 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"; + } + } + + public void write_status(int status) { + System.out.printf("Status: %d %s\n", status, reason_string(status)); + } + + public void write_type(String type) { + System.out.printf("Content-Type: %s\n", type); + } + + public void fail(int status, String reason) { + write_status(status); + write_type("text/html"); + System.out.printf("%s\n", reason); + System.exit(1); + } + + public void process() { + query_string = System.getenv("QUERY_STRING"); + + if (query_string == null) + fail(400, "Missing query string"); + + remote_addr = System.getenv("REMOTE_ADDR"); + + if (remote_addr == null) + fail(400, "Missing remote address"); + + String[] queries = query_string.split("&"); + + double lon = AltosLib.MISSING; + double lat = AltosLib.MISSING; + int zoom = AltosLib.MISSING; + + try { + for (String query : queries) { + String[] q = query.split("="); + if (q.length >= 2) { + String name = q[0]; + String value = q[1]; + if (name.equals("lon")) + lon = AltosParse.parse_double_net(value); + else if (name.equals("lat")) + lat = AltosParse.parse_double_net(value); + else if (name.equals("zoom")) + zoom = AltosParse.parse_int(value); + else + fail(400, String.format("Extra query param \"%s\"", query)); + } + } + } catch (ParseException pe) { + fail(400, String.format("Invalid query: %s", pe.toString())); + } + + if (lon == AltosLib.MISSING) + fail(400, "Missing longitude"); + if (lat == AltosLib.MISSING) + fail(400, "Missing latitude"); + if (zoom == AltosLib.MISSING) + fail(400, "Missing zoom"); + + try { + Socket socket = new Socket(InetAddress.getLoopbackAddress(), port); + + AltosJson request = new AltosJson(); + + request.put("lat", lat); + request.put("lon", lon); + request.put("zoom", zoom); + request.put("remote_addr", remote_addr); + + Writer writer = new PrintWriter(socket.getOutputStream()); + request.write(writer); + writer.flush(); + + AltosJson reply = AltosJson.fromInputStream(socket.getInputStream()); + + int status = reply.get_int("status", 400); + + if (status != 200) + fail(status, "Bad cache status"); + + String filename = reply.get_string("filename", null); + try { + File file = new File(filename); + long length = file.length(); + FileInputStream in = new FileInputStream(file); + String content_type = reply.get_string("content_type", null); + System.out.printf("Content-Type: %s\n", content_type); + System.out.printf("Content-Length: %d\n", file.length()); + byte[] buf = new byte[4096]; + int bytes_read; + while ((bytes_read = in.read(buf)) > 0) + System.out.write(buf); + } catch (IOException ie) { + fail(404, String.format("IO Exception: %s", ie.toString())); + } + } catch (Exception e) { + fail(404, String.format("Exception %s", e.toString())); + } + } + + public AltosMap() { + } + + public static void main(final String[] args) { + + new AltosMap().process(); + + } +} diff --git a/map-server/altos-map/Makefile.am b/map-server/altos-map/Makefile.am new file mode 100644 index 00000000..efaae457 --- /dev/null +++ b/map-server/altos-map/Makefile.am @@ -0,0 +1,56 @@ +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-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 + +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/"$@" . + diff --git a/map-server/altos-map/Manifest.txt b/map-server/altos-map/Manifest.txt new file mode 100644 index 00000000..1a285b40 --- /dev/null +++ b/map-server/altos-map/Manifest.txt @@ -0,0 +1,2 @@ +Main-Class: altosmap.AltosMap +Class-Path: altoslib_13.jar diff --git a/map-server/altos-map/altos-map-fake b/map-server/altos-map/altos-map-fake new file mode 100755 index 00000000..a78bbd64 --- /dev/null +++ b/map-server/altos-map/altos-map-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-map-test + diff --git a/map-server/altos-mapd/.gitignore b/map-server/altos-mapd/.gitignore new file mode 100644 index 00000000..5f5ce0ae --- /dev/null +++ b/map-server/altos-mapd/.gitignore @@ -0,0 +1,6 @@ +*.stamp +*.jar +altos-mapd +altos-mapd-jdb +altos-mapd-test +classes diff --git a/map-server/altos-mapd/AltosMapd.java b/map-server/altos-mapd/AltosMapd.java new file mode 100644 index 00000000..cfa1ef35 --- /dev/null +++ b/map-server/altos-mapd/AltosMapd.java @@ -0,0 +1,50 @@ +/* + * Copyright © 2018 Keith Packard + * + * 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. + */ + +package altosmapd; + +import java.net.*; +import java.io.*; + +import org.altusmetrum.altoslib_13.*; + +public class AltosMapd { + + public final static int port = 16717; + + public final static int maptype = AltosMap.maptype_hybrid; + + public final static int px_size = 512; + + public final static int scale = 1; + + public static void main(final String[] args) { + + AltosMapdServer server = new AltosMapdServer(port); + + AltosPreferences.init(new AltosMapdPreferences()); + + AltosPreferences.mapdir = new File("/home/keithp/misc/rockets/flights/maps"); + + for (;;) { + Socket client = server.accept(); + if (client == null) { + System.out.printf("accept failed\n"); + continue; + } + System.out.printf("got client\n"); + new AltosMapdClient(client); + } + } +} diff --git a/map-server/altos-mapd/AltosMapdClient.java b/map-server/altos-mapd/AltosMapdClient.java new file mode 100644 index 00000000..fb0c08e6 --- /dev/null +++ b/map-server/altos-mapd/AltosMapdClient.java @@ -0,0 +1,148 @@ +/* + * Copyright © 2018 Keith Packard + * + * 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. + */ + +package altosmapd; + +import java.net.*; +import java.util.*; +import java.util.concurrent.*; +import java.io.*; + +import org.altusmetrum.altoslib_13.*; + +public class AltosMapdClient extends Thread implements AltosMapStoreListener { + private Socket socket; + private AltosJson request; + private AltosJson reply; + + private void set_status(int status) { + reply.put("status", status); + } + + private void set_filename(String filename) { + reply.put("filename", filename); + + } + + private void set_content_type(String content_type) { + reply.put("content_type", content_type); + } + + private String content_type(File file) { + String content_type = "application/octet-stream"; + String basename = file.getName(); + if (basename.endsWith(".jpg")) + content_type = "image/jpeg"; + if (basename.endsWith(".png")) + content_type = "image/png"; + return content_type; + } + + private void set_file(File file) { + set_filename(file.getAbsolutePath()); + set_content_type(content_type(file)); + } + + private Semaphore store_ready; + + public void notify_store(AltosMapStore map_store, int status) { + if (status != AltosMapTile.fetching) + store_ready.release(); + } + + public void run() { + reply = new AltosJson(); + try { + request = AltosJson.fromInputStream(socket.getInputStream()); + + double lat = request.get_double("lat", AltosLib.MISSING); + double lon = request.get_double("lon", AltosLib.MISSING); + int zoom = request.get_int("zoom", AltosLib.MISSING); + String addr = request.get_string("remote_addr", null); + + if (lat == AltosLib.MISSING || + lon == AltosLib.MISSING || + zoom == AltosLib.MISSING || + addr == null) + { + set_status(400); + } else { + store_ready = new Semaphore(0); + + System.out.printf("Fetching tile for %g %g %d\n", lat, lon, zoom); + + AltosMapStore map_store = AltosMapStore.get(new AltosLatLon(lat, lon), + zoom, + AltosMapd.maptype, + AltosMapd.px_size, + AltosMapd.scale); + int status; + + if (map_store == null) { + System.out.printf("no store?\n"); + status = AltosMapTile.failed; + } else { + map_store.add_listener(this); + + System.out.printf("Waiting for tile\n"); + + try { + store_ready.acquire(); + } catch (Exception ie) { + } + + status = map_store.status(); + } + + if (status == AltosMapTile.fetched || status == AltosMapTile.loaded) { + set_status(200); + set_file(map_store.file); + } else if (status == AltosMapTile.failed) { + set_status(404); + } else if (status == AltosMapTile.fetching) { + set_status(408); + } else if (status == AltosMapTile.bad_request) { + set_status(400); + } else if (status == AltosMapTile.forbidden) { + set_status(403); + } else { + set_status(400); + } + } + } catch (Exception e) { + System.out.printf("client exception %s\n", e.toString()); + e.printStackTrace(System.out); + set_status(400); + + } finally { + try { + Writer writer = new PrintWriter(socket.getOutputStream()); + reply.write(writer); + writer.write('\n'); + writer.flush(); + } catch (IOException ie) { + } + try { + socket.close(); + } catch (IOException ie) { + } + System.out.printf("client done\n"); + } + } + + public AltosMapdClient(Socket socket) { + this.socket = socket; + start(); + } +} diff --git a/map-server/altos-mapd/AltosMapdPreferences.java b/map-server/altos-mapd/AltosMapdPreferences.java new file mode 100644 index 00000000..fcfe3261 --- /dev/null +++ b/map-server/altos-mapd/AltosMapdPreferences.java @@ -0,0 +1,85 @@ +/* + * Copyright © 2018 Keith Packard + * + * 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. + */ + +package altosmapd; + +import java.io.*; + +import org.altusmetrum.altoslib_13.*; + +public class AltosMapdPreferences extends AltosPreferencesBackend { + + public String getString(String key, String def) { + return def; + } + public void putString(String key, String value) { + } + + public int getInt(String key, int def) { + return def; + } + + public void putInt(String key, int value) { + } + + public double getDouble(String key, double def) { + return def; + } + + public void putDouble(String key, double value) { + } + + public boolean getBoolean(String key, boolean def) { + return def; + } + + public void putBoolean(String key, boolean value) { + } + + public byte[] getBytes(String key, byte[] def) { + return def; + } + + public void putBytes(String key, byte[] value) { + } + + public boolean nodeExists(String key) { + return false; + } + + public AltosPreferencesBackend node(String key) { + return this; + } + + public String[] keys() { + return null; + } + + public void remove(String key) { + } + + public void flush() { + } + + public File homeDirectory() { + return new File ("."); + } + + public void debug(String format, Object ... arguments) { + System.out.printf(format, arguments); + } + + public AltosMapdPreferences() { + } +} diff --git a/map-server/altos-mapd/AltosMapdServer.java b/map-server/altos-mapd/AltosMapdServer.java new file mode 100644 index 00000000..68b427f0 --- /dev/null +++ b/map-server/altos-mapd/AltosMapdServer.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2018 Keith Packard + * + * 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. + */ + +package altosmapd; + +import java.net.*; + +public class AltosMapdServer { + ServerSocket socket; + + public Socket accept() { + try { + return socket.accept(); + } catch (Exception e) { + return null; + } + } + + public AltosMapdServer(int port) { + try { + socket = new ServerSocket(port, 5, InetAddress.getLoopbackAddress()); + } catch (Exception e) { + socket = null; + } + } +} diff --git a/map-server/altos-mapd/Makefile.am b/map-server/altos-mapd/Makefile.am new file mode 100644 index 00000000..c099d1c7 --- /dev/null +++ b/map-server/altos-mapd/Makefile.am @@ -0,0 +1,59 @@ +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-mapd + +altosmapd_JAVA = \ + AltosMapd.java \ + AltosMapdServer.java \ + AltosMapdClient.java \ + AltosMapdPreferences.java + +ALTOSLIB_CLASS=\ + altoslib_$(ALTOSLIB_VERSION).jar + +JAR=altosmapd.jar + +FATJAR=altosmapd-fat.jar + +all-local: classes/altosmapd $(JAR) altos-mapd altos-mapd-test altos-mapd-jdb + +classes/altosmapd: + mkdir -p classes/altosmapd + +$(JAR): classaltosmapd.stamp Manifest.txt $(ALTOSLIB_CLASS) + jar cfm $@ Manifest.txt \ + -C classes altosmapd + +altosmapddir=$(datadir)/java + +$(FATJAR): classaltosmapd.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) + jar cfm $@ Manifest-fat.txt \ + -C classes altosmapd + +altos-mapd: Makefile + echo "#!/bin/sh" > $@ + echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosmapddir)/altosmapd.jar" "$$@"' >> $@ + chmod +x $@ + +altos-mapd-test: Makefile + echo '#!/bin/sh' > $@ + echo 'dir="$$(dirname $$0)"' >> $@ + echo 'cd "$$dir"' >> $@ + echo 'altosmapd="$$(pwd -P)"' >> $@ + echo 'exec java -jar "$$altosmapd/altosmapd.jar" "$$@"' >> $@ + chmod +x $@ + +altos-mapd-jdb: Makefile + echo "#!/bin/sh" > $@ + echo 'exec jdb altosmapd/AltosMapd "$$@"' >> $@ + chmod +x $@ + +$(ALTOSLIB_CLASS): + -rm -f "$@" + $(LN_S) ../../altoslib/"$@" . + diff --git a/map-server/altos-mapd/Manifest.txt b/map-server/altos-mapd/Manifest.txt new file mode 100644 index 00000000..42c0313b --- /dev/null +++ b/map-server/altos-mapd/Manifest.txt @@ -0,0 +1,2 @@ +Main-Class: altosmapd.AltosMapd +Class-Path: altoslib_13.jar -- cgit v1.2.3 From a372152654613fd8479ed4687b987ae2a513adf6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 18:10:57 -0600 Subject: altos-map: Fix altos-map HTTP syntax Add blank line between header and content. Make error pages have actual HTML content. Signed-off-by: Keith Packard --- map-server/altos-map/AltosMap.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'map-server') diff --git a/map-server/altos-map/AltosMap.java b/map-server/altos-map/AltosMap.java index 83bc7cea..380556f4 100644 --- a/map-server/altos-map/AltosMap.java +++ b/map-server/altos-map/AltosMap.java @@ -56,7 +56,11 @@ public class AltosMap { public void fail(int status, String reason) { write_status(status); write_type("text/html"); + System.out.printf("\n"); + System.out.printf("\n"); + System.out.printf("Map Fetch Failure\n"); System.out.printf("%s\n", reason); + System.out.printf("\n"); System.exit(1); } @@ -133,6 +137,7 @@ public class AltosMap { String content_type = reply.get_string("content_type", null); System.out.printf("Content-Type: %s\n", content_type); System.out.printf("Content-Length: %d\n", file.length()); + System.out.printf("\n"); byte[] buf = new byte[4096]; int bytes_read; while ((bytes_read = in.read(buf)) > 0) -- cgit v1.2.3 From e405ec771b812f0ff78abbe813c3a793ae129487 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 18:11:13 -0600 Subject: altos-map: Install .jar file for altos-map Signed-off-by: Keith Packard --- map-server/altos-map/Makefile.am | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'map-server') diff --git a/map-server/altos-map/Makefile.am b/map-server/altos-map/Makefile.am index efaae457..f7c9bdc8 100644 --- a/map-server/altos-map/Makefile.am +++ b/map-server/altos-map/Makefile.am @@ -19,6 +19,12 @@ 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 -- cgit v1.2.3 From cabfcb078950238cdaee4e6ec4702195feaabc7b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 18:11:48 -0600 Subject: altos-mapd: Use command line to pass map directory in Don't bother with a default value, just require a command line param. Signed-off-by: Keith Packard --- map-server/altos-mapd/AltosMapd.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'map-server') diff --git a/map-server/altos-mapd/AltosMapd.java b/map-server/altos-mapd/AltosMapd.java index cfa1ef35..9c39adb1 100644 --- a/map-server/altos-mapd/AltosMapd.java +++ b/map-server/altos-mapd/AltosMapd.java @@ -35,7 +35,12 @@ public class AltosMapd { AltosPreferences.init(new AltosMapdPreferences()); - AltosPreferences.mapdir = new File("/home/keithp/misc/rockets/flights/maps"); + if (args.length < 1) { + System.out.printf("usage: altos-mapd \n"); + System.exit(1); + } + + AltosPreferences.mapdir = new File(args[0]); for (;;) { Socket client = server.accept(); -- cgit v1.2.3 From e7c0bcd945f8365e86e99b9d450f3a3389fa0e66 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 19:33:51 -0700 Subject: altos-mapd: Add geo-fencing for map requests. Add port and key arguments Map requests are now limited to a region within 17km of any registered launch site. The --port argument allows the listen port to be changed. The --key argument provides the name of a file containing the Google maps API key. Signed-off-by: Keith Packard --- map-server/altos-mapd/AltosMapd.java | 153 ++++++++++++++++++++++++++--- map-server/altos-mapd/AltosMapdClient.java | 3 + map-server/altos-mapd/AltosMapdServer.java | 21 +--- 3 files changed, 146 insertions(+), 31 deletions(-) (limited to 'map-server') diff --git a/map-server/altos-mapd/AltosMapd.java b/map-server/altos-mapd/AltosMapd.java index 9c39adb1..923c713e 100644 --- a/map-server/altos-mapd/AltosMapd.java +++ b/map-server/altos-mapd/AltosMapd.java @@ -16,12 +16,15 @@ package altosmapd; import java.net.*; import java.io.*; +import java.text.*; +import java.util.*; +import java.util.concurrent.*; import org.altusmetrum.altoslib_13.*; -public class AltosMapd { +public class AltosMapd implements AltosLaunchSiteListener { - public final static int port = 16717; + public static int port = 16717; public final static int maptype = AltosMap.maptype_hybrid; @@ -29,27 +32,149 @@ public class AltosMapd { public final static int scale = 1; - public static void main(final String[] args) { + public static double valid_radius = 17000; /* 17km */ + + public String map_dir = null; + public String launch_sites_file = null; + public String key_file = null; + + public void usage() { + System.out.printf("usage: altos-mapd [--mapdir ]\n" + + " [--radius [--port ] [--key ]\n"); + System.exit(1); + } + + private static Semaphore launch_sites_ready; + + private static List launch_sites; + + public void notify_launch_sites(List sites) { + synchronized (launch_sites_ready) { + if (sites != null) { + launch_sites = sites; + launch_sites_ready.release(); + } + } + } + + public static boolean check_lat_lon(double lat, double lon) { + synchronized (launch_sites_ready) { + if (launch_sites == null) { + try { + launch_sites_ready.acquire(); + } catch (InterruptedException ie) { + return false; + } + } + } + if (launch_sites == null) { + System.out.printf("No launch site data available, refusing all requests\n"); + return false; + } + + for (AltosLaunchSite site : launch_sites) { + AltosGreatCircle gc = new AltosGreatCircle(site.latitude, site.longitude, + lat, lon); + if (gc.distance <= valid_radius) + return true; + } + + return false; + } - AltosMapdServer server = new AltosMapdServer(port); + AltosMapdServer server; + + public void process(String[] args) { AltosPreferences.init(new AltosMapdPreferences()); - if (args.length < 1) { - System.out.printf("usage: altos-mapd \n"); - System.exit(1); + int skip = 1; + for (int i = 0; i < args.length; i += skip) { + skip = 1; + if (args[i].equals("--mapdir") && i < args.length-1) { + map_dir = args[i+1]; + skip = 2; + } else if (args[i].equals("--launch-sites") && i < args.length-1) { + launch_sites_file = args[i+1]; + skip = 2; + } else if (args[i].equals("--radius") && i < args.length-1) { + try { + valid_radius = AltosParse.parse_double_locale(args[i+1]); + } catch (ParseException pe) { + usage(); + } + skip = 2; + } else if (args[i].equals("--port") && i < args.length-1) { + try { + port = AltosParse.parse_int(args[i+1]); + } catch (ParseException pe) { + usage(); + } + skip = 2; + } else if (args[i].equals("--key") && i < args.length-1) { + key_file = args[i+1]; + skip = 2; + } else { + usage(); + } } - AltosPreferences.mapdir = new File(args[0]); + if (map_dir == null) + usage(); + + if (key_file != null) { + try { + BufferedReader key_reader = new BufferedReader(new FileReader(key_file)); + + String line = key_reader.readLine(); + if (line == null || line.length() != 39) { + System.out.printf("%s: invalid contents %d \"%s\"\n", + key_file, line.length(), line); + usage(); + } + key_reader.close(); + AltosMapStore.google_maps_api_key = line; + } catch (Exception e) { + System.out.printf("%s: %s\n", key_file, e.toString()); + usage(); + } + } + + AltosPreferences.mapdir = new File(map_dir); + + if (launch_sites_file != null) + AltosLaunchSites.launch_sites_url = "file://" + launch_sites_file; + + launch_sites_ready = new Semaphore(0); + + new AltosLaunchSites(this); + + try { + server = new AltosMapdServer(port); + } catch (IOException ie) { + System.out.printf("Cannot bind to port %d: %s\n", port, ie.toString()); + usage(); + } for (;;) { - Socket client = server.accept(); - if (client == null) { - System.out.printf("accept failed\n"); - continue; + try { + Socket client = server.accept(); + if (client == null) { + System.out.printf("accept failed\n"); + continue; + } + System.out.printf("got client\n"); + new AltosMapdClient(client); + } catch (Exception e) { + System.out.printf("Exception %s\n", e.toString()); } - System.out.printf("got client\n"); - new AltosMapdClient(client); } } + + public void AltosMapd() { + } + + public static void main(final String[] args) { + new AltosMapd().process(args); + } } diff --git a/map-server/altos-mapd/AltosMapdClient.java b/map-server/altos-mapd/AltosMapdClient.java index fb0c08e6..70ceae82 100644 --- a/map-server/altos-mapd/AltosMapdClient.java +++ b/map-server/altos-mapd/AltosMapdClient.java @@ -77,7 +77,10 @@ public class AltosMapdClient extends Thread implements AltosMapStoreListener { addr == null) { set_status(400); + } else if (!AltosMapd.check_lat_lon(lat, lon)) { + set_status(403); /* Forbidden */ } else { + store_ready = new Semaphore(0); System.out.printf("Fetching tile for %g %g %d\n", lat, lon, zoom); diff --git a/map-server/altos-mapd/AltosMapdServer.java b/map-server/altos-mapd/AltosMapdServer.java index 68b427f0..749edbc7 100644 --- a/map-server/altos-mapd/AltosMapdServer.java +++ b/map-server/altos-mapd/AltosMapdServer.java @@ -15,23 +15,10 @@ package altosmapd; import java.net.*; +import java.io.*; -public class AltosMapdServer { - ServerSocket socket; - - public Socket accept() { - try { - return socket.accept(); - } catch (Exception e) { - return null; - } - } - - public AltosMapdServer(int port) { - try { - socket = new ServerSocket(port, 5, InetAddress.getLoopbackAddress()); - } catch (Exception e) { - socket = null; - } +public class AltosMapdServer extends ServerSocket { + public AltosMapdServer(int port) throws IOException { + super(port, 5, InetAddress.getLoopbackAddress()); } } -- cgit v1.2.3 From 026c735393f6029d09011dba1d5c780322921921 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 22:25:48 -0600 Subject: altos-map: Retry connection to cache service Just in case the cache service gets busy, retry the connection instead of immediately failing. Signed-off-by: Keith Packard --- map-server/altos-map/AltosMap.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'map-server') diff --git a/map-server/altos-map/AltosMap.java b/map-server/altos-map/AltosMap.java index 380556f4..d78396d0 100644 --- a/map-server/altos-map/AltosMap.java +++ b/map-server/altos-map/AltosMap.java @@ -109,7 +109,17 @@ public class AltosMap { fail(400, "Missing zoom"); try { - Socket socket = new Socket(InetAddress.getLoopbackAddress(), port); + Socket socket = null; + int tries = 0; + + while (tries < 10 && socket == null) { + try { + socket = new Socket(InetAddress.getLoopbackAddress(), port); + } catch (IOException ie) { + Thread.sleep(100); + tries++; + } + } AltosJson request = new AltosJson(); -- cgit v1.2.3 From 839e3a413a60c6a61851a94cc299de701ab5c277 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 22:26:46 -0600 Subject: altos-mapd: remove debug printf Signed-off-by: Keith Packard --- map-server/altos-mapd/AltosMapd.java | 1 - 1 file changed, 1 deletion(-) (limited to 'map-server') diff --git a/map-server/altos-mapd/AltosMapd.java b/map-server/altos-mapd/AltosMapd.java index 923c713e..b4105861 100644 --- a/map-server/altos-mapd/AltosMapd.java +++ b/map-server/altos-mapd/AltosMapd.java @@ -163,7 +163,6 @@ public class AltosMapd implements AltosLaunchSiteListener { System.out.printf("accept failed\n"); continue; } - System.out.printf("got client\n"); new AltosMapdClient(client); } catch (Exception e) { System.out.printf("Exception %s\n", e.toString()); -- cgit v1.2.3 From 02adfb13297f7dffcd8edcdd3b8747cf52b2a70b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 22:27:20 -0600 Subject: altos-mapd: Clean up log messages Generate a single log message per request with remote address, parameters and result code. Signed-off-by: Keith Packard --- map-server/altos-mapd/AltosMapdClient.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'map-server') diff --git a/map-server/altos-mapd/AltosMapdClient.java b/map-server/altos-mapd/AltosMapdClient.java index 70ceae82..09833363 100644 --- a/map-server/altos-mapd/AltosMapdClient.java +++ b/map-server/altos-mapd/AltosMapdClient.java @@ -26,7 +26,10 @@ public class AltosMapdClient extends Thread implements AltosMapStoreListener { private AltosJson request; private AltosJson reply; + private int http_status; + private void set_status(int status) { + http_status = status; reply.put("status", status); } @@ -83,8 +86,6 @@ public class AltosMapdClient extends Thread implements AltosMapStoreListener { store_ready = new Semaphore(0); - System.out.printf("Fetching tile for %g %g %d\n", lat, lon, zoom); - AltosMapStore map_store = AltosMapStore.get(new AltosLatLon(lat, lon), zoom, AltosMapd.maptype, @@ -93,13 +94,10 @@ public class AltosMapdClient extends Thread implements AltosMapStoreListener { int status; if (map_store == null) { - System.out.printf("no store?\n"); status = AltosMapTile.failed; } else { map_store.add_listener(this); - System.out.printf("Waiting for tile\n"); - try { store_ready.acquire(); } catch (Exception ie) { @@ -123,6 +121,9 @@ public class AltosMapdClient extends Thread implements AltosMapStoreListener { set_status(400); } } + System.out.printf("%s: %.6f %.6f %d status %d\n", + addr, lat, lon, zoom, http_status); + } catch (Exception e) { System.out.printf("client exception %s\n", e.toString()); e.printStackTrace(System.out); @@ -140,7 +141,6 @@ public class AltosMapdClient extends Thread implements AltosMapStoreListener { socket.close(); } catch (IOException ie) { } - System.out.printf("client done\n"); } } -- cgit v1.2.3 From 1b841e14d11b3a9e7a754730b1d87b30d22f3dd4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 22:27:58 -0600 Subject: altos-mapd: Make cache service listen queue longer Just in case the service gets busy, make the listen queue longer. Signed-off-by: Keith Packard --- map-server/altos-mapd/AltosMapdServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'map-server') diff --git a/map-server/altos-mapd/AltosMapdServer.java b/map-server/altos-mapd/AltosMapdServer.java index 749edbc7..db7f7dc1 100644 --- a/map-server/altos-mapd/AltosMapdServer.java +++ b/map-server/altos-mapd/AltosMapdServer.java @@ -19,6 +19,6 @@ import java.io.*; public class AltosMapdServer extends ServerSocket { public AltosMapdServer(int port) throws IOException { - super(port, 5, InetAddress.getLoopbackAddress()); + super(port, 256, InetAddress.getLoopbackAddress()); } } -- cgit v1.2.3 From a203aa6e3ed67337b752f939da956856e208c28b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 22:28:36 -0600 Subject: altos-mapd: Install altosmapd.jar file Signed-off-by: Keith Packard --- map-server/altos-mapd/Makefile.am | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'map-server') diff --git a/map-server/altos-mapd/Makefile.am b/map-server/altos-mapd/Makefile.am index c099d1c7..a3fd196e 100644 --- a/map-server/altos-mapd/Makefile.am +++ b/map-server/altos-mapd/Makefile.am @@ -22,6 +22,12 @@ FATJAR=altosmapd-fat.jar all-local: classes/altosmapd $(JAR) altos-mapd altos-mapd-test altos-mapd-jdb +install-altosmapdJAVA: altosmapd.jar + @$(NORMAL_INSTALL) + test -z "$(altosmapddir)" || $(MKDIR_P) "$(DESTDIR)$(altosmapddir)" + echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosmapddir)/altosdmap.jar'"; \ + $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosmapddir)" + classes/altosmapd: mkdir -p classes/altosmapd -- cgit v1.2.3 From 64d6689f97dfbed13533350dcb75a0a6a3d11c78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 21:32:12 -0700 Subject: altos-map: Support version query from application Signed-off-by: Keith Packard --- map-server/altos-map/AltosMap.java | 103 ++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 46 deletions(-) (limited to 'map-server') diff --git a/map-server/altos-map/AltosMap.java b/map-server/altos-map/AltosMap.java index d78396d0..ad0a4f5f 100644 --- a/map-server/altos-map/AltosMap.java +++ b/map-server/altos-map/AltosMap.java @@ -25,6 +25,8 @@ public class AltosMap { public final static int port = 16717; + public final static String protocol_version = "1.0.0"; + String query_string; String remote_addr; @@ -80,6 +82,7 @@ public class AltosMap { double lon = AltosLib.MISSING; double lat = AltosLib.MISSING; int zoom = AltosLib.MISSING; + String version = null; try { for (String query : queries) { @@ -93,6 +96,8 @@ public class AltosMap { lat = AltosParse.parse_double_net(value); else if (name.equals("zoom")) zoom = AltosParse.parse_int(value); + else if (name.equals("version")) + version = value; else fail(400, String.format("Extra query param \"%s\"", query)); } @@ -101,62 +106,68 @@ public class AltosMap { fail(400, String.format("Invalid query: %s", pe.toString())); } - if (lon == AltosLib.MISSING) - fail(400, "Missing longitude"); - if (lat == AltosLib.MISSING) - fail(400, "Missing latitude"); - if (zoom == AltosLib.MISSING) - fail(400, "Missing zoom"); - - try { - Socket socket = null; - int tries = 0; + if (version != null) { + System.out.printf("Content-Type: text/plain\n"); + System.out.printf("\n"); + System.out.printf("%s\n", protocol_version); + } else { + if (lon == AltosLib.MISSING) + fail(400, "Missing longitude"); + if (lat == AltosLib.MISSING) + fail(400, "Missing latitude"); + if (zoom == AltosLib.MISSING) + fail(400, "Missing zoom"); - while (tries < 10 && socket == null) { - try { - socket = new Socket(InetAddress.getLoopbackAddress(), port); - } catch (IOException ie) { - Thread.sleep(100); - tries++; + try { + Socket socket = null; + int tries = 0; + + while (tries < 10 && socket == null) { + try { + socket = new Socket(InetAddress.getLoopbackAddress(), port); + } catch (IOException ie) { + Thread.sleep(100); + tries++; + } } - } - AltosJson request = new AltosJson(); + AltosJson request = new AltosJson(); - request.put("lat", lat); - request.put("lon", lon); - request.put("zoom", zoom); - request.put("remote_addr", remote_addr); + request.put("lat", lat); + request.put("lon", lon); + request.put("zoom", zoom); + request.put("remote_addr", remote_addr); - Writer writer = new PrintWriter(socket.getOutputStream()); - request.write(writer); - writer.flush(); + Writer writer = new PrintWriter(socket.getOutputStream()); + request.write(writer); + writer.flush(); - AltosJson reply = AltosJson.fromInputStream(socket.getInputStream()); + AltosJson reply = AltosJson.fromInputStream(socket.getInputStream()); - int status = reply.get_int("status", 400); + int status = reply.get_int("status", 400); - if (status != 200) - fail(status, "Bad cache status"); + if (status != 200) + fail(status, "Bad cache status"); - String filename = reply.get_string("filename", null); - try { - File file = new File(filename); - long length = file.length(); - FileInputStream in = new FileInputStream(file); - String content_type = reply.get_string("content_type", null); - System.out.printf("Content-Type: %s\n", content_type); - System.out.printf("Content-Length: %d\n", file.length()); - System.out.printf("\n"); - byte[] buf = new byte[4096]; - int bytes_read; - while ((bytes_read = in.read(buf)) > 0) - System.out.write(buf); - } catch (IOException ie) { - fail(404, String.format("IO Exception: %s", ie.toString())); + String filename = reply.get_string("filename", null); + try { + File file = new File(filename); + long length = file.length(); + FileInputStream in = new FileInputStream(file); + String content_type = reply.get_string("content_type", null); + System.out.printf("Content-Type: %s\n", content_type); + System.out.printf("Content-Length: %d\n", file.length()); + System.out.printf("\n"); + byte[] buf = new byte[4096]; + int bytes_read; + while ((bytes_read = in.read(buf)) > 0) + System.out.write(buf); + } catch (IOException ie) { + fail(404, String.format("IO Exception: %s", ie.toString())); + } + } catch (Exception e) { + fail(404, String.format("Exception %s", e.toString())); } - } catch (Exception e) { - fail(404, String.format("Exception %s", e.toString())); } } -- cgit v1.2.3 From 417ec9c2a42bbe74f3aba4d00b42eb14dd6eb079 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2018 23:22:26 -0600 Subject: altos-mapd: Install systemd service file and defaults file This lets the map service 'just work' if enabled. Signed-off-by: Keith Packard --- map-server/altos-mapd/Makefile.am | 8 ++++++++ map-server/altos-mapd/altos-mapd-default | 3 +++ map-server/altos-mapd/altos-mapd.service | 14 ++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 map-server/altos-mapd/altos-mapd-default create mode 100644 map-server/altos-mapd/altos-mapd.service (limited to 'map-server') diff --git a/map-server/altos-mapd/Makefile.am b/map-server/altos-mapd/Makefile.am index a3fd196e..39f67536 100644 --- a/map-server/altos-mapd/Makefile.am +++ b/map-server/altos-mapd/Makefile.am @@ -22,6 +22,14 @@ FATJAR=altosmapd-fat.jar all-local: classes/altosmapd $(JAR) altos-mapd altos-mapd-test altos-mapd-jdb +defaultsdir=$(sysconfdir)/default + +defaults_DATA=altos-mapd-default + +systemddir=$(libdir)/systemd/system + +systemd_DATA=altos-mapd.service + install-altosmapdJAVA: altosmapd.jar @$(NORMAL_INSTALL) test -z "$(altosmapddir)" || $(MKDIR_P) "$(DESTDIR)$(altosmapddir)" diff --git a/map-server/altos-mapd/altos-mapd-default b/map-server/altos-mapd/altos-mapd-default new file mode 100644 index 00000000..40d283a2 --- /dev/null +++ b/map-server/altos-mapd/altos-mapd-default @@ -0,0 +1,3 @@ +MAPKEY=/home/altos-mapd/google-maps-api-key +MAPDIR=/home/altos-mapd/maps +LAUNCHSITES=/var/www/html/launch-sites.txt diff --git a/map-server/altos-mapd/altos-mapd.service b/map-server/altos-mapd/altos-mapd.service new file mode 100644 index 00000000..d6f01da1 --- /dev/null +++ b/map-server/altos-mapd/altos-mapd.service @@ -0,0 +1,14 @@ +[Unit] +Description=AltOS Map Cache +Requires=network-online.target +After=network-online.target + +[Service] +Type=simple +User=altos-mapd +Restart=always +EnvironmentFile=/etc/default/altos-mapd-default +ExecStart=/usr/bin/altos-mapd --key $MAPKEY --mapdir $MAPDIR --launch-sites $LAUNCHSITES + +[Install] +WantedBy=multi-user.target -- cgit v1.2.3 From af678be97e419a1167a0630f28bcaba82d67929b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Oct 2018 09:22:44 -0700 Subject: map-server: Implement altos-map in C This app is all about startup time, and java starts slowly. Re-implement in C to improve server performance. Signed-off-by: Keith Packard --- configure.ac | 3 + map-server/Makefile.am | 2 +- map-server/altos-map/.gitignore | 5 - map-server/altos-map/AltosMap.java | 182 ---------------------- map-server/altos-map/Makefile.am | 64 +------- map-server/altos-map/Manifest.txt | 2 - map-server/altos-map/altos-map-fake | 6 - map-server/altos-map/altos-map.c | 286 ++++++++++++++++++++++++++++++++++ map-server/altos-map/altos-mapc-fake | 6 + map-server/altos-mapj/.gitignore | 6 + map-server/altos-mapj/AltosMap.java | 182 ++++++++++++++++++++++ map-server/altos-mapj/Makefile.am | 62 ++++++++ map-server/altos-mapj/Manifest.txt | 2 + map-server/altos-mapj/altos-mapj-fake | 6 + 14 files changed, 558 insertions(+), 256 deletions(-) delete mode 100644 map-server/altos-map/AltosMap.java delete mode 100644 map-server/altos-map/Manifest.txt delete mode 100755 map-server/altos-map/altos-map-fake create mode 100644 map-server/altos-map/altos-map.c create mode 100755 map-server/altos-map/altos-mapc-fake create mode 100644 map-server/altos-mapj/.gitignore create mode 100644 map-server/altos-mapj/AltosMap.java create mode 100644 map-server/altos-mapj/Makefile.am create mode 100644 map-server/altos-mapj/Manifest.txt create mode 100755 map-server/altos-mapj/altos-mapj-fake (limited to 'map-server') 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/AltosMap.java b/map-server/altos-map/AltosMap.java deleted file mode 100644 index ad0a4f5f..00000000 --- a/map-server/altos-map/AltosMap.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright © 2018 Keith Packard - * - * 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. - */ - -package altosmap; - -import java.net.*; -import java.io.*; -import java.util.*; -import java.text.*; - -import org.altusmetrum.altoslib_13.*; - -public class AltosMap { - - public final static int port = 16717; - - public final static String protocol_version = "1.0.0"; - - String query_string; - String remote_addr; - - public String 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"; - } - } - - public void write_status(int status) { - System.out.printf("Status: %d %s\n", status, reason_string(status)); - } - - public void write_type(String type) { - System.out.printf("Content-Type: %s\n", type); - } - - public void fail(int status, String reason) { - write_status(status); - write_type("text/html"); - System.out.printf("\n"); - System.out.printf("\n"); - System.out.printf("Map Fetch Failure\n"); - System.out.printf("%s\n", reason); - System.out.printf("\n"); - System.exit(1); - } - - public void process() { - query_string = System.getenv("QUERY_STRING"); - - if (query_string == null) - fail(400, "Missing query string"); - - remote_addr = System.getenv("REMOTE_ADDR"); - - if (remote_addr == null) - fail(400, "Missing remote address"); - - String[] queries = query_string.split("&"); - - double lon = AltosLib.MISSING; - double lat = AltosLib.MISSING; - int zoom = AltosLib.MISSING; - String version = null; - - try { - for (String query : queries) { - String[] q = query.split("="); - if (q.length >= 2) { - String name = q[0]; - String value = q[1]; - if (name.equals("lon")) - lon = AltosParse.parse_double_net(value); - else if (name.equals("lat")) - lat = AltosParse.parse_double_net(value); - else if (name.equals("zoom")) - zoom = AltosParse.parse_int(value); - else if (name.equals("version")) - version = value; - else - fail(400, String.format("Extra query param \"%s\"", query)); - } - } - } catch (ParseException pe) { - fail(400, String.format("Invalid query: %s", pe.toString())); - } - - if (version != null) { - System.out.printf("Content-Type: text/plain\n"); - System.out.printf("\n"); - System.out.printf("%s\n", protocol_version); - } else { - if (lon == AltosLib.MISSING) - fail(400, "Missing longitude"); - if (lat == AltosLib.MISSING) - fail(400, "Missing latitude"); - if (zoom == AltosLib.MISSING) - fail(400, "Missing zoom"); - - try { - Socket socket = null; - int tries = 0; - - while (tries < 10 && socket == null) { - try { - socket = new Socket(InetAddress.getLoopbackAddress(), port); - } catch (IOException ie) { - Thread.sleep(100); - tries++; - } - } - - AltosJson request = new AltosJson(); - - request.put("lat", lat); - request.put("lon", lon); - request.put("zoom", zoom); - request.put("remote_addr", remote_addr); - - Writer writer = new PrintWriter(socket.getOutputStream()); - request.write(writer); - writer.flush(); - - AltosJson reply = AltosJson.fromInputStream(socket.getInputStream()); - - int status = reply.get_int("status", 400); - - if (status != 200) - fail(status, "Bad cache status"); - - String filename = reply.get_string("filename", null); - try { - File file = new File(filename); - long length = file.length(); - FileInputStream in = new FileInputStream(file); - String content_type = reply.get_string("content_type", null); - System.out.printf("Content-Type: %s\n", content_type); - System.out.printf("Content-Length: %d\n", file.length()); - System.out.printf("\n"); - byte[] buf = new byte[4096]; - int bytes_read; - while ((bytes_read = in.read(buf)) > 0) - System.out.write(buf); - } catch (IOException ie) { - fail(404, String.format("IO Exception: %s", ie.toString())); - } - } catch (Exception e) { - fail(404, String.format("Exception %s", e.toString())); - } - } - } - - public AltosMap() { - } - - public static void main(final String[] args) { - - new AltosMap().process(); - - } -} 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/Manifest.txt b/map-server/altos-map/Manifest.txt deleted file mode 100644 index 1a285b40..00000000 --- a/map-server/altos-map/Manifest.txt +++ /dev/null @@ -1,2 +0,0 @@ -Main-Class: altosmap.AltosMap -Class-Path: altoslib_13.jar diff --git a/map-server/altos-map/altos-map-fake b/map-server/altos-map/altos-map-fake deleted file mode 100755 index a78bbd64..00000000 --- a/map-server/altos-map/altos-map-fake +++ /dev/null @@ -1,6 +0,0 @@ -#!/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-map-test - 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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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("\n"); + printf("Map Fetch Failure\n"); + printf("\n"); + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + printf("\n"); + printf("\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-mapc-fake b/map-server/altos-map/altos-mapc-fake new file mode 100755 index 00000000..9e22f76f --- /dev/null +++ b/map-server/altos-map/altos-mapc-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-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-mapj/AltosMap.java b/map-server/altos-mapj/AltosMap.java new file mode 100644 index 00000000..ad0a4f5f --- /dev/null +++ b/map-server/altos-mapj/AltosMap.java @@ -0,0 +1,182 @@ +/* + * Copyright © 2018 Keith Packard + * + * 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. + */ + +package altosmap; + +import java.net.*; +import java.io.*; +import java.util.*; +import java.text.*; + +import org.altusmetrum.altoslib_13.*; + +public class AltosMap { + + public final static int port = 16717; + + public final static String protocol_version = "1.0.0"; + + String query_string; + String remote_addr; + + public String 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"; + } + } + + public void write_status(int status) { + System.out.printf("Status: %d %s\n", status, reason_string(status)); + } + + public void write_type(String type) { + System.out.printf("Content-Type: %s\n", type); + } + + public void fail(int status, String reason) { + write_status(status); + write_type("text/html"); + System.out.printf("\n"); + System.out.printf("\n"); + System.out.printf("Map Fetch Failure\n"); + System.out.printf("%s\n", reason); + System.out.printf("\n"); + System.exit(1); + } + + public void process() { + query_string = System.getenv("QUERY_STRING"); + + if (query_string == null) + fail(400, "Missing query string"); + + remote_addr = System.getenv("REMOTE_ADDR"); + + if (remote_addr == null) + fail(400, "Missing remote address"); + + String[] queries = query_string.split("&"); + + double lon = AltosLib.MISSING; + double lat = AltosLib.MISSING; + int zoom = AltosLib.MISSING; + String version = null; + + try { + for (String query : queries) { + String[] q = query.split("="); + if (q.length >= 2) { + String name = q[0]; + String value = q[1]; + if (name.equals("lon")) + lon = AltosParse.parse_double_net(value); + else if (name.equals("lat")) + lat = AltosParse.parse_double_net(value); + else if (name.equals("zoom")) + zoom = AltosParse.parse_int(value); + else if (name.equals("version")) + version = value; + else + fail(400, String.format("Extra query param \"%s\"", query)); + } + } + } catch (ParseException pe) { + fail(400, String.format("Invalid query: %s", pe.toString())); + } + + if (version != null) { + System.out.printf("Content-Type: text/plain\n"); + System.out.printf("\n"); + System.out.printf("%s\n", protocol_version); + } else { + if (lon == AltosLib.MISSING) + fail(400, "Missing longitude"); + if (lat == AltosLib.MISSING) + fail(400, "Missing latitude"); + if (zoom == AltosLib.MISSING) + fail(400, "Missing zoom"); + + try { + Socket socket = null; + int tries = 0; + + while (tries < 10 && socket == null) { + try { + socket = new Socket(InetAddress.getLoopbackAddress(), port); + } catch (IOException ie) { + Thread.sleep(100); + tries++; + } + } + + AltosJson request = new AltosJson(); + + request.put("lat", lat); + request.put("lon", lon); + request.put("zoom", zoom); + request.put("remote_addr", remote_addr); + + Writer writer = new PrintWriter(socket.getOutputStream()); + request.write(writer); + writer.flush(); + + AltosJson reply = AltosJson.fromInputStream(socket.getInputStream()); + + int status = reply.get_int("status", 400); + + if (status != 200) + fail(status, "Bad cache status"); + + String filename = reply.get_string("filename", null); + try { + File file = new File(filename); + long length = file.length(); + FileInputStream in = new FileInputStream(file); + String content_type = reply.get_string("content_type", null); + System.out.printf("Content-Type: %s\n", content_type); + System.out.printf("Content-Length: %d\n", file.length()); + System.out.printf("\n"); + byte[] buf = new byte[4096]; + int bytes_read; + while ((bytes_read = in.read(buf)) > 0) + System.out.write(buf); + } catch (IOException ie) { + fail(404, String.format("IO Exception: %s", ie.toString())); + } + } catch (Exception e) { + fail(404, String.format("Exception %s", e.toString())); + } + } + } + + public AltosMap() { + } + + public static void main(final String[] args) { + + new AltosMap().process(); + + } +} 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-mapj/Manifest.txt b/map-server/altos-mapj/Manifest.txt new file mode 100644 index 00000000..1a285b40 --- /dev/null +++ b/map-server/altos-mapj/Manifest.txt @@ -0,0 +1,2 @@ +Main-Class: altosmap.AltosMap +Class-Path: altoslib_13.jar 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 + -- cgit v1.2.3 From 6f911b92652de890ebff67b3b28f21a36f300ebf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Oct 2018 10:03:31 -0700 Subject: altos-mapd: Handle clients failing to send valid JSON Just bail if the data we receive doesn't generate a json value. Signed-off-by: Keith Packard --- map-server/altos-mapd/AltosMapdClient.java | 95 ++++++++++++++++-------------- 1 file changed, 50 insertions(+), 45 deletions(-) (limited to 'map-server') diff --git a/map-server/altos-mapd/AltosMapdClient.java b/map-server/altos-mapd/AltosMapdClient.java index 09833363..19174088 100644 --- a/map-server/altos-mapd/AltosMapdClient.java +++ b/map-server/altos-mapd/AltosMapdClient.java @@ -69,61 +69,66 @@ public class AltosMapdClient extends Thread implements AltosMapStoreListener { try { request = AltosJson.fromInputStream(socket.getInputStream()); - double lat = request.get_double("lat", AltosLib.MISSING); - double lon = request.get_double("lon", AltosLib.MISSING); - int zoom = request.get_int("zoom", AltosLib.MISSING); - String addr = request.get_string("remote_addr", null); - - if (lat == AltosLib.MISSING || - lon == AltosLib.MISSING || - zoom == AltosLib.MISSING || - addr == null) - { + if (request == null) { set_status(400); - } else if (!AltosMapd.check_lat_lon(lat, lon)) { - set_status(403); /* Forbidden */ + System.out.printf("client failed %d\n", http_status); } else { - store_ready = new Semaphore(0); + double lat = request.get_double("lat", AltosLib.MISSING); + double lon = request.get_double("lon", AltosLib.MISSING); + int zoom = request.get_int("zoom", AltosLib.MISSING); + String addr = request.get_string("remote_addr", null); - AltosMapStore map_store = AltosMapStore.get(new AltosLatLon(lat, lon), - zoom, - AltosMapd.maptype, - AltosMapd.px_size, - AltosMapd.scale); - int status; - - if (map_store == null) { - status = AltosMapTile.failed; + if (lat == AltosLib.MISSING || + lon == AltosLib.MISSING || + zoom == AltosLib.MISSING || + addr == null) + { + set_status(400); + } else if (!AltosMapd.check_lat_lon(lat, lon)) { + set_status(403); /* Forbidden */ } else { - map_store.add_listener(this); - try { - store_ready.acquire(); - } catch (Exception ie) { - } + store_ready = new Semaphore(0); - status = map_store.status(); - } + AltosMapStore map_store = AltosMapStore.get(new AltosLatLon(lat, lon), + zoom, + AltosMapd.maptype, + AltosMapd.px_size, + AltosMapd.scale); + int status; - if (status == AltosMapTile.fetched || status == AltosMapTile.loaded) { - set_status(200); - set_file(map_store.file); - } else if (status == AltosMapTile.failed) { - set_status(404); - } else if (status == AltosMapTile.fetching) { - set_status(408); - } else if (status == AltosMapTile.bad_request) { - set_status(400); - } else if (status == AltosMapTile.forbidden) { - set_status(403); - } else { - set_status(400); + if (map_store == null) { + status = AltosMapTile.failed; + } else { + map_store.add_listener(this); + + try { + store_ready.acquire(); + } catch (Exception ie) { + } + + status = map_store.status(); + } + + if (status == AltosMapTile.fetched || status == AltosMapTile.loaded) { + set_status(200); + set_file(map_store.file); + } else if (status == AltosMapTile.failed) { + set_status(404); + } else if (status == AltosMapTile.fetching) { + set_status(408); + } else if (status == AltosMapTile.bad_request) { + set_status(400); + } else if (status == AltosMapTile.forbidden) { + set_status(403); + } else { + set_status(400); + } } + System.out.printf("%s: %.6f %.6f %d status %d\n", + addr, lat, lon, zoom, http_status); } - System.out.printf("%s: %.6f %.6f %d status %d\n", - addr, lat, lon, zoom, http_status); - } catch (Exception e) { System.out.printf("client exception %s\n", e.toString()); e.printStackTrace(System.out); -- cgit v1.2.3 From 581f700e08ec8a1c3bfc5a09e7186676c54a5460 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Oct 2018 10:32:48 -0700 Subject: altos-map: Switch from json FD ops to json FILE ops Older versions (in Debian stable) do not have the fd-based operations. Signed-off-by: Keith Packard --- map-server/altos-map/altos-map-fake | 5 +++++ map-server/altos-map/altos-map.c | 11 +++++++++-- map-server/altos-map/altos-mapc-fake | 6 ------ 3 files changed, 14 insertions(+), 8 deletions(-) create mode 100755 map-server/altos-map/altos-map-fake delete mode 100755 map-server/altos-map/altos-mapc-fake (limited to 'map-server') diff --git a/map-server/altos-map/altos-map-fake b/map-server/altos-map/altos-map-fake new file mode 100755 index 00000000..1bf5f8e2 --- /dev/null +++ b/map-server/altos-map/altos-map-fake @@ -0,0 +1,5 @@ +#!/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-map diff --git a/map-server/altos-map/altos-map.c b/map-server/altos-map/altos-map.c index 690ec728..38701076 100644 --- a/map-server/altos-map/altos-map.c +++ b/map-server/altos-map/altos-map.c @@ -226,16 +226,23 @@ int main(int argc, char **argv) if (s < 0) fail(408, "Cannot connect AltOS map daemon"); + FILE *sf = fdopen(s, "r+"); + + if (sf == NULL) + fail(400, "allocation failure"); + 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) + if (json_dumpf(request, sf, 0) < 0) fail(400, "Cannot write JSON request"); + fflush(sf); + json_error_t error; - json_t *reply = json_loadfd(s, 0, &error); + json_t *reply = json_loadf(sf, 0, &error); if (!reply) fail(400, "Cannot read JSON reply"); diff --git a/map-server/altos-map/altos-mapc-fake b/map-server/altos-map/altos-mapc-fake deleted file mode 100755 index 9e22f76f..00000000 --- a/map-server/altos-map/altos-mapc-fake +++ /dev/null @@ -1,6 +0,0 @@ -#!/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-mapc - -- cgit v1.2.3 From e7e1e805f1358052b33103a2ffdd4e9c435c8650 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Oct 2018 14:08:30 -0600 Subject: altos-mapd: Check nearest portion of tile to launch site We limit tile queries to those within 17km of a known launch site. Change the check to look at the portion of the tile nearest each launch site, instead of only checking the center location of the tile. Signed-off-by: Keith Packard --- map-server/altos-mapd/AltosMapd.java | 46 ++++++++++++++++++++++++++++-- map-server/altos-mapd/AltosMapdClient.java | 2 +- 2 files changed, 45 insertions(+), 3 deletions(-) (limited to 'map-server') diff --git a/map-server/altos-mapd/AltosMapd.java b/map-server/altos-mapd/AltosMapd.java index b4105861..1be1655d 100644 --- a/map-server/altos-mapd/AltosMapd.java +++ b/map-server/altos-mapd/AltosMapd.java @@ -57,7 +57,23 @@ public class AltosMapd implements AltosLaunchSiteListener { } } - public static boolean check_lat_lon(double lat, double lon) { + private static boolean west_of(double a, double b) { + double diff = b - a; + + while (diff >= 360.0) + diff -= 360.0; + while (diff <= -360.0) + diff += 360.0; + + return diff >= 0; + } + + public static boolean check_lat_lon(double lat, double lon, int zoom) { + AltosMapTransform transform = new AltosMapTransform(px_size, px_size, zoom, new AltosLatLon(lat, lon)); + + AltosLatLon upper_left = transform.screen_lat_lon(new AltosPointInt(0, 0)); + AltosLatLon lower_right = transform.screen_lat_lon(new AltosPointInt(px_size, px_size)); + synchronized (launch_sites_ready) { if (launch_sites == null) { try { @@ -73,8 +89,34 @@ public class AltosMapd implements AltosLaunchSiteListener { } for (AltosLaunchSite site : launch_sites) { + + /* Figure out which point in the tile to + * measure to the site That's one of the edges + * or the site location depend on where the + * site is in relation to the tile + */ + + double check_lon; + + if (west_of(site.longitude, upper_left.lon)) + check_lon = upper_left.lon; + else if (west_of(lower_right.lon, site.longitude)) + check_lon = lower_right.lon; + else + check_lon = site.longitude; + + double check_lat; + + if (site.latitude < lower_right.lat) + check_lat = lower_right.lat; + else if (upper_left.lat < site.latitude) + check_lat = upper_left.lat; + else + check_lat = site.latitude; + AltosGreatCircle gc = new AltosGreatCircle(site.latitude, site.longitude, - lat, lon); + check_lat, check_lon); + if (gc.distance <= valid_radius) return true; } diff --git a/map-server/altos-mapd/AltosMapdClient.java b/map-server/altos-mapd/AltosMapdClient.java index 19174088..6c95da8f 100644 --- a/map-server/altos-mapd/AltosMapdClient.java +++ b/map-server/altos-mapd/AltosMapdClient.java @@ -85,7 +85,7 @@ public class AltosMapdClient extends Thread implements AltosMapStoreListener { addr == null) { set_status(400); - } else if (!AltosMapd.check_lat_lon(lat, lon)) { + } else if (!AltosMapd.check_lat_lon(lat, lon, zoom)) { set_status(403); /* Forbidden */ } else { -- cgit v1.2.3 From 746ad2c385046c77831b43291ef4335a11e5bfab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Oct 2018 16:28:32 -0600 Subject: altos-mapd: Add --max-zoom to limit tile loading. Set default to 15. This ensures that we won't end up serving huge numbers of high resolution images. Signed-off-by: Keith Packard --- map-server/altos-mapd/AltosMapd.java | 16 +++++++++++++++- map-server/altos-mapd/altos-mapd-default | 1 + map-server/altos-mapd/altos-mapd.service | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'map-server') diff --git a/map-server/altos-mapd/AltosMapd.java b/map-server/altos-mapd/AltosMapd.java index 1be1655d..29528541 100644 --- a/map-server/altos-mapd/AltosMapd.java +++ b/map-server/altos-mapd/AltosMapd.java @@ -32,6 +32,8 @@ public class AltosMapd implements AltosLaunchSiteListener { public final static int scale = 1; + public static int max_zoom = 17; + public static double valid_radius = 17000; /* 17km */ public String map_dir = null; @@ -40,7 +42,8 @@ public class AltosMapd implements AltosLaunchSiteListener { public void usage() { System.out.printf("usage: altos-mapd [--mapdir ]\n" + - " [--radius [--port ] [--key ]\n"); + " [--radius [--port ] [--key ]\n" + + " [--max-zoom \n"); System.exit(1); } @@ -69,6 +72,10 @@ public class AltosMapd implements AltosLaunchSiteListener { } public static boolean check_lat_lon(double lat, double lon, int zoom) { + + if (zoom > max_zoom) + return false; + AltosMapTransform transform = new AltosMapTransform(px_size, px_size, zoom, new AltosLatLon(lat, lon)); AltosLatLon upper_left = transform.screen_lat_lon(new AltosPointInt(0, 0)); @@ -156,6 +163,13 @@ public class AltosMapd implements AltosLaunchSiteListener { } else if (args[i].equals("--key") && i < args.length-1) { key_file = args[i+1]; skip = 2; + } else if (args[i].equals("--max-zoom") && i < args.length-1) { + try { + max_zoom = AltosParse.parse_int(args[i+1]); + } catch (ParseException pe) { + usage(); + } + skip = 2; } else { usage(); } diff --git a/map-server/altos-mapd/altos-mapd-default b/map-server/altos-mapd/altos-mapd-default index 40d283a2..1611f0b6 100644 --- a/map-server/altos-mapd/altos-mapd-default +++ b/map-server/altos-mapd/altos-mapd-default @@ -1,3 +1,4 @@ MAPKEY=/home/altos-mapd/google-maps-api-key MAPDIR=/home/altos-mapd/maps LAUNCHSITES=/var/www/html/launch-sites.txt +MAXZOOM=17 diff --git a/map-server/altos-mapd/altos-mapd.service b/map-server/altos-mapd/altos-mapd.service index d6f01da1..ba263c2a 100644 --- a/map-server/altos-mapd/altos-mapd.service +++ b/map-server/altos-mapd/altos-mapd.service @@ -8,7 +8,7 @@ Type=simple User=altos-mapd Restart=always EnvironmentFile=/etc/default/altos-mapd-default -ExecStart=/usr/bin/altos-mapd --key $MAPKEY --mapdir $MAPDIR --launch-sites $LAUNCHSITES +ExecStart=/usr/bin/altos-mapd --key $MAPKEY --mapdir $MAPDIR --launch-sites $LAUNCHSITES --max-zoom $MAXZOOM [Install] WantedBy=multi-user.target -- cgit v1.2.3