discard.c
Go to the documentation of this file.
1 /**
2  * @file discard.c
3  * @brief Discard protocol
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  * The discard service is a useful debugging and measurement tool. The service
28  * simply throws away any data it receives. Refer to RFC 863 for complete details
29  *
30  * @author Oryx Embedded SARL (www.oryx-embedded.com)
31  * @version 1.9.0
32  **/
33 
34 //Switch to the appropriate trace level
35 #define TRACE_LEVEL STD_SERVICES_TRACE_LEVEL
36 
37 //Dependencies
38 #include "core/net.h"
39 #include "std_services/discard.h"
40 #include "debug.h"
41 
42 
43 /**
44  * @brief Start TCP discard service
45  * @return Error code
46  **/
47 
49 {
50  error_t error;
51  Socket *socket;
52  OsTask *task;
53 
54  //Debug message
55  TRACE_INFO("Starting TCP discard service...\r\n");
56 
57  //Open a TCP socket
59  //Failed to open socket?
60  if(socket == NULL)
61  return ERROR_OPEN_FAILED;
62 
63  //Start of exception handling block
64  do
65  {
66  //Bind the newly created socket to port 9
68  //Failed to bind the socket to the desired port?
69  if(error)
70  break;
71 
72  //Place the socket into listening mode
73  error = socketListen(socket, 0);
74  //Any error to report?
75  if(error)
76  break;
77 
78  //Create a task to handle incoming connection requests
79  task = osCreateTask("TCP Discard Listener", tcpDiscardListenerTask,
81 
82  //Unable to create the task?
83  if(task == OS_INVALID_HANDLE)
84  {
85  //Report an error to the calling function
86  error = ERROR_OUT_OF_RESOURCES;
87  break;
88  }
89 
90  //End of exception handling block
91  } while(0);
92 
93  //Any error to report?
94  if(error)
95  {
96  //Clean up side effects...
98  }
99 
100  //Return status code
101  return error;
102 }
103 
104 
105 /**
106  * @brief Task handling connection requests
107  * @param[in] param Pointer to the discard service context
108  **/
109 
110 void tcpDiscardListenerTask(void *param)
111 {
112  error_t error;
113  uint16_t clientPort;
114  IpAddr clientIpAddr;
115  Socket *serverSocket;
116  Socket *clientSocket;
117  DiscardServiceContext *context;
118  OsTask *task;
119 
120  //Point to the listening socket
121  serverSocket = (Socket *) param;
122 
123  //Main loop
124  while(1)
125  {
126  //Accept an incoming connection
127  clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort);
128  //Check whether a valid connection request has been received
129  if(!clientSocket)
130  continue;
131 
132  //Debug message
133  TRACE_INFO("Discard service: connection established with client %s port %" PRIu16 "\r\n",
134  ipAddrToString(&clientIpAddr, NULL), clientPort);
135 
136  //Adjust timeout
137  error = socketSetTimeout(clientSocket, DISCARD_TIMEOUT);
138 
139  //Any error to report?
140  if(error)
141  {
142  //Close socket
143  socketClose(clientSocket);
144  //Wait for an incoming connection attempt
145  continue;
146  }
147 
148  //Allocate resources for the new connection
149  context = osAllocMem(sizeof(DiscardServiceContext));
150 
151  //Failed to allocate memory?
152  if(context == NULL)
153  {
154  //Close socket
155  socketClose(clientSocket);
156  //Wait for an incoming connection attempt
157  continue;
158  }
159 
160  //Record the handle of the newly created socket
161  context->socket = clientSocket;
162 
163  //Create a task to service the current connection
164  task = osCreateTask("TCP Discard Connection", tcpDiscardConnectionTask,
166 
167  //Did we encounter an error?
168  if(task == OS_INVALID_HANDLE)
169  {
170  //Close socket
171  socketClose(clientSocket);
172  //Release resources
173  osFreeMem(context);
174  }
175  }
176 }
177 
178 
179 /**
180  * @brief TCP discard service implementation
181  * @param[in] param Pointer to the discard service context
182  **/
183 
184 void tcpDiscardConnectionTask(void *param)
185 {
186  error_t error;
187  size_t n;
188  size_t byteCount;
189  systime_t startTime;
191  DiscardServiceContext *context;
192 
193  //Get a pointer to the context
194  context = (DiscardServiceContext *) param;
195  //Get current time
196  startTime = osGetSystemTime();
197 
198  //Total number of bytes received
199  byteCount = 0;
200 
201  //Main loop
202  while(1)
203  {
204  //Throw away any received datagram...
205  error = socketReceive(context->socket, context->buffer, DISCARD_BUFFER_SIZE, &n, 0);
206  //Any error to report?
207  if(error)
208  break;
209 
210  //Total number of bytes received
211  byteCount += n;
212  }
213 
214  //Graceful shutdown
216  //Compute total duration
217  duration = osGetSystemTime() - startTime;
218  //Avoid division by zero...
219  if(!duration)
220  duration = 1;
221 
222  //Debug message
223  TRACE_INFO("Discard service: %" PRIuSIZE " bytes "
224  "received in %" PRIu32 " ms (%" PRIu32 " kBps, %" PRIu32 " kbps)\r\n",
226 
227  //Close socket
228  socketClose(context->socket);
229  //Release previously allocated memory
230  osFreeMem(context);
231 
232  //Kill ourselves
233  osDeleteTask(NULL);
234 }
235 
236 
237 /**
238  * @brief Start UDP discard service
239  * @return Error code
240  **/
241 
243 {
244  error_t error;
245  DiscardServiceContext *context;
246  OsTask *task;
247 
248  //Debug message
249  TRACE_INFO("Starting UDP discard service...\r\n");
250 
251  //Allocate a memory block to hold the context
252  context = osAllocMem(sizeof(DiscardServiceContext));
253  //Failed to allocate memory?
254  if(context == NULL)
255  return ERROR_OUT_OF_MEMORY;
256 
257  //Start of exception handling block
258  do
259  {
260  //Open a UDP socket
262 
263  //Failed to open socket?
264  if(context->socket == NULL)
265  {
266  //Report an error
267  error = ERROR_OPEN_FAILED;
268  //Exit immediately
269  break;
270  }
271 
272  //The server listens for incoming datagrams on port 9
273  error = socketBind(context->socket, &IP_ADDR_ANY, DISCARD_PORT);
274  //Unable to bind the socket to the desired port?
275  if(error)
276  break;
277 
278  //Create a task to handle incoming datagrams
279  task = osCreateTask("UDP Discard", udpDiscardTask,
281 
282  //Unable to create the task?
283  if(task == OS_INVALID_HANDLE)
284  {
285  //Report an error to the calling function
286  error = ERROR_OUT_OF_RESOURCES;
287  break;
288  }
289 
290  //End of exception handling block
291  } while(0);
292 
293  //Any error to report?
294  if(error)
295  {
296  //Clean up side effects...
297  socketClose(context->socket);
298  osFreeMem(context);
299  }
300 
301  //Return status code
302  return error;
303 }
304 
305 
306 /**
307  * @brief UDP discard service implementation
308  * @param[in] param Pointer to the discard service context
309  **/
310 
311 void udpDiscardTask(void *param)
312 {
313  error_t error;
314  size_t length;
315  uint16_t port;
316  IpAddr ipAddr;
317  DiscardServiceContext *context;
318 
319  //Get a pointer to the context
320  context = (DiscardServiceContext *) param;
321 
322  //Main loop
323  while(1)
324  {
325  //Wait for an incoming datagram
326  error = socketReceiveFrom(context->socket, &ipAddr, &port,
327  context->buffer, DISCARD_BUFFER_SIZE, &length, 0);
328 
329  //Any datagram received?
330  if(!error)
331  {
332  //Debug message
333  TRACE_INFO("Discard service: %" PRIuSIZE " bytes received from %s port %" PRIu16 "\r\n",
334  length, ipAddrToString(&ipAddr, NULL), port);
335 
336  //Throw away any received datagram...
337  }
338  }
339 }
uint32_t systime_t
Definition: compiler_port.h:44
error_t socketReceive(Socket *socket, void *data, size_t size, size_t *received, uint_t flags)
Receive data from a connected socket.
Definition: socket.c:584
error_t udpDiscardStart(void)
Start UDP discard service.
Definition: discard.c:242
systime_t osGetSystemTime(void)
Retrieve system time.
void osFreeMem(void *p)
Release a previously allocated memory block.
TCP/IP stack core.
Debugging facilities.
char_t buffer[DISCARD_BUFFER_SIZE]
Definition: discard.h:78
void udpDiscardTask(void *param)
UDP discard service implementation.
Definition: discard.c:311
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
Socket * socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a socket.
Definition: socket.c:457
error_t socketListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: socket.c:420
IP network address.
Definition: ip.h:57
void tcpDiscardListenerTask(void *param)
Task handling connection requests.
Definition: discard.c:110
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:797
#define DISCARD_PORT
Definition: discard.h:63
char_t * ipAddrToString(const IpAddr *ipAddr, char_t *str)
Convert a binary IP address to a string representation.
Definition: ip.c:685
const IpAddr IP_ADDR_ANY
Definition: ip.c:42
#define DISCARD_TIMEOUT
Definition: discard.h:57
uint16_t duration
error_t socketReceiveFrom(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, void *data, size_t size, size_t *received, uint_t flags)
Receive a datagram from a connectionless socket.
Definition: socket.c:604
int_t socket(int_t family, int_t type, int_t protocol)
Create a socket that is bound to a specific transport service provider.
Definition: bsd_socket.c:106
uint8_t ipAddr[4]
Definition: mib_common.h:185
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:216
#define Socket
Definition: socket.h:34
#define DISCARD_SERVICE_PRIORITY
Definition: discard.h:45
Task object.
void tcpDiscardConnectionTask(void *param)
TCP discard service implementation.
Definition: discard.c:184
Discard protocol.
#define DISCARD_SERVICE_STACK_SIZE
Definition: discard.h:38
error_t tcpDiscardStart(void)
Start TCP discard service.
Definition: discard.c:48
error_t socketShutdown(Socket *socket, uint_t how)
Disable reception, transmission, or both.
Definition: socket.c:760
#define TRACE_INFO(...)
Definition: debug.h:86
void * osAllocMem(size_t size)
Allocate a memory block.
Discard service context.
Definition: discard.h:75
error_t
Error codes.
Definition: error.h:40
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:92
#define PRIuSIZE
Definition: compiler_port.h:72
void osDeleteTask(OsTask *task)
Delete a task.
#define DISCARD_BUFFER_SIZE
Definition: discard.h:50
uint16_t port
Definition: dns_common.h:221
uint16_t byteCount
#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
uint8_t length
Definition: dtls_misc.h:140
uint8_t n