Menu Sign In Contact FAQ
Banner
Welcome to our forums

LWIP and netconn API

This is not aviation, although the product might be GA related

For “getting onto the internet” there are three LWIP APIs: raw, netconn and sockets. Most people use sockets. I have written a simple web server with netconn but have drawn a blank when it comes to receiving streaming data (say 2MB). Single packets are ok and one can do a great deal with those, but for file upload it needs to be done properly. Transmit is also ok; netconn_write, etc. I have asked on every imaginable embedded forum, put it up on freelancer.com (that works well for a lot of stuff) but have drawn a blank.

Maybe somebody here knows somebody? This is the basic idea, and the loop is rubbish.

Administrator
Shoreham EGKA, United Kingdom

Your code looks absolutely nothing like the API shown on https://lwip.fandom.com/wiki/Netconn_receive or https://doc.ecoscentric.com/ref/lwip-api-sequential-netconn-recv.html and if those are the API that you use, I don’t understand how it even compiles. You seem to confuse with sockets… The return value is not an amount of bytes read, but an error code. You don’t pass it a netbuf, you get a netbuf from it that it has created. Etc.

The second of these links contains an example that you can use as starting point.

Note that according to these documentations, accessing a netbuf is not at all as straightforward as you seem to think it is. The netbuf may be non-contiguous memory, so you need to use netbuf_first and netbuf_next to access the chunks. Or use netbuf_copy, but then you lose the whole zero-copy design…

So very roughly, as I understand things:

struct netbuf *buf;
err_t err; 
while((err = netconn_recv(conn, buf)) == ERR_OK) {
  do
  {
    char *data;
    int len;
    netbuf_first(buf);
    netbuf_data(buf, data, len);
    debug_thread_printf("chunk size=%3d", len);
  } while (netbuf_next(buf) >= 0);
  debug_thread_printf("end of netbuf");
}

The above follows the example linked to, but I must admit the example looks wrong to me, it passes a “struct netbuf*” where a “struct netbuf**” is expected. Here’s something that looks better to me:

struct netbuf *buf = NULL;
err_t err; 
while((err = netconn_recv(conn, &buf)) == ERR_OK) {
  do
  {
    char *data = NULL;
    int len = -1;
    netbuf_first(buf);
    netbuf_data(buf, data, len);
    debug_thread_printf("chunk size=%3d", len);
  } while (netbuf_next(buf) >= 0);
  netbuf_delete(buf); /* I'm not sure if one is supposed to do that
                       * or if netbuf_recv will reuse buf if a valid one is passed
                       *  the history of the lwIP 1.3.2 interface suggests rather the former
                       *  but maybe that's one the changes for the 1.4.0 interface.
                       *  Need to find a good documentation... */
  debug_thread_printf("end of netbuf");
}
Last Edited by lionel at 04 Aug 12:07
ELLX

I am all ears for ideas but I think the various example code works only for one packet, or works only if the incoming data is slow (so all you need is always in the first pbuf). But I don’t really understand it. There is too much complexity in this. Double indirection… why? I just want a solution.

The system doesn’t use zero copy anyway. There is data copy at low level, although it can be eliminated (but again those who know how are not talking because they did it commercially). Not an issue; I am getting 250kbytes/sec on file downloads, which is perfect. I know where the exact bottleneck is, too (a compromise with RTOS task scheduling).

I will send you details on tg.

Administrator
Shoreham EGKA, United Kingdom

lionel wrote:

/* I’m not sure if one is supposed to do that

Other examples in other docs suggest that this netbuf_delete() is necessary.

ELLX

Corrected version, for people that read that in X days/months/years:

struct netbuf *buf = NULL;
err_t err; 
while((err = netconn_recv(conn, &buf)) == ERR_OK) {
  netbuf_first(buf);
  do
  {
    char *data = NULL;
    int len = -1;
    netbuf_data(buf, data, len);
    debug_thread_printf("chunk size=%3d", len);
  } while (netbuf_next(buf) >= 0);
  netbuf_delete(buf);
  debug_thread_printf("end of netbuf");
}
ELLX

Yeah – Lionel cracked it. So many failed. A few I tried on freelancer.com could not work it out. One LWIP specialist who runs a forum on LWIP told me to not bother.

It’s quite a simple interface after all.

Administrator
Shoreham EGKA, United Kingdom

Just to complete the above, this is the sequence:

Set up with
netconn_new(NETCONN_TCP);

Specify the port (80 for HTTP; other values work equally and it is good to test with them because some browsers modify their HTTP behaviour if port==80)
netconn_bind(conn, NULL, 80);

Put the connection into LISTEN state (this one is blocking)
netconn_listen(conn);

This tells you if some data has arrived
netconn_accept(conn, &newconn);

Get 1st packet
netconn_recv(conn, &inbuf);

Get the address and size if this first packet (and extract whatever header data from it; there is an assumption, with complicated but reasonable conditions, that all you want will be in this packet)
netbuf_data(inbuf, (void**)&buf, &buflen);

Then you use a loop like this to get the rest of the data


// Now write the rest of the data to the file
while((err = netconn_recv(conn, &nbuf)) == ERR_OK)
{
char *data = NULL;
uint16_t len = 0;

netbuf_first(nbuf);
do
{
netbuf_data(nbuf, (void**)&data, &len);
if ( f_write(&fp, data, len, &actual_length) != FR_OK )
{
wr_fail=true;
break;
}
total_written+=len;
}
while ( (netbuf_next(nbuf) >= 0) && (len==actual_length) );
netbuf_delete(nbuf);
}
}
f_close(&fp);
}

// Return status to client

if ( !found || wr_fail || (total_written!=filesize) )
{
netconn_write(conn, EDIT_WRITE_BAD, strlen((char*)EDIT_WRITE_BAD), NETCONN_COPY);
}
else
{
netconn_write(conn, EDIT_WRITE_GOOD, strlen((char*)EDIT_WRITE_GOOD), NETCONN_COPY);
}

// Close connection
netconn_close(conn);
}

Obviously the code can be simplified if the 1st packet has no special meaning.

Unfortunately I found a funny issue with the text edit box: it strips off CR chars. So a CRLF becomes just an LF. This appears to be standard TEXTAREA behaviour. I may need a custom JS implementation.

Administrator
Shoreham EGKA, United Kingdom

When I read LWIP I thought that some new airport in Northern Macedonia was opened.

LDZA LDVA, Croatia
8 Posts
Sign in to add your message

Back to Top