/// <summary>
        /// Replaces the old socket from <see cref="m_socket_conn"/>
        /// with the current socket or adds it, if it does not exist.
        /// </summary>
        /// <param name="stNew">The current socket</param>
        protected void ReplaceSocket(stDeviceSocket stNew)
        {
            try
            {
                if (!m_socket_conn.ContainsKey(stNew.deviceid))
                {
                    // device not exist, lets add it
                    m_socket_conn.Add(stNew.deviceid, stNew);
                }
                else
                {
                    // device exist, find the old thread and kill it, and replace it
                    stDeviceSocket stOld = m_socket_conn[stNew.deviceid];

                    // do nothing if device is comming from same thread
                    if (stNew.thread.ManagedThreadId == stOld.thread.ManagedThreadId)
                    {
                        return;
                    }

                    // explicitly close the client socket
                    if (stOld.thread.IsAlive && stOld.tcpClient.Connected)
                    {
                        stOld.tcpClient.Close();
                    }

                    // replace with current thread
                    m_socket_conn[stNew.deviceid] = stNew;
                }
            }
            catch (Exception ex)
            {
                LogManager.LogErrorLine("Exception ReplaceSocket: {0}", ex.Message);
            }
        }
        protected override void HandleDeviceThread(object obj)
        {
            byte[]        data      = new byte[SocketParserConstants.MAX_SIZE_READ_PACKET_BUFFER];
            TcpClient     remclient = (TcpClient)obj;
            NetworkStream netstream = remclient.GetStream();

            remclient.ReceiveTimeout = SocketParserConstants.READ_PACKET_TIMEOUT_SHORT;
            LogManager.LogInfoLine("Client Connected. Active Connections = {0}", ++m_nConnections);

            // main loop to service the client
            while (netstream.CanRead)
            {
                try
                {
                    // clear buffer and read from network packet [blocking call]
                    Array.Clear(data, 0, data.Length);
                    int recv = netstream.Read(data, 0, data.Length);

                    // close socket if nothing was received
                    if (recv <= 0)
                    {
                        LogManager.LogInfoLine("Socket Closed.");
                        break;
                    }

                    // now that we have received initial data from device, let's increase max time-out
                    remclient.ReceiveTimeout = SocketParserConstants.READ_PACKET_TIMEOUT_LONG;

                    // handle data packet, log any and all data sent to server
                    if (this.OnRead(data, recv, netstream) == false || recv > SocketParserConstants.MAX_SIZE_DATAGRAM)
                    {
                        continue;
                    }

                    /*
                     * // check if client issued a closing request, if so, close client socket and thread
                     * if (IsClientClosing(data))
                     * {
                     *  LogManager.LogInfoLine("Client Closed.");
                     *  break;
                     * }
                     * */

                    // we'll need to replace the socket/close the old thread
                    long devid = 0;
                    if (this.OnGetDeviceId(data, out devid))
                    {
                        stDeviceSocket stobj = new stDeviceSocket
                        {
                            deviceid  = devid,
                            thread    = Thread.CurrentThread,
                            tcpClient = remclient
                        };

                        // replace socket, and insert data into tracker log
                        string strerr = string.Empty;
                        lock (_cs_mutex)
                        {
                            this.ReplaceSocket(stobj);

                            if (SocketSQL.Instance.InsertToDatabase(_deviceModel, data, recv, out strerr))
                            {
                                continue;
                            }

                            if (SocketSQL.Instance.InsertToDatabase(_deviceModel, data, recv, out strerr))
                            {
                                continue;
                            }

                            if (SocketSQL.Instance.InsertToDatabase(_deviceModel, data, recv, out strerr))
                            {
                                continue;
                            }
                        }
                        // end critical section

                        // 3x tries and we failed to insert into TrackerLog, lets log it
                        LogManager.LogErrorLine("MySqlInsertError: {0}", strerr);
                    }
                }
                catch (IOException)
                {
                    LogManager.LogInfoLine("Socket replaced or client timed-out.");
                    break;
                }
                catch (SocketException ex)
                {
                    LogManager.LogErrorLine("HandleDeviceThread - SocketException: {0}", ex.Message);
                    break;
                }
                catch (Exception ex)
                {
                    LogManager.LogErrorLine("HandleDeviceThread - Exception: {0}", ex.Message);
                    break;
                }
            }
            netstream.Close();
            remclient.Close();
            LogManager.LogInfoLine("Client Disconnected. Active Connections = {0}", --m_nConnections);
        }