]> average.org Git - loctrkd.git/blobdiff - gps303/__main__.py
make object parser and sqlite store
[loctrkd.git] / gps303 / __main__.py
diff --git a/gps303/__main__.py b/gps303/__main__.py
new file mode 100755 (executable)
index 0000000..0f6484a
--- /dev/null
@@ -0,0 +1,82 @@
+from logging import getLogger, StreamHandler, DEBUG, INFO
+from logging.handlers import SysLogHandler
+from select import poll, POLLIN, POLLERR, POLLHUP, POLLPRI
+from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
+import sys
+from time import time
+
+from .GT06mod import handle_packet, make_response, LOGIN
+from .evstore import initdb, stow
+
+PORT = 4303
+log = getLogger("gps303")
+
+if __name__.endswith("__main__"):
+    if sys.stdout.isatty():
+        log.addHandler(StreamHandler(sys.stderr))
+        log.setLevel(DEBUG)
+    else:
+        log.addHandler(SysLogHandler(address="/dev/log"))
+        log.setLevel(INFO)
+
+    initdb("/tmp/gps303.sqlite")
+
+    ctlsock = socket(AF_INET, SOCK_STREAM)
+    ctlsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
+    ctlsock.bind(("", PORT))
+    ctlsock.listen(5)
+    ctlfd = ctlsock.fileno()
+    pollset = poll()
+    pollset.register(ctlfd, POLLIN | POLLERR | POLLHUP | POLLPRI)
+    clnt_dict = {}
+    while True:
+        try:
+            events = pollset.poll(1000)
+        except KeyboardInterrupt:
+            log.info("Exiting")
+            sys.exit(0)
+        for fd, ev in events:
+            if fd == ctlfd:
+                if ev & POLLIN:
+                    clntsock, clntaddr = ctlsock.accept()
+                    clntfd = clntsock.fileno()
+                    clnt_dict[clntfd] = (clntsock, clntaddr, None)
+                    pollset.register(
+                        clntfd, POLLIN | POLLERR | POLLHUP | POLLPRI
+                    )
+                    log.debug(
+                        "accepted connection from %s as fd %d",
+                        clntaddr,
+                        clntfd,
+                    )
+                if ev & ~POLLIN:
+                    log.debug("unexpected event on ctlfd: %s", ev)
+            else:
+                try:
+                    clntsock, clntaddr, imei = clnt_dict[fd]
+                except KeyError:  # this socket closed already
+                    continue
+                if ev & POLLIN:
+                    packet = clntsock.recv(4096)
+                    when = time()
+                    if packet:
+                        msg = handle_packet(packet, clntaddr, when)
+                        log.debug("%s from %s fd %d'", msg, clntaddr, fd)
+                        if isinstance(msg, LOGIN):
+                            imei = msg.imei
+                            clnt_dict[fd] = (clntsock, clntaddr, imei)
+                        stow(clntaddr, when, imei, msg.proto, msg.payload)
+                        response = make_response(msg)
+                        if response:
+                            try:
+                                # Ignore possibility of blocking
+                                clntsock.send(make_response(msg))
+                            except OSError as e:
+                                log.debug("sending to fd %d error %s", fd, e)
+                    else:
+                        log.info("disconnect fd %d imei %s", fd, imei)
+                        pollset.unregister(fd)
+                        clntsock.close()
+                        del clnt_dict[fd]
+                if ev & ~POLLIN:
+                    log.warning("unexpected event", ev, "on fd", fd)