2002-07-03 12:06:54 -07:00
|
|
|
/*=========================================================================*\
|
|
|
|
* Timeout management functions
|
2003-06-26 11:47:49 -07:00
|
|
|
* LuaSocket toolkit
|
2002-07-03 12:06:54 -07:00
|
|
|
\*=========================================================================*/
|
2019-02-25 15:01:04 -08:00
|
|
|
#include "luasocket.h"
|
2003-05-24 18:54:13 -07:00
|
|
|
|
2003-06-09 11:23:40 -07:00
|
|
|
#include "auxiliar.h"
|
|
|
|
#include "timeout.h"
|
2002-07-03 12:06:54 -07:00
|
|
|
|
2019-02-25 15:01:04 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <float.h>
|
|
|
|
|
2004-06-16 17:18:48 -07:00
|
|
|
#ifdef _WIN32
|
2002-07-03 12:06:54 -07:00
|
|
|
#include <windows.h>
|
|
|
|
#else
|
2004-01-16 16:17:46 -08:00
|
|
|
#include <time.h>
|
2003-11-26 16:30:54 -08:00
|
|
|
#include <sys/time.h>
|
2002-07-03 12:06:54 -07:00
|
|
|
#endif
|
|
|
|
|
2004-06-14 23:24:00 -07:00
|
|
|
/* min and max macros */
|
|
|
|
#ifndef MIN
|
|
|
|
#define MIN(x, y) ((x) < (y) ? x : y)
|
|
|
|
#endif
|
|
|
|
#ifndef MAX
|
|
|
|
#define MAX(x, y) ((x) > (y) ? x : y)
|
|
|
|
#endif
|
|
|
|
|
2002-07-03 12:06:54 -07:00
|
|
|
/*=========================================================================*\
|
|
|
|
* Internal function prototypes
|
|
|
|
\*=========================================================================*/
|
2005-10-06 21:40:59 -07:00
|
|
|
static int timeout_lua_gettime(lua_State *L);
|
|
|
|
static int timeout_lua_sleep(lua_State *L);
|
2002-07-03 12:06:54 -07:00
|
|
|
|
2011-07-04 15:31:14 -07:00
|
|
|
static luaL_Reg func[] = {
|
2005-10-06 21:40:59 -07:00
|
|
|
{ "gettime", timeout_lua_gettime },
|
|
|
|
{ "sleep", timeout_lua_sleep },
|
2003-05-24 18:54:13 -07:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2002-07-03 12:06:54 -07:00
|
|
|
/*=========================================================================*\
|
|
|
|
* Exported functions.
|
|
|
|
\*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-05-24 18:54:13 -07:00
|
|
|
* Initialize structure
|
2002-07-03 12:06:54 -07:00
|
|
|
\*-------------------------------------------------------------------------*/
|
2019-02-27 20:01:16 -08:00
|
|
|
void timeout_init(p_timeout tm, double block, double total) {
|
2003-05-24 18:54:13 -07:00
|
|
|
tm->block = block;
|
|
|
|
tm->total = total;
|
2002-07-03 12:06:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-11-26 16:30:54 -08:00
|
|
|
* Determines how much time we have left for the next system call,
|
2015-08-21 11:39:34 -07:00
|
|
|
* if the previous call was successful
|
2003-11-26 16:30:54 -08:00
|
|
|
* Input
|
|
|
|
* tm: timeout control structure
|
|
|
|
* Returns
|
|
|
|
* the number of ms left or -1 if there is no time limit
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2019-02-27 20:01:16 -08:00
|
|
|
double timeout_get(p_timeout tm) {
|
2004-06-30 20:32:09 -07:00
|
|
|
if (tm->block < 0.0 && tm->total < 0.0) {
|
2003-11-26 16:30:54 -08:00
|
|
|
return -1;
|
2004-06-30 20:32:09 -07:00
|
|
|
} else if (tm->block < 0.0) {
|
2005-10-06 21:40:59 -07:00
|
|
|
double t = tm->total - timeout_gettime() + tm->start;
|
2004-06-30 20:32:09 -07:00
|
|
|
return MAX(t, 0.0);
|
|
|
|
} else if (tm->total < 0.0) {
|
2003-11-26 16:30:54 -08:00
|
|
|
return tm->block;
|
|
|
|
} else {
|
2005-10-06 21:40:59 -07:00
|
|
|
double t = tm->total - timeout_gettime() + tm->start;
|
2004-06-30 20:32:09 -07:00
|
|
|
return MIN(tm->block, MAX(t, 0.0));
|
2003-11-26 16:30:54 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Returns time since start of operation
|
|
|
|
* Input
|
|
|
|
* tm: timeout control structure
|
|
|
|
* Returns
|
|
|
|
* start field of structure
|
2002-07-03 12:06:54 -07:00
|
|
|
\*-------------------------------------------------------------------------*/
|
2019-02-27 20:01:16 -08:00
|
|
|
double timeout_getstart(p_timeout tm) {
|
2003-11-26 16:30:54 -08:00
|
|
|
return tm->start;
|
|
|
|
}
|
2002-07-03 12:06:54 -07:00
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-11-26 16:30:54 -08:00
|
|
|
* Determines how much time we have left for the next system call,
|
|
|
|
* if the previous call was a failure
|
2002-07-03 12:06:54 -07:00
|
|
|
* Input
|
|
|
|
* tm: timeout control structure
|
|
|
|
* Returns
|
|
|
|
* the number of ms left or -1 if there is no time limit
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2019-02-27 20:01:16 -08:00
|
|
|
double timeout_getretry(p_timeout tm) {
|
2004-06-30 20:32:09 -07:00
|
|
|
if (tm->block < 0.0 && tm->total < 0.0) {
|
2002-07-03 12:06:54 -07:00
|
|
|
return -1;
|
2004-06-30 20:32:09 -07:00
|
|
|
} else if (tm->block < 0.0) {
|
2005-10-06 21:40:59 -07:00
|
|
|
double t = tm->total - timeout_gettime() + tm->start;
|
2004-06-30 20:32:09 -07:00
|
|
|
return MAX(t, 0.0);
|
|
|
|
} else if (tm->total < 0.0) {
|
2005-10-06 21:40:59 -07:00
|
|
|
double t = tm->block - timeout_gettime() + tm->start;
|
2004-06-30 20:32:09 -07:00
|
|
|
return MAX(t, 0.0);
|
2003-11-26 16:30:54 -08:00
|
|
|
} else {
|
2005-10-06 21:40:59 -07:00
|
|
|
double t = tm->total - timeout_gettime() + tm->start;
|
2004-06-30 20:32:09 -07:00
|
|
|
return MIN(tm->block, MAX(t, 0.0));
|
2003-11-26 16:30:54 -08:00
|
|
|
}
|
2002-07-03 12:06:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2015-08-21 11:39:34 -07:00
|
|
|
* Marks the operation start time in structure
|
2002-07-03 12:06:54 -07:00
|
|
|
* Input
|
|
|
|
* tm: timeout control structure
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2019-02-27 20:01:16 -08:00
|
|
|
p_timeout timeout_markstart(p_timeout tm) {
|
2005-10-06 21:40:59 -07:00
|
|
|
tm->start = timeout_gettime();
|
2004-01-21 10:40:52 -08:00
|
|
|
return tm;
|
2002-07-03 12:06:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2015-08-21 11:39:34 -07:00
|
|
|
* Gets time in s, relative to January 1, 1970 (UTC)
|
2002-07-03 12:06:54 -07:00
|
|
|
* Returns
|
2004-08-04 13:42:02 -07:00
|
|
|
* time in s.
|
2002-07-03 12:06:54 -07:00
|
|
|
\*-------------------------------------------------------------------------*/
|
2004-06-16 17:18:48 -07:00
|
|
|
#ifdef _WIN32
|
2019-02-27 20:01:16 -08:00
|
|
|
double timeout_gettime(void) {
|
2004-06-30 20:32:09 -07:00
|
|
|
FILETIME ft;
|
2004-08-04 13:42:02 -07:00
|
|
|
double t;
|
2004-06-30 20:32:09 -07:00
|
|
|
GetSystemTimeAsFileTime(&ft);
|
2004-08-04 13:42:02 -07:00
|
|
|
/* Windows file time (time since January 1, 1601 (UTC)) */
|
|
|
|
t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
|
|
|
|
/* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */
|
|
|
|
return (t - 11644473600.0);
|
2002-07-03 12:06:54 -07:00
|
|
|
}
|
|
|
|
#else
|
2019-02-27 20:01:16 -08:00
|
|
|
double timeout_gettime(void) {
|
2004-06-20 15:19:54 -07:00
|
|
|
struct timeval v;
|
2004-06-21 21:49:57 -07:00
|
|
|
gettimeofday(&v, (struct timezone *) NULL);
|
2004-08-04 13:42:02 -07:00
|
|
|
/* Unix Epoch time (time since January 1, 1970 (UTC)) */
|
2004-06-30 20:32:09 -07:00
|
|
|
return v.tv_sec + v.tv_usec/1.0e6;
|
2002-07-03 12:06:54 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Initializes module
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2019-02-27 20:01:16 -08:00
|
|
|
int timeout_open(lua_State *L) {
|
2013-05-29 01:56:56 -07:00
|
|
|
luaL_setfuncs(L, func, 0);
|
2004-02-04 06:29:11 -08:00
|
|
|
return 0;
|
2003-05-24 18:54:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Sets timeout values for IO operations
|
|
|
|
* Lua Input: base, time [, mode]
|
|
|
|
* time: time out value in seconds
|
|
|
|
* mode: "b" for block timeout, "t" for total timeout. (default: b)
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2019-02-27 20:01:16 -08:00
|
|
|
int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
|
2004-06-30 20:32:09 -07:00
|
|
|
double t = luaL_optnumber(L, 2, -1);
|
2003-05-24 18:54:13 -07:00
|
|
|
const char *mode = luaL_optstring(L, 3, "b");
|
|
|
|
switch (*mode) {
|
|
|
|
case 'b':
|
2015-08-21 11:39:34 -07:00
|
|
|
tm->block = t;
|
2003-05-24 18:54:13 -07:00
|
|
|
break;
|
|
|
|
case 'r': case 't':
|
2004-06-30 20:32:09 -07:00
|
|
|
tm->total = t;
|
2003-05-24 18:54:13 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
luaL_argcheck(L, 0, 3, "invalid timeout mode");
|
|
|
|
break;
|
|
|
|
}
|
2004-03-21 23:45:07 -08:00
|
|
|
lua_pushnumber(L, 1);
|
|
|
|
return 1;
|
2002-07-03 12:06:54 -07:00
|
|
|
}
|
|
|
|
|
2016-03-04 10:36:32 -08:00
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Gets timeout values for IO operations
|
|
|
|
* Lua Output: block, total
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2019-02-27 20:01:16 -08:00
|
|
|
int timeout_meth_gettimeout(lua_State *L, p_timeout tm) {
|
2016-03-04 10:36:32 -08:00
|
|
|
lua_pushnumber(L, tm->block);
|
|
|
|
lua_pushnumber(L, tm->total);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2002-07-03 12:06:54 -07:00
|
|
|
/*=========================================================================*\
|
|
|
|
* Test support functions
|
|
|
|
\*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Returns the time the system has been up, in secconds.
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2005-10-06 21:40:59 -07:00
|
|
|
static int timeout_lua_gettime(lua_State *L)
|
2002-07-03 12:06:54 -07:00
|
|
|
{
|
2005-10-06 21:40:59 -07:00
|
|
|
lua_pushnumber(L, timeout_gettime());
|
2002-07-03 12:06:54 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Sleep for n seconds.
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2009-05-27 02:31:38 -07:00
|
|
|
#ifdef _WIN32
|
2019-02-27 20:01:16 -08:00
|
|
|
int timeout_lua_sleep(lua_State *L)
|
2002-07-03 12:06:54 -07:00
|
|
|
{
|
2003-03-20 15:11:25 -08:00
|
|
|
double n = luaL_checknumber(L, 1);
|
2009-05-27 02:31:38 -07:00
|
|
|
if (n < 0.0) n = 0.0;
|
|
|
|
if (n < DBL_MAX/1000.0) n *= 1000.0;
|
|
|
|
if (n > INT_MAX) n = INT_MAX;
|
|
|
|
Sleep((int)n);
|
|
|
|
return 0;
|
|
|
|
}
|
2002-07-03 12:06:54 -07:00
|
|
|
#else
|
2019-02-27 20:01:16 -08:00
|
|
|
int timeout_lua_sleep(lua_State *L)
|
2009-05-27 02:31:38 -07:00
|
|
|
{
|
|
|
|
double n = luaL_checknumber(L, 1);
|
2004-06-20 15:19:54 -07:00
|
|
|
struct timespec t, r;
|
2009-05-27 02:31:38 -07:00
|
|
|
if (n < 0.0) n = 0.0;
|
|
|
|
if (n > INT_MAX) n = INT_MAX;
|
2004-06-20 15:19:54 -07:00
|
|
|
t.tv_sec = (int) n;
|
|
|
|
n -= t.tv_sec;
|
2004-07-15 23:48:48 -07:00
|
|
|
t.tv_nsec = (int) (n * 1000000000);
|
|
|
|
if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
|
2004-08-04 13:51:57 -07:00
|
|
|
while (nanosleep(&t, &r) != 0) {
|
|
|
|
t.tv_sec = r.tv_sec;
|
|
|
|
t.tv_nsec = r.tv_nsec;
|
|
|
|
}
|
2002-07-03 12:06:54 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2009-05-27 02:31:38 -07:00
|
|
|
#endif
|