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:
parent
0595d54470
commit
5337176cdf
3 changed files with 45 additions and 11 deletions
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue