source: trunk/URouterOS.pas

Last change on this file was 4, checked in by george, 14 years ago
  • Modified: Minor changes.
File size: 6.2 KB
Line 
1unit URouterOS;
2
3interface
4
5uses
6 Classes, SysUtils, IdTelnet, Forms;
7
8type
9 TLineReceiveEvent = procedure(Line: string) of object;
10 TConnectionState = (csNotConnected, csConnectedLoginProcessing, csConnectedPasswordProcessing,
11 csConnectedReady, csConnectedCommandProcessing);
12 TConnectionStateChangeEvent = procedure(State: TConnectionState) of object;
13 TEscapeCodePhase = (ecNone, ecStart, ecBracket, ecEnd);
14
15 TRouterOS = class
16 private
17 FirstResponseBracket: Boolean;
18 Line: string;
19 LineCharIndex: Integer;
20 BufferParseState: TEscapeCodePhase;
21 Telnet: TIdTelnet;
22 UserName: string;
23 Password: string;
24 FOnLineReceive: TLineReceiveEvent;
25 FConnectionState: TConnectionState;
26 CommandResponse: TStringList;
27 FOnConnectionStateChange: TConnectionStateChangeEvent;
28 procedure ChangeState(NewState: TConnectionState);
29 procedure HandleResponse(Line: string);
30 procedure DataAvailable(Sender: TIdTelnet; const Buffer: String);
31 public
32 Timeout: Integer;
33 function StripControlCodes(Text: string): string;
34 function Execute(Command: string): TStringList;
35 procedure Connect(HostName, UserName, Password: string);
36 procedure Close;
37 constructor Create;
38 destructor Destroy; override;
39 property OnLineReceive: TLineReceiveEvent read FOnLineReceive write FOnLineReceive;
40 property OnConnectionStateChange: TConnectionStateChangeEvent read FOnConnectionStateChange write FOnConnectionStateChange;
41 property ConnectionState: TConnectionState read FConnectionState;
42 end;
43
44implementation
45
46{ TRouterOS }
47
48procedure TRouterOS.ChangeState(NewState: TConnectionState);
49begin
50 if NewState <> FConnectionState then
51 if Assigned(FOnConnectionStateChange) then
52 FOnConnectionStateChange(NewState);
53 FConnectionState := NewState;
54end;
55
56procedure TRouterOS.Close;
57begin
58
59end;
60
61procedure TRouterOS.Connect(HostName, UserName, Password: string);
62begin
63 with Telnet do begin
64 FirstResponseBracket := True;
65 OnDataAvailable := DataAvailable;
66 Self.UserName := UserName;
67 Self.Password := Password;
68 Connect(HostName);
69 if not Connected then raise Exception.Create('Could not connect to ' + HostName)
70 else FConnectionState := csConnectedLoginProcessing;
71 end;
72end;
73
74constructor TRouterOS.Create;
75begin
76 Timeout := 3000;
77 Telnet := TIdTelnet.Create(nil);
78 CommandResponse := TStringList.Create;
79 Line := '';
80 LineCharIndex := 1;
81end;
82
83procedure TRouterOS.DataAvailable(Sender: TIdTelnet; const Buffer: String);
84var
85 I: Integer;
86 Temp: string;
87begin
88 I := 1;
89 repeat
90 while I <= Length(Buffer) do begin
91 if Buffer[I] = #13 then LineCharIndex := 1 // Carriage return
92 else if Buffer[I] = #10 then begin // Line feed
93 HandleResponse(Line);
94 Line := '';
95 LineCharIndex := 1;
96 end else if Buffer[I] = #27 then begin // Escape
97 BufferParseState := ecStart;
98 end else if Ord(Buffer[I]) < 32 then begin
99 end else begin
100 if (BufferParseState = ecStart) then begin
101 if (Buffer[I] = '[') then begin
102 BufferParseState := ecBracket;
103 end else BufferParseState := ecNone;
104 end else
105 if (BufferParseState = ecBracket) then begin
106 if (Buffer[I] >= '0') and (Buffer[I] <= '9') then begin
107 end else BufferParseState := ecNone;
108 end else begin
109 if Length(Line) < LineCharIndex then SetLength(Line, LineCharIndex);
110 Line[LineCharIndex] := Buffer[I];
111 Inc(LineCharIndex);
112 end;
113 end;
114 Inc(I);
115 end;
116 until I >= Length(Buffer);
117
118 Temp := Trim(Line);
119 if Line <> '' then
120 case FConnectionState of
121 csConnectedLoginProcessing: begin
122 if Line = 'Login: ' then begin
123 Telnet.IOHandler.WriteLn(UserName);
124 ChangeState(csConnectedPasswordProcessing);
125 end;
126 end;
127 csConnectedPasswordProcessing: begin
128 if Line = 'Password: ' then begin
129 Telnet.IOHandler.WriteLn(Password);
130 end;
131 if Line[1] = '[' then ChangeState(csConnectedReady)
132 end;
133 csConnectedCommandProcessing: begin
134 if Line[1] = '[' then begin
135 //if not FirstResponseBracket then FirstResponseBracket := True
136 //else ChangeState(csConnectedReady)
137 if (Line[1] = '[') and (Temp[Length(Temp)] = '>') then
138 ChangeState(csConnectedReady);
139 end else CommandResponse.Add(Line);
140 end;
141 end;
142end;
143
144destructor TRouterOS.Destroy;
145begin
146 CommandResponse.Free;
147 Telnet.Free;
148 inherited;
149end;
150
151function TRouterOS.Execute(Command: string): TStringList;
152var
153 Time: Integer;
154begin
155 FirstResponseBracket := False;
156 CommandResponse.Clear;
157 ChangeState(csConnectedCommandProcessing);
158 Result := TStringList.Create;
159 Telnet.IOHandler.WriteLn(#27'[7l' + Command);
160 Time := 0;
161 while (FConnectionState = csConnectedCommandProcessing) and (Time < Timeout) do begin
162 Sleep(10);
163 Application.ProcessMessages;
164 Inc(Time, 10);
165 end;
166 if Time >= Timeout then
167 raise Exception.Create('Connection timeout');
168
169 Result.Assign(CommandResponse);
170end;
171
172procedure TRouterOS.HandleResponse(Line: string);
173begin
174 if Assigned(FOnLineReceive) then FOnLineReceive(Line);
175 if Line <> '' then
176 case FConnectionState of
177 csConnectedReady: begin
178 end;
179 csConnectedCommandProcessing: begin
180 if Line[1] = '[' then begin
181 if not FirstResponseBracket then FirstResponseBracket := True
182 else ChangeState(csConnectedReady)
183 end else CommandResponse.Add(Line);
184 end;
185 end;
186end;
187
188function TRouterOS.StripControlCodes(Text: string): string;
189var
190 EscapeCode: TEscapeCodePhase;
191 I: Integer;
192begin
193 Result := '';
194 EscapeCode := ecNone;
195 I := 1;
196 while I <= Length(Text) do begin
197 if Ord(Text[I]) < 32 then begin
198 Result := Result + '#' + IntToStr(Ord(Text[I]));
199 //if Ord(Text[I]) = 27 then begin
200 // EscapeCode := ecStart;
201 //end;
202 end else begin
203 if Escapecode = ecStart then begin
204 if Text[I] = '[' then EscapeCode := ecBracket
205 else Result := Result + Text[I];
206 end else Result := Result + Text[I];
207 end;
208 Inc(I);
209 end;
210end;
211
212end.
Note: See TracBrowser for help on using the repository browser.