1: using Dart.PowerTCP.Telnet;
2: using System;
3: using System.Collections.Generic;
4: using System.Diagnostics;
5:
6: namespace Ia.Ngn.Cl.Model.Client.Nokia
7: {
8: ////////////////////////////////////////////////////////////////////////////
9:
10: /// <summary publish="true">
11: /// Optical Fiber Network's Operations Support System Management Intranet (OFN OSS) client support class for Nokia's Optical Fiber Network (OFN) AMS client model.
12: /// </summary>
13: ///
14: /// <remarks>
15: /// Copyright © 2020-2021 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
16: ///
17: /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
18: /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
19: ///
20: /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21: /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22: ///
23: /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
24: ///
25: /// Copyright notice: This notice may not be removed or altered from any source distribution.
26: /// </remarks>
27: public class Ams
28: {
29: private bool isLoggedIn;
30:
31: // interactive Telnet does not require a very large buffer, so 1024 is fine
32: private readonly byte[] buffer = new byte[1024];
33: private string receiveString;
34: internal Telnet telnet;
35:
36: /// <summary/>
37: public static int WaitAfterSendInMillisecond { get { return 4000; } }
38: public static int WaitAfterSendForCfgCommandInMillisecond { get { return 10000; } }
39:
40: public string LastSentCommand { get; private set; }
41:
42: public Queue<string> ReceiveQueue { get; set; }
43:
44: public Queue<string> SendQueue { get; set; }
45:
46: ////////////////////////////////////////////////////////////////////////////
47:
48: /// <summary>
49: ///
50: /// </summary>
51: public Ams()
52: {
53: this.telnet = new Dart.PowerTCP.Telnet.Telnet(); // this.components);
54:
55: this.telnet.ClientOptions.AddRange(new Dart.PowerTCP.Telnet.Option[] {
56: new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.SuppressGoAheads, null, Dart.PowerTCP.Telnet.OptionState.RequestOn),
57: new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.WindowSize, new byte[] {((byte)(0)),((byte)(80)),((byte)(0)),((byte)(24))}, Dart.PowerTCP.Telnet.OptionState.RequestOn),
58: new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.TerminalType, new byte[] {((byte)(0)),((byte)(120)),((byte)(116)),((byte)(101)),((byte)(114)),((byte)(109))}, Dart.PowerTCP.Telnet.OptionState.RequestOn)});
59:
60: this.telnet.ServerOptions.AddRange(new Dart.PowerTCP.Telnet.Option[] {
61: new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.SuppressGoAheads, null, Dart.PowerTCP.Telnet.OptionState.RequestOn),
62: new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.Echo, null, Dart.PowerTCP.Telnet.OptionState.RequestOn)});
63:
64: //this.telnet.SynchronizingObject = this;
65: this.telnet.TerminalType = "xterm";
66: //this.telnet.WindowSize = new System.Drawing.Size(80, 24);
67: this.telnet.EndReceive += new Dart.PowerTCP.Telnet.SegmentEventHandler(this.Telnet_EndReceive);
68: this.telnet.ConnectedChangedEx += new Dart.PowerTCP.Telnet.EventHandlerEx(this.Telnet_ConnectedChangedEx);
69:
70: receiveString = string.Empty;
71: ReceiveQueue = new Queue<string>(100);
72: SendQueue = new Queue<string>(100);
73:
74: isLoggedIn = false;
75: }
76:
77: ////////////////////////////////////////////////////////////////////////////
78:
79: /// <summary>
80: ///
81: /// </summary>
82: ~Ams()
83: {
84: Dispose();
85: }
86:
87: ////////////////////////////////////////////////////////////////////////////
88:
89: /// <summary>
90: ///
91: /// </summary>
92: public void Connect(out Ia.Cl.Model.Result result)
93: {
94: result = new Ia.Cl.Model.Result();
95:
96: try
97: {
98: telnet.ClientOptions.Add(new Option(OptionCode.SuppressGoAheads, null, OptionState.RequestOn));
99: telnet.ClientOptions.Add(new Option(OptionCode.TerminalType, new System.Byte[] { ((System.Byte)(0)), ((System.Byte)(116)), ((System.Byte)(116)), ((System.Byte)(121)) }, OptionState.RequestOn));
100: telnet.ServerOptions.Add(new Option(OptionCode.SuppressGoAheads, null, OptionState.RequestOn));
101: telnet.ServerOptions.Add(new Option(OptionCode.Echo, null, OptionState.RequestOn));
102: telnet.ServerOptions.Add(new Option(OptionCode.OutputPageSize, null, OptionState.RequestOn));
103:
104: telnet.Connect(Ia.Ngn.Cl.Model.Business.Nokia.Ams.Host, Ia.Ngn.Cl.Model.Business.Nokia.Ams.Port.ToString());
105:
106: // receive using asynchronous technique
107: telnet.ReceiveTimeout = 0;
108: telnet.BeginReceive(buffer);
109:
110: result.AddSuccess("Connected. ");
111: }
112: catch (Exception ex)
113: {
114: result.AddError("Exception: " + ex.Message);
115:
116: telnet.Close();
117: }
118: }
119:
120: ////////////////////////////////////////////////////////////////////////////
121:
122: /// <summary>
123: ///
124: /// </summary>
125: public void Disconnect(out Ia.Cl.Model.Result result)
126: {
127: result = new Ia.Cl.Model.Result();
128:
129: try
130: {
131: telnet.Close();
132:
133: result.AddSuccess("Disconnected. ");
134: }
135: catch (Exception ex)
136: {
137: result.AddError(ex.Message);
138: }
139: }
140:
141: ////////////////////////////////////////////////////////////////////////////
142:
143: /// <summary>
144: ///
145: /// </summary>
146: public bool IsConnected
147: {
148: get
149: {
150: return telnet.Connected;
151: }
152: }
153:
154: ////////////////////////////////////////////////////////////////////////////
155:
156: /// <summary>
157: ///
158: /// </summary>
159: public bool IsLoggedIn
160: {
161: get
162: {
163: return isLoggedIn;
164: }
165: set
166: {
167: isLoggedIn = value;
168: }
169: }
170:
171: ////////////////////////////////////////////////////////////////////////////
172:
173: /// <summary>
174: ///
175: /// </summary>
176: public void Dispose()
177: {
178: telnet.Dispose();
179: }
180:
181: ////////////////////////////////////////////////////////////////////////////
182:
183: /// <summary>
184: ///
185: /// </summary>
186: public void Send(string text, out Ia.Cl.Model.Result result)
187: {
188: result = new Ia.Cl.Model.Result();
189:
190: try
191: {
192: if (telnet.Connected)
193: {
194: if (text != null)
195: {
196: LastSentCommand = text;
197:
198: //this.textBox.AppendText("\r\n/* Sending: " + text + " */\r\n");
199:
200: telnet.Send(text);
201:
202: //result.AddSuccess("Sent: " + text);
203: }
204: else
205: {
206: result.AddError("No text to send. ");
207: }
208: }
209: else
210: {
211: result.AddError("No established telnet connection. ");
212: //if(processRunning) waitToConnectionCounter = waitToConnectionCounterSeconds;
213: }
214: }
215: catch (Exception ex)
216: {
217: //if(processRunning) waitToConnectionCounter = waitToConnectionCounterSeconds;
218:
219: result.AddError(ex.Message);
220: }
221: }
222:
223: ////////////////////////////////////////////////////////////////////////////
224:
225: /// <summary>
226: ///
227: /// </summary>
228: private void Telnet_EndReceive(object sender, Dart.PowerTCP.Telnet.SegmentEventArgs e)
229: {
230: string message, entry;
231: string[] receiveStringSplit;
232:
233: if (e.Exception == null)
234: {
235: receiveString += e.Segment.ToString();
236:
237: if (!string.IsNullOrEmpty(receiveString))
238: {
239: receiveStringSplit = receiveString.Split(new string[] { "\r\n;" }, StringSplitOptions.None);
240:
241: if (receiveStringSplit.Length > 0)
242: {
243: for (int i = 0; i < receiveStringSplit.Length; i++)
244: {
245: entry = receiveStringSplit[i];
246:
247: if (!string.IsNullOrEmpty(entry) && !string.IsNullOrWhiteSpace(entry))
248: {
249: // will not enqueue an empty entry
250:
251: if (i == receiveStringSplit.Length - 1)
252: {
253: // if there is a non empty last entry that means its incomplete and we will assign it to receiveString
254:
255: receiveString = entry;
256: }
257: else
258: {
259: message = entry + "\r\n;"; // important
260:
261: if (!ReceiveQueue.Contains(message))
262: {
263: // will not enqueue duplicate
264:
265: ReceiveQueue.Enqueue(message);
266: }
267:
268: receiveString = string.Empty;
269: }
270: }
271: }
272: }
273: }
274: else
275: {
276:
277: }
278:
279: if (telnet.Connected) telnet.BeginReceive(buffer);
280: }
281: else
282: {
283: Debug.WriteLine("Telnet_EndReceive(): Exception: " + e.Exception.Message);
284:
285: // I will not throw or handle the exception from the event handler
286: // https://stackoverflow.com/questions/3114543/should-event-handlers-in-c-sharp-ever-raise-exceptions
287: //throw new Exception("Telnet_EndReceive(): " + e.Exception.Message);
288: }
289: }
290:
291: ////////////////////////////////////////////////////////////////////////////
292:
293: /// <summary>
294: ///
295: /// </summary>
296: private void Telnet_ConnectedChangedEx(object sender, System.EventArgs e)
297: {
298: // always raised when Connection is established or closed (Connected property changes)
299:
300: //UpdateToolStripStatusLabel();
301: }
302:
303: ////////////////////////////////////////////////////////////////////////////
304:
305: /// <summary>
306: ///
307: /// </summary>
308: public Ia.Cl.Model.Result Update(string rowData)
309: {
310: bool isUpdated;
311:
312: isUpdated = Ia.Ngn.Cl.Model.Business.Nokia.Ams.UpdateDatabaseWithAmsCommandOutput(rowData, out Ia.Cl.Model.Result updateDatabaseWithAmsCommandOutputResult);
313:
314: return updateDatabaseWithAmsCommandOutputResult;
315: }
316:
317: ////////////////////////////////////////////////////////////////////////////
318: ////////////////////////////////////////////////////////////////////////////
319: }
320:
321: ////////////////////////////////////////////////////////////////////////////
322: ////////////////////////////////////////////////////////////////////////////
323: }