]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/commitdiff
nc - receive timeout, udp support
authorJan Dolezal <pm.jenik@gmail.com>
Tue, 13 Aug 2013 17:10:42 +0000 (19:10 +0200)
committerJan Dolezal <pm.jenik@gmail.com>
Wed, 14 Aug 2013 12:46:39 +0000 (14:46 +0200)
  - help messages not yet updated

commands/cmd_lwip.c
commands/cmd_lwip.h
rpp-lib

index 8c47728d8b6e03d61c9a89faaf9d0da3d8f2fb9d..821cf1cb4ba4f59252a1f62f454621c1e23af7b3 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "rpp/rpp.h"
 #include "lwip/api.h" //netconn
+#include "lwip/udp.h"
 
 #define INTERFACE_INSTANCE_NUMBER 0
 
@@ -73,53 +74,33 @@ int cmd_do_read_ip(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
 #define BUF_SIZE 80
 static char in_buffer[BUF_SIZE];
 boolean_t ncStop = FALSE;
-xSemaphoreHandle rpp_eth_dataArrived, rpp_eth_rcvReady;
-struct netbuf *remoteData;
-
-/* task waiting for data to be received from remote IP node */
-void rpp_eth_nc_recv(void *arg)
-{
-       while(!ncStop)
-       {
-               if(xSemaphoreTake(rpp_eth_rcvReady, 200) != pdTRUE)continue;
-               if(netconn_recv ( (struct netconn *) arg, &remoteData ) != ERR_OK )
-               {
-#if FILE_DBG
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E netconn_recv\r\n");
-#endif /* DEBUG */
+#if !NO_SYS
+boolean_t closeths; /* variable controling threads closing */
 #endif
-                       ncStop = TRUE;
-                       continue;
-               }
-               xSemaphoreGive(rpp_eth_dataArrived);
-       }
+struct netbuf *remoteData, *localData;
 
-       vSemaphoreDelete(rpp_eth_rcvReady);
-       rpp_eth_rcvReady = NULL;
-    // Delete myself
-    vTaskDelete(NULL);
-}
+uint16_t tcpDindex;
+static char tcpData_buffer[1522];
+
+void run_nc(void *arg){
 
-/* For now this does print only first pbuf in the chain of pbufs */
-void rpp_eth_print_payload()
-{
-    struct pbuf *current = remoteData->p;
-    uint16_t index = 0;
-    uint8_t *payload = current->payload;
-    while(index<current->len)
-    {
-       rpp_sci_printf((const char *) "%c",payload[index]);
-       index++;
-    }
 }
 
-int cmd_do_run_nc(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+/* when -p option not given, srcPort is used; when nc run repeatedly,
+ * even though netconn was removed, netconn_new() with previously used port
+ * might still cause errors like address in use, therefore in srcPort
+ * there next port NO prepared to be used */
+uint16_t srcPort = 1025; /* initial value */
+
+int cmd_do_init_nc(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
 {
     err_t err = ERR_OK;
        uint8_t input = 0;
     uint8_t buff_index = 0;
-       uint16_t portNO;
+    uint16_t index;
+    uint8_t *payload;
+       uint16_t portNO, srcPortNO;
+       uint8_t tries;
        uint32_t counter;
        ip_addr_t remoteIP;
        struct netconn *netconn, *newconn;
@@ -127,160 +108,286 @@ int cmd_do_run_nc(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
     ncStop = FALSE;
     netconn = NULL;
     newconn = NULL;
+       struct pbuf *p;
 
     struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
 
-       if(param[1] == 0 || strncmp((char *) param[1], "-h", 3) == 0 || strncmp((char *) param[1], "help", 3) == 0){
-        rpp_sci_printf((const char *) "Usage:\tnc -l port\tlistens on the specified port number\r\n");
-        rpp_sci_printf((const char *) "\tnc address port\tconnects to the address on port NO.\r\n");
-        rpp_sci_printf((const char *) "\tnc -d address port\tsends big amoung of testing data\r\n");
-               return err;
-       } else if(param[3] != 0 && (param[4] != 0 || strncmp((char *) param[1], "-d", 3))){
-               rpp_sci_printf((const char *) "wrong number of parameters\r\n");
-               return -1;
-       } else if(strncmp((char *) param[1], "-l", 3) == 0){
-               portNO = rpp_eth_portStrToInt((uint8_t *)param[2]);
-#if FILE_DBG
-               rpp_sci_printf((const char *) "portNO assigned\r\n");
-#endif
-               if(portNO == 0)
-               {
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E wrong portNO\r\n");
-#endif
-                       return -1;
-               }
-#if FILE_DBG
-               rpp_sci_printf((const char *) "netconn - new\r\n");
+    boolean_t udp = FALSE, listen = FALSE, ping = FALSE, test = FALSE, help = FALSE, srcPortSpec = FALSE;
+#if !NO_SYS
+    boolean_t thread = FALSE; /* variable controling whether this instance should run as thread */
 #endif
-               netconn = netconn_new(NETCONN_TCP);
-               if(netconn == NULL){
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E allocating NETCONN_TCP failed\r\n");
-#endif
-                       return -1;
-               }
-#if FILE_DBG
-               rpp_sci_printf((const char *) "netconn - bind\r\n");
-#endif
-               if((err = netconn_bind(netconn, &(netif->ip_addr), portNO)) != ERR_OK){
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E binding failed\r\n");
-#endif
-                       netconn_delete(netconn);
-                       return err;
-               }
-#if FILE_DBG
-               rpp_sci_printf((const char *) "netconn - listen\r\n");
-#endif
-               netconn_listen(netconn);
-#if FILE_DBG
-               rpp_sci_printf((const char *) "netconn - accept\r\n");
-#endif
-           if( (err = netconn_accept(netconn, &newconn)) != ERR_OK)
-           {
-#ifdef DEBUG
-               rpp_sci_printf((const char *) "E netconn_accept: %x\r\n", err);
+    uint8_t pindex;
+
+    closeths = FALSE; /* switch off closing of threads */
+
+    /* examine parameters */
+    for(pindex = 1;param[pindex] != 0;pindex++)
+    {
+       if        (strncmp((char *) param[pindex], "-h", 3) == 0) {
+            help = TRUE;
+            break;
+       } else if (strncmp((char *) param[pindex], "-u", 3) == 0) {
+               udp = TRUE;
+#if !NO_SYS
+       } else if (strncmp((char *) param[pindex], "-t", 3) == 0) {
+               thread = TRUE;
+       } else if (strncmp((char *) param[pindex], "-c", 3) == 0) {
+               closeths = TRUE;
+               return ERR_OK;
 #endif
-               netconn_delete(netconn);
-               return err;
-           }
-       } else {
-#if FILE_DBG
-               rpp_sci_printf((const char *) "ip assign\r\n");
+       } else if (strncmp((char *) param[pindex], "-l", 3) == 0 && !srcPortSpec) {
+               listen = TRUE;
+               srcPortNO = rpp_eth_portStrToInt((uint8_t *)param[++pindex]);
+                       if(srcPortNO == 0)
+                       {
+                               rpp_sci_printf((const char *) "E wrong portNO, portNO must follow immediately after -l option\r\n");
+                               return BAD_PORT_NO;
+                       }
+               srcPortSpec = TRUE;
+       } else if (strncmp((char *) param[pindex], "-p", 3) == 0 && !srcPortSpec) {
+               srcPortNO = rpp_eth_portStrToInt((uint8_t *)param[++pindex]);
+                       if(srcPortNO == 0)
+                       {
+                               rpp_sci_printf((const char *) "E wrong portNO, portNO must follow immediately after -p option\r\n");
+                               return BAD_PORT_NO;
+                       }
+               srcPortSpec = TRUE;
+       } else if (strncmp((char *) param[pindex], "-m", 3) == 0) {
+               ping = TRUE;
+       } else if (strncmp((char *) param[pindex], "-d", 3) == 0) {
+            test = TRUE;
+       } else if ( (err = rpp_eth_stringToIP(&remoteIP, (uint8_t *) param[pindex])) == SUCCESS ) {
+               portNO = rpp_eth_portStrToInt((uint8_t *)param[++pindex]);
+                       if(portNO == 0)
+                       {
+                               rpp_sci_printf((const char *) "E wrong portNO, portNO must follow immediately after IP address\r\n");
+                               return BAD_PORT_NO;
+                       }
+       } else {
+               rpp_sci_printf((const char *) "ERR: check option name, option combination, IP address format\r\n");
+               help = TRUE;
+               err = BAD_OPTION;
+               break;
+       }
+    }
+
+    /* usage of command */
+    if(help || !param[1])
+    {
+       rpp_sci_printf((const char *) "-h help, -u udp, -t thread, -l listen, -p ping/mirror, -d test\r\n\n");
+        rpp_sci_printf((const char *) "Usage:\tnc -l port\tlistens on the specified port number\r\n");
+        rpp_sci_printf((const char *) "\tnc address port\tconnects to the address on port NO.\r\n");
+        rpp_sci_printf((const char *) "\tnc -d address port\tsends big amoung of testing data/packets\r\n");
+       return err;
+    }
+
+    /* determine srcPortNO if not done yet */
+    if(!srcPortSpec)
+    {
+       srcPortNO = srcPort++;
+    }
+
+#if NO_SYS /* raw LwIP API */
+    rpp_sci_printf((const char *) "nc does not support NO_SYS yet\r\n");
+    return 1;
 #endif
-               if(( err = rpp_eth_stringToIP(&remoteIP, (uint8_t *) (strncmp(param[1], "-d", 3)?param[1]:param[2])) ) != ERR_OK)
+
+
+    /*** make connection ***/
+
+    /* fill netconn struct */
+       netconn = netconn_new(udp?NETCONN_UDP:NETCONN_TCP);
+       if(netconn == NULL){
+               return ERR_NETCONN_NEW;
+       }
+       /* bind filled netconn with local interface address and source port number */
+       if((err = netconn_bind(netconn, &(netif->ip_addr), srcPortNO)) != ERR_OK){
+               netconn_delete(netconn);
+               return ERR_BINDING;
+       }
+
+       /* XXX: adjust recvtimeout time and tries to different values, if user shouldn't loose control over cmd processor at any time */
+       netconn_set_recvtimeout(netconn, 1000);
+       tries = 60;
+
+       if(listen) /* -l <PORT> option */
+       {
+               if(!udp) /* TCP - make connection */
                {
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E wrong IP address format\r\n");
-#endif
-                       return err;
+                       /* make listening netconn */
+                       netconn_listen(netconn);
+                       /* accept connection to newconn */
+                       while( tries-- && (err = netconn_accept(netconn, &newconn)) == ERR_TIMEOUT)
+                       {
+                if(rpp_sci_read_nb(1, &input) != FAILURE) /* allow user to interrupt accepting new connection */
+                {
+                    break; /* on user input break */
+                }
+                       }
+                       netconn_delete(netconn); /* we don't need listening netconn anymore */
+                       if(err != ERR_OK)
+                       {
+                               return ERR_CONN_ACCEPT;
+                       }
                }
-               rpp_sci_printf((const char *) "%x\r\n",remoteIP.addr);
-#if FILE_DBG
-               rpp_sci_printf((const char *) "port assign\r\n");
-#endif
-               portNO = rpp_eth_portStrToInt((uint8_t *) (strncmp(param[1], "-d", 3)?param[2]:param[3]));
-               if(portNO == 0)
+               else
                {
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E wrong portNO\r\n");
-#endif
-                       return -1;
+                       while(tries--)
+                       {
+                               if(rpp_sci_read_nb(1, &input) == SUCCESS){ /* allow user to interrupt waiting for "udp connection" */
+                                       netconn_delete(netconn);
+                                       return ERR_CONNECTING;
+                               }
+
+                               if((err = netconn_recv(netconn, &remoteData)) == ERR_OK) /* wait for data, from which we will determine our peer address and portNO */
+                               {
+                                       remoteIP = remoteData->addr;
+                                       portNO = remoteData->port;
+                                       if(test)netbuf_delete(remoteData);
+                                       break;
+                               }
+                               else
+                               {
+                                       if(err == ERR_TIMEOUT)continue;
+                                       else
+                                       {
+                                               netconn_delete(netconn);
+                                               return err;
+                                       }
+                               }
+                       }
+                       if(!tries){
+                               netconn_delete(netconn);
+                               return ERR_CONNECTING;
+                       }
                }
-#if FILE_DBG
-               rpp_sci_printf((const char *) "newconn - new\r\n");
-#endif
-               newconn = netconn_new(NETCONN_TCP);
-               if(newconn == NULL){
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E allocating NETCONN_TCP failed\r\n");
-#endif
-                       return -1;
-               }
-#if FILE_DBG
-               rpp_sci_printf((const char *) "newconn - bind\r\n");
-#endif
-               if( ( err = netconn_bind(newconn, &(netif->ip_addr), portNO) ) != ERR_OK){
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E binding failed\r\n");
-#endif
-                       netconn_delete(newconn);
-                       return err;
+       }
+
+       if(!listen || (listen && udp) ) /* connect to remote node */
+       {
+               newconn = netconn;
+               netconn = NULL;
+               tries = 15; /* how many local ports to try */
+               while( tries-- && ( err = netconn_connect(newconn, &remoteIP, portNO) ) == ERR_USE){
+                       srcPort++;
                }
-#if FILE_DBG
-               rpp_sci_printf((const char *) "newconn - connect\r\n");
-#endif
-               if( ( err = netconn_connect(newconn, &remoteIP, portNO) ) != ERR_OK){
-#ifdef DEBUG
-                       rpp_sci_printf((const char *) "E not connected\r\n");
-#endif
+               if(err != ERR_OK)
+               {
                        netconn_delete(newconn);
-                       return err;
+                       return ERR_CONNECTING;
                }
        }
 
-       if(strncmp((char *) param[1], "-d", 3) == 0)
+    /* we will block for time specified on next line on netconn to receive data, if it does not come, we block for user sci input */
+       netconn_set_recvtimeout(newconn, 50);
+
+       if(udp && (localData = netbuf_new()) == NULL){
+               netconn_delete(newconn);
+               return ERR_MEM;
+       }
+
+       if(test) /* -d option; sends packets to the opposite node and doesn't receive anything */
        {
                counter = 0;
                char strbuf[10];
                int strlen;
-               while(counter++ < 500000){
-                       if(rpp_sci_read_nb(1, &input) == SUCCESS)return ERR_OK;
+               while(!closeths && counter++ < 500000){
+                       if(rpp_sci_read_nb(1, &input) == SUCCESS)break; /* allow user to interrupt sending */
                strlen = sprintf(strbuf,"%d\r\n",counter);
-               netconn_write(newconn, strbuf, strlen, NETCONN_COPY);
+               if(!udp)
+               {
+                       if((err = netconn_write(newconn, strbuf, strlen, NETCONN_COPY)) != ERR_OK)break;
+               }
+               else
+               {
+                       payload = netbuf_alloc(localData,strlen);
+                       if(payload != NULL)
+                       {
+                               netbuf_take(localData,strbuf,strlen);
+                               netbuf_len(localData) = strlen;
+                               if((err = netconn_send(newconn, localData)) != ERR_OK)break;
+                       }
+                       else
+                       {
+                               err = ERR_MEM;
+                               break;
+                       }
+               }
                }
-               netconn_close(newconn);
-               if(netconn != NULL)netconn_delete(netconn);
+               if(udp && localData != NULL)netbuf_delete(localData);
+               if(!udp)netconn_close(newconn);
+               else netconn_disconnect(newconn); /* pbbly not necessary */
                netconn_delete(newconn);
-               return ERR_OK;
+               return err;
        }
 
-       /* start receiving task */
-       vSemaphoreCreateBinary(rpp_eth_rcvReady);
-       xSemaphoreGive(rpp_eth_rcvReady);
-       vSemaphoreCreateBinary(rpp_eth_dataArrived);
-       xSemaphoreTake(rpp_eth_dataArrived, 0);
-
-#if FILE_DBG
-       rpp_sci_printf((const char *) "recv task create\r\n");
-#endif
-       if(xTaskCreate(rpp_eth_nc_recv, (const signed char*)"rpp_eth_ncRecv", 128, newconn, 2, NULL) != pdPASS)
+       if(ping) /* -m option */
        {
-           rpp_sci_printf((const char *) "rpp_eth_ncRecv task not created\r\n");
+               err = ERR_OK;
+               while(!closeths && rpp_sci_read_nb(1, &input) != SUCCESS){ /* allow user to interrupt operation */
+                       if( (err = netconn_recv ( newconn, &remoteData )) == ERR_TIMEOUT )
+                       {
+                               continue;
+                       }
+                       else if(err != ERR_OK)
+                       {
+                               err = ERR_RECEIVING;
+                               break;
+                       }
+
+                       p = remoteData->p;
+                       while(p != NULL)
+                       {
+                   index = 0;
+                   payload = p->payload;
+                while(index<p->len)
+                {
+                               tcpData_buffer[tcpDindex++] = payload[index++];
+                }
+                       p = p->next;
+                       }
+               netbuf_delete(remoteData);
+               remoteData = NULL;
+                   netconn_write(newconn, tcpData_buffer, tcpDindex, NETCONN_COPY); /*NETCONN_DONTBLOCK*/
+               }
+               if(udp && localData != NULL)netbuf_delete(localData);
+               netbuf_delete(remoteData);
+               if(!udp)netconn_close(newconn);
+               netconn_delete(newconn);
+               return err;
        }
 
-       rpp_sci_printf((const char *) "loop\r\n");
-       while(!ncStop)
+
+    /* receive remote data and print them to sci, receive sci data and write them to netconn */
+       while(!closeths && !ncStop)
        {
                if(rpp_sci_read_nb(1, &input) != SUCCESS && !ncStop) {
-                   if(xSemaphoreTake(rpp_eth_dataArrived, 50 / portTICK_RATE_MS) == pdTRUE){
-                       /* print remote data to SCI */
-                       rpp_eth_print_payload();
-                       netbuf_delete(remoteData);
-                       remoteData = NULL;
-                       xSemaphoreGive(rpp_eth_rcvReady);
+                   if( remoteData != NULL || (err = netconn_recv ( newconn, &remoteData )) != ERR_TIMEOUT)
+                   {
+                       if(err == ERR_OK)
+                       {
+                               /* print remote data to SCI */
+                               p = remoteData->p;
+                               while(p != NULL)
+                               {
+                                   index = 0;
+                                   payload = p->payload;
+                                   while(index<p->len)
+                                   {
+                                       rpp_sci_printf((const char *) "%c",payload[index]);
+                                       index++;
+                                   }
+                                       p = p->next;
+                               }
+                               netbuf_delete(remoteData);
+                               remoteData = NULL;
+                       }
+                       else
+                       {
+                               ncStop = TRUE; /* receive error - e.g. newconn was closed */
+                       }
                    }
+                   if(err == ERR_TIMEOUT)err = ERR_OK;
                        continue;
                }
 
@@ -315,7 +422,7 @@ int cmd_do_run_nc(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
             if(buff_index == BUF_SIZE - 3) {
                 flush = TRUE;
             }
-        // All other character ends nc
+        // All other character stops nc
         } else {
                ncStop = TRUE;
                flush = TRUE;
@@ -323,26 +430,36 @@ int cmd_do_run_nc(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
 
         if(flush)
         {
-            netconn_write(newconn, in_buffer, buff_index, NETCONN_COPY);
-
+            if(!udp)
+               {
+                netconn_write(newconn, in_buffer, buff_index, NETCONN_COPY);
+               }
+               else
+               {
+                       payload = netbuf_alloc(localData,buff_index);
+                       if(payload != NULL)
+                       {
+                               netbuf_take(localData,in_buffer,buff_index);
+                               netbuf_len(localData) = buff_index;
+                               if((err = netconn_send(newconn, localData)) != ERR_OK)break;
+                       }
+                       else
+                       {
+                               err = ERR_MEM;
+                               break;
+                       }
+               }
             // Reset variables
             buff_index = 0;
             flush = FALSE;
         }
        }
-#if FILE_DBG
-       rpp_sci_printf((const char *) "newconn - close\r\n");
-#endif
-
-       //netconn_disconnect(newconn);
-       netconn_close(newconn);
-       if(netconn != NULL)netconn_delete(netconn);
+       if(udp && localData != NULL)netbuf_delete(localData);
+       if(remoteData != NULL)netbuf_delete(remoteData);
+       if(!udp)netconn_close(newconn);
        netconn_delete(newconn);
-       vSemaphoreDelete(rpp_eth_dataArrived);
 
-       rpp_eth_dataArrived = NULL;
-
-    return SUCCESS;
+    return err;
 }
 
 #endif /* DOCGEN */
@@ -437,7 +554,7 @@ cmd_des_t const cmd_des_nc={
     "   --> nc 192.168.247.15 80\n"
     "   \n"
     "   --> nc -d 192.168.247.2 1025\n",
-    CMD_HANDLER(cmd_do_run_nc), (void *)&cmd_list_lwip
+    CMD_HANDLER(cmd_do_init_nc), (void *)&cmd_list_lwip
 };
 
 /** List of commands for lwip, defined as external */
index f2d544abd49ed3bc2a35909ecb06fb9b9061d066..b8ad7f20e753d74162dedc17080e590bd8349c0f 100644 (file)
@@ -8,6 +8,17 @@
 #ifndef CMD_LWIP_H_
 #define CMD_LWIP_H_
 
+/* nc return values */
+#define BAD_IP_ADDR     -21
+#define BAD_PORT_NO     -22
+#define BAD_OPTION      -23
+#define ERR_NETCONN_NEW -30
+#define ERR_BINDING     -31
+#define ERR_CONN_ACCEPT -32
+#define ERR_CONNECTING  -33
+#define ERR_SENDING     -34
+#define ERR_RECEIVING   -35
+
 #include "cmdproc.h"
 
 extern cmd_des_t const *cmd_list_lwip[];
diff --git a/rpp-lib b/rpp-lib
index 55a68b0bfc4b7cb0b0ec6a92759cb6076b4724e5..3cca591de8291f94ccc5471abfc6c35daa538528 160000 (submodule)
--- a/rpp-lib
+++ b/rpp-lib
@@ -1 +1 @@
-Subproject commit 55a68b0bfc4b7cb0b0ec6a92759cb6076b4724e5
+Subproject commit 3cca591de8291f94ccc5471abfc6c35daa538528