def __init__(self, reader, writer, *, coordinator, motd, udp_protocol, udp_host, udp_port): self.r = reader self.w = writer self.coordinator = coordinator self.loop = coordinator.loop self.motd = motd self.sync_accepted = 0 self.sync_rejected = 0 self.mc_start = time.time() self.mrate_limit = 80 self.transport = writer.transport peer = self.transport.get_extra_info('peername') self.host = peer[0] self.port = peer[1] self.source_ip = peer[0] self.source_port = str(peer[1]) self.udp_protocol = udp_protocol self.udp_host = udp_host self.udp_port = udp_port self.logger = util.TaggingLogger( glogger, {'tag': '{host}:{port}'.format(host=self.host, port=self.port)}) self.receiver = None self._read_task = None self._heartbeat_task = None self._pending_traffic_update = None self._udp_key = None self._compression_methods = (('zlib2', self.handle_zlib_messages, self.write_zlib), ('zlib', self.handle_zlib_messages, self.write_raw), ('none', self.handle_line_messages, self.write_raw)) self._last_message_time = None self._compressor = zlib.compressobj(1) self._decompressor = zlib.decompressobj() self._pending_flush = None self._writebuf = [] self._requested_traffic = set() self._wanted_traffic = set() self.message_counter = 0 self.return_stats = False # start self._read_task = asyncio.ensure_future(self.handle_connection())
def __init__(self, reader, writer, *, coordinator, use_kalman_data, heartbeat_interval=30.0): peer = writer.get_extra_info('peername') self.host = peer[0] self.port = peer[1] self.logger = util.TaggingLogger( logging.getLogger("basestation"), {'tag': '{host}:{port}'.format(host=self.host, port=self.port)}) self.reader = reader self.writer = writer self.coordinator = coordinator self.use_kalman_data = use_kalman_data self.heartbeat_interval = heartbeat_interval self.last_output = time.time() self.heartbeat_task = asyncio.ensure_future(self.send_heartbeats()) self.reader_task = asyncio.ensure_future(self.read_until_eof()) self.logger.warning("Connection established") self.coordinator.add_output_handler(self.write_result)
async def process_handshake(self): deny = None rawline = await asyncio.wait_for(self.r.readline(), timeout=15.0) try: line = rawline.decode('ascii') if line.startswith('PROXY '): proxyLine = line.split(' ') self.source_ip = proxyLine[2] self.source_port = proxyLine[4] rawline = await asyncio.wait_for(self.r.readline(), timeout=15.0) line = rawline.decode('ascii') hs = ujson.loads(line) except ValueError as e: deny = 'Badly formatted handshake: ' + str(e) else: try: self.coordinator.handshake_logger.debug(line) if hs['version'] != 2 and hs['version'] != 3: raise ValueError('Unsupported version in handshake') user = str(hs['user']) uuid = hs.get('uuid') # replace bad characters with an underscore user = re.sub("[^A-Za-z0-9_.-]", r'_', user) if len(user) > 400: user = user[:400] if len(user) < 3: user = user + '_' + str(random.randrange(10,99)) if user in self.coordinator.usernames: existingReceiver = self.coordinator.usernames[user] if uuid and uuid == existingReceiver.uuid: # if we have another user with the same uuid, disconnect the existing user existingReceiver.connection.close() else: while user in self.coordinator.usernames: user = user + '_' + str(random.randrange(10,99)) peer_compression_methods = set(hs['compress']) self.compress = None for c, readmeth, writemeth in self._compression_methods: if c in peer_compression_methods: self.compress = c self.handle_messages = readmeth self.send = writemeth break if self.compress is None: raise ValueError('No mutually usable compression type') lat = float(hs['lat']) if lat < -90 or lat > 90: raise ValueError('invalid latitude, should be -90 .. 90') lon = float(hs['lon']) if lon < -180 or lon > 360: raise ValueError('invalid longitude, should be -180 .. 360') if lon > 180: lon = lon - 180 alt = float(hs['alt']) if alt < -1000 or alt > 10000: raise ValueError('invalid altitude, should be -1000 .. 10000') clock_type = str(hs.get('clock_type', 'dump1090')) self.use_return_results = bool(hs.get('return_results', False)) if self.use_return_results: return_result_format = hs.get('return_result_format', 'old') if return_result_format == 'old': self.report_mlat_position = self.report_mlat_position_old elif return_result_format == 'ecef': self.report_mlat_position = self.report_mlat_position_ecef else: raise ValueError('invalid return_result_format, should be one of "old" or "ecef"') else: self.report_mlat_position = self.report_mlat_position_discard self.use_udp = (self.udp_protocol is not None and hs.get('udp_transport', 0) == 2) conn_info = '{user} v{v} {clock_type} {cversion} {udp} {compress}'.format( user=user, v=hs['version'], cversion=hs.get("client_version", "unknown"), udp="udp" if self.use_udp else "tcp", clock_type=clock_type, compress=self.compress) self.receiver = self.coordinator.new_receiver(connection=self, uuid=uuid, user=user, auth=hs.get('auth'), clock_type=clock_type, position_llh=(lat, lon, alt), privacy=bool(hs.get('privacy', False)), connection_info=conn_info) # disabled until I get to the bottom of the odd timestamps #if False and self.receiver.clock.epoch == 'gps_midnight': # self.process_mlat = self.process_mlat_gps #else: self.process_mlat = self.process_mlat_nongps except KeyError as e: deny = 'Missing field in handshake: ' + str(e) except ValueError as e: deny = 'Bad values in handshake: ' + str(e) if deny: self.logger.warning('Handshake failed: %s', deny) self.write_raw(deny=[deny], reconnect_in=util.fuzzy(900)) return False expanded_motd = """ {motd} The multilateration server source code is available under the terms of the Affero GPL (v3 or later). You may obtain a copy of this server's source code at the following location: {agpl_url} """.format(agpl_url=config.AGPL_SERVER_CODE_URL, motd=self.motd) response = {"compress": self.compress, "reconnect_in": util.fuzzy(10), "selective_traffic": True, "heartbeat": True, "return_results": self.use_return_results, "rate_reports": True, "motd": expanded_motd} if self.use_udp: self._udp_key = self.udp_protocol.add_client(sync_handler=self.process_sync, mlat_handler=self.process_mlat) response['udp_transport'] = (self.udp_host, self.udp_port, self._udp_key) self.write_raw(**response) strange = '' if clock_type != 'dump1090' and clock_type != 'radarcape_gps': strange = 'strange clock: ' self.logger.warning("Handshake successful ({conn_info})".format(conn_info=conn_info)) self.logger = util.TaggingLogger(glogger, {'tag': '{user}'.format(user=user)}) return True