From: Pekka Riikonen Date: Wed, 11 Jul 2007 14:09:57 +0000 (+0000) Subject: Added SILC Timer API. X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=182f1698206a2227616be30691591eea1274cd2b Added SILC Timer API. --- diff --git a/CHANGES.RUNTIME b/CHANGES.RUNTIME index a2c6bdb9..017e2288 100644 --- a/CHANGES.RUNTIME +++ b/CHANGES.RUNTIME @@ -1,3 +1,8 @@ +Wed Jul 11 17:10:11 EEST 2007 Pekka Riikonen + + * Added SILC Timer API to lib/silcutil/silctimer.[ch], + silctimer_i.h, tests/test_silctimer.c. + Tue Jul 10 20:02:04 EEST 2007 Pekka Riikonen * Added queue entry free list to thread pool instead of diff --git a/TODO b/TODO index f32a2234..c02ecdce 100644 --- a/TODO +++ b/TODO @@ -54,6 +54,8 @@ lib/silccore lib/silcclient, The Client Library ================================== + o UDP SILC connection support to SILC server + o Giving WHOIS for nick that doesn't exist should remove any same named entries from the client cache. @@ -161,9 +163,9 @@ Runtime library, lib/silcutil/ o Structured log messages to Log API. Allows machine readable log messages. Would allow sending of any kind of data in a log message. - o Base64 to an own API + o Base64 to an own API (***DONE) - o Timer API + o Timer API (***DONE) o Add builtin SOCKS and HTTP Proxy support, well the SOCKS at least. SILC currently supports SOCKS4 and SOCKS5 but it needs to be compiled @@ -480,6 +482,9 @@ lib/silcserver o Library must have support for SERVICE command. + o Both UDP and TCP support for incoming connecetions. Maintaining long + term UDP sessions. + o The server must be able to run behind NAT device. This means that Server ID must be based on public IP instead of private IP. diff --git a/includes/silc.h.in b/includes/silc.h.in index 10040866..a5773c29 100644 --- a/includes/silc.h.in +++ b/includes/silc.h.in @@ -231,6 +231,7 @@ extern "C" { /* More SILC util library includes */ #include "silctime.h" +#include "silctimer.h" #include "silccond.h" #include "silcthread.h" #include "silcschedule.h" diff --git a/lib/silcutil/Makefile.ad b/lib/silcutil/Makefile.ad index e7e540d8..09bc5bcd 100644 --- a/lib/silcutil/Makefile.ad +++ b/lib/silcutil/Makefile.ad @@ -66,6 +66,7 @@ libsilcutil_la_SOURCES = \ silcfsm.c \ silcasync.c \ silctime.c \ + silctimer.c \ silcmime.c \ silcstack.c \ silcsnprintf.c \ @@ -107,6 +108,8 @@ include_HEADERS = \ silcfsm.h \ silcfsm_i.h \ silctime.h \ + silctimer.h \ + silctimer_i.h \ silcmime.h \ silcmime_i.h \ silcasync.h \ diff --git a/lib/silcutil/silctimer.c b/lib/silcutil/silctimer.c new file mode 100644 index 00000000..90371274 --- /dev/null +++ b/lib/silcutil/silctimer.c @@ -0,0 +1,127 @@ +/* + + silctimer.c + + Author: Pekka Riikonen + + Copyright (C) 2007 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +#include "silc.h" + +/* Start timer */ + +void silc_timer_start(SilcTimer timer) +{ + struct timeval curtime; + + memset(timer, 0, sizeof(timer)); + + silc_gettimeofday(&curtime); + timer->start_sec = curtime.tv_sec; + timer->start_usec = curtime.tv_usec; + + timer->running = TRUE; +} + +/* Stop timer */ + +void silc_timer_stop(SilcTimer timer) +{ + struct timeval curtime; + + silc_gettimeofday(&curtime); + + if (curtime.tv_usec < timer->start_usec) { + curtime.tv_sec--; + curtime.tv_usec += 1000000L; + } + timer->timer_sec = curtime.tv_sec - timer->start_sec; + timer->timer_usec = curtime.tv_usec - timer->start_usec; + + timer->running = FALSE; +} + +/* Continue stopped timer */ + +void silc_timer_continue(SilcTimer timer) +{ + struct timeval curtime; + + if (timer->running) + return; + + silc_gettimeofday(&curtime); + + if (curtime.tv_usec < timer->timer_usec) { + curtime.tv_sec--; + curtime.tv_usec += 1000000L; + } + timer->start_sec = curtime.tv_sec - timer->timer_sec; + timer->start_usec = curtime.tv_usec - timer->timer_usec; + + timer->running = TRUE; +} + +/* Return timer value */ + +void silc_timer_value(SilcTimer timer, + SilcUInt64 *elapsed_time_seconds, + SilcUInt32 *elapsed_time_microseconds) +{ + if (timer->running) { + struct timeval curtime; + + silc_gettimeofday(&curtime); + + if (curtime.tv_usec < timer->start_usec) { + curtime.tv_sec--; + curtime.tv_usec += 1000000L; + } + timer->timer_sec = curtime.tv_sec - timer->start_sec; + timer->timer_usec = curtime.tv_usec - timer->start_usec; + } + + if (elapsed_time_seconds) + *elapsed_time_seconds = timer->timer_sec; + if (elapsed_time_microseconds) + *elapsed_time_microseconds = timer->timer_usec; +} + +/* Return timer value */ + +void silc_timer_value_time(SilcTimer timer, SilcTime ret_time) +{ + SilcUInt64 sec; + SilcUInt32 usec; + + silc_timer_value(timer, &sec, &usec); + sec = ((timer->start_sec + sec) * (SilcUInt64)1000); + sec += ((timer->start_usec + usec) / 1000); + silc_time_value(sec, ret_time); +} + +/* Return start time */ + +void silc_timer_start_time(SilcTimer timer, SilcTime ret_start_time) +{ + silc_time_value(((timer->start_sec * (SilcUInt64)1000) + + (timer->start_usec / 1000)), ret_start_time); +} + +/* Return TRUE if timer is running */ + +SilcBool silc_timer_is_running(SilcTimer timer) +{ + return timer->running; +} diff --git a/lib/silcutil/silctimer.h b/lib/silcutil/silctimer.h new file mode 100644 index 00000000..79c57750 --- /dev/null +++ b/lib/silcutil/silctimer.h @@ -0,0 +1,157 @@ +/* + + silctimer.h + + Author: Pekka Riikonen + + Copyright (C) 2007 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +/****h* silcutil/SILC Timer Interface + * + * SILC Timer interface provides a simple way to measure time intervals. + * The SILC Timer works with microsecond resolution, depending on platform. + * + ***/ + +#ifndef SILCTIMER_H +#define SILCTIMER_H + +/****s* silcutil/SilcTimerAPI/SilcTimer + * + * NAME + * + * typedef struct SilcTimerObject *SilcTimer, SilcTimerStruct; + * + * DESCRIPTION + * + * The timer context. The context is given as argument to all + * silc_timer_* functions. + * + ***/ +typedef struct SilcTimerObject *SilcTimer, SilcTimerStruct; + +/****f* silcutil/SilcTimerAPI/silc_timer_start + * + * SYNOPSIS + * + * SilcBool silc_timer_start(SilcTimer timer); + * + * DESCRIPTION + * + * Starts the timer. If the timer is already running this will reset + * the timer and continue. + * + * EXAMPLE + * + * SilcTimerStruct timer; + * + * silc_timer_start(&timer); + * ... time passes ... + * silc_timer_stop(&timer); + * silc_timer_value(&timer, &elapsed_sec, &elapsed_usec); + * + ***/ +void silc_timer_start(SilcTimer timer); + +/****f* silcutil/SilcTimerAPI/silc_timer_stop + * + * SYNOPSIS + * + * void silc_timer_stop(SilcTimer timer); + * + * DESCRIPTION + * + * Stop the timer. The elapsed time can be retrieved by calling the + * silc_timer_value function. + * + ***/ +void silc_timer_stop(SilcTimer timer); + +/****f* silcutil/SilcTimerAPI/silc_timer_continue + * + * SYNOPSIS + * + * void silc_timer_continue(SilcTimer timer); + * + * DESCRIPTION + * + * Continue stopped timer. If timer is running already this does nothing. + * + ***/ +void silc_timer_continue(SilcTimer timer); + +/****f* silcutil/SilcTimerAPI/silc_timer_value + * + * SYNOPSIS + * + * void silc_timer_value(SilcTimer timer, + * SilcUInt64 *elapsed_time_seconds, + * SilcUInt32 *elapsed_time_microseconds); + * + * DESCRIPTION + * + * Returns either the current value or the end value of the timer. If the + * timer is currently running this returns the currently elapsed time. If + * the timer is stopped this returns the cumulative elapsed time. + * + ***/ +void silc_timer_value(SilcTimer timer, + SilcUInt64 *elapsed_time_seconds, + SilcUInt32 *elapsed_time_microseconds); + +/****f* silcutil/SilcTimerAPI/silc_timer_value_time + * + * SYNOPSIS + * + * void silc_timer_value_time(SilcTimer timer, SilcTime ret_time); + * + * DESCRIPTION + * + * Same as silc_timer_value but returns the elapsed time to `ret_time' + * SilcTime structure as absolute date and time. This is useful if the + * returned time needs to be converted into some other format such as + * time and date strings. + * + ***/ +void silc_timer_value_time(SilcTimer timer, SilcTime ret_time); + +/****f* silcutil/SilcTimerAPI/silc_timer_start_time + * + * SYNOPSIS + * + * void silc_timer_start_time(SilcTimer timer, SilcTime ret_start_time); + * + * DESCRIPTION + * + * Returns the timer's start time into `ret_start_time' SilcTime structure. + * + ***/ +void silc_timer_start_time(SilcTimer timer, SilcTime ret_start_time); + +/****f* silcutil/SilcTimerAPI/silc_timer_is_running + * + * SYNOPSIS + * + * SilcBool silc_timer_is_running(SilcTimer timer); + * + * DESCRIPTION + * + * Returns TRUE if the timer is currently running, FALSE otherwise. + * + ***/ +SilcBool silc_timer_is_running(SilcTimer timer); + +#include "silctimer_i.h" + +#endif /* SILCTIMER_H */ diff --git a/lib/silcutil/silctimer_i.h b/lib/silcutil/silctimer_i.h new file mode 100644 index 00000000..06656e90 --- /dev/null +++ b/lib/silcutil/silctimer_i.h @@ -0,0 +1,35 @@ +/* + + silctimer_i.h + + Author: Pekka Riikonen + + Copyright (C) 2007 Pekka Riikonen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +#ifndef SILCTIMER_I_H +#define SILCTIMER_I_H + +#ifndef SILCTIMER_H +#error "Do not include this header directly" +#endif + +struct SilcTimerObject { + SilcUInt64 start_sec; /* Start seconds */ + SilcUInt32 start_usec; /* Start microseconds */ + SilcUInt64 timer_sec; /* Timer seconds */ + SilcUInt32 timer_usec; /* Timer microseconds */ + unsigned int running : 1; /* Set when timer is running */ +}; + +#endif /* SILCTIMER_I_H */ diff --git a/lib/silcutil/tests/Makefile.am b/lib/silcutil/tests/Makefile.am index 364092bb..f6654a19 100644 --- a/lib/silcutil/tests/Makefile.am +++ b/lib/silcutil/tests/Makefile.am @@ -21,7 +21,7 @@ bin_PROGRAMS = test_silcstrutil test_silcstringprep test_silchashtable \ test_silclist test_silcfsm test_silcasync test_silcschedule \ test_silcnet test_silcstack test_silcmime test_silcfdstream \ test_silcatomic test_silcmutex test_silctime test_silcthread \ - test_silcdll test_silcenv + test_silcdll test_silcenv test_silctimer test_silcstrutil_SOURCES = test_silcstrutil.c test_silcstringprep_SOURCES = test_silcstringprep.c @@ -40,6 +40,7 @@ test_silctime_SOURCES = test_silctime.c test_silcthread_SOURCES = test_silcthread.c test_silcdll_SOURCES = test_silcdll.c test_silcenv_SOURCES = test_silcenv.c +test_silctimer_SOURCES = test_silctimer.c LIBS = $(SILC_COMMON_LIBS) LDADD = -L.. -L../.. -lsilc diff --git a/lib/silcutil/tests/test_silctime.c b/lib/silcutil/tests/test_silctime.c index bcfa713e..6e65550b 100644 --- a/lib/silcutil/tests/test_silctime.c +++ b/lib/silcutil/tests/test_silctime.c @@ -6,6 +6,7 @@ int main(int argc, char **argv) { SilcBool success = FALSE; SilcTimeStruct curtime; + unsigned char ts[32]; if (argc > 1 && !strcmp(argv[1], "-d")) { silc_log_debug(TRUE); @@ -29,6 +30,11 @@ int main(int argc, char **argv) SILC_LOG_DEBUG(("utc_east : %d", curtime.utc_east)); SILC_LOG_DEBUG(("dst : %d", curtime.dst)); + silc_time_universal_string(&curtime, ts, sizeof(ts)); + SILC_LOG_DEBUG(("Universal: %s", ts)); + silc_time_generalized_string(&curtime, ts, sizeof(ts)); + SILC_LOG_DEBUG(("Generaliz: %s", ts)); + success = TRUE; err: diff --git a/lib/silcutil/tests/test_silctimer.c b/lib/silcutil/tests/test_silctimer.c new file mode 100644 index 00000000..f7354d3b --- /dev/null +++ b/lib/silcutil/tests/test_silctimer.c @@ -0,0 +1,90 @@ +/* SilcTimer tests */ + +#include "silc.h" + +SilcSchedule schedule; +SilcTimerStruct timer; +SilcBool success = FALSE; + +SILC_TASK_CALLBACK(check); + +SILC_TASK_CALLBACK(restart) +{ + SILC_LOG_DEBUG(("Timer is %s", silc_timer_is_running(&timer) ? + "running" : "stopped")); + SILC_LOG_DEBUG(("Restart timer")); + silc_timer_continue(&timer); + silc_schedule_task_add_timeout(schedule, check, NULL, 1, 0); +} + +SILC_TASK_CALLBACK(check) +{ + SilcUInt64 sec; + SilcUInt32 usec; + SilcTimeStruct t, st; + char ts[32]; + + SILC_LOG_DEBUG(("Timer is %s", silc_timer_is_running(&timer) ? + "running" : "stopped")); + + silc_timer_value(&timer, &sec, &usec); + SILC_LOG_DEBUG(("Timer elapsed: %llu secs, %lu usec", sec, usec)); + + if (sec == 5) { + SILC_LOG_DEBUG(("Stop timer")); + silc_timer_stop(&timer); + + silc_timer_value(&timer, &sec, &usec); + SILC_LOG_DEBUG(("Timer elapsed: %llu secs, %lu usec", sec, usec)); + + silc_timer_start_time(&timer, &st); + silc_timer_value_time(&timer, &t); + silc_time_universal_string(&st, ts, sizeof(ts)); + SILC_LOG_DEBUG(("Start time: %s", ts)); + silc_time_universal_string(&t, ts, sizeof(ts)); + SILC_LOG_DEBUG(("End time: %s", ts)); + + success = TRUE; + silc_schedule_stop(schedule); + return; + } + + if (sec == 2) { + SILC_LOG_DEBUG(("Stopping timer, sleep 3 seconds")); + silc_timer_stop(&timer); + silc_schedule_task_add_timeout(schedule, restart, NULL, 3, 0); + return; + } + + silc_schedule_task_add_timeout(schedule, check, NULL, 0, 500000); +} + + +int main(int argc, char **argv) +{ + if (argc > 1 && !strcmp(argv[1], "-d")) { + silc_log_debug(TRUE); + silc_log_quick(TRUE); + silc_log_debug_hexdump(TRUE); + silc_log_set_debug_string("*timer*"); + } + + schedule = silc_schedule_init(0, NULL, NULL); + if (!schedule) + goto err; + + SILC_LOG_DEBUG(("Start timer")); + silc_timer_start(&timer); + + silc_schedule_task_add_timeout(schedule, check, NULL, 1, 0); + + silc_schedule(schedule); + + silc_schedule_uninit(schedule); + + err: + SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE")); + fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE"); + + return success; +}