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