]> www.average.org Git - loctrkd.git/blob - gps303/__main__.py
the whole shebang is working now
[loctrkd.git] / gps303 / __main__.py
1 from logging import getLogger
2 from select import poll, POLLIN, POLLERR, POLLHUP, POLLPRI
3 from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
4 import sys
5 from time import time
6
7 from . import common
8 from .gps303proto import handle_packet, make_response, LOGIN
9 from .evstore import initdb, stow
10 from .lookaside import prepare_response
11
12 CONF = "/etc/gps303.conf"
13
14 log = getLogger("gps303")
15
16 def runserver(conf):
17     initdb(conf.get("storage", "dbfn"))
18
19     ctlsock = socket(AF_INET, SOCK_STREAM)
20     ctlsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
21     ctlsock.bind(("", conf.getint("collector", "port")))
22     ctlsock.listen(5)
23     ctlfd = ctlsock.fileno()
24     pollset = poll()
25     pollset.register(ctlfd, POLLIN | POLLERR | POLLHUP | POLLPRI)
26     clnt_dict = {}
27     while True:
28         try:
29             events = pollset.poll(1000)
30         except KeyboardInterrupt:
31             log.info("Exiting")
32             sys.exit(0)
33         for fd, ev in events:
34             if fd == ctlfd:
35                 if ev & POLLIN:
36                     clntsock, clntaddr = ctlsock.accept()
37                     clntfd = clntsock.fileno()
38                     clnt_dict[clntfd] = (clntsock, clntaddr, None)
39                     pollset.register(
40                         clntfd, POLLIN | POLLERR | POLLHUP | POLLPRI
41                     )
42                     log.debug(
43                         "accepted connection from %s as fd %d",
44                         clntaddr,
45                         clntfd,
46                     )
47                 if ev & ~POLLIN:
48                     log.debug("unexpected event on ctlfd: %s", ev)
49             else:
50                 try:
51                     clntsock, clntaddr, imei = clnt_dict[fd]
52                 except KeyError:  # this socket closed already
53                     continue
54                 if ev & POLLIN:
55                     packet = clntsock.recv(4096)
56                     when = time()
57                     if packet:
58                         msg = handle_packet(packet)
59                         log.debug("%s from %s fd %d", msg, clntaddr, fd)
60                         if isinstance(msg, LOGIN):
61                             imei = msg.imei
62                             clnt_dict[fd] = (clntsock, clntaddr, imei)
63                         stow(
64                             clntaddr,
65                             when,
66                             imei,
67                             msg.length,
68                             msg.PROTO,
69                             msg.payload,
70                         )
71                         kwargs = prepare_response(conf, msg)
72                         response = make_response(msg, **kwargs)
73                         if response:
74                             try:
75                                 # Ignore possibility of blocking
76                                 clntsock.send(make_response(msg))
77                             except OSError as e:
78                                 log.debug("sending to fd %d error %s", fd, e)
79                     else:
80                         # TODO: Also disconnect on HIBERNATION
81                         log.info("disconnect fd %d imei %s", fd, imei)
82                         pollset.unregister(fd)
83                         clntsock.close()
84                         del clnt_dict[fd]
85                 if ev & ~POLLIN:
86                     log.warning("unexpected event", ev, "on fd", fd)
87
88 if __name__.endswith("__main__"):
89     runserver(common.init(log))