public void Read(CallbackRegister register, out UInt32 topic, out UInt16 revision) { #if DEBUG if (null == register) { throw new ArgumentNullException(nameof(register)); } #endif lock (Sync) { // TODO: Is lock required here? if (!IsStarted) { throw new InvalidOperationException("Not yet started."); } // Receive packet var buffer = new Byte[Mtu]; var endpoint = Server; var len = Socket.ReceiveFrom(buffer, ref endpoint); Trace.WriteLineIf(len < 1, $"Strange byte count {len}.", "client-receive-warning"); // Read header var typeCode = BitConverter.ToUInt32(buffer, 0); topic = BitConverter.ToUInt32(buffer, 4); revision = BitConverter.ToUInt16(buffer, 8); // Get the head revision for the topic if (!TopicRevisions.TryGetValue(topic, out var headRevision)) { headRevision = UInt16.MaxValue; } // If the update isn't stale... if (revision > headRevision || headRevision > UInt16.MaxValue / 4 * 3 && revision < UInt16.MaxValue / 4) { // Note topic head TopicRevisions[topic] = revision; // Read payload var payload = new ArraySegment <Byte>(buffer, 10, len - Constants.SERVERTXHEADER_LENGTH); // Queue acknowledgement AcknowledgementsPending.Enqueue(new KeyValuePair <UInt32, UInt16>(topic, revision)); SendLock.Set(); // Invoke callback register.Invoke(typeCode, payload); } else { Trace.WriteLine($"Stale update {topic}#{revision} received (head is {headRevision}). Discarded.", "client-receive"); // This occurs when packets arrive out of order Read(register, out topic, out revision); // Read again } } }
/// <summary> /// Read a message when the type is unknown. /// </summary> /// <param name="register">Register of all possible message types, and a callback for each one.</param> public void Read(CallbackRegister register) { Read(register, out var topic, out var revision); }