-
Notifications
You must be signed in to change notification settings - Fork 166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG] Buffer/Window properties for incoming connections #1184
Comments
Don't despair, you already gave the solution: set the properties in the parent socket, and every child socket will inherit those properties. On a LAN it happens often that data has been received on a new socket, before you have seen the new socket returned by When I wrote an FTP server, I saw sockets were opened and closed at a high speed. All child sockets inherit the properties of the parent. Other properties like timing can still be set right after For sockets that call Cheers, |
Thanks for your comment @htibosch thoughts? |
As it works now, when you try to change a TCP streaming buffer size after the buffer has already been created, the code will show this logging at debug level:
( most developers only use Now I must admit that I do not check the result of Now I am defending backward compatibility: there will be some projects that succeed to set Therefor, I would rather propose the following, symbolically: if( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( rxStream != NULL ) )
{
- FreeRTOS_debug_printf( ( "Set SO_RCVBUF: buffer already created" ) );
+ FreeRTOS_printf( ( "Set SO_RCVBUF: buffer already created" ) );
return -pdFREERTOS_ERRNO_EINVAL;
}
if( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( rxStream != NULL ) )
{
- FreeRTOS_debug_printf( ( "Set SO_SNDBUF: buffer already created" ) );
+ FreeRTOS_printf( ( "Set SO_SNDBUF: buffer already created" ) );
return -pdFREERTOS_ERRNO_EINVAL;
}
+ if( ( lOptionName == FREERTOS_SO_RCV/SNDBUF ) && ( FreeRTOS_issocketconnected( xSocket ) == pdTRUE ) )
+ {
+ FreeRTOS_printf( ( "Set SO_RCVBUF/SNDBUF: connection already established" ) );
+ /* Print a warning but don't make it a fatal error. */
+ xReturn = 0;
+ } With the proposed change, you would have seen warnings in the logging about the socket being connected, and it does not break existing projects. What do you think? Colleague reviewers? |
@htibosch ,you convinced me. I like the idea of using static BaseType_t prvSockopt_so_buffer( FreeRTOS_Socket_t * pxSocket,
int32_t lOptionName,
const void * pvOptionValue )
{
uint32_t ulNewValue;
BaseType_t xReturn;
+ if( ( FreeRTOS_issocketconnected( xSocket ) == pdTRUE ) )
+ {
+ /* If this socket is the child of a listening socket, the remote client may or may not have already sent
+ * us data. If data was already sent, then pxSocket->u.xTCP.rxStream != NULL and this call will fail.
+ * Warn the user about this inconsistent behavior. */
+ FreeRTOS_printf( ( "Warning: Changing buffer/window properties on a connected socket may fail." ) );
+ }
+
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
xReturn = -pdFREERTOS_ERRNO_EINVAL;
}
else if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
{
- FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
+ FreeRTOS_printf( ( "Set SO_%sBUF: buffer already created\n",
( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
xReturn = -pdFREERTOS_ERRNO_EINVAL;
}
else
{
ulNewValue = *( ( const uint32_t * ) pvOptionValue );
if( lOptionName == FREERTOS_SO_SNDBUF )
{
/* Round up to nearest MSS size */
ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usMSS );
pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
}
else
{
pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
}
xReturn = 0;
}
return xReturn;
} Some comments on the changes above:
what do you think? |
Emil, I agree with all remarks and proposals that you make. |
Yes Hein, I don't see any good place or use for assert here as well. |
… on an already connected socket. Discussed in FreeRTOS#1184 Also changes the error message to using FreeRTOS_printf instead of FreeRTOS_debug_printf to increase the chances of being seen.
… on an already connected socket. Discussed in #1184 (#1188) Also changes the error message to using FreeRTOS_printf instead of FreeRTOS_debug_printf to increase the chances of being seen. Co-authored-by: Emil Popov <[email protected]>
Describe the bug
FreeRTOS+TCP allows us to set/override the TCP stream buffer and window sizes of a socket to values other than the values coming from FreeRTOSIPConfig.h This is accomplished by doing something like this:
The code above works great for outgoing connection. It does not work reliably for incoming connections.
As far as I can tell,
prvSetOptionTCPWindows
fails with-pdFREERTOS_ERRNO_EINVAL
because the call toprvSockopt_so_buffer
detects that the receive buffer is already allocated. The issue happens intermittently.
It appears that, when accept returns a new connected socket, it depends on the remote host whether the code above succeeds or fails. If the remote host manages to send data before the code above executes, then the socket's stream buffers will get allocated and the call to
FreeRTOS_setsockopt
fails. If the code above executes before the first data arrives, thenFreeRTOS_setsockopt
succeeds.I do not have a fix for this and it looks like this may not be a fundamental and unfixable problem.
Workaround
The new socket returned by
FreeRTOS_accept
inherits its buffer/window properties from the listening socket, so one workaround might be to execute the code above on the listening socket.Target
ALL
To Reproduce
Sorry, but I don't have a reliable way of reproducing this. I ran into the issue by running my own http server at very low priority and noticing that every once in a while, the code above would fail. As far as I can tell, it just comes down to timing of when that first piece of data comes from the client that connects.
The text was updated successfully, but these errors were encountered: