tftp_server.c
Go to the documentation of this file.
1 /**
2  * @file tftp_server.c
3  * @brief TFTP server
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * TFTP is a very simple protocol used to transfer files. Refer to the
30  * following RFCs for complete details:
31  * - RFC 1123: Requirements for Internet Hosts
32  * - RFC 1350: The TFTP Protocol (Revision 2)
33  * - RFC 1782: TFTP Option Extension
34  * - RFC 1783: TFTP Blocksize Option
35  * - RFC 1784: TFTP Timeout Interval and Transfer Size Options
36  *
37  * @author Oryx Embedded SARL (www.oryx-embedded.com)
38  * @version 1.9.8
39  **/
40 
41 //Switch to the appropriate trace level
42 #define TRACE_LEVEL TFTP_TRACE_LEVEL
43 
44 //Dependencies
45 #include "tftp/tftp_server.h"
46 #include "tftp/tftp_server_misc.h"
47 #include "debug.h"
48 
49 //Check TCP/IP stack configuration
50 #if (TFTP_SERVER_SUPPORT == ENABLED)
51 
52 
53 /**
54  * @brief Initialize settings with default values
55  * @param[out] settings Structure that contains TFTP server settings
56  **/
57 
59 {
60  //The TFTP server is not bound to any interface
61  settings->interface = NULL;
62 
63  //TFTP port number
64  settings->port = TFTP_PORT;
65 
66  //Open file callback function
67  settings->openFileCallback = NULL;
68  //Write file callback function
69  settings->writeFileCallback = NULL;
70  //Read file callback function
71  settings->readFileCallback = NULL;
72  //Close file callback function
73  settings->closeFileCallback = NULL;
74 }
75 
76 
77 /**
78  * @brief TFTP server initialization
79  * @param[in] context Pointer to the TFTP server context
80  * @param[in] settings TFTP server specific settings
81  * @return Error code
82  **/
83 
85 {
86  error_t error;
87 
88  //Debug message
89  TRACE_INFO("Initializing TFTP server...\r\n");
90 
91  //Ensure the parameters are valid
92  if(context == NULL || settings == NULL)
94 
95  //Clear the TFTP server context
96  osMemset(context, 0, sizeof(TftpServerContext));
97 
98  //Save user settings
99  context->settings = *settings;
100 
101  //Create an event object to poll the state of sockets
102  if(!osCreateEvent(&context->event))
103  {
104  //Failed to create event
105  return ERROR_OUT_OF_RESOURCES;
106  }
107 
108  //Start of exception handling block
109  do
110  {
111  //Open a UDP socket
113 
114  //Failed to open socket?
115  if(context->socket == NULL)
116  {
117  //Report an error
118  error = ERROR_OPEN_FAILED;
119  //Exit immediately
120  break;
121  }
122 
123  //Associate the socket with the relevant interface
124  error = socketBindToInterface(context->socket, settings->interface);
125  //Unable to bind the socket to the desired interface?
126  if(error)
127  break;
128 
129  //The TFTP server listens for connection requests on port 69
130  error = socketBind(context->socket, &IP_ADDR_ANY, settings->port);
131  //Unable to bind the socket to the desired port?
132  if(error)
133  break;
134 
135  //End of exception handling block
136  } while(0);
137 
138  //Check status code
139  if(error)
140  {
141  //Clean up side effects
142  tftpServerDeinit(context);
143  }
144 
145  //Return status code
146  return error;
147 }
148 
149 
150 /**
151  * @brief Start TFTP server
152  * @param[in] context Pointer to the TFTP server context
153  * @return Error code
154  **/
155 
157 {
158  OsTask *task;
159 
160  //Make sure the TFTP server context is valid
161  if(context == NULL)
163 
164  //Debug message
165  TRACE_INFO("Starting TFTP server...\r\n");
166 
167  //Create the TFTP server task
168  task = osCreateTask("TFTP Server", (OsTaskCode) tftpServerTask,
170 
171  //Unable to create the task?
172  if(task == OS_INVALID_HANDLE)
173  return ERROR_OUT_OF_RESOURCES;
174 
175  //Successful processing
176  return NO_ERROR;
177 }
178 
179 
180 /**
181  * @brief TFTP server task
182  * @param[in] context Pointer to the TFTP server context
183  **/
184 
186 {
187  error_t error;
188  uint_t i;
189  TftpClientConnection *connection;
190 
191 #if (NET_RTOS_SUPPORT == ENABLED)
192  //Task prologue
193  osEnterTask();
194 
195  //Process events
196  while(1)
197  {
198 #endif
199  //Clear event descriptor set
200  osMemset(context->eventDesc, 0, sizeof(context->eventDesc));
201 
202  //Specify the events the application is interested in
203  for(i = 0; i < TFTP_SERVER_MAX_CONNECTIONS; i++)
204  {
205  //Point to the structure describing the current connection
206  connection = &context->connection[i];
207 
208  //Loop through active connections only
209  if(connection->state != TFTP_STATE_CLOSED)
210  {
211  //Wait for a packet to be received
212  context->eventDesc[i].socket = connection->socket;
213  context->eventDesc[i].eventMask = SOCKET_EVENT_RX_READY;
214  }
215  }
216 
217  //The TFTP server listens for connection requests on port 69
218  context->eventDesc[i].socket = context->socket;
219  context->eventDesc[i].eventMask = SOCKET_EVENT_RX_READY;
220 
221  //Wait for one of the set of sockets to become ready to perform I/O
222  error = socketPoll(context->eventDesc, TFTP_SERVER_MAX_CONNECTIONS + 1,
223  &context->event, TFTP_SERVER_TICK_INTERVAL);
224 
225  //Verify status code
226  if(!error)
227  {
228  //Event-driven processing
229  for(i = 0; i < TFTP_SERVER_MAX_CONNECTIONS; i++)
230  {
231  //Point to the structure describing the current connection
232  connection = &context->connection[i];
233 
234  //Loop through active connections only
235  if(connection->state != TFTP_STATE_CLOSED)
236  {
237  //Check whether a packet has been received
238  if(context->eventDesc[i].eventFlags & SOCKET_EVENT_RX_READY)
239  {
240  //Process incoming packet
241  tftpServerProcessPacket(context, connection);
242  }
243  }
244  }
245 
246  //Any connection request received on port 69?
247  if(context->eventDesc[i].eventFlags & SOCKET_EVENT_RX_READY)
248  {
249  //Accept connection request
250  tftpServerAcceptRequest(context);
251  }
252  }
253 
254  //Handle periodic operations
255  tftpServerTick(context);
256 
257 #if (NET_RTOS_SUPPORT == ENABLED)
258  }
259 #endif
260 }
261 
262 
263 /**
264  * @brief Release TFTP server context
265  * @param[in] context Pointer to the TFTP server context
266  **/
267 
269 {
270  uint_t i;
271 
272  //Make sure the TFTP server context is valid
273  if(context != NULL)
274  {
275  //Loop through the connection table
276  for(i = 0; i < TFTP_SERVER_MAX_CONNECTIONS; i++)
277  {
278  //Close client connection
279  tftpServerCloseConnection(&context->connection[i]);
280  }
281 
282  //Close listening socket
283  socketClose(context->socket);
284 
285  //Free previously allocated resources
286  osDeleteEvent(&context->event);
287 
288  //Clear TFTP server context
289  osMemset(context, 0, sizeof(TftpServerContext));
290  }
291 }
292 
293 #endif
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:616
void tftpServerProcessPacket(TftpServerContext *context, TftpClientConnection *connection)
Process incoming packet.
#define TFTP_SERVER_TICK_INTERVAL
Definition: tftp_server.h:66
TftpServerCloseFileCallback closeFileCallback
Close file callback function.
Definition: tftp_server.h:173
error_t tftpServerInit(TftpServerContext *context, const TftpServerSettings *settings)
TFTP server initialization.
Definition: tftp_server.c:84
uint16_t port
TFTP port number.
Definition: tftp_server.h:169
void tftpServerCloseConnection(TftpClientConnection *connection)
Close client connection.
NetInterface * interface
Underlying network interface.
Definition: tftp_server.h:168
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:1259
#define TftpServerContext
Definition: tftp_server.h:108
void tftpServerTask(TftpServerContext *context)
TFTP server task.
Definition: tftp_server.c:185
void tftpServerDeinit(TftpServerContext *context)
Release TFTP server context.
Definition: tftp_server.c:268
TFTP server.
TftpServerReadFileCallback readFileCallback
Read file callback function.
Definition: tftp_server.h:172
TftpServerWriteFileCallback writeFileCallback
Write file callback function.
Definition: tftp_server.h:171
const IpAddr IP_ADDR_ANY
Definition: ip.c:45
Invalid parameter.
Definition: error.h:47
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
error_t
Error codes.
Definition: error.h:42
void osDeleteEvent(OsEvent *event)
Delete an event object.
error_t tftpServerStart(TftpServerContext *context)
Start TFTP server.
Definition: tftp_server.c:156
Task object.
TftpServerOpenFileCallback openFileCallback
Open file callback function.
Definition: tftp_server.h:170
#define TRACE_INFO(...)
Definition: debug.h:95
#define TFTP_SERVER_MAX_CONNECTIONS
Definition: tftp_server.h:59
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:119
#define osEnterTask()
error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout)
Wait for one of a set of sockets to become ready to perform I/O.
Definition: socket.c:1319
void tftpServerTick(TftpServerContext *context)
Handle periodic operations.
#define socketBindToInterface
Definition: net_legacy.h:264
void tftpServerAcceptRequest(TftpServerContext *context)
Accept connection request.
#define OS_INVALID_HANDLE
Definition: os_port.h:79
#define TFTP_PORT
Definition: tftp_common.h:38
void(* OsTaskCode)(void *param)
Task routine.
#define TFTP_SERVER_PRIORITY
Definition: tftp_server.h:54
bool_t osCreateEvent(OsEvent *event)
Create an event object.
#define TftpClientConnection
Definition: tftp_server.h:104
Helper functions for TFTP server.
TFTP server settings.
Definition: tftp_server.h:166
#define TFTP_SERVER_STACK_SIZE
Definition: tftp_server.h:47
unsigned int uint_t
Definition: compiler_port.h:45
#define osMemset(p, value, length)
Definition: os_port.h:128
void tftpServerGetDefaultSettings(TftpServerSettings *settings)
Initialize settings with default values.
Definition: tftp_server.c:58
Success.
Definition: error.h:44
Debugging facilities.