/// <summary>
		/// Override the OnRun method to capture the date and time that the job was started and to change it's state
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected override void OnRun(object sender, BackgroundThreadStartEventArgs e)
		{
			_job._dateTimeStarted = DateTime.Now;
			_job._state = BackgroundThreadPoolJobStates.Running;
 
			base.OnRun (sender, e);
		}
Beispiel #2
0
        /// <summary>
        /// Override the OnRun method to capture the date and time that the job was started and to change it's state
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected override void OnRun(object sender, BackgroundThreadStartEventArgs e)
        {
            _job._dateTimeStarted = DateTime.Now;
            _job._state           = BackgroundThreadPoolJobStates.Running;

            base.OnRun(sender, e);
        }
 /// <summary>
 /// Provides a virtual method to override and perform custom processing on a background thread
 /// </summary>
 /// <param name="args"></param>
 protected virtual void OnRun(object sender, BackgroundThreadStartEventArgs e)
 {
     try
     {
         if (this.Run != null)
         {
             this.Run(sender, e);
         }
     }
     catch (ThreadAbortException)
     {
     }
     catch (Exception ex)
     {
         Trace.WriteLine(ex);
     }
 }
        /// <summary>
        /// Monitors the jobs in the job queue and delegates threads to service the waiting jobs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void OnProcessJobs(object sender, BackgroundThreadStartEventArgs e)
        {
            try
            {
                // continuously monitor the job queue and thread count
                while (true)
                {
                    // lock the thread list
                    lock (this.ThreadList.SyncRoot)
                    {
                        // if we haven't reached the max thread limit
                        if (this.ThreadList.Count < _maxThreads)
                        {
                            // lock the job queue
                            lock (this.JobQueue.SyncRoot)
                            {
                                // if there are jobs waiting
                                if (this.JobQueue.Count > 0)
                                {
                                    // dequeue the next waiting job
                                    BackgroundThreadPoolJob job = this.JobQueue.Dequeue();

                                    // create a new background thread pool thread to process the job
                                    BackgroundThreadPoolThread thread = new BackgroundThreadPoolThread(job);

                                    // and finally add the thread to our list of threads
                                    this.ThreadList.Add(thread);
                                }
                            }
                        }

                        this.DestroyThreads(true /* only the finished ones */);
                    }

                    Thread.Sleep(100);
                }
            }
            catch (ThreadAbortException)
            {
                // the processing thread is aborting
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }
		/// <summary>
		/// Occurs when the engine's background thread runs
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="ea"></param>
		protected virtual void OnThreadRun(object sender, BackgroundThreadStartEventArgs threadStartEventArgs)
		{
			bool downloaded = false;
			bool installed = false;
			bool finalized = false;
			AutoUpdateDownloadDescriptor recommendedUpdateDescriptor = null;

			try
			{
				/*
				 * Raise the AutoUpdateProcessStarted event
				 * */
				AutoUpdateManagerEventArgs startedArgs = new AutoUpdateManagerEventArgs(this, null);
				this.OnAutoUpdateProcessStarted(this, startedArgs);

				#region Step 1. QueryForLatestVersion

				/*
				 * Raise the BeforeQueryForLatestVersion event
				 * */
				AutoUpdateManagerCancelEventArgs beforeQueryArgs = new AutoUpdateManagerCancelEventArgs(this, startedArgs.ProgressViewer, false);
				this.OnBeforeQueryForLatestVersion(this, beforeQueryArgs);

				// create an array list to hold all of the available updates
				ArrayList listOfAvailableDownloads = new ArrayList();				
				
				// use the downloaders to check for downloads
				foreach(AutoUpdateDownloader downloader in _downloaders)
				{
					try
					{
						// query the latest update available for the specified product
						AutoUpdateDownloadDescriptor updateAvailable;						
						
						// if the downloader finds an update is available
						if (downloader.QueryLatestVersion(beforeQueryArgs.ProgressViewer, _options, _productToUpdate, out updateAvailable))														
							// add it to the list of downloads available
							listOfAvailableDownloads.Add(updateAvailable);						
					}
					catch(ThreadAbortException ex)
					{
						throw new Exception(ex.Message, ex);
					}
					catch(Exception ex)
					{
						Trace.WriteLine(ex);
					}
				}

				// create a simple array of the updates that are available for download
				AutoUpdateDownloadDescriptor[] availableDownloads = listOfAvailableDownloads.ToArray(typeof(AutoUpdateDownloadDescriptor)) as AutoUpdateDownloadDescriptor[];

				// sort and select the download that contains the newest version
				recommendedUpdateDescriptor = this.SelectTheDownloadWithTheNewestUpdate(availableDownloads);

				/*
				 * Raise the AfterQueryForLatestVersion event
				 * */
				AutoUpdateManagerWithDownloadDescriptorEventArgs afterQueryArgs = new AutoUpdateManagerWithDownloadDescriptorEventArgs(this, beforeQueryArgs.ProgressViewer, recommendedUpdateDescriptor);
				this.OnAfterQueryForLatestVersion(this, afterQueryArgs);

				// if the manager could not find a suitable recomendation for downloading, we're done 
				if (recommendedUpdateDescriptor == null)
				{
					/*
					 * Raise the NoLaterVersionAvailable event
					 * */
					this.OnNoLaterVersionAvailable(this, new AutoUpdateManagerEventArgs(this, afterQueryArgs.ProgressViewer));
					return;
				}
				
				// or if the product to update is newer or equal to the version of the recommended update picked for downloading
				if (_productToUpdate.Version >= recommendedUpdateDescriptor.Manifest.Product.Version)
				{
					/*
					 * Raise the NoLaterVersionAvailable event
					 * */
					this.OnNoLaterVersionAvailable(this, new AutoUpdateManagerEventArgs(this, afterQueryArgs.ProgressViewer));
					return;
				}
                
				#endregion

				#region Step 2. Download

				/*
				 * Create the path including the filename where the .Update file will be downloaded to locally
				 * (ex: "C:\Program Files\Razor\1.0.0.0.update")				  
				 * */
				recommendedUpdateDescriptor.DownloadedPath = Path.Combine(_options.DownloadPath, Path.GetFileName(recommendedUpdateDescriptor.Manifest.UrlOfUpdate));

				/*
				 * Raise the BeforeDownload event
				 * */
				AutoUpdateManagerWithDownloadDescriptorCancelEventArgs beforeDownloadArgs = new AutoUpdateManagerWithDownloadDescriptorCancelEventArgs(this, afterQueryArgs.ProgressViewer, recommendedUpdateDescriptor, false);
				this.OnBeforeDownload(this, beforeDownloadArgs);
				
				// bail if the download was cancelled
				if (beforeDownloadArgs.Cancel)
					return;				
				
				// use the downloader that found the update to download it
				// the update may be available via some proprietary communications channel (http, ftp, or Unc paths)
				downloaded = recommendedUpdateDescriptor.Downloader.Download(beforeDownloadArgs.ProgressViewer, recommendedUpdateDescriptor);

				/*
				 * Raise the AfterDownload event
				 * */
				AutoUpdateManagerWithDownloadDescriptorEventArgs afterDownloadArgs = new AutoUpdateManagerWithDownloadDescriptorEventArgs(this, beforeDownloadArgs.ProgressViewer, recommendedUpdateDescriptor);
				afterDownloadArgs.OperationStatus = downloaded;
				this.OnAfterDownload(this, afterDownloadArgs);
				
				// if the download failed bail out
				if (!downloaded)
					return;

				#endregion

				#region Step 3. Install

				/*
				 * Raise the BeforeInstall event
				 * */
				AutoUpdateManagerWithDownloadDescriptorCancelEventArgs beforeInstallArgs = new AutoUpdateManagerWithDownloadDescriptorCancelEventArgs(this, afterDownloadArgs.ProgressViewer, recommendedUpdateDescriptor, false);
				this.OnBeforeInstall(this, beforeInstallArgs);

				// if the installation was not cancelled
				if (!beforeInstallArgs.Cancel)
				{				
					// install the update
					installed = this.InstallUpdate(beforeInstallArgs.ProgressViewer, recommendedUpdateDescriptor);

					// if the update was installed, now is the time to finalize the installation
					if (installed)
					{
						// all the downloader to finalize the install, there may be things to do after the installation is complete
						// depending upon the source of the download, and again since it's plugable only the downloader will know how to deal with it
						// and by default it will just delete the downloaded .update file
						finalized = recommendedUpdateDescriptor.Downloader.FinalizeInstallation(beforeInstallArgs.ProgressViewer, recommendedUpdateDescriptor);
                    }    															
				}

				/*
				 * Raise the AfterInstall event
				 * */				
				AutoUpdateManagerWithDownloadDescriptorEventArgs afterInstallArgs = new AutoUpdateManagerWithDownloadDescriptorEventArgs(this, beforeInstallArgs.ProgressViewer, recommendedUpdateDescriptor);				
				afterInstallArgs.OperationStatus = installed && finalized;																	
				this.OnAfterInstall(this, afterInstallArgs);
				
				#endregion

				#region Step 4. Update Alternate Path

				/*
				 * Raise the X event
				 * */
				AutoUpdateManagerWithDownloadDescriptorCancelEventArgs beforeUpdateAltPathArgs = new AutoUpdateManagerWithDownloadDescriptorCancelEventArgs(this, afterInstallArgs.ProgressViewer, recommendedUpdateDescriptor, false);
				this.OnBeforeUpdateAlternatePath(this, beforeUpdateAltPathArgs);

				if (!beforeUpdateAltPathArgs.Cancel)
				{
					// copy the manifest & the update there 
					this.AdjustUrlOfUpdateInManifest(_options, recommendedUpdateDescriptor);
					this.CreateCopyOfManifestInAlternatePath(beforeUpdateAltPathArgs.ProgressViewer, recommendedUpdateDescriptor);
					this.CreateCopyOfUpdateInAlternatePath(beforeUpdateAltPathArgs.ProgressViewer, recommendedUpdateDescriptor);
				}
				
				// delete the downloaded .update file, don't leave it laying around
				File.Delete(recommendedUpdateDescriptor.DownloadedPath);

				AutoUpdateManagerWithDownloadDescriptorEventArgs afterUpdateAltPathArgs = new AutoUpdateManagerWithDownloadDescriptorEventArgs(this, beforeUpdateAltPathArgs.ProgressViewer, recommendedUpdateDescriptor);
				this.OnAfterUpdateAlternatePath(this, afterUpdateAltPathArgs);

				#endregion

				#region Step 5. Switch to Latest Version

				if (installed)
				{
					/*
					 * Raise the BeforeSwitchToLatestVersion event
					 * */
					AutoUpdateManagerWithDownloadDescriptorCancelEventArgs beforeSwitchedArgs = new AutoUpdateManagerWithDownloadDescriptorCancelEventArgs(this, afterUpdateAltPathArgs.ProgressViewer, recommendedUpdateDescriptor, false);
					this.OnBeforeSwitchToLatestVersion(this, beforeSwitchedArgs);

					// if switching to the latest version was not cancelled
					if (!beforeSwitchedArgs.Cancel)
					{
						/*
						* Raise the SwitchToLatestVersion event
						* */
						AutoUpdateManagerWithDownloadDescriptorEventArgs switchToArgs = new AutoUpdateManagerWithDownloadDescriptorEventArgs(this, beforeSwitchedArgs.ProgressViewer, recommendedUpdateDescriptor);
						this.OnSwitchToLatestVersion(this, switchToArgs);

						// the rest should be history because the AutoUpdateSnapIn should catch that event and switch to the latest version using the bootstrap
					}
				}

				#endregion
			}
			catch(ThreadAbortException)
			{
				Debug.WriteLine("The AutoUpdateManager has encountered a ThreadAbortException.\n\tThe auto-update thread has been aborted.", MY_TRACE_CATEGORY);

				try
				{
					// delete the downloaded .update file, don't leave it laying around
					File.Delete(recommendedUpdateDescriptor.DownloadedPath);
				}
				catch(Exception)
				{

				}
			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex);
				this.OnException(this, new AutoUpdateExceptionEventArgs(ex));				
			}
		}
		/// <summary>
		/// Tries to receive data from the network on a background thread
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void OnReadFromSocket(object sender, BackgroundThreadStartEventArgs threadStartArgs) 
		{
			try 
			{	               
				// create a new message reader
				_messageReader = new HttpMessageReader();
				
				while(true) 
				{
					try 
					{			
//						if (!_isServerSideConnection)
//							Debug.WriteLine(string.Format("User-Agent connection '{0}' trying to read next incoming message from '{1}'", _id.ToString(), this.RemoteAddress.ToString()), MY_TRACE_CATEGORY);
//						else
//							Debug.WriteLine(string.Format("Server-Side connection '{0}' trying to read next incoming message from '{1}'", _id.ToString(), this.RemoteAddress.ToString()), MY_TRACE_CATEGORY);

						// read a single message
						HttpMessage message = null;
							
						// lock the reader
						lock(_messageReader)
						{
							// read a message
							message = _messageReader.Read(_socket, _stopEvent);
						}

						// what type of message is this ?						
						switch(message.Type)
						{
								/*
								 * process the request
								 * */
							case HttpMessageTypes.HttpRequest:
							{	
								// create a request event args
								HttpRequestCancelEventArgs e = new HttpRequestCancelEventArgs(new HttpRequest(message), false);					
								
								// process the request by dispatching it and then responding if need be
								this.OnRequestReceived(this, e);
								
								//								// next check the request to see if the connection should be closed after the response was sent
								//								if (HttpUtils.Contains(e.Request.Connection, HttpConnections.Close))
								//								{
								//									// yup, they wanted us to close the connection automatically so lets do that now
								//									this.Close();
								//									return;
								//								}
								break;
							}
								/*
								 * process the response
								 * */
							case HttpMessageTypes.HttpResponse:
							{
								this.OnResponseReceived(this, new HttpResponseEventArgs(new HttpResponse(message)));
								break;
							}
								/*
								 * an unknown message type
								 * */
							default:
							{	
								// hopefully this will never happen!
								Debug.WriteLine(string.Format("A message of unknown type was received from '{0}'...\n{1}", message));	
								break;
							}							
						};
					}
					catch(HttpMessageReaderAbortedException)
					{
						// the reader was aborted
					}
					catch(HttpConnectionClosedByPeerException) 
					{					
						/*
						* the remote host has closed the connection
						* */
						this.Close();
						return;
					}
					
					// see if we should stop receiving
					if (_stopEvent != null)
						if (_stopEvent.WaitOne(1, false)) 
						{
							/*
							* we have recieved a signal that we should stop receiving
							* and disconnect the current connection
							* */
							if (_disconnectOnStop)
								this.Close();
							return;
						}							
				}
												
			}
			catch(ThreadAbortException) 
			{
				/*
				 * the thread is aborting
				 * */
				if (_disconnectOnStop)
					this.Close();
			}
			catch(ObjectDisposedException) 
			{
				/*
				 * the connection has closed the socket
				 * */				
				this.Close();
			}
			catch(SocketException ex) 
			{
				// if the connection is reset, or a blocking call was cancelled with a call to cancelblockingcall
				if (ex.ErrorCode == (int)SocketErrors.WSAECONNRESET ||
					ex.ErrorCode == (int)SocketErrors.WSAEINTR) 
				{
					this.Close();
					return;
				}

				// notify that this connection has encountered an exception
				this.OnException(this, new ExceptionEventArgs(ex));
			}
			catch(Exception ex) 
			{
				// notify that this connection has encountered an exception
				this.OnException(this, new ExceptionEventArgs(ex));
			}
//			finally
//			{
//				Debug.WriteLineIf(!_isServerSideConnection, string.Format("*** exiting receiving thread loop for connection '{0}'", _id.ToString()), MY_TRACE_CATEGORY);
//			}
		}
		/// <summary>
		/// Provides a virtual method to override and perform custom processing on a background thread
		/// </summary>
		/// <param name="args"></param>
		protected virtual void OnRun(object sender, BackgroundThreadStartEventArgs e)
		{
			try
			{
				if (this.Run != null)
					this.Run(sender, e);
			}
			catch(ThreadAbortException)
			{
			}
			catch(Exception ex)
			{
				Trace.WriteLine(ex);
			}			
		}		
		/// <summary>
		/// Monitors the jobs in the job queue and delegates threads to service the waiting jobs
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void OnProcessJobs(object sender, BackgroundThreadStartEventArgs e)
		{
			try
			{
				// continuously monitor the job queue and thread count
				while(true)
				{		
					// lock the thread list
					lock(this.ThreadList.SyncRoot)
					{
						// if we haven't reached the max thread limit
						if (this.ThreadList.Count < _maxThreads)
						{				
							// lock the job queue
							lock(this.JobQueue.SyncRoot)
							{
								// if there are jobs waiting
								if (this.JobQueue.Count > 0)
								{
									// dequeue the next waiting job
									BackgroundThreadPoolJob job = this.JobQueue.Dequeue();

									// create a new background thread pool thread to process the job
									BackgroundThreadPoolThread thread = new BackgroundThreadPoolThread(job);															

									// and finally add the thread to our list of threads
									this.ThreadList.Add(thread);
								}
							}
						}	
   					
						this.DestroyThreads(true /* only the finished ones */);
					}

					Thread.Sleep(100);
				}
			}
			catch(ThreadAbortException)
			{
				// the processing thread is aborting
			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex);
			}
		}
		/// <summary>
		/// Runs the background thread that listens for incoming connections
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnThreadRun(object sender, BackgroundThreadStartEventArgs e)
		{
			try
			{
				IPEndPoint ep = (IPEndPoint)e.Args[0];
            
				Debug.Assert(ep != null);
				Trace.WriteLineIf(_verbose, string.Format("Binding to the end point '{0}'.", ep.ToString()), MY_TRACE_CATEGORY);
                  
				_listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
				_listeningSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
				_listeningSocket.Bind(ep);
            
				Trace.WriteLineIf(_verbose, string.Format("Listening for inbound connections on '{0}'.", ep.ToString()), MY_TRACE_CATEGORY);

				while(true)
				{           
					_listeningSocket.Listen(100); // pending connections queue length

					// accept the connection
					Socket socket = _listeningSocket.Accept();
      
					Trace.WriteLineIf(_verbose, string.Format("Accepted an inbound connection from '{0}'.", socket.RemoteEndPoint.ToString()), MY_TRACE_CATEGORY);

					// create a new connection for the connection
					HttpConnection connection = new HttpConnection(socket, _verbose);
					connection.RequestDispatcher = _dispatcher;
					connection.Exception += new ExceptionEventHandler(this.OnConnectionException);
					connection.Opened += new HttpConnectionEventHandler(this.OnConnectionOpened);
					connection.Closed += new HttpConnectionEventHandler(this.OnConnectionClosed); 
					connection.IsServerSideConnection = true;
					connection.BeginSession(true);                                       
				}  
			}
			catch(ThreadAbortException)
			{
			}
			catch(Exception ex)
			{
				this.OnException(this, new ExceptionEventArgs(ex));
			}
		}
Beispiel #10
0
		private void OnThreadRun(object sender, BackgroundThreadStartEventArgs e)
		{
//			const int SOCKET_ERROR = -1;
			
			try
			{
				string address = (string)e.Args[0];
				int timesToPing = (int)e.Args[1];

				#region Address Resolution

				bool isHostName = false;
				IPAddress ipAddress = null;
				try
				{
					ipAddress = IPAddress.Parse(address);
				}
				catch(Exception)
				{
					try
					{
						ipAddress = Dns.GetHostByName(address).AddressList[0];
						isHostName = true;
					}
					catch(Exception ex)
					{
						throw ex;
					}
				}

				#endregion
				
				// create the source and destination end points
				IPEndPoint sourceIPEP = new IPEndPoint(IPAddress.Any, 0);
				IPEndPoint destinationIPEP = new IPEndPoint(ipAddress, 0);

				EndPoint source = sourceIPEP;
				EndPoint destination = destinationIPEP;

				// create an icmp socket
				Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
				
				// create an icmp echo packet
				IcmpEchoPacket packet = new IcmpEchoPacket();

				// serialize the packet to a byte array
				byte[] bytes = IcmpPacket.GetBytes(packet);

				// create the checksum for the packet based on it's data
				packet.Checksum = IcmpPacket.CreateChecksum(bytes);
				
				// create a packet reader and writer
				IcmpPacketReader reader = new IcmpPacketReader();
				IcmpPacketWriter writer = new IcmpPacketWriter();				

				// raise the ping started event
				this.OnPingStarted(this, new PingerEventArgs(address, isHostName, ipAddress, timesToPing));

				// ping statistics
				int packetsSent = 0;
				int packetsReceived = 0;				
				int[] elapsedTimes = new int[timesToPing];

				// now ping the destination X number of times as instructed
				for(int i = 0; i < timesToPing; i++)
				{
					int start = System.Environment.TickCount;
					int end = 0;
					int elapsed = 0;

					try
					{
						// send the icmp echo request					
						int bytesSent = writer.Write(socket, packet, destination);	
						
						packetsSent++;

						// wait for a response
						IcmpPacket response;
						int bytesReceived;
						bool receivedResponse = reader.Read(socket, source, 1000 /* 1 second timeout */, out response, out bytesReceived);
						
						// calculate the end and elapsed time in milliseconds
						end = System.Environment.TickCount;
						elapsed = end - start;
						
						elapsedTimes[i] = elapsed;

						if (receivedResponse)
							packetsReceived++;

						// raise the ping result event	
						this.OnPingResult(this, new PingerResultEventArgs(address, isHostName, ipAddress, timesToPing, !receivedResponse, bytesReceived, elapsed));
					}
					catch(Exception ex)
					{
						/*
						 * this should never hit
						 * 
						 * raw sockets shouldn't pose a problem when targeting icmp 
						 * */
						this.OnException(this, new ExceptionEventArgs(ex));
					}									
				}
				
				// calculate the percentage lost
				int percentLost = (int)(((double)(packetsSent - packetsReceived) / (double)packetsSent) * 100d);
				int min = int.MaxValue;
				int max = int.MinValue;
				int average = 0;
				int total = 0;
				for(int i = 0; i < timesToPing; i++)
				{
					if (elapsedTimes[i] < min)
						min = elapsedTimes[i];

					if (elapsedTimes[i] > max)
						max = elapsedTimes[i];

					total += elapsedTimes[i];
				}

				average = (int)((double)total / (double)timesToPing);

				PingerStatisticsEventArgs ea = new PingerStatisticsEventArgs(
					address, isHostName, ipAddress, timesToPing, 
					packetsSent, 
					packetsReceived, 
					packetsSent - packetsReceived,
					percentLost, 
					min, 
					max, 
					average);

				this.OnPingStatistics(this, ea);
			}
			catch(ThreadAbortException)
			{

			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex);
				this.OnException(this, new ExceptionEventArgs(ex));
			}
			finally
			{

			}
		}
		/// <summary>
		/// Looks up the connection manager responsible for the address book item and disconnects it from the remote host
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnDisconnectSessionForAddressBookItem(object sender, BackgroundThreadStartEventArgs e)
		{
			// retrieve the address book item that is requiring attention
			AddressBookItem item = (AddressBookItem)e.Args[0];

			try
			{  
				lock(_sessionManagers)
				{
					AddressBookItemConnectionManager manager = _sessionManagers[item];
					if (manager != null)
						manager.Disconnect();
				}
			}
			catch(ThreadAbortException)
			{
				// ignore thread abort exceptions
			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex);				
			}
		}
		/// <summary>
		/// Creates a connection manager for the address book item, and connects the connection to the remote host specified by the address book item
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnConnectSessionForAddressBookItem(object sender, BackgroundThreadStartEventArgs e)
		{			
			// retrieve the address book item that is requiring attention
			AddressBookItem item = (AddressBookItem)e.Args[0];
			bool disconnectFirst = (bool)e.Args[1];
			bool verboseSession	 = (bool)e.Args[2];
			bool autoRecv		 = (bool)e.Args[3];

			try
			{  
				/*
				 * if we are supposed to disconnect the current connection first
				 * */
				if (disconnectFirst)
				{
					lock(_sessionManagers)
					{
						// look up the item to see if an existing connection is already in use
						AddressBookItemConnectionManager prevManager = _sessionManagers[item];

						// if a connection manager is found for the item then disconnect it
						if (prevManager != null)
							prevManager.Disconnect();
					}
				}

				// create a new tcp connection in verbose mode
				HttpConnection connection = new HttpConnection(verboseSession);       
            
				// create a new connection manager to manage the connection
				AddressBookItemConnectionManager manager = new AddressBookItemConnectionManager(item, connection);

				// wire up to the manager's events
				manager.ConnectionEstablishContext += new AddressBookItemConnectionManagerContextEventHandler(OnConnectionEstablishContext);
				manager.ConnectionResolvingAddress += new AddressBookItemConnectionManagerResolvingAddressEventHandler(OnConnectionResolvingAddress);
				manager.BeforeConnectionOpened += new AddressBookItemConnectionManagerCancelEventHandler(OnBeforeConnectionOpened);
				manager.BeforeConnectionClosed += new AddressBookItemConnectionManagerCancelEventHandler(OnBeforeConnectionClosed);
				manager.ConnectionOpened += new AddressBookItemConnectionManagerEventHandler(OnConnectionOpened);
				manager.ConnectionClosed += new AddressBookItemConnectionManagerEventHandler(OnConnectionClosed);
				manager.ConnectionException += new AddressBookItemConnectionManagerExceptionEventHandler(OnConnectionException);
				
				// create the thread context that will enable us to determine the background thread upon which this connection manager is operating
				manager.ThreadContext = new AddressBookItemBackgroundThreadContext((BackgroundThread)sender, item);

				// instruct the manager to connect the connection to the remote host
				// pass it instructions on whether it should begin receiving automatically or not
				// NOTE: In almost every case from a client created connection this will be false. 
				//		 Only server created sessions will be set to automatically receive.
				manager.Connect(autoRecv, manager.ThreadContext);
            
				// add the connection manager to our list of connection managers
				lock(_sessionManagers)
					_sessionManagers.Add(manager);				
			}
			catch(ThreadAbortException)
			{
				// ignore thread abort exceptions
			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex);				
			}
		}