def userNameRequestReceived(self, host, port, key, payload): """The client asks for the display name of a user account.""" if len(payload) != 8: return pilot = User.by_tracking_key(key) if pilot is None: log.err("No such pilot: %d" % key) return data = struct.unpack('!II', payload) user_id = data[0] user = User.get(user_id) if user is None: response = struct.pack('!IHHQIIIBBBBII', MAGIC, 0, TYPE_USER_NAME_RESPONSE, 0, user_id, USER_FLAG_NOT_FOUND, 0, 0, 0, 0, 0, 0, 0) response = set_crc(response) self.transport.write(response, (host, port)) return name = user.name[:64].encode('utf8', 'ignore') club_id = user.club_id or 0 response = struct.pack('!IHHQIIIBBBBII', MAGIC, 0, TYPE_USER_NAME_RESPONSE, 0, user_id, 0, club_id, len(name), 0, 0, 0, 0, 0) response += name response = set_crc(response) self.transport.write(response, (host, port))
def trafficRequestReceived(self, host, port, key, payload): if len(payload) != 8: return pilot = User.by_tracking_key(key) if pilot is None: log.err("No such pilot: %d" % key) return data = struct.unpack('!II', payload) or_filters = [] flags = data[0] if flags & TRAFFIC_FLAG_FOLLOWEES: subq = db.session \ .query(Follower.destination_id) \ .filter(Follower.source_id == pilot.id) \ .subquery() or_filters.append(TrackingFix.pilot_id.in_(subq)) if flags & TRAFFIC_FLAG_CLUB: subq = db.session \ .query(User.id) \ .filter(User.club_id == pilot.club_id) \ .subquery() or_filters.append(TrackingFix.pilot_id.in_(subq)) if len(or_filters) == 0: return query = TrackingFix.query() \ .distinct(TrackingFix.pilot_id) \ .filter(and_(TrackingFix.time >= datetime.utcnow() - timedelta(hours=2), TrackingFix.pilot_id != pilot.id, TrackingFix.location_wkt != None, TrackingFix.altitude != None, or_(*or_filters))) \ .order_by(TrackingFix.pilot_id, TrackingFix.time.desc()) \ .limit(32) response = '' count = 0 for fix in query: location = fix.location if location is None: continue t = fix.time t = t.hour * 3600000 + t.minute * 60000 + t.second * 1000 + t.microsecond / 1000 response += struct.pack('!IIiihHI', fix.pilot_id, t, int(location.latitude * 1000000), int(location.longitude * 1000000), int(fix.altitude), 0, 0) count += 1 response = struct.pack('!HBBI', 0, 0, count, 0) + response response = struct.pack('!IHHQ', MAGIC, 0, TYPE_TRAFFIC_RESPONSE, 0) + response response = set_crc(response) self.transport.write(response, (host, port))
def test_ping_with_key(server, test_user): """ Tracking server can query by tracking key """ # Create fake ping message ping_id = 42 message = struct.pack("!IHHQHHI", _server.MAGIC, 0, _server.TYPE_PING, test_user.tracking_key, ping_id, 0, 0) message = set_crc(message) # Create mockup function def check_pong(data, host_port): # Make sure the host and port match up assert host_port == HOST_PORT # Check if this is a valid message assert len(data) >= 16 header = struct.unpack("!IHHQ", data[:16]) assert header[0] == _server.MAGIC assert check_crc(data) assert header[2] == _server.TYPE_ACK ping_id2, _, flags = struct.unpack("!HHI", data[16:]) assert ping_id2 == ping_id assert not (flags & _server.FLAG_ACK_BAD_KEY) # Connect mockup function to tracking server server.socket = Mock() server.socket.sendto = Mock(side_effect=check_pong) # Send fake ping message server.handle(message, HOST_PORT) # Check that mockup function was called assert server.socket.sendto.called
def create_fix_message( self, tracking_key, time, latitude=None, longitude=None, track=None, ground_speed=None, airspeed=None, altitude=None, vario=None, enl=None): flags = 0 if latitude is None or longitude is None: latitude = 0 longitude = 0 else: latitude *= 1000000 longitude *= 1000000 flags |= server.FLAG_LOCATION if track is None: track = 0 else: flags |= server.FLAG_TRACK if ground_speed is None: ground_speed = 0 else: ground_speed *= 16 flags |= server.FLAG_GROUND_SPEED if airspeed is None: airspeed = 0 else: airspeed *= 16 flags |= server.FLAG_AIRSPEED if altitude is None: altitude = 0 else: flags |= server.FLAG_ALTITUDE if vario is None: vario = 0 else: vario *= 256 flags |= server.FLAG_VARIO if enl is None: enl = 0 else: flags |= server.FLAG_ENL message = struct.pack( '!IHHQIIiiIHHHhhH', server.MAGIC, 0, server.TYPE_FIX, tracking_key, flags, int(time), int(latitude), int(longitude), 0, int(track), int(ground_speed), int(airspeed), int(altitude), int(vario), int(enl)) return set_crc(message)
def userNameRequestReceived(self, host, port, key, payload): """The client asks for the display name of a user account.""" if len(payload) != 8: return pilot = User.by_tracking_key(key) if pilot is None: log("%s USER_NAME_REQUEST unknown pilot (key: %x)" % (host, key)) return data = struct.unpack('!II', payload) user_id = data[0] user = User.get(user_id) if user is None: response = struct.pack('!IHHQIIIBBBBII', MAGIC, 0, TYPE_USER_NAME_RESPONSE, 0, user_id, USER_FLAG_NOT_FOUND, 0, 0, 0, 0, 0, 0, 0) response = set_crc(response) self.transport.write(response, (host, port)) log("%s, USER_NAME_REQUEST %s -> NOT_FOUND" % (host, unicode(pilot).encode('utf8', 'ignore'))) return name = user.name[:64].encode('utf8', 'ignore') club_id = user.club_id or 0 response = struct.pack('!IHHQIIIBBBBII', MAGIC, 0, TYPE_USER_NAME_RESPONSE, 0, user_id, 0, club_id, len(name), 0, 0, 0, 0, 0) response += name response = set_crc(response) self.socket.sendto(response, (host, port)) log("%s USER_NAME_REQUEST %s -> %s" % (host, unicode(pilot).encode('utf8', 'ignore'), unicode(user).encode('utf8', 'ignore')))
def username_request_received(self, host, port, key, payload): """The client asks for the display name of a user account.""" if len(payload) != 8: return pilot = User.by_tracking_key(key) if pilot is None: log("%s USER_NAME_REQUEST unknown pilot (key: %x)" % (host, key)) return data = struct.unpack('!II', payload) user_id = data[0] user = User.get(user_id) if user is None: response = struct.pack('!IHHQIIIBBBBII', MAGIC, 0, TYPE_USER_NAME_RESPONSE, 0, user_id, USER_FLAG_NOT_FOUND, 0, 0, 0, 0, 0, 0, 0) response = set_crc(response) self.transport.write(response, (host, port)) log("%s, USER_NAME_REQUEST %s -> NOT_FOUND" % (host, pilot.name.encode('utf8', 'ignore'))) return name = user.name[:64].encode('utf8', 'ignore') club_id = user.club_id or 0 response = struct.pack('!IHHQIIIBBBBII', MAGIC, 0, TYPE_USER_NAME_RESPONSE, 0, user_id, 0, club_id, len(name), 0, 0, 0, 0, 0) response += name response = set_crc(response) self.socket.sendto(response, (host, port)) log("%s USER_NAME_REQUEST %s -> %s" % (host, pilot.name.encode('utf8', 'ignore'), user.name.encode('utf8', 'ignore')))
def pingReceived(self, host, port, key, payload): if len(payload) != 8: return id, reserved, reserved2 = struct.unpack('!HHI', payload) flags = 0 pilot = User.by_tracking_key(key) if not pilot: flags |= FLAG_ACK_BAD_KEY data = struct.pack('!IHHQHHI', MAGIC, 0, TYPE_ACK, 0, id, 0, flags) data = set_crc(data) self.transport.write(data, (host, port))
def pingReceived(self, host, port, key, payload): if len(payload) != 8: return id, reserved, reserved2 = struct.unpack('!HHI', payload) flags = 0 pilot = User.by_tracking_key(key) if not pilot: log("%s PING unknown pilot (key: %x)" % (host, key)) flags |= FLAG_ACK_BAD_KEY else: log("%s PING %s -> PONG" % (host, unicode(pilot).encode('utf8', 'ignore'))) data = struct.pack('!IHHQHHI', MAGIC, 0, TYPE_ACK, 0, id, 0, flags) data = set_crc(data) self.socket.sendto(data, (host, port))
def test_ping_with_key(server, test_user): """ Tracking server can query by tracking key """ # Create fake ping message ping_id = 42 message = struct.pack( "!IHHQHHI", _server.MAGIC, 0, _server.TYPE_PING, test_user.tracking_key, ping_id, 0, 0, ) message = set_crc(message) # Create mockup function def check_pong(data, host_port): # Make sure the host and port match up assert host_port == HOST_PORT # Check if this is a valid message assert len(data) >= 16 header = struct.unpack("!IHHQ", data[:16]) assert header[0] == _server.MAGIC assert check_crc(data) assert header[2] == _server.TYPE_ACK ping_id2, _, flags = struct.unpack("!HHI", data[16:]) assert ping_id2 == ping_id assert not (flags & _server.FLAG_ACK_BAD_KEY) # Connect mockup function to tracking server server.socket = Mock() server.socket.sendto = Mock(side_effect=check_pong) # Send fake ping message server.handle(message, HOST_PORT) # Check that mockup function was called assert server.socket.sendto.called
def test_ping_with_key(self): """ Tracking server can query by tracking key """ # Create fake ping message ping_id = 42 message = struct.pack('!IHHQHHI', server.MAGIC, 0, server.TYPE_PING, 123456, ping_id, 0, 0) message = set_crc(message) # Create mockup function def check_pong(data, host_port): # Make sure the host and port match up eq_(host_port, self.HOST_PORT) # Check if this is a valid message assert len(data) >= 16 header = struct.unpack('!IHHQ', data[:16]) eq_(header[0], server.MAGIC) ok_(check_crc(data)) eq_(header[2], server.TYPE_ACK) ping_id2, _, flags = struct.unpack('!HHI', data[16:]) eq_(ping_id2, ping_id) ok_(not (flags & server.FLAG_ACK_BAD_KEY)) # Connect mockup function to tracking server self.server.transport = Mock() self.server.transport.write = Mock(side_effect=check_pong) # Send fake ping message self.server.datagramReceived(message, self.HOST_PORT) # Check that mockup function was called ok_(self.server.transport.write.called)
def test_ping(self): """ Tracking server sends ACK when PING is received """ # Create fake ping message ping_id = 42 message = struct.pack('!IHHQHHI', server.MAGIC, 0, server.TYPE_PING, 0, ping_id, 0, 0) message = set_crc(message) # Create mockup function def check_pong(data, host_port): # Make sure the host and port match up assert host_port == self.HOST_PORT # Check if this is a valid message assert len(data) >= 16 header = struct.unpack('!IHHQ', data[:16]) assert header[0] == server.MAGIC assert check_crc(data) assert header[2] == server.TYPE_ACK ping_id2, _, flags = struct.unpack('!HHI', data[16:]) assert ping_id2 == ping_id assert flags & server.FLAG_ACK_BAD_KEY # Connect mockup function to tracking server self.server.socket = Mock() self.server.socket.sendto = Mock(side_effect=check_pong) # Send fake ping message self.server.handle(message, self.HOST_PORT) # Check that mockup function was called assert self.server.socket.sendto.called
def test_ping(self): """ Tracking server sends ACK when PING is received """ # Create fake ping message ping_id = 42 message = struct.pack('!IHHQHHI', server.MAGIC, 0, server.TYPE_PING, 0, ping_id, 0, 0) message = set_crc(message) # Create mockup function def check_pong(data, host_port): # Make sure the host and port match up assert host_port == self.HOST_PORT # Check if this is a valid message assert len(data) >= 16 header = struct.unpack('!IHHQ', data[:16]) assert header[0] == server.MAGIC assert check_crc(data) assert header[2] == server.TYPE_ACK ping_id2, _, flags = struct.unpack('!HHI', data[16:]) assert ping_id2 == ping_id assert flags & server.FLAG_ACK_BAD_KEY # Connect mockup function to tracking server self.server.transport = Mock() self.server.transport.write = Mock(side_effect=check_pong) # Send fake ping message self.server.datagramReceived(message, self.HOST_PORT) # Check that mockup function was called assert self.server.transport.write.called
def create_fix_message( tracking_key, time, latitude=None, longitude=None, track=None, ground_speed=None, airspeed=None, altitude=None, vario=None, enl=None, ): flags = 0 if latitude is None or longitude is None: latitude = 0 longitude = 0 else: latitude *= 1000000 longitude *= 1000000 flags |= _server.FLAG_LOCATION if track is None: track = 0 else: flags |= _server.FLAG_TRACK if ground_speed is None: ground_speed = 0 else: ground_speed *= 16 flags |= _server.FLAG_GROUND_SPEED if airspeed is None: airspeed = 0 else: airspeed *= 16 flags |= _server.FLAG_AIRSPEED if altitude is None: altitude = 0 else: flags |= _server.FLAG_ALTITUDE if vario is None: vario = 0 else: vario *= 256 flags |= _server.FLAG_VARIO if enl is None: enl = 0 else: flags |= _server.FLAG_ENL message = struct.pack( "!IHHQIIiiIHHHhhH", _server.MAGIC, 0, _server.TYPE_FIX, tracking_key, flags, int(time), int(latitude), int(longitude), 0, int(track), int(ground_speed), int(airspeed), int(altitude), int(vario), int(enl), ) return set_crc(message)
def trafficRequestReceived(self, host, port, key, payload): if len(payload) != 8: return pilot = User.by_tracking_key(key) if pilot is None: log("%s TRAFFIC_REQUEST unknown pilot (key: %x)" % (host, key)) return data = struct.unpack('!II', payload) or_filters = [] flags = data[0] if flags & TRAFFIC_FLAG_FOLLOWEES: subq = db.session \ .query(Follower.destination_id) \ .filter(Follower.source_id == pilot.id) \ .subquery() or_filters.append(TrackingFix.pilot_id.in_(subq)) if flags & TRAFFIC_FLAG_CLUB: subq = db.session \ .query(User.id) \ .filter(User.club_id == pilot.club_id) \ .subquery() or_filters.append(TrackingFix.pilot_id.in_(subq)) if len(or_filters) == 0: return # Add a db.Column to the inner query with # numbers ordered by time for each pilot row_number = db.over(db.func.row_number(), partition_by=TrackingFix.pilot_id, order_by=TrackingFix.time.desc()) # Create inner query subq = db.session \ .query(TrackingFix.id, row_number.label('row_number')) \ .join(TrackingFix.pilot) \ .filter(TrackingFix.pilot_id != pilot.id) \ .filter(TrackingFix.max_age_filter(2)) \ .filter(TrackingFix.delay_filter(User.tracking_delay_interval())) \ .filter(TrackingFix.location_wkt != None) \ .filter(TrackingFix.altitude != None) \ .filter(or_(*or_filters)) \ .subquery() # Create outer query that orders by time and # only selects the latest fix query = TrackingFix.query() \ .filter(TrackingFix.id == subq.c.id) \ .filter(subq.c.row_number == 1) \ .order_by(TrackingFix.time.desc()) \ .limit(32) response = '' count = 0 for fix in query: location = fix.location if location is None: continue t = fix.time t = t.hour * 3600000 + t.minute * 60000 + t.second * 1000 + t.microsecond / 1000 response += struct.pack('!IIiihHI', fix.pilot_id, t, int(location.latitude * 1000000), int(location.longitude * 1000000), int(fix.altitude), 0, 0) count += 1 response = struct.pack('!HBBI', 0, 0, count, 0) + response response = struct.pack('!IHHQ', MAGIC, 0, TYPE_TRAFFIC_RESPONSE, 0) + response response = set_crc(response) self.socket.sendto(response, (host, port)) log("%s TRAFFIC_REQUEST %s -> %d locations" % (host, unicode(pilot).encode('utf8', 'ignore'), count))