#include "rpp/rpp.h"
#include "lwip/api.h" //netconn
+#include "lwip/udp.h"
#define INTERFACE_INSTANCE_NUMBER 0
#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;
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;
}
if(buff_index == BUF_SIZE - 3) {
flush = TRUE;
}
- // All other character ends nc
+ // All other character stops nc
} else {
ncStop = TRUE;
flush = TRUE;
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 */
" --> 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 */