Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
chargen.c
00001 /** 00002 * @file chargen.c 00003 * @brief Character generator protocol 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @section Description 00026 * 00027 * The character generator service is a useful debugging and measurement 00028 * tool. The service simply sends data until the calling user terminates 00029 * the connection. Refer to RFC 864 for complete details 00030 * 00031 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00032 * @version 1.7.6 00033 **/ 00034 00035 //Switch to the appropriate trace level 00036 #define TRACE_LEVEL STD_SERVICES_TRACE_LEVEL 00037 00038 //Dependencies 00039 #include "core/net.h" 00040 #include "std_services/chargen.h" 00041 #include "debug.h" 00042 00043 //Character pattern (from RFC 864) 00044 const char_t pattern[190] = 00045 { 00046 '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', 00047 '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 00048 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 00049 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 00050 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', ' ', 00051 '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', 00052 '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 00053 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 00054 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 00055 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', ' ' 00056 }; 00057 00058 00059 /** 00060 * @brief Start TCP chargen service 00061 * @return Error code 00062 **/ 00063 00064 error_t tcpChargenStart(void) 00065 { 00066 error_t error; 00067 Socket *socket; 00068 OsTask *task; 00069 00070 //Debug message 00071 TRACE_INFO("Starting TCP chargen service...\r\n"); 00072 00073 //Open a TCP socket 00074 socket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP); 00075 //Failed to open socket? 00076 if(socket == NULL) 00077 return ERROR_OPEN_FAILED; 00078 00079 //Start of exception handling block 00080 do 00081 { 00082 //Bind the newly created socket to port 19 00083 error = socketBind(socket, &IP_ADDR_ANY, CHARGEN_PORT); 00084 //Failed to bind the socket to the desired port? 00085 if(error) 00086 break; 00087 00088 //Place the socket into listening mode 00089 error = socketListen(socket, 0); 00090 //Any error to report? 00091 if(error) 00092 break; 00093 00094 //Create a task to handle incoming connection requests 00095 task = osCreateTask("TCP Chargen Listener", tcpChargenListenerTask, 00096 socket, CHARGEN_SERVICE_STACK_SIZE, CHARGEN_SERVICE_PRIORITY); 00097 00098 //Unable to create the task? 00099 if(task == OS_INVALID_HANDLE) 00100 { 00101 //Report an error to the calling function 00102 error = ERROR_OUT_OF_RESOURCES; 00103 break; 00104 } 00105 00106 //End of exception handling block 00107 } while(0); 00108 00109 //Any error to report? 00110 if(error) 00111 { 00112 //Clean up side effects... 00113 socketClose(socket); 00114 } 00115 00116 //Return status code 00117 return error; 00118 } 00119 00120 00121 /** 00122 * @brief Task handling connection requests 00123 * @param[in] param Pointer to the chargen service context 00124 **/ 00125 00126 void tcpChargenListenerTask(void *param) 00127 { 00128 error_t error; 00129 uint16_t clientPort; 00130 IpAddr clientIpAddr; 00131 Socket *serverSocket; 00132 Socket *clientSocket; 00133 ChargenServiceContext *context; 00134 OsTask *task; 00135 00136 //Point to the listening socket 00137 serverSocket = (Socket *) param; 00138 00139 //Main loop 00140 while(1) 00141 { 00142 //Accept an incoming connection 00143 clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort); 00144 //Check whether a valid connection request has been received 00145 if(!clientSocket) continue; 00146 00147 //Debug message 00148 TRACE_INFO("Chargen service: connection established with client %s port %" PRIu16 "\r\n", 00149 ipAddrToString(&clientIpAddr, NULL), clientPort); 00150 00151 //Adjust timeout 00152 error = socketSetTimeout(clientSocket, CHARGEN_TIMEOUT); 00153 00154 //Any error to report? 00155 if(error) 00156 { 00157 //Close socket 00158 socketClose(clientSocket); 00159 //Wait for an incoming connection attempt 00160 continue; 00161 } 00162 00163 //Allocate resources for the new connection 00164 context = osAllocMem(sizeof(ChargenServiceContext)); 00165 00166 //Failed to allocate memory? 00167 if(context == NULL) 00168 { 00169 //Close socket 00170 socketClose(clientSocket); 00171 //Wait for an incoming connection attempt 00172 continue; 00173 } 00174 00175 //Record the handle of the newly created socket 00176 context->socket = clientSocket; 00177 00178 //Create a task to service the current connection 00179 task = osCreateTask("TCP Chargen Connection", tcpChargenConnectionTask, 00180 context, CHARGEN_SERVICE_STACK_SIZE, CHARGEN_SERVICE_PRIORITY); 00181 00182 //Did we encounter an error? 00183 if(task == OS_INVALID_HANDLE) 00184 { 00185 //Close socket 00186 socketClose(clientSocket); 00187 //Release resources 00188 osFreeMem(context); 00189 } 00190 } 00191 } 00192 00193 00194 /** 00195 * @brief TCP chargen service implementation 00196 * @param[in] param Pointer to the chargen service context 00197 **/ 00198 00199 void tcpChargenConnectionTask(void *param) 00200 { 00201 error_t error; 00202 //size_t i; 00203 size_t n; 00204 //size_t offset; 00205 size_t byteCount; 00206 systime_t startTime; 00207 systime_t duration; 00208 ChargenServiceContext *context; 00209 00210 //Get a pointer to the context 00211 context = (ChargenServiceContext *) param; 00212 //Get current time 00213 startTime = osGetSystemTime(); 00214 00215 //Initialize counters 00216 byteCount = 0; 00217 //offset = 0; 00218 00219 //Once a connection is established a stream of data is sent out 00220 //the connection (and any data received is thrown away). This 00221 //continues until the calling user terminates the connection 00222 while(1) 00223 { 00224 //Format output data 00225 /*for(i = 0; i < CHARGEN_BUFFER_SIZE; i += 95) 00226 { 00227 //Calculate the length of the current line 00228 n = MIN(CHARGEN_BUFFER_SIZE - i, 95); 00229 //Copy character pattern 00230 memcpy(context->buffer + i, pattern + offset, n); 00231 } 00232 00233 //Update offset 00234 offset += CHARGEN_BUFFER_SIZE + 95 - i; 00235 //Wrap around if necessary 00236 if(offset >= 95) offset = 0;*/ 00237 00238 //Send data 00239 error = socketSend(context->socket, context->buffer, CHARGEN_BUFFER_SIZE, &n, 0); 00240 //Any error to report? 00241 if(error) 00242 break; 00243 00244 //Total number of bytes sent 00245 byteCount += n; 00246 } 00247 00248 //Graceful shutdown 00249 socketShutdown(context->socket, SOCKET_SD_BOTH); 00250 //Compute total duration 00251 duration = osGetSystemTime() - startTime; 00252 //Avoid division by zero... 00253 if(!duration) duration = 1; 00254 00255 //Debug message 00256 TRACE_INFO("Chargen service: %" PRIuSIZE " bytes " 00257 "sent in %" PRIu32 " ms (%" PRIu32 " kBps, %" PRIu32 " kbps)\r\n", 00258 byteCount, duration, byteCount / duration, (byteCount * 8) / duration); 00259 00260 //Close socket 00261 socketClose(context->socket); 00262 //Release previously allocated memory 00263 osFreeMem(context); 00264 00265 //Kill ourselves 00266 osDeleteTask(NULL); 00267 } 00268 00269 00270 /** 00271 * @brief Start UDP chargen service 00272 * @return Error code 00273 **/ 00274 00275 error_t udpChargenStart(void) 00276 { 00277 error_t error; 00278 ChargenServiceContext *context; 00279 OsTask *task; 00280 00281 //Debug message 00282 TRACE_INFO("Starting UDP chargen service...\r\n"); 00283 00284 //Allocate a memory block to hold the context 00285 context = osAllocMem(sizeof(ChargenServiceContext)); 00286 //Failed to allocate memory? 00287 if(context == NULL) 00288 return ERROR_OUT_OF_MEMORY; 00289 00290 //Start of exception handling block 00291 do 00292 { 00293 //Open a UDP socket 00294 context->socket = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_IP_PROTO_UDP); 00295 00296 //Failed to open socket? 00297 if(!context->socket) 00298 { 00299 //Report an error 00300 error = ERROR_OPEN_FAILED; 00301 //Exit immediately 00302 break; 00303 } 00304 00305 //The server listens for incoming datagrams on port 19 00306 error = socketBind(context->socket, &IP_ADDR_ANY, CHARGEN_PORT); 00307 //Unable to bind the socket to the desired port? 00308 if(error) 00309 break; 00310 00311 //Create a task to handle incoming datagrams 00312 task = osCreateTask("UDP Chargen", udpChargenTask, 00313 context, CHARGEN_SERVICE_STACK_SIZE, CHARGEN_SERVICE_PRIORITY); 00314 00315 //Unable to create the task? 00316 if(task == OS_INVALID_HANDLE) 00317 { 00318 //Report an error to the calling function 00319 error = ERROR_OUT_OF_RESOURCES; 00320 break; 00321 } 00322 00323 //End of exception handling block 00324 } while(0); 00325 00326 //Any error to report? 00327 if(error) 00328 { 00329 //Clean up side effects... 00330 socketClose(context->socket); 00331 osFreeMem(context); 00332 } 00333 00334 //Return status code 00335 return error; 00336 } 00337 00338 00339 /** 00340 * @brief UDP chargen service implementation 00341 * @param[in] param Pointer to the chargen service context 00342 **/ 00343 00344 void udpChargenTask(void *param) 00345 { 00346 error_t error; 00347 size_t i; 00348 size_t k; 00349 size_t n; 00350 size_t length; 00351 uint16_t port; 00352 IpAddr ipAddr; 00353 ChargenServiceContext *context; 00354 00355 //Get a pointer to the context 00356 context = (ChargenServiceContext *) param; 00357 00358 //Main loop 00359 while(1) 00360 { 00361 //Wait for an incoming datagram 00362 error = socketReceiveFrom(context->socket, &ipAddr, &port, 00363 context->buffer, CHARGEN_BUFFER_SIZE, &n, 0); 00364 00365 //Any datagram received? 00366 if(!error) 00367 { 00368 //When a datagram is received, an answering datagram is sent 00369 //containing a random number (between 0 and 512) of characters 00370 length = netGetRand() % 513; 00371 00372 //Reset line counter 00373 n = 0; 00374 00375 //Format output data 00376 for(i = 0; i < length; i += 74) 00377 { 00378 //Calculate the length of the current line 00379 k = MIN(length - i, 74); 00380 //Copy character pattern 00381 memcpy(context->buffer + i, pattern + n, k); 00382 00383 //End each line with carriage return and line feed 00384 if(k == 74) 00385 { 00386 context->buffer[i + 72] = '\r'; 00387 context->buffer[i + 73] = '\n'; 00388 } 00389 00390 //Increment line counter 00391 if(++n >= 95) n = 0; 00392 } 00393 00394 //Send data to the remote host 00395 error = socketSendTo(context->socket, &ipAddr, port, 00396 context->buffer, length, &n, 0); 00397 00398 //Debug message 00399 TRACE_INFO("Chargen service: %" PRIuSIZE " bytes sent to %s port %" PRIu16 "\r\n", 00400 n, ipAddrToString(&ipAddr, NULL), port); 00401 } 00402 } 00403 } 00404
Generated on Tue Jul 12 2022 17:10:12 by
1.7.2