-- Fabio Giovagnini Aurion s.r.l. via degli orti 11, 40050 Funo di Argelato (BO)
www.aurion-tech.com account telefono VoIP skype (www.skype.com): aurion.giovagnini
/** * \addtogroup arnproto * @{ */ /** * \file * base communication protocol over TCP/IP. * \author Fabio Gioavgnini <[EMAIL PROTECTED]> * This class impelment a protocol having these commands:\n * 1) a read command from an asker to our system:\n * :RDxxxxxxxxyyyy -> xxxxxxxx is an Hex address in capital nibble\n * yyyy is an Hex number in capital nibble. * The answer is :\n * -) as header :DT;\n * -) the real application pay load;\n * Ex: :RD00FFACDF0004 means:\n * 2) target transmits a message of form:\n * :DTxxyyzzcc.....\n * \n * 3) a write command has the form:\n * :WRxxxxxxxxyyyyaabbcc....zz -> xxxxxxxx is an Hex address in capital nibble\n * yyyy is an Hex number in capital nibble, aabbcc....zz are Hex numbers\n * in capital nibbles so that the number expressed by yyyy is exactly\n * the number of byte expressed by aabbcc...zz we like to write at address\n * xxxxxxxx.\n * The protocol answer :OK!chks if chks is correct,otherwise :NOTchks.\n * Ex: :WR00FFACDF000401020305chks means:\n * write 0x01,0x02,0x03,0x04 starting at address 0x00FFACDF if chks is correct\n * \n * 4) a reset rxbuffer command has the form:\n * :## \n * The protocol answer :OK!chks if chks is correct,otherwise :NOTchks.\n * If everything is ok, the rxBuffer of the understanding interface is erased.\n *\n * 5) Get confogutarion command * :CF000000000000\n * The protocol answers: :DTxxyyzz...kkjj\n * where xxyyzz...kk is the array of bytes representing the\n * configuration parameters for use the real time tools in user mode. * \n * Note:\n * 1) If you send at most 3 char like 'r' waiting for an answer, you can\n * reset the rxBuffer engine, empting it.\n * 2) In this implementation we DON'T check the incoming massage checksum.\n */ /* * Copyright (c) 2004, Aurion s.r.l. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This file is part of the uIP TCP/IP stack. * * $Id: arnproto.h,v 1.1.2.1 2006/06/08 21:23:49 fabio Exp $ * */ #ifdef __cplusplus extern "C" { #endif #ifndef __ARNPROTO_H__ #define __ARNPROTO_H__ #include "arnArchTypes.h" #include "arnAppTypes.h" void arnproto_init(void); void arnproto_appcall(void); #endif /* __ARNPROTO_H__ */ #ifdef __cplusplus } #endif
/** * \addtogroup exampleapps * @{ */ /** * \defgroup ftp server * @{ * * The uIP ftp server is a very simplistic implementation of an FTP * server. It can serve only one file in binary mode ed only the commands * to download a file are implemented. */ /** * \file * FTP server. * \author Fabio Giovagnini <[EMAIL PROTECTED]> */ /* * Copyright (c) 2006, Aurion s.r.l. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This file is part of the uIP TCP/IP stack. * * $Id: arnproto.cpp,v 1.1.2.1 2006/06/08 21:21:01 fabio Exp $ * */ #include "arnUtilFunctions.h" #include "uip.h" #include "ftpd.h" #define DEBUG #ifdef DEBUG #include "arnDebug.h" #define PRINT(x) arnDEBUG("%s",x) /*printf("%s", x)*/ #define PRINTLN(x) arnDEBUG("%s\n",x) /*printf("%s\n", x)*/ #define PRINTNUM(x) arnDEBUG("%d",x) #define PRINTNUMLN(x) arnDEBUG("%d\n",x) #else /* DEBUG */ #define PRINT(x) #define PRINTLN(x) #define PRINTNUMLN(x) #define PRINTNUM(x) #endif /* NOT DEBUG */ #ifdef __cplusplus extern "C" { #endif static void _abort(void); static void _timeout(void); static void _close(void); static void _connect(void); static void _newdata(void); static void _ack(void); static void _poll(void); static void _senddata(void); static void _retrasmit(void); static void SplitCmdArg(arn_CHAR * line, arn_CHAR ** cmd, arn_CHAR ** args); static const arn_CHAR cmd_cwd_P[] = "CWD"; static const arn_CHAR cmd_dele_P[] = "DELE"; static const arn_CHAR cmd_list_P[] = "LIST"; static const arn_CHAR cmd_mkd_P[] = "MKD"; static const arn_CHAR cmd_xmkd_P[] = "XMKD"; static const arn_CHAR cmd_nlst_P[] = "NLST"; static const arn_CHAR cmd_noop_P[] = "NOOP"; static const arn_CHAR cmd_pass_P[] = "PASS"; static const arn_CHAR cmd_pasv_P[] = "PASV"; static const arn_CHAR cmd_port_P[] = "PORT"; static const arn_CHAR cmd_pwd_P[] = "PWD"; static const arn_CHAR cmd_xpwd_P[] = "XPWD"; static const arn_CHAR cmd_quit_P[] = "QUIT"; static const arn_CHAR cmd_retr_P[] = "RETR"; static const arn_CHAR cmd_rmd_P[] = "RMD"; static const arn_CHAR cmd_xrmd_P[] = "XRMD"; static const arn_CHAR cmd_size_P[] = "SIZE"; static const arn_CHAR cmd_stor_P[] = "STOR"; static const arn_CHAR cmd_syst_P[] = "SYST"; static const arn_CHAR cmd_type_P[] = "TYPE"; static const arn_CHAR cmd_user_P[] = "USER"; static const arn_CHAR rep_banner[] = "220 uIP/arnSys FTP server ready\r\n"; static const arn_CHAR okCode200[] = "200 OK\r\n"; static const arn_CHAR okCode221[] = "221 OK\r\n"; static const arn_CHAR okCode225[] = "225 OK\r\n"; static const arn_CHAR okCode226[] = "226 OK\r\n"; static const arn_CHAR okCode230[] = "230 OK\r\n"; static const arn_CHAR FailCode500[] = "500 sintax error; command unrecognized.\r\n"; static const arn_CHAR FailCode501[] = "501 sintax error; arg unrecognized.\r\n"; static const arn_CHAR FailCode502[] = "502 command not implemented.\r\n"; static const arn_CHAR FailCode504[] = "504 command not implemented for that parameter.\r\n"; static const arn_CHAR FailCode421[] = "421 servivece not available; closing connection.\r\n"; // this is the section defining the the allowed command #define FTPDREC_NONE 0 #define FTPDREC_CONNECT (1 + FTPDREC_NONE) #define FTPDREC_NOOP (1 + FTPDREC_CONNECT) #define FTPDREC_USER (1 + FTPDREC_NOOP) #define FTPDREC_PWD (1 + FTPDREC_USER) #define FTPDREC_CWD (1 + FTPDREC_PWD) #define FTPDREC_PASV (1 + FTPDREC_CWD) #define FTPDREC_LIST (1 + FTPDREC_PASV) #define FTPDREC_RETR (1 + FTPDREC_LIST) #define FTPDREC_SYST (1 + FTPDREC_RETR) #define FTPDREC_SIZE (1 + FTPDREC_SYST) #define FTPDREC_QUIT (1 + FTPDREC_SIZE) #define FTPDREC_TYPE (1 + FTPDREC_QUIT) #define FTPDREC_UNK (1 + FTPDREC_TYPE) //END this is the section defining the the allowed command // this is the section defining the answer to command #define FTPDANS_NONE 0 #define FTPDANS_BANNER (1 + FTPDANS_NONE) #define FTPDANS_OK200 (1 + FTPDANS_BANNER) // command ok #define FTPDANS_OK221 (1 + FTPDANS_OK200) // user name ok; no password #define FTPDANS_OK225 (1 + FTPDANS_OK221) // user name ok; no password #define FTPDANS_OK226 (1 + FTPDANS_OK225) // user name ok; no password #define FTPDANS_OK230 (1 + FTPDANS_OK226) // user name ok; no password #define FTPDANS_SYST (1 + FTPDANS_OK230) // risponde al comando che identifica il sistema target #define FTPDANS_PWD (1 + FTPDANS_SYST) // risponde al comando che chiede la stampa della working directory #define FTPDANS_TYPE (1 + FTPDANS_PWD) // risponde al comando TYPE per stabilire se ASCII oppure BINARY #define FTPDANS_PASV (1 + FTPDANS_TYPE) // risponde al comando PASV #define FTPDANS_LIST (1 + FTPDANS_PASV) // risponde al LIST NLST #define FTPDANS_FAIL502 (1 + FTPDANS_LIST) // risponde a comandi non conosciuti #define FTPDANS_SIZE (1 + FTPDANS_FAIL502) // risponde al SIZE #define FTPDANS_RETR (1 + FTPDANS_SIZE) // risponde al RETR #define FTPDANS_CWD (1 + FTPDANS_RETR) // risponde al CWD #define FTPDANS_FAIL500 (1 + FTPDANS_CWD) // errore sintattico #define FTPDANS_FAIL501 (1 + FTPDANS_FAIL500) // errore sintattico sui parametri #define FTPDANS_FAIL504 (1 + FTPDANS_FAIL501) // comando non implementati per quel parametro #define FTPDANS_FAIL421 (1 + FTPDANS_FAIL504) // servizio non disponibile; chiudo connesisone #define FTPDANS_NOOP (1 + FTPDANS_FAIL421) // no operation //END this is the section defining the answer to command // this is the section defining the internal status of the server #define FTPDSTS_NONE 0 #define FTPDSTS_WAITFORCMD (1 + FTPDSTS_NONE) #define FTPDSTS_PREP_FTPDATA (1 + FTPDSTS_WAITFORCMD) #define FTPDSTS_SENDING_FTPDATA (1 + FTPDSTS_PREP_FTPDATA) #define FTPDSTS_SENT_FTPDATA (1 + FTPDSTS_SENDING_FTPDATA) #define FTPDSTS_SENDING_CTLANS (1 + FTPDSTS_SENT_FTPDATA) #define FTPDSTS_SENT_CTLANS (1 + FTPDSTS_SENDING_CTLANS) #define FTPDSTS_SENDING_ENDDATACTLANS (1 + FTPDSTS_SENT_CTLANS) #define FTPDSTS_SENT_ENDDATACTLANS (1 + FTPDSTS_SENDING_ENDDATACTLANS) //#define FTPDSTS_CLOSING_DATACONN (1 + FTPDSTS_SENT_ENDDATACTLANS) //#define FTPDSTS_CLOSED_DATACONN (1 + FTPDSTS_CLOSING_DATACONN) //END this is the section defining the internal status of the server // this is the section defining the TYPE #define FTPDTYP_NONE 0 #define FTPDTYP_ASCII (1 + FTPDTYP_NONE) #define FTPDTYP_BINARY (1 + FTPDTYP_ASCII) //END this is the section defining the TYPE // this is the section defining the MODE #define FTPDMOD_NONE 0 #define FTPDMOD_STREAM (1 + FTPDMOD_NONE) //END this is the section defining the MODE // this is the section defining the STRUCTURE #define FTPDSTRU_NONE 0 #define FTPDSTRU_FILE (1 + FTPDSTRU_NONE) //END this is the section defining the STRUCTURE #define PACK_DATA_SIZE 512 static void _abort_data(void); static void _timeout_data(void); static void _close_data(void); static void _connect_data(void); static void _newdata_data(void); static void _ack_data(void); static void _poll_data(void); static void _senddata_data(void); static void _retrasmit_data(void); struct { arn_uCHAR Status; arn_uCHAR RecvCmd; arn_uCHAR AnsToCmd; arn_uCHAR ftpMode; arn_uCHAR ftpType; arn_uCHAR ftpStru; } exchgParams; // test test test arn_uLONG ftpd_size = 0x000000; arn_uLONG ftpd_sadd = 0x00420000; arn_CHAR* ftpd_name = "DDF.ddf"; //END #ifdef __cplusplus } #endif void ftpd_init(void) { /* Listen to port 21. */ uip_listen(HTONS(21)); } void ftpd_init_data(void) { /* Listen to port 20. */ uip_listen(HTONS(20)); } void ftpd_appcall_data(void) { if(uip_aborted()) { _abort_data(); } if(uip_timedout()) { _timeout_data(); } if(uip_closed()) { _close_data(); } if(uip_connected()) { _connect_data(); } if(uip_acked()) { _ack_data(); } if(uip_newdata()) { _newdata_data(); } if(uip_poll()) { _poll_data(); } if(uip_rexmit()) { _retrasmit_data(); } if(uip_rexmit() || uip_newdata() || uip_acked() || uip_connected() || uip_poll()) { _senddata_data(); } } void ftpd_appcall(void) { if(uip_aborted()) { _abort(); } if(uip_timedout()) { _timeout(); } if(uip_closed()) { _close(); } if(uip_connected()) { _connect(); } if(uip_acked()) { _ack(); } if(uip_newdata()) { _newdata(); } if(uip_poll()) { _poll(); } if(uip_rexmit()) { _retrasmit(); } if(uip_rexmit() || uip_newdata() || uip_acked() || uip_connected() || uip_poll()) { _senddata(); } } void _abort(void) { // struct arnftpd_state *ftps = (struct arnftpd_state *)(uip_conn->appstate); PRINT("Abort_Handler:\n"); uip_abort(); } void _timeout(void) { // struct arnftpd_state *ftps = (struct arnftpd_state *)(uip_conn->appstate); PRINT("Timeout_Handler:\n"); uip_close(); } void _close(void) { // struct arnftpd_state *ftps = (struct arnftpd_state *)(uip_conn->appstate); PRINT("Close_Handler:\n"); // exchgParams.Status = FTPDSTS_CLOSING_DATACONN; } void _connect(void) { struct ftpd_state *ftps = (struct ftpd_state *)(uip_conn->appstate); ftps->RecvCmd = FTPDREC_CONNECT; ftps->count = strlen(rep_banner); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(rep_banner),uip_len); ftps->AnsToCmd = FTPDANS_BANNER; ftps->dataptr = 0; ftps->count = 0; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_WAITFORCMD; exchgParams.Status = FTPDSTS_NONE; exchgParams.ftpMode = FTPDMOD_STREAM; exchgParams.ftpType = FTPDTYP_ASCII; exchgParams.ftpStru = FTPDSTRU_FILE; //PRINT("Connect_Handler:\n"); } void _newdata(void) { struct ftpd_state *ftps = (struct ftpd_state *)(uip_conn->appstate); arn_CHAR* cmd; arn_CHAR* arg; //PRINT("Newdata_Handler:\n"); if (ftps->Status != FTPDSTS_WAITFORCMD) return; SplitCmdArg((arn_CHAR*)uip_appdata,&cmd,&arg); PRINTLN(cmd); PRINTLN(arg); if (!strcmp(cmd,cmd_user_P)) { ftps->RecvCmd = FTPDREC_USER; ftps->count = strlen(okCode230); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(okCode230),uip_len); ftps->AnsToCmd = FTPDANS_OK230; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_syst_P)) { arn_CHAR *msg = "215 UNIX Type: L8\r\n"; ftps->RecvCmd = FTPDREC_SYST; ftps->count = strlen(msg); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(msg),uip_len); ftps->AnsToCmd = FTPDANS_SYST; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_pwd_P) || (!strcmp(cmd,cmd_xpwd_P))) { arn_CHAR *msg = "257 \"/\"\r\n"; ftps->RecvCmd = FTPDREC_PWD; ftps->count = strlen(msg); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(msg),uip_len); ftps->AnsToCmd = FTPDANS_PWD; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_type_P)) { ftps->RecvCmd = FTPDREC_TYPE; if (!strcmp(arg,"A")) exchgParams.ftpType = FTPDTYP_ASCII; else exchgParams.ftpType = FTPDTYP_BINARY; ftps->count = strlen(okCode200); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(okCode200),uip_len); ftps->AnsToCmd = FTPDANS_OK200; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_WAITFORCMD; } else if (!strcmp(cmd,cmd_quit_P)) { ftps->RecvCmd = FTPDREC_QUIT; ftps->count = strlen(okCode221); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(okCode221),uip_len); ftps->AnsToCmd = FTPDANS_OK221; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_pasv_P)) { arn_uSHORT hadd[2]; ftps->RecvCmd = FTPDREC_PASV; uip_gethostaddr(hadd); sprintf((arn_CHAR*)uip_appdata,"227 Passive (%u,%u,%u,%u,%u,%u).\r\n", (arn_uCHAR) (hadd[0] >> 8), (arn_uCHAR) (hadd[0] & 0x00ff), (arn_uCHAR) (hadd[1] >> 8), (arn_uCHAR) (hadd[1] & 0x00ff), 0, 20); // port ftps->count = strlen((arn_CHAR*)uip_appdata); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); ftps->AnsToCmd = FTPDANS_PASV; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_size_P)) { ftps->RecvCmd = FTPDREC_SIZE; arn_CHAR tmpBff[32];tmpBff[0] = '/'; strcpy(tmpBff + 1,ftpd_name); if (!strcmp(arg,tmpBff) || !strcmp(arg,ftpd_name)) { sprintf((arn_CHAR*)uip_appdata,"213 %6lu\r\n", (arn_uLONG) ftpd_size); ftps->count = strlen((arn_CHAR*)uip_appdata); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); ftps->AnsToCmd = FTPDANS_SIZE; } else { ftps->count = strlen(FailCode502); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(FailCode502),uip_len); ftps->AnsToCmd = FTPDANS_FAIL502; } ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_list_P) || !strcmp(cmd,cmd_nlst_P)) { arn_CHAR* msg = "150 opening data connection list answer.\r\n"; ftps->RecvCmd = FTPDREC_LIST; ftps->count = strlen(msg); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(msg),uip_len); ftps->AnsToCmd = FTPDANS_LIST; ftps->IsCmdWD = arnTRUE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_retr_P)) { if (!strcmp(arg,"/")) { ftps->count = strlen(FailCode504); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(FailCode504),uip_len); ftps->AnsToCmd = FTPDANS_FAIL504; ftps->IsCmdWD = arnFALSE; } else { arn_CHAR* msg = "150 opening data connection for retr answer.\r\n"; ftps->RecvCmd = FTPDREC_RETR; ftps->count = strlen(msg); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(msg),uip_len); ftps->AnsToCmd = FTPDANS_RETR; ftps->IsCmdWD = arnTRUE; } ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_cwd_P)) { ftps->RecvCmd = FTPDREC_CWD; if (!strcmp(arg,"/")) { arn_CHAR* msg = "200 directory changed to /.\r\n"; ftps->count = strlen(msg); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(msg),uip_len); ftps->AnsToCmd = FTPDANS_CWD; } else { ftps->count = strlen(FailCode504); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(FailCode504),uip_len); ftps->AnsToCmd = FTPDANS_FAIL504; } ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else if (!strcmp(cmd,cmd_noop_P)) { ftps->RecvCmd = FTPDREC_NOOP; ftps->count = strlen(okCode200); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(okCode200),uip_len); ftps->AnsToCmd = FTPDANS_NOOP; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } else { ftps->RecvCmd = FTPDREC_UNK; ftps->count = strlen(FailCode502); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(FailCode502),uip_len); ftps->AnsToCmd = FTPDANS_FAIL502; ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_SENDING_CTLANS; } } void _poll(void) { struct ftpd_state *ftps = (struct ftpd_state *)(uip_conn->appstate); if (ftps->IsCmdWD ) { if (exchgParams.Status == FTPDSTS_SENT_FTPDATA) { ftps->Status = exchgParams.Status; switch (ftps->AnsToCmd) { case FTPDANS_LIST: case FTPDANS_RETR: ftps->AnsToCmd = FTPDANS_OK226; ftps->count = strlen(okCode226); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(okCode226),uip_len); ftps->IsCmdWD = arnFALSE; exchgParams.Status = FTPDSTS_NONE; ftps->Status = FTPDSTS_SENDING_ENDDATACTLANS; break; default: break; } } } } // test testt test arn_uCHAR TSTrtx; //END void _retrasmit(void) { TSTrtx++; } void _ack(void) { struct ftpd_state *ftps = (struct ftpd_state *)(uip_conn->appstate); switch (ftps->Status) { case FTPDSTS_SENDING_CTLANS: switch (ftps->AnsToCmd) { case FTPDANS_BANNER: case FTPDANS_OK200: case FTPDANS_OK221: case FTPDANS_OK230: case FTPDANS_SYST: case FTPDANS_PWD: case FTPDANS_PASV: case FTPDANS_FAIL502: case FTPDANS_FAIL504: case FTPDANS_SIZE: case FTPDANS_CWD: case FTPDANS_NOOP: ftps->Status = FTPDSTS_WAITFORCMD; ftps->RecvCmd = FTPDREC_NONE; ftps->AnsToCmd = FTPDANS_NONE; uip_len = 0; break; case FTPDANS_LIST: case FTPDANS_RETR: ftps->Status = FTPDSTS_PREP_FTPDATA; uip_len = 0; exchgParams.Status = ftps->Status; exchgParams.RecvCmd = ftps->RecvCmd; exchgParams.AnsToCmd = ftps->AnsToCmd; break; default : break; } break; case FTPDSTS_SENDING_ENDDATACTLANS: switch (ftps->AnsToCmd) { case FTPDANS_OK226: ftps->IsCmdWD = arnFALSE; ftps->Status = FTPDSTS_WAITFORCMD; ftps->RecvCmd = FTPDREC_NONE; ftps->AnsToCmd = FTPDANS_NONE; break; default : break; } break; default : break; } /* SplitCmdArg((arn_CHAR*)uip_appdata,&cmd,&arg); PRINTLN(cmd); PRINTLN(arg); if (!strcmp(cmd,cmd_user_P)) { ftps->Command = FTPDC_SENDOK200; ftps->count = strlen(okCode200); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); strncpy((arn_CHAR*) (uip_appdata),(arn_CHAR*)(okCode200),uip_len); }*/ } void _senddata(void) { // struct arnftpd_state *ftps = (struct arnftpd_state *)(uip_conn->appstate); if (uip_len > 0) { uip_send(uip_appdata,uip_len); //PRINT("Senddata_Handler:\n"); } } void SplitCmdArg(arn_CHAR * line, arn_CHAR ** cmd, arn_CHAR ** args) { /* Skip leading spaces. */ while (*line && *line <= ' ') { line++; } /* The first word is the command. Convert it to upper case. */ *cmd = line; while (*line > ' ') { if (*line >= (arn_uCHAR) 'a' && *line <= (arn_uCHAR) 'z') { *line -= (arn_uCHAR) 'a' - 'A'; } line++; } /* Mark end of the command word. */ if (*line) { *line++ = '\0'; } /* Skip spaces. */ while (*line && *line <= ' ') { ++line; } /* Arguments start here. */ *args = line; while (*line && *line != '\r' && *line != '\n') { line++; } /* Mark end of arguments. */ *line = 0; } void _abort_data(void) { } void _timeout_data(void) { uip_close(); } void _close_data(void) { } void _connect_data(void) { struct ftpd_state *ftps = (struct ftpd_state *)(uip_conn->appstate); ftps->Status = FTPDSTS_NONE; ftps->RecvCmd = FTPDREC_NONE; ftps->dataptr = 0; ftps->count = 0; } // test testt test arn_uCHAR TSTrtx_data; //END void _retrasmit_data(void) { TSTrtx_data++; struct ftpd_state *ftps = (struct ftpd_state *)(uip_conn->appstate); switch (ftps->Status) { case FTPDSTS_SENDING_FTPDATA: switch (ftps->RecvCmd) { case FTPDREC_LIST: sprintf((arn_CHAR*)uip_appdata,"-rw-r--r-- 1 0 0 %6lu Jan 1 2007 %s\r\n",ftpd_size,ftpd_name); ftps->count = strlen((arn_CHAR*)uip_appdata); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); break; case FTPDREC_RETR: ftps->count += PACK_DATA_SIZE; ftps->dataptr -= PACK_DATA_SIZE; //uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); uip_len = ((ftps->count > PACK_DATA_SIZE) ? PACK_DATA_SIZE : ftps->count); memcpy((void*)uip_appdata,(void*)ftps->dataptr,uip_len); if (ftps->count > PACK_DATA_SIZE) ftps->count-= PACK_DATA_SIZE; else ftps->count = 0; ftps->dataptr+= PACK_DATA_SIZE; break; default: break; } break; default : break; } } void _newdata_data(void) { } void _ack_data(void) { struct ftpd_state *ftps = (struct ftpd_state *)(uip_conn->appstate); switch (ftps->Status) { case FTPDSTS_SENDING_FTPDATA: switch (ftps->RecvCmd) { case FTPDREC_LIST: uip_close(); ftps->Status = FTPDSTS_SENT_FTPDATA; exchgParams.Status = ftps->Status; break; case FTPDREC_RETR: if (!ftps->count) { uip_close(); ftps->Status = FTPDSTS_SENT_FTPDATA; exchgParams.Status = ftps->Status; } else { //uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); uip_len = ((ftps->count > PACK_DATA_SIZE) ? PACK_DATA_SIZE : ftps->count); memcpy((void*)uip_appdata,(void*)ftps->dataptr,uip_len); if (ftps->count > PACK_DATA_SIZE) ftps->count-= PACK_DATA_SIZE; else ftps->count = 0; ftps->dataptr += PACK_DATA_SIZE; } break; default: break; } break; default: break; } } void _poll_data(void) { struct ftpd_state *ftps = (struct ftpd_state *)(uip_conn->appstate); if (ftps->Status == FTPDSTS_NONE) { if (exchgParams.Status == FTPDSTS_PREP_FTPDATA) { ftps->Status = exchgParams.Status; ftps->RecvCmd = exchgParams.RecvCmd; } } /* if (exchgParams.Status == FTPDSTS_CLOSING_DATACONN) { exchgParams.Status = FTPDSTS_CLOSED_DATACONN; uip_close(); }*/ switch (ftps->Status) { case FTPDSTS_PREP_FTPDATA: switch (ftps->RecvCmd) { case FTPDREC_LIST: sprintf((arn_CHAR*)uip_appdata,"-rw-r--r-- 1 0 0 %6lu Jan 1 2007 %s\r\n",ftpd_size,ftpd_name); ftps->count = strlen((arn_CHAR*)uip_appdata); uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); ftps->Status = FTPDSTS_SENDING_FTPDATA; break; case FTPDREC_RETR: ftps->dataptr = (arn_CHAR*)ftpd_sadd; ftps->count = ftpd_size; //uip_len = ((ftps->count > uip_mss()) ? uip_mss() : ftps->count); uip_len = ((ftps->count > PACK_DATA_SIZE) ? PACK_DATA_SIZE : ftps->count); memcpy((void*)uip_appdata,(void*)ftps->dataptr,uip_len); if (ftps->count > PACK_DATA_SIZE) ftps->count-= PACK_DATA_SIZE; else ftps->count = 0; ftps->dataptr += PACK_DATA_SIZE; ftps->Status = FTPDSTS_SENDING_FTPDATA; break; default: break; } break; default : break; } } void _senddata_data(void) { // struct arnftpd_state *ftps = (struct arnftpd_state *)(uip_conn->appstate); if (uip_len > 0) { uip_send(uip_appdata,uip_len); //PRINT("Senddata_Handler:\n"); } }