In packet stream destroy, free linked callbacks.
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /*
20  * Created: Fri Jul 25 18:52:14 1997
21  */
22 /* $Id$ */
23
24 #include "silc.h"
25
26 /************************** Types and definitions ***************************/
27
28 /* Packet engine */
29 struct SilcPacketEngineStruct {
30   SilcRng rng;                           /* RNG for engine */
31   SilcPacketCallbacks *callbacks;        /* Packet callbacks */
32   void *callback_context;                /* Context for callbacks */
33   SilcList streams;                      /* All streams in engine */
34   SilcList packet_pool;                  /* Free list for received packets */
35   SilcMutex lock;                        /* Engine lock */
36   SilcHashTable udp_remote;              /* UDP remote streams, or NULL */
37   SilcBool local_is_router;
38 };
39
40 /* Packet processor context */
41 typedef struct SilcPacketProcessStruct {
42   SilcInt32 priority;                    /* Priority */
43   SilcPacketType *types;                 /* Packets to process */
44   SilcPacketCallbacks *callbacks;        /* Callbacks or NULL */
45   void *callback_context;
46 } *SilcPacketProcess;
47
48 /* UDP remote stream tuple */
49 typedef struct {
50   char *remote_ip;                       /* Remote IP address */
51   SilcUInt16 remote_port;                /* Remote port */
52 } *SilcPacketRemoteUDP;
53
54 /* Packet stream */
55 struct SilcPacketStreamStruct {
56   struct SilcPacketStreamStruct *next;
57   SilcPacketEngine engine;               /* Packet engine */
58   SilcStream stream;                     /* Underlaying stream */
59   SilcMutex lock;                        /* Stream lock */
60   SilcDList process;                     /* Packet processors, or NULL */
61   SilcPacketRemoteUDP remote_udp;        /* UDP remote stream tuple, or NULL */
62   void *stream_context;                  /* Stream context */
63   SilcBufferStruct inbuf;                /* In buffer */
64   SilcBufferStruct outbuf;               /* Out buffer */
65   SilcCipher send_key[2];                /* Sending key */
66   SilcHmac send_hmac[2];                 /* Sending HMAC */
67   SilcCipher receive_key[2];             /* Receiving key */
68   SilcHmac receive_hmac[2];              /* Receiving HMAC */
69   unsigned char *src_id;                 /* Source ID */
70   unsigned char *dst_id;                 /* Destination ID */
71   SilcUInt32 send_psn;                   /* Sending sequence */
72   SilcUInt32 receive_psn;                /* Receiving sequence */
73   SilcAtomic8 refcnt;                    /* Reference counter */
74   SilcUInt8 sid;                         /* Security ID, set if IV included */
75   unsigned int src_id_len  : 6;
76   unsigned int src_id_type : 2;
77   unsigned int dst_id_len  : 6;
78   unsigned int dst_id_type : 2;
79   unsigned int is_router   : 1;          /* Set if router stream */
80   unsigned int destroyed   : 1;          /* Set if destroyed */
81   unsigned int iv_included : 1;          /* Set if IV included */
82   unsigned int udp         : 1;          /* UDP remote stream */
83 };
84
85 /* Initial size of stream buffers */
86 #define SILC_PACKET_DEFAULT_SIZE  1024
87
88 /* Header length without source and destination ID's. */
89 #define SILC_PACKET_HEADER_LEN 10
90
91 /* Minimum length of SILC Packet Header. */
92 #define SILC_PACKET_MIN_HEADER_LEN 16
93 #define SILC_PACKET_MIN_HEADER_LEN_IV 32 + 1
94
95 /* Maximum padding length */
96 #define SILC_PACKET_MAX_PADLEN 128
97
98 /* Default padding length */
99 #define SILC_PACKET_DEFAULT_PADLEN 16
100
101 /* Minimum packet length */
102 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
103
104 /* Returns true length of the packet. */
105 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
106 do {                                                                     \
107   SILC_GET16_MSB((__ret_truelen), (__packetdata));                       \
108   (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4];    \
109 } while(0)
110
111 /* Calculates the data length with given header length.  This macro
112    can be used to check whether the data_len with header_len exceeds
113    SILC_PACKET_MAX_LEN.  If it does, this returns the new data_len
114    so that the SILC_PACKET_MAX_LEN is not exceeded.  If the data_len
115    plus header_len fits SILC_PACKET_MAX_LEN the returned data length
116    is the data_len given as argument. */
117 #define SILC_PACKET_DATALEN(data_len, header_len)                         \
118   ((data_len + header_len) > SILC_PACKET_MAX_LEN ?                        \
119    data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
120
121 /* Calculates the length of the padding in the packet. */
122 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen)               \
123 do {                                                                        \
124   __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                  \
125               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN));  \
126   if (__padlen < 8)                                                         \
127     __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
128 } while(0)
129
130 /* Returns the length of the padding up to the maximum length, which
131    is 128 bytes.*/
132 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen)          \
133 do {                                                                       \
134   __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) %                     \
135               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
136 } while(0)
137
138 /* EOS callback */
139 #define SILC_PACKET_CALLBACK_EOS(s)                                     \
140 do {                                                                    \
141   (s)->engine->callbacks->eos((s)->engine, s,                           \
142                               (s)->engine->callback_context,            \
143                               (s)->stream_context);                     \
144 } while(0)
145
146 /* Error callback */
147 #define SILC_PACKET_CALLBACK_ERROR(s, err)                              \
148 do {                                                                    \
149   (s)->engine->callbacks->error((s)->engine, s, err,                    \
150                                 (s)->engine->callback_context,          \
151                                 (s)->stream_context);                   \
152 } while(0)
153
154 static void silc_packet_dispatch(SilcPacket packet);
155 static void silc_packet_read_process(SilcPacketStream stream);
156
157 /************************ Static utility functions **************************/
158
159 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
160
161 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
162 {
163   SilcPacket packet = context;
164   SilcPacketStream stream = packet->stream;
165
166   SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
167
168   silc_mutex_lock(stream->lock);
169   silc_packet_dispatch(packet);
170   silc_mutex_unlock(stream->lock);
171 }
172
173 /* Write data to the stream.  Must be called with ps->lock locked.  Unlocks
174    the lock inside this function. */
175
176 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps)
177 {
178   SilcStream stream;
179   SilcBool connected;
180   int i;
181
182   if (ps->udp)
183     stream = ((SilcPacketStream)ps->stream)->stream;
184   else
185     stream = ps->stream;
186
187   if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
188     if (!connected) {
189       /* Connectionless UDP stream */
190       while (silc_buffer_len(&ps->outbuf) > 0) {
191         i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
192                               ps->remote_udp->remote_port,
193                               ps->outbuf.data, silc_buffer_len(&ps->outbuf));
194         if (i == -2) {
195           /* Error */
196           silc_buffer_reset(&ps->outbuf);
197           silc_mutex_unlock(ps->lock);
198           SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
199           return FALSE;
200         }
201
202         if (i == -1) {
203           /* Cannot write now, write later. */
204           silc_mutex_unlock(ps->lock);
205           return TRUE;
206         }
207
208         /* Wrote data */
209         silc_buffer_pull(&ps->outbuf, i);
210       }
211
212       silc_buffer_reset(&ps->outbuf);
213       silc_mutex_unlock(ps->lock);
214
215       return TRUE;
216     }
217   }
218
219   /* Write the data to the stream */
220   while (silc_buffer_len(&ps->outbuf) > 0) {
221     i = silc_stream_write(stream, ps->outbuf.data,
222                           silc_buffer_len(&ps->outbuf));
223     if (i == 0) {
224       /* EOS */
225       silc_buffer_reset(&ps->outbuf);
226       silc_mutex_unlock(ps->lock);
227       SILC_PACKET_CALLBACK_EOS(ps);
228       return FALSE;
229     }
230
231     if (i == -2) {
232       /* Error */
233       silc_buffer_reset(&ps->outbuf);
234       silc_mutex_unlock(ps->lock);
235       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
236       return FALSE;
237     }
238
239     if (i == -1) {
240       /* Cannot write now, write later. */
241       silc_mutex_unlock(ps->lock);
242       return TRUE;
243     }
244
245     /* Wrote data */
246     silc_buffer_pull(&ps->outbuf, i);
247   }
248
249   silc_buffer_reset(&ps->outbuf);
250   silc_mutex_unlock(ps->lock);
251
252   return TRUE;
253 }
254
255 /* Reads data from stream.  Must be called with the ps->lock locked.  If this
256    returns FALSE the lock has been unlocked.  If this returns packet stream
257    to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
258    It is returned if the stream is UDP and remote UDP stream exists for
259    the sender of the packet. */
260
261 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
262                                                SilcPacketStream *ret_ps)
263 {
264   SilcStream stream;
265   SilcBool connected;
266   int ret;
267
268   stream = ps->stream;
269
270   /* Make sure we have fair amount of free space in inbuf */
271   if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
272     if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
273                              SILC_PACKET_DEFAULT_SIZE * 2)) {
274       silc_mutex_unlock(ps->lock);
275       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
276       return FALSE;
277     }
278
279   if (silc_socket_stream_is_udp(stream, &connected)) {
280     if (!connected) {
281       /* Connectionless UDP stream, read one UDP packet */
282       char remote_ip[64], tuple[64];
283       int remote_port;
284       SilcPacketStream remote;
285
286       ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
287                                  &remote_port, ps->inbuf.tail,
288                                  silc_buffer_taillen(&ps->inbuf));
289       if (ret == -2) {
290         /* Error */
291         silc_buffer_reset(&ps->inbuf);
292         silc_mutex_unlock(ps->lock);
293         SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
294         return FALSE;
295       }
296
297       if (ret == -1) {
298         /* Cannot read now, do it later. */
299         silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
300         silc_mutex_unlock(ps->lock);
301         return FALSE;
302       }
303
304       /* See if remote packet stream exist for this sender */
305       snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
306       silc_mutex_lock(ps->engine->lock);
307       if (silc_hash_table_find(ps->engine->udp_remote, tuple, NULL,
308                                (void *)&remote)) {
309         /* Found packet stream for this sender, copy the packet */
310         silc_mutex_unlock(ps->engine->lock);
311
312         SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p",
313                         remote_ip, remote_port, remote));
314
315         silc_mutex_lock(remote->lock);
316         if (ret > silc_buffer_taillen(&remote->inbuf))
317           if (!silc_buffer_realloc(&remote->inbuf, ret)) {
318             silc_mutex_unlock(remote->lock);
319             silc_mutex_unlock(ps->lock);
320             SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
321             return FALSE;
322           }
323
324         silc_buffer_put_tail(&remote->inbuf, ps->inbuf.tail, ret);
325         silc_buffer_pull_tail(&remote->inbuf, ret);
326         *ret_ps = remote;
327
328         silc_buffer_reset(&ps->inbuf);
329         silc_mutex_unlock(ps->lock);
330         return TRUE;
331       }
332       silc_mutex_unlock(ps->engine->lock);
333
334       /* Unknown sender */
335       if (!ps->remote_udp) {
336         ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
337         if (!ps->remote_udp) {
338           silc_mutex_unlock(ps->lock);
339           SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
340           return FALSE;
341         }
342       }
343
344       /* Save sender IP and port */
345       silc_free(ps->remote_udp->remote_ip);
346       ps->remote_udp->remote_ip = strdup(remote_ip);
347       ps->remote_udp->remote_port = remote_port;
348
349       silc_buffer_pull_tail(&ps->inbuf, ret);
350       return TRUE;
351     }
352   }
353
354   /* Read data from the stream */
355   ret = silc_stream_read(ps->stream, ps->inbuf.tail,
356                          silc_buffer_taillen(&ps->inbuf));
357
358   if (ret == 0) {
359     /* EOS */
360     silc_buffer_reset(&ps->inbuf);
361     silc_mutex_unlock(ps->lock);
362     SILC_PACKET_CALLBACK_EOS(ps);
363     return FALSE;
364   }
365
366   if (ret == -2) {
367     /* Error */
368     silc_buffer_reset(&ps->inbuf);
369     silc_mutex_unlock(ps->lock);
370     SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
371     return FALSE;
372   }
373
374   if (ret == -1) {
375     /* Cannot read now, do it later. */
376     silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
377     silc_mutex_unlock(ps->lock);
378     return FALSE;
379   }
380
381   silc_buffer_pull_tail(&ps->inbuf, ret);
382   return TRUE;
383 }
384
385 /* Our stream IO notifier callback. */
386
387 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
388                                   void *context)
389 {
390   SilcPacketStream remote = NULL, ps = context;
391
392   silc_mutex_lock(ps->lock);
393
394   if (ps->destroyed) {
395     silc_mutex_unlock(ps->lock);
396     return;
397   }
398
399   switch (status) {
400
401   case SILC_STREAM_CAN_WRITE:
402     SILC_LOG_DEBUG(("Writing pending data to stream"));
403
404     if (!silc_buffer_headlen(&ps->outbuf)) {
405       silc_mutex_unlock(ps->lock);
406       return;
407     }
408
409     /* Write pending data to stream */
410     silc_packet_stream_write(ps);
411     break;
412
413   case SILC_STREAM_CAN_READ:
414     SILC_LOG_DEBUG(("Reading data from stream"));
415
416     /* Read data from stream */
417     if (!silc_packet_stream_read(ps, &remote))
418       return;
419
420     /* Now process the data */
421     if (!remote) {
422       silc_packet_read_process(ps);
423       silc_mutex_unlock(ps->lock);
424     } else {
425       silc_packet_read_process(remote);
426       silc_mutex_unlock(remote->lock);
427     }
428     break;
429
430   default:
431     silc_mutex_unlock(ps->lock);
432     break;
433   }
434 }
435
436 /* Allocate packet */
437
438 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
439 {
440   SilcPacket packet;
441
442   SILC_LOG_DEBUG(("Packet pool count %d",
443                   silc_list_count(engine->packet_pool)));
444
445   silc_mutex_lock(engine->lock);
446
447   /* Get packet from freelist or allocate new one. */
448   packet = silc_list_get(engine->packet_pool);
449   if (!packet) {
450     void *tmp;
451
452     silc_mutex_unlock(engine->lock);
453
454     packet = silc_calloc(1, sizeof(*packet));
455     if (!packet)
456       return NULL;
457
458     SILC_LOG_DEBUG(("Allocating new packet %p", packet));
459
460     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
461     if (!tmp) {
462       silc_free(packet);
463       return NULL;
464     }
465     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
466     silc_buffer_reset(&packet->buffer);
467
468     return packet;
469   }
470
471   SILC_LOG_DEBUG(("Get packet %p", packet));
472
473   /* Delete from freelist */
474   silc_list_del(engine->packet_pool, packet);
475
476   silc_mutex_unlock(engine->lock);
477
478   return packet;
479 }
480
481 /* UDP remote stream hash table destructor */
482
483 static void silc_packet_engine_hash_destr(void *key, void *context,
484                                           void *user_context)
485 {
486   silc_free(key);
487 }
488
489
490 /******************************** Packet API ********************************/
491
492 /* Allocate new packet engine */
493
494 SilcPacketEngine
495 silc_packet_engine_start(SilcRng rng, SilcBool router,
496                          SilcPacketCallbacks *callbacks,
497                          void *callback_context)
498 {
499   SilcPacketEngine engine;
500   SilcPacket packet;
501   int i;
502   void *tmp;
503
504   SILC_LOG_DEBUG(("Starting new packet engine"));
505
506   if (!callbacks)
507     return NULL;
508   if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
509     return NULL;
510
511   engine = silc_calloc(1, sizeof(*engine));
512   if (!engine)
513     return NULL;
514
515   engine->rng = rng;
516   engine->local_is_router = router;
517   engine->callbacks = callbacks;
518   engine->callback_context = callback_context;
519   silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
520   silc_mutex_alloc(&engine->lock);
521
522   /* Allocate packet free list */
523   silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
524   for (i = 0; i < 5; i++) {
525     packet = silc_calloc(1, sizeof(*packet));
526     if (!packet) {
527       silc_packet_engine_stop(engine);
528       return NULL;
529     }
530
531     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
532     if (!tmp) {
533       silc_packet_engine_stop(engine);
534       return NULL;
535     }
536     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
537     silc_buffer_reset(&packet->buffer);
538
539     silc_list_add(engine->packet_pool, packet);
540   }
541   silc_list_start(engine->packet_pool);
542
543   return engine;
544 }
545
546 /* Stop packet engine */
547
548 void silc_packet_engine_stop(SilcPacketEngine engine)
549 {
550
551   SILC_LOG_DEBUG(("Stopping packet engine"));
552
553   if (!engine)
554     return;
555
556   /* XXX */
557
558   silc_free(engine);
559 }
560
561 /* Create new packet stream */
562
563 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
564                                            SilcSchedule schedule,
565                                            SilcStream stream)
566 {
567   SilcPacketStream ps;
568   void *tmp;
569
570   SILC_LOG_DEBUG(("Creating new packet stream"));
571
572   if (!engine || !stream)
573     return NULL;
574
575   ps = silc_calloc(1, sizeof(*ps));
576   if (!ps)
577     return NULL;
578
579   ps->engine = engine;
580   ps->stream = stream;
581   silc_atomic_init8(&ps->refcnt, 1);
582   silc_mutex_alloc(&ps->lock);
583
584   /* Allocate buffers */
585   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
586   if (!tmp) {
587     silc_packet_stream_destroy(ps);
588     return NULL;
589   }
590   silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
591   silc_buffer_reset(&ps->inbuf);
592   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
593   if (!tmp) {
594     silc_packet_stream_destroy(ps);
595     return NULL;
596   }
597   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
598   silc_buffer_reset(&ps->outbuf);
599
600   /* Initialize packet procesors list */
601   ps->process = silc_dlist_init();
602   if (!ps->process) {
603     silc_packet_stream_destroy(ps);
604     return NULL;
605   }
606
607   /* Set IO notifier callback */
608   silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
609
610   /* Add to engine */
611   silc_mutex_lock(engine->lock);
612   silc_list_add(engine->streams, ps);
613   silc_mutex_unlock(engine->lock);
614
615   /* If this is UDP stream, allocate UDP remote stream hash table */
616   if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
617     engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
618                                                silc_hash_string_compare, NULL,
619                                                silc_packet_engine_hash_destr,
620                                                NULL, TRUE);
621
622   return ps;
623 }
624
625 /* Add new remote packet stream for UDP packet streams */
626
627 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
628                                                const char *remote_ip,
629                                                SilcUInt16 remote_port,
630                                                SilcPacket packet)
631 {
632   SilcPacketEngine engine = stream->engine;
633   SilcPacketStream ps;
634   char *tuple;
635   void *tmp;
636
637   SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
638                   remote_ip, remote_port, stream));
639
640   if (!stream || !remote_ip || !remote_port)
641     return NULL;
642
643   if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
644     SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
645     return NULL;
646   }
647
648   ps = silc_calloc(1, sizeof(*ps));
649   if (!ps)
650     return NULL;
651
652   ps->engine = engine;
653   silc_atomic_init8(&ps->refcnt, 1);
654   silc_mutex_alloc(&ps->lock);
655
656   /* Set the UDP packet stream as underlaying stream */
657   silc_packet_stream_ref(stream);
658   ps->stream = (SilcStream)stream;
659   ps->udp = TRUE;
660
661   /* Allocate buffers */
662   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
663   if (!tmp) {
664     silc_packet_stream_destroy(ps);
665     return NULL;
666   }
667   silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
668   silc_buffer_reset(&ps->inbuf);
669   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
670   if (!tmp) {
671     silc_packet_stream_destroy(ps);
672     return NULL;
673   }
674   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
675   silc_buffer_reset(&ps->outbuf);
676
677   /* Initialize packet procesors list */
678   ps->process = silc_dlist_init();
679   if (!ps->process) {
680     silc_packet_stream_destroy(ps);
681     return NULL;
682   }
683
684   /* Add to engine with this IP and port pair */
685   tuple = silc_format("%d%s", remote_port, remote_ip);
686   silc_mutex_lock(engine->lock);
687   if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
688     silc_mutex_unlock(engine->lock);
689     silc_packet_stream_destroy(ps);
690     return NULL;
691   }
692   silc_mutex_unlock(engine->lock);
693
694   /* Save remote IP and port pair */
695   ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
696   if (!ps->remote_udp) {
697     silc_packet_stream_destroy(ps);
698     return NULL;
699   }
700   ps->remote_udp->remote_port = remote_port;
701   ps->remote_udp->remote_ip = strdup(remote_ip);
702   if (!ps->remote_udp->remote_ip) {
703     silc_packet_stream_destroy(ps);
704     return NULL;
705   }
706
707   if (packet) {
708     /* Inject packet to the new stream */
709     packet->stream = ps;
710     silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
711                                    silc_packet_stream_inject_packet, packet,
712                                    0, 0);
713   }
714
715   return ps;
716 }
717
718 /* Destroy packet stream */
719
720 void silc_packet_stream_destroy(SilcPacketStream stream)
721 {
722   if (!stream)
723     return;
724
725   if (silc_atomic_get_int8(&stream->refcnt) > 1) {
726     stream->destroyed = TRUE;
727     return;
728   }
729
730   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
731
732   if (!stream->udp) {
733     /* Delete from engine */
734     silc_mutex_lock(stream->engine->lock);
735     silc_list_del(stream->engine->streams, stream);
736     silc_mutex_unlock(stream->engine->lock);
737
738     /* Destroy the underlaying stream */
739     if (stream->stream)
740       silc_stream_destroy(stream->stream);
741   } else {
742     /* Delete from UDP remote hash table */
743     char tuple[64];
744     snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
745              stream->remote_udp->remote_ip);
746     silc_mutex_lock(stream->engine->lock);
747     silc_hash_table_del(stream->engine->udp_remote, tuple);
748     silc_mutex_unlock(stream->engine->lock);
749
750     silc_free(stream->remote_udp->remote_ip);
751     silc_free(stream->remote_udp);
752
753     /* Unreference the underlaying packet stream */
754     silc_packet_stream_unref((SilcPacketStream)stream->stream);
755   }
756
757   /* Clear and free buffers */
758   silc_buffer_clear(&stream->inbuf);
759   silc_buffer_clear(&stream->outbuf);
760   silc_buffer_purge(&stream->inbuf);
761   silc_buffer_purge(&stream->outbuf);
762
763   if (stream->process) {
764     SilcPacketProcess p;
765     silc_dlist_start(stream->process);
766     while ((p = silc_dlist_get(stream->process))) {
767       silc_free(p->types);
768       silc_free(p);
769       silc_dlist_del(stream->process, p);
770     }
771     silc_dlist_uninit(stream->process);
772   }
773
774   /* XXX */
775
776   silc_atomic_uninit8(&stream->refcnt);
777   silc_mutex_free(stream->lock);
778   silc_free(stream);
779 }
780
781 /* Marks as router stream */
782
783 void silc_packet_stream_set_router(SilcPacketStream stream)
784 {
785   stream->is_router = TRUE;
786 }
787
788 /* Mark to include IV in ciphertext */
789
790 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
791 {
792   stream->iv_included = TRUE;
793 }
794
795 /* Links `callbacks' to `stream' for specified packet types */
796
797 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
798                                            SilcPacketCallbacks *callbacks,
799                                            void *callback_context,
800                                            int priority, va_list ap)
801 {
802   SilcPacketProcess p, e;
803   SilcInt32 packet_type;
804   int i;
805
806   SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
807
808   if (!callbacks)
809     return FALSE;
810   if (!callbacks->packet_receive)
811     return FALSE;
812
813   p = silc_calloc(1, sizeof(*p));
814   if (!p)
815     return FALSE;
816
817   p->priority = priority;
818   p->callbacks = callbacks;
819   p->callback_context = callback_context;
820
821   silc_mutex_lock(stream->lock);
822
823   if (!stream->process) {
824     stream->process = silc_dlist_init();
825     if (!stream->process) {
826       silc_mutex_unlock(stream->lock);
827       return FALSE;
828     }
829   }
830
831   /* According to priority set the procesor to correct position.  First
832      entry has the highest priority */
833   silc_dlist_start(stream->process);
834   while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
835     if (p->priority > e->priority) {
836       silc_dlist_insert(stream->process, p);
837       break;
838     }
839   }
840   if (!e)
841     silc_dlist_add(stream->process, p);
842
843   /* Get packet types to process */
844   i = 1;
845   while (1) {
846     packet_type = va_arg(ap, SilcInt32);
847
848     if (packet_type == SILC_PACKET_ANY)
849       break;
850
851     if (packet_type == -1)
852       break;
853
854     p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
855     if (!p->types) {
856       silc_mutex_unlock(stream->lock);
857       return FALSE;
858     }
859
860     p->types[i - 1] = (SilcPacketType)packet_type;
861     i++;
862   }
863   if (p->types)
864     p->types[i - 1] = 0;
865
866   silc_mutex_unlock(stream->lock);
867
868   silc_packet_stream_ref(stream);
869
870   return TRUE;
871 }
872
873 /* Links `callbacks' to `stream' for specified packet types */
874
875 SilcBool silc_packet_stream_link(SilcPacketStream stream,
876                                  SilcPacketCallbacks *callbacks,
877                                  void *callback_context,
878                                  int priority, ...)
879 {
880   va_list ap;
881   SilcBool ret;
882
883   va_start(ap, priority);
884   ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
885                                    priority, ap);
886   va_end(ap);
887
888   return ret;
889 }
890
891 /* Unlinks `callbacks' from `stream'. */
892
893 void silc_packet_stream_unlink(SilcPacketStream stream,
894                                SilcPacketCallbacks *callbacks,
895                                void *callback_context)
896 {
897   SilcPacketProcess p;
898
899   SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
900                   callbacks, stream));
901
902   silc_mutex_lock(stream->lock);
903
904   silc_dlist_start(stream->process);
905   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
906     if (p->callbacks == callbacks &&
907         p->callback_context == callback_context) {
908       silc_dlist_del(stream->process, p);
909       silc_free(p->types);
910       silc_free(p);
911       break;
912     }
913
914   if (!silc_dlist_count(stream->process)) {
915     silc_dlist_uninit(stream->process);
916     stream->process = NULL;
917   }
918
919   silc_mutex_unlock(stream->lock);
920
921   silc_packet_stream_unref(stream);
922 }
923
924 /* Return packet sender IP and port for UDP packet stream */
925
926 SilcBool silc_packet_get_sender(SilcPacket packet,
927                                 const char **sender_ip,
928                                 SilcUInt16 *sender_port)
929 {
930   if (!packet->stream->remote_udp)
931     return FALSE;
932
933   *sender_ip = packet->stream->remote_udp->remote_ip;
934   *sender_port = packet->stream->remote_udp->remote_port;
935
936   return TRUE;
937 }
938
939 /* Reference packet stream */
940
941 void silc_packet_stream_ref(SilcPacketStream stream)
942 {
943   silc_atomic_add_int8(&stream->refcnt, 1);
944 }
945
946 /* Unreference packet stream */
947
948 void silc_packet_stream_unref(SilcPacketStream stream)
949 {
950   if (silc_atomic_sub_int8(&stream->refcnt, 1) == 0)
951     silc_packet_stream_destroy(stream);
952 }
953
954 /* Return engine */
955
956 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
957 {
958   return stream->engine;
959 }
960
961 /* Set application context for packet stream */
962
963 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
964 {
965   silc_mutex_lock(stream->lock);
966   stream->stream_context = stream_context;
967   silc_mutex_unlock(stream->lock);
968 }
969
970 /* Return application context from packet stream */
971
972 void *silc_packet_get_context(SilcPacketStream stream)
973 {
974   void *context;
975   silc_mutex_lock(stream->lock);
976   context = stream->stream_context;
977   silc_mutex_unlock(stream->lock);
978   return context;
979 }
980
981 /* Change underlaying stream */
982
983 void silc_packet_stream_set_stream(SilcPacketStream ps,
984                                    SilcStream stream,
985                                    SilcSchedule schedule)
986 {
987   if (ps->stream)
988     silc_stream_set_notifier(ps->stream, schedule, NULL, NULL);
989   ps->stream = stream;
990   silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
991 }
992
993 /* Return underlaying stream */
994
995 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
996 {
997   return stream->stream;
998 }
999
1000 /* Set ciphers for packet stream */
1001
1002 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
1003                              SilcCipher receive)
1004 {
1005   SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
1006
1007   silc_mutex_lock(stream->lock);
1008
1009   /* In case IV Included is set, save the old key */
1010   if (stream->iv_included) {
1011     if (stream->send_key[1]) {
1012       silc_cipher_free(stream->send_key[1]);
1013       stream->send_key[1] = stream->send_key[0];
1014     }
1015     if (stream->receive_key[1]) {
1016       silc_cipher_free(stream->receive_key[1]);
1017       stream->receive_key[1] = stream->receive_key[0];
1018     }
1019   } else {
1020     if (stream->send_key[0])
1021       silc_cipher_free(stream->send_key[0]);
1022     if (stream->send_key[1])
1023       silc_cipher_free(stream->receive_key[0]);
1024   }
1025
1026   stream->send_key[0] = send;
1027   stream->receive_key[0] = receive;
1028
1029   silc_mutex_unlock(stream->lock);
1030 }
1031
1032 /* Return current ciphers from packet stream */
1033
1034 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
1035                                  SilcCipher *receive)
1036 {
1037   if (!stream->send_key[0] && !stream->receive_key[0])
1038     return FALSE;
1039
1040   silc_mutex_lock(stream->lock);
1041
1042   if (send)
1043     *send = stream->send_key[0];
1044   if (receive)
1045     *receive = stream->receive_key[0];
1046
1047   silc_mutex_unlock(stream->lock);
1048
1049   return TRUE;
1050 }
1051
1052 /* Set HMACs for packet stream */
1053
1054 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
1055                            SilcHmac receive)
1056 {
1057   SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
1058
1059   silc_mutex_lock(stream->lock);
1060
1061   /* In case IV Included is set, save the old HMAC */
1062   if (stream->iv_included) {
1063     if (stream->send_hmac[1]) {
1064       silc_hmac_free(stream->send_hmac[1]);
1065       stream->send_hmac[1] = stream->send_hmac[0];
1066     }
1067     if (stream->receive_hmac[1]) {
1068       silc_hmac_free(stream->receive_hmac[1]);
1069       stream->receive_hmac[1] = stream->receive_hmac[0];
1070     }
1071   } else {
1072     if (stream->send_hmac[0])
1073       silc_hmac_free(stream->send_hmac[0]);
1074     if (stream->receive_hmac[0])
1075       silc_hmac_free(stream->receive_hmac[0]);
1076   }
1077
1078   stream->send_hmac[0] = send;
1079   stream->receive_hmac[0] = receive;
1080
1081   silc_mutex_unlock(stream->lock);
1082 }
1083
1084 /* Return current HMACs from packet stream */
1085
1086 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
1087                                SilcHmac *receive)
1088 {
1089   if (!stream->send_hmac[0] && !stream->receive_hmac[0])
1090     return FALSE;
1091
1092   silc_mutex_lock(stream->lock);
1093
1094   if (send)
1095     *send = stream->send_hmac[0];
1096   if (receive)
1097     *receive = stream->receive_hmac[0];
1098
1099   silc_mutex_unlock(stream->lock);
1100
1101   return TRUE;
1102 }
1103
1104 /* Set SILC IDs to packet stream */
1105
1106 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1107                              SilcIdType src_id_type, const void *src_id,
1108                              SilcIdType dst_id_type, const void *dst_id)
1109 {
1110   SilcUInt32 len;
1111   unsigned char tmp[32];
1112
1113   if (!src_id && !dst_id)
1114     return FALSE;
1115
1116   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1117
1118   silc_mutex_lock(stream->lock);
1119
1120   if (src_id) {
1121     silc_free(stream->src_id);
1122     if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1123       silc_mutex_unlock(stream->lock);
1124       return FALSE;
1125     }
1126     stream->src_id = silc_memdup(tmp, len);
1127     if (!stream->src_id) {
1128       silc_mutex_unlock(stream->lock);
1129       return FALSE;
1130     }
1131     stream->src_id_type = src_id_type;
1132     stream->src_id_len = len;
1133   }
1134
1135   if (dst_id) {
1136     silc_free(stream->dst_id);
1137     if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1138       silc_mutex_unlock(stream->lock);
1139       return FALSE;
1140     }
1141     stream->dst_id = silc_memdup(tmp, len);
1142     if (!stream->dst_id) {
1143       silc_mutex_unlock(stream->lock);
1144       return FALSE;
1145     }
1146     stream->dst_id_type = dst_id_type;
1147     stream->dst_id_len = len;
1148   }
1149
1150   silc_mutex_unlock(stream->lock);
1151
1152   return TRUE;
1153 }
1154
1155 /* Adds Security ID (SID) */
1156
1157 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1158 {
1159   if (!stream->iv_included)
1160     return FALSE;
1161
1162   SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1163
1164   stream->sid = sid;
1165   return TRUE;
1166 }
1167
1168 /* Free packet */
1169
1170 void silc_packet_free(SilcPacket packet)
1171 {
1172   SilcPacketStream stream = packet->stream;
1173
1174   SILC_LOG_DEBUG(("Freeing packet %p", packet));
1175
1176   /* Check for double free */
1177   SILC_ASSERT(packet->stream != NULL);
1178
1179   packet->stream = NULL;
1180   packet->src_id = packet->dst_id = NULL;
1181   silc_buffer_reset(&packet->buffer);
1182
1183   silc_mutex_lock(stream->engine->lock);
1184
1185   /* Put the packet back to freelist */
1186   silc_list_add(stream->engine->packet_pool, packet);
1187   if (silc_list_count(stream->engine->packet_pool) == 1)
1188     silc_list_start(stream->engine->packet_pool);
1189
1190   silc_mutex_unlock(stream->engine->lock);
1191 }
1192
1193 /****************************** Packet Sending ******************************/
1194
1195 /* Prepare outgoing data buffer for packet sending.  Returns the
1196    pointer to that buffer into the `packet'. */
1197
1198 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1199                                          SilcUInt32 totlen,
1200                                          SilcHmac hmac,
1201                                          SilcBuffer packet)
1202 {
1203   unsigned char *oldptr;
1204   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1205
1206   totlen += mac_len;
1207
1208   /* Allocate more space if needed */
1209   if (silc_buffer_taillen(&stream->outbuf) < totlen) {
1210     if (!silc_buffer_realloc(&stream->outbuf,
1211                              silc_buffer_truelen(&stream->outbuf) + totlen))
1212       return FALSE;
1213   }
1214
1215   /* Pull data area for the new packet, and return pointer to the start of
1216      the data area and save the pointer in to the `packet'.  MAC is pulled
1217      later after it's computed. */
1218   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1219   silc_buffer_set(packet, oldptr, totlen);
1220   silc_buffer_push_tail(packet, mac_len);
1221
1222   return TRUE;
1223 }
1224
1225 /* Internal routine to send packet */
1226
1227 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
1228                                      SilcPacketType type,
1229                                      SilcPacketFlags flags,
1230                                      SilcIdType src_id_type,
1231                                      unsigned char *src_id,
1232                                      SilcUInt32 src_id_len,
1233                                      SilcIdType dst_id_type,
1234                                      unsigned char *dst_id,
1235                                      SilcUInt32 dst_id_len,
1236                                      const unsigned char *data,
1237                                      SilcUInt32 data_len,
1238                                      SilcCipher cipher,
1239                                      SilcHmac hmac)
1240 {
1241   unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1242   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1243   int i, enclen, truelen, padlen, ivlen = 0, psnlen = 0;
1244   SilcBufferStruct packet;
1245
1246   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1247                   "data len %d", silc_get_packet_name(type), stream->send_psn,
1248                   flags, src_id_type, dst_id_type, data_len));
1249
1250   /* Get the true length of the packet. This is saved as payload length
1251      into the packet header.  This does not include the length of the
1252      padding. */
1253   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1254                                             src_id_len + dst_id_len));
1255   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1256                       src_id_len + dst_id_len);
1257
1258   /* If IV is included, the SID, IV and sequence number is added to packet */
1259   if (stream->iv_included && cipher) {
1260     psnlen = sizeof(psn);
1261     ivlen = block_len + 1;
1262     iv[0] = stream->sid;
1263     memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1264   }
1265
1266   /* We automatically figure out the packet structure from the packet
1267      type and flags, and calculate correct length.  Private messages with
1268      private keys and channel messages are special packets as their
1269      payload is encrypted already. */
1270   if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1271        flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1272       type == SILC_PACKET_CHANNEL_MESSAGE) {
1273
1274     /* Padding is calculated from header + IDs */
1275     SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1276                         psnlen), block_len, padlen);
1277
1278     /* Length to encrypt, header + IDs + padding. */
1279     enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1280               padlen + psnlen);
1281   } else {
1282
1283     /* Padding is calculated from true length of the packet */
1284     if (flags & SILC_PACKET_FLAG_LONG_PAD)
1285       SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1286     else
1287       SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1288
1289     enclen += padlen + psnlen;
1290   }
1291
1292   /* Remove implementation specific flags */
1293   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1294
1295   /* Get random padding */
1296   for (i = 0; i < padlen; i++) tmppad[i] =
1297                                  silc_rng_get_byte_fast(stream->engine->rng);
1298
1299   silc_mutex_lock(stream->lock);
1300
1301   /* Get packet pointer from the outgoing buffer */
1302   if (!silc_packet_send_prepare(stream, truelen + padlen + ivlen + psnlen,
1303                                 hmac, &packet)) {
1304     silc_mutex_unlock(stream->lock);
1305     return FALSE;
1306   }
1307
1308   SILC_PUT32_MSB(stream->send_psn, psn);
1309
1310   /* Create the packet.  This creates the SILC header, adds padding, and
1311      the actual packet data. */
1312   i = silc_buffer_format(&packet,
1313                          SILC_STR_DATA(iv, ivlen),
1314                          SILC_STR_DATA(psn, psnlen),
1315                          SILC_STR_UI_SHORT(truelen),
1316                          SILC_STR_UI_CHAR(flags),
1317                          SILC_STR_UI_CHAR(type),
1318                          SILC_STR_UI_CHAR(padlen),
1319                          SILC_STR_UI_CHAR(0),
1320                          SILC_STR_UI_CHAR(src_id_len),
1321                          SILC_STR_UI_CHAR(dst_id_len),
1322                          SILC_STR_UI_CHAR(src_id_type),
1323                          SILC_STR_DATA(src_id, src_id_len),
1324                          SILC_STR_UI_CHAR(dst_id_type),
1325                          SILC_STR_DATA(dst_id, dst_id_len),
1326                          SILC_STR_DATA(tmppad, padlen),
1327                          SILC_STR_DATA(data, data_len),
1328                          SILC_STR_END);
1329   if (i < 0) {
1330     silc_mutex_unlock(stream->lock);
1331     return FALSE;
1332   }
1333
1334   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1335                    silc_buffer_data(&packet), silc_buffer_len(&packet));
1336
1337   /* Encrypt the packet */
1338   if (cipher) {
1339     SILC_LOG_DEBUG(("Encrypting packet"));
1340     if (!silc_cipher_encrypt(cipher, packet.data + ivlen,
1341                              packet.data + ivlen, enclen, NULL)) {
1342       SILC_LOG_ERROR(("Packet encryption failed"));
1343       silc_mutex_unlock(stream->lock);
1344       return FALSE;
1345     }
1346   }
1347
1348   /* Compute HMAC */
1349   if (hmac) {
1350     SilcUInt32 mac_len;
1351
1352     /* MAC is computed from the entire encrypted packet data, and put
1353        to the end of the packet. */
1354     silc_hmac_init(hmac);
1355     silc_hmac_update(hmac, psn, sizeof(psn));
1356     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1357     silc_hmac_final(hmac, packet.tail, &mac_len);
1358     silc_buffer_pull_tail(&packet, mac_len);
1359     stream->send_psn++;
1360   }
1361
1362   /* Write the packet to the stream */
1363   return silc_packet_stream_write(stream);
1364 }
1365
1366 /* Sends a packet */
1367
1368 SilcBool silc_packet_send(SilcPacketStream stream,
1369                           SilcPacketType type, SilcPacketFlags flags,
1370                           const unsigned char *data, SilcUInt32 data_len)
1371 {
1372   return silc_packet_send_raw(stream, type, flags,
1373                               stream->src_id_type,
1374                               stream->src_id,
1375                               stream->src_id_len,
1376                               stream->dst_id_type,
1377                               stream->dst_id,
1378                               stream->dst_id_len,
1379                               data, data_len,
1380                               stream->send_key[0],
1381                               stream->send_hmac[0]);
1382 }
1383
1384 /* Sends a packet, extended routine */
1385
1386 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1387                               SilcPacketType type, SilcPacketFlags flags,
1388                               SilcIdType src_id_type, void *src_id,
1389                               SilcIdType dst_id_type, void *dst_id,
1390                               const unsigned char *data, SilcUInt32 data_len,
1391                               SilcCipher cipher, SilcHmac hmac)
1392 {
1393   unsigned char src_id_data[32], dst_id_data[32];
1394   SilcUInt32 src_id_len, dst_id_len;
1395
1396   if (src_id)
1397     if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1398                         sizeof(src_id_data), &src_id_len))
1399       return FALSE;
1400   if (dst_id)
1401     if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1402                         sizeof(dst_id_data), &dst_id_len))
1403       return FALSE;
1404
1405   return silc_packet_send_raw(stream, type, flags,
1406                               src_id ? src_id_type : stream->src_id_type,
1407                               src_id ? src_id_data : stream->src_id,
1408                               src_id ? src_id_len : stream->src_id_len,
1409                               dst_id ? dst_id_type : stream->dst_id_type,
1410                               dst_id ? dst_id_data : stream->dst_id,
1411                               dst_id ? dst_id_len : stream->dst_id_len,
1412                               data, data_len,
1413                               cipher ? cipher : stream->send_key[0],
1414                               hmac ? hmac : stream->send_hmac[0]);
1415 }
1416
1417 /* Sends packet after formatting the arguments to buffer */
1418
1419 SilcBool silc_packet_send_va(SilcPacketStream stream,
1420                              SilcPacketType type, SilcPacketFlags flags, ...)
1421 {
1422   SilcBufferStruct buf;
1423   SilcBool ret;
1424   va_list va;
1425
1426   va_start(va, flags);
1427
1428   memset(&buf, 0, sizeof(buf));
1429   if (silc_buffer_format_vp(&buf, va) < 0) {
1430     va_end(va);
1431     return FALSE;
1432   }
1433
1434   ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1435                          silc_buffer_len(&buf));
1436
1437   silc_buffer_purge(&buf);
1438   va_end(va);
1439
1440   return ret;
1441 }
1442
1443 /* Sends packet after formatting the arguments to buffer, extended routine */
1444
1445 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1446                                  SilcPacketType type, SilcPacketFlags flags,
1447                                  SilcIdType src_id_type, void *src_id,
1448                                  SilcIdType dst_id_type, void *dst_id,
1449                                  SilcCipher cipher, SilcHmac hmac, ...)
1450 {
1451   SilcBufferStruct buf;
1452   SilcBool ret;
1453   va_list va;
1454
1455   va_start(va, hmac);
1456
1457   memset(&buf, 0, sizeof(buf));
1458   if (silc_buffer_format_vp(&buf, va) < 0) {
1459     va_end(va);
1460     return FALSE;
1461   }
1462
1463   ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1464                              dst_id_type, dst_id, silc_buffer_data(&buf),
1465                              silc_buffer_len(&buf), cipher, hmac);
1466
1467   silc_buffer_purge(&buf);
1468   va_end(va);
1469
1470   return TRUE;
1471 }
1472
1473 /***************************** Packet Receiving *****************************/
1474
1475 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1476
1477 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1478                                              const unsigned char *data,
1479                                              SilcUInt32 data_len,
1480                                              const unsigned char *packet_mac,
1481                                              const unsigned char *packet_seq,
1482                                              SilcUInt32 sequence)
1483 {
1484   /* Check MAC */
1485   if (hmac) {
1486     unsigned char mac[32], psn[4];
1487     SilcUInt32 mac_len;
1488
1489     SILC_LOG_DEBUG(("Verifying MAC"));
1490
1491     /* Compute HMAC of packet */
1492     silc_hmac_init(hmac);
1493
1494     if (!packet_seq) {
1495       SILC_PUT32_MSB(sequence, psn);
1496       silc_hmac_update(hmac, psn, 4);
1497     } else
1498       silc_hmac_update(hmac, packet_seq, 4);
1499
1500     silc_hmac_update(hmac, data, data_len);
1501     silc_hmac_final(hmac, mac, &mac_len);
1502
1503     /* Compare the MAC's */
1504     if (memcmp(packet_mac, mac, mac_len)) {
1505       SILC_LOG_DEBUG(("MAC failed"));
1506       return FALSE;
1507     }
1508
1509     SILC_LOG_DEBUG(("MAC is Ok"));
1510   }
1511
1512   return TRUE;
1513 }
1514
1515 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1516    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1517
1518 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1519                                       SilcUInt32 sequence, SilcBuffer buffer,
1520                                       SilcBool normal)
1521 {
1522   if (normal == TRUE) {
1523     if (cipher) {
1524       /* Decrypt rest of the packet */
1525       SILC_LOG_DEBUG(("Decrypting the packet"));
1526       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1527                                silc_buffer_len(buffer), NULL))
1528         return -1;
1529     }
1530     return 0;
1531
1532   } else {
1533     /* Decrypt rest of the header plus padding */
1534     if (cipher) {
1535       SilcUInt16 len;
1536       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1537
1538       SILC_LOG_DEBUG(("Decrypting the header"));
1539
1540       /* Padding length + src id len + dst id len + header length - 16
1541          bytes already decrypted, gives the rest of the encrypted packet */
1542       silc_buffer_push(buffer, block_len);
1543       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1544               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1545              block_len);
1546       silc_buffer_pull(buffer, block_len);
1547
1548       if (len > silc_buffer_len(buffer)) {
1549         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1550                         "packet dropped"));
1551         return -1;
1552       }
1553       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1554                                len, NULL))
1555         return -1;
1556     }
1557
1558     return 1;
1559   }
1560 }
1561
1562 /* Parses the packet. This is called when a whole packet is ready to be
1563    parsed. The buffer sent must be already decrypted before calling this
1564    function. */
1565
1566 static inline SilcBool silc_packet_parse(SilcPacket packet)
1567 {
1568   SilcBuffer buffer = &packet->buffer;
1569   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1570   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1571   int ret;
1572
1573   SILC_LOG_DEBUG(("Parsing incoming packet"));
1574
1575   /* Parse the buffer.  This parses the SILC header of the packet. */
1576   ret = silc_buffer_unformat(buffer,
1577                              SILC_STR_ADVANCE,
1578                              SILC_STR_OFFSET(6),
1579                              SILC_STR_UI_CHAR(&src_id_len),
1580                              SILC_STR_UI_CHAR(&dst_id_len),
1581                              SILC_STR_UI_CHAR(&src_id_type),
1582                              SILC_STR_END);
1583   if (ret == -1) {
1584     if (!packet->stream->udp &&
1585         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1586       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1587     return FALSE;
1588   }
1589
1590   if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1591       dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1592     if (!packet->stream->udp &&
1593         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1594       SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1595                       packet->src_id_len, packet->dst_id_len));
1596     return FALSE;
1597   }
1598
1599   ret = silc_buffer_unformat(buffer,
1600                              SILC_STR_ADVANCE,
1601                              SILC_STR_DATA(&packet->src_id, src_id_len),
1602                              SILC_STR_UI_CHAR(&dst_id_type),
1603                              SILC_STR_DATA(&packet->dst_id, dst_id_len),
1604                              SILC_STR_OFFSET(padlen),
1605                              SILC_STR_END);
1606   if (ret == -1) {
1607     if (!packet->stream->udp &&
1608         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1609       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1610     return FALSE;
1611   }
1612
1613   if (src_id_type > SILC_ID_CHANNEL ||
1614       dst_id_type > SILC_ID_CHANNEL) {
1615     if (!packet->stream->udp &&
1616         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1617       SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1618                       src_id_type, dst_id_type));
1619     return FALSE;
1620   }
1621
1622   packet->src_id_len = src_id_len;
1623   packet->dst_id_len = dst_id_len;
1624   packet->src_id_type = src_id_type;
1625   packet->dst_id_type = dst_id_type;
1626
1627   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1628                    silc_buffer_len(buffer)), buffer->head,
1629                    silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1630
1631   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1632                   silc_get_packet_name(packet->type)));
1633
1634   return TRUE;
1635 }
1636
1637 /* Dispatch packet to application.  Called with stream->lock locked. */
1638
1639 static void silc_packet_dispatch(SilcPacket packet)
1640 {
1641   SilcPacketStream stream = packet->stream;
1642   SilcPacketProcess p;
1643   SilcBool default_sent = FALSE;
1644   SilcPacketType *pt;
1645
1646   /* Dispatch packet to all packet processors that want it */
1647
1648   if (!stream->process) {
1649     /* Send to default processor as no others exist */
1650     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1651     silc_mutex_unlock(stream->lock);
1652     if (!stream->engine->callbacks->
1653         packet_receive(stream->engine, stream, packet,
1654                        stream->engine->callback_context,
1655                        stream->stream_context))
1656       silc_packet_free(packet);
1657     silc_mutex_lock(stream->lock);
1658     return;
1659   }
1660
1661   silc_dlist_start(stream->process);
1662   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1663
1664     /* If priority is 0 or less, we send to default processor first
1665        because default processor has 0 priority */
1666     if (!default_sent && p->priority <= 0) {
1667       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1668       default_sent = TRUE;
1669       silc_mutex_unlock(stream->lock);
1670       if (stream->engine->callbacks->
1671           packet_receive(stream->engine, stream, packet,
1672                          stream->engine->callback_context,
1673                          stream->stream_context)) {
1674         silc_mutex_lock(stream->lock);
1675         return;
1676       }
1677       silc_mutex_lock(stream->lock);
1678     }
1679
1680     /* Send to processor */
1681     if (!p->types) {
1682       /* Send all packet types */
1683       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1684       silc_mutex_unlock(stream->lock);
1685       if (p->callbacks->packet_receive(stream->engine, stream, packet,
1686                                        p->callback_context,
1687                                        stream->stream_context)) {
1688         silc_mutex_lock(stream->lock);
1689         return;
1690       }
1691       silc_mutex_lock(stream->lock);
1692     } else {
1693       /* Send specific types */
1694       for (pt = p->types; *pt; pt++) {
1695         if (*pt != packet->type)
1696           continue;
1697         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1698         silc_mutex_unlock(stream->lock);
1699         if (p->callbacks->packet_receive(stream->engine, stream, packet,
1700                                          p->callback_context,
1701                                          stream->stream_context)) {
1702           silc_mutex_lock(stream->lock);
1703           return;
1704         }
1705         silc_mutex_lock(stream->lock);
1706         break;
1707       }
1708     }
1709   }
1710
1711   if (!default_sent) {
1712     /* Send to default processor as it has not been sent yet */
1713     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1714     silc_mutex_unlock(stream->lock);
1715     if (stream->engine->callbacks->
1716         packet_receive(stream->engine, stream, packet,
1717                        stream->engine->callback_context,
1718                        stream->stream_context)) {
1719       silc_mutex_lock(stream->lock);
1720       return;
1721     }
1722     silc_mutex_lock(stream->lock);
1723   }
1724
1725   /* If we got here, no one wanted the packet, so drop it */
1726   silc_packet_free(packet);
1727 }
1728
1729 /* Process incoming data and parse packets.  Called with stream->lock
1730    locked. */
1731
1732 static void silc_packet_read_process(SilcPacketStream stream)
1733 {
1734   SilcCipher cipher;
1735   SilcHmac hmac;
1736   SilcPacket packet;
1737   SilcUInt8 sid;
1738   SilcUInt16 packetlen;
1739   SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1740   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1741   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1742   SilcBool normal;
1743   int ret;
1744
1745   /* Parse the packets from the data */
1746   while (silc_buffer_len(&stream->inbuf) > 0) {
1747     ivlen = psnlen = 0;
1748     cipher = stream->receive_key[0];
1749     hmac = stream->receive_hmac[0];
1750     normal = FALSE;
1751
1752     if (silc_buffer_len(&stream->inbuf) <
1753         (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1754          SILC_PACKET_MIN_HEADER_LEN)) {
1755       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1756       return;
1757     }
1758
1759     if (hmac)
1760       mac_len = silc_hmac_len(hmac);
1761     else
1762       mac_len = 0;
1763
1764     /* Decrypt first block of the packet to get the length field out */
1765     if (cipher) {
1766       block_len = silc_cipher_get_block_len(cipher);
1767
1768       if (stream->iv_included) {
1769         /* SID, IV and sequence number is included in the ciphertext */
1770         sid = (SilcUInt8)stream->inbuf.data[0];
1771         memcpy(iv, stream->inbuf.data + 1, block_len);
1772         ivlen = block_len + 1;
1773         psnlen = 4;
1774
1775         /* Check SID, and get correct decryption key */
1776         if (sid != stream->sid) {
1777           /* If SID is recent get the previous key and use it */
1778           if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
1779               stream->receive_key[1] && !stream->receive_hmac[1]) {
1780             cipher = stream->receive_key[1];
1781             hmac = stream->receive_hmac[1];
1782           } else {
1783             /* The SID is unknown, drop rest of the data in buffer */
1784             SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
1785                             sid, stream->sid));
1786             silc_mutex_unlock(stream->lock);
1787             SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
1788             silc_mutex_lock(stream->lock);
1789             silc_buffer_reset(&stream->inbuf);
1790             return;
1791           }
1792         }
1793       } else {
1794         memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1795       }
1796
1797       silc_cipher_decrypt(cipher, stream->inbuf.data + ivlen, tmp,
1798                           block_len, iv);
1799
1800       header = tmp;
1801       if (stream->iv_included) {
1802         /* Take sequence number from packet */
1803         packet_seq = header;
1804         header += 4;
1805       }
1806     } else {
1807       block_len = SILC_PACKET_MIN_HEADER_LEN;
1808       header = stream->inbuf.data;
1809     }
1810
1811     /* Get packet length and full packet length with padding */
1812     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1813
1814     /* Sanity checks */
1815     if (packetlen < SILC_PACKET_MIN_LEN) {
1816       if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
1817         SILC_LOG_ERROR(("Received too short packet"));
1818       silc_mutex_unlock(stream->lock);
1819       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1820       silc_mutex_lock(stream->lock);
1821       memset(tmp, 0, sizeof(tmp));
1822       silc_buffer_reset(&stream->inbuf);
1823       return;
1824     }
1825
1826     if (silc_buffer_len(&stream->inbuf) < paddedlen + ivlen + mac_len) {
1827       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1828                       "(%d bytes)",
1829                       paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1830       memset(tmp, 0, sizeof(tmp));
1831       return;
1832     }
1833
1834     /* Check MAC of the packet */
1835     if (!silc_packet_check_mac(hmac, stream->inbuf.data,
1836                                paddedlen + ivlen,
1837                                stream->inbuf.data + ivlen + paddedlen,
1838                                packet_seq, stream->receive_psn)) {
1839       silc_mutex_unlock(stream->lock);
1840       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1841       silc_mutex_lock(stream->lock);
1842       memset(tmp, 0, sizeof(tmp));
1843       silc_buffer_reset(&stream->inbuf);
1844       return;
1845     }
1846
1847     /* Get packet */
1848     packet = silc_packet_alloc(stream->engine);
1849     if (!packet) {
1850       silc_mutex_unlock(stream->lock);
1851       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1852       silc_mutex_lock(stream->lock);
1853       memset(tmp, 0, sizeof(tmp));
1854       silc_buffer_reset(&stream->inbuf);
1855       return;
1856     }
1857     packet->stream = stream;
1858
1859     /* Allocate more space to packet buffer, if needed */
1860     if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1861       if (!silc_buffer_realloc(&packet->buffer,
1862                                silc_buffer_truelen(&packet->buffer) +
1863                                (paddedlen -
1864                                 silc_buffer_truelen(&packet->buffer)))) {
1865         silc_mutex_unlock(stream->lock);
1866         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1867         silc_mutex_lock(stream->lock);
1868         silc_packet_free(packet);
1869         memset(tmp, 0, sizeof(tmp));
1870         silc_buffer_reset(&stream->inbuf);
1871         return;
1872       }
1873     }
1874
1875     /* Parse packet header */
1876     packet->flags = (SilcPacketFlags)header[2];
1877     packet->type = (SilcPacketType)header[3];
1878
1879     if (stream->engine->local_is_router) {
1880       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1881           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1882         normal = FALSE;
1883       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1884                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1885                 stream->is_router == TRUE))
1886         normal = TRUE;
1887     } else {
1888       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1889           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1890         normal = FALSE;
1891       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1892         normal = TRUE;
1893     }
1894
1895     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1896                       stream->receive_psn, paddedlen + ivlen + mac_len),
1897                      stream->inbuf.data, paddedlen + ivlen + mac_len);
1898
1899     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1900     silc_buffer_pull_tail(&packet->buffer, paddedlen);
1901     silc_buffer_put(&packet->buffer, header, block_len - psnlen);
1902     silc_buffer_pull(&packet->buffer, block_len - psnlen);
1903     silc_buffer_put(&packet->buffer, (stream->inbuf.data + ivlen +
1904                                       psnlen + (block_len - psnlen)),
1905                     paddedlen - ivlen - psnlen - (block_len - psnlen));
1906     if (cipher) {
1907       silc_cipher_set_iv(cipher, iv);
1908       ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
1909                                 &packet->buffer, normal);
1910       if (ret < 0) {
1911         silc_mutex_unlock(stream->lock);
1912         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1913         silc_mutex_lock(stream->lock);
1914         silc_packet_free(packet);
1915         memset(tmp, 0, sizeof(tmp));
1916         return;
1917       }
1918
1919       stream->receive_psn++;
1920     }
1921     silc_buffer_push(&packet->buffer, block_len);
1922
1923     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1924     silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1925
1926     /* Parse the packet */
1927     if (!silc_packet_parse(packet)) {
1928       silc_mutex_unlock(stream->lock);
1929       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1930       silc_mutex_lock(stream->lock);
1931       silc_packet_free(packet);
1932       memset(tmp, 0, sizeof(tmp));
1933       return;
1934     }
1935
1936     /* Dispatch the packet to application */
1937     silc_packet_dispatch(packet);
1938   }
1939
1940   silc_buffer_reset(&stream->inbuf);
1941 }
1942
1943
1944 /****************************** Packet Waiting ******************************/
1945
1946 /* Packet wait receive callback */
1947 static SilcBool
1948 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1949                                 SilcPacketStream stream,
1950                                 SilcPacket packet,
1951                                 void *callback_context,
1952                                 void *stream_context);
1953
1954 /* Packet waiting callbacks */
1955 static SilcPacketCallbacks silc_packet_wait_cbs =
1956 {
1957   silc_packet_wait_packet_receive, NULL, NULL
1958 };
1959
1960 /* Packet waiting context */
1961 typedef struct {
1962   SilcMutex wait_lock;
1963   SilcCond wait_cond;
1964   SilcList packet_queue;
1965   unsigned int stopped     : 1;
1966 } *SilcPacketWait;
1967
1968 /* Packet wait receive callback */
1969
1970 static SilcBool
1971 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1972                                 SilcPacketStream stream,
1973                                 SilcPacket packet,
1974                                 void *callback_context,
1975                                 void *stream_context)
1976 {
1977   SilcPacketWait pw = callback_context;
1978
1979   /* Signal the waiting thread for a new packet */
1980   silc_mutex_lock(pw->wait_lock);
1981
1982   if (pw->stopped) {
1983     silc_mutex_unlock(pw->wait_lock);
1984     return FALSE;
1985   }
1986
1987   silc_list_add(pw->packet_queue, packet);
1988   silc_cond_broadcast(pw->wait_cond);
1989
1990   silc_mutex_unlock(pw->wait_lock);
1991
1992   return TRUE;
1993 }
1994
1995 /* Initialize packet waiting */
1996
1997 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1998 {
1999   SilcPacketWait pw;
2000   SilcBool ret;
2001   va_list ap;
2002
2003   pw = silc_calloc(1, sizeof(*pw));
2004   if (!pw)
2005     return NULL;
2006
2007   /* Allocate mutex and conditional variable */
2008   if (!silc_mutex_alloc(&pw->wait_lock)) {
2009     silc_free(pw);
2010     return NULL;
2011   }
2012   if (!silc_cond_alloc(&pw->wait_cond)) {
2013     silc_mutex_free(pw->wait_lock);
2014     silc_free(pw);
2015     return NULL;
2016   }
2017
2018   /* Link to the packet stream for the requested packet types */
2019   va_start(ap, stream);
2020   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2021                                    10000000, ap);
2022   va_end(ap);
2023   if (!ret) {
2024     silc_cond_free(pw->wait_cond);
2025     silc_mutex_free(pw->wait_lock);
2026     silc_free(pw);
2027     return NULL;
2028   }
2029
2030   /* Initialize packet queue */
2031   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2032
2033   return (void *)pw;
2034 }
2035
2036 /* Uninitialize packet waiting */
2037
2038 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2039 {
2040   SilcPacketWait pw = waiter;
2041   SilcPacket packet;
2042
2043   /* Signal any threads to stop waiting */
2044   silc_mutex_lock(pw->wait_lock);
2045   pw->stopped = TRUE;
2046   silc_cond_broadcast(pw->wait_cond);
2047   silc_mutex_unlock(pw->wait_lock);
2048
2049   /* Re-acquire lock and free resources */
2050   silc_mutex_lock(pw->wait_lock);
2051   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2052
2053   /* Free any remaining packets */
2054   silc_list_start(pw->packet_queue);
2055   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2056     silc_packet_free(packet);
2057
2058   silc_mutex_unlock(pw->wait_lock);
2059   silc_cond_free(pw->wait_cond);
2060   silc_mutex_free(pw->wait_lock);
2061   silc_free(pw);
2062 }
2063
2064 /* Blocks thread until a packet has been received. */
2065
2066 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2067 {
2068   SilcPacketWait pw = waiter;
2069   SilcBool ret = FALSE;
2070
2071   silc_mutex_lock(pw->wait_lock);
2072
2073   /* Wait here until packet has arrived */
2074   while (silc_list_count(pw->packet_queue) == 0) {
2075     if (pw->stopped) {
2076       silc_mutex_unlock(pw->wait_lock);
2077       return -1;
2078     }
2079     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2080   }
2081
2082   /* Return packet */
2083   silc_list_start(pw->packet_queue);
2084   *return_packet = silc_list_get(pw->packet_queue);
2085   silc_list_del(pw->packet_queue, *return_packet);
2086
2087   silc_mutex_unlock(pw->wait_lock);
2088
2089   return ret == TRUE ? 1 : 0;
2090 }