Handle packet wait uninitializing from another thread.
[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   SilcBool local_is_router;
37 };
38
39 /* Packet procesor context */
40 typedef struct SilcPacketProcessStruct {
41   SilcInt32 priority;                    /* Priority */
42   SilcPacketType *types;                 /* Packets to process */
43   SilcPacketCallbacks *callbacks;        /* Callbacks or NULL */
44   void *callback_context;
45 } *SilcPacketProcess;
46
47 /* Packet stream */
48 struct SilcPacketStreamStruct {
49   struct SilcPacketStreamStruct *next;
50   SilcPacketEngine engine;               /* Packet engine */
51   SilcStream stream;                     /* Underlaying stream */
52   SilcMutex lock;                        /* Stream lock */
53   SilcDList process;                     /* Packet processors, it set */
54   void *stream_context;                  /* Stream context */
55   SilcBufferStruct inbuf;                /* In buffer */
56   SilcBufferStruct outbuf;               /* Out buffer */
57   SilcUInt32 send_psn;                   /* Sending sequence */
58   SilcCipher send_key;                   /* Sending key */
59   SilcHmac send_hmac;                    /* Sending HMAC */
60   SilcUInt32 receive_psn;                /* Receiving sequence */
61   SilcCipher receive_key;                /* Receiving key */
62   SilcHmac receive_hmac;                 /* Receiving HMAC */
63   unsigned char *src_id;                 /* Source ID */
64   unsigned char *dst_id;                 /* Destination ID */
65   unsigned int src_id_len  : 6;
66   unsigned int src_id_type : 2;
67   unsigned int dst_id_len  : 6;
68   unsigned int dst_id_type : 2;
69   SilcUInt8 refcnt;                      /* Reference counter */
70   unsigned int is_router   : 1;          /* Set if router stream */
71   unsigned int destroyed   : 1;          /* Set if destroyed */
72 };
73
74 /* Initial size of stream buffers */
75 #define SILC_PACKET_DEFAULT_SIZE  1024
76
77 /* Header length without source and destination ID's. */
78 #define SILC_PACKET_HEADER_LEN 10
79
80 /* Minimum length of SILC Packet Header. This much is decrypted always
81    when packet is received to be able to get all the relevant data out
82    from the header. */
83 #define SILC_PACKET_MIN_HEADER_LEN 16
84
85 /* Maximum padding length */
86 #define SILC_PACKET_MAX_PADLEN 128
87
88 /* Default padding length */
89 #define SILC_PACKET_DEFAULT_PADLEN 16
90
91 /* Minimum packet length */
92 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
93
94
95 /* Macros */
96
97 /* Returns true length of the packet. */
98 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
99 do {                                                                     \
100   SILC_GET16_MSB((__ret_truelen), (__packetdata));                       \
101   (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4];    \
102 } while(0)
103
104 /* Calculates the data length with given header length.  This macro
105    can be used to check whether the data_len with header_len exceeds
106    SILC_PACKET_MAX_LEN.  If it does, this returns the new data_len
107    so that the SILC_PACKET_MAX_LEN is not exceeded.  If the data_len
108    plus header_len fits SILC_PACKET_MAX_LEN the returned data length
109    is the data_len given as argument. */
110 #define SILC_PACKET_DATALEN(data_len, header_len)                         \
111   ((data_len + header_len) > SILC_PACKET_MAX_LEN ?                        \
112    data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
113
114 /* Calculates the length of the padding in the packet. */
115 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen)               \
116 do {                                                                        \
117   __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                  \
118               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN));  \
119   if (__padlen < 8)                                                         \
120     __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
121 } while(0)
122
123 /* Returns the length of the padding up to the maximum length, which
124    is 128 bytes.*/
125 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen)          \
126 do {                                                                       \
127   __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) %                     \
128               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
129 } while(0)
130
131 /* EOS callback */
132 #define SILC_PACKET_CALLBACK_EOS(s)                                     \
133 do {                                                                    \
134   (s)->engine->callbacks->eos((s)->engine, s,                           \
135                               (s)->engine->callback_context,            \
136                               (s)->stream_context);                     \
137 } while(0)
138
139 /* Error callback */
140 #define SILC_PACKET_CALLBACK_ERROR(s, err)                              \
141 do {                                                                    \
142   (s)->engine->callbacks->error((s)->engine, s, err,                    \
143                                 (s)->engine->callback_context,          \
144                                 (s)->stream_context);                   \
145 } while(0)
146
147
148 /************************ Static utility functions **************************/
149
150 static void silc_packet_read_process(SilcPacketStream stream);
151
152 /* Our stream IO notifier callback. */
153
154 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
155                                   void *context)
156 {
157   SilcPacketStream ps = context;
158   int ret;
159
160   silc_mutex_lock(ps->lock);
161
162   if (ps->destroyed) {
163     silc_mutex_unlock(ps->lock);
164     return;
165   }
166
167   switch (status) {
168
169   case SILC_STREAM_CAN_WRITE:
170     if (!silc_buffer_headlen(&ps->outbuf)) {
171       silc_mutex_unlock(ps->lock);
172       return;
173     }
174
175     SILC_LOG_DEBUG(("Writing pending data to stream"));
176
177     /* Write pending data to stream */
178     while (silc_buffer_len(&ps->outbuf) > 0) {
179       ret = silc_stream_write(ps->stream, ps->outbuf.data,
180                               silc_buffer_len(&ps->outbuf));
181       if (ret == 0) {
182         /* EOS */
183         silc_buffer_reset(&ps->outbuf);
184         silc_mutex_unlock(ps->lock);
185         SILC_PACKET_CALLBACK_EOS(ps);
186         return;
187       }
188
189       if (ret == -2) {
190         /* Error */
191         silc_buffer_reset(&ps->outbuf);
192         silc_mutex_unlock(ps->lock);
193         SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
194         return;
195       }
196
197       if (ret == -1) {
198         /* Cannot write now, write later. */
199         silc_mutex_unlock(ps->lock);
200         return;
201       }
202
203       /* Wrote data */
204       silc_buffer_pull(&ps->outbuf, ret);
205     }
206
207     silc_buffer_reset(&ps->outbuf);
208
209     silc_mutex_unlock(ps->lock);
210     break;
211
212   case SILC_STREAM_CAN_READ:
213     SILC_LOG_DEBUG(("Reading data from stream"));
214
215     /* Make sure we have fair amount of free space in inbuf */
216     if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
217       if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
218                                SILC_PACKET_DEFAULT_SIZE * 2)) {
219         silc_mutex_unlock(ps->lock);
220         return;
221       }
222
223     /* Read data from stream */
224     ret = silc_stream_read(ps->stream, ps->inbuf.tail,
225                            silc_buffer_taillen(&ps->inbuf));
226
227     if (ret == 0) {
228       /* EOS */
229       silc_buffer_reset(&ps->inbuf);
230       silc_mutex_unlock(ps->lock);
231       SILC_PACKET_CALLBACK_EOS(ps);
232       return;
233     }
234
235     if (ret == -2) {
236       /* Error */
237       silc_buffer_reset(&ps->inbuf);
238       silc_mutex_unlock(ps->lock);
239       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
240       return;
241     }
242
243     if (ret == -1) {
244       /* Cannot read now, do it later. */
245       silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
246       silc_mutex_unlock(ps->lock);
247       return;
248     }
249
250     /* Now process the data */
251     silc_buffer_pull_tail(&ps->inbuf, ret);
252     silc_packet_read_process(ps);
253
254     silc_mutex_unlock(ps->lock);
255     break;
256
257   default:
258     silc_mutex_unlock(ps->lock);
259     break;
260   }
261 }
262
263 /* Allocate packet */
264
265 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
266 {
267   SilcPacket packet;
268
269   SILC_LOG_DEBUG(("Packet pool count %d",
270                   silc_list_count(engine->packet_pool)));
271
272   silc_mutex_lock(engine->lock);
273
274   /* Get packet from freelist or allocate new one. */
275   packet = silc_list_get(engine->packet_pool);
276   if (!packet) {
277     void *tmp;
278
279     silc_mutex_unlock(engine->lock);
280
281     packet = silc_calloc(1, sizeof(*packet));
282     if (!packet)
283       return NULL;
284
285     SILC_LOG_DEBUG(("Allocating new packet %p", packet));
286
287     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
288     if (!tmp) {
289       silc_free(packet);
290       return NULL;
291     }
292     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
293     silc_buffer_reset(&packet->buffer);
294
295     return packet;
296   }
297
298   SILC_LOG_DEBUG(("Get packet %p", packet));
299
300   /* Delete from freelist */
301   silc_list_del(engine->packet_pool, packet);
302
303   silc_mutex_unlock(engine->lock);
304
305   return packet;
306 }
307
308
309 /******************************** Packet API ********************************/
310
311 /* Allocate new packet engine */
312
313 SilcPacketEngine
314 silc_packet_engine_start(SilcRng rng, SilcBool router,
315                          SilcPacketCallbacks *callbacks,
316                          void *callback_context)
317 {
318   SilcPacketEngine engine;
319   SilcPacket packet;
320   int i;
321   void *tmp;
322
323   SILC_LOG_DEBUG(("Starting new packet engine"));
324
325   if (!callbacks)
326     return NULL;
327   if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
328     return NULL;
329
330   engine = silc_calloc(1, sizeof(*engine));
331   if (!engine)
332     return NULL;
333
334   engine->rng = rng;
335   engine->local_is_router = router;
336   engine->callbacks = callbacks;
337   engine->callback_context = callback_context;
338   silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
339   silc_mutex_alloc(&engine->lock);
340
341   /* Allocate packet free list */
342   silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
343   for (i = 0; i < 5; i++) {
344     packet = silc_calloc(1, sizeof(*packet));
345     if (!packet)
346       return NULL;
347
348     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
349     if (!tmp)
350       return NULL;
351     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
352     silc_buffer_reset(&packet->buffer);
353
354     silc_list_add(engine->packet_pool, packet);
355   }
356   silc_list_start(engine->packet_pool);
357
358   return engine;
359 }
360
361 /* Stop packet engine */
362
363 void silc_packet_engine_stop(SilcPacketEngine engine)
364 {
365
366   SILC_LOG_DEBUG(("Stopping packet engine"));
367
368   if (!engine)
369     return;
370
371   /* XXX */
372
373   silc_free(engine);
374 }
375
376 /* Create new packet stream */
377
378 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
379                                            SilcSchedule schedule,
380                                            SilcStream stream)
381 {
382   SilcPacketStream ps;
383   void *tmp;
384
385   SILC_LOG_DEBUG(("Creating new packet stream"));
386
387   if (!engine || !stream)
388     return NULL;
389
390   ps = silc_calloc(1, sizeof(*ps));
391   if (!ps)
392     return NULL;
393
394   ps->engine = engine;
395   ps->stream = stream;
396   ps->refcnt++;
397
398   /* Allocate buffers */
399   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
400   if (!tmp)
401     return NULL;
402   silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
403   silc_buffer_reset(&ps->inbuf);
404   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
405   if (!tmp)
406     return NULL;
407   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
408   silc_buffer_reset(&ps->outbuf);
409
410   /* Initialize packet procesors list */
411   ps->process = silc_dlist_init();
412
413   /* Set IO notifier callback */
414   silc_stream_set_notifier(ps->stream, schedule, silc_packet_stream_io, ps);
415
416   silc_mutex_alloc(&ps->lock);
417
418   /* Add to engine */
419   silc_mutex_lock(engine->lock);
420   silc_list_add(engine->streams, ps);
421   silc_mutex_unlock(engine->lock);
422
423   return ps;
424 }
425
426 /* Destroy packet stream */
427
428 void silc_packet_stream_destroy(SilcPacketStream stream)
429 {
430   if (!stream)
431     return;
432
433   if (stream->refcnt > 1) {
434     stream->destroyed = TRUE;
435     return;
436   }
437
438   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
439
440   /* Delete from engine */
441   silc_mutex_lock(stream->engine->lock);
442   silc_list_del(stream->engine->streams, stream);
443   silc_mutex_unlock(stream->engine->lock);
444
445   /* Clear and free buffers */
446   silc_buffer_clear(&stream->inbuf);
447   silc_buffer_clear(&stream->outbuf);
448   silc_buffer_purge(&stream->inbuf);
449   silc_buffer_purge(&stream->outbuf);
450
451   /* XXX */
452
453   /* Destroy the underlaying stream */
454   silc_stream_destroy(stream->stream);
455
456   silc_dlist_uninit(stream->process);
457   silc_mutex_free(stream->lock);
458   silc_free(stream);
459 }
460
461 /* Marks as router stream */
462
463 void silc_packet_stream_set_router(SilcPacketStream stream)
464 {
465   stream->is_router = TRUE;
466 }
467
468
469 /* Links `callbacks' to `stream' for specified packet types */
470
471 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
472                                            SilcPacketCallbacks *callbacks,
473                                            void *callback_context,
474                                            int priority, va_list ap)
475 {
476   SilcPacketProcess p, e;
477   SilcInt32 packet_type;
478   int i;
479
480   SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
481
482   if (!callbacks)
483     return FALSE;
484   if (!callbacks->packet_receive)
485     return FALSE;
486
487   p = silc_calloc(1, sizeof(*p));
488   if (!p)
489     return FALSE;
490
491   p->priority = priority;
492   p->callbacks = callbacks;
493   p->callback_context = callback_context;
494
495   silc_mutex_lock(stream->lock);
496
497   if (!stream->process) {
498     stream->process = silc_dlist_init();
499     if (!stream->process) {
500       silc_mutex_unlock(stream->lock);
501       return FALSE;
502     }
503   }
504
505   /* According to priority set the procesor to correct position.  First
506      entry has the highest priority */
507   silc_dlist_start(stream->process);
508   while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
509     if (p->priority > e->priority) {
510       silc_dlist_insert(stream->process, p);
511       break;
512     }
513   }
514   if (!e)
515     silc_dlist_add(stream->process, p);
516
517   /* Get packet types to process */
518   i = 1;
519   while (1) {
520     packet_type = va_arg(ap, SilcInt32);
521
522     if (packet_type == SILC_PACKET_ANY)
523       break;
524
525     if (packet_type == -1)
526       break;
527
528     p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
529     if (!p->types) {
530       silc_mutex_unlock(stream->lock);
531       return FALSE;
532     }
533
534     p->types[i - 1] = (SilcPacketType)packet_type;
535     i++;
536   }
537   if (p->types)
538     p->types[i - 1] = 0;
539
540   silc_mutex_unlock(stream->lock);
541
542   silc_packet_stream_ref(stream);
543
544   return TRUE;
545 }
546
547 /* Links `callbacks' to `stream' for specified packet types */
548
549 SilcBool silc_packet_stream_link(SilcPacketStream stream,
550                                  SilcPacketCallbacks *callbacks,
551                                  void *callback_context,
552                                  int priority, ...)
553 {
554   va_list ap;
555   SilcBool ret;
556
557   va_start(ap, priority);
558   ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
559                                    priority, ap);
560   va_end(ap);
561
562   return ret;
563 }
564
565 /* Unlinks `callbacks' from `stream'. */
566
567 void silc_packet_stream_unlink(SilcPacketStream stream,
568                                SilcPacketCallbacks *callbacks,
569                                void *callback_context)
570 {
571   SilcPacketProcess p;
572
573   SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
574                   callbacks, stream));
575
576   silc_mutex_lock(stream->lock);
577
578   silc_dlist_start(stream->process);
579   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
580     if (p->callbacks == callbacks &&
581         p->callback_context == callback_context) {
582       silc_dlist_del(stream->process, p);
583       silc_free(p);
584       break;
585     }
586
587   if (!silc_dlist_count(stream->process)) {
588     silc_dlist_uninit(stream->process);
589     stream->process = NULL;
590   }
591
592   silc_mutex_unlock(stream->lock);
593
594   silc_packet_stream_unref(stream);
595 }
596
597 /* Reference packet stream */
598
599 void silc_packet_stream_ref(SilcPacketStream stream)
600 {
601   silc_mutex_lock(stream->lock);
602   stream->refcnt++;
603   silc_mutex_unlock(stream->lock);
604 }
605
606 /* Unreference packet stream */
607
608 void silc_packet_stream_unref(SilcPacketStream stream)
609 {
610   silc_mutex_lock(stream->lock);
611   stream->refcnt--;
612   silc_mutex_unlock(stream->lock);
613   if (stream->refcnt == 0)
614     silc_packet_stream_destroy(stream);
615 }
616
617 /* Return engine */
618
619 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
620 {
621   return stream->engine;
622 }
623
624 /* Set application context for packet stream */
625
626 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
627 {
628   silc_mutex_lock(stream->lock);
629   stream->stream_context = stream_context;
630   silc_mutex_unlock(stream->lock);
631 }
632
633 /* Return application context from packet stream */
634
635 void *silc_packet_get_context(SilcPacketStream stream)
636 {
637   void *context;
638   silc_mutex_lock(stream->lock);
639   context = stream->stream_context;
640   silc_mutex_unlock(stream->lock);
641   return context;
642 }
643
644 /* Return underlaying stream */
645
646 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
647 {
648   return stream->stream;
649 }
650
651 /* Set ciphers for packet stream */
652
653 void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send,
654                              SilcCipher receive)
655 {
656   SILC_LOG_DEBUG(("Setting new ciphers to packet stream"));
657   silc_mutex_lock(stream->lock);
658   stream->send_key = send;
659   stream->receive_key = receive;
660   silc_mutex_unlock(stream->lock);
661 }
662
663 /* Return current ciphers from packet stream */
664
665 SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send,
666                                  SilcCipher *receive)
667 {
668   if (!stream->send_key && !stream->receive_key)
669     return FALSE;
670
671   silc_mutex_lock(stream->lock);
672
673   if (send)
674     *send = stream->send_key;
675   if (receive)
676     *receive = stream->receive_key;
677
678   silc_mutex_unlock(stream->lock);
679
680   return TRUE;
681 }
682
683 /* Set HMACs for packet stream */
684
685 void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send,
686                            SilcHmac receive)
687 {
688   SILC_LOG_DEBUG(("Setting new HMACs to packet stream"));
689   silc_mutex_lock(stream->lock);
690   stream->send_hmac = send;
691   stream->receive_hmac = receive;
692   silc_mutex_unlock(stream->lock);
693 }
694
695 /* Return current HMACs from packet stream */
696
697 SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send,
698                                SilcHmac *receive)
699 {
700   if (!stream->send_hmac && !stream->receive_hmac)
701     return FALSE;
702
703   silc_mutex_lock(stream->lock);
704
705   if (send)
706     *send = stream->send_hmac;
707   if (receive)
708     *receive = stream->receive_hmac;
709
710   silc_mutex_unlock(stream->lock);
711
712   return TRUE;
713 }
714
715 /* Set SILC IDs to packet stream */
716
717 SilcBool silc_packet_set_ids(SilcPacketStream stream,
718                              SilcIdType src_id_type, const void *src_id,
719                              SilcIdType dst_id_type, const void *dst_id)
720 {
721   SilcUInt32 len;
722   unsigned char tmp[32];
723
724   if (!src_id && !dst_id)
725     return FALSE;
726
727   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
728
729   silc_mutex_lock(stream->lock);
730
731   if (src_id) {
732     silc_free(stream->src_id);
733     if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
734       silc_mutex_unlock(stream->lock);
735       return FALSE;
736     }
737     stream->src_id = silc_memdup(tmp, len);
738     if (!stream->src_id) {
739       silc_mutex_unlock(stream->lock);
740       return FALSE;
741     }
742     stream->src_id_type = src_id_type;
743     stream->src_id_len = len;
744   }
745
746   if (dst_id) {
747     silc_free(stream->dst_id);
748     if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
749       silc_mutex_unlock(stream->lock);
750       return FALSE;
751     }
752     stream->dst_id = silc_memdup(tmp, len);
753     if (!stream->dst_id) {
754       silc_mutex_unlock(stream->lock);
755       return FALSE;
756     }
757     stream->dst_id_type = dst_id_type;
758     stream->dst_id_len = len;
759   }
760
761   silc_mutex_unlock(stream->lock);
762
763   return TRUE;
764 }
765
766 /* Free packet */
767
768 void silc_packet_free(SilcPacket packet)
769 {
770   SilcPacketStream stream = packet->stream;
771
772   SILC_LOG_DEBUG(("Freeing packet %p", packet));
773
774 #if defined(SILC_DEBUG)
775   /* Check for double free */
776   assert(packet->stream != NULL);
777 #endif /* SILC_DEBUG */
778
779   silc_mutex_lock(stream->engine->lock);
780
781   packet->stream = NULL;
782   packet->src_id = packet->dst_id = NULL;
783   silc_buffer_reset(&packet->buffer);
784
785   /* Put the packet back to freelist */
786   silc_list_add(stream->engine->packet_pool, packet);
787
788   silc_mutex_unlock(stream->engine->lock);
789 }
790
791 /****************************** Packet Sending ******************************/
792
793 /* Prepare outgoing data buffer for packet sending.  Returns the
794    pointer to that buffer into the `packet'. */
795
796 static SilcBool silc_packet_send_prepare(SilcPacketStream stream,
797                                          SilcUInt32 totlen,
798                                          SilcHmac hmac,
799                                          SilcBuffer packet)
800 {
801   unsigned char *oldptr;
802   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
803
804   totlen += mac_len;
805
806   /* Allocate more space if needed */
807   if (silc_buffer_taillen(&stream->outbuf) < totlen) {
808     if (!silc_buffer_realloc(&stream->outbuf,
809                              silc_buffer_truelen(&stream->outbuf) + totlen))
810       return FALSE;
811   }
812
813   /* Pull data area for the new packet, and return pointer to the start of
814      the data area and save the pointer in to the `packet'.  MAC is pulled
815      later after it's computed. */
816   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
817   silc_buffer_set(packet, oldptr, totlen);
818   silc_buffer_push_tail(packet, mac_len);
819
820   return TRUE;
821 }
822
823 /* Internal routine to send packet */
824
825 static SilcBool silc_packet_send_raw(SilcPacketStream stream,
826                                      SilcPacketType type,
827                                      SilcPacketFlags flags,
828                                      SilcIdType src_id_type,
829                                      unsigned char *src_id,
830                                      SilcUInt32 src_id_len,
831                                      SilcIdType dst_id_type,
832                                      unsigned char *dst_id,
833                                      SilcUInt32 dst_id_len,
834                                      const unsigned char *data,
835                                      SilcUInt32 data_len,
836                                      SilcCipher cipher,
837                                      SilcHmac hmac)
838 {
839   unsigned char tmppad[SILC_PACKET_MAX_PADLEN];
840   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
841   int i, enclen, truelen, padlen;
842   SilcBufferStruct packet;
843
844   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d,"
845                   "data len %d", silc_get_packet_name(type), stream->send_psn,
846                   flags, src_id_type, dst_id_type, data_len));
847
848   /* Get the true length of the packet. This is saved as payload length
849      into the packet header.  This does not include the length of the
850      padding. */
851   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
852                                             src_id_len + dst_id_len));
853   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
854                       src_id_len + dst_id_len);
855
856   /* We automatically figure out the packet structure from the packet
857      type and flags, and calculate correct length.  Private messages with
858      private keys and channel messages are special packets as their
859      payload is encrypted already. */
860   if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
861        flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
862       type == SILC_PACKET_CHANNEL_MESSAGE) {
863
864     /* Padding is calculated from header + IDs */
865     SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
866                         src_id_len +
867                         dst_id_len), block_len, padlen);
868
869     /* Length to encrypt, header + IDs + padding. */
870     enclen = SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len + padlen;
871   } else {
872
873     /* Padding is calculated from true length of the packet */
874     if (flags & SILC_PACKET_FLAG_LONG_PAD)
875       SILC_PACKET_PADLEN_MAX(truelen, block_len, padlen);
876     else
877       SILC_PACKET_PADLEN(truelen, block_len, padlen);
878
879     enclen += padlen;
880   }
881
882   /* Remove implementation specific flags */
883   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
884
885   /* Get random padding */
886   for (i = 0; i < padlen; i++) tmppad[i] =
887                                  silc_rng_get_byte_fast(stream->engine->rng);
888
889   silc_mutex_lock(stream->lock);
890
891   /* Get packet pointer from the outgoing buffer */
892   if (!silc_packet_send_prepare(stream, truelen + padlen, hmac, &packet)) {
893     silc_mutex_unlock(stream->lock);
894     return FALSE;
895   }
896
897   /* Create the packet.  This creates the SILC header, adds padding, and
898      the actual packet data. */
899   i = silc_buffer_format(&packet,
900                          SILC_STR_UI_SHORT(truelen),
901                          SILC_STR_UI_CHAR(flags),
902                          SILC_STR_UI_CHAR(type),
903                          SILC_STR_UI_CHAR(padlen),
904                          SILC_STR_UI_CHAR(0),
905                          SILC_STR_UI_CHAR(src_id_len),
906                          SILC_STR_UI_CHAR(dst_id_len),
907                          SILC_STR_UI_CHAR(src_id_type),
908                          SILC_STR_UI_XNSTRING(src_id, src_id_len),
909                          SILC_STR_UI_CHAR(dst_id_type),
910                          SILC_STR_UI_XNSTRING(dst_id, dst_id_len),
911                          SILC_STR_UI_XNSTRING(tmppad, padlen),
912                          SILC_STR_UI_XNSTRING(data, data_len),
913                          SILC_STR_END);
914   if (i < 0) {
915     silc_mutex_unlock(stream->lock);
916     return FALSE;
917   }
918
919   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
920                    packet.data, silc_buffer_len(&packet));
921
922   /* Encrypt the packet */
923   if (cipher) {
924     SILC_LOG_DEBUG(("Encrypting packet"));
925     if (!silc_cipher_encrypt(cipher, packet.data, packet.data,
926                              enclen, NULL)) {
927       SILC_LOG_ERROR(("Packet encryption failed"));
928       silc_mutex_unlock(stream->lock);
929       return FALSE;
930     }
931   }
932
933   /* Compute HMAC */
934   if (hmac) {
935     unsigned char psn[4];
936     SilcUInt32 mac_len;
937
938     /* MAC is computed from the entire encrypted packet data, and put
939        to the end of the packet. */
940     silc_hmac_init(hmac);
941     SILC_PUT32_MSB(stream->send_psn, psn);
942     silc_hmac_update(hmac, psn, 4);
943     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
944     silc_hmac_final(hmac, packet.tail, &mac_len);
945     silc_buffer_pull_tail(&packet, mac_len);
946     stream->send_psn++;
947   }
948
949   /* Write the packet to the stream */
950   while (silc_buffer_len(&stream->outbuf) > 0) {
951     i = silc_stream_write(stream->stream, stream->outbuf.data,
952                           silc_buffer_len(&stream->outbuf));
953     if (i == 0) {
954       /* EOS */
955       silc_buffer_reset(&stream->outbuf);
956       silc_mutex_unlock(stream->lock);
957       SILC_PACKET_CALLBACK_EOS(stream);
958       return FALSE;
959     }
960
961     if (i == -2) {
962       /* Error */
963       silc_buffer_reset(&stream->outbuf);
964       silc_mutex_unlock(stream->lock);
965       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_WRITE);
966       return FALSE;
967     }
968
969     if (i == -1) {
970       /* Cannot write now, write later. */
971       silc_mutex_unlock(stream->lock);
972       return TRUE;
973     }
974
975     /* Wrote data */
976     silc_buffer_pull(&stream->outbuf, i);
977   }
978   silc_buffer_reset(&stream->outbuf);
979
980   silc_mutex_unlock(stream->lock);
981   return TRUE;
982 }
983
984 /* Sends a packet */
985
986 SilcBool silc_packet_send(SilcPacketStream stream,
987                           SilcPacketType type, SilcPacketFlags flags,
988                           const unsigned char *data, SilcUInt32 data_len)
989 {
990   return silc_packet_send_raw(stream, type, flags,
991                               stream->src_id_type,
992                               stream->src_id,
993                               stream->src_id_len,
994                               stream->dst_id_type,
995                               stream->dst_id,
996                               stream->dst_id_len,
997                               data, data_len,
998                               stream->send_key,
999                               stream->send_hmac);
1000 }
1001
1002 /* Sends a packet, extended routine */
1003
1004 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1005                               SilcPacketType type, SilcPacketFlags flags,
1006                               SilcIdType src_id_type, void *src_id,
1007                               SilcIdType dst_id_type, void *dst_id,
1008                               const unsigned char *data, SilcUInt32 data_len,
1009                               SilcCipher cipher, SilcHmac hmac)
1010 {
1011   unsigned char src_id_data[32], dst_id_data[32];
1012   SilcUInt32 src_id_len, dst_id_len;
1013
1014   if (src_id)
1015     if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1016                         sizeof(src_id_data), &src_id_len))
1017       return FALSE;
1018   if (dst_id)
1019     if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1020                         sizeof(dst_id_data), &dst_id_len))
1021       return FALSE;
1022
1023   return silc_packet_send_raw(stream, type, flags,
1024                               src_id ? src_id_type : stream->src_id_type,
1025                               src_id ? src_id_data : stream->src_id,
1026                               src_id ? src_id_len : stream->src_id_len,
1027                               dst_id ? dst_id_type : stream->dst_id_type,
1028                               dst_id ? dst_id_data : stream->dst_id,
1029                               dst_id ? dst_id_len : stream->dst_id_len,
1030                               data, data_len,
1031                               cipher ? cipher : stream->send_key,
1032                               hmac ? hmac : stream->send_hmac);
1033 }
1034
1035
1036 /***************************** Packet Receiving *****************************/
1037
1038 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1039
1040 static SilcBool silc_packet_check_mac(SilcHmac hmac,
1041                                       const unsigned char *data,
1042                                       SilcUInt32 data_len,
1043                                       const unsigned char *packet_mac,
1044                                       SilcUInt32 sequence)
1045 {
1046   /* Check MAC */
1047   if (hmac) {
1048     unsigned char mac[32], psn[4];
1049     SilcUInt32 mac_len;
1050
1051     SILC_LOG_DEBUG(("Verifying MAC"));
1052
1053     /* Compute HMAC of packet */
1054     silc_hmac_init(hmac);
1055     SILC_PUT32_MSB(sequence, psn);
1056     silc_hmac_update(hmac, psn, 4);
1057     silc_hmac_update(hmac, data, data_len);
1058     silc_hmac_final(hmac, mac, &mac_len);
1059
1060     /* Compare the MAC's */
1061     if (memcmp(packet_mac, mac, mac_len)) {
1062       SILC_LOG_DEBUG(("MAC failed"));
1063       return FALSE;
1064     }
1065
1066     SILC_LOG_DEBUG(("MAC is Ok"));
1067   }
1068
1069   return TRUE;
1070 }
1071
1072 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1073    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1074
1075 static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1076                                SilcUInt32 sequence, SilcBuffer buffer,
1077                                SilcBool normal)
1078 {
1079   if (normal == TRUE) {
1080     if (cipher) {
1081       /* Decrypt rest of the packet */
1082       SILC_LOG_DEBUG(("Decrypting the packet"));
1083       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1084                                silc_buffer_len(buffer), NULL))
1085         return -1;
1086     }
1087     return 0;
1088
1089   } else {
1090     /* Decrypt rest of the header plus padding */
1091     if (cipher) {
1092       SilcUInt16 len;
1093       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1094
1095       SILC_LOG_DEBUG(("Decrypting the header"));
1096
1097       /* Padding length + src id len + dst id len + header length - 16
1098          bytes already decrypted, gives the rest of the encrypted packet */
1099       silc_buffer_push(buffer, block_len);
1100       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1101               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1102              block_len);
1103       silc_buffer_pull(buffer, block_len);
1104
1105       if (len > silc_buffer_len(buffer)) {
1106         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1107                         "packet dropped"));
1108         return -1;
1109       }
1110       if (!silc_cipher_decrypt(cipher, buffer->data, buffer->data,
1111                                len, NULL))
1112         return -1;
1113     }
1114
1115     return 1;
1116   }
1117 }
1118
1119 /* Parses the packet. This is called when a whole packet is ready to be
1120    parsed. The buffer sent must be already decrypted before calling this
1121    function. */
1122
1123 static SilcBool silc_packet_parse(SilcPacket packet)
1124 {
1125   SilcBuffer buffer = &packet->buffer;
1126   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1127   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1128   int len, ret;
1129
1130   SILC_LOG_DEBUG(("Parsing incoming packet"));
1131
1132   /* Parse the buffer.  This parses the SILC header of the packet. */
1133   len = silc_buffer_unformat(buffer,
1134                              SILC_STR_OFFSET(6),
1135                              SILC_STR_UI_CHAR(&src_id_len),
1136                              SILC_STR_UI_CHAR(&dst_id_len),
1137                              SILC_STR_UI_CHAR(&src_id_type),
1138                              SILC_STR_END);
1139   if (len == -1) {
1140     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1141     return FALSE;
1142   }
1143
1144   if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
1145       dst_id_len > SILC_PACKET_MAX_ID_LEN) {
1146     SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1147                     packet->src_id_len, packet->dst_id_len));
1148     return FALSE;
1149   }
1150
1151   ret = silc_buffer_unformat(buffer,
1152                              SILC_STR_OFFSET(len),
1153                              SILC_STR_UI_XNSTRING(&packet->src_id,
1154                                                   src_id_len),
1155                              SILC_STR_UI_CHAR(&dst_id_type),
1156                              SILC_STR_UI_XNSTRING(&packet->dst_id,
1157                                                   dst_id_len),
1158                              SILC_STR_OFFSET(padlen),
1159                              SILC_STR_END);
1160   if (ret == -1) {
1161     SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1162     return FALSE;
1163   }
1164
1165   if (src_id_type > SILC_ID_CHANNEL ||
1166       dst_id_type > SILC_ID_CHANNEL) {
1167     SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1168                     src_id_type, dst_id_type));
1169     return FALSE;
1170   }
1171
1172   packet->src_id_len = src_id_len;
1173   packet->dst_id_len = dst_id_len;
1174   packet->src_id_type = src_id_type;
1175   packet->dst_id_type = dst_id_type;
1176
1177   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_len(buffer)),
1178                    buffer->data, silc_buffer_len(buffer));
1179
1180   /* Pull SILC header and padding from packet to get the data payload */
1181   silc_buffer_pull(buffer, SILC_PACKET_HEADER_LEN +
1182                    packet->src_id_len + packet->dst_id_len + padlen);
1183
1184   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1185                   silc_get_packet_name(packet->type)));
1186
1187   return TRUE;
1188 }
1189
1190 /* Dispatch packet to application.  Called with stream->lock locked. */
1191
1192 static void silc_packet_dispatch(SilcPacket packet)
1193 {
1194   SilcPacketStream stream = packet->stream;
1195   SilcPacketProcess p;
1196   SilcBool default_sent = FALSE;
1197   SilcPacketType *pt;
1198
1199   /* Parse the packet */
1200   if (!silc_packet_parse(packet)) {
1201     silc_mutex_unlock(packet->stream->lock);
1202     SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1203     silc_mutex_lock(packet->stream->lock);
1204     silc_packet_free(packet);
1205     return;
1206   }
1207
1208   /* Dispatch packet to all packet processors that want it */
1209
1210   if (!stream->process) {
1211     /* Send to default processor as no others exist */
1212     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1213     silc_mutex_unlock(packet->stream->lock);
1214     if (!stream->engine->callbacks->
1215         packet_receive(stream->engine, stream, packet,
1216                        stream->engine->callback_context,
1217                        stream->stream_context))
1218       silc_packet_free(packet);
1219     silc_mutex_lock(packet->stream->lock);
1220     return;
1221   }
1222
1223   silc_dlist_start(stream->process);
1224   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1225
1226     /* If priority is 0 or less, we send to default processor first
1227        because default processor has 0 priority */
1228     if (!default_sent && p->priority <= 0) {
1229       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1230       default_sent = TRUE;
1231       silc_mutex_unlock(packet->stream->lock);
1232       if (stream->engine->callbacks->
1233           packet_receive(stream->engine, stream, packet,
1234                          stream->engine->callback_context,
1235                          stream->stream_context)) {
1236         silc_mutex_lock(packet->stream->lock);
1237         return;
1238       }
1239       silc_mutex_lock(packet->stream->lock);
1240     }
1241
1242     /* Send to processor */
1243     if (!p->types) {
1244       /* Send all packet types */
1245       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1246       silc_mutex_unlock(packet->stream->lock);
1247       if (p->callbacks->packet_receive(stream->engine, stream, packet,
1248                                        p->callback_context,
1249                                        stream->stream_context)) {
1250         silc_mutex_lock(packet->stream->lock);
1251         return;
1252       }
1253       silc_mutex_lock(packet->stream->lock);
1254     } else {
1255       /* Send specific types */
1256       for (pt = p->types; *pt; pt++) {
1257         if (*pt != packet->type)
1258           continue;
1259         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1260         silc_mutex_unlock(packet->stream->lock);
1261         if (p->callbacks->packet_receive(stream->engine, stream, packet,
1262                                          p->callback_context,
1263                                          stream->stream_context)) {
1264           silc_mutex_lock(packet->stream->lock);
1265           return;
1266         }
1267         silc_mutex_lock(packet->stream->lock);
1268         break;
1269       }
1270     }
1271   }
1272
1273   if (!default_sent) {
1274     /* Send to default processor as it has not been sent yet */
1275     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1276     silc_mutex_unlock(packet->stream->lock);
1277     if (stream->engine->callbacks->
1278         packet_receive(stream->engine, stream, packet,
1279                        stream->engine->callback_context,
1280                        stream->stream_context)) {
1281       silc_mutex_lock(packet->stream->lock);
1282       return;
1283     }
1284     silc_mutex_lock(packet->stream->lock);
1285   }
1286
1287   /* If we got here, no one wanted the packet, so drop it */
1288   silc_packet_free(packet);
1289 }
1290
1291 /* Process incoming data and parse packets.  Called with stream->lock
1292    locked. */
1293
1294 static void silc_packet_read_process(SilcPacketStream stream)
1295 {
1296   SilcPacket packet;
1297   SilcUInt16 packetlen;
1298   SilcUInt32 paddedlen, mac_len, block_len;
1299   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1300   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
1301   SilcBool normal = TRUE;
1302   int ret;
1303
1304   /* Parse the packets from the data */
1305   while (silc_buffer_len(&stream->inbuf) > 0) {
1306
1307     if (silc_buffer_len(&stream->inbuf) < SILC_PACKET_MIN_HEADER_LEN) {
1308       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1309       return;
1310     }
1311
1312     if (stream->receive_hmac)
1313       mac_len = silc_hmac_len(stream->receive_hmac);
1314     else
1315       mac_len = 0;
1316
1317     /* Decrypt first block of the packet to get the length field out */
1318     if (stream->receive_key) {
1319       block_len = silc_cipher_get_block_len(stream->receive_key);
1320       memcpy(iv, silc_cipher_get_iv(stream->receive_key), block_len);
1321       silc_cipher_decrypt(stream->receive_key, stream->inbuf.data,
1322                           tmp, block_len, iv);
1323       header = tmp;
1324     } else {
1325       block_len = SILC_PACKET_MIN_HEADER_LEN;
1326       header = stream->inbuf.data;
1327     }
1328
1329     /* Get packet length and full packet length with padding */
1330     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
1331
1332     /* Sanity checks */
1333     if (packetlen < SILC_PACKET_MIN_LEN) {
1334       SILC_LOG_ERROR(("Received too short packet"));
1335       silc_mutex_unlock(stream->lock);
1336       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
1337       silc_mutex_lock(stream->lock);
1338       memset(tmp, 0, sizeof(tmp));
1339       silc_buffer_reset(&stream->inbuf);
1340       return;
1341     }
1342
1343     if (silc_buffer_len(&stream->inbuf) < paddedlen + mac_len) {
1344       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
1345                       "(%d bytes)",
1346                       paddedlen + mac_len - silc_buffer_len(&stream->inbuf)));
1347       memset(tmp, 0, sizeof(tmp));
1348       return;
1349     }
1350
1351     /* Check MAC of the packet */
1352     if (!silc_packet_check_mac(stream->receive_hmac, stream->inbuf.data,
1353                                paddedlen, stream->inbuf.data + paddedlen,
1354                                stream->receive_psn)) {
1355       silc_mutex_unlock(stream->lock);
1356       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
1357       silc_mutex_lock(stream->lock);
1358       memset(tmp, 0, sizeof(tmp));
1359       silc_buffer_reset(&stream->inbuf);
1360       return;
1361     }
1362
1363     /* Get packet */
1364     packet = silc_packet_alloc(stream->engine);
1365     if (!packet) {
1366       silc_mutex_unlock(stream->lock);
1367       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1368       silc_mutex_lock(stream->lock);
1369       memset(tmp, 0, sizeof(tmp));
1370       silc_buffer_reset(&stream->inbuf);
1371       return;
1372     }
1373
1374     /* Allocate more space to packet buffer, if needed */
1375     if (silc_buffer_truelen(&packet->buffer) < paddedlen) {
1376       if (!silc_buffer_realloc(&packet->buffer,
1377                                silc_buffer_truelen(&packet->buffer) +
1378                                (paddedlen -
1379                                 silc_buffer_truelen(&packet->buffer)))) {
1380         silc_mutex_unlock(stream->lock);
1381         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
1382         silc_mutex_lock(stream->lock);
1383         silc_packet_free(packet);
1384         memset(tmp, 0, sizeof(tmp));
1385         silc_buffer_reset(&stream->inbuf);
1386         return;
1387       }
1388     }
1389
1390     /* Parse packet header */
1391     packet->flags = (SilcPacketFlags)header[2];
1392     packet->type = (SilcPacketType)header[3];
1393
1394     if (stream->engine->local_is_router) {
1395       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1396           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1397         normal = FALSE;
1398       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
1399                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
1400                 stream->is_router == TRUE))
1401         normal = TRUE;
1402     } else {
1403       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
1404           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
1405         normal = FALSE;
1406       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
1407         normal = TRUE;
1408     }
1409
1410     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
1411                       stream->receive_psn, paddedlen + mac_len),
1412                      stream->inbuf.data, paddedlen + mac_len);
1413
1414     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
1415     silc_buffer_pull_tail(&packet->buffer, paddedlen);
1416     silc_buffer_put(&packet->buffer, header, block_len);
1417     silc_buffer_pull(&packet->buffer, block_len);
1418     silc_buffer_put(&packet->buffer, stream->inbuf.data + block_len,
1419                     paddedlen - block_len);
1420     if (stream->receive_key) {
1421       silc_cipher_set_iv(stream->receive_key, iv);
1422       ret = silc_packet_decrypt(stream->receive_key, stream->receive_hmac,
1423                                 stream->receive_psn, &packet->buffer, normal);
1424       if (ret < 0) {
1425         silc_mutex_unlock(stream->lock);
1426         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
1427         silc_mutex_lock(stream->lock);
1428         silc_packet_free(packet);
1429         memset(tmp, 0, sizeof(tmp));
1430         return;
1431       }
1432
1433       stream->receive_psn++;
1434     }
1435     silc_buffer_push(&packet->buffer, block_len);
1436
1437     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
1438     silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
1439
1440     /* Dispatch the packet to application */
1441     packet->stream = stream;
1442     silc_packet_dispatch(packet);
1443   }
1444
1445   silc_buffer_reset(&stream->inbuf);
1446 }
1447
1448
1449 /****************************** Packet Waiting ******************************/
1450
1451 /* Packet wait receive callback */
1452 static SilcBool
1453 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1454                                 SilcPacketStream stream,
1455                                 SilcPacket packet,
1456                                 void *callback_context,
1457                                 void *stream_context);
1458
1459 /* Packet waiting callbacks */
1460 static SilcPacketCallbacks silc_packet_wait_cbs =
1461 {
1462   silc_packet_wait_packet_receive, NULL, NULL
1463 };
1464
1465 /* Packet waiting context */
1466 typedef struct {
1467   SilcMutex wait_lock;
1468   SilcCond wait_cond;
1469   SilcList packet_queue;
1470   unsigned int stopped     : 1;
1471 } *SilcPacketWait;
1472
1473 /* Packet wait receive callback */
1474
1475 static SilcBool
1476 silc_packet_wait_packet_receive(SilcPacketEngine engine,
1477                                 SilcPacketStream stream,
1478                                 SilcPacket packet,
1479                                 void *callback_context,
1480                                 void *stream_context)
1481 {
1482   SilcPacketWait pw = callback_context;
1483
1484   /* Signal the waiting thread for a new packet */
1485   silc_mutex_lock(pw->wait_lock);
1486
1487   if (pw->stopped) {
1488     silc_mutex_unlock(pw->wait_lock);
1489     return FALSE;
1490   }
1491
1492   silc_list_add(pw->packet_queue, packet);
1493   silc_cond_broadcast(pw->wait_cond);
1494
1495   silc_mutex_unlock(pw->wait_lock);
1496
1497   return TRUE;
1498 }
1499
1500 /* Initialize packet waiting */
1501
1502 void *silc_packet_wait_init(SilcPacketStream stream, ...)
1503 {
1504   SilcPacketWait pw;
1505   SilcBool ret;
1506   va_list ap;
1507
1508   pw = silc_calloc(1, sizeof(*pw));
1509   if (!pw)
1510     return NULL;
1511
1512   /* Allocate mutex and conditional variable */
1513   if (!silc_mutex_alloc(&pw->wait_lock)) {
1514     silc_free(pw);
1515     return NULL;
1516   }
1517   if (!silc_cond_alloc(&pw->wait_cond)) {
1518     silc_mutex_free(pw->wait_lock);
1519     silc_free(pw);
1520     return NULL;
1521   }
1522
1523   /* Link to the packet stream for the requested packet types */
1524   va_start(ap, stream);
1525   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
1526                                    10000000, ap);
1527   va_end(ap);
1528   if (!ret) {
1529     silc_cond_free(pw->wait_cond);
1530     silc_mutex_free(pw->wait_lock);
1531     silc_free(pw);
1532     return NULL;
1533   }
1534
1535   /* Initialize packet queue */
1536   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
1537
1538   return (void *)pw;
1539 }
1540
1541 /* Uninitialize packet waiting */
1542
1543 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
1544 {
1545   SilcPacketWait pw = waiter;
1546   SilcPacket packet;
1547
1548   /* Signal any threads to stop waiting */
1549   silc_mutex_lock(pw->wait_lock);
1550   pw->stopped = TRUE;
1551   silc_cond_broadcast(pw->wait_cond);
1552   silc_mutex_unlock(pw->wait_lock);
1553
1554   /* Re-acquire lock and free resources */
1555   silc_mutex_lock(pw->wait_lock);
1556   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
1557
1558   /* Free any remaining packets */
1559   silc_list_start(pw->packet_queue);
1560   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
1561     silc_packet_free(packet);
1562
1563   silc_mutex_unlock(pw->wait_lock);
1564   silc_cond_free(pw->wait_cond);
1565   silc_mutex_free(pw->wait_lock);
1566   silc_free(pw);
1567 }
1568
1569 /* Blocks thread until a packet has been received. */
1570
1571 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
1572 {
1573   SilcPacketWait pw = waiter;
1574   SilcBool ret = FALSE;
1575
1576   silc_mutex_lock(pw->wait_lock);
1577
1578   /* Wait here until packet has arrived */
1579   while (silc_list_count(pw->packet_queue) == 0) {
1580     if (pw->stopped) {
1581       silc_mutex_unlock(pw->wait_lock);
1582       return -1;
1583     }
1584     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
1585   }
1586
1587   /* Return packet */
1588   silc_list_start(pw->packet_queue);
1589   *return_packet = silc_list_get(pw->packet_queue);
1590   silc_list_del(pw->packet_queue, *return_packet);
1591
1592   silc_mutex_unlock(pw->wait_lock);
1593
1594   return ret == TRUE ? 1 : 0;
1595 }