Ejemplo n.º 1
0
        /// <summary>
        /// Publish a message to clients.
        /// </summary>
        public void Publish <TMessage>(TMessage message, UInt32 topic) where TMessage : IExportableMessage, new()
        {
            // Handle un-publishes
            if (null == message)
            {
                TopicRecords.TryRemove(topic, out var a);
                return;
            }

            // Extract typecode
            var typeCode = message.TypeCode;

            // Extract payload
            var payload = message.Export();

            Trace.WriteLineIf(payload.Count + Constants.SERVERTXHEADER_LENGTH > Mtu, $"Publish value length exceeds MTU set in options and will probably be dropped by the network. Sending anyway. ([Header]{Constants.SERVERTXHEADER_LENGTH} + [Value]{payload.Count} > [MTU]{Mtu})", "server-publish-warning");

            lock (Sync) {
                if (IsDisposed)
                {
                    throw new ObjectDisposedException("Object disposed.");
                }

                if (!IsStarted)
                {
                    throw new InvalidOperationException("Not yet started.");
                }

                var record = new TopicRecord(); // Note that SendAfter initializes as '0000-00-00 00:00:00'

                // Calculate new revision
                if (TopicRecords.TryGetValue(topic, out var lastRecord))
                {
                    record.Revision = lastRecord.Revision;
                }
                else
                {
                    record.Revision = UInt16.MaxValue;
                }
                record.Revision++;

                // Add all subscribers as pending recipents
                record.PendingSubscribers = SubscriberRecords.Select(a => a.Key).ToArray();

                // Compose packet
                record.Packet = new Byte[Constants.SERVERTXHEADER_LENGTH + payload.Count];
                Buffer.BlockCopy(BitConverter.GetBytes(typeCode), 0, record.Packet, 0, 4);          // UInt32 typecode
                Buffer.BlockCopy(BitConverter.GetBytes(topic), 0, record.Packet, 4, 4);             // UInt32 topic
                Buffer.BlockCopy(BitConverter.GetBytes(record.Revision), 0, record.Packet, 8, 2);   // UInt16 revision
                Buffer.BlockCopy(payload.Array, payload.Offset, record.Packet, 10, payload.Count);  // Byte[?] value

                // Release topic update
                TopicRecords[topic] = record;
                SendLock.Set();
            }
        }
Ejemplo n.º 2
0
        public void Publish <TMessage>(TMessage message, UInt32 topic = 0, UInt32 channel = 0) where TMessage : IExportableMessage
        {
            // Handle un-publishes
            if (null == message)
            {
                TopicRecords.TryRemove(topic, out var a);
                return;
            }

            // Extract payload
            var payload = message.Export();

            lock (Sync) {
                if (IsDisposed)
                {
                    throw new ObjectDisposedException("Object disposed.");
                }

                // Create new topic record
                var record = new TopicRecord()
                {
                    Channel  = channel,
                    Revision = 0
                };

                // Calculate new revision
                if (TopicRecords.TryGetValue(topic, out var lastRecord))
                {
                    record.Revision = lastRecord.Revision + 1;
                }

                // Compose packet
                var packet = new Byte[Constants.SERVERTXHEADER_LENGTH + payload.Count];
                Buffer.BlockCopy(BitConverter.GetBytes(topic), 0, packet, 0, 4);            // UInt32 topic
                Buffer.BlockCopy(BitConverter.GetBytes(record.Revision), 0, packet, 4, 4);  // UInt32 revision
                Buffer.BlockCopy(payload.Array, payload.Offset, packet, 8, payload.Count);  // Byte[?] value
                record.Packet = new ArraySegment <Byte>(packet);

                // Release topic update
                TopicRecords[topic] = record;
                foreach (var subscriber in SubscriberRecords.Values)
                {
                    if (subscriber.Channels.Contains(channel))  // Over optimisation?
                    {
                        subscriber.SendLock.Set();
                    }
                }
            }
        }