Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file ftp_server.c
Sergunb 0:8918a71cdbe9 3 * @brief FTP server (File Transfer Protocol)
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @section Description
Sergunb 0:8918a71cdbe9 26 *
Sergunb 0:8918a71cdbe9 27 * File Transfer Protocol (FTP) is a standard network protocol used to
Sergunb 0:8918a71cdbe9 28 * transfer files from one host to another host over a TCP-based network.
Sergunb 0:8918a71cdbe9 29 * Refer to the following RFCs for complete details:
Sergunb 0:8918a71cdbe9 30 * - RFC 959: File Transfer Protocol (FTP)
Sergunb 0:8918a71cdbe9 31 * - RFC 3659: Extensions to FTP
Sergunb 0:8918a71cdbe9 32 * - RFC 2428: FTP Extensions for IPv6 and NATs
Sergunb 0:8918a71cdbe9 33 *
Sergunb 0:8918a71cdbe9 34 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 35 * @version 1.7.6
Sergunb 0:8918a71cdbe9 36 **/
Sergunb 0:8918a71cdbe9 37
Sergunb 0:8918a71cdbe9 38 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 39 #define TRACE_LEVEL FTP_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 40
Sergunb 0:8918a71cdbe9 41 //Dependencies
Sergunb 0:8918a71cdbe9 42 #include "ftp/ftp_server.h"
Sergunb 0:8918a71cdbe9 43 #include "ftp/ftp_server_events.h"
Sergunb 0:8918a71cdbe9 44 #include "ftp/ftp_server_commands.h"
Sergunb 0:8918a71cdbe9 45 #include "ftp/ftp_server_misc.h"
Sergunb 0:8918a71cdbe9 46 #include "str.h"
Sergunb 0:8918a71cdbe9 47 #include "path.h"
Sergunb 0:8918a71cdbe9 48 #include "error.h"
Sergunb 0:8918a71cdbe9 49 #include "debug.h"
Sergunb 0:8918a71cdbe9 50
Sergunb 0:8918a71cdbe9 51 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 52 #if (FTP_SERVER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 53
Sergunb 0:8918a71cdbe9 54
Sergunb 0:8918a71cdbe9 55 /**
Sergunb 0:8918a71cdbe9 56 * @brief Initialize settings with default values
Sergunb 0:8918a71cdbe9 57 * @param[out] settings Structure that contains FTP server settings
Sergunb 0:8918a71cdbe9 58 **/
Sergunb 0:8918a71cdbe9 59
Sergunb 0:8918a71cdbe9 60 void ftpServerGetDefaultSettings(FtpServerSettings *settings)
Sergunb 0:8918a71cdbe9 61 {
Sergunb 0:8918a71cdbe9 62 //The FTP server is not bound to any interface
Sergunb 0:8918a71cdbe9 63 settings->interface = NULL;
Sergunb 0:8918a71cdbe9 64
Sergunb 0:8918a71cdbe9 65 //FTP command port number
Sergunb 0:8918a71cdbe9 66 settings->port = FTP_PORT;
Sergunb 0:8918a71cdbe9 67 //FTP data port number
Sergunb 0:8918a71cdbe9 68 settings->dataPort = FTP_DATA_PORT;
Sergunb 0:8918a71cdbe9 69 //Passive port range
Sergunb 0:8918a71cdbe9 70 settings->passivePortMin = FTP_SERVER_PASSIVE_PORT_MIN;
Sergunb 0:8918a71cdbe9 71 settings->passivePortMax = FTP_SERVER_PASSIVE_PORT_MAX;
Sergunb 0:8918a71cdbe9 72 //Set root directory
Sergunb 0:8918a71cdbe9 73 strcpy(settings->rootDir, "/");
Sergunb 0:8918a71cdbe9 74 //User verification callback function
Sergunb 0:8918a71cdbe9 75 settings->checkUserCallback = NULL;
Sergunb 0:8918a71cdbe9 76 //Password verification callback function
Sergunb 0:8918a71cdbe9 77 settings->checkPasswordCallback = NULL;
Sergunb 0:8918a71cdbe9 78 //Callback used to retrieve file permissions
Sergunb 0:8918a71cdbe9 79 settings->getFilePermCallback = NULL;
Sergunb 0:8918a71cdbe9 80 //Unknown command callback function
Sergunb 0:8918a71cdbe9 81 settings->unknownCommandCallback = NULL;
Sergunb 0:8918a71cdbe9 82 }
Sergunb 0:8918a71cdbe9 83
Sergunb 0:8918a71cdbe9 84
Sergunb 0:8918a71cdbe9 85 /**
Sergunb 0:8918a71cdbe9 86 * @brief FTP server initialization
Sergunb 0:8918a71cdbe9 87 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 88 * @param[in] settings FTP server specific settings
Sergunb 0:8918a71cdbe9 89 * @return Error code
Sergunb 0:8918a71cdbe9 90 **/
Sergunb 0:8918a71cdbe9 91
Sergunb 0:8918a71cdbe9 92 error_t ftpServerInit(FtpServerContext *context, const FtpServerSettings *settings)
Sergunb 0:8918a71cdbe9 93 {
Sergunb 0:8918a71cdbe9 94 error_t error;
Sergunb 0:8918a71cdbe9 95
Sergunb 0:8918a71cdbe9 96 //Debug message
Sergunb 0:8918a71cdbe9 97 TRACE_INFO("Initializing FTP server...\r\n");
Sergunb 0:8918a71cdbe9 98
Sergunb 0:8918a71cdbe9 99 //Ensure the parameters are valid
Sergunb 0:8918a71cdbe9 100 if(context == NULL || settings == NULL)
Sergunb 0:8918a71cdbe9 101 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 102
Sergunb 0:8918a71cdbe9 103 //Check passive port range
Sergunb 0:8918a71cdbe9 104 if(settings->passivePortMax <= settings->passivePortMin)
Sergunb 0:8918a71cdbe9 105 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 106
Sergunb 0:8918a71cdbe9 107 //Clear the FTP server context
Sergunb 0:8918a71cdbe9 108 memset(context, 0, sizeof(FtpServerContext));
Sergunb 0:8918a71cdbe9 109
Sergunb 0:8918a71cdbe9 110 //Save user settings
Sergunb 0:8918a71cdbe9 111 context->settings = *settings;
Sergunb 0:8918a71cdbe9 112
Sergunb 0:8918a71cdbe9 113 //Clean the root directory path
Sergunb 0:8918a71cdbe9 114 pathCanonicalize(context->settings.rootDir);
Sergunb 0:8918a71cdbe9 115 pathRemoveSlash(context->settings.rootDir);
Sergunb 0:8918a71cdbe9 116
Sergunb 0:8918a71cdbe9 117 //Create an event object to poll the state of sockets
Sergunb 0:8918a71cdbe9 118 if(!osCreateEvent(&context->event))
Sergunb 0:8918a71cdbe9 119 {
Sergunb 0:8918a71cdbe9 120 //Failed to create event
Sergunb 0:8918a71cdbe9 121 return ERROR_OUT_OF_RESOURCES;
Sergunb 0:8918a71cdbe9 122 }
Sergunb 0:8918a71cdbe9 123
Sergunb 0:8918a71cdbe9 124 //Start of exception handling block
Sergunb 0:8918a71cdbe9 125 do
Sergunb 0:8918a71cdbe9 126 {
Sergunb 0:8918a71cdbe9 127 //Open a TCP socket
Sergunb 0:8918a71cdbe9 128 context->socket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP);
Sergunb 0:8918a71cdbe9 129 //Failed to open socket?
Sergunb 0:8918a71cdbe9 130 if(!context->socket)
Sergunb 0:8918a71cdbe9 131 {
Sergunb 0:8918a71cdbe9 132 //Report an error
Sergunb 0:8918a71cdbe9 133 error = ERROR_OPEN_FAILED;
Sergunb 0:8918a71cdbe9 134 //Exit immediately
Sergunb 0:8918a71cdbe9 135 break;
Sergunb 0:8918a71cdbe9 136 }
Sergunb 0:8918a71cdbe9 137
Sergunb 0:8918a71cdbe9 138 //Set timeout for blocking functions
Sergunb 0:8918a71cdbe9 139 error = socketSetTimeout(context->socket, INFINITE_DELAY);
Sergunb 0:8918a71cdbe9 140 //Any error to report?
Sergunb 0:8918a71cdbe9 141 if(error)
Sergunb 0:8918a71cdbe9 142 break;
Sergunb 0:8918a71cdbe9 143
Sergunb 0:8918a71cdbe9 144 //Change the size of the TX buffer
Sergunb 0:8918a71cdbe9 145 error = socketSetTxBufferSize(context->socket,
Sergunb 0:8918a71cdbe9 146 FTP_SERVER_CTRL_SOCKET_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 147 //Any error to report?
Sergunb 0:8918a71cdbe9 148 if(error)
Sergunb 0:8918a71cdbe9 149 break;
Sergunb 0:8918a71cdbe9 150
Sergunb 0:8918a71cdbe9 151 //Change the size of the RX buffer
Sergunb 0:8918a71cdbe9 152 error = socketSetRxBufferSize(context->socket,
Sergunb 0:8918a71cdbe9 153 FTP_SERVER_CTRL_SOCKET_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 154 //Any error to report?
Sergunb 0:8918a71cdbe9 155 if(error)
Sergunb 0:8918a71cdbe9 156 break;
Sergunb 0:8918a71cdbe9 157
Sergunb 0:8918a71cdbe9 158 //Associate the socket with the relevant interface
Sergunb 0:8918a71cdbe9 159 error = socketBindToInterface(context->socket, settings->interface);
Sergunb 0:8918a71cdbe9 160 //Unable to bind the socket to the desired interface?
Sergunb 0:8918a71cdbe9 161 if(error)
Sergunb 0:8918a71cdbe9 162 break;
Sergunb 0:8918a71cdbe9 163
Sergunb 0:8918a71cdbe9 164 //Bind newly created socket to port 21
Sergunb 0:8918a71cdbe9 165 error = socketBind(context->socket, &IP_ADDR_ANY, settings->port);
Sergunb 0:8918a71cdbe9 166 //Failed to bind socket to port 21?
Sergunb 0:8918a71cdbe9 167 if(error)
Sergunb 0:8918a71cdbe9 168 break;
Sergunb 0:8918a71cdbe9 169
Sergunb 0:8918a71cdbe9 170 //Place socket in listening state
Sergunb 0:8918a71cdbe9 171 error = socketListen(context->socket, FTP_SERVER_BACKLOG);
Sergunb 0:8918a71cdbe9 172 //Any failure to report?
Sergunb 0:8918a71cdbe9 173 if(error)
Sergunb 0:8918a71cdbe9 174 break;
Sergunb 0:8918a71cdbe9 175
Sergunb 0:8918a71cdbe9 176 //End of exception handling block
Sergunb 0:8918a71cdbe9 177 } while(0);
Sergunb 0:8918a71cdbe9 178
Sergunb 0:8918a71cdbe9 179 //Did we encounter an error?
Sergunb 0:8918a71cdbe9 180 if(error)
Sergunb 0:8918a71cdbe9 181 {
Sergunb 0:8918a71cdbe9 182 //Free previously allocated resources
Sergunb 0:8918a71cdbe9 183 osDeleteEvent(&context->event);
Sergunb 0:8918a71cdbe9 184 //Close socket
Sergunb 0:8918a71cdbe9 185 socketClose(context->socket);
Sergunb 0:8918a71cdbe9 186 }
Sergunb 0:8918a71cdbe9 187
Sergunb 0:8918a71cdbe9 188 //Return status code
Sergunb 0:8918a71cdbe9 189 return error;
Sergunb 0:8918a71cdbe9 190 }
Sergunb 0:8918a71cdbe9 191
Sergunb 0:8918a71cdbe9 192
Sergunb 0:8918a71cdbe9 193 /**
Sergunb 0:8918a71cdbe9 194 * @brief Start FTP server
Sergunb 0:8918a71cdbe9 195 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 196 * @return Error code
Sergunb 0:8918a71cdbe9 197 **/
Sergunb 0:8918a71cdbe9 198
Sergunb 0:8918a71cdbe9 199 error_t ftpServerStart(FtpServerContext *context)
Sergunb 0:8918a71cdbe9 200 {
Sergunb 0:8918a71cdbe9 201 OsTask *task;
Sergunb 0:8918a71cdbe9 202
Sergunb 0:8918a71cdbe9 203 //Debug message
Sergunb 0:8918a71cdbe9 204 TRACE_INFO("Starting FTP server...\r\n");
Sergunb 0:8918a71cdbe9 205
Sergunb 0:8918a71cdbe9 206 //Make sure the FTP server context is valid
Sergunb 0:8918a71cdbe9 207 if(context == NULL)
Sergunb 0:8918a71cdbe9 208 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 209
Sergunb 0:8918a71cdbe9 210 //Create the FTP server task
Sergunb 0:8918a71cdbe9 211 task = osCreateTask("FTP Server", (OsTaskCode) ftpServerTask,
Sergunb 0:8918a71cdbe9 212 context, FTP_SERVER_STACK_SIZE, FTP_SERVER_PRIORITY);
Sergunb 0:8918a71cdbe9 213
Sergunb 0:8918a71cdbe9 214 //Unable to create the task?
Sergunb 0:8918a71cdbe9 215 if(task == OS_INVALID_HANDLE)
Sergunb 0:8918a71cdbe9 216 return ERROR_OUT_OF_RESOURCES;
Sergunb 0:8918a71cdbe9 217
Sergunb 0:8918a71cdbe9 218 //Successful processing
Sergunb 0:8918a71cdbe9 219 return NO_ERROR;
Sergunb 0:8918a71cdbe9 220 }
Sergunb 0:8918a71cdbe9 221
Sergunb 0:8918a71cdbe9 222
Sergunb 0:8918a71cdbe9 223 /**
Sergunb 0:8918a71cdbe9 224 * @brief Set home directory
Sergunb 0:8918a71cdbe9 225 * @param[in] connection Pointer to the client connection
Sergunb 0:8918a71cdbe9 226 * @param[in] homeDir NULL-terminated string specifying the home directory
Sergunb 0:8918a71cdbe9 227 * @return Error code
Sergunb 0:8918a71cdbe9 228 **/
Sergunb 0:8918a71cdbe9 229
Sergunb 0:8918a71cdbe9 230 error_t ftpServerSetHomeDir(FtpClientConnection *connection, const char_t *homeDir)
Sergunb 0:8918a71cdbe9 231 {
Sergunb 0:8918a71cdbe9 232 //Ensure the parameters are valid
Sergunb 0:8918a71cdbe9 233 if(connection == NULL || homeDir == NULL)
Sergunb 0:8918a71cdbe9 234 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 235
Sergunb 0:8918a71cdbe9 236 //Set home directory
Sergunb 0:8918a71cdbe9 237 pathCombine(connection->homeDir, homeDir, FTP_SERVER_MAX_HOME_DIR_LEN);
Sergunb 0:8918a71cdbe9 238 //Clean the resulting path
Sergunb 0:8918a71cdbe9 239 pathCanonicalize(connection->homeDir);
Sergunb 0:8918a71cdbe9 240 pathRemoveSlash(connection->homeDir);
Sergunb 0:8918a71cdbe9 241
Sergunb 0:8918a71cdbe9 242 //Set current directory
Sergunb 0:8918a71cdbe9 243 strcpy(connection->currentDir, connection->homeDir);
Sergunb 0:8918a71cdbe9 244
Sergunb 0:8918a71cdbe9 245 //Successful processing
Sergunb 0:8918a71cdbe9 246 return NO_ERROR;
Sergunb 0:8918a71cdbe9 247 }
Sergunb 0:8918a71cdbe9 248
Sergunb 0:8918a71cdbe9 249
Sergunb 0:8918a71cdbe9 250 /**
Sergunb 0:8918a71cdbe9 251 * @brief FTP server task
Sergunb 0:8918a71cdbe9 252 * @param[in] context Pointer to the FTP server context
Sergunb 0:8918a71cdbe9 253 **/
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255 void ftpServerTask(FtpServerContext *context)
Sergunb 0:8918a71cdbe9 256 {
Sergunb 0:8918a71cdbe9 257 error_t error;
Sergunb 0:8918a71cdbe9 258 uint_t i;
Sergunb 0:8918a71cdbe9 259 systime_t time;
Sergunb 0:8918a71cdbe9 260 FtpClientConnection *connection;
Sergunb 0:8918a71cdbe9 261
Sergunb 0:8918a71cdbe9 262 #if (NET_RTOS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 263 //Process events
Sergunb 0:8918a71cdbe9 264 while(1)
Sergunb 0:8918a71cdbe9 265 {
Sergunb 0:8918a71cdbe9 266 #endif
Sergunb 0:8918a71cdbe9 267 //Clear event descriptor set
Sergunb 0:8918a71cdbe9 268 memset(context->eventDesc, 0, sizeof(context->eventDesc));
Sergunb 0:8918a71cdbe9 269
Sergunb 0:8918a71cdbe9 270 //Specify the events the application is interested in
Sergunb 0:8918a71cdbe9 271 for(i = 0; i < FTP_SERVER_MAX_CONNECTIONS; i++)
Sergunb 0:8918a71cdbe9 272 {
Sergunb 0:8918a71cdbe9 273 //Point to the structure describing the current connection
Sergunb 0:8918a71cdbe9 274 connection = context->connection[i];
Sergunb 0:8918a71cdbe9 275
Sergunb 0:8918a71cdbe9 276 //Loop through active connections only
Sergunb 0:8918a71cdbe9 277 if(connection != NULL)
Sergunb 0:8918a71cdbe9 278 {
Sergunb 0:8918a71cdbe9 279 //Ensure the control connection is opened
Sergunb 0:8918a71cdbe9 280 if(connection->controlSocket != NULL)
Sergunb 0:8918a71cdbe9 281 {
Sergunb 0:8918a71cdbe9 282 //Check the state of the control connection
Sergunb 0:8918a71cdbe9 283 if(connection->responseLength > 0)
Sergunb 0:8918a71cdbe9 284 {
Sergunb 0:8918a71cdbe9 285 //Wait until there is more room in the send buffer
Sergunb 0:8918a71cdbe9 286 context->eventDesc[2 * i].socket = connection->controlSocket;
Sergunb 0:8918a71cdbe9 287 context->eventDesc[2 * i].eventMask = SOCKET_EVENT_TX_READY;
Sergunb 0:8918a71cdbe9 288 }
Sergunb 0:8918a71cdbe9 289 else if(connection->controlState == FTP_CONTROL_STATE_WAIT_ACK)
Sergunb 0:8918a71cdbe9 290 {
Sergunb 0:8918a71cdbe9 291 //Wait for all the data to be transmitted and acknowledged
Sergunb 0:8918a71cdbe9 292 context->eventDesc[2 * i].socket = connection->controlSocket;
Sergunb 0:8918a71cdbe9 293 context->eventDesc[2 * i].eventMask = SOCKET_EVENT_TX_ACKED;
Sergunb 0:8918a71cdbe9 294 }
Sergunb 0:8918a71cdbe9 295 else if(connection->controlState == FTP_CONTROL_STATE_SHUTDOWN_TX)
Sergunb 0:8918a71cdbe9 296 {
Sergunb 0:8918a71cdbe9 297 //Wait for the FIN to be acknowledged
Sergunb 0:8918a71cdbe9 298 context->eventDesc[2 * i].socket = connection->controlSocket;
Sergunb 0:8918a71cdbe9 299 context->eventDesc[2 * i].eventMask = SOCKET_EVENT_TX_SHUTDOWN;
Sergunb 0:8918a71cdbe9 300 }
Sergunb 0:8918a71cdbe9 301 else if(connection->controlState == FTP_CONTROL_STATE_SHUTDOWN_RX)
Sergunb 0:8918a71cdbe9 302 {
Sergunb 0:8918a71cdbe9 303 //Wait for a FIN to be received
Sergunb 0:8918a71cdbe9 304 context->eventDesc[2 * i].socket = connection->controlSocket;
Sergunb 0:8918a71cdbe9 305 context->eventDesc[2 * i].eventMask = SOCKET_EVENT_RX_SHUTDOWN;
Sergunb 0:8918a71cdbe9 306 }
Sergunb 0:8918a71cdbe9 307 else
Sergunb 0:8918a71cdbe9 308 {
Sergunb 0:8918a71cdbe9 309 //Wait for data to be available for reading
Sergunb 0:8918a71cdbe9 310 context->eventDesc[2 * i].socket = connection->controlSocket;
Sergunb 0:8918a71cdbe9 311 context->eventDesc[2 * i].eventMask = SOCKET_EVENT_RX_READY;
Sergunb 0:8918a71cdbe9 312 }
Sergunb 0:8918a71cdbe9 313 }
Sergunb 0:8918a71cdbe9 314
Sergunb 0:8918a71cdbe9 315 //Ensure the data connection is opened
Sergunb 0:8918a71cdbe9 316 if(connection->dataSocket != NULL)
Sergunb 0:8918a71cdbe9 317 {
Sergunb 0:8918a71cdbe9 318 //Check the state of the data connection
Sergunb 0:8918a71cdbe9 319 if(connection->dataState == FTP_DATA_STATE_LISTEN ||
Sergunb 0:8918a71cdbe9 320 connection->dataState == FTP_DATA_STATE_RECEIVE)
Sergunb 0:8918a71cdbe9 321 {
Sergunb 0:8918a71cdbe9 322 //Wait for data to be available for reading
Sergunb 0:8918a71cdbe9 323 context->eventDesc[2 * i + 1].socket = connection->dataSocket;
Sergunb 0:8918a71cdbe9 324 context->eventDesc[2 * i + 1].eventMask = SOCKET_EVENT_RX_READY;
Sergunb 0:8918a71cdbe9 325 }
Sergunb 0:8918a71cdbe9 326 else if(connection->dataState == FTP_DATA_STATE_SEND)
Sergunb 0:8918a71cdbe9 327 {
Sergunb 0:8918a71cdbe9 328 //Wait until there is more room in the send buffer
Sergunb 0:8918a71cdbe9 329 context->eventDesc[2 * i + 1].socket = connection->dataSocket;
Sergunb 0:8918a71cdbe9 330 context->eventDesc[2 * i + 1].eventMask = SOCKET_EVENT_TX_READY;
Sergunb 0:8918a71cdbe9 331 }
Sergunb 0:8918a71cdbe9 332
Sergunb 0:8918a71cdbe9 333 else if(connection->dataState == FTP_DATA_STATE_WAIT_ACK)
Sergunb 0:8918a71cdbe9 334 {
Sergunb 0:8918a71cdbe9 335 //Wait for all the data to be transmitted and acknowledged
Sergunb 0:8918a71cdbe9 336 context->eventDesc[2 * i + 1].socket = connection->dataSocket;
Sergunb 0:8918a71cdbe9 337 context->eventDesc[2 * i + 1].eventMask = SOCKET_EVENT_TX_ACKED;
Sergunb 0:8918a71cdbe9 338 }
Sergunb 0:8918a71cdbe9 339 else if(connection->dataState == FTP_DATA_STATE_SHUTDOWN_TX)
Sergunb 0:8918a71cdbe9 340 {
Sergunb 0:8918a71cdbe9 341 //Wait for the FIN to be acknowledged
Sergunb 0:8918a71cdbe9 342 context->eventDesc[2 * i + 1].socket = connection->dataSocket;
Sergunb 0:8918a71cdbe9 343 context->eventDesc[2 * i + 1].eventMask = SOCKET_EVENT_TX_SHUTDOWN;
Sergunb 0:8918a71cdbe9 344 }
Sergunb 0:8918a71cdbe9 345 else if(connection->dataState == FTP_DATA_STATE_SHUTDOWN_RX)
Sergunb 0:8918a71cdbe9 346 {
Sergunb 0:8918a71cdbe9 347 //Wait for a FIN to be received
Sergunb 0:8918a71cdbe9 348 context->eventDesc[2 * i + 1].socket = connection->dataSocket;
Sergunb 0:8918a71cdbe9 349 context->eventDesc[2 * i + 1].eventMask = SOCKET_EVENT_RX_SHUTDOWN;
Sergunb 0:8918a71cdbe9 350 }
Sergunb 0:8918a71cdbe9 351 }
Sergunb 0:8918a71cdbe9 352 }
Sergunb 0:8918a71cdbe9 353 }
Sergunb 0:8918a71cdbe9 354
Sergunb 0:8918a71cdbe9 355 //Accept connection request events
Sergunb 0:8918a71cdbe9 356 context->eventDesc[2 * i].socket = context->socket;
Sergunb 0:8918a71cdbe9 357 context->eventDesc[2 * i].eventMask = SOCKET_EVENT_RX_READY;
Sergunb 0:8918a71cdbe9 358
Sergunb 0:8918a71cdbe9 359 //Wait for one of the set of sockets to become ready to perform I/O
Sergunb 0:8918a71cdbe9 360 error = socketPoll(context->eventDesc, 2 * FTP_SERVER_MAX_CONNECTIONS + 1,
Sergunb 0:8918a71cdbe9 361 &context->event, FTP_SERVER_SOCKET_POLLING_TIMEOUT);
Sergunb 0:8918a71cdbe9 362
Sergunb 0:8918a71cdbe9 363 //Get current time
Sergunb 0:8918a71cdbe9 364 time = osGetSystemTime();
Sergunb 0:8918a71cdbe9 365
Sergunb 0:8918a71cdbe9 366 //Verify status code
Sergunb 0:8918a71cdbe9 367 if(!error)
Sergunb 0:8918a71cdbe9 368 {
Sergunb 0:8918a71cdbe9 369 //Event-driven processing
Sergunb 0:8918a71cdbe9 370 for(i = 0; i < FTP_SERVER_MAX_CONNECTIONS; i++)
Sergunb 0:8918a71cdbe9 371 {
Sergunb 0:8918a71cdbe9 372 //Point to the structure describing the current connection
Sergunb 0:8918a71cdbe9 373 connection = context->connection[i];
Sergunb 0:8918a71cdbe9 374
Sergunb 0:8918a71cdbe9 375 //Make sure the control connection is still active
Sergunb 0:8918a71cdbe9 376 if(connection != NULL && connection->controlSocket != NULL)
Sergunb 0:8918a71cdbe9 377 {
Sergunb 0:8918a71cdbe9 378 //Check whether the control socket is to ready to perform I/O
Sergunb 0:8918a71cdbe9 379 if(context->eventDesc[2 * i].eventFlags)
Sergunb 0:8918a71cdbe9 380 {
Sergunb 0:8918a71cdbe9 381 //Update time stamp
Sergunb 0:8918a71cdbe9 382 connection->timestamp = time;
Sergunb 0:8918a71cdbe9 383 //Control connection event handler
Sergunb 0:8918a71cdbe9 384 ftpServerControlEventHandler(context, connection,
Sergunb 0:8918a71cdbe9 385 context->eventDesc[2 * i].eventFlags);
Sergunb 0:8918a71cdbe9 386 }
Sergunb 0:8918a71cdbe9 387 }
Sergunb 0:8918a71cdbe9 388
Sergunb 0:8918a71cdbe9 389 //The connection may have been closed...
Sergunb 0:8918a71cdbe9 390 connection = context->connection[i];
Sergunb 0:8918a71cdbe9 391
Sergunb 0:8918a71cdbe9 392 //Make sure the data connection is still active
Sergunb 0:8918a71cdbe9 393 if(connection != NULL && connection->dataSocket != NULL)
Sergunb 0:8918a71cdbe9 394 {
Sergunb 0:8918a71cdbe9 395 //Check whether the data socket to is ready to perform I/O
Sergunb 0:8918a71cdbe9 396 if(context->eventDesc[2 * i + 1].eventFlags)
Sergunb 0:8918a71cdbe9 397 {
Sergunb 0:8918a71cdbe9 398 //Update time stamp
Sergunb 0:8918a71cdbe9 399 connection->timestamp = time;
Sergunb 0:8918a71cdbe9 400 //Data connection event handler
Sergunb 0:8918a71cdbe9 401 ftpServerDataEventHandler(context, connection,
Sergunb 0:8918a71cdbe9 402 context->eventDesc[2 * i + 1].eventFlags);
Sergunb 0:8918a71cdbe9 403 }
Sergunb 0:8918a71cdbe9 404 }
Sergunb 0:8918a71cdbe9 405 }
Sergunb 0:8918a71cdbe9 406
Sergunb 0:8918a71cdbe9 407 //Check the state of the listening socket
Sergunb 0:8918a71cdbe9 408 if(context->eventDesc[2 * i].eventFlags & SOCKET_EVENT_RX_READY)
Sergunb 0:8918a71cdbe9 409 {
Sergunb 0:8918a71cdbe9 410 //Process incoming connection request
Sergunb 0:8918a71cdbe9 411 connection = ftpServerAcceptControlConnection(context);
Sergunb 0:8918a71cdbe9 412 //Initialize time stamp
Sergunb 0:8918a71cdbe9 413 if(connection != NULL)
Sergunb 0:8918a71cdbe9 414 connection->timestamp = time;
Sergunb 0:8918a71cdbe9 415 }
Sergunb 0:8918a71cdbe9 416 }
Sergunb 0:8918a71cdbe9 417
Sergunb 0:8918a71cdbe9 418 //Manage timeouts
Sergunb 0:8918a71cdbe9 419 for(i = 0; i < FTP_SERVER_MAX_CONNECTIONS; i++)
Sergunb 0:8918a71cdbe9 420 {
Sergunb 0:8918a71cdbe9 421 //Point to the structure describing the current connection
Sergunb 0:8918a71cdbe9 422 connection = context->connection[i];
Sergunb 0:8918a71cdbe9 423
Sergunb 0:8918a71cdbe9 424 //Any client connected?
Sergunb 0:8918a71cdbe9 425 if(connection != NULL)
Sergunb 0:8918a71cdbe9 426 {
Sergunb 0:8918a71cdbe9 427 //Disconnect inactive client after idle timeout
Sergunb 0:8918a71cdbe9 428 if((time - connection->timestamp) >= FTP_SERVER_TIMEOUT)
Sergunb 0:8918a71cdbe9 429 {
Sergunb 0:8918a71cdbe9 430 //Debug message
Sergunb 0:8918a71cdbe9 431 TRACE_INFO("FTP server: Closing inactive connection...\r\n");
Sergunb 0:8918a71cdbe9 432 //Close connection with the client
Sergunb 0:8918a71cdbe9 433 ftpServerCloseConnection(context, connection);
Sergunb 0:8918a71cdbe9 434 }
Sergunb 0:8918a71cdbe9 435 }
Sergunb 0:8918a71cdbe9 436 }
Sergunb 0:8918a71cdbe9 437 #if (NET_RTOS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 438 }
Sergunb 0:8918a71cdbe9 439 #endif
Sergunb 0:8918a71cdbe9 440 }
Sergunb 0:8918a71cdbe9 441
Sergunb 0:8918a71cdbe9 442 #endif
Sergunb 0:8918a71cdbe9 443