changed stio_gettime() to use clock_gettime() if available.

enhanced connect timeout handling
This commit is contained in:
hyung-hwan 2016-01-30 19:08:28 +00:00
parent 9b901e924c
commit 15652f70e4
12 changed files with 122 additions and 65 deletions

2
stio/configure vendored
View File

@ -17509,7 +17509,7 @@ _ACEOF
fi
done
for ac_func in timegm timelocal localtime_r gettimeofday settimeofday
for ac_func in timegm timelocal localtime_r gettimeofday settimeofday clock_gettime clock_settime
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

View File

@ -154,7 +154,7 @@ AC_CHECK_FUNCS([wctype iswctype wctrans towctrans])
AC_CHECK_FUNCS([isblank iswblank])
AC_CHECK_FUNCS([lseek64 stat64 fstat64 lstat64 ftruncate64 readdir64 dirfd])
AC_CHECK_FUNCS([lstat fchmod fsync ftruncate])
AC_CHECK_FUNCS([timegm timelocal localtime_r gettimeofday settimeofday])
AC_CHECK_FUNCS([timegm timelocal localtime_r gettimeofday settimeofday clock_gettime clock_settime])
AC_CHECK_FUNCS([utime utimes futimes lutimes futimens])
AC_CHECK_FUNCS([sysconf prctl fdopendir setrlimit getrlimit getpgid getpgrp])
AC_CHECK_FUNCS([backtrace backtrace_symbols])

View File

@ -161,7 +161,7 @@ int main ()
memset (&sin, 0, STIO_SIZEOF(sin));
sin.sin_family = AF_INET;
memset (&tcp_make, 0, STIO_SIZEOF(&tcp_make));
memcpy (&tcp_make.addr, &sin, STIO_SIZEOF(sin));
tcp_make.on_sent = tcp_on_sent;
tcp_make.on_recv = tcp_on_recv;
@ -172,23 +172,28 @@ int main ()
goto oops;
}
{
struct sockaddr_in* p;
p = (struct sockaddr_in*)&tcp_conn.addr;
p->sin_family = AF_INET;
p->sin_port = htons(9999);
inet_pton (p->sin_family, "127.0.0.1", &p->sin_addr);
tcp_conn.on_connected = tcp_on_connected;
tcp_conn.on_disconnected = tcp_on_disconnected;
//tcp_conn.on_failure = .... (error code? etc???) or on_connect to access success or failure??? what is better??
}
memset (&sin, 0, STIO_SIZEOF(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(9999);
//inet_pton (sin.sin_family, "192.168.1.1", &sin.sin_addr);
inet_pton (sin.sin_family, "127.0.0.1", &sin.sin_addr);
memset (&tcp_conn, 0, STIO_SIZEOF(tcp_conn));
memcpy (&tcp_conn.addr, &sin, STIO_SIZEOF(sin));
tcp_conn.timeout.sec = 5;
tcp_conn.on_connected = tcp_on_connected;
tcp_conn.on_disconnected = tcp_on_disconnected;
if (stio_dev_tcp_connect (tcp[0], &tcp_conn) <= -1)
{
printf ("stio_dev_tcp_connect() failed....\n");
goto oops;
}
memset (&sin, 0, STIO_SIZEOF(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(1234);
memset (&tcp_make, 0, STIO_SIZEOF(&tcp_make));
memcpy (&tcp_make.addr, &sin, STIO_SIZEOF(sin));
tcp_make.on_sent = tcp_on_sent;
tcp_make.on_recv = tcp_on_recv;

View File

@ -69,6 +69,12 @@
/* Define to 1 if you have the `ceilq' function. */
#undef HAVE_CEILQ
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* Define to 1 if you have the `clock_settime' function. */
#undef HAVE_CLOCK_SETTIME
/* Define to 1 if you have the `connect' function. */
#undef HAVE_CONNECT

View File

@ -42,8 +42,7 @@
#define STIO_MEMMOVE(dst,src,count) memmove(dst,src,count)
#define STIO_ASSERT assert
typedef struct stio_tmrjob_t stio_tmrjob_t;
typedef stio_size_t stio_tmridx_t;
typedef void (*stio_tmr_handler_t) (
stio_t* stio,
@ -137,9 +136,10 @@ void stio_cleartmrjobs (
stio_t* stio
);
stio_size_t stio_firetmrjobs (
void stio_firetmrjobs (
stio_t* stio,
const stio_ntime_t* tm
const stio_ntime_t* tm,
stio_size_t* firecnt
);
int stio_gettmrtmout (

View File

@ -62,6 +62,7 @@ static int tcp_make (stio_dev_t* dev, void* ctx)
tcp->on_sent = arg->on_sent;
tcp->on_recv = arg->on_recv;
tcp->tmridx_connect = STIO_TMRIDX_INVALID;
return 0;
oops:
@ -88,11 +89,17 @@ static void tcp_kill (stio_dev_t* dev)
{
stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
if (tcp->state | (STIO_DEV_TCP_ACCEPTED | STIO_DEV_TCP_CONNECTED))
if (tcp->state & (STIO_DEV_TCP_ACCEPTED | STIO_DEV_TCP_CONNECTED))
{
if (tcp->on_disconnected) tcp->on_disconnected (tcp);
}
if (tcp->tmridx_connect != STIO_TMRIDX_INVALID)
{
stio_deltmrjob (dev->stio, tcp->tmridx_connect);
STIO_ASSERT (tcp->tmridx_connect == STIO_TMRIDX_INVALID);
}
if (tcp->sck != STIO_SCKHND_INVALID)
{
stio_closeasyncsck (tcp->sck);
@ -156,12 +163,16 @@ static void tmr_connect_handle (stio_t* stio, const stio_ntime_t* now, stio_tmrj
* after it gets connected. the timer job doesn't need to be deleted
* when it gets connected for this check here */
if (tcp->on_disconnected) tcp->on_disconnected (tcp);
tcp->state &= ~STIO_DEV_TCP_CONNECTING;
stio_dev_tcp_kill (tcp);
}
}
static void tmr_connect_update (stio_t* stio, stio_tmridx_t old_index, stio_tmridx_t new_index, stio_tmrjob_t* job)
{
stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)job->ctx;
tcp->tmridx_connect = new_index;
}
@ -217,7 +228,6 @@ static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
#else
/* the socket is already non-blocking */
x = connect (tcp->sck, sa, sl);
if (x == -1)
{
@ -231,11 +241,17 @@ static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
{
STIO_MEMSET (&tmrjob, 0, STIO_SIZEOF(tmrjob));
tmrjob.ctx = tcp;
tmrjob.when = conn->timeout;
stio_gettime (&tmrjob.when);
stio_addtime (&tmrjob.when, &conn->timeout, &tmrjob.when);
tmrjob.handler = tmr_connect_handle;
tmrjob.updater = tmr_connect_update;
if (stio_instmrjob (tcp->stio, &tmrjob) == STIO_TMRIDX_INVALID)
STIO_ASSERT (tcp->tmridx_connect == STIO_TMRIDX_INVALID);
tcp->tmridx_connect = stio_instmrjob (tcp->stio, &tmrjob);
if (tcp->tmridx_connect == STIO_TMRIDX_INVALID)
{
stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_UPD, STIO_DEV_EVENT_IN);
/* event manipulation failure can't be handled properly. so ignore it */
return -1;
}
}
@ -350,13 +366,18 @@ printf ("TCP READY...%p\n", dev);
tcp->state &= ~STIO_DEV_TCP_CONNECTING;
tcp->state |= STIO_DEV_TCP_CONNECTED;
if (stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_UPD, STIO_DEV_EVENT_IN) <= -1)
if (stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_UPD, STIO_DEV_EVENT_IN) <= -1)
{
printf ("CAANOT MANIPULTE EVENT ...\n");
return -1;
}
if (tcp->tmridx_connect != STIO_TMRIDX_INVALID)
{
stio_deltmrjob (tcp->stio, tcp->tmridx_connect);
STIO_ASSERT (tcp->tmridx_connect == STIO_TMRIDX_INVALID);
}
if (tcp->on_connected (tcp) <= -1)
{
printf ("ON_CONNECTE HANDLER RETURNEF FAILURE...\n");
@ -410,6 +431,8 @@ printf ("TCP READY...%p\n", dev);
clitcp->peer = peer;
clitcp->parent = tcp;
/* inherit some event handlers from the parent.
* you can still change them inside the on_connected handler */
clitcp->on_connected = tcp->on_connected;
@ -417,6 +440,7 @@ printf ("TCP READY...%p\n", dev);
clitcp->on_sent = tcp->on_sent;
clitcp->on_recv = tcp->on_recv;
clitcp->tmridx_connect = STIO_TMRIDX_INVALID;
if (clitcp->on_connected (clitcp) <= -1) stio_dev_tcp_kill (clitcp);
return 0; /* success but don't invoke on_recv() */
}

View File

@ -62,7 +62,8 @@ struct stio_dev_tcp_t
stio_sckhnd_t sck;
unsigned int state;
/* bitwised-ORed of #stio_dev_tcp_state_t enumerators */
int state;
/* peer address - valid if one of the followings is set:
* STIO_DEV_TCP_ACCEPTED
@ -81,6 +82,8 @@ struct stio_dev_tcp_t
stio_dev_tcp_on_disconnected_t on_disconnected;
stio_dev_tcp_on_recv_t on_recv;
stio_dev_tcp_on_sent_t on_sent;
stio_tmridx_t tmridx_connect;
};
typedef struct stio_dev_tcp_make_t stio_dev_tcp_make_t;

View File

@ -54,7 +54,7 @@
#define EPOCH_DIFF_SECS ((stio_intptr_t)EPOCH_DIFF_DAYS*24*60*60)
#endif
int stio_gettime (stio_ntime_t* t)
void stio_gettime (stio_ntime_t* t)
{
#if defined(_WIN32)
SYSTEMTIME st;
@ -67,7 +67,7 @@ int stio_gettime (stio_ntime_t* t)
*/
GetSystemTime (&st);
if (SystemTimeToFileTime (&st, &ft) == FALSE) return -1;
SystemTimeToFileTime (&st, &ft); /* this must not fail */
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
@ -76,11 +76,8 @@ int stio_gettime (stio_ntime_t* t)
t->sec = (li.QuadPart / (STIO_NSECS_PER_SEC / 100)) - EPOCH_DIFF_SECS;
t->nsec = (li.QuadPart % (STIO_NSECS_PER_SEC / 100)) * 100;
return 0;
#elif defined(__OS2__)
APIRET rc;
DATETIME dt;
stio_btime_t bt;
@ -89,8 +86,8 @@ int stio_gettime (stio_ntime_t* t)
* Maybe, resolution too low as it returns values
* in seconds. */
rc = DosGetDateTime (&dt);
if (rc != NO_ERROR) return -1;
DosGetDateTime (&dt);
/* DosGetDateTime() never fails. it always returns NO_ERROR */
bt.year = dt.year - STIO_BTIME_YEAR_BASE;
bt.mon = dt.month - 1;
@ -101,8 +98,15 @@ int stio_gettime (stio_ntime_t* t)
/*bt.msec = dt.hundredths * 10;*/
bt.isdst = -1; /* determine dst for me */
if (stio_timelocal (&bt, t) <= -1) return -1;
t->nsec = STIO_MSEC_TO_NSEC(dt.hundredths * 10);
if (stio_timelocal (&bt, t) <= -1)
{
t->sec = time (STIO_NULL);
t->nsec = 0;
}
else
{
t->nsec = STIO_MSEC_TO_NSEC(dt.hundredths * 10);
}
return 0;
#elif defined(__DOS__)
@ -123,41 +127,51 @@ int stio_gettime (stio_ntime_t* t)
/*bt.msec = dt.hsecond * 10; */
bt.isdst = -1; /* determine dst for me */
if (stio_timelocal (&bt, t) <= -1) return -1;
t->nsec = STIO_MSEC_TO_NSEC(dt.hsecond * 10);
return 0;
if (stio_timelocal (&bt, t) <= -1)
{
t->sec = time (STIO_NULL);
t->nsec = 0;
}
else
{
t->nsec = STIO_MSEC_TO_NSEC(dt.hsecond * 10);
}
#elif defined(macintosh)
unsigned long tv;
GetDateTime (&tv);
t->sec = tv;
tv->nsec = 0;
return 0;
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
struct timespec ts;
if (clock_gettime (CLOCK_REALTIME, &ts) == -1 && errno == EINVAL)
{
#if defined(HAVE_GETTIMEOFDAY)
struct timeval tv;
gettimeofday (&tv, STIO_NULL);
t->sec = tv.tv_sec;
t->nsec = STIO_USEC_TO_NSEC(tv.tv_usec);
#else
t->sec = time (STIO_NULL);
t->nsec = 0;
#endif
}
t->sec = ts.tv_sec;
t->nsec = ts.tv_nsec;
#elif defined(HAVE_GETTIMEOFDAY)
struct timeval tv;
int n;
/* TODO: consider using clock_gettime() if it's avaialble.. -lrt may be needed */
n = gettimeofday (&tv, STIO_NULL);
if (n == -1)
{
/* TODO: set stio->errnum using errno... */
return -1;
}
gettimeofday (&tv, STIO_NULL);
t->sec = tv.tv_sec;
t->nsec = STIO_USEC_TO_NSEC(tv.tv_usec);
return 0;
#else
t->sec = STIO_TIME (STIO_NULL);
t->sec = time (STIO_NULL);
t->nsec = 0;
return 0;
#endif
}

View File

@ -106,7 +106,7 @@ extern "C" {
/**
* The stio_gettime() function gets the current time.
*/
STIO_EXPORT int stio_gettime (
STIO_EXPORT void stio_gettime (
stio_ntime_t* nt
);

View File

@ -172,35 +172,35 @@ stio_tmridx_t stio_updtmrjob (stio_t* stio, stio_size_t index, const stio_tmrjob
return YOUNGER_THAN(job, &item)? sift_up (stio, index, 0): sift_down (stio, index, 0);
}
stio_size_t stio_firetmrjobs (stio_t* stio, const stio_ntime_t* tm)
void stio_firetmrjobs (stio_t* stio, const stio_ntime_t* tm, stio_size_t* firecnt)
{
stio_ntime_t now;
stio_tmrjob_t event;
stio_size_t fire_count = 0;
stio_size_t count = 0;
/* if the current time is not specified, get it from the system */
if (tm) now = *tm;
else if (stio_gettime (&now) <= -1) return -1;
else stio_gettime (&now);
while (stio->tmr.size > 0)
{
if (stio_cmptime(&stio->tmr.jobs[0].when, &now) > 0) break;
event = stio->tmr.jobs[0];
stio_deltmrjob (stio, 0); /* remove the registered event structure */
stio_deltmrjob (stio, 0); /* remove the registered job */
fire_count++;
event.handler (stio, &now, &event); /* then fire the event */
count++;
event.handler (stio, &now, &event); /* then fire the job */
}
return fire_count;
if (firecnt) *firecnt = count;
}
int stio_gettmrtmout (stio_t* stio, const stio_ntime_t* tm, stio_ntime_t* tmout)
{
stio_ntime_t now;
/* time-out can't be calculated when there's no event scheduled */
/* time-out can't be calculated when there's no job scheduled */
if (stio->tmr.size <= 0)
{
stio->errnum = STIO_ENOENT;
@ -209,7 +209,7 @@ int stio_gettmrtmout (stio_t* stio, const stio_ntime_t* tm, stio_ntime_t* tmout)
/* if the current time is not specified, get it from the system */
if (tm) now = *tm;
else if (stio_gettime (&now) <= -1) return -1;
else stio_gettime (&now);
stio_subtime (&stio->tmr.jobs[0].when, &now, tmout);
if (tmout->sec < 0) stio_cleartime (tmout);

View File

@ -227,15 +227,17 @@ int stio_exec (stio_t* stio)
/*if (!stio->dev.head) return 0;*/
/* execute the scheduled jobs before checking devices with the
* multiplexer. the scheduled jobs can safely destroy the devices */
stio_firetmrjobs (stio, STIO_NULL, STIO_NULL);
if (stio_gettmrtmout (stio, STIO_NULL, &tmout) <= -1)
{
/* defaults to 1 second if timeout can't be acquired */
tmout.sec = 1;
tmout.sec = 1; /* TODO: make the default timeout configurable */
tmout.nsec = 0;
}
#if defined(_WIN32)
/*
if (GetQueuedCompletionStatusEx (stio->iocp, stio->ovls, STIO_COUNTOF(stio->ovls), &nentries, timeout, FALSE) == FALSE)

View File

@ -29,6 +29,9 @@
#include <stio-cmn.h>
typedef struct stio_tmrjob_t stio_tmrjob_t;
typedef stio_size_t stio_tmridx_t;
struct stio_sckadr_t
{
int family;