History

Renamed folders and separated GSF.Media and GSF.Net into separate projects.

StephenCWills committed 14 years ago

Commit ac1ef661 parent 45bce55628 files · +733 −461Browse files

Showing the changes to Source/Libraries/GSF.ServiceProcess/ClientHelper.cs (1 of 628 files). Show all

Unified · Split

Source/Libraries/GSF.ServiceProcess/ClientHelper.cs+1013−0
@@ -0,0 +1,1013 @@
1//*******************************************************************************************************
2// ClientHelper.cs - Gbtc
3//
4// Tennessee Valley Authority, 2009
5// No copyright is claimed pursuant to 17 USC § 105. All Other Rights Reserved.
6//
7// This software is made freely available under the TVA Open Source Agreement (see below).
8//
9// Code Modification History:
10// -----------------------------------------------------------------------------------------------------
11// 08/29/2006 - Pinal C. Patel
12// Original version of source code generated.
13// 11/30/2007 - Pinal C. Patel
14// Modified the "design time" check in EndInit() method to use LicenseManager.UsageMode property
15// instead of DesignMode property as the former is more accurate than the latter.
16// 09/30/2008 - J. Ritchie Carroll
17// Convert to C#.
18// 07/15/2009 - Pinal C. Patel
19// Added AuthenticationMethod, AuthenticationUsername and AuthenticationPassword properties to
20// provision for the authentication process as part of security.
21// Added ISupportLifecycle, ISupportInitialize and IPersistSettings interface implementations
22// to support the persistance and retrieval of settings from the config file.
23// 07/17/2009 - Pinal C. Patel
24// Added static PretendRequest() method that can be used to create pretend request for manually
25// invoking request handlers registered with the ServiceHelper.
26// 07/21/2009 - Pinal C. Patel
27// Replace AuthenticationUsername and AuthenticationPassword properties with AuthenticationInput
28// to allow for input text to be specified for any AuthenticationMethod instead of just Ntml.
29// 07/23/2009 - Pinal C. Patel
30// ReceivedServiceResponse is now raised only for custom service responses instead of all.
31// 09/14/2009 - Stephen C. Wills
32// Added new header and license agreement.
33// 10/23/2009 - Pinal C. Patel
34// Modified ReceivedServiceUpdate event to support the change in ServiceHelper.UpdateStatus().
35// 06/16/2010 - Pinal C. Patel
36// Made changes necessary to implement role-based security.
37// 04/14/2011 - Pinal C. Patel
38// Updated to use new deserialization methods in GSF.Serialization class.
39//
40//*******************************************************************************************************
41
42#region [ TVA Open Source Agreement ]
43/*
44
45 THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE,REPRODUCTION, DISTRIBUTION,
46 MODIFICATION AND REDISTRIBUTION OF CERTAIN COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE
47 TENNESSEE VALLEY AUTHORITY, A CORPORATE AGENCY AND INSTRUMENTALITY OF THE UNITED STATES GOVERNMENT
48 ("GOVERNMENT AGENCY"). GOVERNMENT AGENCY IS AN INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT
49 DISTRIBUTIONS OR REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO USES, REPRODUCES, DISTRIBUTES,
50 MODIFIES OR REDISTRIBUTES THE SUBJECT SOFTWARE, AS DEFINED HEREIN, OR ANY PART THEREOF, IS, BY THAT
51 ACTION, ACCEPTING IN FULL THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS AGREEMENT.
52
53 Original Software Designation: openPDC
54 Original Software Title: The GSF Open Source Phasor Data Concentrator
55 User Registration Requested. Please Visit https://naspi.tva.com/Registration/
56 Point of Contact for Original Software: J. Ritchie Carroll <mailto:jrcarrol@tva.gov>
57
58 1. DEFINITIONS
59
60 A. "Contributor" means Government Agency, as the developer of the Original Software, and any entity
61 that makes a Modification.
62
63 B. "Covered Patents" mean patent claims licensable by a Contributor that are necessarily infringed by
64 the use or sale of its Modification alone or when combined with the Subject Software.
65
66 C. "Display" means the showing of a copy of the Subject Software, either directly or by means of an
67 image, or any other device.
68
69 D. "Distribution" means conveyance or transfer of the Subject Software, regardless of means, to
70 another.
71
72 E. "Larger Work" means computer software that combines Subject Software, or portions thereof, with
73 software separate from the Subject Software that is not governed by the terms of this Agreement.
74
75 F. "Modification" means any alteration of, including addition to or deletion from, the substance or
76 structure of either the Original Software or Subject Software, and includes derivative works, as that
77 term is defined in the Copyright Statute, 17 USC § 101. However, the act of including Subject Software
78 as part of a Larger Work does not in and of itself constitute a Modification.
79
80 G. "Original Software" means the computer software first released under this Agreement by Government
81 Agency entitled openPDC, including source code, object code and accompanying documentation, if any.
82
83 H. "Recipient" means anyone who acquires the Subject Software under this Agreement, including all
84 Contributors.
85
86 I. "Redistribution" means Distribution of the Subject Software after a Modification has been made.
87
88 J. "Reproduction" means the making of a counterpart, image or copy of the Subject Software.
89
90 K. "Sale" means the exchange of the Subject Software for money or equivalent value.
91
92 L. "Subject Software" means the Original Software, Modifications, or any respective parts thereof.
93
94 M. "Use" means the application or employment of the Subject Software for any purpose.
95
96 2. GRANT OF RIGHTS
97
98 A. Under Non-Patent Rights: Subject to the terms and conditions of this Agreement, each Contributor,
99 with respect to its own contribution to the Subject Software, hereby grants to each Recipient a
100 non-exclusive, world-wide, royalty-free license to engage in the following activities pertaining to
101 the Subject Software:
102
103 1. Use
104
105 2. Distribution
106
107 3. Reproduction
108
109 4. Modification
110
111 5. Redistribution
112
113 6. Display
114
115 B. Under Patent Rights: Subject to the terms and conditions of this Agreement, each Contributor, with
116 respect to its own contribution to the Subject Software, hereby grants to each Recipient under Covered
117 Patents a non-exclusive, world-wide, royalty-free license to engage in the following activities
118 pertaining to the Subject Software:
119
120 1. Use
121
122 2. Distribution
123
124 3. Reproduction
125
126 4. Sale
127
128 5. Offer for Sale
129
130 C. The rights granted under Paragraph B. also apply to the combination of a Contributor's Modification
131 and the Subject Software if, at the time the Modification is added by the Contributor, the addition of
132 such Modification causes the combination to be covered by the Covered Patents. It does not apply to
133 any other combinations that include a Modification.
134
135 D. The rights granted in Paragraphs A. and B. allow the Recipient to sublicense those same rights.
136 Such sublicense must be under the same terms and conditions of this Agreement.
137
138 3. OBLIGATIONS OF RECIPIENT
139
140 A. Distribution or Redistribution of the Subject Software must be made under this Agreement except for
141 additions covered under paragraph 3H.
142
143 1. Whenever a Recipient distributes or redistributes the Subject Software, a copy of this Agreement
144 must be included with each copy of the Subject Software; and
145
146 2. If Recipient distributes or redistributes the Subject Software in any form other than source code,
147 Recipient must also make the source code freely available, and must provide with each copy of the
148 Subject Software information on how to obtain the source code in a reasonable manner on or through a
149 medium customarily used for software exchange.
150
151 B. Each Recipient must ensure that the following copyright notice appears prominently in the Subject
152 Software:
153
154 No copyright is claimed pursuant to 17 USC § 105. All Other Rights Reserved.
155
156 C. Each Contributor must characterize its alteration of the Subject Software as a Modification and
157 must identify itself as the originator of its Modification in a manner that reasonably allows
158 subsequent Recipients to identify the originator of the Modification. In fulfillment of these
159 requirements, Contributor must include a file (e.g., a change log file) that describes the alterations
160 made and the date of the alterations, identifies Contributor as originator of the alterations, and
161 consents to characterization of the alterations as a Modification, for example, by including a
162 statement that the Modification is derived, directly or indirectly, from Original Software provided by
163 Government Agency. Once consent is granted, it may not thereafter be revoked.
164
165 D. A Contributor may add its own copyright notice to the Subject Software. Once a copyright notice has
166 been added to the Subject Software, a Recipient may not remove it without the express permission of
167 the Contributor who added the notice.
168
169 E. A Recipient may not make any representation in the Subject Software or in any promotional,
170 advertising or other material that may be construed as an endorsement by Government Agency or by any
171 prior Recipient of any product or service provided by Recipient, or that may seek to obtain commercial
172 advantage by the fact of Government Agency's or a prior Recipient's participation in this Agreement.
173
174 F. In an effort to track usage and maintain accurate records of the Subject Software, each Recipient,
175 upon receipt of the Subject Software, is requested to register with Government Agency by visiting the
176 following website: https://naspi.tva.com/Registration/. Recipient's name and personal information
177 shall be used for statistical purposes only. Once a Recipient makes a Modification available, it is
178 requested that the Recipient inform Government Agency at the web site provided above how to access the
179 Modification.
180
181 G. Each Contributor represents that that its Modification does not violate any existing agreements,
182 regulations, statutes or rules, and further that Contributor has sufficient rights to grant the rights
183 conveyed by this Agreement.
184
185 H. A Recipient may choose to offer, and to charge a fee for, warranty, support, indemnity and/or
186 liability obligations to one or more other Recipients of the Subject Software. A Recipient may do so,
187 however, only on its own behalf and not on behalf of Government Agency or any other Recipient. Such a
188 Recipient must make it absolutely clear that any such warranty, support, indemnity and/or liability
189 obligation is offered by that Recipient alone. Further, such Recipient agrees to indemnify Government
190 Agency and every other Recipient for any liability incurred by them as a result of warranty, support,
191 indemnity and/or liability offered by such Recipient.
192
193 I. A Recipient may create a Larger Work by combining Subject Software with separate software not
194 governed by the terms of this agreement and distribute the Larger Work as a single product. In such
195 case, the Recipient must make sure Subject Software, or portions thereof, included in the Larger Work
196 is subject to this Agreement.
197
198 J. Notwithstanding any provisions contained herein, Recipient is hereby put on notice that export of
199 any goods or technical data from the United States may require some form of export license from the
200 U.S. Government. Failure to obtain necessary export licenses may result in criminal liability under
201 U.S. laws. Government Agency neither represents that a license shall not be required nor that, if
202 required, it shall be issued. Nothing granted herein provides any such export license.
203
204 4. DISCLAIMER OF WARRANTIES AND LIABILITIES; WAIVER AND INDEMNIFICATION
205
206 A. No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND, EITHER
207 EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT
208 SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
209 PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR
210 FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. THIS
211 AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR
212 RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS
213 RESULTING FROM USE OF THE SUBJECT SOFTWARE. FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND
214 LIABILITIES REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT
215 "AS IS."
216
217 B. Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST GOVERNMENT AGENCY, ITS
218 AGENTS, EMPLOYEES, CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE
219 OF THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM
220 SUCH USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE
221 SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS GOVERNMENT AGENCY, ITS AGENTS,
222 EMPLOYEES, CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY
223 LAW. THE FOREGOING RELEASE AND INDEMNIFICATION SHALL APPLY EVEN IF THE LIABILITIES, DEMANDS, DAMAGES,
224 EXPENSES OR LOSSES ARE CAUSED, OCCASIONED, OR CONTRIBUTED TO BY THE NEGLIGENCE, SOLE OR CONCURRENT, OF
225 GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT. RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER SHALL BE THE
226 IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.
227
228 5. GENERAL TERMS
229
230 A. Termination: This Agreement and the rights granted hereunder will terminate automatically if a
231 Recipient fails to comply with these terms and conditions, and fails to cure such noncompliance within
232 thirty (30) days of becoming aware of such noncompliance. Upon termination, a Recipient agrees to
233 immediately cease use and distribution of the Subject Software. All sublicenses to the Subject
234 Software properly granted by the breaching Recipient shall survive any such termination of this
235 Agreement.
236
237 B. Severability: If any provision of this Agreement is invalid or unenforceable under applicable law,
238 it shall not affect the validity or enforceability of the remainder of the terms of this Agreement.
239
240 C. Applicable Law: This Agreement shall be subject to United States federal law only for all purposes,
241 including, but not limited to, determining the validity of this Agreement, the meaning of its
242 provisions and the rights, obligations and remedies of the parties.
243
244 D. Entire Understanding: This Agreement constitutes the entire understanding and agreement of the
245 parties relating to release of the Subject Software and may not be superseded, modified or amended
246 except by further written agreement duly executed by the parties.
247
248 E. Binding Authority: By accepting and using the Subject Software under this Agreement, a Recipient
249 affirms its authority to bind the Recipient to all terms and conditions of this Agreement and that
250 Recipient hereby agrees to all terms and conditions herein.
251
252 F. Point of Contact: Any Recipient contact with Government Agency is to be directed to the designated
253 representative as follows: J. Ritchie Carroll <mailto:jrcarrol@tva.gov>.
254
255*/
256#endregion
257
258using GSF.Communication;
259using GSF.Configuration;
260using System;
261using System.ComponentModel;
262using System.Configuration;
263using System.Drawing;
264using System.Text;
265using System.Threading;
266
267namespace GSF.ServiceProcess
268{
269 /// <summary>
270 /// Component that provides client-side functionality to <see cref="ServiceHelper"/>.
271 /// </summary>
272 [ToolboxBitmap(typeof(ClientHelper))]
273 public class ClientHelper : Component, ISupportLifecycle, ISupportInitialize, IPersistSettings
274 {
275 #region [ Members ]
276
277 // Constants
278
279 /// <summary>
280 /// Specifies the default value for the <see cref="Username"/> property.
281 /// </summary>
282 public const string DefaultUsername = "";
283
284 /// <summary>
285 /// Specifies the default value for the <see cref="Password"/> property.
286 /// </summary>
287 public const string DefaultPassword = "";
288
289 /// <summary>
290 /// Specifies the default value for the <see cref="PersistSettings"/> property.
291 /// </summary>
292 public const bool DefaultPersistSettings = false;
293
294 /// <summary>
295 /// Specifies the default value for the <see cref="SettingsCategory"/> property.
296 /// </summary>
297 public const string DefaultSettingsCategory = "ClientHelper";
298
299 // Events
300
301 /// <summary>
302 /// Occurs when a status update is received from the <see cref="ServiceHelper"/>.
303 /// </summary>
304 [Category("Client"),
305 Description("Occurs when a status update is received from the ServiceHelper.")]
306 public event EventHandler<EventArgs<UpdateType, string>> ReceivedServiceUpdate;
307
308 /// <summary>
309 /// Occurs when a custom <see cref="ServiceResponse"/> is received from the <see cref="ServiceHelper"/>.
310 /// </summary>
311 [Category("Service"),
312 Description("Occurs when a ServiceResponse is received from the ServiceHelper.")]
313 public event EventHandler<EventArgs<ServiceResponse>> ReceivedServiceResponse;
314
315 /// <summary>
316 /// Occurs when the state of the <see cref="ServiceHelper"/> is changed.
317 /// </summary>
318 [Category("Service"),
319 Description("Occurs when the state of the ServiceHelper is changed.")]
320 public event EventHandler<EventArgs<ObjectState<ServiceState>>> ServiceStateChanged;
321
322 /// <summary>
323 /// Occurs when the state of a <see cref="ServiceProcess"/> is changed.
324 /// </summary>
325 [Category("Service"),
326 Description("Occurs when the state of a ServiceProcess is changed.")]
327 public event EventHandler<EventArgs<ObjectState<ServiceProcessState>>> ProcessStateChanged;
328
329 /// <summary>
330 /// Occurs when the <see cref="ServiceHelper"/> successfully authenticates the <see cref="ClientHelper"/>.
331 /// </summary>
332 [Category("Security"),
333 Description("Occurs when the ServiceHelper successfully authenticates the ClientHelper.")]
334 public event EventHandler AuthenticationSuccess;
335
336 /// <summary>
337 /// Occurs when the <see cref="ServiceHelper"/> fails to authenticate the <see cref="ClientHelper"/>.
338 /// </summary>
339 /// <remarks>
340 /// Set <see cref="CancelEventArgs.Cancel"/> to <b>true</b> to continue with connection attempts even after authentication fails.
341 /// This can be useful for re-authenticating the <see cref="ClientHelper"/> using different <see cref="Username"/> and <see cref="Password"/>.
342 /// </remarks>
343 [Category("Security"),
344 Description("Occurs when the ServiceHelper fails to authenticate the ClientHelper.")]
345 public event EventHandler<CancelEventArgs> AuthenticationFailure;
346
347 /// <summary>
348 /// Occurs when a telnet session has been established.
349 /// </summary>
350 [Category("Command"),
351 Description("Occurs when a telnet session has been established.")]
352 public event EventHandler TelnetSessionEstablished;
353
354 /// <summary>
355 /// Occurs when a telnet session has been terminated.
356 /// </summary>
357 [Category("Command"),
358 Description("Occurs when a telnet session has been terminated.")]
359 public event EventHandler TelnetSessionTerminated;
360
361 // Fields
362 private ClientBase m_remotingClient;
363 private string m_username;
364 private string m_password;
365 private bool m_persistSettings;
366 private string m_settingsCategory;
367 private bool m_attemptReconnection;
368 private bool m_authenticationComplete;
369 private bool m_disposed;
370 private bool m_initialized;
371
372 #endregion
373
374 #region [ Constructors ]
375
376 /// <summary>
377 /// Initializes a new instance of the <see cref="ClientHelper"/> class.
378 /// </summary>
379 public ClientHelper()
380 : base()
381 {
382 m_username = DefaultUsername;
383 m_password = DefaultPassword;
384 m_persistSettings = DefaultPersistSettings;
385 m_settingsCategory = DefaultSettingsCategory;
386 }
387
388 /// <summary>
389 /// Initializes a new instance of the <see cref="ClientHelper"/> class.
390 /// </summary>
391 /// <param name="container"><see cref="IContainer"/> object that contains the <see cref="ClientHelper"/>.</param>
392 public ClientHelper(IContainer container)
393 : this()
394 {
395 if (container != null)
396 container.Add(this);
397 }
398
399 #endregion
400
401 #region [ Properties ]
402
403 /// <summary>
404 /// Gets or sets the <see cref="ClientBase"/> object used for communicating with the <see cref="ServiceHelper"/>.
405 /// </summary>
406 [Category("Components"),
407 Description("ClientBase object used for communicating with the ServiceHelper.")]
408 public ClientBase RemotingClient
409 {
410 get
411 {
412 return m_remotingClient;
413 }
414 set
415 {
416 if (m_remotingClient != null)
417 {
418 // Detach events from any existing instance
419 m_remotingClient.ConnectionEstablished -= RemotingClient_ConnectionEstablished;
420 m_remotingClient.ConnectionAttempt -= RemotingClient_ConnectionAttempt;
421 m_remotingClient.ConnectionTerminated -= RemotingClient_ConnectionTerminated;
422 m_remotingClient.ReceiveDataComplete -= RemotingClient_ReceiveDataComplete;
423 }
424
425 m_remotingClient = value;
426
427 if (m_remotingClient != null)
428 {
429 // Attach events to new instance
430 m_remotingClient.ConnectionEstablished += RemotingClient_ConnectionEstablished;
431 m_remotingClient.ConnectionAttempt += RemotingClient_ConnectionAttempt;
432 m_remotingClient.ConnectionTerminated += RemotingClient_ConnectionTerminated;
433 m_remotingClient.ReceiveDataComplete += RemotingClient_ReceiveDataComplete;
434 }
435 }
436 }
437
438 /// <summary>
439 /// Gets or sets the username of the <see cref="ClientHelper"/>'s user to be used for authenticating with the <see cref="ServiceHelper"/>.
440 /// </summary>
441 /// <exception cref="ArgumentNullException">The value being specified is a null string.</exception>
442 [Category("Security"),
443 DefaultValue(DefaultUsername),
444 Description("Username of the ClientHelper's user to be used for authenticating with the ServiceHelper.")]
445 public string Username
446 {
447 get
448 {
449 return m_username;
450 }
451 set
452 {
453 if (value == null)
454 throw new ArgumentNullException("value");
455
456 m_username = value;
457 }
458 }
459
460 /// <summary>
461 /// Gets or sets the password of the <see cref="ClientHelper"/>'s user to be used for authenticating with the <see cref="ServiceHelper"/>.
462 /// </summary>
463 /// <exception cref="ArgumentNullException">The value being specified is a null string.</exception>
464 [Category("Security"),
465 DefaultValue(DefaultPassword),
466 Description("Password of the ClientHelper's user to be used for authenticating with the ServiceHelper.")]
467 public string Password
468 {
469 get
470 {
471 return m_password;
472 }
473 set
474 {
475 if (value == null)
476 throw new ArgumentNullException("value");
477
478 m_password = value;
479 }
480 }
481
482 /// <summary>
483 /// Gets or sets a boolean value that indicates whether the settings of <see cref="ClientHelper"/> are to be saved to the config file.
484 /// </summary>
485 [Category("Persistance"),
486 DefaultValue(DefaultPersistSettings),
487 Description("Indicates whether the settings of ClientHelper are to be saved to the config file.")]
488 public bool PersistSettings
489 {
490 get
491 {
492 return m_persistSettings;
493 }
494 set
495 {
496 m_persistSettings = value;
497 }
498 }
499
500 /// <summary>
501 /// Gets or sets the category under which the settings of <see cref="ClientHelper"/> are to be saved to the config file if the <see cref="PersistSettings"/> property is set to true.
502 /// </summary>
503 /// <exception cref="ArgumentNullException">The value being assigned is a null or empty string.</exception>
504 [Category("Persistance"),
505 DefaultValue(DefaultSettingsCategory),
506 Description("Category under which the settings of ClientHelper are to be saved to the config file if the PersistSettings property is set to true.")]
507 public string SettingsCategory
508 {
509 get
510 {
511 return m_settingsCategory;
512 }
513 set
514 {
515 if (string.IsNullOrEmpty(value))
516 throw new ArgumentNullException("value");
517
518 m_settingsCategory = value;
519 }
520 }
521
522 /// <summary>
523 /// Gets or sets a boolean value that indicates whether the <see cref="ClientHelper"/> is currently enabled.
524 /// </summary>
525 /// <remarks>
526 /// <see cref="Enabled"/> property is not be set by user-code directly.
527 /// </remarks>
528 [Browsable(false),
529 EditorBrowsable(EditorBrowsableState.Never),
530 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
531 public bool Enabled
532 {
533 get
534 {
535 if (m_remotingClient == null)
536 return false;
537 else
538 return m_remotingClient.Enabled;
539 }
540 set
541 {
542 if (m_remotingClient != null)
543 m_remotingClient.Enabled = value;
544 }
545 }
546
547
548 #endregion
549
550 #region [ Methods ]
551
552 /// <summary>
553 /// Initializes the <see cref="ClientHelper"/>.
554 /// </summary>
555 /// <remarks>
556 /// <see cref="Initialize()"/> is to be called by user-code directly only if the <see cref="ClientHelper"/> is not consumed through the designer surface of the IDE.
557 /// </remarks>
558 public void Initialize()
559 {
560 if (!m_initialized)
561 {
562 LoadSettings(); // Load settings from the config file.
563 m_initialized = true; // Initialize only once.
564 }
565 }
566
567 /// <summary>
568 /// Performs necessary operations before the <see cref="ClientHelper"/> properties are initialized.
569 /// </summary>
570 /// <remarks>
571 /// <see cref="BeginInit()"/> should never be called by user-code directly. This method exists solely for use
572 /// by the designer if the <see cref="ClientHelper"/> is consumed through the designer surface of the IDE.
573 /// </remarks>
574 [EditorBrowsable(EditorBrowsableState.Never)]
575 public void BeginInit()
576 {
577 if (!DesignMode)
578 {
579 try
580 {
581 // Nothing needs to be done before component is initialized.
582 }
583 catch (Exception)
584 {
585 // Prevent the IDE from crashing when component is in design mode.
586 }
587 }
588 }
589
590 /// <summary>
591 /// Performs necessary operations after the <see cref="ClientHelper"/> properties are initialized.
592 /// </summary>
593 /// <remarks>
594 /// <see cref="EndInit()"/> should never be called by user-code directly. This method exists solely for use
595 /// by the designer if the <see cref="ClientHelper"/> is consumed through the designer surface of the IDE.
596 /// </remarks>
597 [EditorBrowsable(EditorBrowsableState.Never)]
598 public void EndInit()
599 {
600 if (!DesignMode)
601 {
602 try
603 {
604 Initialize();
605 }
606 catch (Exception)
607 {
608 // Prevent the IDE from crashing when component is in design mode.
609 }
610 }
611 }
612
613 /// <summary>
614 /// Saves settings for the <see cref="ClientHelper"/> to the config file if the <see cref="PersistSettings"/> property is set to true.
615 /// </summary>
616 /// <exception cref="ConfigurationErrorsException"><see cref="SettingsCategory"/> has a value of null or empty string.</exception>
617 public void SaveSettings()
618 {
619 if (m_persistSettings)
620 {
621 // Ensure that settings category is specified.
622 if (string.IsNullOrEmpty(m_settingsCategory))
623 throw new ConfigurationErrorsException("SettingsCategory property has not been set");
624
625 // Save settings under the specified category.
626 ConfigurationFile config = ConfigurationFile.Current;
627 CategorizedSettingsElementCollection settings = config.Settings[m_settingsCategory];
628 settings["Username", true].Update(m_username);
629 settings["Password", true].Update(m_password);
630 config.Save();
631 }
632 }
633
634 /// <summary>
635 /// Loads saved settings for the <see cref="ClientHelper"/> from the config file if the <see cref="PersistSettings"/> property is set to true.
636 /// </summary>
637 /// <exception cref="ConfigurationErrorsException"><see cref="SettingsCategory"/> has a value of null or empty string.</exception>
638 public void LoadSettings()
639 {
640 if (m_persistSettings)
641 {
642 // Ensure that settings category is specified.
643 if (string.IsNullOrEmpty(m_settingsCategory))
644 throw new ConfigurationErrorsException("SettingsCategory property has not been set");
645
646 // Load settings from the specified category.
647 ConfigurationFile config = ConfigurationFile.Current;
648 CategorizedSettingsElementCollection settings = config.Settings[m_settingsCategory];
649 settings.Add("Username", m_username, "Username to be used for authentication with the service.");
650 settings.Add("Password", m_password, "Password to be used for authentication with the service.", true);
651 Username = settings["Username"].ValueAs(m_username);
652 Password = settings["Password"].ValueAs(m_password);
653 }
654 }
655
656 /// <summary>
657 /// Connects <see cref="RemotingClient"/> to <see cref="ServiceHelper.RemotingServer"/> and wait until authentication is complete.
658 /// </summary>
659 public void Connect()
660 {
661 if (m_remotingClient == null)
662 throw new InvalidOperationException("RemotingClient property of ClientHelper component is not set");
663
664 m_attemptReconnection = true;
665 m_authenticationComplete = false;
666 m_remotingClient.Connect(); // Wait for connection.
667
668 while (!m_authenticationComplete && m_remotingClient.Enabled)
669 {
670 Thread.Sleep(100);
671 } // Wait for authentication.
672 }
673
674 /// <summary>
675 /// Disconnects <see cref="RemotingClient"/> from <see cref="ServiceHelper.RemotingServer"/>.
676 /// </summary>
677 public void Disconnect()
678 {
679 m_attemptReconnection = false;
680
681 if (m_remotingClient != null)
682 m_remotingClient.Disconnect();
683 }
684
685 /// <summary>
686 /// Sends a request to the <see cref="ServiceHelper"/> using <see cref="RemotingClient"/>.
687 /// </summary>
688 /// <param name="request">Request text to be sent.</param>
689 public void SendRequest(string request)
690 {
691 ClientRequest requestInstance = ClientRequest.Parse(request);
692
693 if (requestInstance != null)
694 SendRequest(requestInstance);
695 else
696 UpdateStatus(UpdateType.Warning, string.Format("Request command \"{0}\" is invalid\r\n\r\n", request));
697 }
698
699 /// <summary>
700 /// Sends a request to the <see cref="ServiceHelper"/> using <see cref="RemotingClient"/>.
701 /// </summary>
702 /// <param name="request"><see cref="ClientRequest"/> object to be sent.</param>
703 public void SendRequest(ClientRequest request)
704 {
705 m_remotingClient.SendAsync(request);
706 }
707
708 /// <summary>
709 /// Raises the <see cref="ReceivedServiceUpdate"/> event.
710 /// </summary>
711 /// <param name="type">One of the <see cref="UpdateType"/> values.</param>
712 /// <param name="update">Update message received.</param>
713 protected virtual void OnReceivedServiceUpdate(UpdateType type, string update)
714 {
715 if (ReceivedServiceUpdate != null)
716 ReceivedServiceUpdate(this, new EventArgs<UpdateType, string>(type, update));
717 }
718
719 /// <summary>
720 /// Raises the <see cref="ReceivedServiceResponse"/> event.
721 /// </summary>
722 /// <param name="response"><see cref="ServiceResponse"/> received.</param>
723 protected virtual void OnReceivedServiceResponse(ServiceResponse response)
724 {
725 if (ReceivedServiceResponse != null)
726 ReceivedServiceResponse(this, new EventArgs<ServiceResponse>(response));
727 }
728
729 /// <summary>
730 /// Raises the <see cref="ServiceStateChanged"/> event.
731 /// </summary>
732 /// <param name="state">New <see cref="ServiceState"/>.</param>
733 protected virtual void OnServiceStateChanged(ObjectState<ServiceState> state)
734 {
735 if (ServiceStateChanged != null)
736 ServiceStateChanged(this, new EventArgs<ObjectState<ServiceState>>(state));
737 }
738
739 /// <summary>
740 /// Raises the <see cref="ProcessStateChanged"/> event.
741 /// </summary>
742 /// <param name="state">New <see cref="ServiceProcessState"/>.</param>
743 protected virtual void OnProcessStateChanged(ObjectState<ServiceProcessState> state)
744 {
745 if (ProcessStateChanged != null)
746 ProcessStateChanged(this, new EventArgs<ObjectState<ServiceProcessState>>(state));
747 }
748
749 /// <summary>
750 /// Raises the <see cref="AuthenticationSuccess"/> event.
751 /// </summary>
752 protected virtual void OnAuthenticationSuccess()
753 {
754 m_authenticationComplete = true;
755 if (AuthenticationSuccess != null)
756 AuthenticationSuccess(this, EventArgs.Empty);
757 }
758
759 /// <summary>
760 /// Raises the <see cref="AuthenticationFailure"/> event.
761 /// </summary>
762 protected virtual void OnAuthenticationFailure()
763 {
764 CancelEventArgs args = new CancelEventArgs(true);
765 if (AuthenticationFailure != null)
766 AuthenticationFailure(this, args);
767
768 // Continue connection attempts if requested.
769 if (args.Cancel)
770 {
771 m_attemptReconnection = false;
772 m_authenticationComplete = true;
773 }
774 }
775
776 /// <summary>
777 /// Raises the <see cref="TelnetSessionEstablished"/> event.
778 /// </summary>
779 protected virtual void OnTelnetSessionEstablished()
780 {
781 if (TelnetSessionEstablished != null)
782 TelnetSessionEstablished(this, EventArgs.Empty);
783 }
784
785 /// <summary>
786 /// Raises the <see cref="TelnetSessionTerminated"/> event.
787 /// </summary>
788 protected virtual void OnTelnetSessionTerminated()
789 {
790 if (TelnetSessionTerminated != null)
791 TelnetSessionTerminated(this, EventArgs.Empty);
792 }
793
794 /// <summary>
795 /// Releases the unmanaged resources used by the <see cref="ClientHelper"/> object and optionally releases the managed resources.
796 /// </summary>
797 /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
798 protected override void Dispose(bool disposing)
799 {
800 if (!m_disposed)
801 {
802 try
803 {
804 // This will be done regardless of whether the object is finalized or disposed.
805 if (disposing)
806 {
807 // This will be done only when the object is disposed by calling Dispose().
808 Disconnect();
809 SaveSettings();
810 RemotingClient = null;
811 }
812 }
813 finally
814 {
815 m_disposed = true; // Prevent duplicate dispose.
816 base.Dispose(disposing); // Call base class Dispose().
817 }
818 }
819 }
820
821 private void UpdateStatus(UpdateType type, string message, params object[] args)
822 {
823 OnReceivedServiceUpdate(type, string.Format(message, args));
824 }
825
826 private void RemotingClient_ConnectionAttempt(object sender, System.EventArgs e)
827 {
828 UpdateStatus(UpdateType.Information, "Connecting to {0}...\r\n\r\n", m_remotingClient.ServerUri);
829 }
830
831 private void RemotingClient_ConnectionEstablished(object sender, System.EventArgs e)
832 {
833 // Upon establishing connection with the service's communication client, we'll send our information to the
834 // service so the service can keep track of all the client that are connected to its communication server.
835 m_remotingClient.SendAsync(new ClientInfo(this));
836
837 StringBuilder status = new StringBuilder();
838 status.AppendFormat("Connected to {0}:", m_remotingClient.ServerUri);
839 status.AppendLine();
840 status.AppendLine();
841 status.Append(m_remotingClient.Status);
842 status.AppendLine();
843 UpdateStatus(UpdateType.Information, status.ToString());
844 }
845
846 private void RemotingClient_ConnectionTerminated(object sender, System.EventArgs e)
847 {
848 StringBuilder status = new StringBuilder();
849 status.AppendFormat("Disconnected from {0}:", m_remotingClient.ServerUri);
850 status.AppendLine();
851 status.AppendLine();
852 status.Append(m_remotingClient.Status);
853 status.AppendLine();
854 UpdateStatus(UpdateType.Warning, status.ToString());
855
856 // Attempt reconnection on a seperate thread.
857 if (m_attemptReconnection)
858 new Thread((ThreadStart)delegate()
859 {
860 Connect();
861 }).Start();
862 }
863
864 private void RemotingClient_ReceiveDataComplete(object sender, EventArgs<byte[], int> e)
865 {
866 ServiceResponse response = null;
867 Serialization.TryDeserialize<ServiceResponse>(e.Argument1.BlockCopy(0, e.Argument2), SerializationFormat.Binary, out response);
868 if (response != null)
869 {
870 switch (response.Type)
871 {
872 case "UPDATECLIENTSTATUS-INFORMATION":
873 UpdateStatus(UpdateType.Information, response.Message);
874 break;
875 case "UPDATECLIENTSTATUS-WARNING":
876 UpdateStatus(UpdateType.Warning, response.Message);
877 break;
878 case "UPDATECLIENTSTATUS-ALARM":
879 UpdateStatus(UpdateType.Alarm, response.Message);
880 break;
881 case "AUTHENTICATIONSUCCESS":
882 OnAuthenticationSuccess();
883 break;
884 case "AUTHENTICATIONFAILURE":
885 OnAuthenticationFailure();
886 break;
887 case "SERVICESTATECHANGED":
888 if (response.Attachments.Count > 0)
889 {
890 ObjectState<ServiceState> state = response.Attachments[0] as ObjectState<ServiceState>;
891
892 if (state != null)
893 {
894 // Notify change in service state by raising an event.
895 OnServiceStateChanged(state);
896
897 // Provide a status update for change in state of the service.
898 UpdateType type = UpdateType.Information;
899 switch (state.CurrentState)
900 {
901 case ServiceState.Stopped:
902 case ServiceState.Paused:
903 case ServiceState.Shutdown:
904 type = UpdateType.Warning;
905 break;
906 }
907 UpdateStatus(type, string.Format("State of service \"{0}\" has changed to \"{1}\".\r\n\r\n", state.ObjectName, state.CurrentState));
908 }
909 }
910 break;
911 case "PROCESSSTATECHANGED":
912 if (response.Attachments.Count > 0)
913 {
914 ObjectState<ServiceProcessState> state = response.Attachments[0] as ObjectState<ServiceProcessState>;
915
916 if (state != null)
917 {
918 // Notify change in process state by raising an event.
919 OnProcessStateChanged(state);
920
921 // Provide a status update for change in state of the service process.
922 UpdateType type = UpdateType.Information;
923 switch (state.CurrentState)
924 {
925 case ServiceProcessState.Aborted:
926 case ServiceProcessState.Exception:
927 type = UpdateType.Alarm;
928 break;
929
930 }
931 UpdateStatus(type, string.Format("State of process \"{0}\" has changed to \"{1}\".\r\n\r\n", state.ObjectName, state.CurrentState));
932 }
933 }
934 break;
935 case "TELNETSESSION":
936 switch (response.Message.ToUpper())
937 {
938 case "ESTABLISHED":
939 OnTelnetSessionEstablished();
940 break;
941 case "TERMINATED":
942 OnTelnetSessionTerminated();
943 break;
944 }
945 break;
946 default:
947 OnReceivedServiceResponse(response);
948 break;
949 }
950 }
951 }
952
953 #endregion
954
955 #region [ Static ]
956
957 /// <summary>
958 /// Returns an <see cref="ClientRequestInfo"/> object for the specified <paramref name="requestCommand"/> that can be used
959 /// to invoke <see cref="ServiceHelper.ClientRequestHandlers"/> manually as if the request was sent by a <see cref="ClientHelper"/> remotely.
960 /// </summary>
961 /// <param name="requestCommand">Command for which an <see cref="ClientRequestInfo"/> object is to be created.</param>
962 /// <returns>An <see cref="ClientRequestInfo"/> object.</returns>
963 public static ClientRequestInfo PretendRequest(string requestCommand)
964 {
965 ClientRequest request = ClientRequest.Parse(requestCommand);
966 ClientRequestInfo requestInfo = new ClientRequestInfo(new ClientInfo(), request);
967
968 return requestInfo;
969 }
970
971 /// <summary>
972 /// Attempts to parse an actionable reponse sent from the service.
973 /// </summary>
974 /// <param name="serviceResponse"><see cref="ServiceResponse"/> to test for actionable response.</param>
975 /// <param name="sourceCommand">Command that invoked <paramref name="serviceResponse"/>.</param>
976 /// <param name="responseSuccess">Boolean success state of <paramref name="serviceResponse"/>.</param>
977 /// <returns><c>true</c> if actionable response was able to be parsed successfully; otherwise <c>false</c>.</returns>
978 public static bool TryParseActionableResponse(ServiceResponse serviceResponse, out string sourceCommand, out bool responseSuccess)
979 {
980 bool parseSucceeded = false;
981
982 sourceCommand = null;
983 responseSuccess = false;
984
985 try
986 {
987 string response = serviceResponse.Type;
988
989 // Attempt to parse response message
990 if (!string.IsNullOrWhiteSpace(response))
991 {
992 // Reponse types are formatted as "Command:Success" or "Command:Failure"
993 string[] parts = response.Split(':');
994
995 if (parts.Length > 1)
996 {
997 sourceCommand = parts[0].Trim().ToTitleCase();
998 responseSuccess = (string.Compare(parts[1].Trim(), "Success", true) == 0);
999 parseSucceeded = true;
1000 }
1001 }
1002 }
1003 catch
1004 {
1005 parseSucceeded = false;
1006 }
1007
1008 return parseSucceeded;
1009 }
1010
1011 #endregion
1012 }
1013}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t