]> www.average.org Git - loctrkd.git/blobdiff - gps303/collector.py
collector: prevent two active clients share IMEI
[loctrkd.git] / gps303 / collector.py
index ef80cc534c0a9683f5219fc676fddb0bd0708d69..ce41cb57b1c91cdf7b3d1f656a1fe98057a672b7 100644 (file)
@@ -105,11 +105,9 @@ class Client:
                 break
             packet = self.buffer[2:frameend]
             self.buffer = self.buffer[frameend + 2 :]
-            if proto_of_message(packet) == LOGIN.PROTO:
-                self.imei = parse_message(packet).imei
-                log.info(
-                    "LOGIN from fd %d (IMEI %s)", self.sock.fileno(), self.imei
-                )
+            if len(packet) < 2:  # frameend comes too early
+                log.warning("Packet too short: %s", packet)
+                break
             msgs.append((when, self.addr, packet))
         return msgs
 
@@ -119,7 +117,7 @@ class Client:
         except OSError as e:
             log.error(
                 "Sending to fd %d (IMEI %s): %s",
-                self.sock.fileno,
+                self.sock.fileno(),
                 self.imei,
                 e,
             )
@@ -153,8 +151,23 @@ class Clients:
             return None
         result = []
         for when, peeraddr, packet in msgs:
-            if proto_of_message(packet) == LOGIN.PROTO:  # Could do blindly...
-                if clnt.imei:
+            if proto_of_message(packet) == LOGIN.PROTO:
+                msg = parse_message(packet)
+                if isinstance(msg, LOGIN):  # Can be unparseable
+                    if clnt.imei is None:
+                        clnt.imei = msg.imei
+                        log.info(
+                            "LOGIN from fd %d (IMEI %s)",
+                            clnt.sock.fileno(),
+                            clnt.imei,
+                        )
+                        oldclnt = self.by_imei.get(clnt.imei)
+                        if oldclnt is not None:
+                            log.info(
+                                "Orphaning fd %d with the same IMEI",
+                                oldclnt.sock.fileno(),
+                            )
+                            oldclnt.imei = None
                     self.by_imei[clnt.imei] = clnt
                 else:
                     log.warning(
@@ -247,9 +260,6 @@ def runserver(conf: ConfigParser, handle_hibernate: bool = True) -> None:
                 else:
                     log.debug("Stray event: %s on socket %s", fl, sk)
             # poll queue consumed, make changes now
-            for fd in tostop:
-                poller.unregister(fd)  # type: ignore
-                clients.stop(fd)
             for zmsg in tosend:
                 zpub.send(
                     Bcast(
@@ -262,6 +272,9 @@ def runserver(conf: ConfigParser, handle_hibernate: bool = True) -> None:
                 )
                 log.debug("Sending to the client: %s", zmsg)
                 clients.response(zmsg)
+            for fd in tostop:
+                poller.unregister(fd)  # type: ignore
+                clients.stop(fd)
             for clntsock, clntaddr in topoll:
                 fd = clients.add(clntsock, clntaddr)
                 poller.register(fd, flags=zmq.POLLIN)