<commit_before>namespace Modbus.Device
{
    using System;
    using System.Collections.Concurrent;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Linq;
    using System.Net.Sockets;
    using System.Diagnostics;
    using System.IO;

    using IO;

    /// <summary>
    ///     Modbus TCP slave device.
    /// </summary>
    public class ModbusTcpSlave : ModbusSlave
    {
        private readonly object _serverLock = new object();

        private readonly ConcurrentDictionary<string, ModbusMasterTcpConnection> _masters =
            new ConcurrentDictionary<string, ModbusMasterTcpConnection>();

        private TcpListener _server;

        private ModbusTcpSlave(byte unitId, TcpListener tcpListener)
            : base(unitId, new EmptyTransport())
        {
            if (tcpListener == null)
                throw new ArgumentNullException("tcpListener");

            _server = tcpListener;
        }

        /// <summary>
        ///     Gets the Modbus TCP Masters connected to this Modbus TCP Slave.
        /// </summary>
        public ReadOnlyCollection<TcpClient> Masters
        {
            get
            {
                return new ReadOnlyCollection<TcpClient>(_masters.Values.Select(mc => mc.TcpClient).ToList());
            }
        }

        /// <summary>
        ///     Gets the server.
        /// </summary>
        /// <value>The server.</value>
        /// <remarks>
        ///     This property is not thread safe, it should only be consumed within a lock.
        /// </remarks>
        private TcpListener Server
        {
            get
            {
                if (_server == null)
                    throw new ObjectDisposedException("Server");

                return _server;
            }
        }

        /// <summary>
        ///     Modbus TCP slave factory method.
        /// </summary>
        public static ModbusTcpSlave CreateTcp(byte unitId, TcpListener tcpListener)
        {
            return new ModbusTcpSlave(unitId, tcpListener);
        }

        /// <summary>
        ///     Start slave listening for requests.
        /// </summary>
        public override void Listen()
        {
            Debug.WriteLine("Start Modbus Tcp Server.");

            lock (_serverLock)
            {
                try
                {
                    Server.Start();

                    // use Socket async API for compact framework compat
                    Server.Server.BeginAccept(AcceptCompleted, this);
                }
                catch (ObjectDisposedException)
                {
                    // this happens when the server stops
                }
            }
        }

        internal void RemoveMaster(string endPoint)
        {
            ModbusMasterTcpConnection connection;
            if (!_masters.TryRemove(endPoint, out connection))
            {
                var msg = string.Format(
                    CultureInfo.InvariantCulture,
                    "EndPoint {0} cannot be removed, it does not exist.",
                    endPoint);

                throw new ArgumentException(msg);
            }

            Debug.WriteLine("Removed Master {0}", endPoint);
        }

        internal void AcceptCompleted(IAsyncResult ar)
        {
            ModbusTcpSlave slave = (ModbusTcpSlave) ar.AsyncState;

            try
            {
                try
                {
                    // use Socket async API for compact framework compat
                    Socket socket = null;
                    lock (_serverLock)
                    {
                        if (_server == null) // Checks for disposal to an otherwise unnecessary exception (which is slow and hinders debugging).
                            return;
                        socket = Server.Server.EndAccept(ar);
                    }

                    TcpClient client = new TcpClient {Client = socket};
                    var masterConnection = new ModbusMasterTcpConnection(client, slave);
                    masterConnection.ModbusMasterTcpConnectionClosed +=
                        (sender, eventArgs) => RemoveMaster(eventArgs.EndPoint);

                    _masters.TryAdd(client.Client.RemoteEndPoint.ToString(), masterConnection);

                    Debug.WriteLine("Accept completed.");
                }
                catch (IOException ex)
                {
                    // Abandon the connection attempt and continue to accepting the next connection.
                    Debug.WriteLine("Accept failed: " + ex.Message);
                }

                // Accept another client
                // use Socket async API for compact framework compat
                lock (_serverLock)
                    Server.Server.BeginAccept(AcceptCompleted, slave);
            }
            catch (ObjectDisposedException)
            {
                // this happens when the server stops
            }
        }

        /// <summary>
        ///     Releases unmanaged and - optionally - managed resources<commit_msg>Replace lambda handler with method. Replace lambda handler of ModbusMasterTcpConnectionClosed event with method. The purpose of this change is ability to unsubscribe from event.<commit_after>namespace Modbus.Device
{
    using System;
    using System.Collections.Concurrent;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Linq;
    using System.Net.Sockets;
    using System.Diagnostics;
    using System.IO;

    using IO;

    /// <summary>
    ///     Modbus TCP slave device.
    /// </summary>
    public class ModbusTcpSlave : ModbusSlave
    {
        private readonly object _serverLock = new object();

        private readonly ConcurrentDictionary<string, ModbusMasterTcpConnection> _masters =
            new ConcurrentDictionary<string, ModbusMasterTcpConnection>();

        private TcpListener _server;

        private ModbusTcpSlave(byte unitId, TcpListener tcpListener)
            : base(unitId, new EmptyTransport())
        {
            if (tcpListener == null)
                throw new ArgumentNullException("tcpListener");

            _server = tcpListener;
        }

        /// <summary>
        ///     Gets the Modbus TCP Masters connected to this Modbus TCP Slave.
        /// </summary>
        public ReadOnlyCollection<TcpClient> Masters
        {
            get
            {
                return new ReadOnlyCollection<TcpClient>(_masters.Values.Select(mc => mc.TcpClient).ToList());
            }
        }

        /// <summary>
        ///     Gets the server.
        /// </summary>
        /// <value>The server.</value>
        /// <remarks>
        ///     This property is not thread safe, it should only be consumed within a lock.
        /// </remarks>
        private TcpListener Server
        {
            get
            {
                if (_server == null)
                    throw new ObjectDisposedException("Server");

                return _server;
            }
        }

        /// <summary>
        ///     Modbus TCP slave factory method.
        /// </summary>
        public static ModbusTcpSlave CreateTcp(byte unitId, TcpListener tcpListener)
        {
            return new ModbusTcpSlave(unitId, tcpListener);
        }

        /// <summary>
        ///     Start slave listening for requests.
        /// </summary>
        public override void Listen()
        {
            Debug.WriteLine("Start Modbus Tcp Server.");

            lock (_serverLock)
            {
                try
                {
                    Server.Start();

                    // use Socket async API for compact framework compat
                    Server.Server.BeginAccept(AcceptCompleted, this);
                }
                catch (ObjectDisposedException)
                {
                    // this happens when the server stops
                }
            }
        }

        private void OnMasterConnectionClosedHandler(object sender, TcpConnectionEventArgs e)
        {
            ModbusMasterTcpConnection connection;
            if (!_masters.TryRemove(e.EndPoint, out connection))
            {
                var msg = string.Format(
                    CultureInfo.InvariantCulture,
                    "EndPoint {0} cannot be removed, it does not exist.",
                    e.EndPoint);

                throw new ArgumentException(msg);
            }

            Debug.WriteLine("Removed Master {0}", e.EndPoint);
        }

        internal void AcceptCompleted(IAsyncResult ar)
        {
            ModbusTcpSlave slave = (ModbusTcpSlave) ar.AsyncState;

            try
            {
                try
                {
                    // use Socket async API for compact framework compat
                    Socket socket = null;
                    lock (_serverLock)
                    {
                        if (_server == null) // Checks for disposal to an otherwise unnecessary exception (which is slow and hinders debugging).
                            return;
                        socket = Server.Server.EndAccept(ar);
                    }

                    TcpClient client = new TcpClient {Client = socket};
                    var masterConnection = new ModbusMasterTcpConnection(client, slave);
                    masterConnection.ModbusMasterTcpConnectionClosed += OnMasterConnectionClosedHandler;

                    _masters.TryAdd(client.Client.RemoteEndPoint.ToString(), masterConnection);

                    Debug.WriteLine("Accept completed.");
                }
                catch (IOException ex)
                {
                    // Abandon the connection attempt and continue to accepting the next connection.
                    Debug.WriteLine("Accept failed: " + ex.Message);
                }

                // Accept another client
                // use Socket async API for compact framework compat
                lock (_serverLock)
                    Server.Server.BeginAccept(AcceptCompleted, slave);
            }
            catch (ObjectDisposedException)
            {
                // this happens when the server stops
            }
        }

        /// <summary>
        ///     Releases unmanaged and - optionally - managed resources
{'fraction_non_alphanumeric': 0.07764455617868884, 'fraction_numerical': 0.00038677238445175013, 'mean_word_length': 1.3722477064220184, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, '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': '643765', 'n_tokens_mistral': 2424, 'n_tokens_neox': 2280, 'n_words': 652}