1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  */
4 
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <stdarg.h>
8 #include <string.h>
9 #include <errno.h>
10 #include "aos/kernel.h"
11 
12 #include <lwip/def.h>
13 #include <lwip/netdb.h>
14 #include <lwip/sockets.h>
15 #include "lwip/apps/telnetserver.h"
16 
17 #define MAX_COMMANDLINE_LENGTH 512U
18 #define AOS_TELNETD_PRI (AOS_DEFAULT_APP_PRI+1)
19 
20 typedef struct
21 {
22     char command_buffer[MAX_COMMANDLINE_LENGTH];  /* A buffer which stores the currently being built command. */
23     int  buffer_position;                         /* The current write position in the command buffer. */
24 } CommandInterpreter_t;
25 
26 static CommandInterpreter_t interpreter;
27 
28 static bool telnetserver_is_running = false;
29 
30 static aos_task_t   aos_telnetd_task;
31 
32 extern int proc_onecmd(int argc, char *argv[]);
33 
34 /**
35  * Clear all characters from the command buffer.
36  *
37  * @param none
38  * @retval none
39  */
ClearCommandBuffer(void)40 void ClearCommandBuffer(void) {
41         for (int i = 0; i < MAX_COMMANDLINE_LENGTH; ++i) {
42                 interpreter.command_buffer[i] = '\0';
43         }
44         interpreter.buffer_position = 0U;
45 }
46 
47 /* Parse input line and locate arguments (if any), keeping count of the number
48 * of arguments and their locations.  Look up and call the corresponding cli
49 * function if one is found and pass it the argv array.
50 *
51 * Returns: 0 on success: the input line contained at least a function name and
52 *          that function exists and was called.
53 *          1 on lookup failure: there is no corresponding function for the
54 *          input line.
55 *          2 on invalid syntax: the arguments list couldn't be parsed
56 */
CommandParseLine(char * inbuf)57 static int CommandParseLine(char *inbuf)
58 {
59     struct {
60         unsigned inArg: 1;
61         unsigned inQuote: 1;
62         unsigned done: 1;
63     } stat;
64     static char *argvall[CLI_MAX_ONCECMD_NUM][CLI_MAX_ARG_NUM];
65     int argcall[CLI_MAX_ONCECMD_NUM] = {0};
66     /*
67     static char *argv[CLI_MAX_ONCECMD_NUM][CLI_MAX_ARG_NUM];
68     int argc = 0;*/
69     int cmdnum = 0;
70     int *pargc = &argcall[0];
71     int i = 0;
72     int ret = 0;
73 
74     memset((void *)&argvall, 0, sizeof(argvall));
75     memset((void *)&argcall, 0, sizeof(argcall));
76     memset(&stat, 0, sizeof(stat));
77 
78     do {
79         switch (inbuf[i]) {
80             case '\0':
81                 if (stat.inQuote) {
82                     return 2;
83                 }
84                 stat.done = 1;
85                 break;
86 
87             case '"':
88                 if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) {
89                     memcpy(&inbuf[i - 1], &inbuf[i], strlen(&inbuf[i]) + 1);
90                     --i;
91                     break;
92                 }
93                 if (!stat.inQuote && stat.inArg) {
94                     break;
95                 }
96                 if (stat.inQuote && !stat.inArg) {
97                     return 2;
98                 }
99 
100                 if (!stat.inQuote && !stat.inArg) {
101                     stat.inArg = 1;
102                     stat.inQuote = 1;
103                     (*pargc)++;
104                     argvall[cmdnum][(*pargc) - 1] = &inbuf[i + 1];
105                 } else if (stat.inQuote && stat.inArg) {
106                     stat.inArg = 0;
107                     stat.inQuote = 0;
108                     inbuf[i] = '\0';
109                 }
110                 break;
111 
112             case ' ':
113                 if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) {
114                     memcpy(&inbuf[i - 1], &inbuf[i],
115                            strlen(&inbuf[i]) + 1);
116                     --i;
117                     break;
118                 }
119                 if (!stat.inQuote && stat.inArg) {
120                     stat.inArg = 0;
121                     inbuf[i] = '\0';
122                 }
123                 break;
124 
125             case ';':
126                 if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) {
127                     memcpy(&inbuf[i - 1], &inbuf[i],
128                            strlen(&inbuf[i]) + 1);
129                     --i;
130                     break;
131                 }
132                 if (stat.inQuote) {
133                     return 2;
134                 }
135                 if (!stat.inQuote && stat.inArg) {
136                     stat.inArg = 0;
137                     inbuf[i] = '\0';
138 
139                     if (*pargc) {
140                         if (++cmdnum < CLI_MAX_ONCECMD_NUM) {
141                             pargc = &argcall[cmdnum];
142                         }
143                     }
144                 }
145 
146                 break;
147 
148             default:
149                 if (!stat.inArg) {
150                     stat.inArg = 1;
151                     (*pargc)++;
152                     argvall[cmdnum][(*pargc) - 1] = &inbuf[i];
153                 }
154                 break;
155         }
156     } while (!stat.done && ++i < BUFSIZ && cmdnum < CLI_MAX_ONCECMD_NUM && (*pargc) < CLI_MAX_ARG_NUM);
157 
158     if (stat.inQuote) {
159         return 2;
160     }
161 
162     for ( i = 0; i <= cmdnum && i < CLI_MAX_ONCECMD_NUM ; i++ ) {
163         TelnetWriteString("\n");
164         ret |= proc_onecmd(argcall[i], argvall[i]);
165     }
166 
167     return ret;
168 }
169 
CommandAddChar(const char character)170 void CommandAddChar(const char character)
171 {
172     if (character != 0x00 && interpreter.buffer_position < MAX_COMMANDLINE_LENGTH)
173     {
174         if (character == 0x0A || character == 0x0D)
175         {
176             /* We have reached the end of a command, parse it */
177             CommandParseLine(interpreter.command_buffer);
178             /* Clear the command buffer */
179             ClearCommandBuffer();
180         }
181         else if (character == 0x08 || character == 0x7F)
182         {
183             /* Remove the last character from the buffer */
184             if (interpreter.buffer_position > 0)
185             {
186                 --interpreter.buffer_position; /* Move the list back one */
187                 interpreter.command_buffer[interpreter.buffer_position] = '\0'; /* Set the current position to a null character */
188             }
189        }
190        else if (character == 0x20)
191        {
192            if (interpreter.buffer_position > 0
193                && interpreter.command_buffer[interpreter.buffer_position - 1] != 0x20)
194            {
195                /* Add another character to the buffer */
196                interpreter.command_buffer[interpreter.buffer_position] = character; /* Add the character at the current position */
197                ++interpreter.buffer_position; /* Move the buffer pointer to the next position */
198            }
199            /* If the previous character is a space, ignore further spaces */
200       }
201       else
202       {
203            /* Add another character to the buffer */
204            interpreter.command_buffer[interpreter.buffer_position] = character; /* Add the character at the current position */
205            ++interpreter.buffer_position; /* Move the buffer pointer to the next position */
206       }
207     }
208     return ;
209 }
210 
TelnetServerProcess(void * arg)211 static void TelnetServerProcess(void* arg)
212 {
213    char character;
214    char telcmd[10] = "echo tel";
215 
216    if (InitializeTelnetServer() != TELNET_OK)
217    {
218        return ;
219    }
220 
221    telnetserver_is_running = true;
222 
223    /* set cli aos telnet server mode */
224    CommandParseLine(telcmd);
225 
226    while(1)
227    {
228         if(telnetserver_is_running != true)
229         {
230             aos_task_exit(0);
231         }
232 
233         if (TelnetIsConnected() == true)
234         { /* We have an active Telnet connection to service */
235             /* Do server stuff */
236             character = TelnetRead();
237             if(character != '\0')
238             {
239                 CommandAddChar(character);
240             }
241             else
242             {
243                 aos_msleep(500);
244             }
245         }
246         else
247         {
248            //printf("Telnet is not connected, try again later.\n");
249            aos_msleep(1000);
250         }
251         aos_msleep(50);
252    }
253    return ;
254 }
255 
telnetserver_start()256 void telnetserver_start()
257 {
258    aos_task_new_ext(&aos_telnetd_task, "telnetserver", TelnetServerProcess, NULL, 81920, AOS_TELNETD_PRI);
259 }
260 
telnetserver_stop()261 void telnetserver_stop()
262 {
263   telnetserver_is_running = false;
264   if(TelnetIsConnected() == true)
265   {
266      TelnetClose();
267   }
268 }
269 
270