1
0
Fork 0
forked from nuttx/nuttx-update

Networking: setsockopt() fails when setting timeouts to values less that an 100 msec. That is because the timeout is limited to stops of 1 decisecond and because the conversion of structure timeval was truncating the microsecond remainder. The utility net_timeval2dsec now accespts and option to determin how it handles the remainder: truncate, discarding the remainder, use the remainder to round to the closed decisecond value, or use any non-zero remainder to the next larger whole decisecond value.

For the setsockopt() case, it will always use the final option.  This means that a time of zero (i.e., not timeout) can only occur if the value zero was explicated provided to setsockopt().
This commit is contained in:
Gregory Nutt 2015-05-29 07:17:15 -06:00
parent 0595d54470
commit 5337176cdf
3 changed files with 45 additions and 11 deletions

View file

@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/setsockopt.c
*
* Copyright (C) 2007, 2008, 2011-2012, 2014 Gregory Nutt. All rights
* Copyright (C) 2007, 2008, 2011-2012, 2014-2015 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
@ -173,19 +173,22 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
case SO_RCVTIMEO:
case SO_SNDTIMEO:
{
FAR struct timeval *tv = (FAR struct timeval *)value;
socktimeo_t timeo;
/* Verify that option is the size of an 'struct timeval'. */
if (value_len != sizeof(struct timeval))
if (tv == NULL || value_len != sizeof(struct timeval))
{
err = EINVAL;
goto errout;
}
/* Get the timeout value */
/* Get the timeout value. Any microsecond remainder will be
* force to the next larger, whole decisecond value.
*/
timeo = (socktimeo_t)net_timeval2dsec((struct timeval *)value);
timeo = (socktimeo_t)net_timeval2dsec(tv, TV2DS_CEIL);
/* Save the timeout value */

View file

@ -1,7 +1,7 @@
/****************************************************************************
* net/utils/net_timeval2dsec.c
*
* Copyright (C) 2007, 2008, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007, 2008, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -57,7 +57,8 @@
* save new timeout values.
*
* Parameters:
* tv The struct timeval to convert
* tv - The struct timeval to convert
* remainder - Determines how to handler the microsecond remainder
*
* Returned Value:
* The converted value
@ -66,7 +67,26 @@
*
****************************************************************************/
unsigned int net_timeval2dsec(struct timeval *tv)
unsigned int net_timeval2dsec(FAR struct timeval *tv,
enum tv2ds_remainder_e remainder)
{
return (unsigned int)(tv->tv_sec * DSEC_PER_SEC + tv->tv_usec / USEC_PER_DSEC);
unsigned long adjust = 0;
switch (remainder)
{
default:
case TV2DS_TRUNC: /* Truncate microsecond remainder */
break;
case TV2DS_ROUND: /* Round to the nearest full decisecond */
adjust = (USEC_PER_DSEC / 2);
break;
case TV2DS_CEIL: /* Force to next larger full decisecond */
adjust = (USEC_PER_DSEC - 1);
break;
}
return (unsigned int)(tv->tv_sec * DSEC_PER_SEC +
(tv->tv_usec + adjust) / USEC_PER_DSEC);
}

View file

@ -1,7 +1,7 @@
/****************************************************************************
* net/utils/utils.h
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -51,6 +51,15 @@
* Public Types
****************************************************************************/
/* These values control the behavior of net_timeval2desc */
enum tv2ds_remainder_e
{
TV2DS_TRUNC = 0, /* Truncate microsecond remainder */
TV2DS_ROUND, /* Round to the nearest full decisecond */
TV2DS_CEIL /* Force to next larger full decisecond */
};
/****************************************************************************
* Public Data
****************************************************************************/
@ -128,7 +137,8 @@ unsigned int net_dsec2tick(int dsec);
* save new timeout values.
*
* Parameters:
* tv The struct timeval to convert
* tv - The struct timeval to convert
* remainder - Determines how to handler the microsecond remainder
*
* Returned Value:
* The converted value
@ -137,7 +147,8 @@ unsigned int net_dsec2tick(int dsec);
*
****************************************************************************/
unsigned int net_timeval2dsec(FAR struct timeval *tv);
unsigned int net_timeval2dsec(FAR struct timeval *tv,
enum tv2ds_remainder_e remainder);
/****************************************************************************
* Function: net_ipv6_pref2mask