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