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