Added SILC Timer API.
authorPekka Riikonen <priikone@silcnet.org>
Wed, 11 Jul 2007 14:09:57 +0000 (14:09 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 11 Jul 2007 14:09:57 +0000 (14:09 +0000)
CHANGES.RUNTIME
TODO
includes/silc.h.in
lib/silcutil/Makefile.ad
lib/silcutil/silctimer.c [new file with mode: 0644]
lib/silcutil/silctimer.h [new file with mode: 0644]
lib/silcutil/silctimer_i.h [new file with mode: 0644]
lib/silcutil/tests/Makefile.am
lib/silcutil/tests/test_silctime.c
lib/silcutil/tests/test_silctimer.c [new file with mode: 0644]

index a2c6bdb920b7b7f0279c5cef80fbd13feeafa6b9..017e2288acc455168daecb6e0aac19280f408dcb 100644 (file)
@@ -1,3 +1,8 @@
+Wed Jul 11 17:10:11 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+
+       * 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 <priikone@silcnet.org>
 
        * Added queue entry free list to thread pool instead of
diff --git a/TODO b/TODO
index f32a223417ad946f64ea7a5c6e28868a88600148..c02ecdce6b8591c7965e10f6e4632d8f6aeb21f3 100644 (file)
--- 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.
 
index 10040866ad42b8f8b314a53b388110704682e2cf..a5773c297f78b60f26284ecda9d81fc064152e9e 100644 (file)
@@ -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"
index e7e540d81f86a50233a79822304f5414c93eccb9..09bc5bcd1542164705d200ab1073ce8dd3d8e8a8 100644 (file)
@@ -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 (file)
index 0000000..9037127
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+
+  silctimer.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  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 (file)
index 0000000..79c5775
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+
+  silctimer.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  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 (file)
index 0000000..06656e9
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+
+  silctimer_i.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  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 */
index 364092bbe2ef0da5c7de674af923c15cde7a3f7d..f6654a199c531cc9b3ea267000a09dcdc3c15b8b 100644 (file)
@@ -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
index bcfa713ebd44e839aafd8f978d19a9d060023858..6e65550bc58b1fba16ba93259daff6332ef4ddd6 100644 (file)
@@ -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 (file)
index 0000000..f7354d3
--- /dev/null
@@ -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;
+}