embkernel
 All Classes Functions Variables Typedefs Groups Pages
NetServerTelnet.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "NetServerTelnet.hpp"
7 #include <string.h>
8 
9 NetServerTelnet::NetServerTelnet(int priority, size_t stackSize) :
10  mTask(priority, "TELNET", stackSize, *this) {
11  mEntries = 0;
12 }
13 
14 NetServerTelnet::~NetServerTelnet() {
15 }
16 
17 void NetServerTelnet::ansiCursorUp(int value) {
18  mSocket.printf("\x1B[%uA", value);
19 }
20 
21 void NetServerTelnet::ansiCursorDown(int value) {
22  mSocket.printf("\x1B[%uB", value);
23 }
24 
25 void NetServerTelnet::ansiCursorForward(int value) {
26  mSocket.printf("\x1B[%uC", value);
27 }
28 
29 void NetServerTelnet::ansiCursorBack(int value) {
30  mSocket.printf("\x1B[%uD", value);
31 }
32 
33 void NetServerTelnet::ansiCursorPosition(int x, int y) {
34  mSocket.printf("\x1B[%u;%uH", y, x);
35 }
36 
37 void NetServerTelnet::ansiEraseData(int value) {
38  mSocket.printf("\x1B[%uJ", value);
39 }
40 
41 void NetServerTelnet::ansiEraseInLine(int value) {
42  mSocket.printf("\x1B[%uK", value);
43 }
44 
45 void NetServerTelnet::ansiSaveCursorPosition() {
46  mSocket.printf("\x1B[s");
47 }
48 
49 void NetServerTelnet::ansiRestoreCursorPosition() {
50  mSocket.printf("\x1B[u");
51 }
52 
53 void NetServerTelnet::ansiHideCursor() {
54  mSocket.printf("\x1B[?25l");
55 }
56 
57 void NetServerTelnet::ansiShowCursor() {
58  mSocket.printf("\x1B[?25h");
59 }
60 
61 void NetServerTelnet::iacNegotiate() {
62  const static char IAC_COMMANDS[] = {
63  IAC, WILL, SUPPRESS_GO_AHEAD, //
64  IAC, WILL, ECHO, //
65  IAC, DO, SUPPRESS_GO_AHEAD, //
66  IAC, DONT, ECHO, //
67  IAC, DONT, LINEMODE, //
68  0 };
69  mSocket.printf(IAC_COMMANDS);
70 }
71 
72 int NetServerTelnet::getLine(char** line) {
73  char c;
74  unsigned int index = 0;
75  bool isLineTooLong = false;
76  *line = 0;
77  char* buffer = (char*) malloc(MAX_LINE_LEN);
78  if (!buffer) {
79  return RESULT_ERR_MEMORY;
80  }
81 
82  while (mSocket.read(&c, 1)) {
83  if ((c >= 0x20) && (c < 0x7F)) {
84  if (index < (MAX_LINE_LEN - 1)) {
85  mSocket.write(&c, 1);
86  buffer[index++] = c;
87  }
88  else {
89  isLineTooLong = true;
90  }
91  }
92  else if (c == '\r' || c == '\n') {
93  if (!mIsLineFeedSeq) {
94  mSocket.printf("\r\n");
95  mIsLineFeedSeq = true;
96  if (isLineTooLong) {
97  free(buffer);
98  return RESULT_ERR_LINE_TOO_LONG;
99  }
100  if (index == 0) {
101  free(buffer);
102  return RESULT_EMPTY_LINE;
103  }
104  buffer[index] = 0;
105  buffer = (char*) realloc(buffer, index + 1);
106  *line = buffer;
107  return index;
108  }
109  }
110  //Escape sequence
111  else if (c == 0x1B) {
112  //Get the '[' char
113  mSocket.read(&c, 1);
114  if (c == '[') {
115  mSocket.read(&c, 1);
116  switch (c) {
117  case 'A':
118  //UP
119  break;
120  case 'B':
121  //DOWN
122  break;
123  case 'C':
124  //RIGHT
125  break;
126  case 'D':
127  //LEFT
128  break;
129  }
130  }
131  }
132  else if (c == IAC) {
133  //Read and discard next two bytes, TODO manage the commands
134  mSocket.read(&c, 1);
135  mSocket.read(&c, 1);
136  }
137  else {
138  switch (c) {
139  case 0x03:
140  //ETX
141  mSocket.close();
142  free(buffer);
143  return 0;
144  case 0x7F:
145  case '\b':
146  //BACKSPACE
147  if (index > 0) {
148  index--;
149  mSocket.printf("\b \b");
150  }
151  break;
152  }
153  }
154  mIsLineFeedSeq = false;
155  }
156  free(buffer);
157  return RESULT_ERR_IO;
158 }
159 
160 void NetServerTelnet::freeLine(char* line) {
161  if (line != 0) {
162  free(line);
163  }
164 }
165 
166 int NetServerTelnet::getArgc(char* line) {
167  int argc = 0;
168  bool isSpaceFound = false;
169  char c;
170  while (true) {
171  c = *line++;
172  if (c == 0) {
173  break;
174  }
175  else if (c == ' ') {
176  isSpaceFound = true;
177  }
178  else if (isSpaceFound) {
179  argc++;
180  isSpaceFound = false;
181  }
182  }
183 
184  return argc;
185 }
186 
187 void NetServerTelnet::getArgV(char* line, char* argv[]) {
188  bool isSpaceFound = false;
189  char c;
190  while (true) {
191  c = *line;
192  if (c == 0) {
193  break;
194  }
195  else if (c == ' ') {
196  *line = 0;
197  isSpaceFound = true;
198  }
199  else if (isSpaceFound) {
200  *argv = line;
201  argv++;
202  isSpaceFound = false;
203  }
204  line++;
205  }
206 }
207 
208 void NetServerTelnet::onConnection() {
209 
210 }
211 
212 void NetServerTelnet::onDisconnection() {
213 
214 }
215 
216 void NetServerTelnet::run() {
217  while (true) {
218  mIsLineFeedSeq = false;
219  mSocket.listen(23);
220  mSocket.accept(Rtos::TICK_INFINITE);
221  iacNegotiate();
222  onConnection();
223  mSocket.printf(">");
224  while (mSocket.isConnected()) {
225  char* line;
226  int len = getLine(&line);
227  bool isEntryFound = false;
228  if (len > 0) {
229  int argc = getArgc(line);
230  char** argv = 0;
231  if (argc > 0) {
232  argv = (char**) malloc(sizeof(char*) * argc);
233  if (!argv) {
234  freeLine(line);
235  break; //Disconnect
236  }
237  }
238  getArgV(line, argv);
239  if (mEntries) {
240  for (const ENTRY* entry = mEntries; entry->name; entry++) {
241  if (strcmp((const char*) line, entry->name) == 0) {
242  (this->*entry->handler)(argc, argv);
243  isEntryFound = true;
244  break;
245  }
246  }
247  }
248  if (argv) {
249  free(argv);
250  }
251  freeLine(line);
252  if (!isEntryFound) {
253  mSocket.printf("Invalid command\r\n");
254  }
255  }
256  mSocket.printf(">");
257  }
258  onDisconnection();
259  mSocket.close();
260  }
261 }
262