updates.
[silc.git] / lib / silccore / silcprotocol.c
1 /*
2
3   silcprotocol.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /*
21  * Created: Tue Nov 25 19:25:33 GMT+0200 1997
22  */
23 /* $Id$ */
24
25 #include "silcincludes.h"
26 #include "silcprotocol.h"
27
28 /* Dynamically registered protocols */
29 SilcProtocolObject *silc_protocol_list = NULL;
30
31 /* Dynamically registers new protocol. The protocol is added into protocol
32    list and can be unregistered with silc_protocol_unregister. */
33
34 void silc_protocol_register(SilcProtocolType type,
35                             SilcProtocolCallback callback)
36 {
37   SilcProtocolObject *new;
38
39   new = silc_calloc(1, sizeof(*new));
40   new->type = type;
41   new->callback = callback;
42
43   if (!silc_protocol_list)
44     silc_protocol_list = new;
45   else {
46     new->next = silc_protocol_list;
47     silc_protocol_list = new;
48   }
49 }
50
51 /* Unregisters protocol. The unregistering is done by both protocol type
52    and the protocol callback. */
53
54 void silc_protocol_unregister(SilcProtocolType type,
55                               SilcProtocolCallback callback)
56 {
57   SilcProtocolObject *protocol, *prev;
58
59   protocol = silc_protocol_list;
60   prev = NULL;
61   while (protocol && (protocol->type != type && 
62                       protocol->callback != callback)) {
63     prev = protocol;
64     protocol = protocol->next;
65   }
66
67   if (protocol) {
68     if (prev)
69       prev->next = protocol->next;
70     else
71       silc_protocol_list = protocol->next;
72
73     silc_free(protocol);
74   }
75 }
76
77 /* Allocates a new protocol object. The new allocated and initialized 
78    protocol is returned to the new_protocol argument. The argument context
79    is the context to be sent as argument for the protocol. The callback
80    argument is the function to be called _after_ the protocol has finished. */
81
82 void silc_protocol_alloc(SilcProtocolType type, SilcProtocol *new_protocol,
83                          void *context, SilcProtocolFinalCallback callback)
84 {
85   SilcProtocolObject *protocol;
86
87   SILC_LOG_DEBUG(("Allocating new protocol type %d", type));
88
89   protocol = silc_protocol_list;
90   while (protocol && protocol->type != type)
91     protocol = protocol->next;
92
93   if (!protocol) {
94     SILC_LOG_ERROR(("Requested protocol does not exists"));
95     *new_protocol = NULL;
96     return;
97   }
98
99   *new_protocol = silc_calloc(1, sizeof(**new_protocol));
100   (*new_protocol)->protocol = protocol;
101   (*new_protocol)->state = SILC_PROTOCOL_STATE_UNKNOWN;
102   (*new_protocol)->context = context;
103   (*new_protocol)->execute = silc_protocol_execute;
104   (*new_protocol)->execute_final = silc_protocol_execute_final;
105   (*new_protocol)->final_callback = callback;
106 }
107
108 /* Free's a protocol object. */
109
110 void silc_protocol_free(SilcProtocol protocol)
111 {
112   if (protocol)
113     silc_free(protocol);
114 }
115
116 /* Executes next state of the protocol. The state must be set before
117    calling this function. */
118
119 void silc_protocol_execute(void *qptr, int type,
120                            void *context, int fd,
121                            long secs, long usecs)
122 {
123   SilcProtocol protocol = (SilcProtocol)context;
124
125   SILC_LOG_DEBUG(("Start"));
126
127   if (secs + usecs) 
128     silc_task_register(qptr, fd, protocol->protocol->callback, context, 
129                        secs, usecs, 
130                        SILC_TASK_TIMEOUT,
131                        SILC_TASK_PRI_NORMAL);
132   else
133     protocol->protocol->callback(qptr, 0, context, fd);
134 }
135
136 /* Executes the final callback of the protocol. */
137
138 void silc_protocol_execute_final(void *qptr, int type,
139                                  void *context, int fd)
140 {
141   SilcProtocol protocol = (SilcProtocol)context;
142  
143   SILC_LOG_DEBUG(("Start, state=%d", protocol->state));
144
145   protocol->final_callback(qptr, 0, context, fd);
146 }