/// <summary> /// Override to provide new behavior for receipt of a complete PosiStageNet info frame /// </summary> /// <param name="header"></param> /// <param name="systemName"></param> /// <param name="infoPackets"></param> protected virtual void OnCompleteInfoFrameReceived(PsnInfoHeaderChunk header, string systemName, IReadOnlyCollection <PsnInfoPacketChunk> infoPackets) { var infoTrackerChunks = infoPackets.SelectMany(p => ((PsnInfoTrackerListChunk)p.SubChunks.Single(c => c.ChunkId == PsnInfoPacketChunkId.PsnInfoTrackerList)) .SubChunks) .ToList(); if (infoTrackerChunks.Select(c => c.TrackerId).Distinct().Count() != infoTrackerChunks.Count) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, false, "Duplicate tracker IDs in frame")); return; } if (RemoteSystemName != systemName) { RemoteSystemName = systemName; RemoteSystemNameUpdated?.Invoke(this, RemoteSystemName); } foreach (var chunk in infoTrackerChunks) { PsnInfoTrackerNameChunk trackerNameChunk = null; foreach (var subchunk in chunk.SubChunks) { switch (subchunk.ChunkId) { case PsnInfoTrackerChunkId.PsnInfoTrackerName: if (trackerNameChunk != null) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, !IsStrict, $"Tracker ID {chunk.TrackerId} has multiple tracker name chunks")); if (IsStrict) { return; } } trackerNameChunk = (PsnInfoTrackerNameChunk)subchunk; break; default: throw new ArgumentOutOfRangeException(); } } if (trackerNameChunk == null) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, !IsStrict, $"Tracker ID {chunk.TrackerId} has no tracker name chunk")); if (IsStrict) { return; } continue; } if (!_trackers.TryGetValue(chunk.TrackerId, out var tracker)) { tracker = new PsnTracker(chunk.TrackerId, trackerNameChunk.TrackerName, null, header.TimeStamp); _trackers.TryAdd(chunk.TrackerId, tracker); } else { tracker = tracker.SetTrackerName(trackerNameChunk.TrackerName); tracker = tracker.SetInfoTimeStamp(header.TimeStamp); } _trackers[chunk.TrackerId] = tracker; } TrackersUpdated?.Invoke(this, Trackers); }
/// <summary> /// Override to provide new behavior for receipt of a complete PosiStageNet info frame /// </summary> /// <param name="header"></param> /// <param name="systemName"></param> /// <param name="infoPackets"></param> protected virtual void OnCompleteInfoFrameReceived(IPEndPoint ipEndPoint, PsnInfoHeaderChunk header, string systemName, IReadOnlyCollection <PsnInfoPacketChunk> infoPackets) { var infoTrackerChunks = infoPackets.SelectMany(p => ((PsnInfoTrackerListChunk)p.SubChunks.Single(c => c.ChunkId == PsnInfoPacketChunkId.PsnInfoTrackerList)) .SubChunks) .ToList(); if (infoTrackerChunks.Select(c => c.TrackerId).Distinct().Count() != infoTrackerChunks.Count) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, false, "Duplicate tracker IDs in frame")); return; } var endPointData = getEndpointData(ipEndPoint); if (endPointData.RemoteSystemName != systemName) { string lastSystemName = systemName; endPointData.UpdateRemoteSystemName(systemName); RemoteSystemNameUpdated?.Invoke(this, new Tuple <string, EndPointData>(lastSystemName, endPointData)); } foreach (var chunk in infoTrackerChunks) { PsnInfoTrackerNameChunk trackerNameChunk = null; foreach (var subChunk in chunk.SubChunks) { switch (subChunk.ChunkId) { case PsnInfoTrackerChunkId.PsnInfoTrackerName: if (trackerNameChunk != null) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, !IsStrict, $"Tracker ID {chunk.TrackerId} has multiple tracker name chunks")); if (IsStrict) { return; } } trackerNameChunk = (PsnInfoTrackerNameChunk)subChunk; break; default: throw new ArgumentOutOfRangeException(); } } if (trackerNameChunk == null) { InvalidPacketReceived?.Invoke(this, new InvalidPacketsReceivedEventArgs(infoPackets, !IsStrict, $"Tracker ID {chunk.TrackerId} has no tracker name chunk")); if (IsStrict) { return; } continue; } if (!_endpoints.TryGetValue(ipEndPoint, out var trackerList)) { trackerList.updateTracker(chunk, trackerNameChunk, header); _endpoints.TryAdd(ipEndPoint, trackerList); } else { trackerList.updateTracker(chunk, trackerNameChunk, header); } TrackersUpdated?.Invoke(this, new TrackerUpdateEventArgs() { TrackerId = chunk.TrackerId, Data = endPointData }); } }