inline void SkyLinesTracking::Client::OnWaveReceived(const WaveResponsePacket &packet, size_t length) { if (length < sizeof(packet)) return; const unsigned n = packet.wave_count; ConstBuffer<Wave> waves((const Wave *)(&packet + 1), n); if (length != sizeof(packet) + waves.size * sizeof(waves.front())) return; for (const auto &wave : waves) handler->OnWave(FromBE32(wave.time), ImportGeoPoint(wave.a), ImportGeoPoint(wave.b)); }
inline void SkyLinesTracking::Client::OnThermalReceived(const ThermalResponsePacket &packet, size_t length) { if (length < sizeof(packet)) return; const unsigned n = packet.thermal_count; ConstBuffer<Thermal> thermals((const Thermal *)(&packet + 1), n); if (length != sizeof(packet) + thermals.size * sizeof(thermals.front())) return; for (const auto &thermal : thermals) handler->OnThermal(FromBE32(thermal.time), AGeoPoint(ImportGeoPoint(thermal.bottom_location), FromBE16(thermal.bottom_altitude)), AGeoPoint(ImportGeoPoint(thermal.top_location), FromBE16(thermal.top_altitude)), FromBE16(thermal.lift) / 256.); }
inline void SkyLinesTracking::Client::OnTrafficReceived(const TrafficResponsePacket &packet, size_t length) { if (length < sizeof(packet)) return; const unsigned n = packet.traffic_count; const ConstBuffer<TrafficResponsePacket::Traffic> list((const TrafficResponsePacket::Traffic *)(&packet + 1), n); if (length != sizeof(packet) + n * sizeof(list.front())) return; for (const auto &traffic : list) handler->OnTraffic(FromBE32(traffic.pilot_id), FromBE32(traffic.time), ImportGeoPoint(traffic.location), (int16_t)FromBE16(traffic.altitude)); }
inline void Server::OnDatagramReceived(Client &&client, void *data, size_t length) { Header &header = *(Header *)data; if (length < sizeof(header)) return; const uint16_t received_crc = FromBE16(header.crc); header.crc = 0; const uint16_t calculated_crc = UpdateCRC16CCITT(data, length, 0); if (received_crc != calculated_crc) return; client.key = FromBE64(header.key); const auto &ping = *(const PingPacket *)data; const auto &fix = *(const FixPacket *)data; const auto &traffic = *(const TrafficRequestPacket *)data; const auto &user_name = *(const UserNameRequestPacket *)data; const auto &wave = ((const WaveSubmitPacket *)data)->wave; const auto &thermal = ((const ThermalSubmitPacket *)data)->thermal; switch ((Type)FromBE16(header.type)) { case PING: if (length < sizeof(ping)) return; OnPing(client, FromBE16(ping.id)); break; case FIX: if (length < sizeof(fix)) return; OnFix(client, ImportTimeMs(fix.time), fix.flags & ToBE32(FixPacket::FLAG_LOCATION) ? ImportGeoPoint(fix.location) : ::GeoPoint::Invalid(), fix.flags & ToBE32(FixPacket::FLAG_ALTITUDE) ? FromBE16(fix.altitude) : -1); break; case TRAFFIC_REQUEST: if (length < sizeof(traffic)) return; OnTrafficRequest(client, traffic.flags & ToBE32(TrafficRequestPacket::FLAG_NEAR)); break; case USER_NAME_REQUEST: if (length < sizeof(user_name)) return; OnUserNameRequest(client, FromBE32(user_name.user_id)); break; case WAVE_SUBMIT: if (length < sizeof(wave)) return; OnWaveSubmit(client, ImportTimeMs(wave.time), ImportGeoPoint(wave.a), ImportGeoPoint(wave.b), (int16_t)FromBE16(wave.bottom_altitude), (int16_t)FromBE16(wave.top_altitude), FromBE16(wave.lift) / 256.); break; case WAVE_REQUEST: OnWaveRequest(client); break; case THERMAL_SUBMIT: if (length < sizeof(thermal)) return; OnThermalSubmit(client, ImportTimeMs(thermal.time), ImportGeoPoint(thermal.bottom_location), (int16_t)FromBE16(thermal.bottom_altitude), ImportGeoPoint(thermal.top_location), (int16_t)FromBE16(thermal.top_altitude), FromBE16(thermal.lift) / 256.); break; case THERMAL_REQUEST: OnThermalRequest(client); break; case ACK: case TRAFFIC_RESPONSE: case USER_NAME_RESPONSE: case WAVE_RESPONSE: case THERMAL_RESPONSE: /* these are server-to-client packets; ignore them */ break; } }