Tobias
Tobias

Reputation: 1

lwip stack / modified echo server example -> sending data

I'm using an Arty A7 board and have implemented the Echo Server example on it. It works without any problems. I then modified the code to send back other data. It works, but only via the receive callback!

Now I want to send data to the computer at the touch of a button, using tcp_write! The button is read in the main loop and runs the function transfer_data. Here I would like to send data via tcp_write! I actually thought that it should work like this, because it also works in the receive callback. So far, however, I have not been able to get this to work. I get "-16" => Illegal argument (ERR_ARG) as an error code. Here is the modified code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
 
#include "lwip/err.h"
#include "lwip/tcp.h"
#if defined (__arm__) || defined (__aarch64__)
#include "xil_printf.h"
#endif
 
//************************************************************
//************************************************************
 
 
int transfer_data() {
 
    err_t err;
    struct tcp_pcb *tpcb;
 
    xil_printf("transfer data\n\r");
    err = tcp_write(tpcb, "data", 4, 1);
    xil_printf("%d\n\r", err);
    return 0;
}
 
 
//************************************************************
//************************************************************
 
void print_app_header()
{
#if (LWIP_IPV6==0)
    xil_printf("\n\r\n\r-----lwIP TCP echo server ------\n\r");
#else
    xil_printf("\n\r\n\r-----lwIPv6 TCP echo server ------\n\r");
#endif
    xil_printf("TCP packets sent to port 6001 will be echoed back\n\r");
}
 
//************************************************************
//************************************************************
 
err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    /* do not read the packet if we are not in ESTABLISHED state */
    if (!p) {
        tcp_close(tpcb);
        tcp_recv(tpcb, NULL);
        return ERR_OK;
    }
 
    /* indicate that the packet has been received */
    tcp_recved(tpcb, p->len);
 
    /* echo back the payload */
    /* in this case, we assume that the payload is < TCP_SND_BUF */
    /* change: we receive "Hello" and send back "World" */
 
    if (tcp_sndbuf(tpcb) > p->len) {
        //err = tcp_write(tpcb, p->payload, p->len, 1);
        xil_printf("data received: %s (%d)\r\n", p->payload, strlen(p->payload));
        //xil_printf("Total data received: %s (%d)\r\n", p->payload, p->len);
        //xil_printf("data received: %s (%d)\r\n", cmd, strlen(cmd));
        char tdata[128];
        memset(tdata, 0, sizeof(tdata));
        char buf[128];
        memset(buf, 0, sizeof(buf));
        memcpy(buf, p->payload, p->len);
        char * cmd = strtok(buf, "\r\n");
        xil_printf("cmd received: %s (%d)\r\n", cmd, strlen(cmd));
 
        while(cmd != NULL) {
            if(strcmp(cmd, "Hello") == 0) {
                strcat(tdata,"World");
                xil_printf("World\n\r");
            }
 
            else if(strcmp(cmd, "TEST") == 0) {
                strcat(tdata,"0123456789");
                xil_printf("Test\n\r");
            }
                // look for next part
 
        cmd = strtok(NULL, "\r\n");
        }
 
        free (cmd);
 
        if(strlen(tdata) > 0) {
            err = tcp_write(tpcb, &tdata, strlen(tdata), 1);
        }
 
    }
    else
        xil_printf("no space in tcp_sndbuf\n\r");
 
    /* free the received pbuf */
    pbuf_free(p);
 
    return ERR_OK;
}
 
//************************************************************
//************************************************************
// active for debugging
err_t sent_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err){
        xil_printf("data were sent\n\r");
 
        return ERR_OK;
    }
 
//************************************************************
//************************************************************
 
err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    static int connection = 1;
 
    xil_printf("Incoming connection: %d.%d.%d.%d - port: %d \r\n",
                           (u8)(newpcb->remote_ip.addr),
                           (u8)(newpcb->remote_ip.addr >> 8),
                           (u8)(newpcb->remote_ip.addr >> 16),
                           (u8)(newpcb->remote_ip.addr >> 24),
                           newpcb->remote_port);
 
    /* set the receive callback for this connection */
    // tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)
    tcp_recv(newpcb, recv_callback);
 
 
    //set the sent callback for this connection
    //info = void tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent)
    tcp_sent(newpcb, sent_callback);
 
 
    /* just use an integer number indicating the connection id as the
       callback argument */
    tcp_arg(newpcb, (void*)(UINTPTR)connection);
 
    /* increment for subsequent accepted connections */
    connection++;
 
    return ERR_OK;
}
 
//************************************************************
//************************************************************
 
int start_application()
{
    struct tcp_pcb *pcb;
    err_t err;
    unsigned port = 7;
 
    /* create new TCP PCB structure */
    pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
    if (!pcb) {
        xil_printf("Error creating PCB. Out of Memory\n\r");
        return -1;
    }
 
    /* bind to specified @port */
    err = tcp_bind(pcb, IP_ANY_TYPE, port);
    if (err != ERR_OK) {
        xil_printf("Unable to bind to port %d: err = %d\n\r", port, err);
        return -2;
    }
 
    /* we do not need any arguments to callback functions */
    tcp_arg(pcb, NULL);
 
    /* listen for connections */
    pcb = tcp_listen(pcb);
    if (!pcb) {
        xil_printf("Out of memory while tcp_listen\n\r");
        return -3;
    }
 
    /* specify callback to use for incoming connections */
    tcp_accept(pcb, accept_callback);
 
    xil_printf("TCP echo server started @ port %d\n\r", port);
 
    return 0;
}

Because of the error message I think that no memory was allocated for sending data. Or I made a mistake when assigning pcb! I have tried to allocate memory and re-establish a connection only for sending! There are only a few applicable examples in the lwip documentation. I have therefore searched for similar contributions, but have not found a suitable solution!

Perhaps the community can point me in the right direction. I would be very grateful for your help!

Upvotes: 0

Views: 929

Answers (0)

Related Questions