📄 ftpd.c
字号:
/******************************************************************
* ftpd.c: File Transfer Protocol
*
* Copyright (c) 2001 Atmel Corporation.
* All Rights Reserved.
*
* You are autorized to use, copy and distribute this software only at
* a single site (the term "site" meaning a single company location).
* This copyright notice must be included in any copy, modification
* or portion of this software merged into another program.
*
* This software is licenced solely for use with Atmel AVR micro
* controller family. The software may not be modified to execute on
* any other microcontroller architectures
*
* This software is provided "as is"; Without warranties either express
* or implied, including any warranty regarding merchantability,
* fitness for a particular purpose or noninfringement.
*
* In no event shall Atmel or its suppliers be liable for any special,
* indirect,incidential or concequential damages resulting from the
* use or inability to use this software.
*
* Revision history:
*
* January 17, 2001: Version 1.0 Created by JB
* July 13, 2001 Version 1.2 JB
* - Changed to IAR compiler V2.25
* - Renamed flash file functions to avoid conflict with
* standard file I/O names
* - Bug fixes in HTTP
* - Speed optimization in TCP
*
*
*******************************************************************/
#include "comp_a90.h"
#include "tcp.h"
#include "ffile.h"
#include "ftpd.h"
#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <pgmspace.h>
extern unsigned int ticker;
FTPCONNECTION ftpconnection; //Only one ftp connection is allowed.
/*constant strings, plased in flash*/
flash char FTP_WELCOME_MSG[] ="220-Welcome to AVR Embedded web server.\r\n220 Please log in.\r\n";
flash char FTP_MAX_USERS[] ="421 Maximum users is 1.\r\n";
flash char FTP_PASS_REQUEST[] ="331 Password required for ";
flash char FTP_LOGGED_IN[] ="230 User Logged in.\r\n";
flash char FTP_INCORRECT_LOGIN[] ="530 Login incorrect.\r\n";
flash char FTP_GOODBYE[] ="221 Goodbye.\r\n";
flash char FTP_BIN[] ="200 Type set to I.\r\n";
flash char FTP_ASCII[] ="200 Type set to A.\r\n";
flash char FTP_ERROR[] ="500 command not understood.\r\n";
flash char FTP_PORT[] ="200 PORT command successful.\r\n";
flash char FTP_PASS[] ="257 \"/\" is current directory.\r\n";
flash char FTP_ACONN[] ="150 ASCII data connection.\r\n";
flash char FTP_BCONN[] ="150 Binary data connection.\r\n";
flash char FTP_ERR_DATA[] ="425 Unable to open data connection.\r\n";
flash char FTP_ERR_DIR[] ="500 Unable to read directory.\r\n";
flash char FTP_ERR_FILE[] ="500 Unable to open file.\r\n";
flash char FTP_DELE[] ="250 DELE command successful.\r\n";
flash char FTP_COMPLETE[] ="226 Transfer complete.\r\n";
void ftpd(void)
{
char inBuffer[FTP_BUFFERSIZE], outBuffer[FTP_BUFFERSIZE], tmp[14];
char *ptr;
unsigned int z,x,j;
char user[10];
char pass[10];
SOCKET *socket;
FTPCONNECTION *ftp;
refresh(); // Remove aborted connections.
if (!TCPlistenPort(21, 0)) // Check if ftp has started to listen to port 21.
{
TCPpopen(21, 0); // If not, initialize and start listening.
ftpconnection.state = ULOCKED;
ftpconnection.datastate = UNUSED;
ftpconnection.type =ASCII;
ftpconnection.hisPort = 0;
ftpconnection.hisIP0 = 0;
ftpconnection.hisIP1 = 0;
ftpconnection.dataPort = 0;
ftpconnection.dataIP0 = 0;
ftpconnection.dataIP1 = 0;
ftpconnection.file = NULL;
ftpconnection.dir = NULL;
ftpconnection.lastAction = ticker;
ftpconnection.username[0] = '\0';
ftpconnection.password[0] = '\0';
}
ftp = &ftpconnection;
socket = TCPfindSockets(21); // Get a linked list of sockets on port 21.
while (socket) // For every socket on port 21....
{
if ( !((socket->hisPort == ftpconnection.hisPort) && (socket->hisIP0 == ftpconnection.hisIP0) &&
(socket->hisIP1 == ftpconnection.hisIP1)) ) //Check if this connection is new.
{
if ( (ftpconnection.state == ULOCKED) && (socket->state == OPEN) ) // If this is a new connection, state is open
{ // and there is no already established connection.
ftp->state = USER;
ftp->hisIP0 = socket->hisIP0;
ftp->hisIP1 = socket->hisIP1;
ftp->hisPort = socket->hisPort;
ftp->dataPort = 0;
ftp->dataIP0 = 0;
ftp->dataIP1 = 0;
ftp->lastAction = ticker;
ftp->controlSocket = socket;
TCPsend_P(socket, sizeof(FTP_WELCOME_MSG), FTP_WELCOME_MSG); // Send a welcome message and wait for username.
}
else if (socket->state == OPEN)
{
TCPsend_P(socket, sizeof(FTP_MAX_USERS), FTP_MAX_USERS);
TCPclose(socket);
}
}
else if (socket->state == HALF_CLOSED)
{
TCPclose(socket);
}
else if (TCPsize(socket) && (ftpconnection.state != DATA) && (socket->state == OPEN) ) // If this is an established connection
{ // and there is new control data.
j=TCPreadln(socket, FTP_BUFFERSIZE, inBuffer, 1); // Read one line
if ( (inBuffer[j-1] == '\r') || (inBuffer[j-1] == '\n') ) // Check if EOL is present
{
ftp->lastAction = ticker;
TCPbufferFlush(socket); // remove from tcp buffer
inBuffer[j] = '\0'; // null terminate string.
ptr = strtok(inBuffer, " \r\n"); // get command
for (x=0;x<strlen(ptr);x++) // convert to upper case.
{
ptr[x] = toupper(ptr[x]);
}
switch(ftp->state)
{
case(USER):
if (!strcmp(ptr, "USER")) // If state is user and command is user.
{
ptr = strtok(NULL, " \r\n"); // save username and ask for password.
TCPsend_P(socket, sizeof(FTP_PASS_REQUEST), FTP_PASS_REQUEST);
TCPsend(socket, strlen(ptr), ptr);
TCPsend(socket, 3, ".\r\n");
strncpy(ftp->username, ptr, 8);
ftp->state = PASS;
}
break;
case(PASS):
if (!strcmp(ptr, "PASS")) //If command is password, check if password is correct.
{
ptr = strtok(NULL, " \r\n");
strncpy(ftp->password, ptr, 8);
if(!(getOption("FTP\0","Password\0",pass) && getOption("FTP\0","Username\0",user)))
{
/*error while reading from server.ini, use default values*/
strncpy(user,CONFIG_DEFAULT_FTP_USER,8);
strncpy(pass,CONFIG_DEFAULT_FTP_PASS,8);
}
if(strcmp(pass,ftp->password) || strcmp(user,ftp->username)) //check if password is correct
{
/*if password is incorrect refuse login*/
TCPsend_P(socket, sizeof(FTP_INCORRECT_LOGIN), FTP_INCORRECT_LOGIN);
TCPclose(socket);
closeFTP(ftp);
}
else
{
TCPsend_P(socket, sizeof(FTP_LOGGED_IN), FTP_LOGGED_IN);
ftp->state = IDLE;
}
}
break;
case(IDLE):
if (!strcmp(ptr, "QUIT")){ // Quit connection.
TCPsend_P(socket, sizeof(FTP_GOODBYE), FTP_GOODBYE);
TCPclose(socket);
closeFTP(ftp);
}
else if(!strcmp(ptr, "TYPE")) //Set transmission type.
{
ptr = strtok(NULL, " \r\n");
*ptr = toupper(*ptr);
if (*ptr == 'A')
{
ftp->type = ASCII;
TCPsend_P(socket, sizeof(FTP_ASCII), FTP_ASCII);
}
else if (*ptr == 'I')
{
ftp->type = BINARY;
TCPsend_P(socket, sizeof(FTP_BIN), FTP_BIN);
}
else
{
TCPsend_P(socket, sizeof(FTP_ERROR), FTP_ERROR);
TCPclose(socket);
closeFTP(ftp);
}
}
else if(!strcmp(ptr, "PORT")) // Get data connection IP address and port number.
{
ptr = strtok(NULL, ",");
if (ptr)
{
ftp->dataIP0 = (atoi(ptr) << 8);
ptr = strtok(NULL, ",");
if (ptr)
{
ftp->dataIP0 |= atoi(ptr);
ptr = strtok(NULL, ",");
if(ptr)
{
ftp->dataIP1 = (atoi(ptr) << 8);
ptr = strtok(NULL, ",");
if(ptr)
{
ftp->dataIP1 |= atoi(ptr);
ptr = strtok(NULL, ",");
if(ptr)
{
ftp->dataPort = (atoi(ptr) << 8);
ptr = strtok(NULL, " \r\n");
if(ptr)
{
ftp->dataPort |= atoi(ptr);
TCPsend_P(socket, sizeof(FTP_PORT), FTP_PORT);
}
}
}
}
}
}
if (!ptr) // Did not understand port command.
{
TCPsend_P(socket, sizeof(FTP_ERROR), FTP_ERROR);
TCPclose(socket);
closeFTP(ftp);
}
}
else if (!strcmp(ptr, "PWD")) //Show working directory.
{
TCPsend_P(socket, sizeof(FTP_PASS), FTP_PASS);
}
else if (!strcmp(ptr, "LIST") || !strcmp(ptr, "NLST")) //Show directory listing
{ //NLST = Short listing, LIST = long listing
if (ftp->type == ASCII)
{
TCPsend_P(socket, sizeof(FTP_ACONN), FTP_ACONN);
}
else
{
TCPsend_P(socket, sizeof(FTP_BCONN), FTP_BCONN);
}
ftp->dataSocket = TCPaopen(ftp->dataPort, ftp->dataIP0, ftp->dataIP1, 20); //Open data connection
if (!ftp->dataSocket)
{
TCPsend_P(socket, sizeof(FTP_ERR_DATA), FTP_ERR_DATA);
}
else
{
ftp->dir = opendir(); //Open directory.
if (ftp->dir)
{
ftp->state = DATA;
if(!strcmp(ptr, "NLST"))
{
ftp->datastate = DIRECTORY; //Send first line of short listing.
ptr = readdir(ftp->dir);
}
else
{
ftp->datastate = WDIRECTORY;
ptr = readwdir(ftp->dir); //Send first line of long listing.
}
if (ptr)
{
TCPsend(ftp->dataSocket, strlen(ptr), ptr);
}
else //If something don't work, close connection and directory.
{
TCPclose(ftp->dataSocket);
TCPsend_P(socket, sizeof(FTP_ERR_DIR), FTP_ERR_DIR);
ftp->state = IDLE;
ftp->datastate = UNUSED;
ftp->dataPort = 0;
ftp->dataIP0 = 0;
ftp->dataIP1 = 0;
closedir(ftp->dir);
}
}
else
{
TCPsend_P(socket, sizeof(FTP_ERR_DIR), FTP_ERR_DIR);
}
}
}
else if(!strcmp(ptr, "RETR")) //User asks for file.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -