)>}]
شركة التطبيقات المتكاملة لتصميم وبرمجة البرمجيات الخاصة ش.ش.و.
Integrated Applications Programming Company
Home » Code Library » TelnetModel (Ia.Ftn.Cl.Models.Client)

Public general use code classes and xml files that we've compiled and used over the years:

This class encapsulates the "Model" part of the Model-View-Controller design pattern, and is used by samples that utilize the PowerTCP Telnet component (part of the Emulation for .NET and Telnet for .NET products). This class can be added to additional applications without the need for cut-and-paste. Note that because this class is used in both the Emulation and Telnet product samples, a compile-time directive indicates which namespace to use (Dart.Emulation or Dart.Telnet).

    1: using System;
    2: using System.Collections.Generic;
    3: using System.Text;
    4: using System.Security.Cryptography.X509Certificates;
    5: using System.Security.Authentication;
    6: using System.Net.Security;
    7: using System.IO;
    8: using static System.Net.WebRequestMethods;
    9: using System.Xml.Serialization;
   10: using System.Reflection;
   11: using System.Runtime.InteropServices;
   12: using Dart.Telnet;
   13: #if EMULATION
   14: using Dart.Emulation;
   15: #elif TELNET
   16: using Dart.Telnet;
   17: #endif
   18:  
   19: namespace Ia.Ftn.Cl.Models.Client
   20: {
   21:     ////////////////////////////////////////////////////////////////////////////
   22:  
   23:     /// <summary publish="true">
   24:     /// This class encapsulates the "Model" part of the Model-View-Controller design pattern, and is used by samples that 
   25:     /// utilize the PowerTCP Telnet component (part of the Emulation for .NET and Telnet for .NET products).  This class
   26:     /// can be added to additional applications without the need for cut-and-paste.  Note that because this class is used 
   27:     /// in both the Emulation and Telnet product samples, a compile-time directive indicates which namespace to use
   28:     /// (Dart.Emulation or Dart.Telnet).
   29:     /// </summary>
   30:     /// <remarks>
   31:     /// This class is marked with the Serializable attribute so values can be easily stored, and restored later.
   32:     /// </remarks>
   33:  
   34:     /// <summary/>
   35:     public enum SecurityType { None, Explicit, Implicit };
   36:  
   37:     ////////////////////////////////////////////////////////////////////////////
   38:  
   39:     /// <summary>
   40:     ///
   41:     /// </summary>
   42:     [Serializable]
   43:     public class TelnetModel
   44:     {
   45:         [NonSerialized]
   46:         public Telnet Telnet;
   47:         private TcpSession session;
   48:         private Credentials credentials;
   49:         private string commandString;
   50:         private bool receiveLoopRequired;
   51:         private SecurityType securityType;
   52:         private bool localEcho;
   53:         private bool useCrLf;
   54:  
   55:         [Serializable]
   56:         public class SessionData
   57:         {
   58:             [XmlElement(Order = 1)]
   59:             public string commandString;
   60:             [XmlElement(Order = 2)]
   61:             public SecurityType securityType;
   62:             [XmlElement(Order = 3)]
   63:             public Credentials credentials;
   64:             [XmlElement(Order = 4)]
   65:             public TcpSession session;
   66:         }
   67:  
   68:         ////////////////////////////////////////////////////////////////////////////
   69:  
   70:         /// <summary>
   71:         ///
   72:         /// </summary>
   73:         public TelnetModel()
   74:         {
   75:             try
   76:             {
   77:                 //Create tcpModel from serialized TcpModel saved to disk
   78:                 SessionData sessionData = this.DeserializeSession<SessionData>(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SessionData.xml"));
   79:                 this.commandString = sessionData.commandString;
   80:                 this.securityType = sessionData.securityType;
   81:                 this.credentials = sessionData.credentials;
   82:                 this.session = sessionData.session;
   83:             }
   84:             catch
   85:             {
   86:                 //No model saved to disk, so create new one
   87:                 this.session = new TcpSession();
   88:                 this.Session.RemoteEndPoint.Port = 23;
   89:                 this.credentials = new Credentials();
   90:                 this.commandString = "";
   91:                 this.securityType = SecurityType.None;
   92:             }
   93:  
   94:             this.session.Security.ValidationCallback = this.RemoteCertificateValidation;
   95:             this.session.Security.SelectionCallback = this.LocalCertificateValidation;
   96:             this.receiveLoopRequired = true;
   97:             this.useCrLf = true;
   98:             this.localEcho = false;
   99:         }
  100:  
  101:         #region Serialization
  102:         /// <summary>
  103:         /// Retrieves a session configuration from a serialized file
  104:         /// </summary
  105:         protected T DeserializeSession<T>(string file) where T : class
  106:         {
  107:             // Deserialize session from previous serialization (if present)
  108:             using (FileStream fs = new FileStream(file, FileMode.Open))
  109:             {
  110:                 System.Xml.Serialization.XmlSerializer xs =
  111:                 new System.Xml.Serialization.XmlSerializer(typeof(T));
  112:  
  113:                 return xs.Deserialize(fs) as T;
  114:             }
  115:         }
  116:  
  117:         /// <summary>
  118:         /// Saves a session configuration to a serialized file
  119:         /// </summary>    
  120:         protected void SerializeSession<T>(T session, string file)
  121:         {
  122:             try
  123:             {
  124:                 using (FileStream fs = new FileStream(file, FileMode.Create))
  125:                 {
  126:                     System.Xml.Serialization.XmlSerializer xs =
  127:                         new System.Xml.Serialization.XmlSerializer(typeof(T));
  128:  
  129:                     xs.Serialize(fs, session);
  130:                 }
  131:             }
  132:             catch { }
  133:         }
  134:         #endregion
  135:  
  136:         ////////////////////////////////////////////////////////////////////////////
  137:  
  138:         /// <summary>
  139:         ///
  140:         /// </summary>
  141:         public void SaveSession()
  142:         {
  143:             //Save session to disk
  144:             SessionData sessionData = new SessionData();
  145:             sessionData.commandString = this.commandString;
  146:             sessionData.securityType = this.securityType;
  147:             sessionData.credentials = this.credentials;
  148:             sessionData.session = this.session;
  149:  
  150:             this.SerializeSession<SessionData>(sessionData, "SessionData.xml");
  151:         }
  152:  
  153:         ////////////////////////////////////////////////////////////////////////////
  154:  
  155:         /// <summary>
  156:         ///
  157:         /// </summary>
  158:         public TcpSession Session
  159:         {
  160:             get { return this.session; }
  161:         }
  162:  
  163:         ////////////////////////////////////////////////////////////////////////////
  164:  
  165:         /// <summary>
  166:         ///
  167:         /// </summary>
  168:         public Credentials Credentials
  169:         {
  170:             get { return this.credentials; }
  171:         }
  172:  
  173:         ////////////////////////////////////////////////////////////////////////////
  174:  
  175:         /// <summary>
  176:         ///
  177:         /// </summary>
  178:         public string CommandString
  179:         {
  180:             get { return this.commandString; }
  181:             set { this.commandString = value; }
  182:         }
  183:  
  184:         ////////////////////////////////////////////////////////////////////////////
  185:  
  186:         /// <summary>
  187:         ///
  188:         /// </summary>
  189:         public bool ReceiveLoopRequired
  190:         {
  191:             get { return this.receiveLoopRequired; }
  192:             set { this.receiveLoopRequired = value; }
  193:         }
  194:  
  195:         ////////////////////////////////////////////////////////////////////////////
  196:  
  197:         /// <summary>
  198:         ///
  199:         /// </summary>
  200:         public SecurityType SecurityType
  201:         {
  202:             get { return this.securityType; }
  203:             set
  204:             {
  205:                 this.securityType = value;
  206:                 this.session.Security.Protocols = (this.securityType == SecurityType.None)
  207:                     ? SslProtocols.None : SslProtocols.Default;
  208:             }
  209:         }
  210:  
  211:         ////////////////////////////////////////////////////////////////////////////
  212:  
  213:         /// <summary>
  214:         ///
  215:         /// </summary>
  216:         public bool UseCrLf
  217:         {
  218:             get { return this.useCrLf; }
  219:             set { this.useCrLf = value; }
  220:         }
  221:  
  222:         ////////////////////////////////////////////////////////////////////////////
  223:  
  224:         /// <summary>
  225:         ///
  226:         /// </summary>
  227:         public bool LocalEcho
  228:         {
  229:             get { return this.localEcho; }
  230:             set { this.localEcho = value; }
  231:         }
  232:  
  233:         ////////////////////////////////////////////////////////////////////////////
  234:  
  235:         /// <summary>
  236:         /// Connects to the remote server and starts receiving data to write to the display.
  237:         /// </summary>
  238:         public void Connect(object state)
  239:         {
  240:             //Necessary for explicit security
  241:             EventHandler<CommandEventArgs> commandReceivedHandler =
  242:                 new EventHandler<CommandEventArgs>(telnet_CommandReceived);
  243:  
  244:             try
  245:             {
  246:                 //Connect to the server
  247:                 Telnet.Connect(session);
  248:                 Telnet.Socket.ReceiveTimeout = 5000;
  249:  
  250:                 //If Explicit security used, use the CommandReceived event to negotiate
  251:                 if (securityType == SecurityType.Explicit)
  252:                     Telnet.CommandReceived += commandReceivedHandler;
  253:                 //If Implicit security used, authenticate server and specify certificate callback functions
  254:                 else if (securityType == SecurityType.Implicit)
  255:                     Telnet.AuthenticateAsClient(session);
  256:  
  257:                 //Login and provide transferred data to the interface (Data event)
  258:                 if (session.RemoteEndPoint.Port > 0 && credentials.Username.Length > 0 &&
  259:                     credentials.Password.Length > 0)
  260:                 {
  261:                     Dart.Telnet.Data data = Telnet.Login(credentials);
  262:                     Telnet.Marshal(data, string.Empty, null);
  263:                 }
  264:  
  265:                 //Provide telnet.Stream to interface (UserState event), or start the read loop.
  266:                 Telnet.Socket.ReceiveTimeout = 0;
  267:                 if (ReceiveLoopRequired) ReceiveData();
  268:                 else Telnet.Marshal("", Telnet.GetStream());
  269:             }
  270:             catch (Exception ex)
  271:             {
  272:                 Telnet.Marshal(ex);
  273:             }
  274:             finally
  275:             {
  276:                 Telnet.CommandReceived -= commandReceivedHandler;
  277:             }
  278:         }
  279:  
  280:         ////////////////////////////////////////////////////////////////////////////
  281:  
  282:         /// <summary>
  283:         /// Receives data from the server for display
  284:         /// </summary>
  285:         public void ReceiveData()
  286:         {
  287:             //Receive data when it is sent by the remote host and marshal it to UI thread
  288:             byte[] buffer = new byte[1024];
  289:             Dart.Telnet.Data data;
  290:             while (IsConnected)
  291:             {
  292:                 data = Telnet.Read(buffer, 0, 1024);
  293:                 if (data != null) Telnet.Marshal(data, string.Empty, null);
  294:             }
  295:         }
  296:  
  297:         ////////////////////////////////////////////////////////////////////////////
  298:  
  299:         /// <summary>
  300:         ///
  301:         /// </summary>
  302:         public void WriteData(string data)
  303:         {
  304:             //Write data string
  305:             if (IsConnected) Telnet.Write(data);
  306:         }
  307:  
  308:         ////////////////////////////////////////////////////////////////////////////
  309:  
  310:         /// <summary>
  311:         ///
  312:         /// </summary>
  313:         public void WriteData(byte[] data)
  314:         {
  315:             //Write data bytes
  316:             if (IsConnected) Telnet.Write(data);
  317:         }
  318:  
  319:         ////////////////////////////////////////////////////////////////////////////
  320:  
  321:         /// <summary>
  322:         ///
  323:         /// </summary>
  324:         public void Execute(object state)
  325:         {
  326:             //Connect to the specified server
  327:             receiveLoopRequired = false;
  328:             Connect(session);
  329:  
  330:             //Execute command
  331:             ExecuteCommand(CommandString, Credentials.CommandPrompt);
  332:  
  333:             //Close
  334:             Telnet.Close();
  335:         }
  336:  
  337:         ////////////////////////////////////////////////////////////////////////////
  338:  
  339:         /// <summary>
  340:         ///
  341:         /// </summary>
  342:         public void ExecuteCommand(string command, string prompt)
  343:         {
  344:             //Write data and display response
  345:             if (IsConnected)
  346:             {
  347:                 Telnet.Socket.ReceiveTimeout = 5000;
  348:                 Telnet.Write(command + "\r\n");
  349:                 try
  350:                 {
  351:                     Telnet.Marshal(Telnet.ReadToDelimiter(prompt), string.Empty, null);
  352:                 }
  353:                 catch (DataException dEx)
  354:                 {
  355:                     Telnet.Marshal(dEx.DataRead, string.Empty, null);
  356:                     Telnet.Marshal(dEx);
  357:                 }
  358:                 finally
  359:                 {
  360:                     Telnet.Socket.ReceiveTimeout = 0;
  361:                 }
  362:             }
  363:         }
  364:  
  365:         ////////////////////////////////////////////////////////////////////////////
  366:  
  367:         /// <summary>
  368:         ///
  369:         /// </summary>
  370:         public bool IsConnected
  371:         {
  372:             //True if connection is open
  373:             get { return Telnet.State != ConnectionState.Closed; }
  374:         }
  375:  
  376:         ////////////////////////////////////////////////////////////////////////////
  377:  
  378:         /// <summary>
  379:         ///
  380:         /// </summary>
  381:         [field: NonSerialized]
  382:         public event EventHandler<LocalCertificateEventArgs> CertificateRequested;
  383:  
  384:         ////////////////////////////////////////////////////////////////////////////
  385:  
  386:         /// <summary>
  387:         ///
  388:         /// </summary>
  389:         [field: NonSerialized]
  390:         public event EventHandler<RemoteCertificateEventArgs> CertificatePresented;
  391:  
  392:         ////////////////////////////////////////////////////////////////////////////
  393:  
  394:         /// <summary>
  395:         ///
  396:         /// </summary>
  397:         public bool AcceptCertificate;
  398:  
  399:         ////////////////////////////////////////////////////////////////////////////
  400:  
  401:         /// <summary>
  402:         ///
  403:         /// </summary>
  404:         private bool RemoteCertificateValidation(Object sender, X509Certificate remoteCertificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
  405:         {
  406:             CertificatePresented(this, new RemoteCertificateEventArgs(remoteCertificate, chain, sslPolicyErrors));
  407:             return AcceptCertificate;
  408:         }
  409:  
  410:         ////////////////////////////////////////////////////////////////////////////
  411:  
  412:         /// <summary>
  413:         ///
  414:         /// </summary>
  415:         private X509Certificate LocalCertificateValidation(Object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers)
  416:         {
  417:             //This callback executes (on worker thread) if server requests a client certificate
  418:             if (this.Session.Security.Certificates.Count == 1)
  419:                 return this.Session.Security.Certificates[0];
  420:             else
  421:             {
  422:                 //Prompt the user to select a certificate from the certificate list
  423:                 CertificateRequested(this, new LocalCertificateEventArgs(targetHost, localCertificates, remoteCertificate, acceptableIssuers));
  424:                 if (this.Session.Security.Certificates.Count > 0) return this.Session.Security.Certificates[0];
  425:             }
  426:             return null;
  427:         }
  428:  
  429:         ////////////////////////////////////////////////////////////////////////////
  430:  
  431:         /// <summary>
  432:         /// Handles negotiation for explicitly secure connection
  433:         /// </summary>
  434:         private void telnet_CommandReceived(object sender, CommandEventArgs e)
  435:         {
  436:             try
  437:             {
  438:                 if (e.OptionCode == OptionCode.Authentication)
  439:                 {
  440:                     if (e.Command == Command.Do)
  441:                         Telnet.SendOption(Command.Will, OptionCode.Authentication);
  442:                     else if (e.Command == Command.SB && e.SubOption[0] == 1)
  443:                     {
  444:                         //Server expects a SEND request (IS)
  445:                         byte[] response = new byte[4];
  446:                         response[0] = 0; // is
  447:                         response[1] = 7; // ssl
  448:                         response[2] = 0; // AuthClientToServer
  449:                         response[3] = 1; // START_SSL is our request
  450:                         Telnet.SendSubOption(e.OptionCode, response);
  451:                     }
  452:                     else if (e.Command == Command.SB && e.SubOption[0] == 2)
  453:                         Telnet.AuthenticateAsClient(session);
  454:                 }
  455:             }
  456:             catch (Exception ex)
  457:             {
  458:                 Telnet.Close();
  459:                 Telnet.Marshal(ex);
  460:             }
  461:         }
  462:     }
  463:  
  464:     ////////////////////////////////////////////////////////////////////////////
  465:  
  466:     /// <summary>
  467:     /// Arguments for the RemoteCertificateValidation event this class raises when a server presents its certificate.
  468:     /// </summary>
  469:     public class RemoteCertificateEventArgs : System.EventArgs
  470:     {
  471:         public RemoteCertificateEventArgs(X509Certificate remoteCertificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
  472:         {
  473:             RemoteCertificate = remoteCertificate;
  474:             Chain = chain;
  475:             SslPolicyErrors = sslPolicyErrors;
  476:         }
  477:  
  478:         public X509Certificate RemoteCertificate;
  479:         public X509Chain Chain;
  480:         public SslPolicyErrors SslPolicyErrors;
  481:     }
  482:  
  483:     ////////////////////////////////////////////////////////////////////////////
  484:  
  485:     /// <summary>
  486:     /// Arguments for the LocalCertificateValidation event this class raises when a server requests a certificate.
  487:     /// </summary>
  488:     public class LocalCertificateEventArgs : System.EventArgs
  489:     {
  490:         public LocalCertificateEventArgs(string targetHost, X509CertificateCollection localCertificates,
  491:             X509Certificate remoteCertificate, string[] acceptableIssuers)
  492:         {
  493:             TargetHost = targetHost;
  494:             LocalCertificates = localCertificates;
  495:             RemoteCertificate = remoteCertificate;
  496:             AcceptableIssuers = acceptableIssuers;
  497:         }
  498:  
  499:         public string TargetHost;
  500:         public X509CertificateCollection LocalCertificates;
  501:         public X509Certificate RemoteCertificate;
  502:         public string[] AcceptableIssuers;
  503:     }
  504:  
  505:     ////////////////////////////////////////////////////////////////////////////
  506:     ////////////////////////////////////////////////////////////////////////////
  507: }