updates.
[silc.git] / lib / silccore / silcsockconn.c
index ebc2812e9a62caf1646f28ea9c1ecd809ad8ad34..5111980b8bb2e6a447554ea75276f5bce3c9716a 100644 (file)
 
 #include "silcincludes.h"
 
+/* Heartbeat context */
+struct SilcSocketConnectionHB {
+  uint32 heartbeat;
+  SilcSocketConnectionHBCb hb_callback;
+  void *hb_context;
+  void *timeout_queue;
+  SilcTask hb_task;
+  SilcSocketConnection sock;
+};
+
 /* Allocates a new socket connection object. The allocated object is 
    returned to the new_socket argument. */
 
@@ -39,13 +49,17 @@ void silc_socket_alloc(int sock, SilcSocketType type, void *user_data,
   (*new_socket)->flags = 0;
   (*new_socket)->inbuf = NULL;
   (*new_socket)->outbuf = NULL;
+  (*new_socket)->users++;
 }
 
 /* Free's the Socket connection object. */
 
 void silc_socket_free(SilcSocketConnection sock)
 {
-  if (sock) {
+  sock->users--;
+  SILC_LOG_DEBUG(("Socket %p refcnt %d->%d", sock, sock->users + 1,
+                 sock->users));
+  if (sock->users < 1) {
     silc_buffer_free(sock->inbuf);
     silc_buffer_free(sock->outbuf);
     if (sock->hb) {
@@ -59,6 +73,16 @@ void silc_socket_free(SilcSocketConnection sock)
   }
 }
 
+/* Increase the reference counter. */
+
+SilcSocketConnection silc_socket_dup(SilcSocketConnection sock)
+{
+  sock->users++;
+  SILC_LOG_DEBUG(("Socket %p refcnt %d->%d", sock, sock->users - 1,
+                 sock->users));
+  return sock;
+}
+
 /* Internal timeout callback to perform heartbeat */
 
 SILC_TASK_CALLBACK(silc_socket_heartbeat)
@@ -87,21 +111,27 @@ SILC_TASK_CALLBACK(silc_socket_heartbeat)
    `timeout_queue' is the application's scheduler timeout queue. */
 
 void silc_socket_set_heartbeat(SilcSocketConnection sock, 
-                              unsigned long heartbeat,
+                              uint32 heartbeat,
                               void *hb_context,
                               SilcSocketConnectionHBCb hb_callback,
                               void *timeout_queue)
 {
-  SilcSocketConnectionHB hb = silc_calloc(1, sizeof(*hb));
-
-  hb->heartbeat = heartbeat;
-  hb->hb_context = hb_context;
-  hb->hb_callback = hb_callback;
-  hb->timeout_queue = timeout_queue;
-  hb->sock = sock;
-  hb->hb_task = silc_task_register(timeout_queue, sock->sock, 
-                                  silc_socket_heartbeat,
-                                  (void *)hb, heartbeat, 0,
-                                  SILC_TASK_TIMEOUT,
-                                  SILC_TASK_PRI_LOW);
+
+  if (sock->hb) {
+    silc_task_unregister(sock->hb->timeout_queue, sock->hb->hb_task);
+    silc_free(sock->hb->hb_context);
+    silc_free(sock->hb);
+  }
+
+  sock->hb = silc_calloc(1, sizeof(*sock->hb));
+  sock->hb->heartbeat = heartbeat;
+  sock->hb->hb_context = hb_context;
+  sock->hb->hb_callback = hb_callback;
+  sock->hb->timeout_queue = timeout_queue;
+  sock->hb->sock = sock;
+  sock->hb->hb_task = silc_task_register(timeout_queue, sock->sock,
+                                         silc_socket_heartbeat,
+                                         (void *)sock->hb, heartbeat, 0,
+                                         SILC_TASK_TIMEOUT,
+                                         SILC_TASK_PRI_LOW);
 }