altos-mapd: Add geo-fencing for map requests. Add port and key arguments
[fw/altos] / map-server / altos-mapd / AltosMapd.java
1 /*
2  * Copyright © 2018 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14
15 package altosmapd;
16
17 import java.net.*;
18 import java.io.*;
19 import java.text.*;
20 import java.util.*;
21 import java.util.concurrent.*;
22
23 import org.altusmetrum.altoslib_13.*;
24
25 public class AltosMapd implements AltosLaunchSiteListener {
26
27         public static int port = 16717;
28
29         public final static int maptype = AltosMap.maptype_hybrid;
30
31         public final static int px_size = 512;
32
33         public final static int scale = 1;
34
35         public static double valid_radius = 17000;      /* 17km */
36
37         public String map_dir = null;
38         public String launch_sites_file = null;
39         public String key_file = null;
40
41         public void usage() {
42                 System.out.printf("usage: altos-mapd [--mapdir <map-directory] [--launch-sites <launch-sites-file>]\n" +
43                                   "                  [--radius <valid-radius-m> [--port <port>] [--key <key-file>]\n");
44                 System.exit(1);
45         }
46
47         private static Semaphore launch_sites_ready;
48
49         private static List<AltosLaunchSite> launch_sites;
50
51         public void notify_launch_sites(List<AltosLaunchSite> sites) {
52                 synchronized (launch_sites_ready) {
53                         if (sites != null) {
54                                 launch_sites = sites;
55                                 launch_sites_ready.release();
56                         }
57                 }
58         }
59
60         public static boolean check_lat_lon(double lat, double lon) {
61                 synchronized (launch_sites_ready) {
62                         if (launch_sites == null) {
63                                 try {
64                                         launch_sites_ready.acquire();
65                                 } catch (InterruptedException ie) {
66                                         return false;
67                                 }
68                         }
69                 }
70                 if (launch_sites == null) {
71                         System.out.printf("No launch site data available, refusing all requests\n");
72                         return false;
73                 }
74
75                 for (AltosLaunchSite site : launch_sites) {
76                         AltosGreatCircle gc = new AltosGreatCircle(site.latitude, site.longitude,
77                                                                    lat, lon);
78                         if (gc.distance <= valid_radius)
79                                 return true;
80                 }
81
82                 return false;
83         }
84
85         AltosMapdServer server;
86
87         public void process(String[] args) {
88
89                 AltosPreferences.init(new AltosMapdPreferences());
90
91                 int skip = 1;
92                 for (int i = 0; i < args.length; i += skip) {
93                         skip = 1;
94                         if (args[i].equals("--mapdir") && i < args.length-1) {
95                                 map_dir = args[i+1];
96                                 skip = 2;
97                         } else if (args[i].equals("--launch-sites") && i < args.length-1) {
98                                 launch_sites_file = args[i+1];
99                                 skip = 2;
100                         } else if (args[i].equals("--radius") && i < args.length-1) {
101                                 try {
102                                         valid_radius = AltosParse.parse_double_locale(args[i+1]);
103                                 } catch (ParseException pe) {
104                                         usage();
105                                 }
106                                 skip = 2;
107                         } else if (args[i].equals("--port") && i < args.length-1) {
108                                 try {
109                                         port = AltosParse.parse_int(args[i+1]);
110                                 } catch (ParseException pe) {
111                                         usage();
112                                 }
113                                 skip = 2;
114                         } else if (args[i].equals("--key") && i < args.length-1) {
115                                 key_file = args[i+1];
116                                 skip = 2;
117                         } else {
118                                 usage();
119                         }
120                 }
121
122                 if (map_dir == null)
123                         usage();
124
125                 if (key_file != null) {
126                         try {
127                                 BufferedReader key_reader = new BufferedReader(new FileReader(key_file));
128
129                                 String line = key_reader.readLine();
130                                 if (line == null || line.length() != 39) {
131                                         System.out.printf("%s: invalid contents %d \"%s\"\n",
132                                                           key_file, line.length(), line);
133                                         usage();
134                                 }
135                                 key_reader.close();
136                                 AltosMapStore.google_maps_api_key = line;
137                         } catch (Exception e) {
138                                 System.out.printf("%s: %s\n", key_file, e.toString());
139                                 usage();
140                         }
141                 }
142
143                 AltosPreferences.mapdir = new File(map_dir);
144
145                 if (launch_sites_file != null)
146                         AltosLaunchSites.launch_sites_url = "file://" + launch_sites_file;
147
148                 launch_sites_ready = new Semaphore(0);
149
150                 new AltosLaunchSites(this);
151
152                 try {
153                         server = new AltosMapdServer(port);
154                 } catch (IOException ie) {
155                         System.out.printf("Cannot bind to port %d: %s\n", port, ie.toString());
156                         usage();
157                 }
158
159                 for (;;) {
160                         try {
161                                 Socket client = server.accept();
162                                 if (client == null) {
163                                         System.out.printf("accept failed\n");
164                                         continue;
165                                 }
166                                 System.out.printf("got client\n");
167                                 new AltosMapdClient(client);
168                         } catch (Exception e) {
169                                 System.out.printf("Exception %s\n", e.toString());
170                         }
171                 }
172         }
173
174         public void AltosMapd() {
175         }
176
177         public static void main(final String[] args) {
178                 new AltosMapd().process(args);
179         }
180 }