Example #1
0
            private void PingElapsed(object sender, NetMQTimerEventArgs e)
            {
                Assumes.NotNull(m_transmit);

                SendUdpFrame(m_transmit);
            }
Example #2
0
            private void Configure(string interfaceName, int port)
            {
                Assumes.NotNull(m_poller);
                Assumes.NotNull(m_pipe);

                // In case the beacon was configured twice
                if (m_udpSocket != null)
                {
                    m_poller.Remove(m_udpSocket);

#if NET35
                    m_udpSocket.Close();
#else
                    m_udpSocket.Dispose();
#endif
                }

                m_udpPort   = port;
                m_udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

                m_poller.Add(m_udpSocket, OnUdpReady);

                // Ask operating system for broadcast permissions on socket
                m_udpSocket.EnableBroadcast = true;

                // Allow multiple owners to bind to socket; incoming
                // messages will replicate to each owner
                m_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

                IPAddress?bindTo = null;
                IPAddress?sendTo = null;

                if (interfaceName == "*")
                {
                    bindTo = IPAddress.Any;
                    sendTo = IPAddress.Broadcast;
                }
                else if (interfaceName == "loopback")
                {
                    bindTo = IPAddress.Loopback;
                    sendTo = IPAddress.Broadcast;
                }
                else
                {
                    var interfaceCollection = new InterfaceCollection();

                    var interfaceAddress = !string.IsNullOrEmpty(interfaceName)
                        ? IPAddress.Parse(interfaceName)
                        : null;

                    foreach (var @interface in interfaceCollection)
                    {
                        if (interfaceAddress == null || @interface.Address.Equals(interfaceAddress))
                        {
                            // because windows and unix differ in how they handle broadcast addressing this needs to be platform specific
                            // on windows any interface can receive broadcast by requesting to enable broadcast on the socket
                            // on linux to receive broadcast you must bind to the broadcast address specifically
                            //bindTo = @interface.Address;
                            sendTo = @interface.BroadcastAddress;
#if NET45 || NET47_OR_GREATER
                            if (Environment.OSVersion.Platform == PlatformID.Unix)
#else
                            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
#endif
                            {
                                bindTo = @interface.BroadcastAddress;
                            }
                            else
                            {
                                bindTo = @interface.Address;
                            }
                            sendTo = @interface.BroadcastAddress;

                            break;
                        }
                    }
                }

                if (bindTo != null)
                {
                    m_broadcastAddress = new IPEndPoint(sendTo, m_udpPort);
                    m_udpSocket.Bind(new IPEndPoint(bindTo, m_udpPort));
                }

                m_pipe.SendFrame(bindTo?.ToString() ?? "");
            }
Example #3
0
        /// <summary>
        /// Runs the poller on the caller's thread. Only returns when <see cref="Stop"/> or <see cref="StopAsync"/> are called from another thread.
        /// </summary>
        private void RunPoller()
        {
            try
            {
                // Recalculate all timers now
                foreach (var timer in m_timers)
                {
                    if (timer.Enable)
                    {
                        timer.When = Clock.NowMs() + timer.Interval;
                    }
                }

                // Run until stop is requested
                while (!m_stopSignaler.IsStopRequested)
                {
                    if (m_isPollSetDirty)
                    {
                        RebuildPollset();
                    }

                    var pollStart = Clock.NowMs();

                    // Set tickless to "infinity"
                    long tickless = pollStart + int.MaxValue;

                    // Find the When-value of the earliest timer..
                    foreach (var timer in m_timers)
                    {
                        // If it is enabled but no When is set yet,
                        if (timer.When == -1 && timer.Enable)
                        {
                            // Set this timer's When to now plus it's Interval.
                            timer.When = pollStart + timer.Interval;
                        }

                        // If it has a When and that is earlier than the earliest found thus far,
                        if (timer.When != -1 && tickless > timer.When)
                        {
                            // save that value.
                            tickless = timer.When;
                        }
                    }

                    // Compute a timeout value - how many milliseconds from now that the earliest-timer will expire.
                    var timeout = tickless - pollStart;

                    // Use zero to indicate it has already expired.
                    if (timeout < 0)
                    {
                        timeout = 0;
                    }

                    var isItemAvailable = false;

                    Assumes.NotNull(m_pollSet);

                    if (m_pollSet.Length != 0)
                    {
                        isItemAvailable = m_netMqSelector.Select(m_pollSet, m_pollSet.Length, timeout);
                    }
                    else if (timeout > 0)
                    {
                        //TODO: Do we really want to simply sleep and return, doing nothing during this interval?
                        //TODO: Should a large value be passed it will sleep for a month literally.
                        //      Solution should be different, but sleep is more natural here than in selector (timers are not selector concern).
                        Debug.Assert(timeout <= int.MaxValue);
                        Thread.Sleep((int)timeout);
                    }

                    // Get the expected end time in case we time out. This looks redundant but, unfortunately,
                    // it happens that Poll takes slightly less than the requested time and 'Clock.NowMs() >= timer.When'
                    // may not true, even if it is supposed to be. In other words, even when Poll times out, it happens
                    // that 'Clock.NowMs() < pollStart + timeout'
                    var expectedPollEnd = !isItemAvailable ? pollStart + timeout : -1L;

                    // that way we make sure we can continue the loop if new timers are added.
                    // timers cannot be removed
                    foreach (var timer in m_timers)
                    {
                        if ((Clock.NowMs() >= timer.When || expectedPollEnd >= timer.When) && timer.When != -1)
                        {
                            timer.InvokeElapsed(this);

                            if (timer.Enable)
                            {
                                timer.When = Clock.NowMs() + timer.Interval;
                            }
                        }
                    }

                    for (var i = 0; i < m_pollSet.Length; i++)
                    {
                        NetMQSelector.Item item = m_pollSet[i];

                        if (item.Socket != null)
                        {
                            Assumes.NotNull(m_pollact);

                            NetMQSocket socket = m_pollact[i];

                            if (item.ResultEvent.HasError())
                            {
                                if (++socket.Errors > 1)
                                {
                                    Remove(socket);
                                    item.ResultEvent = PollEvents.None;
                                }
                            }
                            else
                            {
                                socket.Errors = 0;
                            }

                            if (item.ResultEvent != PollEvents.None)
                            {
                                socket.InvokeEvents(this, item.ResultEvent);
                            }
                        }
                        else if (item.ResultEvent.HasError() || item.ResultEvent.HasIn())
                        {
                            Assumes.NotNull(item.FileDescriptor);
                            if (m_pollinSockets.TryGetValue(item.FileDescriptor, out Action <Socket> action))
                            {
                                action(item.FileDescriptor);
                            }
                        }
                    }
                }

#if !NET35
                // Try to dequeue and execute all pending tasks before stopping poller
                while (m_tasksQueue.TryDequeue(out Task? task, TimeSpan.Zero))
                {
                    TryExecuteTask(task);
                }
#endif
            }
            finally
            {
                foreach (var socket in m_sockets.ToList())
                {
                    Remove(socket);
                }
            }
        }