summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2013-02-27 19:05:34 +0100
committerHarald Welte <laforge@gnumonks.org>2013-02-27 19:05:34 +0100
commitdd46f418be6a5f7cfc7d0d1e60f83f73edcb7743 (patch)
tree34f68f134973152059474834c08a72f4d7a60fe9
parent821f3af2ac2d77f0f15bdea02c2f3efd0e1cf419 (diff)
add new utility to take GPS and AIS messages and fwd them via UDP
this is useful if you wish to send them into gpsd, e.g.
-rw-r--r--src/util/Makefile.am7
-rw-r--r--src/util/gps_fwd.c182
2 files changed, 188 insertions, 1 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 3d87a32..3697358 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -1,7 +1,7 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -std=gnu99
-bin_PROGRAMS = libgsmd-tool cell_log
+bin_PROGRAMS = libgsmd-tool cell_log gps_fwd
libgsmd_tool_SOURCES = libgsmd-tool.c shell.c event.c pin.c atcmd.c \
$(top_srcdir)/src/gsmd/talloc.c
@@ -13,4 +13,9 @@ cell_log_SOURCES = cell_log.c \
cell_log_LDADD = $(top_builddir)/src/libgsmd/libgsmd.la
cell_log_LDFLAGS = -dynamic
+gps_fwd_SOURCES = gps_fwd.c \
+ $(top_srcdir)/src/gsmd/talloc.c
+gps_fwd_LDADD = $(top_builddir)/src/libgsmd/libgsmd.la
+gps_fwd_LDFLAGS = -dynamic
+
noinst_HEADERS = atcmd.h event.h pin.h shell.h
diff --git a/src/util/gps_fwd.c b/src/util/gps_fwd.c
new file mode 100644
index 0000000..3270c48
--- /dev/null
+++ b/src/util/gps_fwd.c
@@ -0,0 +1,182 @@
+/* GPS/AIS client extractor, forwad to gpsd via UDP
+ *
+ * (C) 2013 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <syslog.h>
+#include <stdint.h>
+#include <netdb.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/event.h>
+#include <gsmd/usock.h>
+#include <gsmd/ts0705.h>
+#include <common/linux_list.h>
+
+#ifndef __GSMD__
+#define __GSMD__
+#include <gsmd/talloc.h>
+#undef __GSMD__
+#endif
+
+static int out_fd = -1;
+static FILE *outf;
+
+static int celllog_main(struct lgsm_handle *lgsmh)
+{
+ int rc;
+ char buf[8192+1];
+ fd_set readset;
+ int gsm_fd = lgsm_fd(lgsmh);
+
+ fcntl(gsm_fd, F_SETFD, O_NONBLOCK);
+ FD_ZERO(&readset);
+
+ while (1) {
+ fd_set readset;
+ FD_SET(gsm_fd, &readset);
+
+ rc = select(gsm_fd+1, &readset, NULL, NULL, NULL);
+ if (rc < 0)
+ break;
+
+ if (FD_ISSET(gsm_fd, &readset)) {
+ /* we've received something on the gsmd socket, pass it
+ * on to the library */
+ rc = read(gsm_fd, buf, sizeof(buf));
+ if (rc <= 0) {
+ syslog(LOG_ERR, "ERROR reading from gsm_fd\n");
+ break;
+ }
+ rc = lgsm_handle_packet(lgsmh, buf, rc);
+ if (rc < 0)
+ syslog(LOG_ERR, "ERROR processing packet: %d(%s)\n", rc, strerror(-rc));
+ }
+ fflush(outf);
+ }
+ return 0;
+}
+
+static int gps_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
+{
+ int rc;
+
+ rc = fprintf(outf, "%s\r\n", aux->data);
+ if (rc < 0) {
+ syslog(LOG_ERR, "error %d during fprintf() on socket, aborting\n", rc);
+ exit(3);
+ }
+
+ return 0;
+}
+
+
+/* more or less a copy form libosmocore, we could simply make this a
+ * dependency... */
+static int out_sock_init(uint16_t family, uint16_t type, uint8_t proto,
+ const char *host, uint16_t port)
+{
+ int fd = -1, rc;
+ struct addrinfo hints, *result, *rp;
+ char portbuf[16];
+
+ sprintf(portbuf, "%u", port);
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = family;
+
+ rc = getaddrinfo(host, portbuf, &hints, &result);
+ if (rc != 0) {
+ syslog(LOG_ERR, "Error during getaddrinfo(%s:%d)\n",
+ host, port);
+ return -EINVAL;
+ }
+
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+
+ fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if (fd < 0)
+ continue;
+
+ rc = connect(fd, rp->ai_addr, rp->ai_addrlen);
+ if (rc != -1 || (rc == -1 && errno == EINPROGRESS))
+ break;
+
+ close(fd);
+ }
+ freeaddrinfo(result);
+
+ if (rp == NULL) {
+ syslog(LOG_ERR, "unable to connect socket\n");
+ return -ENODEV;
+ }
+
+ return fd;
+}
+
+int main(int argc, char **argv)
+{
+ static struct lgsm_handle *lgsmh;
+ char *host;
+ int port;
+ int rc;
+
+ printf("gps_fwd - (C) 2013 by Harald Welte <laforge@gnumonks.org>.\n"
+ "This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n");
+
+ if (argc < 3) {
+ fprintf(stderr, "You have to specify the remote hostname + port\n");
+ exit(2);
+ }
+
+ host = argv[1];
+ port = atoi(argv[2]);
+
+ openlog("gps_fwd", 0, LOG_LOCAL0);
+
+ lgsmh = lgsm_init(LGSMD_DEVICE_GSMD);
+ if (!lgsmh) {
+ fprintf(stderr, "Can't connect to gsmd\n");
+ exit(1);
+ }
+
+ lgsm_evt_handler_register(lgsmh, GSMD_EVT_GPS, &gps_handler);
+ lgsm_evt_handler_register(lgsmh, GSMD_EVT_AIS, &gps_handler);
+
+ out_fd = out_sock_init(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, host, port);
+ if (out_fd < 0)
+ exit(1);
+
+ outf = fdopen(out_fd, "w");
+
+ celllog_main(lgsmh);
+
+ exit(0);
+}
personal git repositories of Harald Welte. Your mileage may vary