]> git.mxchange.org Git - flightgear.git/blob - utils/GPSsmooth/UGear_telnet.cxx
Add a telnet command parser to UGear so we can feed commands remotely to
[flightgear.git] / utils / GPSsmooth / UGear_telnet.cxx
1 // \file props.cxx
2 // Property server class.
3 //
4 // Written by Curtis Olson, started September 2000.
5 // Modified by Bernie Bright, May 2002.
6 //
7 // Copyright (C) 2000  Curtis L. Olson - http://www.flightgear.org/~curt
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License as
11 // published by the Free Software Foundation; either version 2 of the
12 // License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 // General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 //
23 // $Id$
24
25
26 #include <simgear/structure/commands.hxx>
27 #include <simgear/misc/strutils.hxx>
28
29 #include <sstream>
30
31 #include <plib/netChat.h>
32
33 #include "UGear_command.hxx"
34 #include "UGear_telnet.hxx"
35
36 using std::stringstream;
37 using std::ends;
38
39 /**
40  * Props connection class.
41  * This class represents a connection to props client.
42  */
43 class PropsChannel : public netChat
44 {
45     netBuffer buffer;
46
47     /**
48      * Current property node name.
49      */
50     string path;
51
52     enum Mode {
53         PROMPT,
54         DATA
55     };
56     Mode mode;
57
58 public:
59
60     /**
61      * Constructor.
62      */
63     PropsChannel();
64     
65     /**
66      * Append incoming data to our request buffer.
67      *
68      * @param s Character string to append to buffer
69      * @param n Number of characters to append.
70      */
71     void collectIncomingData( const char* s, int n );
72
73     /**
74      * Process a complete request from the props client.
75      */
76     void foundTerminator();
77
78 private:
79     /**
80      * Return a "Node no found" error message to the client.
81      */
82     void node_not_found_error( const string& node_name );
83 };
84
85 /**
86  * 
87  */
88 PropsChannel::PropsChannel()
89     : buffer(512),
90       path("/"),
91       mode(PROMPT)
92 {
93     setTerminator( "\r\n" );
94 }
95
96 /**
97  * 
98  */
99 void
100 PropsChannel::collectIncomingData( const char* s, int n )
101 {
102     buffer.append( s, n );
103 }
104
105 /**
106  * 
107  */
108 void
109 PropsChannel::node_not_found_error( const string& node_name )
110 {
111     string error = "-ERR Node \"";
112     error += node_name;
113     error += "\" not found.";
114     push( error.c_str() );
115     push( getTerminator() );
116 }
117
118 /**
119  * We have a command.
120  * 
121  */
122 void
123 PropsChannel::foundTerminator()
124 {
125     const char* cmd = buffer.getData();
126     SG_LOG( SG_IO, SG_INFO, "processing command = \"" << cmd << "\"" );
127
128     vector<string> tokens = simgear::strutils::split( cmd );
129
130     if (!tokens.empty()) {
131         string command = tokens[0];
132
133         if ( command == "send" ) {
134             command_mgr.add( tokens[1] );
135         } else if ( command == "quit" ) {
136             close();
137             shouldDelete();
138             return;
139         } else if ( command == "data" ) {
140             mode = DATA;
141         } else if ( command == "prompt" ) {
142             mode = PROMPT;
143         } else {
144             const char* msg = "\
145 Valid commands are:\r\n\
146 \r\n\
147 data               switch to raw data mode\r\n\
148 prompt             switch to interactive mode (default)\r\n\
149 quit               terminate connection\r\n\
150 send <command>     send <command> to UAS\r\n";
151             push( msg );
152         }
153     }
154
155     if (mode == PROMPT) {
156         string prompt = "> ";
157         push( prompt.c_str() );
158     }
159
160     buffer.remove();
161 }
162
163 /**
164  * 
165  */
166 UGTelnet::UGTelnet( const int port_num ):
167     enabled(false)
168 {
169     port = port_num;
170 }
171
172 /**
173  * 
174  */
175 UGTelnet::~UGTelnet()
176 {
177 }
178
179 /**
180  * 
181  */
182 bool
183 UGTelnet::open()
184 {
185     if (enabled ) {
186         printf("This shouldn't happen, but the telnet channel is already in use, ignoring\n" );
187         return false;
188     }
189
190     netChannel::open();
191     netChannel::bind( "", port );
192     netChannel::listen( 5 );
193     printf("Telnet server started on port %d\n", port );
194
195     enabled = true;
196
197     return true;
198 }
199
200 /**
201  * 
202  */
203 bool
204 UGTelnet::close()
205 {
206     SG_LOG( SG_IO, SG_INFO, "closing UGTelnet" );   
207     return true;
208 }
209
210 /**
211  * 
212  */
213 bool
214 UGTelnet::process()
215 {
216     netChannel::poll();
217     return true;
218 }
219
220 /**
221  * 
222  */
223 void
224 UGTelnet::handleAccept()
225 {
226     netAddress addr;
227     int handle = netChannel::accept( &addr );
228     printf("Telent server accepted connection from %s:%d\n",
229            addr.getHost(), addr.getPort() );
230     PropsChannel* channel = new PropsChannel();
231     channel->setHandle( handle );
232 }