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.Huawei
7: {
8: ////////////////////////////////////////////////////////////////////////////
9:
10: /// <summary publish="true">
11: /// Optical Fiber Network Management Intranet Portal (OFN) client support class for Huawei's Next Generation Network (NGN) EMS client model.
12: /// </summary>
13: ///
14: /// <remarks>
15: /// Copyright © 2017-2018 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 Ems
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 enum ResultCode : long
52: {
53: // I'm basically using the almost exact document phrasing of error codes
54: Unknown = -1,
55: Succeeded = 0,
56: DeviceDoesNotExist1 = 2686058531,
57: DeviceDoesNotExist2 = 15658136501,
58: ResourceDoesNotExist = 2686058552,
59: OntIsNotOnline = 2689012370,
60: CommunicatingWithDmFailed = 2686058603,
61: OntIsOffline = 2689014724,
62: OntLoadingCommandIsBeingExecutedNow = 2689014933,
63: SystemIsBusy1 = 2686058516,
64: SystemIsBusy2 = 2689017157,
65: AttempetingTimeout = 2686058596,
66: CommandSyntaxError = 2686058497,
67: UnknownCommand = 2686058499,
68: TaskTimeout = 2686058508,
69: ValueOfParameterIsWrong = 2686058500,
70: DbaProfileDoesNotExist1 = 102690820,
71: DbaProfileDoesNotExist2 = 2689014791,
72: NodeParameterSetFailed = 1615069195,
73: VersionDoesNotMatchOrCommunicationWithDeviceFailed = 1615462437,
74: FailedToCommunicateWithDevice1 = 1610614842,
75: FailedToCommunicateWithDevice2 = 1616445483,
76: FailedToCommunicateWithDevice3 = 1616445484,
77: FailedToCommunicateWithDevice4 = 1616445485,
78: LoginAddressIsNotInUserAcl = 76546022,
79: LoginAddressIsNotInSystemAcl = 76546023,
80: DeviceOfflineError = 1610612765,
81: OperationIsNotSupported = 2689008176,
82: ParametersConflictWithVasProfile = 1615069206,
83: ProfileAlreadyExists = 2689023090,
84: TrafficProfileDoesNotExist = 2689020327,
85: MgParameterIsConflicting = 2688880284,
86: NoOnuTypeIsSetInGeneralProfile = 1618280538,
87: OntIsUsedByOthers = 1618214927,
88: UserDoesNotLogIn = 2686058521,
89: PortDoesNotExist = 2689015666,
90: TelephoneNumberAlreadyExists = 2689015764,
91: ThePasswordHasExpiredOrNeedsToBeChangedOnNextLogin = 1618280766,
92: TheUserAccountIsLocked = 76546024,
93: }
94:
95: ////////////////////////////////////////////////////////////////////////////
96:
97: /// <summary>
98: ///
99: /// </summary>
100: public static string ResultCodeString(long _resultCode)
101: {
102: // see: ColoredResultCodeString()
103: string resultCodeString;
104: Ia.Ngn.Cl.Model.Client.Huawei.Ems.ResultCode resultCode;
105:
106: resultCode = (Ia.Ngn.Cl.Model.Client.Huawei.Ems.ResultCode)_resultCode;
107:
108: resultCodeString = resultCode.ToString();
109: resultCodeString = Ia.Cl.Model.Default.CamelToProperCase(resultCodeString);
110: resultCodeString = Ia.Cl.Model.Default.ToTitleCase(resultCodeString);
111: resultCodeString = resultCodeString.Replace("Ont", "ONT");
112:
113: return resultCodeString;
114: }
115:
116: ////////////////////////////////////////////////////////////////////////////
117:
118: /// <summary>
119: ///
120: /// </summary>
121: public static string ColoredResultCodeString(long _resultCode)
122: {
123: // see: ResultCodeString()
124: string resultCodeString, coloredResultCodeString;
125: Ia.Ngn.Cl.Model.Client.Huawei.Ems.ResultCode resultCode;
126:
127: resultCode = (Ia.Ngn.Cl.Model.Client.Huawei.Ems.ResultCode)_resultCode;
128:
129: resultCodeString = resultCode.ToString();
130: resultCodeString = Ia.Cl.Model.Default.CamelToProperCase(resultCodeString);
131: resultCodeString = Ia.Cl.Model.Default.ToTitleCase(resultCodeString);
132: resultCodeString = resultCodeString.Replace("Ont", "ONT");
133:
134: switch (resultCode)
135: {
136: case Ia.Ngn.Cl.Model.Client.Huawei.Ems.ResultCode.Succeeded: coloredResultCodeString = "<span style=\"color:Green\">" + resultCodeString + "</span>"; break;
137: default: coloredResultCodeString = "<span style=\"color:Red\">" + resultCodeString + "</span>"; break;
138: }
139:
140: return coloredResultCodeString;
141: }
142:
143: ////////////////////////////////////////////////////////////////////////////
144:
145: /// <summary>
146: ///
147: /// </summary>
148: public Ems()
149: {
150: this.telnet = new Dart.PowerTCP.Telnet.Telnet(); // this.components);
151:
152: this.telnet.ClientOptions.AddRange(new Dart.PowerTCP.Telnet.Option[] {
153: new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.SuppressGoAheads, null, Dart.PowerTCP.Telnet.OptionState.RequestOn),
154: 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),
155: 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)});
156:
157: this.telnet.ServerOptions.AddRange(new Dart.PowerTCP.Telnet.Option[] {
158: new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.SuppressGoAheads, null, Dart.PowerTCP.Telnet.OptionState.RequestOn),
159: new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.Echo, null, Dart.PowerTCP.Telnet.OptionState.RequestOn)});
160:
161: //this.telnet.SynchronizingObject = this;
162: this.telnet.TerminalType = "xterm";
163: //this.telnet.WindowSize = new System.Drawing.Size(80, 24);
164: this.telnet.EndReceive += new Dart.PowerTCP.Telnet.SegmentEventHandler(this.Telnet_EndReceive);
165: this.telnet.ConnectedChangedEx += new Dart.PowerTCP.Telnet.EventHandlerEx(this.Telnet_ConnectedChangedEx);
166:
167: receiveString = string.Empty;
168: ReceiveQueue = new Queue<string>(100);
169: SendQueue = new Queue<string>(100);
170:
171: isLoggedIn = false;
172: }
173:
174: ////////////////////////////////////////////////////////////////////////////
175:
176: /// <summary>
177: ///
178: /// </summary>
179: ~Ems()
180: {
181: Dispose();
182: }
183:
184: ////////////////////////////////////////////////////////////////////////////
185:
186: /// <summary>
187: ///
188: /// </summary>
189: public void Connect(out Ia.Cl.Model.Result result)
190: {
191: result = new Ia.Cl.Model.Result();
192:
193: try
194: {
195: telnet.ClientOptions.Add(new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.SuppressGoAheads, null, Dart.PowerTCP.Telnet.OptionState.RequestOn));
196: telnet.ClientOptions.Add(new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.TerminalType, new System.Byte[] { ((System.Byte)(0)), ((System.Byte)(116)), ((System.Byte)(116)), ((System.Byte)(121)) }, Dart.PowerTCP.Telnet.OptionState.RequestOn));
197: telnet.ServerOptions.Add(new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.SuppressGoAheads, null, Dart.PowerTCP.Telnet.OptionState.RequestOn));
198: telnet.ServerOptions.Add(new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.Echo, null, Dart.PowerTCP.Telnet.OptionState.RequestOn));
199: telnet.ServerOptions.Add(new Dart.PowerTCP.Telnet.Option(Dart.PowerTCP.Telnet.OptionCode.OutputPageSize, null, Dart.PowerTCP.Telnet.OptionState.RequestOn));
200:
201: telnet.Connect(Ia.Ngn.Cl.Model.Business.Huawei.Ems.Host, Ia.Ngn.Cl.Model.Business.Huawei.Ems.Port.ToString());
202:
203: // receive using asynchronous technique
204: telnet.ReceiveTimeout = 0;
205: telnet.BeginReceive(buffer);
206:
207: result.AddSuccess("Connected. ");
208: }
209: catch (Exception ex)
210: {
211: result.AddError("Exception: " + ex.Message);
212:
213: telnet.Close();
214: }
215: }
216:
217: ////////////////////////////////////////////////////////////////////////////
218:
219: /// <summary>
220: ///
221: /// </summary>
222: public void Disconnect(out Ia.Cl.Model.Result result)
223: {
224: result = new Ia.Cl.Model.Result();
225:
226: try
227: {
228: telnet.Close();
229:
230: result.AddSuccess("Disconnected. ");
231: }
232: catch (Exception ex)
233: {
234: result.AddError(ex.Message);
235: }
236: }
237:
238: ////////////////////////////////////////////////////////////////////////////
239:
240: /// <summary>
241: ///
242: /// </summary>
243: public bool IsConnected
244: {
245: get
246: {
247: return telnet.Connected;
248: }
249: }
250:
251: ////////////////////////////////////////////////////////////////////////////
252:
253: /// <summary>
254: ///
255: /// </summary>
256: public bool IsLoggedIn { get { return isLoggedIn; } set { isLoggedIn = value; } }
257:
258: ////////////////////////////////////////////////////////////////////////////
259:
260: /// <summary>
261: ///
262: /// </summary>
263: public void Dispose()
264: {
265: telnet.Dispose();
266: }
267:
268: ////////////////////////////////////////////////////////////////////////////
269:
270: /// <summary>
271: ///
272: /// </summary>
273: public void Login()
274: {
275: // sendQueue.Enqueue(Ia.Ngn.Cl.Model.Business.Huawei.Ems.Semicolon); did not make any different
276:
277: // below: I need this because NCE somehow needs to be triggered before I send login information
278: SendQueue.Enqueue(Ia.Ngn.Cl.Model.Business.Huawei.Ems.EmsKeepAliveCommand);
279: SendQueue.Enqueue(Ia.Ngn.Cl.Model.Business.Huawei.Ems.EmsKeepAliveCommand);
280:
281: SendQueue.Enqueue(Ia.Ngn.Cl.Model.Business.Huawei.Ems.LoginUser);
282: }
283:
284: ////////////////////////////////////////////////////////////////////////////
285:
286: /// <summary>
287: ///
288: /// </summary>
289: public void Logout()
290: {
291: SendQueue.Enqueue(Ia.Ngn.Cl.Model.Business.Huawei.Ems.LogoutUser);
292: }
293:
294: ////////////////////////////////////////////////////////////////////////////
295:
296: /// <summary>
297: ///
298: /// </summary>
299: public void Send(string text, bool skipSleep, out Ia.Cl.Model.Result result)
300: {
301: result = new Ia.Cl.Model.Result();
302:
303: try
304: {
305: if (telnet.Connected)
306: {
307: if (text != null)
308: {
309: LastSentCommand = text;
310:
311: //this.textBox.AppendText("\r\n/* Sending: " + text + " */\r\n");
312:
313: telnet.Send(text);
314:
315: result.AddSuccess("Sent: " + text);
316: }
317: else
318: {
319: result.AddError("No text to send. ");
320: }
321: }
322: else
323: {
324: result.AddError("No established telnet connection. ");
325: //if(processRunning) waitToConnectionCounter = waitToConnectionCounterSeconds;
326: }
327: }
328: catch (Exception ex)
329: {
330: //if(processRunning) waitToConnectionCounter = waitToConnectionCounterSeconds;
331:
332: result.AddError(ex.Message);
333: }
334:
335: if (!skipSleep)
336: {
337: // this is meant to give the Telnet_EndReceive() time to receive and process data from session
338: // we will wait according to the type of commands send
339:
340: if (Ia.Ngn.Cl.Model.Business.Huawei.Ems.IsACfgCommand(LastSentCommand))
341: {
342: System.Threading.Thread.Sleep(Ia.Ngn.Cl.Model.Client.Huawei.Ems.WaitAfterSendForCfgCommandInMillisecond);
343: }
344: else
345: {
346: System.Threading.Thread.Sleep(Ia.Ngn.Cl.Model.Client.Huawei.Ems.WaitAfterSendInMillisecond);
347: }
348: }
349: }
350:
351: ////////////////////////////////////////////////////////////////////////////
352:
353: /// <summary>
354: ///
355: /// </summary>
356: private void Telnet_EndReceive(object sender, Dart.PowerTCP.Telnet.SegmentEventArgs e)
357: {
358: string message, entry;
359: string[] receiveStringSplit;
360:
361: Debug.WriteLine(" ");
362: Debug.WriteLine("============================================");
363:
364: if (e.Exception == null)
365: {
366: receiveString += e.Segment.ToString();
367:
368: Debug.WriteLine("Telnet_EndReceive(): e.Segment: [" + e.Segment.ToString() + "], receiveString: [" + receiveString + "]");
369:
370: if (!string.IsNullOrEmpty(receiveString))
371: {
372: receiveStringSplit = receiveString.Split(new string[] { "\r\n;" }, StringSplitOptions.None);
373:
374: if (receiveStringSplit.Length > 0)
375: {
376: for (int i = 0; i < receiveStringSplit.Length; i++)
377: {
378: entry = receiveStringSplit[i];
379:
380: if (!string.IsNullOrEmpty(entry) && !string.IsNullOrWhiteSpace(entry))
381: {
382: // will not enqueue an empty entry
383:
384: if (i == receiveStringSplit.Length - 1)
385: {
386: // if there is a non empty last entry that means its incomplete and we will assign it to receiveString
387:
388: receiveString = entry;
389: }
390: else
391: {
392: message = entry + "\r\n;"; // important
393:
394: if (!ReceiveQueue.Contains(message))
395: {
396: // will not enqueue duplicate
397:
398: ReceiveQueue.Enqueue(message);
399:
400: Debug.WriteLine("Telnet_EndReceive(): ReceiveQueue.Enqueue(message): [" + message + "]");
401: }
402:
403: receiveString = string.Empty;
404: }
405: }
406: }
407: }
408:
409: Debug.WriteLine("Telnet_EndReceive(): receiveString: [" + receiveString + "]");
410: }
411: else
412: {
413:
414: }
415:
416: if (telnet.Connected) telnet.BeginReceive(buffer);
417: }
418: else
419: {
420: Debug.WriteLine("Telnet_EndReceive(): Exception: " + e.Exception.Message);
421:
422: // I will not throw or handle the exception from the event handler
423: // https://stackoverflow.com/questions/3114543/should-event-handlers-in-c-sharp-ever-raise-exceptions
424: //throw new Exception("Telnet_EndReceive(): " + e.Exception.Message);
425: }
426:
427: Debug.WriteLine("============================================");
428: Debug.WriteLine(" ");
429: }
430:
431: ////////////////////////////////////////////////////////////////////////////
432:
433: /// <summary>
434: ///
435: /// </summary>
436: private void Telnet_ConnectedChangedEx(object sender, System.EventArgs e)
437: {
438: // always raised when Connection is established or closed (Connected property changes)
439:
440: //UpdateToolStripStatusLabel();
441: }
442:
443: ////////////////////////////////////////////////////////////////////////////
444:
445: /// <summary>
446: ///
447: /// </summary>
448: public Ia.Cl.Model.Result Update(string rowData, ref Ia.Ngn.Cl.Model.Client.Huawei.Ems ems)
449: {
450: return Ia.Ngn.Cl.Model.Business.Huawei.Ems.UpdateDatabaseWithEmsCommandOutput(rowData, ref ems);
451: }
452:
453: ////////////////////////////////////////////////////////////////////////////
454: ////////////////////////////////////////////////////////////////////////////
455: }
456:
457: ////////////////////////////////////////////////////////////////////////////
458: ////////////////////////////////////////////////////////////////////////////
459: }