/// <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> /// 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)); } }
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); } }