<commit_before>﻿using NetMQ;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Script.Serialization;

namespace StreamKinect2
{
    /// <summary>
    /// Exception raised by Server on an error.
    /// </summary>
    public class ServerException : Exception
    {
        public ServerException(string message) : base(message) { }
    }

    public class Server : IDisposable
    {
        private enum State
        {
            STOPPED,                    // Server is stopped, can be started
            WAITING_FOR_REGISTRATION,   // Waiting for ZeroConf registration callback
            WAITING_FOR_RESOLVE,        // Waiting for ZeroConf resolution to discover our hostname
            RUNNING,                    // Server is running
        }

        private class DeviceEndpoint
        {
            public string      Address;
            public NetMQSocket Socket;
        }

        // Zeroconf browser we're using to register ourselves
        IZeroconfServiceBrowser m_zcBrowser;

        // Connection information
        private string m_hostname;      // Local hostname to advertise endpoints via
        private string m_name;          // Name of this server

        // State machine
        State m_state = State.STOPPED;

        // ZeroMQ related objects
        private NetMQContext m_netMQContext;
        private Poller m_poller;
        private Task m_pollerTask; // non-null iff we are managing the poller ourselves

        // Control socket
        private NetMQSocket m_controlSocket;
        private int m_controlSocketPort;

        // Set of Kinect devices which we know about
        private IDictionary<IDevice, IDictionary<string, DeviceEndpoint>> m_devices;

        public Server() : this(new Poller(), NetMQContext.Create())
        {
            // Start poller task
            m_pollerTask = Task.Factory.StartNew(m_poller.Start);
        }

        public Server(Poller poller) : this(poller, NetMQContext.Create()) { }

        public Server(Poller poller, NetMQContext netMQContext)
        {
            // Record the netMQ context we use to create the server.
            m_netMQContext = netMQContext;

            // Record the netMQ poller
            m_poller = poller;

            // Initialise our set of devices
            m_devices = new Dictionary<IDevice, IDictionary<string, DeviceEndpoint>>();
        }

        public void Dispose()
        {
            // Stop the server if it is running.
            if (m_state != State.STOPPED)
            {
                Stop();
            }

            // Ensure that the poller task is stopped if one was started
            if (m_poller.IsStarted && (m_pollerTask != null) && !m_pollerTask.IsCompleted)
            {
                m_poller.Stop();
                m_pollerTask.Wait(100);
            }
        }

        /// <summary>
        /// Start the server registering it with the default Zeroconf service browser.
        /// </summary>
        public void Start()
        {
            Start(new BonjourServiceBrowser());
        }

        public void Start(IZeroconfServiceBrowser zcBrowser)
        {
            // Ensure we're not running.
            if (m_state != State.STOPPED)
            {
                throw new ServerException("Server already running");
            }
            Debug.WriteLine("Starting server");

            // Create a control endpoint socket and bind it to a random port
            m_controlSocket = m_netMQContext.CreateResponseSocket();
            m_controlSocketPort = m_controlSocket.BindRandomPort("tcp://0.0.0.0");
            m_controlSocket.ReceiveReady += ControlSocket_ReceiveReady;
            Debug.WriteLine("Server control socket bound to port: " + m_controlSocketPort);

            // Wire up our event handlers to the browser
            m_zcBrowser = zcBrowser;
            m_zcBrowser.ServiceRegistered += ZeroconfBrowser_ServiceRegistered;
            m_zcBrowser.ServiceResolved += ZeroconfBrowser_ServiceResolved;

            // Wait for registration
            m_state = State.WAITING_FOR_REGISTRATION;

            // Register the server with ZeroConf
            Debug.WriteLine("Registering with ZeroConf");
            zcBrowser.Register("Kinect stream on " + System.Environment.MachineName, "_kinect2._tcp", (ushort) m_controlSocketPort);
        }

        public void Stop()
        {
            // Ensure we're not stopped. We can stop the server even when
            // waiting for ZeroConf registration.
            if (m_state == State.STOPPED)
            {
                throw new ServerException("Server not running");
            }
            Debug.WriteLine("Stopping server");
<commit_msg>server: close device endpoints on shutdown<commit_after>﻿using NetMQ;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Script.Serialization;

namespace StreamKinect2
{
    /// <summary>
    /// Exception raised by Server on an error.
    /// </summary>
    public class ServerException : Exception
    {
        public ServerException(string message) : base(message) { }
    }

    public class Server : IDisposable
    {
        private enum State
        {
            STOPPED,                    // Server is stopped, can be started
            WAITING_FOR_REGISTRATION,   // Waiting for ZeroConf registration callback
            WAITING_FOR_RESOLVE,        // Waiting for ZeroConf resolution to discover our hostname
            RUNNING,                    // Server is running
        }

        private class DeviceEndpoint
        {
            public string      Address;
            public NetMQSocket Socket;
        }

        // Zeroconf browser we're using to register ourselves
        IZeroconfServiceBrowser m_zcBrowser;

        // Connection information
        private string m_hostname;      // Local hostname to advertise endpoints via
        private string m_name;          // Name of this server

        // State machine
        State m_state = State.STOPPED;

        // ZeroMQ related objects
        private NetMQContext m_netMQContext;
        private Poller m_poller;
        private Task m_pollerTask; // non-null iff we are managing the poller ourselves

        // Control socket
        private NetMQSocket m_controlSocket;
        private int m_controlSocketPort;

        // Set of Kinect devices which we know about
        private IDictionary<IDevice, IDictionary<string, DeviceEndpoint>> m_devices;

        public Server() : this(new Poller(), NetMQContext.Create())
        {
            // Start poller task
            m_pollerTask = Task.Factory.StartNew(m_poller.Start);
        }

        public Server(Poller poller) : this(poller, NetMQContext.Create()) { }

        public Server(Poller poller, NetMQContext netMQContext)
        {
            // Record the netMQ context we use to create the server.
            m_netMQContext = netMQContext;

            // Record the netMQ poller
            m_poller = poller;

            // Initialise our set of devices
            m_devices = new Dictionary<IDevice, IDictionary<string, DeviceEndpoint>>();
        }

        public void Dispose()
        {
            // Stop the server if it is running.
            if (m_state != State.STOPPED)
            {
                Stop();
            }

            // Ensure that the poller task is stopped if one was started
            if (m_poller.IsStarted && (m_pollerTask != null) && !m_pollerTask.IsCompleted)
            {
                m_poller.Stop();
                m_pollerTask.Wait(100);
            }
        }

        /// <summary>
        /// Start the server registering it with the default Zeroconf service browser.
        /// </summary>
        public void Start()
        {
            Start(new BonjourServiceBrowser());
        }

        public void Start(IZeroconfServiceBrowser zcBrowser)
        {
            // Ensure we're not running.
            if (m_state != State.STOPPED)
            {
                throw new ServerException("Server already running");
            }
            Debug.WriteLine("Starting server");

            // Create a control endpoint socket and bind it to a random port
            m_controlSocket = m_netMQContext.CreateResponseSocket();
            m_controlSocketPort = m_controlSocket.BindRandomPort("tcp://0.0.0.0");
            m_controlSocket.ReceiveReady += ControlSocket_ReceiveReady;
            Debug.WriteLine("Server control socket bound to port: " + m_controlSocketPort);

            // Wire up our event handlers to the browser
            m_zcBrowser = zcBrowser;
            m_zcBrowser.ServiceRegistered += ZeroconfBrowser_ServiceRegistered;
            m_zcBrowser.ServiceResolved += ZeroconfBrowser_ServiceResolved;

            // Wait for registration
            m_state = State.WAITING_FOR_REGISTRATION;

            // Register the server with ZeroConf
            Debug.WriteLine("Registering with ZeroConf");
            zcBrowser.Register("Kinect stream on " + System.Environment.MachineName, "_kinect2._tcp", (ushort) m_controlSocketPort);
        }

        public void Stop()
        {
            // Ensure we're not stopped. We can stop the server even when
            // waiting for ZeroConf registration.
            if (m_state == State.STOPPED)
            {
                throw new ServerException("Server not running");
            }
            Debug.WriteLine("Stopping server");

            // Remove all endpoints for all devices
            foreach(var device in m_devices)
            {
                var endpoints = device.Value;
                foreach(var endpoint in endpoints)
                {
                    endpoint.Value.Socket.Close();
                }
                endpoints.Clear();
            }

{'fraction_non_alphanumeric': 0.07409638554216867, 'fraction_numerical': 0.0018072289156626507, 'mean_word_length': 1.7909778649481647, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3183054', 'n_tokens_mistral': 2576, 'n_tokens_neox': 2431, 'n_words': 726}