private void AcceptConnection( IAsyncResult ar )
        {
            lock ( _s )
            {
                if ( _nStopFlag == 1 )
                {
                    _mreReceivedMessage.Set();
                    return;
                }
            }

            // Note that this fails if you call EndAccept on a closed socket
            Socket s = ( ( Socket )ar.AsyncState ).EndAccept( ar );
            _mreReceivedMessage.Set();

            try
            {
                using ( NetworkStream ns = new NetworkStream( s, true ) )
                {
                    BinaryReader br = new BinaryReader( ns );
                    NetworkMessage nm = ( NetworkMessage )br.ReadInt16();

                    int nAppDomainID, nThreadID, nFunctionID;

                    switch ( nm )
                    {
                        case NetworkMessage.INITIALIZE:
                        {
                            if ( ( ( IPEndPoint )s.RemoteEndPoint ).Address != IPAddress.Loopback )
                            {
                                // Prompt the user?
                            }

                            int nNetworkProtocolVersion = br.ReadInt32();
                            if ( nNetworkProtocolVersion != NETWORK_PROTOCOL_VERSION )
                            {
                                // Wrong version, write a negative byte
                                ns.WriteByte( 0 );
                                if ( Error != null )
                                    Error( new InvalidOperationException( "Profiler hook is wrong version" ) );
                            }
                            else
                            {
                                // Version was okay, write a positive byte
                                if ( _po.Debug )
                                    ns.WriteByte( 2 );
                                else
                                    ns.WriteByte( 1 );

                                UInt32 nProcessID = br.ReadUInt32();
                                string strProcessName = ReadLengthEncodedASCIIString( br );

                                _run.Messages.AddMessage( "Connected to " + strProcessName + " with process ID " + nProcessID );
                            }

                            // We're off!
                            _run.State = Run.RunState.Running;
                            break;
                        }

                        case NetworkMessage.SHUTDOWN:
                        {
                            _bHasStopped = true;
                            _run.Messages.AddMessage( "Profiling completed." );
                            if ( Exited != null )
                                Exited( this, EventArgs.Empty );
                            break;
                        }

                        case NetworkMessage.APPDOMAIN_CREATE:
                        {
                            nAppDomainID = br.ReadInt32();
                            _run.Messages.AddMessage( "AppDomain created: " + nAppDomainID );
                            break;
                        }

                        case NetworkMessage.THREAD_CREATE:
                            nThreadID = br.ReadInt32();
                            _run.Messages.AddMessage( "Thread created: " + nThreadID );
                            break;

                        case NetworkMessage.THREAD_END:
                            nThreadID = br.ReadInt32();
                            _tic[ nThreadID ].StartTime = br.ReadInt64();
                            _tic[ nThreadID ].EndTime = br.ReadInt64();
                            _run.Messages.AddMessage( "Thread completed: " + nThreadID );
                            break;

                        case NetworkMessage.FUNCTION_DATA:
                        {
                            nThreadID = br.ReadInt32();
                            _run.Messages.AddMessage( "Receiving function data for thread  " + nThreadID + "..." );

                            nFunctionID = br.ReadInt32();
                            int nIndex = 0;

                            while ( nFunctionID != -1 )
                            {
                                UInt32 uiFlags = br.ReadUInt32();
                                string strReturn = ReadLengthEncodedASCIIString( br );
                                string strClassName = ReadLengthEncodedASCIIString( br );
                                string strFnName = ReadLengthEncodedASCIIString( br );
                                string strParameters = ReadLengthEncodedASCIIString( br );

                                FunctionSignature fs = new FunctionSignature(
                                    uiFlags,
                                    strReturn,
                                    strClassName,
                                    strFnName,
                                    strParameters
                                );
                                _fsm.MapSignature( nFunctionID, fs );

                                int nCalls = br.ReadInt32();
                                long lTotalTime = br.ReadInt64();
                                long lTotalRecursiveTime = br.ReadInt64();
                                long lTotalSuspendTime = br.ReadInt64();
                                ArrayList alCallees = new ArrayList();
                                int nCalleeFunctionID = br.ReadInt32();

                                while ( nCalleeFunctionID != -1 )
                                {
                                    int nCalleeCalls = br.ReadInt32();
                                    long lCalleeTotalTime = br.ReadInt64();
                                    long lCalleeRecursiveTime = br.ReadInt64();

                                    alCallees.Add( new CalleeFunctionInfo( _fsm, nCalleeFunctionID, nCalleeCalls, lCalleeTotalTime, lCalleeRecursiveTime ) );
                                    nCalleeFunctionID = br.ReadInt32();
                                }
                                CalleeFunctionInfo[] acfi = ( CalleeFunctionInfo[] )alCallees.ToArray( typeof( CalleeFunctionInfo ) );

                                FunctionInfo fi = new FunctionInfo( _tic[ nThreadID ], nFunctionID, fs, nCalls, lTotalTime, lTotalRecursiveTime, lTotalSuspendTime, acfi );
                                _tic[ nThreadID ].FunctionInfoCollection.Add( fi );

                                nFunctionID = br.ReadInt32();
                                nIndex++;
                            }

                            _run.Messages.AddMessage( "Received " + nIndex + " item(s) for thread  " + nThreadID );
                            break;
                        }

                        case NetworkMessage.PROFILER_MESSAGE:
                            string strMessage = ReadLengthEncodedASCIIString( br );
                            _run.Messages.AddMessage( strMessage );

                            break;
                    }
                }
            }
            catch ( Exception e )
            {
                if ( Error != null )
                    Error( e );
            }
        }
 public void Add( FunctionInfo fi )
 {
     _htFunctionInfo[ fi.ID ] = fi;
 }