]> rtime.felk.cvut.cz Git - fpga/plasma.git/blob - kernel/netutil.c
Local copy of Plasma MIPS project.
[fpga/plasma.git] / kernel / netutil.c
1 /*--------------------------------------------------------------------\r
2  * TITLE: Plasma TCP/IP Network Utilities\r
3  * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)\r
4  * DATE CREATED: 4/20/07\r
5  * FILENAME: netutil.c\r
6  * PROJECT: Plasma CPU core\r
7  * COPYRIGHT: Software placed into the public domain by the author.\r
8  *    Software 'as is' without warranty.  Author liable for nothing.\r
9  * DESCRIPTION:\r
10  *    Plasma FTP server and FTP client and TFTP server and client \r
11  *    and Telnet server.\r
12  *--------------------------------------------------------------------*/\r
13 #undef INCLUDE_FILESYS\r
14 #define INCLUDE_FILESYS\r
15 #ifdef WIN32\r
16 #include <stdio.h>\r
17 #include <stdlib.h>\r
18 #include <string.h>\r
19 #include <ctype.h>\r
20 #define _LIBC\r
21 #endif\r
22 #include "rtos.h"\r
23 #include "tcpip.h"\r
24 \r
25 #ifdef DLL_SETUP\r
26 static void ConsoleRun(IPSocket *socket, char *argv[]);\r
27 #endif\r
28 \r
29 //******************* FTP Server ************************\r
30 typedef struct {\r
31    IPSocket *socket;\r
32    int ip, port, bytes, done, canReceive;\r
33    FILE *file;\r
34 } FtpdInfo;\r
35 \r
36 static void FtpdSender(IPSocket *socket)\r
37 {\r
38    unsigned char buf[600];\r
39    int i, bytes, bytes2;\r
40    FtpdInfo *info = (FtpdInfo*)socket->userPtr;\r
41 \r
42    if(info == NULL || info->done)\r
43       return;\r
44    fseek(info->file, info->bytes, 0);\r
45    for(i = 0; i < 100000; ++i)\r
46    {\r
47       bytes = fread(buf, 1, 512, info->file);\r
48       bytes2 = IPWrite(socket, buf, bytes);\r
49       info->bytes += bytes2;\r
50       if(bytes != bytes2)\r
51          return;\r
52       if(bytes < 512)\r
53       {\r
54          fclose(info->file);\r
55          IPClose(socket);\r
56          info->done = 1;\r
57          IPPrintf(info->socket, "226 Done\r\n");\r
58          return;\r
59       }\r
60    }\r
61 }\r
62 \r
63 \r
64 static void FtpdReceiver(IPSocket *socket)\r
65 {\r
66    unsigned char buf[600];\r
67    int bytes, state = socket->state;\r
68    FtpdInfo *info = (FtpdInfo*)socket->userPtr;\r
69 \r
70    if(info == NULL || info->done)\r
71       return;\r
72    do\r
73    {\r
74       bytes = IPRead(socket, buf, sizeof(buf));\r
75       fwrite(buf, 1, bytes, info->file);\r
76    } while(bytes);\r
77 \r
78    if(state > IP_TCP)\r
79    {\r
80       fclose(info->file);\r
81       info->done = 1;\r
82       IPPrintf(info->socket, "226 Done\r\n");\r
83       IPClose(socket);\r
84       return;\r
85    }\r
86 }\r
87 \r
88 \r
89 static void FtpdServer(IPSocket *socket)\r
90 {\r
91    uint8 buf[600];\r
92    int bytes;\r
93    int ip0, ip1, ip2, ip3, port0, port1;\r
94    IPSocket *socketOut;\r
95    FtpdInfo *info = (FtpdInfo*)socket->userPtr;\r
96 \r
97    if(socket == NULL)\r
98       return;\r
99    bytes = IPRead(socket, buf, sizeof(buf)-1);\r
100    buf[bytes] = 0;\r
101    //printf("(%s)\n", buf);\r
102    if(socket->userPtr == NULL)\r
103    {\r
104       info = (FtpdInfo*)malloc(sizeof(FtpdInfo));\r
105       if(info == NULL)\r
106          return;\r
107       memset(info, 0, sizeof(FtpdInfo));\r
108       socket->userPtr = info;\r
109       info->socket = socket;\r
110       socket->timeoutReset = 60;\r
111       IPPrintf(socket, "220 Connected to Plasma\r\n");\r
112    }\r
113    else if(socket->userPtr == (void*)-1)\r
114    {\r
115       return;\r
116    }\r
117    else if(strstr((char*)buf, "USER"))\r
118    {\r
119       if(strstr((char*)buf, "PlasmaSend"))\r
120          info->canReceive = 1;\r
121       IPPrintf(socket, "331 Password?\r\n");\r
122    }\r
123    else if(strstr((char*)buf, "PASS"))\r
124    {\r
125       IPPrintf(socket, "230 Logged in\r\n");\r
126    }\r
127    else if(strstr((char*)buf, "PORT"))\r
128    {\r
129       sscanf((char*)buf + 5, "%d,%d,%d,%d,%d,%d", &ip0, &ip1, &ip2, &ip3, &port0, &port1);\r
130       info->ip = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;\r
131       info->port = (port0 << 8) | port1;\r
132       //printf("ip=0x%x port=%d\n", info->ip, info->port);\r
133       IPPrintf(socket, "200 OK\r\n");\r
134    }\r
135    else if(strstr((char*)buf, "RETR") || strstr((char*)buf, "STOR"))\r
136    {\r
137       char *ptr = strstr((char*)buf, "\r");\r
138       if(ptr)\r
139          *ptr = 0;\r
140       info->file = NULL;\r
141       info->bytes = 0;\r
142       info->done = 0;\r
143       if(strstr((char*)buf, "RETR"))\r
144          info->file = fopen((char*)buf + 5, "rb");\r
145       else if(info->canReceive)\r
146          info->file = fopen((char*)buf + 5, "wb");\r
147       if(info->file)\r
148       {\r
149          IPPrintf(socket, "150 File ready\r\n");\r
150          if(strstr((char*)buf, "RETR"))\r
151             socketOut = IPOpen(IP_MODE_TCP, info->ip, info->port, FtpdSender);\r
152          else\r
153             socketOut = IPOpen(IP_MODE_TCP, info->ip, info->port, FtpdReceiver);\r
154          if(socketOut)\r
155             socketOut->userPtr = info;\r
156       }\r
157       else\r
158       {\r
159          IPPrintf(socket, "500 Error\r\n");\r
160       }\r
161    }\r
162    else if(strstr((char*)buf, "QUIT"))\r
163    {\r
164       if(socket->userPtr)\r
165          free(socket->userPtr);\r
166       socket->userPtr = (void*)-1;\r
167       IPPrintf(socket, "221 Bye\r\n");\r
168       IPClose(socket);\r
169    }\r
170    else if(bytes)\r
171    {\r
172       IPPrintf(socket, "500 Error\r\n");\r
173    }\r
174 }\r
175 \r
176 \r
177 void FtpdInit(int UseFiles)\r
178 {\r
179    (void)UseFiles;\r
180    IPOpen(IP_MODE_TCP, 0, 21, FtpdServer);\r
181 }\r
182 \r
183 \r
184 //******************* FTP Client ************************\r
185 \r
186 typedef struct {\r
187    uint32 ip, port;\r
188    char user[80], passwd[80], filename[80];\r
189    uint8 *buf;\r
190    int size, bytes, send, state;\r
191 } FtpInfo;\r
192 \r
193 \r
194 static void FtpCallbackTransfer(IPSocket *socket)\r
195 {\r
196    int bytes, state = socket->state;\r
197    FtpInfo *info = (FtpInfo*)socket->userPtr;\r
198 \r
199    //printf("FtpCallbackTransfer\n");\r
200    if(info == NULL)\r
201       return;\r
202    bytes = info->size - info->bytes;\r
203    if(info->send == 0)\r
204       bytes = IPRead(socket, info->buf + info->bytes, bytes);\r
205    else\r
206       bytes = IPWrite(socket, info->buf + info->bytes, bytes);\r
207    info->bytes += bytes;\r
208    if(info->bytes == info->size || (bytes == 0 && state > IP_TCP))\r
209    {\r
210       socket->userFunc(info->buf, info->bytes);\r
211       free(info);\r
212       socket->userPtr = NULL;\r
213       IPClose(socket);\r
214    }\r
215 }\r
216 \r
217 \r
218 static void FtpCallback(IPSocket *socket)\r
219 {\r
220    char buf[600];\r
221    FtpInfo *info = (FtpInfo*)socket->userPtr;\r
222    int bytes, value;\r
223 \r
224    bytes = IPRead(socket, (uint8*)buf, sizeof(buf)-1);\r
225    if(bytes == 0)\r
226       return;\r
227    buf[bytes] = 0;\r
228    sscanf(buf, "%d", &value);\r
229    if(bytes > 2)\r
230       buf[bytes-2] = 0;\r
231    //printf("FtpCallback(%d:%s)\n", socket->userData, buf);\r
232    if(value / 100 != 2 && value / 100 != 3)\r
233       return;\r
234    buf[0] = 0;\r
235    switch(socket->userData) {\r
236    case 0:\r
237       sprintf(buf, "USER %s\r\n", info->user);\r
238       socket->userData = 1;\r
239       break;\r
240    case 1:\r
241       sprintf(buf, "PASS %s\r\n", info->passwd);\r
242       socket->userData = 2;\r
243       if(value == 331)\r
244          break;  //possible fall-through\r
245    case 2:\r
246       sprintf(buf, "PORT %d,%d,%d,%d,%d,%d\r\n",\r
247          info->ip >> 24, (uint8)(info->ip >> 16),\r
248          (uint8)(info->ip >> 8), (uint8)info->ip,\r
249          (uint8)(info->port >> 8), (uint8)info->port);\r
250       socket->userData = 3;\r
251       break;\r
252    case 3:\r
253       if(info->send == 0)\r
254          sprintf(buf, "RETR %s\r\n", info->filename);\r
255       else\r
256          sprintf(buf, "STOR %s\r\n", info->filename);\r
257       socket->userData = 4;\r
258       break;\r
259    case 4:\r
260       sprintf(buf, "QUIT\r\n");\r
261       socket->userData = 9;\r
262       break;\r
263    }\r
264    IPWrite(socket, (uint8*)buf, strlen(buf));\r
265    IPWriteFlush(socket);\r
266    if(socket->userData == 9)\r
267       IPClose(socket);\r
268 }\r
269 \r
270 \r
271 IPSocket *FtpTransfer(uint32 ip, char *user, char *passwd, \r
272                       char *filename, uint8 *buf, int size, \r
273                       int send, void (*callback)(uint8 *data, int size))\r
274 {\r
275    IPSocket *socket, *socketTransfer;\r
276    FtpInfo *info;\r
277    uint8 *ptr;\r
278    info = (FtpInfo*)malloc(sizeof(FtpInfo));\r
279    if(info == NULL)\r
280       return NULL;\r
281    strncpy(info->user, user, 80);\r
282    strncpy(info->passwd, passwd, 80);\r
283    strncpy(info->filename, filename, 80);\r
284    info->buf = buf;\r
285    info->size = size;\r
286    info->send = send;\r
287    info->bytes = 0;\r
288    info->state = 0;\r
289    info->port = 2000;\r
290    socketTransfer = IPOpen(IP_MODE_TCP, 0, info->port, FtpCallbackTransfer);\r
291    socketTransfer->userPtr = info;\r
292    socketTransfer->userFunc = callback;\r
293    socket = IPOpen(IP_MODE_TCP, ip, 21, FtpCallback);\r
294    socket->userPtr = info;\r
295    socket->userFunc = callback;\r
296    ptr = socket->headerSend;\r
297    info->ip = IPAddressSelf();\r
298    return socket;\r
299 }\r
300 \r
301 \r
302 //******************* TFTP Server ************************\r
303 \r
304 \r
305 static void TftpdCallback(IPSocket *socket)\r
306 {\r
307    unsigned char buf[512+4];\r
308    int bytes, blockNum;\r
309    FILE *file = (FILE*)socket->userPtr;\r
310    bytes = IPRead(socket, buf, sizeof(buf));\r
311    //printf("TfptdCallback bytes=%d\n", bytes);\r
312    if(bytes < 4 || buf[0])\r
313       return;\r
314    if(buf[1] == 1)  //RRQ = Read Request\r
315    {\r
316       if(file)\r
317          fclose(file);\r
318       file = fopen((char*)buf+2, "rb");\r
319       socket->userPtr = file;\r
320       if(file == NULL)\r
321       {\r
322          buf[0] = 0;\r
323          buf[1] = 5;   //ERROR\r
324          buf[2] = 0;\r
325          buf[3] = 0;\r
326          buf[4] = 'X'; //Error string\r
327          buf[5] = 0;\r
328          IPWrite(socket, buf, 6);\r
329          return;\r
330       }\r
331    }\r
332    if(buf[1] == 1 || buf[1] == 4) //ACK\r
333    {\r
334       if(file == NULL)\r
335          return;\r
336       if(buf[1] == 1)\r
337          blockNum = 0;\r
338       else\r
339          blockNum = (buf[2] << 8) | buf[3];\r
340       ++blockNum;\r
341       buf[0] = 0;\r
342       buf[1] = 3;  //DATA\r
343       buf[2] = (uint8)(blockNum >> 8);\r
344       buf[3] = (uint8)blockNum;\r
345       fseek(file, (blockNum-1)*512, 0);\r
346       bytes = fread(buf+4, 1, 512, file);\r
347       IPWrite(socket, buf, bytes+4);\r
348    }\r
349 }\r
350 \r
351 \r
352 void TftpdInit(void)\r
353 {\r
354    IPSocket *socket;\r
355    socket = IPOpen(IP_MODE_UDP, 0, 69, TftpdCallback);\r
356 }\r
357 \r
358 \r
359 //******************* TFTP Client ************************\r
360 \r
361 \r
362 static void TftpCallback(IPSocket *socket)\r
363 {\r
364    unsigned char buf[512+4];\r
365    int bytes, blockNum, length;\r
366 \r
367    bytes = IPRead(socket, buf, sizeof(buf));\r
368    if(bytes < 4 || buf[0])\r
369       return;\r
370    blockNum = (buf[2] << 8) | buf[3];\r
371    length = blockNum * 512 - 512 + bytes - 4;\r
372    //printf("TftpCallback(%d,%d)\n", buf[1], blockNum);\r
373    if(length > (int)socket->userData)\r
374    {\r
375       bytes -= length - (int)socket->userData;\r
376       length = (int)socket->userData;\r
377    }\r
378    if(buf[1] == 3) //DATA\r
379    {\r
380       memcpy((uint8*)socket->userPtr + blockNum * 512 - 512, buf+4, bytes-4);\r
381       buf[1] = 4; //ACK\r
382       IPWrite(socket, buf, 4);\r
383       if(bytes-4 < 512)\r
384       {\r
385          socket->userFunc(socket->userPtr, length);\r
386          IPClose(socket);\r
387       }\r
388    }\r
389 }\r
390 \r
391 \r
392 IPSocket *TftpTransfer(uint32 ip, char *filename, uint8 *buffer, int size,\r
393                        void (*callback)(uint8 *data, int bytes))\r
394 {\r
395    IPSocket *socket;\r
396    uint8 buf[512+4];\r
397    int bytes;\r
398    socket = IPOpen(IP_MODE_UDP, ip, 69, TftpCallback);\r
399    socket->userPtr = buffer;\r
400    socket->userData = size;\r
401    socket->userFunc = callback;\r
402    buf[0] = 0;\r
403    buf[1] = 1; //read\r
404    strcpy((char*)buf+2, filename);\r
405    bytes = strlen(filename);\r
406    strcpy((char*)buf+bytes+3, "octet");\r
407    IPWrite(socket, buf, bytes+9);\r
408    return socket;\r
409 }\r
410 \r
411 \r
412 //******************* Telnet Server ************************\r
413 \r
414 #define COMMAND_BUFFER_SIZE 80\r
415 #define COMMAND_BUFFER_COUNT 10\r
416 static char CommandHistory[400];\r
417 static char *CommandPtr[COMMAND_BUFFER_COUNT];\r
418 static int CommandIndex;\r
419 \r
420 typedef void (*ConsoleFunc)(IPSocket *socket, char *argv[]);\r
421 typedef struct {\r
422    char *name;\r
423    ConsoleFunc func;\r
424 } TelnetFunc_t;\r
425 static TelnetFunc_t *TelnetFuncList;\r
426 \r
427 \r
428 static void TelnetServer(IPSocket *socket)\r
429 {\r
430    uint8 buf[COMMAND_BUFFER_SIZE+4];\r
431    char bufOut[32];\r
432    int bytes, i, j, k, length, found;\r
433    char *ptr, *command = socket->userPtr;\r
434    char *argv[10];\r
435 \r
436    if(socket->state > IP_TCP)\r
437       return;\r
438    for(;;)\r
439    {\r
440       bytes = IPRead(socket, buf, sizeof(buf)-1);\r
441       if(command == NULL)\r
442       {\r
443          socket->userPtr = command = (char*)malloc(COMMAND_BUFFER_SIZE);\r
444          if(command == NULL)\r
445          {\r
446             IPClose(socket);\r
447             return;\r
448          }\r
449          socket->timeoutReset = 300;\r
450          buf[0] = 255; //IAC\r
451          buf[1] = 251; //WILL\r
452          buf[2] = 3;   //suppress go ahead\r
453          buf[3] = 255; //IAC\r
454          buf[4] = 251; //WILL\r
455          buf[5] = 1;   //echo\r
456          strcpy((char*)buf+6, "Welcome to Plasma.\r\n-> ");\r
457          IPWrite(socket, buf, 6+23);\r
458          IPWriteFlush(socket);\r
459          command[0] = 0;\r
460          return;\r
461       }\r
462       if(bytes == 0)\r
463          return;\r
464       socket->dontFlush = 0;\r
465       buf[bytes] = 0;\r
466       length = (int)strlen(command);\r
467       for(j = 0; j < bytes; ++j)\r
468       {\r
469          if(buf[j] == 255)\r
470             return;\r
471          if(buf[j] == 8 || (buf[j] == 27 && buf[j+2] == 'D'))\r
472          {\r
473             if(buf[j] == 27)\r
474                j += 2;\r
475             if(length)\r
476             {\r
477                // Backspace\r
478                command[--length] = 0;\r
479                bufOut[0] = 8;\r
480                bufOut[1] = ' ';\r
481                bufOut[2] = 8;\r
482                IPWrite(socket, (uint8*)bufOut, 3);\r
483             }\r
484          }\r
485          else if(buf[j] == 27)\r
486          {\r
487             // Command History\r
488             if(buf[j+2] == 'A')\r
489             {\r
490                if(++CommandIndex > COMMAND_BUFFER_COUNT)\r
491                   CommandIndex = COMMAND_BUFFER_COUNT;\r
492             }\r
493             else if(buf[j+2] == 'B')\r
494             {\r
495                if(--CommandIndex < 0)\r
496                   CommandIndex = 0;\r
497             }\r
498             else \r
499                return;\r
500             bufOut[0] = 8;\r
501             bufOut[1] = ' ';\r
502             bufOut[2] = 8;\r
503             for(i = 0; i < length; ++i)\r
504                IPWrite(socket, (uint8*)bufOut, 3);\r
505             command[0] = 0;\r
506             if(CommandIndex && CommandPtr[CommandIndex-1])\r
507                strncat(command, CommandPtr[CommandIndex-1], COMMAND_BUFFER_SIZE-1);\r
508             length = (int)strlen(command);\r
509             IPWrite(socket, (uint8*)command, length);\r
510             j += 2;\r
511          }\r
512          else\r
513          {\r
514             if(buf[j] == 0)\r
515                buf[j] = '\n';  //Linux support\r
516             if(length < COMMAND_BUFFER_SIZE-4 || (length < \r
517                COMMAND_BUFFER_SIZE-2 && (buf[j] == '\r' || buf[j] == '\n')))\r
518             {\r
519                IPWrite(socket, buf+j, 1);\r
520                command[length] = buf[j];\r
521                command[++length] = 0;\r
522             }\r
523          }\r
524          ptr = strstr(command, "\r\n");\r
525          if(ptr)\r
526          {\r
527             // Save command in CommandHistory\r
528             ptr[0] = 0;\r
529             length = (int)strlen(command);\r
530             if(length == 0)\r
531             {\r
532                IPPrintf(socket, "-> ");\r
533                continue;\r
534             }\r
535             if(length < COMMAND_BUFFER_SIZE)\r
536             {\r
537                memmove(CommandHistory + length + 1, CommandHistory,\r
538                   sizeof(CommandHistory) - length - 1);\r
539                strcpy(CommandHistory, command);\r
540                CommandHistory[sizeof(CommandHistory)-1] = 0;\r
541                for(i = COMMAND_BUFFER_COUNT-2; i >= 0; --i)\r
542                {\r
543                   if(CommandPtr[i] == NULL || CommandPtr[i] + length + 1 >= \r
544                      CommandHistory + sizeof(CommandHistory))\r
545                      CommandPtr[i+1] = NULL;\r
546                   else\r
547                      CommandPtr[i+1] = CommandPtr[i] + length + 1;\r
548                }\r
549                CommandPtr[0] = CommandHistory;\r
550             }\r
551    \r
552             //Start command\r
553             for(i = 0; i < 10; ++i)\r
554                argv[i] = "";\r
555             i = 0;\r
556             argv[i++] = command;\r
557             for(ptr = command; *ptr && i < 10; ++ptr)\r
558             {\r
559                if(*ptr == ' ')\r
560                {\r
561                   *ptr = 0;\r
562                   argv[i++] = ptr + 1;\r
563                }\r
564             }\r
565             if(argv[0][0] == 0)\r
566             {\r
567                IPPrintf(socket, "-> ");\r
568                continue;\r
569             }\r
570             found = 0;\r
571             for(i = 0; TelnetFuncList[i].name; ++i)\r
572             {\r
573                if(strcmp(command, TelnetFuncList[i].name) == 0 &&\r
574                   TelnetFuncList[i].func)\r
575                {\r
576                   found = 1;\r
577                   for(k = 1; k < 10; ++k)\r
578                   {\r
579                      if(argv[k][0] == '>' && argv[k][1]) //stdout to file?\r
580                      {\r
581                         socket->fileOut = fopen(&argv[k][1], "a");\r
582                         argv[k] = "";\r
583                      }\r
584                      if(argv[k][0] == '<' && argv[k][1]) //stdin from file?\r
585                      {\r
586                         socket->fileIn = fopen(&argv[k][1], "r");\r
587                         argv[k] = "";\r
588                      }\r
589                   }\r
590                   TelnetFuncList[i].func(socket, argv);\r
591                   if(socket->fileOut)\r
592                   {\r
593                      fwrite("\r\n", 1, 2, socket->fileOut);\r
594                      fclose(socket->fileOut);\r
595                   }\r
596                   socket->fileOut = NULL;\r
597                   break;\r
598                }\r
599             }\r
600 #ifdef DLL_SETUP\r
601             if(found == 0)\r
602             {\r
603                strcpy((char*)buf, "/flash/bin/");\r
604                strcat((char*)buf, argv[0]);\r
605                argv[0] = (char*)buf;\r
606                ConsoleRun(socket, argv);\r
607             }\r
608 #endif\r
609             if(socket->state > IP_TCP)\r
610                return;\r
611             command[0] = 0;\r
612             length = 0;\r
613             CommandIndex = 0;\r
614             if(socket->dontFlush == 0)\r
615                IPPrintf(socket, "\r\n-> ");\r
616          } //command entered\r
617       } //bytes\r
618       IPWriteFlush(socket);\r
619    } \r
620 }\r
621 \r
622 \r
623 void TelnetInit(TelnetFunc_t *funcList)\r
624 {\r
625    IPSocket *socket;\r
626    TelnetFuncList = funcList;\r
627    socket = IPOpen(IP_MODE_TCP, 0, 23, TelnetServer);\r
628 }\r
629 \r
630 \r
631 //******************* Console ************************\r
632 \r
633 #define STORAGE_SIZE 1024*64\r
634 static uint8 *myStorage;\r
635 static IPSocket *socketTelnet;\r
636 static char storageFilename[60];\r
637 \r
638 \r
639 static void ConsoleHelp(IPSocket *socket, char *argv[])\r
640 {\r
641    char buf[200];\r
642    int i;\r
643    (void)argv;\r
644    strcpy(buf, "Commands: ");\r
645    for(i = 0; TelnetFuncList[i].name; ++i)\r
646    {\r
647       if(TelnetFuncList[i].func)\r
648       {\r
649          if(i)\r
650             strcat(buf, ", ");\r
651          strcat(buf, TelnetFuncList[i].name);\r
652       }\r
653    }\r
654    IPPrintf(socket, buf);\r
655 }\r
656 \r
657 \r
658 static void ConsoleExit(IPSocket *socket, char *argv[])\r
659 {\r
660    free(argv[0]);\r
661    socket->userPtr = NULL;\r
662    IPClose(socket);\r
663 }\r
664 \r
665 \r
666 static void ConsoleCat(IPSocket *socket, char *argv[])\r
667 {\r
668    FILE *file;\r
669    uint8 buf[200];\r
670    int bytes;\r
671 \r
672    file = fopen(argv[1], "r");\r
673    if(file == NULL)\r
674       return;\r
675    for(;;)\r
676    {\r
677       bytes = fread(buf, 1, sizeof(buf), file);\r
678       if(bytes == 0)\r
679          break;\r
680       IPWrite(socket, buf, bytes);\r
681    }\r
682    fclose(file);\r
683 }\r
684 \r
685 \r
686 static void ConsoleCp(IPSocket *socket, char *argv[])\r
687 {\r
688    FILE *fileIn, *fileOut;\r
689    uint8 buf[200];\r
690    int bytes;\r
691    (void)socket;\r
692 \r
693    fileIn = fopen(argv[1], "r");\r
694    if(fileIn == NULL)\r
695       return;\r
696    fileOut = fopen(argv[2], "w");\r
697    if(fileOut)\r
698    {\r
699       for(;;)\r
700       {\r
701          bytes = fread(buf, 1, sizeof(buf), fileIn);\r
702          if(bytes == 0)\r
703             break;\r
704          fwrite(buf, 1, bytes, fileOut);\r
705       }\r
706       fclose(fileOut);\r
707    }\r
708    fclose(fileIn);\r
709 }\r
710 \r
711 \r
712 static void ConsoleRm(IPSocket *socket, char *argv[])\r
713 {\r
714    (void)socket;\r
715    OS_fdelete(argv[1]);\r
716 }\r
717 \r
718 \r
719 static void ConsoleMkdir(IPSocket *socket, char *argv[])\r
720 {\r
721    (void)socket;\r
722    OS_fmkdir(argv[1]);\r
723 }\r
724 \r
725 \r
726 static void ConsoleLs(IPSocket *socket, char *argv[])\r
727 {\r
728    FILE *file;\r
729    char buf[200], buf2[80];\r
730    int bytes, width;\r
731 \r
732    file = fopen(argv[1], "r");\r
733    if(file == NULL)\r
734       return;\r
735    width = 0;\r
736    for(;;)\r
737    {\r
738       bytes = OS_fdir(file, buf);\r
739       if(bytes)\r
740          break;\r
741       if(buf[0] == 255)\r
742          continue;\r
743       bytes = OS_flength(buf);\r
744       sprintf(buf2, "%s:%d                    ", buf, bytes);\r
745       bytes = strlen(buf2);\r
746       bytes -= bytes % 20;\r
747       buf2[bytes] = 0;\r
748       width += bytes;\r
749       if(width == 80)\r
750          --bytes;\r
751       if(width > 80)\r
752       {\r
753          IPPrintf(socket, "\n");\r
754          width = bytes;\r
755       }\r
756       IPPrintf(socket, "%s", buf2);\r
757    }\r
758    fclose(file);\r
759 }\r
760 \r
761 \r
762 #ifdef INCLUDE_FLASH\r
763 static void ConsoleFlashErase(IPSocket *socket, char *argv[])\r
764 {\r
765    int bytes;\r
766    (void)argv;\r
767    IPPrintf(socket, "\r\nErasing");\r
768    for(bytes = 1024*128; bytes < 1024*1024*16; bytes += 1024*128)\r
769    {\r
770       IPPrintf(socket, ".");\r
771       FlashErase(bytes);\r
772    }\r
773    IPPrintf(socket, "\r\nMust Reboot\r\n");\r
774    OS_ThreadSleep(OS_WAIT_FOREVER);\r
775 }\r
776 #endif\r
777 \r
778 \r
779 static void ConsoleMath(IPSocket *socket, char *argv[])\r
780 {\r
781    int v1, v2, ch;\r
782    if(argv[3][0] == 0)\r
783    {\r
784       IPPrintf(socket, "Usage: math <number> <operator> <value>\r\n");\r
785       return;\r
786    }\r
787    v1 = atoi(argv[1]);\r
788    ch = argv[2][0];\r
789    v2 = atoi(argv[3]);\r
790    if(ch == '+')\r
791       v1 += v2;\r
792    else if(ch == '-')\r
793       v1 -= v2;\r
794    else if(ch == '*')\r
795       v1 *= v2;\r
796    else if(ch == '/')\r
797    {\r
798       if(v2 != 0)\r
799          v1 /= v2;\r
800    }\r
801    IPPrintf(socket, "%d", v1);\r
802 }\r
803 \r
804 \r
805 static void PingCallback(IPSocket *socket)\r
806 {\r
807    IPSocket *socket2 = socket->userPtr;\r
808    IPClose(socket);\r
809    if(socket2)\r
810       IPPrintf(socket2, "Ping Reply");\r
811    else\r
812       printf("Ping Reply\n");\r
813 }\r
814 \r
815 \r
816 static void DnsResultCallback(IPSocket *socket, uint32 ip, void *arg)\r
817 {\r
818    char buf[COMMAND_BUFFER_SIZE];\r
819    IPSocket *socketTelnet = arg;\r
820    IPSocket *socketPing;\r
821    (void)socket;\r
822 \r
823    sprintf(buf,  "ip=%d.%d.%d.%d\r\n", \r
824       (uint8)(ip >> 24), (uint8)(ip >> 16), (uint8)(ip >> 8), (uint8)ip);\r
825    IPPrintf(socketTelnet, buf);\r
826    socketPing = IPOpen(IP_MODE_PING, ip, 0, PingCallback);\r
827    socketPing->userPtr = socketTelnet;\r
828    buf[0] = 'A';\r
829    IPWrite(socketPing, (uint8*)buf, 1);\r
830 }\r
831 \r
832 \r
833 static void ConsolePing(IPSocket *socket, char *argv[])\r
834 {\r
835    int ip0, ip1, ip2, ip3;\r
836 \r
837    if('0' <= argv[1][0] && argv[1][0] <= '9')\r
838    {\r
839       sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);\r
840       ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;\r
841       DnsResultCallback(socket, ip0, socket);\r
842    }\r
843    else\r
844    {\r
845       IPResolve(argv[1], DnsResultCallback, socket);\r
846       IPPrintf(socket, "Sent DNS request");\r
847    }\r
848 }\r
849 \r
850 \r
851 static void ConsoleTransferDone(uint8 *data, int length)\r
852 {\r
853    FILE *file;\r
854    IPPrintf(socketTelnet, "Transfer Done");\r
855    file = fopen(storageFilename, "w");\r
856    if(file)\r
857    {\r
858       fwrite(data, 1, length, file);\r
859       fclose(file);\r
860    }\r
861    if(myStorage)\r
862       free(myStorage);\r
863    myStorage = NULL;\r
864 }\r
865 \r
866 \r
867 static void ConsoleFtp(IPSocket *socket, char *argv[])\r
868 {\r
869    int ip0, ip1, ip2, ip3;\r
870    if(argv[1][0] == 0)\r
871    {\r
872       IPPrintf(socket, "ftp #.#.#.# User Password File");\r
873       return;\r
874    }\r
875    sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);\r
876    ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;\r
877    socketTelnet = socket;\r
878    if(myStorage == NULL)\r
879       myStorage = (uint8*)malloc(STORAGE_SIZE);\r
880    if(myStorage == NULL)\r
881       return;\r
882    strcpy(storageFilename, argv[4]);\r
883    FtpTransfer(ip0, argv[2], argv[3], argv[4], myStorage, STORAGE_SIZE-1, \r
884       0, ConsoleTransferDone);\r
885 }\r
886 \r
887 \r
888 static void ConsoleTftp(IPSocket *socket, char *argv[])\r
889 {\r
890    int ip0, ip1, ip2, ip3;\r
891    if(argv[1][0] == 0)\r
892    {\r
893       IPPrintf(socket, "tftp #.#.#.# File");\r
894       return;\r
895    }\r
896    sscanf(argv[1], "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);\r
897    ip0 = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;\r
898    socketTelnet = socket;\r
899    if(myStorage == NULL)\r
900       myStorage = (uint8*)malloc(STORAGE_SIZE);\r
901    if(myStorage == NULL)\r
902       return;\r
903    strcpy(storageFilename, argv[2]);\r
904    TftpTransfer(ip0, argv[2], myStorage, STORAGE_SIZE-1, ConsoleTransferDone);\r
905 }\r
906 \r
907 \r
908 static void ConsoleMkfile(IPSocket *socket, char *argv[])\r
909 {\r
910    OS_FILE *file;\r
911    (void)argv;\r
912    file = fopen("myfile.txt", "w");\r
913    fwrite("Hello World!", 1, 12, file);\r
914    fclose(file);\r
915    IPPrintf(socket, "Created myfile.txt");\r
916 }\r
917 \r
918 \r
919 static void ConsoleUptime(IPSocket *socket, char *argv[])\r
920 {\r
921    int days, hours, minutes, seconds;\r
922    (void)argv;\r
923    //ticks per sec = 25E6/2^18 = 95.36743 -> 10.48576 ms/tick\r
924    seconds = OS_ThreadTime() / 95;\r
925    minutes = seconds / 60 % 60;\r
926    hours = seconds / 3600 % 24;\r
927    days = seconds / 3600 / 24;\r
928    seconds %= 60;\r
929    IPPrintf(socket, "%d days %2d:%2d:%2d\n", days, hours, minutes, seconds);\r
930 }\r
931 \r
932 \r
933 static void ConsoleDump(IPSocket *socket, char *argv[])\r
934 {\r
935    FILE *fileIn;\r
936    uint8 buf[16];\r
937    int bytes, i, j;\r
938 \r
939    fileIn = fopen(argv[1], "r");\r
940    if(fileIn == NULL)\r
941       return;\r
942    for(j = 0; j < 1024*1024*16; j += 16)\r
943    {\r
944       bytes = fread(buf, 1, 16, fileIn);\r
945       if(bytes == 0)\r
946          break;\r
947       IPPrintf(socket, "%8x ", j);\r
948       for(i = 0; i < bytes; ++i)\r
949          IPPrintf(socket, "%2x ", buf[i]);\r
950       for( ; i < 16; ++i)\r
951          IPPrintf(socket, "   ");\r
952       for(i = 0; i < bytes; ++i)\r
953       {\r
954          if(isprint(buf[i]))\r
955             IPPrintf(socket, "%c", buf[i]);\r
956          else\r
957             IPPrintf(socket, ".");\r
958       }\r
959       IPPrintf(socket, "\n");\r
960    }\r
961    fclose(fileIn);\r
962 }\r
963 \r
964 \r
965 static void ConsoleGrep(IPSocket *socket, char *argv[])\r
966 {\r
967    FILE *fileIn;\r
968    char buf[200];\r
969    int bytes;\r
970    char *ptr, *ptrEnd;\r
971 \r
972    if(argv[1][0] == 0 || argv[2][0] == 0)\r
973    {\r
974       IPPrintf(socket, "Usage: grep pattern file\n");\r
975       return;\r
976    }\r
977    fileIn = fopen(argv[2], "r");\r
978    if(fileIn == NULL)\r
979       return;\r
980    bytes = 0;\r
981    for(;;)\r
982    {\r
983       bytes += fread(buf + bytes, 1, sizeof(buf) - bytes - 1, fileIn);\r
984       if(bytes == 0)\r
985          break;\r
986       buf[bytes] = 0;\r
987       ptrEnd = strstr(buf, "\r");\r
988       if(ptrEnd == NULL)\r
989          ptrEnd = strstr(buf, "\n");\r
990       if(ptrEnd)\r
991       {\r
992          *ptrEnd = 0;\r
993          if(*++ptrEnd == '\n')\r
994             ++ptrEnd;\r
995       }\r
996       ptr = strstr(buf, argv[1]);\r
997       if(ptr)\r
998          IPPrintf(socket, "%s\n", buf);\r
999       if(ptrEnd)\r
1000       {\r
1001          bytes = strlen(ptrEnd);\r
1002          memcpy(buf, ptrEnd, bytes);\r
1003       }\r
1004       else\r
1005       {\r
1006          bytes = 0;\r
1007       }\r
1008    }\r
1009    fclose(fileIn);\r
1010 }\r
1011 \r
1012 \r
1013 #ifdef DLL_SETUP\r
1014 #include "dll.h"\r
1015 \r
1016 static void ConsoleRun(IPSocket *socket, char *argv[])\r
1017 {\r
1018    FILE *file;\r
1019    int bytes, i;\r
1020    uint8 code[128];\r
1021    DllFunc funcPtr;\r
1022    char *command, *ptr;\r
1023 \r
1024    if(strcmp(argv[0], "run") == 0)\r
1025       ++argv;\r
1026    file = fopen(argv[0], "r");\r
1027    if(file == NULL)\r
1028    {\r
1029       IPPrintf(socket, "Can't find %s", argv[0]);\r
1030       return;\r
1031    }\r
1032 \r
1033    bytes = fread(code, 1, sizeof(code), file);  //load first 128 bytes\r
1034    if(code[0] >= ' ')\r
1035    {\r
1036       socket->fileIn = file;       //script file\r
1037       fseek(file, 0, 0);\r
1038       return;\r
1039    }\r
1040 \r
1041    funcPtr = (DllFunc)code;\r
1042    ptr = funcPtr(NULL);            //determine load address\r
1043 \r
1044    memcpy(ptr, code, bytes);       //copy to correct address\r
1045    bytes += fread(ptr + bytes, 1, 1024*1024*8, file);\r
1046    fclose(file);\r
1047    printf("address=0x%x bytes=%d\n", (int)ptr, bytes);\r
1048    funcPtr = (DllFunc)ptr;\r
1049    funcPtr = (DllFunc)funcPtr(DllFuncList);  //initialize DLL, find Start()\r
1050 \r
1051    //Register new command\r
1052    command = argv[0];\r
1053    for(;;)\r
1054    {\r
1055       ptr = strstr(command, "/");\r
1056       if(ptr == NULL)\r
1057          break;\r
1058       command = ptr + 1;\r
1059    }\r
1060    for(i = 0; TelnetFuncList[i].name; ++i)\r
1061    {\r
1062       if(TelnetFuncList[i].name[0] == 0 ||\r
1063          strcmp(TelnetFuncList[i].name, command) == 0)\r
1064       {\r
1065          TelnetFuncList[i].name = (char*)malloc(40);\r
1066          strcpy(TelnetFuncList[i].name, command);\r
1067          TelnetFuncList[i].func = (ConsoleFunc)funcPtr;\r
1068          break;\r
1069       }\r
1070    }\r
1071 \r
1072    socket->userFunc = socket->funcPtr;\r
1073    funcPtr(socket, argv);\r
1074 }\r
1075 \r
1076 \r
1077 typedef struct NameValue_t {\r
1078    struct NameValue_t *next;\r
1079    void *value;\r
1080    char name[1];\r
1081 } NameValue_t;\r
1082 \r
1083 //Find the value associated with the name\r
1084 void *IPNameValue(const char *name, void *value)\r
1085 {\r
1086    static NameValue_t *head;\r
1087    NameValue_t *node;\r
1088    for(node = head; node; node = node->next)\r
1089    {\r
1090       if(strcmp(node->name, name) == 0)\r
1091          break;\r
1092    }\r
1093    if(node == NULL)\r
1094    {\r
1095       node = (NameValue_t*)malloc(sizeof(NameValue_t) + (int)strlen(name));\r
1096       if(node == NULL)\r
1097          return NULL;\r
1098       strcpy(node->name, name);\r
1099       node->value = value;\r
1100       node->next = head;\r
1101       head = node;\r
1102    }\r
1103    if(value)\r
1104       node->value = value;\r
1105    return node->value;\r
1106 }\r
1107 #endif\r
1108 \r
1109 \r
1110 #ifdef EDIT_FILE\r
1111 extern void EditFile(IPSocket *socket, char *argv[]);\r
1112 #endif\r
1113 \r
1114 static TelnetFunc_t MyFuncs[] = { \r
1115    {"cat", ConsoleCat},\r
1116    {"cp", ConsoleCp},\r
1117    {"dump", ConsoleDump},\r
1118    {"exit", ConsoleExit},\r
1119 #ifdef INCLUDE_FLASH\r
1120    {"flashErase", ConsoleFlashErase},\r
1121 #endif\r
1122    {"ftp", ConsoleFtp},\r
1123    {"grep", ConsoleGrep},\r
1124    {"help", ConsoleHelp},\r
1125    {"ls", ConsoleLs},\r
1126    {"math", ConsoleMath},\r
1127    {"mkdir", ConsoleMkdir},\r
1128    {"mkfile", ConsoleMkfile},\r
1129    {"ping", ConsolePing},\r
1130    {"rm", ConsoleRm},\r
1131    {"tftp", ConsoleTftp},\r
1132    {"uptime", ConsoleUptime},\r
1133 #ifdef DLL_SETUP\r
1134    {"run", ConsoleRun},\r
1135 #endif\r
1136 #ifdef EDIT_FILE\r
1137    {"edit", EditFile},\r
1138 #endif\r
1139    {"", NULL},\r
1140    {"", NULL},\r
1141    {"", NULL},\r
1142    {"", NULL},\r
1143    {"", NULL},\r
1144    {"", NULL},\r
1145    {"", NULL},\r
1146    {"", NULL},\r
1147    {"", NULL},\r
1148    {"", NULL},\r
1149    {"", NULL},\r
1150    {NULL, NULL}\r
1151 };\r
1152 \r
1153 \r
1154 void ConsoleInit(void)\r
1155 {\r
1156    FtpdInit(1);\r
1157    TftpdInit();\r
1158    TelnetInit(MyFuncs);\r
1159 }\r