Fixed connection authentication protocol aborting.
[silc.git] / lib / silccore / silcpacket.c
1 /*
2
3   silcpacket.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2007 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 /* Per scheduler (which usually means per thread) data.  We put per scheduler
29    data here for accessing without locking.  SILC Schedule dictates that
30    tasks are dispatched in one thread, hence the per scheduler context. */
31 typedef struct {
32   SilcSchedule schedule;                 /* The scheduler */
33   SilcPacketEngine engine;               /* Packet engine */
34   SilcDList inbufs;                      /* Data inbut buffer list */
35   SilcUInt32 stream_count;               /* Number of streams using this */
36 } *SilcPacketEngineContext;
37
38 /* Packet engine */
39 struct SilcPacketEngineStruct {
40   SilcMutex lock;                        /* Engine lock */
41   SilcRng rng;                           /* RNG for engine */
42   SilcHashTable contexts;                /* Per scheduler contexts */
43   SilcPacketCallbacks *callbacks;        /* Packet callbacks */
44   void *callback_context;                /* Context for callbacks */
45   SilcList streams;                      /* All streams in engine */
46   SilcList packet_pool;                  /* Free list for received packets */
47   SilcHashTable udp_remote;              /* UDP remote streams, or NULL */
48   unsigned int local_is_router    : 1;
49 };
50
51 /* Packet processor context */
52 typedef struct SilcPacketProcessStruct {
53   SilcPacketType *types;                 /* Packets to process */
54   SilcPacketCallbacks *callbacks;        /* Callbacks or NULL */
55   void *callback_context;
56   SilcInt32 priority;                    /* Priority */
57 } *SilcPacketProcess;
58
59 /* UDP remote stream tuple */
60 typedef struct {
61   char *remote_ip;                       /* Remote IP address */
62   SilcUInt16 remote_port;                /* Remote port */
63 } *SilcPacketRemoteUDP;
64
65 /* Packet stream */
66 struct SilcPacketStreamStruct {
67   struct SilcPacketStreamStruct *next;
68   SilcPacketEngineContext sc;            /* Per scheduler context */
69   SilcStream stream;                     /* Underlaying stream */
70   SilcMutex lock;                        /* Packet stream lock */
71   SilcDList process;                     /* Packet processors, or NULL */
72   SilcPacketRemoteUDP remote_udp;        /* UDP remote stream tuple, or NULL */
73   void *stream_context;                  /* Stream context */
74   SilcBufferStruct outbuf;               /* Out buffer */
75   SilcBuffer inbuf;                      /* Inbuf from inbuf list or NULL */
76   SilcCipher send_key[2];                /* Sending key */
77   SilcHmac send_hmac[2];                 /* Sending HMAC */
78   SilcCipher receive_key[2];             /* Receiving key */
79   SilcHmac receive_hmac[2];              /* Receiving HMAC */
80   unsigned char *src_id;                 /* Source ID */
81   unsigned char *dst_id;                 /* Destination ID */
82   SilcUInt32 send_psn;                   /* Sending sequence */
83   SilcUInt32 receive_psn;                /* Receiving sequence */
84   SilcAtomic8 refcnt;                    /* Reference counter */
85   SilcUInt8 sid;                         /* Security ID, set if IV included */
86   unsigned int src_id_len  : 6;
87   unsigned int src_id_type : 2;
88   unsigned int dst_id_len  : 6;
89   unsigned int dst_id_type : 2;
90   unsigned int is_router   : 1;          /* Set if router stream */
91   unsigned int destroyed   : 1;          /* Set if destroyed */
92   unsigned int iv_included : 1;          /* Set if IV included */
93   unsigned int udp         : 1;          /* UDP remote stream */
94 };
95
96 /* Initial size of stream buffers */
97 #define SILC_PACKET_DEFAULT_SIZE  1024
98
99 /* Header length without source and destination ID's. */
100 #define SILC_PACKET_HEADER_LEN 10
101
102 /* Minimum length of SILC Packet Header. */
103 #define SILC_PACKET_MIN_HEADER_LEN 16
104 #define SILC_PACKET_MIN_HEADER_LEN_IV 32 + 1
105
106 /* Maximum padding length */
107 #define SILC_PACKET_MAX_PADLEN 128
108
109 /* Default padding length */
110 #define SILC_PACKET_DEFAULT_PADLEN 16
111
112 /* Minimum packet length */
113 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
114
115 /* Returns true length of the packet. */
116 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
117 do {                                                                     \
118   SILC_GET16_MSB((__ret_truelen), (__packetdata));                       \
119   (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4];    \
120 } while(0)
121
122 /* Calculates the data length with given header length.  This macro
123    can be used to check whether the data_len with header_len exceeds
124    SILC_PACKET_MAX_LEN.  If it does, this returns the new data_len
125    so that the SILC_PACKET_MAX_LEN is not exceeded.  If the data_len
126    plus header_len fits SILC_PACKET_MAX_LEN the returned data length
127    is the data_len given as argument. */
128 #define SILC_PACKET_DATALEN(data_len, header_len)                         \
129   ((data_len + header_len) > SILC_PACKET_MAX_LEN ?                        \
130    data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
131
132 /* Calculates the length of the padding in the packet. */
133 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen)               \
134 do {                                                                        \
135   __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) %                  \
136               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN));  \
137   if (__padlen < 8)                                                         \
138     __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
139 } while(0)
140
141 /* Returns the length of the padding up to the maximum length, which
142    is 128 bytes.*/
143 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen)          \
144 do {                                                                       \
145   __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) %                     \
146               ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
147 } while(0)
148
149 /* EOS callback */
150 #define SILC_PACKET_CALLBACK_EOS(s)                                     \
151 do {                                                                    \
152   (s)->sc->engine->callbacks->eos((s)->sc->engine, s,                   \
153                                   (s)->sc->engine->callback_context,    \
154                                   (s)->stream_context);                 \
155 } while(0)
156
157 /* Error callback */
158 #define SILC_PACKET_CALLBACK_ERROR(s, err)                              \
159 do {                                                                    \
160   (s)->sc->engine->callbacks->error((s)->sc->engine, s, err,            \
161                                     (s)->sc->engine->callback_context,  \
162                                     (s)->stream_context);               \
163 } while(0)
164
165 static SilcBool silc_packet_dispatch(SilcPacket packet);
166 static void silc_packet_read_process(SilcPacketStream stream);
167 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
168                                             SilcPacketType type,
169                                             SilcPacketFlags flags,
170                                             SilcIdType src_id_type,
171                                             unsigned char *src_id,
172                                             SilcUInt32 src_id_len,
173                                             SilcIdType dst_id_type,
174                                             unsigned char *dst_id,
175                                             SilcUInt32 dst_id_len,
176                                             const unsigned char *data,
177                                             SilcUInt32 data_len,
178                                             SilcCipher cipher,
179                                             SilcHmac hmac);
180
181 /************************ Static utility functions **************************/
182
183 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
184
185 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
186 {
187   SilcPacket packet = context;
188   SilcPacketStream stream = packet->stream;
189
190   SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
191
192   silc_mutex_lock(stream->lock);
193   if (!stream->destroyed)
194     silc_packet_dispatch(packet);
195   silc_mutex_unlock(stream->lock);
196   silc_packet_stream_unref(stream);
197 }
198
199 /* Write data to the stream.  Must be called with ps->lock locked.  Unlocks
200    the lock inside this function, unless no_unlock is TRUE.  Unlocks always
201    in case it returns FALSE. */
202
203 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps,
204                                                 SilcBool no_unlock)
205 {
206   SilcStream stream;
207   SilcBool connected;
208   int i;
209
210   if (ps->udp)
211     stream = ((SilcPacketStream)ps->stream)->stream;
212   else
213     stream = ps->stream;
214
215   if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
216     if (!connected) {
217       /* Connectionless UDP stream */
218       while (silc_buffer_len(&ps->outbuf) > 0) {
219         i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
220                               ps->remote_udp->remote_port,
221                               ps->outbuf.data, silc_buffer_len(&ps->outbuf));
222         if (silc_unlikely(i == -2)) {
223           /* Error */
224           silc_buffer_reset(&ps->outbuf);
225           SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
226           return FALSE;
227         }
228
229         if (silc_unlikely(i == -1)) {
230           /* Cannot write now, write later. */
231           if (!no_unlock)
232             silc_mutex_unlock(ps->lock);
233           return TRUE;
234         }
235
236         /* Wrote data */
237         silc_buffer_pull(&ps->outbuf, i);
238       }
239
240       silc_buffer_reset(&ps->outbuf);
241       if (!no_unlock)
242         silc_mutex_unlock(ps->lock);
243
244       return TRUE;
245     }
246   }
247
248   /* Write the data to the stream */
249   while (silc_buffer_len(&ps->outbuf) > 0) {
250     i = silc_stream_write(stream, ps->outbuf.data,
251                           silc_buffer_len(&ps->outbuf));
252     if (silc_unlikely(i == 0)) {
253       /* EOS */
254       silc_buffer_reset(&ps->outbuf);
255       silc_mutex_unlock(ps->lock);
256       SILC_PACKET_CALLBACK_EOS(ps);
257       return FALSE;
258     }
259
260     if (silc_unlikely(i == -2)) {
261       /* Error */
262       silc_buffer_reset(&ps->outbuf);
263       silc_mutex_unlock(ps->lock);
264       SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
265       return FALSE;
266     }
267
268     if (silc_unlikely(i == -1)) {
269       /* Cannot write now, write later. */
270       if (!no_unlock)
271         silc_mutex_unlock(ps->lock);
272       return TRUE;
273     }
274
275     /* Wrote data */
276     silc_buffer_pull(&ps->outbuf, i);
277   }
278
279   silc_buffer_reset(&ps->outbuf);
280   if (!no_unlock)
281     silc_mutex_unlock(ps->lock);
282
283   return TRUE;
284 }
285
286 /* Reads data from stream.  Must be called with ps->lock locked.  If this
287    returns FALSE the lock has been unlocked.  If this returns packet stream
288    to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
289    It is returned if the stream is UDP and remote UDP stream exists for
290    the sender of the packet. */
291
292 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
293                                                SilcPacketStream *ret_ps)
294 {
295   SilcStream stream = ps->stream;
296   SilcBuffer inbuf;
297   SilcBool connected;
298   int ret;
299
300   /* Get inbuf.  If there is already some data for this stream in the buffer
301      we already have it.  Otherwise get the current one from list, it will
302      include the data. */
303   inbuf = ps->inbuf;
304   if (!inbuf) {
305     silc_dlist_start(ps->sc->inbufs);
306     inbuf = silc_dlist_get(ps->sc->inbufs);
307     if (!inbuf) {
308       /* Allocate new data input buffer */
309       inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE * 31);
310       if (!inbuf) {
311         silc_mutex_unlock(ps->lock);
312         return FALSE;
313       }
314       silc_buffer_reset(inbuf);
315       silc_dlist_add(ps->sc->inbufs, inbuf);
316     }
317   }
318
319   /* Make sure there is enough room to read */
320   if (SILC_PACKET_DEFAULT_SIZE * 2 > silc_buffer_taillen(inbuf))
321     silc_buffer_realloc(inbuf, silc_buffer_truelen(inbuf) +
322                         (SILC_PACKET_DEFAULT_SIZE * 2));
323
324   if (silc_socket_stream_is_udp(stream, &connected)) {
325     if (!connected) {
326       /* Connectionless UDP stream, read one UDP packet */
327       char remote_ip[64], tuple[64];
328       int remote_port;
329       SilcPacketStream remote;
330
331       ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
332                                  &remote_port, inbuf->tail,
333                                  silc_buffer_taillen(inbuf));
334
335       if (silc_unlikely(ret < 0)) {
336         silc_mutex_unlock(ps->lock);
337         if (ret == -1) {
338           /* Cannot read now, do it later. */
339           silc_buffer_pull(inbuf, silc_buffer_len(inbuf));
340           return FALSE;
341         }
342
343         /* Error */
344         silc_buffer_reset(inbuf);
345         SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
346         return FALSE;
347       }
348
349       /* See if remote packet stream exist for this sender */
350       silc_snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
351       silc_mutex_lock(ps->sc->engine->lock);
352       if (silc_hash_table_find(ps->sc->engine->udp_remote, tuple, NULL,
353                                (void *)&remote)) {
354         silc_mutex_unlock(ps->sc->engine->lock);
355         SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p", remote_ip,
356                         remote_port, remote));
357         silc_mutex_unlock(ps->lock);
358         silc_mutex_lock(remote->lock);
359         *ret_ps = remote;
360         return TRUE;
361       }
362       silc_mutex_unlock(ps->sc->engine->lock);
363
364       /* Unknown sender */
365       if (!ps->remote_udp) {
366         ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
367         if (silc_unlikely(!ps->remote_udp)) {
368           silc_mutex_unlock(ps->lock);
369           SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
370           return FALSE;
371         }
372       }
373
374       /* Save sender IP and port */
375       silc_free(ps->remote_udp->remote_ip);
376       ps->remote_udp->remote_ip = strdup(remote_ip);
377       ps->remote_udp->remote_port = remote_port;
378
379       silc_buffer_pull_tail(inbuf, ret);
380       return TRUE;
381     }
382   }
383
384   /* Read data from the stream */
385   ret = silc_stream_read(stream, inbuf->tail, silc_buffer_taillen(inbuf));
386   if (silc_unlikely(ret <= 0)) {
387     silc_mutex_unlock(ps->lock);
388     if (ret == 0) {
389       /* EOS */
390       silc_buffer_reset(inbuf);
391       SILC_PACKET_CALLBACK_EOS(ps);
392       return FALSE;
393     }
394
395     if (ret == -1) {
396       /* Cannot read now, do it later. */
397       silc_buffer_pull(inbuf, silc_buffer_len(inbuf));
398       return FALSE;
399     }
400
401     /* Error */
402     silc_buffer_reset(inbuf);
403     SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
404     return FALSE;
405   }
406
407   silc_buffer_pull_tail(inbuf, ret);
408   return TRUE;
409 }
410
411 /* Our stream IO notifier callback. */
412
413 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
414                                   void *context)
415 {
416   SilcPacketStream remote = NULL, ps = context;
417
418   silc_mutex_lock(ps->lock);
419
420   if (silc_unlikely(ps->destroyed)) {
421     silc_mutex_unlock(ps->lock);
422     return;
423   }
424
425   switch (status) {
426   case SILC_STREAM_CAN_READ:
427     /* Reading is locked also with stream->lock because we may be reading
428        at the same time other thread is writing to same underlaying stream. */
429     SILC_LOG_DEBUG(("Reading data from stream %p, ps %p", ps->stream, ps));
430
431     /* Read data from stream */
432     if (!silc_packet_stream_read(ps, &remote))
433       return;
434
435     /* Now process the data */
436     silc_packet_stream_ref(ps);
437     if (!remote) {
438       silc_packet_read_process(ps);
439       silc_mutex_unlock(ps->lock);
440     } else {
441       silc_packet_read_process(remote);
442       silc_mutex_unlock(remote->lock);
443     }
444     silc_packet_stream_unref(ps);
445     break;
446
447   case SILC_STREAM_CAN_WRITE:
448     SILC_LOG_DEBUG(("Writing pending data to stream %p, ps %p",
449                     ps->stream, ps));
450
451     if (silc_unlikely(!silc_buffer_headlen(&ps->outbuf))) {
452       silc_mutex_unlock(ps->lock);
453       return;
454     }
455
456     /* Write pending data to stream */
457     silc_packet_stream_write(ps, FALSE);
458     break;
459
460   default:
461     silc_mutex_unlock(ps->lock);
462     break;
463   }
464 }
465
466 /* Allocate packet */
467
468 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
469 {
470   SilcPacket packet;
471
472   SILC_LOG_DEBUG(("Packet pool count %d",
473                   silc_list_count(engine->packet_pool)));
474
475   silc_mutex_lock(engine->lock);
476
477   /* Get packet from freelist or allocate new one. */
478   packet = silc_list_get(engine->packet_pool);
479   if (!packet) {
480     void *tmp;
481
482     silc_mutex_unlock(engine->lock);
483
484     packet = silc_calloc(1, sizeof(*packet));
485     if (silc_unlikely(!packet))
486       return NULL;
487
488     SILC_LOG_DEBUG(("Allocating new packet %p", packet));
489
490     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
491     if (silc_unlikely(!tmp)) {
492       silc_free(packet);
493       return NULL;
494     }
495     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
496     silc_buffer_reset(&packet->buffer);
497
498     return packet;
499   }
500
501   SILC_LOG_DEBUG(("Get packet %p", packet));
502
503   /* Delete from freelist */
504   silc_list_del(engine->packet_pool, packet);
505
506   silc_mutex_unlock(engine->lock);
507
508   return packet;
509 }
510
511 /* UDP remote stream hash table destructor */
512
513 static void silc_packet_engine_hash_destr(void *key, void *context,
514                                           void *user_context)
515 {
516   silc_free(key);
517 }
518
519 /* Per scheduler context hash table destructor */
520
521 static void silc_packet_engine_context_destr(void *key, void *context,
522                                              void *user_context)
523 {
524   SilcPacketEngineContext sc = context;
525   SilcBuffer buffer;
526
527   silc_dlist_start(sc->inbufs);
528   while ((buffer = silc_dlist_get(sc->inbufs))) {
529     silc_buffer_clear(buffer);
530     silc_buffer_free(buffer);
531     silc_dlist_del(sc->inbufs, buffer);
532   }
533
534   silc_dlist_uninit(sc->inbufs);
535   silc_free(sc);
536 }
537
538
539 /******************************** Packet API ********************************/
540
541 /* Allocate new packet engine */
542
543 SilcPacketEngine
544 silc_packet_engine_start(SilcRng rng, SilcBool router,
545                          SilcPacketCallbacks *callbacks,
546                          void *callback_context)
547 {
548   SilcPacketEngine engine;
549   SilcPacket packet;
550   int i;
551   void *tmp;
552
553   SILC_LOG_DEBUG(("Starting new packet engine"));
554
555   if (!callbacks)
556     return NULL;
557   if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
558     return NULL;
559
560   engine = silc_calloc(1, sizeof(*engine));
561   if (!engine)
562     return NULL;
563
564   engine->contexts = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
565                                            silc_packet_engine_context_destr,
566                                            engine, TRUE);
567   if (!engine->contexts) {
568     silc_free(engine);
569     return NULL;
570   }
571
572   engine->rng = rng;
573   engine->local_is_router = router;
574   engine->callbacks = callbacks;
575   engine->callback_context = callback_context;
576   silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
577   silc_mutex_alloc(&engine->lock);
578
579   /* Allocate packet free list */
580   silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
581   for (i = 0; i < 5; i++) {
582     packet = silc_calloc(1, sizeof(*packet));
583     if (!packet) {
584       silc_packet_engine_stop(engine);
585       return NULL;
586     }
587
588     tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
589     if (!tmp) {
590       silc_packet_engine_stop(engine);
591       return NULL;
592     }
593     silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
594     silc_buffer_reset(&packet->buffer);
595
596     silc_list_add(engine->packet_pool, packet);
597   }
598   silc_list_start(engine->packet_pool);
599
600   return engine;
601 }
602
603 /* Stop packet engine */
604
605 void silc_packet_engine_stop(SilcPacketEngine engine)
606 {
607   SilcPacket packet;
608
609   SILC_LOG_DEBUG(("Stopping packet engine"));
610
611   if (!engine)
612     return;
613
614   /* Free packet free list */
615   silc_list_start(engine->packet_pool);
616   while ((packet = silc_list_get(engine->packet_pool))) {
617     silc_buffer_purge(&packet->buffer);
618     silc_free(packet);
619   }
620
621   silc_hash_table_free(engine->contexts);
622   silc_mutex_free(engine->lock);
623   silc_free(engine);
624 }
625
626 /* Create new packet stream */
627
628 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
629                                            SilcSchedule schedule,
630                                            SilcStream stream)
631 {
632   SilcPacketStream ps;
633   SilcBuffer inbuf;
634   void *tmp;
635
636   SILC_LOG_DEBUG(("Creating new packet stream"));
637
638   if (!engine || !stream)
639     return NULL;
640
641   ps = silc_calloc(1, sizeof(*ps));
642   if (!ps)
643     return NULL;
644
645   ps->stream = stream;
646   silc_atomic_init8(&ps->refcnt, 1);
647   silc_mutex_alloc(&ps->lock);
648
649   /* Allocate out buffer */
650   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
651   if (!tmp) {
652     silc_packet_stream_destroy(ps);
653     return NULL;
654   }
655   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
656   silc_buffer_reset(&ps->outbuf);
657
658   /* Initialize packet procesors list */
659   ps->process = silc_dlist_init();
660   if (!ps->process) {
661     silc_packet_stream_destroy(ps);
662     return NULL;
663   }
664
665   silc_mutex_lock(engine->lock);
666
667   /* Add per scheduler context */
668   if (!silc_hash_table_find(engine->contexts, schedule, NULL,
669                             (void *)&ps->sc)) {
670     ps->sc = silc_calloc(1, sizeof(*ps->sc));
671     if (!ps->sc) {
672       silc_packet_stream_destroy(ps);
673       silc_mutex_unlock(engine->lock);
674       return NULL;
675     }
676     ps->sc->engine = engine;
677     ps->sc->schedule = schedule;
678
679     /* Allocate data input buffer */
680     inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE * 31);
681     if (!inbuf) {
682       silc_free(ps->sc);
683       ps->sc = NULL;
684       silc_packet_stream_destroy(ps);
685       silc_mutex_unlock(engine->lock);
686       return NULL;
687     }
688     silc_buffer_reset(inbuf);
689
690     ps->sc->inbufs = silc_dlist_init();
691     if (!ps->sc->inbufs) {
692       silc_buffer_free(inbuf);
693       silc_free(ps->sc);
694       ps->sc = NULL;
695       silc_packet_stream_destroy(ps);
696       silc_mutex_unlock(engine->lock);
697       return NULL;
698     }
699     silc_dlist_add(ps->sc->inbufs, inbuf);
700
701     /* Add to per scheduler context hash table */
702     if (!silc_hash_table_add(engine->contexts, schedule, ps->sc)) {
703       silc_buffer_free(inbuf);
704       silc_dlist_del(ps->sc->inbufs, inbuf);
705       silc_free(ps->sc);
706       ps->sc = NULL;
707       silc_packet_stream_destroy(ps);
708       silc_mutex_unlock(engine->lock);
709       return NULL;
710     }
711   }
712   ps->sc->stream_count++;
713
714   /* Add the packet stream to engine */
715   silc_list_add(engine->streams, ps);
716
717   /* If this is UDP stream, allocate UDP remote stream hash table */
718   if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
719     engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
720                                                silc_hash_string_compare, NULL,
721                                                silc_packet_engine_hash_destr,
722                                                NULL, TRUE);
723
724   silc_mutex_unlock(engine->lock);
725
726   /* Set IO notifier callback.  This schedules this stream for I/O. */
727   if (!silc_stream_set_notifier(ps->stream, schedule,
728                                 silc_packet_stream_io, ps)) {
729     SILC_LOG_DEBUG(("Cannot set stream notifier for packet stream"));
730     silc_packet_stream_destroy(ps);
731     return NULL;
732   }
733
734   return ps;
735 }
736
737 /* Add new remote packet stream for UDP packet streams */
738
739 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
740                                                const char *remote_ip,
741                                                SilcUInt16 remote_port,
742                                                SilcPacket packet)
743 {
744   SilcPacketEngine engine = stream->sc->engine;
745   SilcPacketStream ps;
746   char *tuple;
747   void *tmp;
748
749   SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
750                   remote_ip, remote_port, stream));
751
752   if (!stream || !remote_ip || !remote_port)
753     return NULL;
754
755   if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
756     SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
757     return NULL;
758   }
759
760   ps = silc_calloc(1, sizeof(*ps));
761   if (!ps)
762     return NULL;
763   ps->sc = stream->sc;
764
765   silc_atomic_init8(&ps->refcnt, 1);
766   silc_mutex_alloc(&ps->lock);
767
768   /* Set the UDP packet stream as underlaying stream */
769   silc_packet_stream_ref(stream);
770   ps->stream = (SilcStream)stream;
771   ps->udp = TRUE;
772
773   /* Allocate out buffer */
774   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
775   if (!tmp) {
776     silc_packet_stream_destroy(ps);
777     return NULL;
778   }
779   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
780   silc_buffer_reset(&ps->outbuf);
781
782   /* Initialize packet procesors list */
783   ps->process = silc_dlist_init();
784   if (!ps->process) {
785     silc_packet_stream_destroy(ps);
786     return NULL;
787   }
788
789   /* Add to engine with this IP and port pair */
790   tuple = silc_format("%d%s", remote_port, remote_ip);
791   silc_mutex_lock(engine->lock);
792   if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
793     silc_mutex_unlock(engine->lock);
794     silc_packet_stream_destroy(ps);
795     return NULL;
796   }
797   silc_mutex_unlock(engine->lock);
798
799   /* Save remote IP and port pair */
800   ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
801   if (!ps->remote_udp) {
802     silc_packet_stream_destroy(ps);
803     return NULL;
804   }
805   ps->remote_udp->remote_port = remote_port;
806   ps->remote_udp->remote_ip = strdup(remote_ip);
807   if (!ps->remote_udp->remote_ip) {
808     silc_packet_stream_destroy(ps);
809     return NULL;
810   }
811
812   if (packet) {
813     /* Inject packet to the new stream */
814     packet->stream = ps;
815     silc_packet_stream_ref(ps);
816     silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
817                                    silc_packet_stream_inject_packet, packet,
818                                    0, 0);
819   }
820
821   return ps;
822 }
823
824 /* Destroy packet stream */
825
826 void silc_packet_stream_destroy(SilcPacketStream stream)
827 {
828   SilcPacketEngine engine;
829
830   if (!stream)
831     return;
832
833   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0) {
834     stream->destroyed = TRUE;
835
836     /* Close the underlaying stream */
837     if (!stream->udp && stream->stream)
838       silc_stream_close(stream->stream);
839     return;
840   }
841
842   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
843
844   if (!stream->udp) {
845     /* Delete from engine */
846     engine = stream->sc->engine;
847     silc_mutex_lock(engine->lock);
848     silc_list_del(engine->streams, stream);
849
850     /* Remove per scheduler context, if it is not used anymore */
851     if (stream->sc) {
852       stream->sc->stream_count--;
853       if (!stream->sc->stream_count)
854         silc_hash_table_del(engine->contexts, stream->sc->schedule);
855     }
856     silc_mutex_unlock(engine->lock);
857
858     /* Destroy the underlaying stream */
859     if (stream->stream)
860       silc_stream_destroy(stream->stream);
861   } else {
862     /* Delete from UDP remote hash table */
863     char tuple[64];
864     engine = stream->sc->engine;
865     silc_snprintf(tuple, sizeof(tuple), "%d%s",
866                   stream->remote_udp->remote_port
867                   stream->remote_udp->remote_ip);
868     silc_mutex_lock(engine->lock);
869     silc_hash_table_del(engine->udp_remote, tuple);
870     silc_mutex_unlock(engine->lock);
871
872     silc_free(stream->remote_udp->remote_ip);
873     silc_free(stream->remote_udp);
874
875     /* Unreference the underlaying packet stream */
876     silc_packet_stream_unref((SilcPacketStream)stream->stream);
877   }
878
879   /* Clear and free buffers */
880   silc_buffer_clear(&stream->outbuf);
881   silc_buffer_purge(&stream->outbuf);
882
883   if (stream->process) {
884     SilcPacketProcess p;
885     silc_dlist_start(stream->process);
886     while ((p = silc_dlist_get(stream->process))) {
887       silc_free(p->types);
888       silc_free(p);
889       silc_dlist_del(stream->process, p);
890     }
891     silc_dlist_uninit(stream->process);
892   }
893
894   /* Destroy ciphers and HMACs */
895   if (stream->send_key[0])
896     silc_cipher_free(stream->send_key[0]);
897   if (stream->receive_key[0])
898     silc_cipher_free(stream->receive_key[0]);
899   if (stream->send_hmac[0])
900     silc_hmac_free(stream->send_hmac[0]);
901   if (stream->receive_hmac[0])
902     silc_hmac_free(stream->receive_hmac[0]);
903   if (stream->send_key[1])
904     silc_cipher_free(stream->send_key[1]);
905   if (stream->receive_key[1])
906     silc_cipher_free(stream->receive_key[1]);
907   if (stream->send_hmac[1])
908     silc_hmac_free(stream->send_hmac[1]);
909   if (stream->receive_hmac[1])
910     silc_hmac_free(stream->receive_hmac[1]);
911
912   /* Free IDs */
913   silc_free(stream->src_id);
914   silc_free(stream->dst_id);
915
916   silc_atomic_uninit8(&stream->refcnt);
917   silc_mutex_free(stream->lock);
918   silc_free(stream);
919 }
920
921 /* Marks as router stream */
922
923 void silc_packet_stream_set_router(SilcPacketStream stream)
924 {
925   stream->is_router = TRUE;
926 }
927
928 /* Mark to include IV in ciphertext */
929
930 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
931 {
932   stream->iv_included = TRUE;
933 }
934
935 /* Links `callbacks' to `stream' for specified packet types */
936
937 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
938                                            SilcPacketCallbacks *callbacks,
939                                            void *callback_context,
940                                            int priority, va_list ap)
941 {
942   SilcPacketProcess p, e;
943   SilcInt32 packet_type;
944   int i;
945
946   SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
947
948   if (!callbacks)
949     return FALSE;
950   if (!callbacks->packet_receive)
951     return FALSE;
952
953   p = silc_calloc(1, sizeof(*p));
954   if (!p)
955     return FALSE;
956
957   p->priority = priority;
958   p->callbacks = callbacks;
959   p->callback_context = callback_context;
960
961   silc_mutex_lock(stream->lock);
962
963   if (!stream->process) {
964     stream->process = silc_dlist_init();
965     if (!stream->process) {
966       silc_mutex_unlock(stream->lock);
967       return FALSE;
968     }
969   }
970
971   /* According to priority set the procesor to correct position.  First
972      entry has the highest priority */
973   silc_dlist_start(stream->process);
974   while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
975     if (p->priority > e->priority) {
976       silc_dlist_insert(stream->process, p);
977       break;
978     }
979   }
980   if (!e)
981     silc_dlist_add(stream->process, p);
982
983   /* Get packet types to process */
984   i = 1;
985   while (1) {
986     packet_type = va_arg(ap, SilcInt32);
987
988     if (packet_type == SILC_PACKET_ANY)
989       break;
990
991     if (packet_type == -1)
992       break;
993
994     p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
995     if (!p->types) {
996       silc_mutex_unlock(stream->lock);
997       return FALSE;
998     }
999
1000     p->types[i - 1] = (SilcPacketType)packet_type;
1001     i++;
1002   }
1003   if (p->types)
1004     p->types[i - 1] = 0;
1005
1006   silc_mutex_unlock(stream->lock);
1007
1008   silc_packet_stream_ref(stream);
1009
1010   return TRUE;
1011 }
1012
1013 /* Links `callbacks' to `stream' for specified packet types */
1014
1015 SilcBool silc_packet_stream_link(SilcPacketStream stream,
1016                                  SilcPacketCallbacks *callbacks,
1017                                  void *callback_context,
1018                                  int priority, ...)
1019 {
1020   va_list ap;
1021   SilcBool ret;
1022
1023   va_start(ap, priority);
1024   ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
1025                                    priority, ap);
1026   va_end(ap);
1027
1028   return ret;
1029 }
1030
1031 /* Unlinks `callbacks' from `stream'. */
1032
1033 void silc_packet_stream_unlink(SilcPacketStream stream,
1034                                SilcPacketCallbacks *callbacks,
1035                                void *callback_context)
1036 {
1037   SilcPacketProcess p;
1038
1039   SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
1040                   callbacks, stream));
1041
1042   silc_mutex_lock(stream->lock);
1043
1044   silc_dlist_start(stream->process);
1045   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
1046     if (p->callbacks == callbacks &&
1047         p->callback_context == callback_context) {
1048       silc_dlist_del(stream->process, p);
1049       silc_free(p->types);
1050       silc_free(p);
1051       break;
1052     }
1053
1054   if (!silc_dlist_count(stream->process)) {
1055     silc_dlist_uninit(stream->process);
1056     stream->process = NULL;
1057   }
1058
1059   silc_mutex_unlock(stream->lock);
1060
1061   silc_packet_stream_unref(stream);
1062 }
1063
1064 /* Returns TRUE if stream is UDP stream */
1065
1066 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
1067 {
1068   return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
1069 }
1070
1071 /* Return packet sender IP and port for UDP packet stream */
1072
1073 SilcBool silc_packet_get_sender(SilcPacket packet,
1074                                 const char **sender_ip,
1075                                 SilcUInt16 *sender_port)
1076 {
1077   if (!packet->stream->remote_udp)
1078     return FALSE;
1079
1080   *sender_ip = packet->stream->remote_udp->remote_ip;
1081   *sender_port = packet->stream->remote_udp->remote_port;
1082
1083   return TRUE;
1084 }
1085
1086 /* Reference packet stream */
1087
1088 void silc_packet_stream_ref(SilcPacketStream stream)
1089 {
1090   silc_atomic_add_int8(&stream->refcnt, 1);
1091   SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1092                   silc_atomic_get_int8(&stream->refcnt) - 1,
1093                   silc_atomic_get_int8(&stream->refcnt)));
1094 }
1095
1096 /* Unreference packet stream */
1097
1098 void silc_packet_stream_unref(SilcPacketStream stream)
1099 {
1100   SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1101                   silc_atomic_get_int8(&stream->refcnt),
1102                   silc_atomic_get_int8(&stream->refcnt) - 1));
1103   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0)
1104     return;
1105   silc_atomic_add_int8(&stream->refcnt, 1);
1106   silc_packet_stream_destroy(stream);
1107 }
1108
1109 /* Return engine */
1110
1111 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
1112 {
1113   return stream->sc->engine;
1114 }
1115
1116 /* Set application context for packet stream */
1117
1118 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
1119 {
1120   silc_mutex_lock(stream->lock);
1121   stream->stream_context = stream_context;
1122   silc_mutex_unlock(stream->lock);
1123 }
1124
1125 /* Return application context from packet stream */
1126
1127 void *silc_packet_get_context(SilcPacketStream stream)
1128 {
1129   void *context;
1130   silc_mutex_lock(stream->lock);
1131   context = stream->stream_context;
1132   silc_mutex_unlock(stream->lock);
1133   return context;
1134 }
1135
1136 /* Change underlaying stream */
1137
1138 void silc_packet_stream_set_stream(SilcPacketStream ps,
1139                                    SilcStream stream)
1140 {
1141   if (ps->stream)
1142     silc_stream_set_notifier(ps->stream, ps->sc->schedule, NULL, NULL);
1143   ps->stream = stream;
1144   silc_stream_set_notifier(ps->stream, ps->sc->schedule, silc_packet_stream_io,
1145                            ps);
1146 }
1147
1148 /* Return underlaying stream */
1149
1150 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1151 {
1152   return stream->stream;
1153 }
1154
1155 /* Set keys. */
1156
1157 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
1158                               SilcCipher receive_key, SilcHmac send_hmac,
1159                               SilcHmac receive_hmac, SilcBool rekey)
1160 {
1161   SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream));
1162
1163   /* If doing rekey, send REKEY_DONE packet */
1164   if (rekey) {
1165     /* This will take stream lock. */
1166     if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0,
1167                               stream->src_id_type, stream->src_id,
1168                               stream->src_id_len, stream->dst_id_type,
1169                               stream->dst_id, stream->dst_id_len,
1170                               NULL, 0, stream->send_key[0],
1171                               stream->send_hmac[0]))
1172       return FALSE;
1173
1174     /* Write the packet to the stream */
1175     if (!silc_packet_stream_write(stream, TRUE))
1176       return FALSE;
1177   } else {
1178     silc_mutex_lock(stream->lock);
1179   }
1180
1181   /* In case IV Included is set, save the old keys */
1182   if (stream->iv_included) {
1183     if (stream->send_key[1] && send_key) {
1184       silc_cipher_free(stream->send_key[1]);
1185       stream->send_key[1] = stream->send_key[0];
1186     }
1187     if (stream->receive_key[1] && receive_key) {
1188       silc_cipher_free(stream->receive_key[1]);
1189       stream->receive_key[1] = stream->receive_key[0];
1190     }
1191     if (stream->send_hmac[1] && send_hmac) {
1192       silc_hmac_free(stream->send_hmac[1]);
1193       stream->send_hmac[1] = stream->send_hmac[0];
1194     }
1195     if (stream->receive_hmac[1] && receive_hmac) {
1196       silc_hmac_free(stream->receive_hmac[1]);
1197       stream->receive_hmac[1] = stream->receive_hmac[0];
1198     }
1199   } else {
1200     if (stream->send_key[0] && send_key)
1201       silc_cipher_free(stream->send_key[0]);
1202     if (stream->receive_key[0] && receive_key)
1203       silc_cipher_free(stream->receive_key[0]);
1204     if (stream->send_hmac[0] && send_hmac)
1205       silc_hmac_free(stream->send_hmac[0]);
1206     if (stream->receive_hmac[0] && receive_hmac)
1207       silc_hmac_free(stream->receive_hmac[0]);
1208   }
1209
1210   /* Set keys */
1211   if (send_key)
1212     stream->send_key[0] = send_key;
1213   if (receive_key)
1214     stream->receive_key[0] = receive_key;
1215   if (send_hmac)
1216     stream->send_hmac[0] = send_hmac;
1217   if (receive_hmac)
1218     stream->receive_hmac[0] = receive_hmac;
1219
1220   silc_mutex_unlock(stream->lock);
1221   return TRUE;
1222 }
1223
1224 /* Return current ciphers from packet stream */
1225
1226 SilcBool silc_packet_get_keys(SilcPacketStream stream,
1227                               SilcCipher *send_key,
1228                               SilcCipher *receive_key,
1229                               SilcHmac *send_hmac,
1230                               SilcHmac *receive_hmac)
1231 {
1232   if (!stream->send_key[0] && !stream->receive_key[0] &&
1233       !stream->send_hmac[0] && !stream->receive_hmac[0])
1234     return FALSE;
1235
1236   silc_mutex_lock(stream->lock);
1237
1238   if (send_key)
1239     *send_key = stream->send_key[0];
1240   if (receive_key)
1241     *receive_key = stream->receive_key[0];
1242   if (send_hmac)
1243     *send_hmac = stream->send_hmac[0];
1244   if (receive_hmac)
1245     *receive_hmac = stream->receive_hmac[0];
1246
1247   silc_mutex_unlock(stream->lock);
1248
1249   return TRUE;
1250 }
1251
1252 /* Set SILC IDs to packet stream */
1253
1254 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1255                              SilcIdType src_id_type, const void *src_id,
1256                              SilcIdType dst_id_type, const void *dst_id)
1257 {
1258   SilcUInt32 len;
1259   unsigned char tmp[32];
1260
1261   if (!src_id && !dst_id)
1262     return FALSE;
1263
1264   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1265
1266   silc_mutex_lock(stream->lock);
1267
1268   if (src_id) {
1269     silc_free(stream->src_id);
1270     if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1271       silc_mutex_unlock(stream->lock);
1272       return FALSE;
1273     }
1274     stream->src_id = silc_memdup(tmp, len);
1275     if (!stream->src_id) {
1276       silc_mutex_unlock(stream->lock);
1277       return FALSE;
1278     }
1279     stream->src_id_type = src_id_type;
1280     stream->src_id_len = len;
1281   }
1282
1283   if (dst_id) {
1284     silc_free(stream->dst_id);
1285     if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1286       silc_mutex_unlock(stream->lock);
1287       return FALSE;
1288     }
1289     stream->dst_id = silc_memdup(tmp, len);
1290     if (!stream->dst_id) {
1291       silc_mutex_unlock(stream->lock);
1292       return FALSE;
1293     }
1294     stream->dst_id_type = dst_id_type;
1295     stream->dst_id_len = len;
1296   }
1297
1298   silc_mutex_unlock(stream->lock);
1299
1300   return TRUE;
1301 }
1302
1303 /* Adds Security ID (SID) */
1304
1305 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1306 {
1307   if (!stream->iv_included)
1308     return FALSE;
1309
1310   SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1311
1312   stream->sid = sid;
1313   return TRUE;
1314 }
1315
1316 /* Free packet */
1317
1318 void silc_packet_free(SilcPacket packet)
1319 {
1320   SilcPacketStream stream = packet->stream;
1321
1322   SILC_LOG_DEBUG(("Freeing packet %p", packet));
1323
1324   /* Check for double free */
1325   SILC_ASSERT(packet->stream != NULL);
1326
1327   packet->stream = NULL;
1328   packet->src_id = packet->dst_id = NULL;
1329   silc_buffer_reset(&packet->buffer);
1330
1331   silc_mutex_lock(stream->sc->engine->lock);
1332
1333   /* Put the packet back to freelist */
1334   silc_list_add(stream->sc->engine->packet_pool, packet);
1335   if (silc_list_count(stream->sc->engine->packet_pool) == 1)
1336     silc_list_start(stream->sc->engine->packet_pool);
1337
1338   silc_mutex_unlock(stream->sc->engine->lock);
1339 }
1340
1341 /****************************** Packet Sending ******************************/
1342
1343 /* Prepare outgoing data buffer for packet sending.  Returns the
1344    pointer to that buffer into the `packet'. */
1345
1346 static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1347                                                 SilcUInt32 totlen,
1348                                                 SilcHmac hmac,
1349                                                 SilcBuffer packet)
1350 {
1351   unsigned char *oldptr;
1352   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1353
1354   totlen += mac_len;
1355
1356   /* Allocate more space if needed */
1357   if (silc_unlikely(silc_buffer_taillen(&stream->outbuf) < totlen)) {
1358     if (!silc_buffer_realloc(&stream->outbuf,
1359                              silc_buffer_truelen(&stream->outbuf) + totlen))
1360       return FALSE;
1361   }
1362
1363   /* Pull data area for the new packet, and return pointer to the start of
1364      the data area and save the pointer in to the `packet'.  MAC is pulled
1365      later after it's computed. */
1366   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1367   silc_buffer_set(packet, oldptr, totlen);
1368   silc_buffer_push_tail(packet, mac_len);
1369
1370   return TRUE;
1371 }
1372
1373 /* Increments counter when encrypting in counter mode. */
1374
1375 static inline void silc_packet_send_ctr_increment(SilcPacketStream stream,
1376                                                   SilcCipher cipher,
1377                                                   unsigned char *ret_iv)
1378 {
1379   unsigned char *iv = silc_cipher_get_iv(cipher);
1380   SilcUInt32 pc1, pc2;
1381
1382   /* Increment 64-bit packet counter */
1383   SILC_GET32_MSB(pc1, iv + 4);
1384   SILC_GET32_MSB(pc2, iv + 8);
1385   if (++pc2 == 0)
1386     ++pc1;
1387   SILC_PUT32_MSB(pc1, iv + 4);
1388   SILC_PUT32_MSB(pc2, iv + 8);
1389
1390   /* Reset block counter */
1391   memset(iv + 12, 0, 4);
1392
1393   /* If IV Included flag, return the 64-bit IV for inclusion in packet */
1394   if (stream->iv_included) {
1395     /* Get new nonce */
1396     ret_iv[0] = silc_rng_get_byte_fast(stream->sc->engine->rng);
1397     ret_iv[1] = ret_iv[0] + iv[4];
1398     ret_iv[2] = ret_iv[0] ^ ret_iv[1];
1399     ret_iv[3] = ret_iv[0] + ret_iv[2];
1400     SILC_PUT32_MSB(pc2, ret_iv + 4);
1401     SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
1402
1403     /* Set new nonce to counter block */
1404     memcpy(iv + 4, ret_iv, 4);
1405   }
1406
1407   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1408 }
1409
1410 /* Internal routine to assemble outgoing packet.  Assembles and encryptes
1411    the packet.  The silc_packet_stream_write needs to be called to send it
1412    after this returns TRUE. */
1413
1414 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
1415                                             SilcPacketType type,
1416                                             SilcPacketFlags flags,
1417                                             SilcIdType src_id_type,
1418                                             unsigned char *src_id,
1419                                             SilcUInt32 src_id_len,
1420                                             SilcIdType dst_id_type,
1421                                             unsigned char *dst_id,
1422                                             SilcUInt32 dst_id_len,
1423                                             const unsigned char *data,
1424                                             SilcUInt32 data_len,
1425                                             SilcCipher cipher,
1426                                             SilcHmac hmac)
1427 {
1428   unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1429   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1430   int i, enclen, truelen, padlen = 0, ivlen = 0, psnlen = 0;
1431   SilcBool ctr;
1432   SilcBufferStruct packet;
1433
1434   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1435                   "data len %d", silc_get_packet_name(type), stream->send_psn,
1436                   flags, src_id_type, dst_id_type, data_len));
1437
1438   /* Get the true length of the packet. This is saved as payload length
1439      into the packet header.  This does not include the length of the
1440      padding. */
1441   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1442                                             src_id_len + dst_id_len));
1443   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1444                       src_id_len + dst_id_len);
1445
1446   /* If using CTR mode, increment the counter */
1447   ctr = (cipher && silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR);
1448   if (ctr) {
1449     silc_packet_send_ctr_increment(stream, cipher, iv + 1);
1450
1451     /* If IV is included, the SID, IV and sequence number is added to packet */
1452     if (stream->iv_included && cipher) {
1453       psnlen = sizeof(psn);
1454       ivlen = 8 + 1;
1455       iv[0] = stream->sid;
1456     }
1457   } else {
1458     /* If IV is included, the SID, IV and sequence number is added to packet */
1459     if (stream->iv_included && cipher) {
1460       psnlen = sizeof(psn);
1461       ivlen = block_len + 1;
1462       iv[0] = stream->sid;
1463       memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1464     }
1465   }
1466
1467   /* We automatically figure out the packet structure from the packet
1468      type and flags, and calculate correct length.  Private messages with
1469      private keys and channel messages are special packets as their
1470      payload is encrypted already. */
1471   if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1472        flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1473       type == SILC_PACKET_CHANNEL_MESSAGE) {
1474
1475     /* Padding is calculated from header + IDs */
1476     if (!ctr)
1477       SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1478                           psnlen), block_len, padlen);
1479
1480     /* Length to encrypt, header + IDs + padding. */
1481     enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1482               padlen + psnlen);
1483   } else {
1484
1485     /* Padding is calculated from true length of the packet */
1486     if (flags & SILC_PACKET_FLAG_LONG_PAD)
1487       SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1488     else if (!ctr)
1489       SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1490
1491     enclen += padlen + psnlen;
1492   }
1493
1494   /* Remove implementation specific flags */
1495   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1496
1497   /* Get random padding */
1498   for (i = 0; i < padlen; i++) tmppad[i] =
1499     silc_rng_get_byte_fast(stream->sc->engine->rng);
1500
1501   silc_mutex_lock(stream->lock);
1502
1503   /* Get packet pointer from the outgoing buffer */
1504   if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
1505                                               + psnlen, hmac, &packet))) {
1506     silc_mutex_unlock(stream->lock);
1507     return FALSE;
1508   }
1509
1510   SILC_PUT32_MSB(stream->send_psn, psn);
1511
1512   /* Create the packet.  This creates the SILC header, adds padding, and
1513      the actual packet data. */
1514   i = silc_buffer_format(&packet,
1515                          SILC_STR_DATA(iv, ivlen),
1516                          SILC_STR_DATA(psn, psnlen),
1517                          SILC_STR_UI_SHORT(truelen),
1518                          SILC_STR_UI_CHAR(flags),
1519                          SILC_STR_UI_CHAR(type),
1520                          SILC_STR_UI_CHAR(padlen),
1521                          SILC_STR_UI_CHAR(0),
1522                          SILC_STR_UI_CHAR(src_id_len),
1523                          SILC_STR_UI_CHAR(dst_id_len),
1524                          SILC_STR_UI_CHAR(src_id_type),
1525                          SILC_STR_DATA(src_id, src_id_len),
1526                          SILC_STR_UI_CHAR(dst_id_type),
1527                          SILC_STR_DATA(dst_id, dst_id_len),
1528                          SILC_STR_DATA(tmppad, padlen),
1529                          SILC_STR_DATA(data, data_len),
1530                          SILC_STR_END);
1531   if (silc_unlikely(i < 0)) {
1532     silc_mutex_unlock(stream->lock);
1533     return FALSE;
1534   }
1535
1536   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1537                    silc_buffer_data(&packet), silc_buffer_len(&packet));
1538
1539   /* Encrypt the packet */
1540   if (silc_likely(cipher)) {
1541     SILC_LOG_DEBUG(("Encrypting packet"));
1542     silc_cipher_set_iv(cipher, NULL);
1543     if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
1544                                            packet.data + ivlen, enclen,
1545                                            NULL))) {
1546       SILC_LOG_ERROR(("Packet encryption failed"));
1547       silc_mutex_unlock(stream->lock);
1548       return FALSE;
1549     }
1550   }
1551
1552   /* Compute HMAC */
1553   if (silc_likely(hmac)) {
1554     SilcUInt32 mac_len;
1555
1556     /* MAC is computed from the entire encrypted packet data, and put
1557        to the end of the packet. */
1558     silc_hmac_init(hmac);
1559     silc_hmac_update(hmac, psn, sizeof(psn));
1560     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1561     silc_hmac_final(hmac, packet.tail, &mac_len);
1562     silc_buffer_pull_tail(&packet, mac_len);
1563     stream->send_psn++;
1564   }
1565
1566   return TRUE;
1567 }
1568
1569 /* Sends a packet */
1570
1571 SilcBool silc_packet_send(SilcPacketStream stream,
1572                           SilcPacketType type, SilcPacketFlags flags,
1573                           const unsigned char *data, SilcUInt32 data_len)
1574 {
1575   SilcBool ret;
1576
1577   ret = silc_packet_send_raw(stream, type, flags,
1578                              stream->src_id_type,
1579                              stream->src_id,
1580                              stream->src_id_len,
1581                              stream->dst_id_type,
1582                              stream->dst_id,
1583                              stream->dst_id_len,
1584                              data, data_len,
1585                              stream->send_key[0],
1586                              stream->send_hmac[0]);
1587
1588   /* Write the packet to the stream */
1589   return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1590 }
1591
1592 /* Sends a packet, extended routine */
1593
1594 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1595                               SilcPacketType type, SilcPacketFlags flags,
1596                               SilcIdType src_id_type, void *src_id,
1597                               SilcIdType dst_id_type, void *dst_id,
1598                               const unsigned char *data, SilcUInt32 data_len,
1599                               SilcCipher cipher, SilcHmac hmac)
1600 {
1601   unsigned char src_id_data[32], dst_id_data[32];
1602   SilcUInt32 src_id_len, dst_id_len;
1603   SilcBool ret;
1604
1605   if (src_id)
1606     if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1607                         sizeof(src_id_data), &src_id_len))
1608       return FALSE;
1609   if (dst_id)
1610     if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1611                         sizeof(dst_id_data), &dst_id_len))
1612       return FALSE;
1613
1614   ret = silc_packet_send_raw(stream, type, flags,
1615                              src_id ? src_id_type : stream->src_id_type,
1616                              src_id ? src_id_data : stream->src_id,
1617                              src_id ? src_id_len : stream->src_id_len,
1618                              dst_id ? dst_id_type : stream->dst_id_type,
1619                              dst_id ? dst_id_data : stream->dst_id,
1620                              dst_id ? dst_id_len : stream->dst_id_len,
1621                              data, data_len,
1622                              cipher ? cipher : stream->send_key[0],
1623                              hmac ? hmac : stream->send_hmac[0]);
1624
1625   /* Write the packet to the stream */
1626   return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1627 }
1628
1629 /* Sends packet after formatting the arguments to buffer */
1630
1631 SilcBool silc_packet_send_va(SilcPacketStream stream,
1632                              SilcPacketType type, SilcPacketFlags flags, ...)
1633 {
1634   SilcBufferStruct buf;
1635   SilcBool ret;
1636   va_list va;
1637
1638   va_start(va, flags);
1639
1640   memset(&buf, 0, sizeof(buf));
1641   if (silc_buffer_format_vp(&buf, va) < 0) {
1642     va_end(va);
1643     return FALSE;
1644   }
1645
1646   ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1647                          silc_buffer_len(&buf));
1648
1649   silc_buffer_purge(&buf);
1650   va_end(va);
1651
1652   return ret;
1653 }
1654
1655 /* Sends packet after formatting the arguments to buffer, extended routine */
1656
1657 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1658                                  SilcPacketType type, SilcPacketFlags flags,
1659                                  SilcIdType src_id_type, void *src_id,
1660                                  SilcIdType dst_id_type, void *dst_id,
1661                                  SilcCipher cipher, SilcHmac hmac, ...)
1662 {
1663   SilcBufferStruct buf;
1664   SilcBool ret;
1665   va_list va;
1666
1667   va_start(va, hmac);
1668
1669   memset(&buf, 0, sizeof(buf));
1670   if (silc_buffer_format_vp(&buf, va) < 0) {
1671     va_end(va);
1672     return FALSE;
1673   }
1674
1675   ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1676                              dst_id_type, dst_id, silc_buffer_data(&buf),
1677                              silc_buffer_len(&buf), cipher, hmac);
1678
1679   silc_buffer_purge(&buf);
1680   va_end(va);
1681
1682   return TRUE;
1683 }
1684
1685 /***************************** Packet Receiving *****************************/
1686
1687 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1688
1689 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1690                                              const unsigned char *data,
1691                                              SilcUInt32 data_len,
1692                                              const unsigned char *packet_mac,
1693                                              const unsigned char *packet_seq,
1694                                              SilcUInt32 sequence)
1695 {
1696   /* Check MAC */
1697   if (silc_likely(hmac)) {
1698     unsigned char mac[32], psn[4];
1699     SilcUInt32 mac_len;
1700
1701     SILC_LOG_DEBUG(("Verifying MAC"));
1702
1703     /* Compute HMAC of packet */
1704     silc_hmac_init(hmac);
1705
1706     if (!packet_seq) {
1707       SILC_PUT32_MSB(sequence, psn);
1708       silc_hmac_update(hmac, psn, 4);
1709     } else
1710       silc_hmac_update(hmac, packet_seq, 4);
1711
1712     silc_hmac_update(hmac, data, data_len);
1713     silc_hmac_final(hmac, mac, &mac_len);
1714
1715     /* Compare the MAC's */
1716     if (silc_unlikely(memcmp(packet_mac, mac, mac_len))) {
1717       SILC_LOG_DEBUG(("MAC failed"));
1718       return FALSE;
1719     }
1720
1721     SILC_LOG_DEBUG(("MAC is Ok"));
1722   }
1723
1724   return TRUE;
1725 }
1726
1727 /* Increments/sets counter when decrypting in counter mode. */
1728
1729 static inline void silc_packet_receive_ctr_increment(SilcPacketStream stream,
1730                                                      unsigned char *iv,
1731                                                      unsigned char *packet_iv)
1732 {
1733   SilcUInt32 pc1, pc2;
1734
1735   /* If IV Included flag, set the IV from packet to block counter. */
1736   if (stream->iv_included) {
1737     memcpy(iv + 4, packet_iv, 8);
1738   } else {
1739     /* Increment 64-bit packet counter. */
1740     SILC_GET32_MSB(pc1, iv + 4);
1741     SILC_GET32_MSB(pc2, iv + 8);
1742     if (++pc2 == 0)
1743       ++pc1;
1744     SILC_PUT32_MSB(pc1, iv + 4);
1745     SILC_PUT32_MSB(pc2, iv + 8);
1746   }
1747
1748   /* Reset block counter */
1749   memset(iv + 12, 0, 4);
1750
1751   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1752 }
1753
1754 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1755    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1756
1757 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1758                                       SilcUInt32 sequence, SilcBuffer buffer,
1759                                       SilcBool normal)
1760 {
1761   if (normal == TRUE) {
1762     if (silc_likely(cipher)) {
1763       /* Decrypt rest of the packet */
1764       SILC_LOG_DEBUG(("Decrypting the packet"));
1765       if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1766                                              buffer->data,
1767                                              silc_buffer_len(buffer), NULL)))
1768         return -1;
1769     }
1770     return 0;
1771
1772   } else {
1773     /* Decrypt rest of the header plus padding */
1774     if (silc_likely(cipher)) {
1775       SilcUInt16 len;
1776       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1777
1778       SILC_LOG_DEBUG(("Decrypting the header"));
1779
1780       /* Padding length + src id len + dst id len + header length - 16
1781          bytes already decrypted, gives the rest of the encrypted packet */
1782       silc_buffer_push(buffer, block_len);
1783       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1784               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1785              block_len);
1786       silc_buffer_pull(buffer, block_len);
1787
1788       if (silc_unlikely(len > silc_buffer_len(buffer))) {
1789         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1790                         "packet dropped"));
1791         return -1;
1792       }
1793       if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1794                                              buffer->data, len, NULL)))
1795         return -1;
1796     }
1797
1798     return 1;
1799   }
1800 }
1801
1802 /* Parses the packet. This is called when a whole packet is ready to be
1803    parsed. The buffer sent must be already decrypted before calling this
1804    function. */
1805
1806 static inline SilcBool silc_packet_parse(SilcPacket packet)
1807 {
1808   SilcBuffer buffer = &packet->buffer;
1809   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1810   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1811   int ret;
1812
1813   SILC_LOG_DEBUG(("Parsing incoming packet"));
1814
1815   /* Parse the buffer.  This parses the SILC header of the packet. */
1816   ret = silc_buffer_unformat(buffer,
1817                              SILC_STR_ADVANCE,
1818                              SILC_STR_OFFSET(6),
1819                              SILC_STR_UI_CHAR(&src_id_len),
1820                              SILC_STR_UI_CHAR(&dst_id_len),
1821                              SILC_STR_UI_CHAR(&src_id_type),
1822                              SILC_STR_END);
1823   if (silc_unlikely(ret == -1)) {
1824     if (!packet->stream->udp &&
1825         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1826       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1827     return FALSE;
1828   }
1829
1830   if (silc_unlikely(src_id_len > SILC_PACKET_MAX_ID_LEN ||
1831                     dst_id_len > SILC_PACKET_MAX_ID_LEN)) {
1832     if (!packet->stream->udp &&
1833         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1834       SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1835                       packet->src_id_len, packet->dst_id_len));
1836     return FALSE;
1837   }
1838
1839   ret = silc_buffer_unformat(buffer,
1840                              SILC_STR_ADVANCE,
1841                              SILC_STR_DATA(&packet->src_id, src_id_len),
1842                              SILC_STR_UI_CHAR(&dst_id_type),
1843                              SILC_STR_DATA(&packet->dst_id, dst_id_len),
1844                              SILC_STR_OFFSET(padlen),
1845                              SILC_STR_END);
1846   if (silc_unlikely(ret == -1)) {
1847     if (!packet->stream->udp &&
1848         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1849       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1850     return FALSE;
1851   }
1852
1853   if (silc_unlikely(src_id_type > SILC_ID_CHANNEL ||
1854                     dst_id_type > SILC_ID_CHANNEL)) {
1855     if (!packet->stream->udp &&
1856         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1857       SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1858                       src_id_type, dst_id_type));
1859     return FALSE;
1860   }
1861
1862   packet->src_id_len = src_id_len;
1863   packet->dst_id_len = dst_id_len;
1864   packet->src_id_type = src_id_type;
1865   packet->dst_id_type = dst_id_type;
1866
1867   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1868                    silc_buffer_len(buffer)), buffer->head,
1869                    silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1870
1871   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1872                   silc_get_packet_name(packet->type)));
1873
1874   return TRUE;
1875 }
1876
1877 /* Dispatch packet to application.  Called with stream->lock locked.
1878    Returns FALSE if the stream was destroyed while dispatching a packet. */
1879
1880 static SilcBool silc_packet_dispatch(SilcPacket packet)
1881 {
1882   SilcPacketStream stream = packet->stream;
1883   SilcPacketProcess p;
1884   SilcBool default_sent = FALSE;
1885   SilcPacketType *pt;
1886
1887   /* Dispatch packet to all packet processors that want it */
1888
1889   if (silc_likely(!stream->process)) {
1890     /* Send to default processor as no others exist */
1891     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1892     silc_mutex_unlock(stream->lock);
1893     if (silc_unlikely(!stream->sc->engine->callbacks->
1894                       packet_receive(stream->sc->engine, stream, packet,
1895                                      stream->sc->engine->callback_context,
1896                                      stream->stream_context)))
1897       silc_packet_free(packet);
1898     silc_mutex_lock(stream->lock);
1899     return stream->destroyed == FALSE;
1900   }
1901
1902   silc_dlist_start(stream->process);
1903   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1904
1905     /* If priority is 0 or less, we send to default processor first
1906        because default processor has 0 priority */
1907     if (!default_sent && p->priority <= 0) {
1908       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1909       default_sent = TRUE;
1910       silc_mutex_unlock(stream->lock);
1911       if (stream->sc->engine->callbacks->
1912           packet_receive(stream->sc->engine, stream, packet,
1913                          stream->sc->engine->callback_context,
1914                          stream->stream_context)) {
1915         silc_mutex_lock(stream->lock);
1916         return stream->destroyed == FALSE;
1917       }
1918       silc_mutex_lock(stream->lock);
1919     }
1920
1921     /* Send to processor */
1922     if (!p->types) {
1923       /* Send all packet types */
1924       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1925       silc_mutex_unlock(stream->lock);
1926       if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
1927                                        p->callback_context,
1928                                        stream->stream_context)) {
1929         silc_mutex_lock(stream->lock);
1930         return stream->destroyed == FALSE;
1931       }
1932       silc_mutex_lock(stream->lock);
1933     } else {
1934       /* Send specific types */
1935       for (pt = p->types; *pt; pt++) {
1936         if (*pt != packet->type)
1937           continue;
1938         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1939         silc_mutex_unlock(stream->lock);
1940         if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
1941                                          p->callback_context,
1942                                          stream->stream_context)) {
1943           silc_mutex_lock(stream->lock);
1944           return stream->destroyed == FALSE;
1945         }
1946         silc_mutex_lock(stream->lock);
1947         break;
1948       }
1949     }
1950   }
1951
1952   if (!default_sent) {
1953     /* Send to default processor as it has not been sent yet */
1954     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1955     silc_mutex_unlock(stream->lock);
1956     if (stream->sc->engine->callbacks->
1957         packet_receive(stream->sc->engine, stream, packet,
1958                        stream->sc->engine->callback_context,
1959                        stream->stream_context)) {
1960       silc_mutex_lock(stream->lock);
1961       return stream->destroyed == FALSE;
1962     }
1963     silc_mutex_lock(stream->lock);
1964   }
1965
1966   /* If we got here, no one wanted the packet, so drop it */
1967   silc_packet_free(packet);
1968   return stream->destroyed == FALSE;
1969 }
1970
1971 /* Process incoming data and parse packets.  Called with stream->lock
1972    locked. */
1973
1974 static void silc_packet_read_process(SilcPacketStream stream)
1975 {
1976   SilcBuffer inbuf;
1977   SilcCipher cipher;
1978   SilcHmac hmac;
1979   SilcPacket packet;
1980   SilcUInt8 sid;
1981   SilcUInt16 packetlen;
1982   SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1983   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1984   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1985   SilcBool normal;
1986   int ret;
1987
1988   /* Get inbuf.  If there is already some data for this stream in the buffer
1989      we already have it.  Otherwise get the current one from list, it will
1990      include the data. */
1991   inbuf = stream->inbuf;
1992   if (!inbuf) {
1993     silc_dlist_start(stream->sc->inbufs);
1994     inbuf = silc_dlist_get(stream->sc->inbufs);
1995   }
1996
1997   /* Parse the packets from the data */
1998   while (silc_buffer_len(inbuf) > 0) {
1999     ivlen = psnlen = 0;
2000     cipher = stream->receive_key[0];
2001     hmac = stream->receive_hmac[0];
2002     normal = FALSE;
2003
2004     if (silc_unlikely(silc_buffer_len(inbuf) <
2005                       (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
2006                        SILC_PACKET_MIN_HEADER_LEN))) {
2007       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
2008       silc_dlist_del(stream->sc->inbufs, inbuf);
2009       stream->inbuf = inbuf;
2010       return;
2011     }
2012
2013     if (silc_likely(hmac))
2014       mac_len = silc_hmac_len(hmac);
2015     else
2016       mac_len = 0;
2017
2018     /* Decrypt first block of the packet to get the length field out */
2019     if (silc_likely(cipher)) {
2020       block_len = silc_cipher_get_block_len(cipher);
2021
2022       if (stream->iv_included) {
2023         /* SID, IV and sequence number is included in the ciphertext */
2024         sid = (SilcUInt8)inbuf->data[0];
2025
2026         if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR) {
2027           /* Set the CTR mode IV from packet to counter block */
2028           memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2029           silc_packet_receive_ctr_increment(stream, iv, inbuf->data + 1);
2030           ivlen = 8 + 1;
2031         } else {
2032           /* Get IV from packet */
2033           memcpy(iv, inbuf->data + 1, block_len);
2034           ivlen = block_len + 1;
2035         }
2036         psnlen = 4;
2037
2038         /* Check SID, and get correct decryption key */
2039         if (sid != stream->sid) {
2040           /* If SID is recent get the previous key and use it */
2041           if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
2042               stream->receive_key[1] && !stream->receive_hmac[1]) {
2043             cipher = stream->receive_key[1];
2044             hmac = stream->receive_hmac[1];
2045           } else {
2046             /* The SID is unknown, drop rest of the data in buffer */
2047             SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
2048                             sid, stream->sid));
2049             silc_mutex_unlock(stream->lock);
2050             SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
2051             silc_mutex_lock(stream->lock);
2052             goto out;
2053           }
2054         }
2055       } else {
2056         memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2057
2058         /* If using CTR mode, increment the counter */
2059         if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2060           silc_packet_receive_ctr_increment(stream, iv, NULL);
2061       }
2062
2063       if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2064         silc_cipher_set_iv(cipher, NULL);
2065       silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp, block_len, iv);
2066
2067       header = tmp;
2068       if (stream->iv_included) {
2069         /* Take sequence number from packet */
2070         packet_seq = header;
2071         header += 4;
2072       }
2073     } else {
2074       /* Unencrypted packet */
2075       block_len = SILC_PACKET_MIN_HEADER_LEN;
2076       header = inbuf->data;
2077     }
2078
2079     /* Get packet length and full packet length with padding */
2080     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
2081
2082     /* Sanity checks */
2083     if (silc_unlikely(packetlen < SILC_PACKET_MIN_LEN)) {
2084       if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
2085         SILC_LOG_ERROR(("Received too short packet"));
2086       silc_mutex_unlock(stream->lock);
2087       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2088       silc_mutex_lock(stream->lock);
2089       memset(tmp, 0, sizeof(tmp));
2090       goto out;
2091     }
2092
2093     if (silc_buffer_len(inbuf) < paddedlen + ivlen + mac_len) {
2094       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
2095                       "(%d bytes)",
2096                       paddedlen + mac_len - silc_buffer_len(inbuf)));
2097       memset(tmp, 0, sizeof(tmp));
2098       silc_dlist_del(stream->sc->inbufs, inbuf);
2099       stream->inbuf = inbuf;
2100       return;
2101     }
2102
2103     /* Check MAC of the packet */
2104     if (silc_unlikely(!silc_packet_check_mac(hmac, inbuf->data,
2105                                              paddedlen + ivlen,
2106                                              inbuf->data + ivlen +
2107                                              paddedlen, packet_seq,
2108                                              stream->receive_psn))) {
2109       silc_mutex_unlock(stream->lock);
2110       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
2111       silc_mutex_lock(stream->lock);
2112       memset(tmp, 0, sizeof(tmp));
2113       goto out;
2114     }
2115
2116     /* Get packet */
2117     packet = silc_packet_alloc(stream->sc->engine);
2118     if (silc_unlikely(!packet)) {
2119       silc_mutex_unlock(stream->lock);
2120       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2121       silc_mutex_lock(stream->lock);
2122       memset(tmp, 0, sizeof(tmp));
2123       goto out;
2124     }
2125     packet->stream = stream;
2126
2127     /* Allocate more space to packet buffer, if needed */
2128     if (silc_unlikely(silc_buffer_truelen(&packet->buffer) < paddedlen)) {
2129       if (!silc_buffer_realloc(&packet->buffer,
2130                                silc_buffer_truelen(&packet->buffer) +
2131                                (paddedlen -
2132                                 silc_buffer_truelen(&packet->buffer)))) {
2133         silc_mutex_unlock(stream->lock);
2134         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2135         silc_mutex_lock(stream->lock);
2136         silc_packet_free(packet);
2137         memset(tmp, 0, sizeof(tmp));
2138         goto out;
2139       }
2140     }
2141
2142     /* Parse packet header */
2143     packet->flags = (SilcPacketFlags)header[2];
2144     packet->type = (SilcPacketType)header[3];
2145
2146     if (stream->sc->engine->local_is_router) {
2147       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2148           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2149         normal = FALSE;
2150       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
2151                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
2152                 stream->is_router == TRUE))
2153         normal = TRUE;
2154     } else {
2155       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2156           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2157         normal = FALSE;
2158       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
2159         normal = TRUE;
2160     }
2161
2162     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
2163                       stream->receive_psn, paddedlen + ivlen + mac_len),
2164                      inbuf->data, paddedlen + ivlen + mac_len);
2165
2166     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
2167     silc_buffer_pull_tail(&packet->buffer, paddedlen);
2168     silc_buffer_put(&packet->buffer, header, block_len - psnlen);
2169     silc_buffer_pull(&packet->buffer, block_len - psnlen);
2170     silc_buffer_put(&packet->buffer, (inbuf->data + ivlen +
2171                                       psnlen + (block_len - psnlen)),
2172                     paddedlen - ivlen - psnlen - (block_len - psnlen));
2173     if (silc_likely(cipher)) {
2174       silc_cipher_set_iv(cipher, iv);
2175       ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
2176                                 &packet->buffer, normal);
2177       if (silc_unlikely(ret < 0)) {
2178         silc_mutex_unlock(stream->lock);
2179         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
2180         silc_mutex_lock(stream->lock);
2181         silc_packet_free(packet);
2182         memset(tmp, 0, sizeof(tmp));
2183         goto out;
2184       }
2185
2186       stream->receive_psn++;
2187     }
2188     silc_buffer_push(&packet->buffer, block_len);
2189
2190     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
2191     silc_buffer_pull(inbuf, paddedlen + mac_len);
2192
2193     /* Parse the packet */
2194     if (silc_unlikely(!silc_packet_parse(packet))) {
2195       silc_mutex_unlock(stream->lock);
2196       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2197       silc_mutex_lock(stream->lock);
2198       silc_packet_free(packet);
2199       memset(tmp, 0, sizeof(tmp));
2200       goto out;
2201     }
2202
2203     /* Dispatch the packet to application */
2204     if (!silc_packet_dispatch(packet))
2205       break;
2206   }
2207
2208  out:
2209   /* Add inbuf back to free list, if we owned it. */
2210   if (stream->inbuf) {
2211     silc_dlist_add(stream->sc->inbufs, inbuf);
2212     stream->inbuf = NULL;
2213   }
2214
2215   silc_buffer_reset(inbuf);
2216 }
2217
2218 /****************************** Packet Waiting ******************************/
2219
2220 /* Packet wait receive callback */
2221 static SilcBool
2222 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2223                                 SilcPacketStream stream,
2224                                 SilcPacket packet,
2225                                 void *callback_context,
2226                                 void *stream_context);
2227
2228 /* Packet waiting callbacks */
2229 static SilcPacketCallbacks silc_packet_wait_cbs =
2230 {
2231   silc_packet_wait_packet_receive, NULL, NULL
2232 };
2233
2234 /* Packet waiting context */
2235 typedef struct {
2236   SilcMutex wait_lock;
2237   SilcCond wait_cond;
2238   SilcList packet_queue;
2239   unsigned int stopped     : 1;
2240 } *SilcPacketWait;
2241
2242 /* Packet wait receive callback */
2243
2244 static SilcBool
2245 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2246                                 SilcPacketStream stream,
2247                                 SilcPacket packet,
2248                                 void *callback_context,
2249                                 void *stream_context)
2250 {
2251   SilcPacketWait pw = callback_context;
2252
2253   /* Signal the waiting thread for a new packet */
2254   silc_mutex_lock(pw->wait_lock);
2255
2256   if (silc_unlikely(pw->stopped)) {
2257     silc_mutex_unlock(pw->wait_lock);
2258     return FALSE;
2259   }
2260
2261   silc_list_add(pw->packet_queue, packet);
2262   silc_cond_broadcast(pw->wait_cond);
2263
2264   silc_mutex_unlock(pw->wait_lock);
2265
2266   return TRUE;
2267 }
2268
2269 /* Initialize packet waiting */
2270
2271 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2272 {
2273   SilcPacketWait pw;
2274   SilcBool ret;
2275   va_list ap;
2276
2277   pw = silc_calloc(1, sizeof(*pw));
2278   if (!pw)
2279     return NULL;
2280
2281   /* Allocate mutex and conditional variable */
2282   if (!silc_mutex_alloc(&pw->wait_lock)) {
2283     silc_free(pw);
2284     return NULL;
2285   }
2286   if (!silc_cond_alloc(&pw->wait_cond)) {
2287     silc_mutex_free(pw->wait_lock);
2288     silc_free(pw);
2289     return NULL;
2290   }
2291
2292   /* Link to the packet stream for the requested packet types */
2293   va_start(ap, stream);
2294   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2295                                    10000000, ap);
2296   va_end(ap);
2297   if (!ret) {
2298     silc_cond_free(pw->wait_cond);
2299     silc_mutex_free(pw->wait_lock);
2300     silc_free(pw);
2301     return NULL;
2302   }
2303
2304   /* Initialize packet queue */
2305   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2306
2307   return (void *)pw;
2308 }
2309
2310 /* Uninitialize packet waiting */
2311
2312 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2313 {
2314   SilcPacketWait pw = waiter;
2315   SilcPacket packet;
2316
2317   /* Signal any threads to stop waiting */
2318   silc_mutex_lock(pw->wait_lock);
2319   pw->stopped = TRUE;
2320   silc_cond_broadcast(pw->wait_cond);
2321   silc_mutex_unlock(pw->wait_lock);
2322
2323   /* Re-acquire lock and free resources */
2324   silc_mutex_lock(pw->wait_lock);
2325   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2326
2327   /* Free any remaining packets */
2328   silc_list_start(pw->packet_queue);
2329   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2330     silc_packet_free(packet);
2331
2332   silc_mutex_unlock(pw->wait_lock);
2333   silc_cond_free(pw->wait_cond);
2334   silc_mutex_free(pw->wait_lock);
2335   silc_free(pw);
2336 }
2337
2338 /* Blocks thread until a packet has been received. */
2339
2340 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2341 {
2342   SilcPacketWait pw = waiter;
2343   SilcBool ret = FALSE;
2344
2345   silc_mutex_lock(pw->wait_lock);
2346
2347   /* Wait here until packet has arrived */
2348   while (silc_list_count(pw->packet_queue) == 0) {
2349     if (silc_unlikely(pw->stopped)) {
2350       silc_mutex_unlock(pw->wait_lock);
2351       return -1;
2352     }
2353     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2354   }
2355
2356   /* Return packet */
2357   silc_list_start(pw->packet_queue);
2358   *return_packet = silc_list_get(pw->packet_queue);
2359   silc_list_del(pw->packet_queue, *return_packet);
2360
2361   silc_mutex_unlock(pw->wait_lock);
2362
2363   return ret == TRUE ? 1 : 0;
2364 }
2365
2366 /************************** Packet Stream Wrapper ***************************/
2367
2368 /* Packet stream wrapper receive callback */
2369 static SilcBool
2370 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2371                                 SilcPacketStream stream,
2372                                 SilcPacket packet,
2373                                 void *callback_context,
2374                                 void *stream_context);
2375
2376 const SilcStreamOps silc_packet_stream_ops;
2377
2378 /* Packet stream wrapper context */
2379 typedef struct {
2380   const SilcStreamOps *ops;
2381   SilcPacketStream stream;
2382   SilcMutex lock;
2383   void *waiter;                   /* Waiter context in blocking mode */
2384   SilcPacketWrapCoder coder;
2385   void *coder_context;
2386   SilcBuffer encbuf;
2387   SilcStreamNotifier callback;
2388   void *context;
2389   SilcList in_queue;
2390   SilcPacketType type;
2391   SilcPacketFlags flags;
2392   unsigned int closed        : 1;
2393   unsigned int blocking      : 1;
2394   unsigned int read_more     : 1;
2395 } *SilcPacketWrapperStream;
2396
2397 /* Packet wrapper callbacks */
2398 static SilcPacketCallbacks silc_packet_wrap_cbs =
2399 {
2400   silc_packet_wrap_packet_receive, NULL, NULL
2401 };
2402
2403 /* Packet stream wrapper receive callback, non-blocking mode */
2404
2405 static SilcBool
2406 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2407                                 SilcPacketStream stream,
2408                                 SilcPacket packet,
2409                                 void *callback_context,
2410                                 void *stream_context)
2411 {
2412   SilcPacketWrapperStream pws = callback_context;
2413
2414   if (pws->closed || !pws->callback)
2415     return FALSE;
2416
2417   silc_mutex_lock(pws->lock);
2418   silc_list_add(pws->in_queue, packet);
2419   silc_mutex_unlock(pws->lock);
2420
2421   /* Call notifier callback */
2422   pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2423
2424   return TRUE;
2425 }
2426
2427 /* Task callback to notify more data is available for reading */
2428
2429 SILC_TASK_CALLBACK(silc_packet_wrap_read_more)
2430 {
2431   SilcPacketWrapperStream pws = context;
2432
2433   if (pws->closed || !pws->callback)
2434     return;
2435
2436   /* Call notifier callback */
2437   pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2438 }
2439
2440 /* Read SILC packet */
2441
2442 int silc_packet_wrap_read(SilcStream stream, unsigned char *buf,
2443                           SilcUInt32 buf_len)
2444 {
2445   SilcPacketWrapperStream pws = stream;
2446   SilcPacket packet;
2447   SilcBool read_more = FALSE;
2448   int len;
2449
2450   if (pws->closed)
2451     return -2;
2452
2453   if (pws->blocking) {
2454     /* Block until packet is received */
2455     if ((silc_packet_wait(pws->waiter, 0, &packet)) < 0)
2456       return -2;
2457     if (pws->closed)
2458       return -2;
2459   } else {
2460     /* Non-blocking mode */
2461     silc_mutex_lock(pws->lock);
2462     if (!silc_list_count(pws->in_queue)) {
2463       silc_mutex_unlock(pws->lock);
2464       return -1;
2465     }
2466
2467     silc_list_start(pws->in_queue);
2468     packet = silc_list_get(pws->in_queue);
2469     silc_list_del(pws->in_queue, packet);
2470     silc_mutex_unlock(pws->lock);
2471   }
2472
2473   /* Call decoder if set */
2474   if (pws->coder && !pws->read_more)
2475     pws->coder(stream, SILC_STREAM_CAN_READ, &packet->buffer,
2476                pws->coder_context);
2477
2478   len = silc_buffer_len(&packet->buffer);
2479   if (len > buf_len) {
2480     len = buf_len;
2481     read_more = TRUE;
2482   }
2483
2484   /* Read data */
2485   memcpy(buf, packet->buffer.data, len);
2486
2487   if (read_more && !pws->blocking) {
2488     /* More data will be available (in blocking mode not supported). */
2489     silc_buffer_pull(&packet->buffer, len);
2490     silc_list_insert(pws->in_queue, NULL, packet);
2491     silc_schedule_task_add_timeout(pws->stream->sc->schedule,
2492                                    silc_packet_wrap_read_more, pws, 0, 0);
2493     pws->read_more = TRUE;
2494     return len;
2495   }
2496
2497   pws->read_more = FALSE;
2498   silc_packet_free(packet);
2499   return len;
2500 }
2501
2502 /* Write SILC packet */
2503
2504 int silc_packet_wrap_write(SilcStream stream, const unsigned char *data,
2505                            SilcUInt32 data_len)
2506 {
2507   SilcPacketWrapperStream pws = stream;
2508   SilcBool ret = FALSE;
2509
2510   /* Call decoder if set */
2511   if (pws->coder) {
2512     silc_buffer_reset(pws->encbuf);
2513     ret = pws->coder(stream, SILC_STREAM_CAN_WRITE, pws->encbuf,
2514                      pws->coder_context);
2515   }
2516
2517   /* Send the SILC packet */
2518   if (ret) {
2519     if (!silc_packet_send_va(pws->stream, pws->type, pws->flags,
2520                              SILC_STR_DATA(silc_buffer_data(pws->encbuf),
2521                                            silc_buffer_len(pws->encbuf)),
2522                              SILC_STR_DATA(data, data_len),
2523                              SILC_STR_END))
2524       return -2;
2525   } else {
2526     if (!silc_packet_send(pws->stream, pws->type, pws->flags, data, data_len))
2527       return -2;
2528   }
2529
2530   return data_len;
2531 }
2532
2533 /* Close stream */
2534
2535 SilcBool silc_packet_wrap_close(SilcStream stream)
2536 {
2537   SilcPacketWrapperStream pws = stream;
2538
2539   if (pws->closed)
2540     return TRUE;
2541
2542   if (pws->blocking) {
2543     /* Close packet waiter */
2544     silc_packet_wait_uninit(pws->waiter, pws->stream);
2545   } else {
2546     /* Unlink */
2547     if (pws->callback)
2548       silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2549   }
2550   pws->closed = TRUE;
2551
2552   return TRUE;
2553 }
2554
2555 /* Destroy wrapper stream */
2556
2557 void silc_packet_wrap_destroy(SilcStream stream)
2558
2559 {
2560   SilcPacketWrapperStream pws = stream;
2561   SilcPacket packet;
2562
2563   SILC_LOG_DEBUG(("Destroying wrapped packet stream %p", pws));
2564
2565   silc_stream_close(stream);
2566   silc_list_start(pws->in_queue);
2567   while ((packet = silc_list_get(pws->in_queue)))
2568     silc_packet_free(packet);
2569   if (pws->lock)
2570     silc_mutex_free(pws->lock);
2571   if (pws->encbuf)
2572     silc_buffer_free(pws->encbuf);
2573   silc_packet_stream_unref(pws->stream);
2574
2575   silc_free(pws);
2576 }
2577
2578 /* Link stream to receive packets */
2579
2580 SilcBool silc_packet_wrap_notifier(SilcStream stream,
2581                                    SilcSchedule schedule,
2582                                    SilcStreamNotifier callback,
2583                                    void *context)
2584 {
2585   SilcPacketWrapperStream pws = stream;
2586
2587   if (pws->closed || pws->blocking)
2588     return FALSE;
2589
2590   /* Link to receive packets */
2591   if (callback)
2592     silc_packet_stream_link(pws->stream, &silc_packet_wrap_cbs, pws,
2593                             100000, pws->type, -1);
2594   else
2595     silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2596
2597   pws->callback = callback;
2598   pws->context = context;
2599
2600   return TRUE;
2601 }
2602
2603 /* Return schedule */
2604
2605 SilcSchedule silc_packet_wrap_get_schedule(SilcStream stream)
2606 {
2607   return NULL;
2608 }
2609
2610 /* Wraps packet stream into SilcStream. */
2611
2612 SilcStream silc_packet_stream_wrap(SilcPacketStream stream,
2613                                    SilcPacketType type,
2614                                    SilcPacketFlags flags,
2615                                    SilcBool blocking_mode,
2616                                    SilcPacketWrapCoder coder,
2617                                    void *context)
2618 {
2619   SilcPacketWrapperStream pws;
2620
2621   pws = silc_calloc(1, sizeof(*pws));
2622   if (!pws)
2623     return NULL;
2624
2625   SILC_LOG_DEBUG(("Wrapping packet stream %p to stream %p", stream, pws));
2626
2627   pws->ops = &silc_packet_stream_ops;
2628   pws->stream = stream;
2629   pws->type = type;
2630   pws->flags = flags;
2631   pws->blocking = blocking_mode;
2632   pws->coder = coder;
2633   pws->coder_context = context;
2634
2635   /* Allocate small amount for encoder buffer. */
2636   if (pws->coder)
2637     pws->encbuf = silc_buffer_alloc(8);
2638
2639   if (pws->blocking) {
2640     /* Blocking mode.  Use packet waiter to do the thing. */
2641     pws->waiter = silc_packet_wait_init(pws->stream, pws->type, -1);
2642     if (!pws->waiter) {
2643       silc_free(pws);
2644       return NULL;
2645     }
2646   } else {
2647     /* Non-blocking mode */
2648     silc_mutex_alloc(&pws->lock);
2649     silc_list_init(pws->in_queue, struct SilcPacketStruct, next);
2650   }
2651
2652   silc_packet_stream_ref(stream);
2653
2654   return (SilcStream)pws;
2655 }
2656
2657 const SilcStreamOps silc_packet_stream_ops =
2658 {
2659   silc_packet_wrap_read,
2660   silc_packet_wrap_write,
2661   silc_packet_wrap_close,
2662   silc_packet_wrap_destroy,
2663   silc_packet_wrap_notifier,
2664   silc_packet_wrap_get_schedule,
2665 };