updates.
[silc.git] / lib / silccore / silcprotocol.c
index dfdf0321af317e18190fc7c3ce263f1520ada964..9eb50898d1fdf4b1ec6351afa8e3d18b3dd96403 100644 (file)
 /*
  * Created: Tue Nov 25 19:25:33 GMT+0200 1997
  */
-/*
- * $Id$
- * $Log$
- * Revision 1.1.1.1  2000/06/27 11:36:55  priikone
- *     Importet from internal CVS/Added Log headers.
- *
- *
- */
+/* $Id$ */
 
 #include "silcincludes.h"
 #include "silcprotocol.h"
 
+/* Dynamically registered protocols */
+SilcProtocolObject *silc_protocol_list = NULL;
+
+/* Dynamically registers new protocol. The protocol is added into protocol
+   list and can be unregistered with silc_protocol_unregister. */
+
+void silc_protocol_register(SilcProtocolType type,
+                           SilcProtocolCallback callback)
+{
+  SilcProtocolObject *new;
+
+  new = silc_calloc(1, sizeof(*new));
+  new->type = type;
+  new->callback = callback;
+
+  if (!silc_protocol_list)
+    silc_protocol_list = new;
+  else {
+    new->next = silc_protocol_list;
+    silc_protocol_list = new;
+  }
+}
+
+/* Unregisters protocol. The unregistering is done by both protocol type
+   and the protocol callback. */
+
+void silc_protocol_unregister(SilcProtocolType type,
+                              SilcProtocolCallback callback)
+{
+  SilcProtocolObject *protocol, *prev;
+
+  protocol = silc_protocol_list;
+  prev = NULL;
+  while (protocol && (protocol->type != type && 
+                      protocol->callback != callback)) {
+    prev = protocol;
+    protocol = protocol->next;
+  }
+
+  if (protocol) {
+    if (prev)
+      prev->next = protocol->next;
+    else
+      silc_protocol_list = protocol->next;
+
+    silc_free(protocol);
+  }
+}
+
 /* Allocates a new protocol object. The new allocated and initialized 
    protocol is returned to the new_protocol argument. The argument context
    is the context to be sent as argument for the protocol. The callback
 void silc_protocol_alloc(SilcProtocolType type, SilcProtocol *new_protocol,
                         void *context, SilcProtocolFinalCallback callback)
 {
-  int i;
+  SilcProtocolObject *protocol;
 
   SILC_LOG_DEBUG(("Allocating new protocol type %d", type));
 
-  for (i = 0; silc_protocol_list[i].callback; i++)
-    if (silc_protocol_list[i].type == type)
-      break;
+  protocol = silc_protocol_list;
+  while (protocol && protocol->type != type)
+    protocol = protocol->next;
 
-  if (!silc_protocol_list[i].callback) {
+  if (!protocol) {
     SILC_LOG_ERROR(("Requested protocol does not exists"));
+    *new_protocol = NULL;
     return;
   }
 
   *new_protocol = silc_calloc(1, sizeof(**new_protocol));
-  if (*new_protocol == NULL) {
-    SILC_LOG_ERROR(("Cannot allocate new protocol object"));
-    return;
-  }
-
-  (*new_protocol)->protocol = (SilcProtocolObject *)&silc_protocol_list[i];
+  (*new_protocol)->protocol = protocol;
   (*new_protocol)->state = SILC_PROTOCOL_STATE_UNKNOWN;
   (*new_protocol)->context = context;
   (*new_protocol)->execute = silc_protocol_execute;
@@ -106,3 +144,14 @@ void silc_protocol_execute_final(void *qptr, int type,
 
   protocol->final_callback(qptr, 0, context, fd);
 }
+
+/* Cancels the execution of the next state of the protocol. */
+
+void silc_protocol_cancel(void *qptr, void *context)
+{
+  SilcProtocol protocol = (SilcProtocol)context;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  silc_task_unregister_by_callback(qptr, protocol->protocol->callback);
+}