/[H8]/trunk/docs/MCHPStack2.20/Source/ftp.c
ViewVC logotype

Annotation of /trunk/docs/MCHPStack2.20/Source/ftp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue May 1 08:17:39 2007 UTC (17 years, 1 month ago) by hedin
File MIME type: text/plain
File size: 15913 byte(s)
Removed tcpip stack 4.02 and added tcpip stack 2.20.
1 hedin 62 /*********************************************************************
2     *
3     * FTP ServerModule for Microchip TCP/IP Stack
4     *
5     *********************************************************************
6     * FileName: ftp.c
7     * Dependencies: StackTsk.h
8     * tcp.h
9     * Processor: PIC18
10     * Complier: MCC18 v1.00.50 or higher
11     * HITECH PICC-18 V8.10PL1 or higher
12     * Company: Microchip Technology, Inc.
13     *
14     * Software License Agreement
15     *
16     * The software supplied herewith by Microchip Technology Incorporated
17     * (the “Company”) for its PICmicro® Microcontroller is intended and
18     * supplied to you, the Company’s customer, for use solely and
19     * exclusively on Microchip PICmicro Microcontroller products. The
20     * software is owned by the Company and/or its supplier, and is
21     * protected under applicable copyright laws. All rights are reserved.
22     * Any use in violation of the foregoing restrictions may subject the
23     * user to criminal sanctions under applicable laws, as well as to
24     * civil liability for the breach of the terms and conditions of this
25     * license.
26     *
27     * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
28     * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
29     * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
30     * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
31     * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
32     * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
33     *
34     * HiTech PICC18 Compiler Options excluding device selection:
35     * -FAKELOCAL -G -Zg -E -C
36     *
37     *
38     * Author Date Comment
39     *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40     * Nilesh Rajbharti 4/23/01 Original (Rev 1.0)
41     * Nilesh Rajbharti 11/13/02 Fixed FTPServer()
42     ********************************************************************/
43     #define THIS_IS_FTP
44    
45     #include <string.h>
46     #include <stdlib.h>
47     #include "ftp.h"
48     #include "tcp.h"
49     #include "tick.h"
50    
51     #include "mpfs.h"
52    
53     #if !defined(STACK_USE_FTP_SERVER)
54     #error FTP SERVER module is not enabled.
55     #error If you do not want FTP module, remove this file from your
56     #error project to reduce your code size.
57     #error If you do want FTP module, make sure that STACK_USE_FTP_SERVER
58     #error is defined in StackTsk.h file.
59     #endif
60    
61    
62     #define FTP_COMMAND_PORT (21)
63     #define FTP_DATA_PORT (20)
64     #define FTP_TIMEOUT (TICK)((TICK)180 * TICK_SECOND)
65     #define MAX_FTP_ARGS (7)
66     #define MAX_FTP_CMD_STRING_LEN (31)
67    
68     typedef enum _SM_FTP
69     {
70     SM_FTP_NOT_CONNECTED,
71     SM_FTP_CONNECTED,
72     SM_FTP_USER_NAME,
73     SM_FTP_USER_PASS,
74     SM_FTP_RESPOND
75     } SM_FTP;
76    
77     typedef enum _SM_FTP_CMD
78     {
79     SM_FTP_CMD_IDLE,
80     SM_FTP_CMD_WAIT,
81     SM_FTP_CMD_RECEIVE,
82     SM_FTP_CMD_WAIT_FOR_DISCONNECT
83     } SM_FTP_CMD;
84    
85     typedef enum _FTP_COMMAND
86     {
87     FTP_CMD_USER,
88     FTP_CMD_PASS,
89     FTP_CMD_QUIT,
90     FTP_CMD_STOR,
91     FTP_CMD_PORT,
92     FTP_CMD_ABORT,
93     FTP_CMD_UNKNOWN,
94     FTP_CMD_NONE,
95     } FTP_COMMAND;
96    
97     /*
98     * Each entry in following table must match with that of FTP_COMMAND enum.
99     */
100     ROM char *FTPCommandString[] =
101     {
102     { "USER" }, // FTP_CMD_USER
103     { "PASS" }, // FTP_CMD_PASS
104     { "QUIT" }, // FTP_CMD_QUIT
105     { "STOR" }, // FTP_CMD_STOR
106     { "PORT" }, // FTP_CMD_PORT
107     { "ABOR" } // FTP_CMD_ABORT
108     };
109     #define FTP_COMMAND_TABLE_SIZE ( sizeof(FTPCommandString)/sizeof(FTPCommandString[0]) )
110    
111    
112     typedef enum _FTP_RESPONSE
113     {
114     FTP_RESP_BANNER,
115     FTP_RESP_USER_OK,
116     FTP_RESP_PASS_OK,
117     FTP_RESP_QUIT_OK,
118     FTP_RESP_STOR_OK,
119     FTP_RESP_UNKNOWN,
120     FTP_RESP_LOGIN,
121     FTP_RESP_DATA_OPEN,
122     FTP_RESP_DATA_READY,
123     FTP_RESP_DATA_CLOSE,
124     FTP_RESP_OK,
125    
126     FTP_RESP_NONE // This must always be the last
127     // There is no corresponding string.
128     } FTP_RESPONSE;
129    
130     /*
131     * Each entry in following table must match with FTP_RESPONE enum
132     */
133     ROM char *FTPResponseString[] =
134     {
135     "220 Ready\r\n", // FTP_RESP_BANNER
136     "331 Password required\r\n", // FTP_RESP_USER_OK
137     "230 Logged in\r\n", // FTP_RESP_PASS_OK
138     "221 Bye\r\n", // FTP_RESP_QUIT_OK
139     "500 \r\n", // FTP_RESP_STOR_OK
140     "502 Not implemented\r\n", // FTP_RESP_UNKNOWN
141     "530 Login required\r\n", // FTP_RESP_LOGIN
142     "150 Transferring data...\r\n", // FTP_RESP_DATA_OPEN
143     "125 Done.\r\n", // FTP_RESP_DATA_READY
144     "226 Transfer Complete\r\n", // FTP_RESP_DATA_CLOSE
145     "200 ok\r\n" // FTP_RESP_OK
146     };
147    
148    
149     static union
150     {
151     struct
152     {
153     unsigned int bUserSupplied : 1;
154     unsigned int bLoggedIn: 1;
155     } Bits;
156     BYTE Val;
157     } FTPFlags;
158    
159    
160     static TCP_SOCKET FTPSocket; // Main ftp command socket.
161     static TCP_SOCKET FTPDataSocket; // ftp data socket.
162     static WORD_VAL FTPDataPort; // ftp data port number as supplied by client
163    
164     static SM_FTP smFTP; // ftp server FSM state
165     static SM_FTP_CMD smFTPCommand; // ftp command FSM state
166    
167     static FTP_COMMAND FTPCommand;
168     static FTP_RESPONSE FTPResponse;
169    
170     static char FTPUser[FTP_USER_NAME_LEN];
171     static char FTPString[MAX_FTP_CMD_STRING_LEN+2];
172     static BYTE FTPStringLen;
173     static char *FTP_argv[MAX_FTP_ARGS]; // Parameters for a ftp command
174     static BYTE FTP_argc; // Total number of params for a ftp command
175     static TICK lastActivity; // Timeout keeper.
176    
177    
178     static MPFS FTPFileHandle;
179    
180     /*
181     * Private helper functions.
182     */
183     static void ParseFTPString(void);
184     static FTP_COMMAND ParseFTPCommand(char *cmd);
185     static void ParseFTPString(void);
186     static BOOL ExecuteFTPCommand(FTP_COMMAND cmd);
187     static BOOL PutFile(void);
188     static BOOL Quit(void);
189    
190     /*
191     * Uncomment following line if ftp transactions are to be displayed on
192     * RS-232 - for debug purpose only.
193     */
194     //#define FTP_SERVER_DEBUG_MODE
195     #define FTP_PUT_ENABLED
196    
197     #if defined(FTP_SERVER_DEBUG_MODE)
198     static USARTPut(BYTE c)
199     {
200     while( !TXSTA_TRMT);
201     TXREG = c;
202     }
203     #else
204    
205     #define USARTPut(a)
206    
207     #endif
208    
209    
210     /*********************************************************************
211     * Function: void FTPInit(void)
212     *
213     * PreCondition: TCP module is already initialized.
214     *
215     * Input: None
216     *
217     * Output: None
218     *
219     * Side Effects: None
220     *
221     * Overview: Initializes internal variables of FTP
222     *
223     * Note:
224     ********************************************************************/
225     void FTPInit(void)
226     {
227     FTPSocket = TCPListen(FTP_COMMAND_PORT);
228     smFTP = SM_FTP_NOT_CONNECTED;
229     FTPStringLen = 0;
230     FTPFlags.Val = 0;
231     FTPDataPort.Val = FTP_DATA_PORT;
232     }
233    
234    
235     /*********************************************************************
236     * Function: void FTPServer(void)
237     *
238     * PreCondition: FTPInit() must already be called.
239     *
240     * Input: None
241     *
242     * Output: Opened FTP connections are served.
243     *
244     * Side Effects: None
245     *
246     * Overview:
247     *
248     * Note: This function acts as a task (similar to one in
249     * RTOS). This function performs its task in
250     * co-operative manner. Main application must call
251     * this function repeatdly to ensure all open
252     * or new connections are served on time.
253     ********************************************************************/
254     BOOL FTPServer(void)
255     {
256     BYTE v;
257     TICK currentTick;
258    
259     if ( !TCPIsConnected(FTPSocket) )
260     {
261     FTPStringLen = 0;
262     FTPCommand = FTP_CMD_NONE;
263     smFTP = SM_FTP_NOT_CONNECTED;
264     FTPFlags.Val = 0;
265     smFTPCommand = SM_FTP_CMD_IDLE;
266     return TRUE;
267     }
268    
269     if ( TCPIsGetReady(FTPSocket) )
270     {
271     lastActivity = TickGet();
272    
273     while( TCPGet(FTPSocket, &v ) )
274     {
275     USARTPut(v);
276     FTPString[FTPStringLen++] = v;
277     if ( FTPStringLen == MAX_FTP_CMD_STRING_LEN )
278     FTPStringLen = 0;
279     }
280     TCPDiscard(FTPSocket);
281    
282    
283     if ( v == '\n' )
284     {
285     FTPString[FTPStringLen] = '\0';
286     FTPStringLen = 0;
287     ParseFTPString();
288     FTPCommand = ParseFTPCommand(FTP_argv[0]);
289     }
290     }
291     else if ( smFTP != SM_FTP_NOT_CONNECTED )
292     {
293     currentTick = TickGet();
294     currentTick = TickGetDiff(currentTick, lastActivity);
295     if ( currentTick >= FTP_TIMEOUT )
296     {
297     lastActivity = TickGet();
298     FTPCommand = FTP_CMD_QUIT;
299     smFTP = SM_FTP_CONNECTED;
300     }
301     }
302    
303     switch(smFTP)
304     {
305     case SM_FTP_NOT_CONNECTED:
306     FTPResponse = FTP_RESP_BANNER;
307     lastActivity = TickGet();
308     /* No break - Continue... */
309    
310     case SM_FTP_RESPOND:
311     SM_FTP_RESPOND_Label:
312     while( !TCPIsPutReady(FTPSocket) );
313     if ( TCPIsPutReady(FTPSocket) )
314     {
315     ROM char* pMsg;
316    
317     pMsg = FTPResponseString[FTPResponse];
318    
319     while( (v = *pMsg++) )
320     {
321     USARTPut(v);
322     TCPPut(FTPSocket, v);
323     }
324     TCPFlush(FTPSocket);
325     FTPResponse = FTP_RESP_NONE;
326     smFTP = SM_FTP_CONNECTED;
327     }
328     /* No break - this will speed up little bit */
329    
330     case SM_FTP_CONNECTED:
331     if ( FTPCommand != FTP_CMD_NONE )
332     {
333     if ( ExecuteFTPCommand(FTPCommand) )
334     {
335     if ( FTPResponse != FTP_RESP_NONE )
336     smFTP = SM_FTP_RESPOND;
337     else if ( FTPCommand == FTP_CMD_QUIT )
338     smFTP = SM_FTP_NOT_CONNECTED;
339    
340     FTPCommand = FTP_CMD_NONE;
341     smFTPCommand = SM_FTP_CMD_IDLE;
342     }
343     else if ( FTPResponse != FTP_RESP_NONE )
344     {
345     smFTP = SM_FTP_RESPOND;
346     goto SM_FTP_RESPOND_Label;
347     }
348     }
349     break;
350    
351    
352     }
353    
354     return TRUE;
355     }
356    
357     static BOOL ExecuteFTPCommand(FTP_COMMAND cmd)
358     {
359     switch(cmd)
360     {
361     case FTP_CMD_USER:
362     FTPFlags.Bits.bUserSupplied = TRUE;
363     FTPFlags.Bits.bLoggedIn = FALSE;
364     FTPResponse = FTP_RESP_USER_OK;
365     strncpy(FTPUser, FTP_argv[1], sizeof(FTPUser));
366     break;
367    
368     case FTP_CMD_PASS:
369     if ( !FTPFlags.Bits.bUserSupplied )
370     FTPResponse = FTP_RESP_LOGIN;
371     else
372     {
373     if ( FTPVerify(FTPUser, FTP_argv[1]) )
374     {
375     FTPFlags.Bits.bLoggedIn = TRUE;
376     FTPResponse = FTP_RESP_PASS_OK;
377     }
378     else
379     FTPResponse = FTP_RESP_LOGIN;
380     }
381     break;
382    
383     case FTP_CMD_QUIT:
384     return Quit();
385    
386     case FTP_CMD_PORT:
387     FTPDataPort.v[1] = (BYTE)atoi(FTP_argv[5]);
388     FTPDataPort.v[0] = (BYTE)atoi(FTP_argv[6]);
389     FTPResponse = FTP_RESP_OK;
390     break;
391    
392     case FTP_CMD_STOR:
393     return PutFile();
394    
395     case FTP_CMD_ABORT:
396     FTPResponse = FTP_RESP_OK;
397     if ( FTPDataSocket != INVALID_SOCKET )
398     TCPDisconnect(FTPDataSocket);
399     break;
400    
401     default:
402     FTPResponse = FTP_RESP_UNKNOWN;
403     break;
404     }
405     return TRUE;
406     }
407    
408     static BOOL Quit(void)
409     {
410     switch(smFTPCommand)
411     {
412     case SM_FTP_CMD_IDLE:
413     #if defined(FTP_PUT_ENABLED)
414     if ( smFTPCommand == SM_FTP_CMD_RECEIVE )
415     MPFSClose();
416     #endif
417    
418     if ( FTPDataSocket != INVALID_SOCKET )
419     {
420     #if defined(FTP_PUT_ENABLED)
421     MPFSClose();
422     #endif
423     TCPDisconnect(FTPDataSocket);
424     smFTPCommand = SM_FTP_CMD_WAIT;
425     }
426     else
427     goto Quit_Done;
428     break;
429    
430     case SM_FTP_CMD_WAIT:
431     if ( !TCPIsConnected(FTPDataSocket) )
432     {
433     Quit_Done:
434     FTPResponse = FTP_RESP_QUIT_OK;
435     smFTPCommand = SM_FTP_CMD_WAIT_FOR_DISCONNECT;
436     }
437     break;
438    
439     case SM_FTP_CMD_WAIT_FOR_DISCONNECT:
440     if ( TCPIsPutReady(FTPSocket) )
441     {
442     if ( TCPIsConnected(FTPSocket) )
443     TCPDisconnect(FTPSocket);
444     }
445     break;
446    
447     }
448     return FALSE;
449     }
450    
451    
452     static BOOL PutFile(void)
453     {
454     BYTE v;
455    
456    
457     switch(smFTPCommand)
458     {
459     case SM_FTP_CMD_IDLE:
460     if ( !FTPFlags.Bits.bLoggedIn )
461     {
462     FTPResponse = FTP_RESP_LOGIN;
463     return TRUE;
464     }
465     else
466     {
467     FTPResponse = FTP_RESP_DATA_OPEN;
468     FTPDataSocket = TCPConnect(&REMOTE_HOST(FTPSocket), FTPDataPort.Val);
469     smFTPCommand = SM_FTP_CMD_WAIT;
470     }
471     break;
472    
473     case SM_FTP_CMD_WAIT:
474     if ( TCPIsConnected(FTPDataSocket) )
475     {
476     #if defined(FTP_PUT_ENABLED)
477     if ( !MPFSIsInUse() )
478     #endif
479     {
480     #if defined(FTP_PUT_ENABLED)
481     FTPFileHandle = MPFSFormat();
482     #endif
483    
484     smFTPCommand = SM_FTP_CMD_RECEIVE;
485     }
486     }
487     break;
488    
489     case SM_FTP_CMD_RECEIVE:
490     if ( TCPIsGetReady(FTPDataSocket) )
491     {
492     /*
493     * Reload timeout timer.
494     */
495     lastActivity = TickGet();
496     MPFSPutBegin(FTPFileHandle);
497     while( TCPGet(FTPDataSocket, &v) )
498     {
499     USARTPut(v);
500    
501     #if defined(FTP_PUT_ENABLED)
502     MPFSPut(v);
503     #endif
504     }
505     FTPFileHandle = MPFSPutEnd();
506     TCPDiscard(FTPDataSocket);
507     }
508     else if ( !TCPIsConnected(FTPDataSocket) )
509     {
510     #if defined(FTP_PUT_ENABLED)
511     MPFSPutEnd();
512     MPFSClose();
513     #endif
514     TCPDisconnect(FTPDataSocket);
515     FTPDataSocket = INVALID_SOCKET;
516     FTPResponse = FTP_RESP_DATA_CLOSE;
517     return TRUE;
518     }
519     }
520     return FALSE;
521     }
522    
523    
524    
525     static FTP_COMMAND ParseFTPCommand(char *cmd)
526     {
527     FTP_COMMAND i;
528    
529     for ( i = 0; i < (FTP_COMMAND)FTP_COMMAND_TABLE_SIZE; i++ )
530     {
531     if ( !memcmppgm2ram((void*)cmd, (ROM void*)FTPCommandString[i], 4) )
532     return i;
533     }
534    
535     return FTP_CMD_UNKNOWN;
536     }
537    
538     static void ParseFTPString(void)
539     {
540     BYTE *p;
541     BYTE v;
542     enum { SM_FTP_PARSE_PARAM, SM_FTP_PARSE_SPACE } smParseFTP;
543    
544     smParseFTP = SM_FTP_PARSE_PARAM;
545     p = (BYTE*)&FTPString[0];
546    
547     /*
548     * Skip white blanks
549     */
550     while( *p == ' ' )
551     p++;
552    
553     FTP_argv[0] = (char*)p;
554     FTP_argc = 1;
555    
556     while( (v = *p) )
557     {
558     switch(smParseFTP)
559     {
560     case SM_FTP_PARSE_PARAM:
561     if ( v == ' ' || v == ',' )
562     {
563     *p = '\0';
564     smParseFTP = SM_FTP_PARSE_SPACE;
565     }
566     else if ( v == '\r' || v == '\n' )
567     *p = '\0';
568     break;
569    
570     case SM_FTP_PARSE_SPACE:
571     if ( v != ' ' )
572     {
573     FTP_argv[FTP_argc++] = (char*)p;
574     smParseFTP = SM_FTP_PARSE_PARAM;
575     }
576     break;
577     }
578     p++;
579     }
580     }
581    

  ViewVC Help
Powered by ViewVC 1.1.20