Webserver+3d print

Dependents:   Nucleo

Revision:
0:8918a71cdbe9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cyclone_tcp/std_services/chargen.c	Sat Feb 04 18:15:49 2017 +0000
@@ -0,0 +1,404 @@
+/**
+ * @file chargen.c
+ * @brief Character generator protocol
+ *
+ * @section License
+ *
+ * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
+ *
+ * This file is part of CycloneTCP Open.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * @section Description
+ *
+ * The character generator service is a useful debugging and measurement
+ * tool. The service simply sends data until the calling user terminates
+ * the connection. Refer to RFC 864 for complete details
+ *
+ * @author Oryx Embedded SARL (www.oryx-embedded.com)
+ * @version 1.7.6
+ **/
+
+//Switch to the appropriate trace level
+#define TRACE_LEVEL STD_SERVICES_TRACE_LEVEL
+
+//Dependencies
+#include "core/net.h"
+#include "std_services/chargen.h"
+#include "debug.h"
+
+//Character pattern (from RFC 864)
+const char_t pattern[190] =
+{
+   '!', '"', '#',  '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3',
+   '4', '5', '6',  '7', '8', '9', ':',  ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F',
+   'G', 'H', 'I',  'J', 'K', 'L', 'M',  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+   'Z', '[', '\\', ']', '^', '_', '`',  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+   'm', 'n', 'o',  'p', 'q', 'r', 's',  't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', ' ',
+   '!', '"', '#',  '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3',
+   '4', '5', '6',  '7', '8', '9', ':',  ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F',
+   'G', 'H', 'I',  'J', 'K', 'L', 'M',  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+   'Z', '[', '\\', ']', '^', '_', '`',  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+   'm', 'n', 'o',  'p', 'q', 'r', 's',  't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', ' '
+};
+
+
+/**
+ * @brief Start TCP chargen service
+ * @return Error code
+ **/
+
+error_t tcpChargenStart(void)
+{
+   error_t error;
+   Socket *socket;
+   OsTask *task;
+
+   //Debug message
+   TRACE_INFO("Starting TCP chargen service...\r\n");
+
+   //Open a TCP socket
+   socket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_IP_PROTO_TCP);
+   //Failed to open socket?
+   if(socket == NULL)
+      return ERROR_OPEN_FAILED;
+
+   //Start of exception handling block
+   do
+   {
+      //Bind the newly created socket to port 19
+      error = socketBind(socket, &IP_ADDR_ANY, CHARGEN_PORT);
+      //Failed to bind the socket to the desired port?
+      if(error)
+         break;
+
+      //Place the socket into listening mode
+      error = socketListen(socket, 0);
+      //Any error to report?
+      if(error)
+         break;
+
+      //Create a task to handle incoming connection requests
+      task = osCreateTask("TCP Chargen Listener", tcpChargenListenerTask,
+         socket, CHARGEN_SERVICE_STACK_SIZE, CHARGEN_SERVICE_PRIORITY);
+
+      //Unable to create the task?
+      if(task == OS_INVALID_HANDLE)
+      {
+         //Report an error to the calling function
+         error = ERROR_OUT_OF_RESOURCES;
+         break;
+      }
+
+      //End of exception handling block
+   } while(0);
+
+   //Any error to report?
+   if(error)
+   {
+      //Clean up side effects...
+      socketClose(socket);
+   }
+
+   //Return status code
+   return error;
+}
+
+
+/**
+ * @brief Task handling connection requests
+ * @param[in] param Pointer to the chargen service context
+ **/
+
+void tcpChargenListenerTask(void *param)
+{
+   error_t error;
+   uint16_t clientPort;
+   IpAddr clientIpAddr;
+   Socket *serverSocket;
+   Socket *clientSocket;
+   ChargenServiceContext *context;
+   OsTask *task;
+
+   //Point to the listening socket
+   serverSocket = (Socket *) param;
+
+   //Main loop
+   while(1)
+   {
+      //Accept an incoming connection
+      clientSocket = socketAccept(serverSocket, &clientIpAddr, &clientPort);
+      //Check whether a valid connection request has been received
+      if(!clientSocket) continue;
+
+      //Debug message
+      TRACE_INFO("Chargen service: connection established with client %s port %" PRIu16 "\r\n",
+         ipAddrToString(&clientIpAddr, NULL), clientPort);
+
+      //Adjust timeout
+      error = socketSetTimeout(clientSocket, CHARGEN_TIMEOUT);
+
+      //Any error to report?
+      if(error)
+      {
+         //Close socket
+         socketClose(clientSocket);
+         //Wait for an incoming connection attempt
+         continue;
+      }
+
+      //Allocate resources for the new connection
+      context = osAllocMem(sizeof(ChargenServiceContext));
+
+      //Failed to allocate memory?
+      if(context == NULL)
+      {
+         //Close socket
+         socketClose(clientSocket);
+         //Wait for an incoming connection attempt
+         continue;
+      }
+
+      //Record the handle of the newly created socket
+      context->socket = clientSocket;
+
+      //Create a task to service the current connection
+      task = osCreateTask("TCP Chargen Connection", tcpChargenConnectionTask,
+         context, CHARGEN_SERVICE_STACK_SIZE, CHARGEN_SERVICE_PRIORITY);
+
+      //Did we encounter an error?
+      if(task == OS_INVALID_HANDLE)
+      {
+         //Close socket
+         socketClose(clientSocket);
+         //Release resources
+         osFreeMem(context);
+      }
+   }
+}
+
+
+/**
+ * @brief TCP chargen service implementation
+ * @param[in] param Pointer to the chargen service context
+ **/
+
+void tcpChargenConnectionTask(void *param)
+{
+   error_t error;
+   //size_t i;
+   size_t n;
+   //size_t offset;
+   size_t byteCount;
+   systime_t startTime;
+   systime_t duration;
+   ChargenServiceContext *context;
+
+   //Get a pointer to the context
+   context = (ChargenServiceContext *) param;
+   //Get current time
+   startTime = osGetSystemTime();
+
+   //Initialize counters
+   byteCount = 0;
+   //offset = 0;
+
+   //Once a connection is established a stream of data is sent out
+   //the connection (and any data received is thrown away). This
+   //continues until the calling user terminates the connection
+   while(1)
+   {
+      //Format output data
+      /*for(i = 0; i < CHARGEN_BUFFER_SIZE; i += 95)
+      {
+         //Calculate the length of the current line
+         n = MIN(CHARGEN_BUFFER_SIZE - i, 95);
+         //Copy character pattern
+         memcpy(context->buffer + i, pattern + offset, n);
+      }
+
+      //Update offset
+      offset += CHARGEN_BUFFER_SIZE + 95 - i;
+      //Wrap around if necessary
+      if(offset >= 95) offset = 0;*/
+
+      //Send data
+      error = socketSend(context->socket, context->buffer, CHARGEN_BUFFER_SIZE, &n, 0);
+      //Any error to report?
+      if(error)
+         break;
+
+      //Total number of bytes sent
+      byteCount += n;
+   }
+
+   //Graceful shutdown
+   socketShutdown(context->socket, SOCKET_SD_BOTH);
+   //Compute total duration
+   duration = osGetSystemTime() - startTime;
+   //Avoid division by zero...
+   if(!duration) duration = 1;
+
+   //Debug message
+   TRACE_INFO("Chargen service: %" PRIuSIZE " bytes "
+      "sent in %" PRIu32 " ms (%" PRIu32 " kBps, %" PRIu32 " kbps)\r\n",
+      byteCount, duration, byteCount / duration, (byteCount * 8) / duration);
+
+   //Close socket
+   socketClose(context->socket);
+   //Release previously allocated memory
+   osFreeMem(context);
+
+   //Kill ourselves
+   osDeleteTask(NULL);
+}
+
+
+/**
+ * @brief Start UDP chargen service
+ * @return Error code
+ **/
+
+error_t udpChargenStart(void)
+{
+   error_t error;
+   ChargenServiceContext *context;
+   OsTask *task;
+
+   //Debug message
+   TRACE_INFO("Starting UDP chargen service...\r\n");
+
+   //Allocate a memory block to hold the context
+   context = osAllocMem(sizeof(ChargenServiceContext));
+   //Failed to allocate memory?
+   if(context == NULL)
+      return ERROR_OUT_OF_MEMORY;
+
+   //Start of exception handling block
+   do
+   {
+      //Open a UDP socket
+      context->socket = socketOpen(SOCKET_TYPE_DGRAM, SOCKET_IP_PROTO_UDP);
+
+      //Failed to open socket?
+      if(!context->socket)
+      {
+         //Report an error
+         error = ERROR_OPEN_FAILED;
+         //Exit immediately
+         break;
+      }
+
+      //The server listens for incoming datagrams on port 19
+      error = socketBind(context->socket, &IP_ADDR_ANY, CHARGEN_PORT);
+      //Unable to bind the socket to the desired port?
+      if(error)
+         break;
+
+      //Create a task to handle incoming datagrams
+      task = osCreateTask("UDP Chargen", udpChargenTask,
+         context, CHARGEN_SERVICE_STACK_SIZE, CHARGEN_SERVICE_PRIORITY);
+
+      //Unable to create the task?
+      if(task == OS_INVALID_HANDLE)
+      {
+         //Report an error to the calling function
+         error = ERROR_OUT_OF_RESOURCES;
+         break;
+      }
+
+      //End of exception handling block
+   } while(0);
+
+   //Any error to report?
+   if(error)
+   {
+      //Clean up side effects...
+      socketClose(context->socket);
+      osFreeMem(context);
+   }
+
+   //Return status code
+   return error;
+}
+
+
+/**
+ * @brief UDP chargen service implementation
+ * @param[in] param Pointer to the chargen service context
+ **/
+
+void udpChargenTask(void *param)
+{
+   error_t error;
+   size_t i;
+   size_t k;
+   size_t n;
+   size_t length;
+   uint16_t port;
+   IpAddr ipAddr;
+   ChargenServiceContext *context;
+
+   //Get a pointer to the context
+   context = (ChargenServiceContext *) param;
+
+   //Main loop
+   while(1)
+   {
+      //Wait for an incoming datagram
+      error = socketReceiveFrom(context->socket, &ipAddr, &port,
+         context->buffer, CHARGEN_BUFFER_SIZE, &n, 0);
+
+      //Any datagram received?
+      if(!error)
+      {
+         //When a datagram is received, an answering datagram is sent
+         //containing a random number (between 0 and 512) of characters
+         length = netGetRand() % 513;
+
+         //Reset line counter
+         n = 0;
+
+         //Format output data
+         for(i = 0; i < length; i += 74)
+         {
+            //Calculate the length of the current line
+            k = MIN(length - i, 74);
+            //Copy character pattern
+            memcpy(context->buffer + i, pattern + n, k);
+
+            //End each line with carriage return and line feed
+            if(k == 74)
+            {
+               context->buffer[i + 72] = '\r';
+               context->buffer[i + 73] = '\n';
+            }
+
+            //Increment line counter
+            if(++n >= 95) n = 0;
+         }
+
+         //Send data to the remote host
+         error = socketSendTo(context->socket, &ipAddr, port,
+            context->buffer, length, &n, 0);
+
+         //Debug message
+         TRACE_INFO("Chargen service: %" PRIuSIZE " bytes sent to %s port %" PRIu16 "\r\n",
+            n, ipAddrToString(&ipAddr, NULL), port);
+      }
+   }
+}
+