libc lwip recv MSG_PEEK doesn't behave as specified

Johannes Kliemann kliemann at componolit.com
Tue Jun 19 20:14:07 CEST 2018


Hi Christian,

> I've to admit that we never considered about supporting this (rather
> exotic) feature.
> 
> On Tue, Jun 19, 2018 at 03:52:16PM +0200, Johannes Kliemann wrote:
>> Yet this doesn't seem to be the case (at least with lwip). I implemented
>> a test [1] that creates a connection from the test http client and
>> subsequently calls recv(sock, buf, 1, MSG_PEEK) which always should
>> yield 'G' into the buffer (the first character of the GET request). Yet
>> the output looks as follows:
>>
>>> [init -> test-http_clnt] got IP address 10.0.2.15
>>> [init -> test-http_clnt] Create new socket ...
>>> [init -> test-http_clnt] Connect to server ...
>>> [init -> test-http_clnt] Send request...
>>> [init -> test-libc_msg_peek] peek: G
>>> [init -> test-libc_msg_peek] peek: E
>>> [init -> test-libc_msg_peek] peek: T
>>> [init -> test-libc_msg_peek] peek:  
>>> [init -> test-libc_msg_peek] peek: /
>> (this is just an extract but you get the point)
>>
>> The problem is that this doesn't only account to the recv call but also
>> any further read call will miss the first "peeked" bytes which
>> completely defeats the purpose of MSG_PEEK.
>>
>> According to the lwip_legacy port MSG_PEEK should be supported since
>> 2007 and I'm not sure why it should stay broken such a long time.
>>
>>> 2007-06-30 Frédéric Bernon
>>> * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions.
>>
>> As far as I can see I have used it correctly so I'm not sure why it
>> isn't working. You can view the code at [1] and run the test with
>> run/libc_msg_peek.
> 
> The reason for this behavior can be found in the libc_lwip library,
> which (as my statement above hints) does not translate the 'flags'
> parameter, which seems to be incompatibly defined in lwip and libc:
> 
>   grep -rn define.*MSG_PEEK $(./tool/ports/current lwip_legacy)/include $(./tool/ports/current libc)/include
>   .../contrib/lwip_legacy-7f5610426ed8c4c64903136122d9ba58836cdc89/include/lwip_legacy/lwip/sockets.h:157:#define MSG_PEEK       0x01    /* Peeks at an incoming message */
>   .../contrib/libc-5a5de5baab6e3ce23f24012a7604abf070fa990c/include/libc/sys/socket.h:450:#define	MSG_PEEK	0x2		/* peek at incoming message */

Oh, I only grepped inside lwip so I didn't find the conflict with libc.

> The current migration to VFS-based socket operations does not include
> any support for recv flags too. Is this feature essential for your use
> case?

While the MSG_PEEK isn't absolutely necessary to me some other flags
are. We're trying to build a TCP/IP unwrapper/wrapper and transmit OSI
layer 5 with a Terminal session in between. Yet the asynchronous
semantics of the Terminal session and the synchronous ones of the socket
API aren't exactly easy to combine. Currently I use MSG_DONTWAIT to
prevent blocking in read operations and polling to check if data is
available (I wasn't able to stop select if necessary and recv with
MSG_PEEK obviously wasn't working).

So having at least MSG_DONTWAIT would be quite helpful. But I think the
general problem is the API. Having a native asynchronous TCP or IP
session with a native TCP/IP stack would be the best case but I assume
this won't happen soon. But also an asynchronous (or at least more
compatible) approach using libc would already be useful (and potentially
resolve the need for any recv flags ;) ).

So currently I need some flags but I would happily switch to a generally
better approach if there is one.

Regards,
Johannes



More information about the users mailing list