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