- def recv(self, fd):
- clnt = by_fd[fd]
- msg = clnt.recv()
- if isinstance(msg, LOGIN):
- self.by_imei[clnt.imei] = clnt
- return clnt.imei, msg
+ def recv(
+ self, fd: int
+ ) -> Optional[List[Tuple[Optional[str], float, Tuple[str, int], bytes]]]:
+ clnt = self.by_fd[fd]
+ msgs = clnt.recv()
+ if msgs is None:
+ return None
+ result = []
+ for when, peeraddr, packet in msgs:
+ 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(
+ "Login message from %s: %s, but client imei unfilled",
+ peeraddr,
+ packet,
+ )
+ result.append((clnt.imei, when, peeraddr, packet))
+ log.debug(
+ "Received from %s (IMEI %s): %s",
+ peeraddr,
+ clnt.imei,
+ packet.hex(),
+ )
+ return result