diff --git a/stio/configure b/stio/configure index 360bb97..4705708 100755 --- a/stio/configure +++ b/stio/configure @@ -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" diff --git a/stio/configure.ac b/stio/configure.ac index 43f0bcb..80d5bc2 100644 --- a/stio/configure.ac +++ b/stio/configure.ac @@ -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]) diff --git a/stio/lib/main.c b/stio/lib/main.c index 0c3768f..fa44220 100644 --- a/stio/lib/main.c +++ b/stio/lib/main.c @@ -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; diff --git a/stio/lib/stio-cfg.h.in b/stio/lib/stio-cfg.h.in index 9796f35..0c09dbe 100644 --- a/stio/lib/stio-cfg.h.in +++ b/stio/lib/stio-cfg.h.in @@ -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 diff --git a/stio/lib/stio-prv.h b/stio/lib/stio-prv.h index fa9db51..f33cb38 100644 --- a/stio/lib/stio-prv.h +++ b/stio/lib/stio-prv.h @@ -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 ( diff --git a/stio/lib/stio-tcp.c b/stio/lib/stio-tcp.c index 04b6a0a..03e2390 100644 --- a/stio/lib/stio-tcp.c +++ b/stio/lib/stio-tcp.c @@ -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() */ } diff --git a/stio/lib/stio-tcp.h b/stio/lib/stio-tcp.h index 35b8757..10b3fb1 100644 --- a/stio/lib/stio-tcp.h +++ b/stio/lib/stio-tcp.h @@ -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; diff --git a/stio/lib/stio-tim.c b/stio/lib/stio-tim.c index 0c0ec11..dfa014a 100644 --- a/stio/lib/stio-tim.c +++ b/stio/lib/stio-tim.c @@ -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 } diff --git a/stio/lib/stio-tim.h b/stio/lib/stio-tim.h index 66ad7eb..dbbce11 100644 --- a/stio/lib/stio-tim.h +++ b/stio/lib/stio-tim.h @@ -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 ); diff --git a/stio/lib/stio-tmr.c b/stio/lib/stio-tmr.c index 9fcc347..e56f9de 100644 --- a/stio/lib/stio-tmr.c +++ b/stio/lib/stio-tmr.c @@ -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); diff --git a/stio/lib/stio.c b/stio/lib/stio.c index efd11f6..3673a92 100644 --- a/stio/lib/stio.c +++ b/stio/lib/stio.c @@ -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) diff --git a/stio/lib/stio.h b/stio/lib/stio.h index 635f5ca..aa1f4a3 100644 --- a/stio/lib/stio.h +++ b/stio/lib/stio.h @@ -29,6 +29,9 @@ #include +typedef struct stio_tmrjob_t stio_tmrjob_t; +typedef stio_size_t stio_tmridx_t; + struct stio_sckadr_t { int family;