Use list of input buffers in per scheduler context so that multiple
[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
608   SILC_LOG_DEBUG(("Stopping packet engine"));
609
610   if (!engine)
611     return;
612
613   /* XXX */
614
615   silc_free(engine);
616 }
617
618 /* Create new packet stream */
619
620 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
621                                            SilcSchedule schedule,
622                                            SilcStream stream)
623 {
624   SilcPacketStream ps;
625   SilcBuffer inbuf;
626   void *tmp;
627
628   SILC_LOG_DEBUG(("Creating new packet stream"));
629
630   if (!engine || !stream)
631     return NULL;
632
633   ps = silc_calloc(1, sizeof(*ps));
634   if (!ps)
635     return NULL;
636
637   ps->stream = stream;
638   silc_atomic_init8(&ps->refcnt, 1);
639   silc_mutex_alloc(&ps->lock);
640
641   /* Allocate out buffer */
642   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
643   if (!tmp) {
644     silc_packet_stream_destroy(ps);
645     return NULL;
646   }
647   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
648   silc_buffer_reset(&ps->outbuf);
649
650   /* Initialize packet procesors list */
651   ps->process = silc_dlist_init();
652   if (!ps->process) {
653     silc_packet_stream_destroy(ps);
654     return NULL;
655   }
656
657   silc_mutex_lock(engine->lock);
658
659   /* Add per scheduler context */
660   if (!silc_hash_table_find(engine->contexts, schedule, NULL,
661                             (void *)&ps->sc)) {
662     ps->sc = silc_calloc(1, sizeof(*ps->sc));
663     if (!ps->sc) {
664       silc_packet_stream_destroy(ps);
665       silc_mutex_unlock(engine->lock);
666       return NULL;
667     }
668     ps->sc->engine = engine;
669     ps->sc->schedule = schedule;
670
671     /* Allocate data input buffer */
672     inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE * 31);
673     if (!inbuf) {
674       silc_free(ps->sc);
675       ps->sc = NULL;
676       silc_packet_stream_destroy(ps);
677       silc_mutex_unlock(engine->lock);
678       return NULL;
679     }
680     silc_buffer_reset(inbuf);
681
682     ps->sc->inbufs = silc_dlist_init();
683     if (!ps->sc->inbufs) {
684       silc_buffer_free(inbuf);
685       silc_free(ps->sc);
686       ps->sc = NULL;
687       silc_packet_stream_destroy(ps);
688       silc_mutex_unlock(engine->lock);
689       return NULL;
690     }
691     silc_dlist_add(ps->sc->inbufs, inbuf);
692
693     /* Add to per scheduler context hash table */
694     if (!silc_hash_table_add(engine->contexts, schedule, ps->sc)) {
695       silc_buffer_free(inbuf);
696       silc_dlist_del(ps->sc->inbufs, inbuf);
697       silc_free(ps->sc);
698       ps->sc = NULL;
699       silc_packet_stream_destroy(ps);
700       silc_mutex_unlock(engine->lock);
701       return NULL;
702     }
703   }
704   ps->sc->stream_count++;
705
706   /* Add the packet stream to engine */
707   silc_list_add(engine->streams, ps);
708
709   /* If this is UDP stream, allocate UDP remote stream hash table */
710   if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
711     engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
712                                                silc_hash_string_compare, NULL,
713                                                silc_packet_engine_hash_destr,
714                                                NULL, TRUE);
715
716   silc_mutex_unlock(engine->lock);
717
718   /* Set IO notifier callback.  This schedules this stream for I/O. */
719   if (!silc_stream_set_notifier(ps->stream, schedule,
720                                 silc_packet_stream_io, ps)) {
721     SILC_LOG_DEBUG(("Cannot set stream notifier for packet stream"));
722     silc_packet_stream_destroy(ps);
723     return NULL;
724   }
725
726   return ps;
727 }
728
729 /* Add new remote packet stream for UDP packet streams */
730
731 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
732                                                const char *remote_ip,
733                                                SilcUInt16 remote_port,
734                                                SilcPacket packet)
735 {
736   SilcPacketEngine engine = stream->sc->engine;
737   SilcPacketStream ps;
738   char *tuple;
739   void *tmp;
740
741   SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
742                   remote_ip, remote_port, stream));
743
744   if (!stream || !remote_ip || !remote_port)
745     return NULL;
746
747   if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
748     SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
749     return NULL;
750   }
751
752   ps = silc_calloc(1, sizeof(*ps));
753   if (!ps)
754     return NULL;
755   ps->sc = stream->sc;
756
757   silc_atomic_init8(&ps->refcnt, 1);
758   silc_mutex_alloc(&ps->lock);
759
760   /* Set the UDP packet stream as underlaying stream */
761   silc_packet_stream_ref(stream);
762   ps->stream = (SilcStream)stream;
763   ps->udp = TRUE;
764
765   /* Allocate out buffer */
766   tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
767   if (!tmp) {
768     silc_packet_stream_destroy(ps);
769     return NULL;
770   }
771   silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
772   silc_buffer_reset(&ps->outbuf);
773
774   /* Initialize packet procesors list */
775   ps->process = silc_dlist_init();
776   if (!ps->process) {
777     silc_packet_stream_destroy(ps);
778     return NULL;
779   }
780
781   /* Add to engine with this IP and port pair */
782   tuple = silc_format("%d%s", remote_port, remote_ip);
783   silc_mutex_lock(engine->lock);
784   if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
785     silc_mutex_unlock(engine->lock);
786     silc_packet_stream_destroy(ps);
787     return NULL;
788   }
789   silc_mutex_unlock(engine->lock);
790
791   /* Save remote IP and port pair */
792   ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
793   if (!ps->remote_udp) {
794     silc_packet_stream_destroy(ps);
795     return NULL;
796   }
797   ps->remote_udp->remote_port = remote_port;
798   ps->remote_udp->remote_ip = strdup(remote_ip);
799   if (!ps->remote_udp->remote_ip) {
800     silc_packet_stream_destroy(ps);
801     return NULL;
802   }
803
804   if (packet) {
805     /* Inject packet to the new stream */
806     packet->stream = ps;
807     silc_packet_stream_ref(ps);
808     silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
809                                    silc_packet_stream_inject_packet, packet,
810                                    0, 0);
811   }
812
813   return ps;
814 }
815
816 /* Destroy packet stream */
817
818 void silc_packet_stream_destroy(SilcPacketStream stream)
819 {
820   if (!stream)
821     return;
822
823   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0) {
824     stream->destroyed = TRUE;
825
826     /* Close the underlaying stream */
827     if (!stream->udp && stream->stream)
828       silc_stream_close(stream->stream);
829     return;
830   }
831
832   SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
833
834   if (!stream->udp) {
835     /* Delete from engine */
836     silc_mutex_lock(stream->sc->engine->lock);
837     silc_list_del(stream->sc->engine->streams, stream);
838
839     /* Remove per scheduler context, if it is not used anymore */
840     if (stream->sc) {
841       stream->sc->stream_count--;
842       if (!stream->sc->stream_count)
843         silc_hash_table_del(stream->sc->engine->contexts,
844                             stream->sc->schedule);
845     }
846     silc_mutex_unlock(stream->sc->engine->lock);
847
848     /* Destroy the underlaying stream */
849     if (stream->stream)
850       silc_stream_destroy(stream->stream);
851   } else {
852     /* Delete from UDP remote hash table */
853     char tuple[64];
854     silc_snprintf(tuple, sizeof(tuple), "%d%s", stream->remote_udp->remote_port,
855              stream->remote_udp->remote_ip);
856     silc_mutex_lock(stream->sc->engine->lock);
857     silc_hash_table_del(stream->sc->engine->udp_remote, tuple);
858     silc_mutex_unlock(stream->sc->engine->lock);
859
860     silc_free(stream->remote_udp->remote_ip);
861     silc_free(stream->remote_udp);
862
863     /* Unreference the underlaying packet stream */
864     silc_packet_stream_unref((SilcPacketStream)stream->stream);
865   }
866
867   /* Clear and free buffers */
868   silc_buffer_clear(&stream->outbuf);
869   silc_buffer_purge(&stream->outbuf);
870
871   if (stream->process) {
872     SilcPacketProcess p;
873     silc_dlist_start(stream->process);
874     while ((p = silc_dlist_get(stream->process))) {
875       silc_free(p->types);
876       silc_free(p);
877       silc_dlist_del(stream->process, p);
878     }
879     silc_dlist_uninit(stream->process);
880   }
881
882   /* XXX */
883
884   silc_atomic_uninit8(&stream->refcnt);
885   silc_mutex_free(stream->lock);
886   silc_free(stream);
887 }
888
889 /* Marks as router stream */
890
891 void silc_packet_stream_set_router(SilcPacketStream stream)
892 {
893   stream->is_router = TRUE;
894 }
895
896 /* Mark to include IV in ciphertext */
897
898 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
899 {
900   stream->iv_included = TRUE;
901 }
902
903 /* Links `callbacks' to `stream' for specified packet types */
904
905 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
906                                            SilcPacketCallbacks *callbacks,
907                                            void *callback_context,
908                                            int priority, va_list ap)
909 {
910   SilcPacketProcess p, e;
911   SilcInt32 packet_type;
912   int i;
913
914   SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
915
916   if (!callbacks)
917     return FALSE;
918   if (!callbacks->packet_receive)
919     return FALSE;
920
921   p = silc_calloc(1, sizeof(*p));
922   if (!p)
923     return FALSE;
924
925   p->priority = priority;
926   p->callbacks = callbacks;
927   p->callback_context = callback_context;
928
929   silc_mutex_lock(stream->lock);
930
931   if (!stream->process) {
932     stream->process = silc_dlist_init();
933     if (!stream->process) {
934       silc_mutex_unlock(stream->lock);
935       return FALSE;
936     }
937   }
938
939   /* According to priority set the procesor to correct position.  First
940      entry has the highest priority */
941   silc_dlist_start(stream->process);
942   while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
943     if (p->priority > e->priority) {
944       silc_dlist_insert(stream->process, p);
945       break;
946     }
947   }
948   if (!e)
949     silc_dlist_add(stream->process, p);
950
951   /* Get packet types to process */
952   i = 1;
953   while (1) {
954     packet_type = va_arg(ap, SilcInt32);
955
956     if (packet_type == SILC_PACKET_ANY)
957       break;
958
959     if (packet_type == -1)
960       break;
961
962     p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
963     if (!p->types) {
964       silc_mutex_unlock(stream->lock);
965       return FALSE;
966     }
967
968     p->types[i - 1] = (SilcPacketType)packet_type;
969     i++;
970   }
971   if (p->types)
972     p->types[i - 1] = 0;
973
974   silc_mutex_unlock(stream->lock);
975
976   silc_packet_stream_ref(stream);
977
978   return TRUE;
979 }
980
981 /* Links `callbacks' to `stream' for specified packet types */
982
983 SilcBool silc_packet_stream_link(SilcPacketStream stream,
984                                  SilcPacketCallbacks *callbacks,
985                                  void *callback_context,
986                                  int priority, ...)
987 {
988   va_list ap;
989   SilcBool ret;
990
991   va_start(ap, priority);
992   ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
993                                    priority, ap);
994   va_end(ap);
995
996   return ret;
997 }
998
999 /* Unlinks `callbacks' from `stream'. */
1000
1001 void silc_packet_stream_unlink(SilcPacketStream stream,
1002                                SilcPacketCallbacks *callbacks,
1003                                void *callback_context)
1004 {
1005   SilcPacketProcess p;
1006
1007   SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
1008                   callbacks, stream));
1009
1010   silc_mutex_lock(stream->lock);
1011
1012   silc_dlist_start(stream->process);
1013   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
1014     if (p->callbacks == callbacks &&
1015         p->callback_context == callback_context) {
1016       silc_dlist_del(stream->process, p);
1017       silc_free(p->types);
1018       silc_free(p);
1019       break;
1020     }
1021
1022   if (!silc_dlist_count(stream->process)) {
1023     silc_dlist_uninit(stream->process);
1024     stream->process = NULL;
1025   }
1026
1027   silc_mutex_unlock(stream->lock);
1028
1029   silc_packet_stream_unref(stream);
1030 }
1031
1032 /* Returns TRUE if stream is UDP stream */
1033
1034 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
1035 {
1036   return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
1037 }
1038
1039 /* Return packet sender IP and port for UDP packet stream */
1040
1041 SilcBool silc_packet_get_sender(SilcPacket packet,
1042                                 const char **sender_ip,
1043                                 SilcUInt16 *sender_port)
1044 {
1045   if (!packet->stream->remote_udp)
1046     return FALSE;
1047
1048   *sender_ip = packet->stream->remote_udp->remote_ip;
1049   *sender_port = packet->stream->remote_udp->remote_port;
1050
1051   return TRUE;
1052 }
1053
1054 /* Reference packet stream */
1055
1056 void silc_packet_stream_ref(SilcPacketStream stream)
1057 {
1058   silc_atomic_add_int8(&stream->refcnt, 1);
1059   SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1060                   silc_atomic_get_int8(&stream->refcnt) - 1,
1061                   silc_atomic_get_int8(&stream->refcnt)));
1062 }
1063
1064 /* Unreference packet stream */
1065
1066 void silc_packet_stream_unref(SilcPacketStream stream)
1067 {
1068   SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1069                   silc_atomic_get_int8(&stream->refcnt),
1070                   silc_atomic_get_int8(&stream->refcnt) - 1));
1071   if (silc_atomic_sub_int8(&stream->refcnt, 1) > 0)
1072     return;
1073   silc_atomic_add_int8(&stream->refcnt, 1);
1074   silc_packet_stream_destroy(stream);
1075 }
1076
1077 /* Return engine */
1078
1079 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
1080 {
1081   return stream->sc->engine;
1082 }
1083
1084 /* Set application context for packet stream */
1085
1086 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
1087 {
1088   silc_mutex_lock(stream->lock);
1089   stream->stream_context = stream_context;
1090   silc_mutex_unlock(stream->lock);
1091 }
1092
1093 /* Return application context from packet stream */
1094
1095 void *silc_packet_get_context(SilcPacketStream stream)
1096 {
1097   void *context;
1098   silc_mutex_lock(stream->lock);
1099   context = stream->stream_context;
1100   silc_mutex_unlock(stream->lock);
1101   return context;
1102 }
1103
1104 /* Change underlaying stream */
1105
1106 void silc_packet_stream_set_stream(SilcPacketStream ps,
1107                                    SilcStream stream)
1108 {
1109   if (ps->stream)
1110     silc_stream_set_notifier(ps->stream, ps->sc->schedule, NULL, NULL);
1111   ps->stream = stream;
1112   silc_stream_set_notifier(ps->stream, ps->sc->schedule, silc_packet_stream_io,
1113                            ps);
1114 }
1115
1116 /* Return underlaying stream */
1117
1118 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1119 {
1120   return stream->stream;
1121 }
1122
1123 /* Set keys. */
1124
1125 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
1126                               SilcCipher receive_key, SilcHmac send_hmac,
1127                               SilcHmac receive_hmac, SilcBool rekey)
1128 {
1129   SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream));
1130
1131   /* If doing rekey, send REKEY_DONE packet */
1132   if (rekey) {
1133     /* This will take stream lock. */
1134     if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0,
1135                               stream->src_id_type, stream->src_id,
1136                               stream->src_id_len, stream->dst_id_type,
1137                               stream->dst_id, stream->dst_id_len,
1138                               NULL, 0, stream->send_key[0],
1139                               stream->send_hmac[0]))
1140       return FALSE;
1141
1142     /* Write the packet to the stream */
1143     if (!silc_packet_stream_write(stream, TRUE))
1144       return FALSE;
1145   } else {
1146     silc_mutex_lock(stream->lock);
1147   }
1148
1149   /* In case IV Included is set, save the old keys */
1150   if (stream->iv_included) {
1151     if (stream->send_key[1] && send_key) {
1152       silc_cipher_free(stream->send_key[1]);
1153       stream->send_key[1] = stream->send_key[0];
1154     }
1155     if (stream->receive_key[1] && receive_key) {
1156       silc_cipher_free(stream->receive_key[1]);
1157       stream->receive_key[1] = stream->receive_key[0];
1158     }
1159     if (stream->send_hmac[1] && send_hmac) {
1160       silc_hmac_free(stream->send_hmac[1]);
1161       stream->send_hmac[1] = stream->send_hmac[0];
1162     }
1163     if (stream->receive_hmac[1] && receive_hmac) {
1164       silc_hmac_free(stream->receive_hmac[1]);
1165       stream->receive_hmac[1] = stream->receive_hmac[0];
1166     }
1167   } else {
1168     if (stream->send_key[0] && send_key)
1169       silc_cipher_free(stream->send_key[0]);
1170     if (stream->send_key[1] && receive_key)
1171       silc_cipher_free(stream->receive_key[0]);
1172     if (stream->send_hmac[0] && send_hmac)
1173       silc_hmac_free(stream->send_hmac[0]);
1174     if (stream->receive_hmac[0] && receive_hmac)
1175       silc_hmac_free(stream->receive_hmac[0]);
1176   }
1177
1178   /* Set keys */
1179   if (send_key)
1180     stream->send_key[0] = send_key;
1181   if (receive_key)
1182     stream->receive_key[0] = receive_key;
1183   if (send_hmac)
1184     stream->send_hmac[0] = send_hmac;
1185   if (receive_hmac)
1186     stream->receive_hmac[0] = receive_hmac;
1187
1188   silc_mutex_unlock(stream->lock);
1189   return TRUE;
1190 }
1191
1192 /* Return current ciphers from packet stream */
1193
1194 SilcBool silc_packet_get_keys(SilcPacketStream stream,
1195                               SilcCipher *send_key,
1196                               SilcCipher *receive_key,
1197                               SilcHmac *send_hmac,
1198                               SilcHmac *receive_hmac)
1199 {
1200   if (!stream->send_key[0] && !stream->receive_key[0] &&
1201       !stream->send_hmac[0] && !stream->receive_hmac[0])
1202     return FALSE;
1203
1204   silc_mutex_lock(stream->lock);
1205
1206   if (send_key)
1207     *send_key = stream->send_key[0];
1208   if (receive_key)
1209     *receive_key = stream->receive_key[0];
1210   if (send_hmac)
1211     *send_hmac = stream->send_hmac[0];
1212   if (receive_hmac)
1213     *receive_hmac = stream->receive_hmac[0];
1214
1215   silc_mutex_unlock(stream->lock);
1216
1217   return TRUE;
1218 }
1219
1220 /* Set SILC IDs to packet stream */
1221
1222 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1223                              SilcIdType src_id_type, const void *src_id,
1224                              SilcIdType dst_id_type, const void *dst_id)
1225 {
1226   SilcUInt32 len;
1227   unsigned char tmp[32];
1228
1229   if (!src_id && !dst_id)
1230     return FALSE;
1231
1232   SILC_LOG_DEBUG(("Setting new IDs to packet stream"));
1233
1234   silc_mutex_lock(stream->lock);
1235
1236   if (src_id) {
1237     silc_free(stream->src_id);
1238     if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1239       silc_mutex_unlock(stream->lock);
1240       return FALSE;
1241     }
1242     stream->src_id = silc_memdup(tmp, len);
1243     if (!stream->src_id) {
1244       silc_mutex_unlock(stream->lock);
1245       return FALSE;
1246     }
1247     stream->src_id_type = src_id_type;
1248     stream->src_id_len = len;
1249   }
1250
1251   if (dst_id) {
1252     silc_free(stream->dst_id);
1253     if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1254       silc_mutex_unlock(stream->lock);
1255       return FALSE;
1256     }
1257     stream->dst_id = silc_memdup(tmp, len);
1258     if (!stream->dst_id) {
1259       silc_mutex_unlock(stream->lock);
1260       return FALSE;
1261     }
1262     stream->dst_id_type = dst_id_type;
1263     stream->dst_id_len = len;
1264   }
1265
1266   silc_mutex_unlock(stream->lock);
1267
1268   return TRUE;
1269 }
1270
1271 /* Adds Security ID (SID) */
1272
1273 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1274 {
1275   if (!stream->iv_included)
1276     return FALSE;
1277
1278   SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1279
1280   stream->sid = sid;
1281   return TRUE;
1282 }
1283
1284 /* Free packet */
1285
1286 void silc_packet_free(SilcPacket packet)
1287 {
1288   SilcPacketStream stream = packet->stream;
1289
1290   SILC_LOG_DEBUG(("Freeing packet %p", packet));
1291
1292   /* Check for double free */
1293   SILC_ASSERT(packet->stream != NULL);
1294
1295   packet->stream = NULL;
1296   packet->src_id = packet->dst_id = NULL;
1297   silc_buffer_reset(&packet->buffer);
1298
1299   silc_mutex_lock(stream->sc->engine->lock);
1300
1301   /* Put the packet back to freelist */
1302   silc_list_add(stream->sc->engine->packet_pool, packet);
1303   if (silc_list_count(stream->sc->engine->packet_pool) == 1)
1304     silc_list_start(stream->sc->engine->packet_pool);
1305
1306   silc_mutex_unlock(stream->sc->engine->lock);
1307 }
1308
1309 /****************************** Packet Sending ******************************/
1310
1311 /* Prepare outgoing data buffer for packet sending.  Returns the
1312    pointer to that buffer into the `packet'. */
1313
1314 static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1315                                                 SilcUInt32 totlen,
1316                                                 SilcHmac hmac,
1317                                                 SilcBuffer packet)
1318 {
1319   unsigned char *oldptr;
1320   unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1321
1322   totlen += mac_len;
1323
1324   /* Allocate more space if needed */
1325   if (silc_unlikely(silc_buffer_taillen(&stream->outbuf) < totlen)) {
1326     if (!silc_buffer_realloc(&stream->outbuf,
1327                              silc_buffer_truelen(&stream->outbuf) + totlen))
1328       return FALSE;
1329   }
1330
1331   /* Pull data area for the new packet, and return pointer to the start of
1332      the data area and save the pointer in to the `packet'.  MAC is pulled
1333      later after it's computed. */
1334   oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1335   silc_buffer_set(packet, oldptr, totlen);
1336   silc_buffer_push_tail(packet, mac_len);
1337
1338   return TRUE;
1339 }
1340
1341 /* Increments counter when encrypting in counter mode. */
1342
1343 static inline void silc_packet_send_ctr_increment(SilcPacketStream stream,
1344                                                   SilcCipher cipher,
1345                                                   unsigned char *ret_iv)
1346 {
1347   unsigned char *iv = silc_cipher_get_iv(cipher);
1348   SilcUInt32 pc;
1349
1350   /* Increment packet counter */
1351   SILC_GET32_MSB(pc, iv + 8);
1352   pc++;
1353   SILC_PUT32_MSB(pc, iv + 8);
1354
1355   /* Reset block counter */
1356   memset(iv + 12, 0, 4);
1357
1358   /* If IV Included flag, return the 64-bit IV for inclusion in packet */
1359   if (stream->iv_included) {
1360     /* Get new nonce */
1361     ret_iv[0] = silc_rng_get_byte_fast(stream->sc->engine->rng);
1362     ret_iv[1] = ret_iv[0] + iv[4];
1363     ret_iv[2] = ret_iv[0] ^ ret_iv[1];
1364     ret_iv[3] = ret_iv[0] + ret_iv[2];
1365     SILC_PUT32_MSB(pc, ret_iv + 4);
1366     SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
1367
1368     /* Set new nonce to counter block */
1369     memcpy(iv + 4, ret_iv, 4);
1370   }
1371
1372   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1373 }
1374
1375 /* Internal routine to assemble outgoing packet.  Assembles and encryptes
1376    the packet.  The silc_packet_stream_write needs to be called to send it
1377    after this returns TRUE. */
1378
1379 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
1380                                             SilcPacketType type,
1381                                             SilcPacketFlags flags,
1382                                             SilcIdType src_id_type,
1383                                             unsigned char *src_id,
1384                                             SilcUInt32 src_id_len,
1385                                             SilcIdType dst_id_type,
1386                                             unsigned char *dst_id,
1387                                             SilcUInt32 dst_id_len,
1388                                             const unsigned char *data,
1389                                             SilcUInt32 data_len,
1390                                             SilcCipher cipher,
1391                                             SilcHmac hmac)
1392 {
1393   unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1394   int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1395   int i, enclen, truelen, padlen = 0, ivlen = 0, psnlen = 0;
1396   SilcBool ctr;
1397   SilcBufferStruct packet;
1398
1399   SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1400                   "data len %d", silc_get_packet_name(type), stream->send_psn,
1401                   flags, src_id_type, dst_id_type, data_len));
1402
1403   /* Get the true length of the packet. This is saved as payload length
1404      into the packet header.  This does not include the length of the
1405      padding. */
1406   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1407                                             src_id_len + dst_id_len));
1408   enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1409                       src_id_len + dst_id_len);
1410
1411   /* If using CTR mode, increment the counter */
1412   ctr = (cipher && silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR);
1413   if (ctr) {
1414     silc_packet_send_ctr_increment(stream, cipher, iv + 1);
1415
1416     /* If IV is included, the SID, IV and sequence number is added to packet */
1417     if (stream->iv_included && cipher) {
1418       psnlen = sizeof(psn);
1419       ivlen = 8 + 1;
1420       iv[0] = stream->sid;
1421     }
1422   } else {
1423     /* If IV is included, the SID, IV and sequence number is added to packet */
1424     if (stream->iv_included && cipher) {
1425       psnlen = sizeof(psn);
1426       ivlen = block_len + 1;
1427       iv[0] = stream->sid;
1428       memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1429     }
1430   }
1431
1432   /* We automatically figure out the packet structure from the packet
1433      type and flags, and calculate correct length.  Private messages with
1434      private keys and channel messages are special packets as their
1435      payload is encrypted already. */
1436   if ((type == SILC_PACKET_PRIVATE_MESSAGE &&
1437        flags & SILC_PACKET_FLAG_PRIVMSG_KEY) ||
1438       type == SILC_PACKET_CHANNEL_MESSAGE) {
1439
1440     /* Padding is calculated from header + IDs */
1441     if (!ctr)
1442       SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1443                           psnlen), block_len, padlen);
1444
1445     /* Length to encrypt, header + IDs + padding. */
1446     enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1447               padlen + psnlen);
1448   } else {
1449
1450     /* Padding is calculated from true length of the packet */
1451     if (flags & SILC_PACKET_FLAG_LONG_PAD)
1452       SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1453     else if (!ctr)
1454       SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1455
1456     enclen += padlen + psnlen;
1457   }
1458
1459   /* Remove implementation specific flags */
1460   flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1461
1462   /* Get random padding */
1463   for (i = 0; i < padlen; i++) tmppad[i] =
1464     silc_rng_get_byte_fast(stream->sc->engine->rng);
1465
1466   silc_mutex_lock(stream->lock);
1467
1468   /* Get packet pointer from the outgoing buffer */
1469   if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
1470                                               + psnlen, hmac, &packet))) {
1471     silc_mutex_unlock(stream->lock);
1472     return FALSE;
1473   }
1474
1475   SILC_PUT32_MSB(stream->send_psn, psn);
1476
1477   /* Create the packet.  This creates the SILC header, adds padding, and
1478      the actual packet data. */
1479   i = silc_buffer_format(&packet,
1480                          SILC_STR_DATA(iv, ivlen),
1481                          SILC_STR_DATA(psn, psnlen),
1482                          SILC_STR_UI_SHORT(truelen),
1483                          SILC_STR_UI_CHAR(flags),
1484                          SILC_STR_UI_CHAR(type),
1485                          SILC_STR_UI_CHAR(padlen),
1486                          SILC_STR_UI_CHAR(0),
1487                          SILC_STR_UI_CHAR(src_id_len),
1488                          SILC_STR_UI_CHAR(dst_id_len),
1489                          SILC_STR_UI_CHAR(src_id_type),
1490                          SILC_STR_DATA(src_id, src_id_len),
1491                          SILC_STR_UI_CHAR(dst_id_type),
1492                          SILC_STR_DATA(dst_id, dst_id_len),
1493                          SILC_STR_DATA(tmppad, padlen),
1494                          SILC_STR_DATA(data, data_len),
1495                          SILC_STR_END);
1496   if (silc_unlikely(i < 0)) {
1497     silc_mutex_unlock(stream->lock);
1498     return FALSE;
1499   }
1500
1501   SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1502                    silc_buffer_data(&packet), silc_buffer_len(&packet));
1503
1504   /* Encrypt the packet */
1505   if (silc_likely(cipher)) {
1506     SILC_LOG_DEBUG(("Encrypting packet"));
1507     if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
1508                                            packet.data + ivlen, enclen,
1509                                            NULL))) {
1510       SILC_LOG_ERROR(("Packet encryption failed"));
1511       silc_mutex_unlock(stream->lock);
1512       return FALSE;
1513     }
1514   }
1515
1516   /* Compute HMAC */
1517   if (silc_likely(hmac)) {
1518     SilcUInt32 mac_len;
1519
1520     /* MAC is computed from the entire encrypted packet data, and put
1521        to the end of the packet. */
1522     silc_hmac_init(hmac);
1523     silc_hmac_update(hmac, psn, sizeof(psn));
1524     silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1525     silc_hmac_final(hmac, packet.tail, &mac_len);
1526     silc_buffer_pull_tail(&packet, mac_len);
1527     stream->send_psn++;
1528   }
1529
1530   return TRUE;
1531 }
1532
1533 /* Sends a packet */
1534
1535 SilcBool silc_packet_send(SilcPacketStream stream,
1536                           SilcPacketType type, SilcPacketFlags flags,
1537                           const unsigned char *data, SilcUInt32 data_len)
1538 {
1539   SilcBool ret;
1540
1541   ret = silc_packet_send_raw(stream, type, flags,
1542                              stream->src_id_type,
1543                              stream->src_id,
1544                              stream->src_id_len,
1545                              stream->dst_id_type,
1546                              stream->dst_id,
1547                              stream->dst_id_len,
1548                              data, data_len,
1549                              stream->send_key[0],
1550                              stream->send_hmac[0]);
1551
1552   /* Write the packet to the stream */
1553   return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1554 }
1555
1556 /* Sends a packet, extended routine */
1557
1558 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1559                               SilcPacketType type, SilcPacketFlags flags,
1560                               SilcIdType src_id_type, void *src_id,
1561                               SilcIdType dst_id_type, void *dst_id,
1562                               const unsigned char *data, SilcUInt32 data_len,
1563                               SilcCipher cipher, SilcHmac hmac)
1564 {
1565   unsigned char src_id_data[32], dst_id_data[32];
1566   SilcUInt32 src_id_len, dst_id_len;
1567   SilcBool ret;
1568
1569   if (src_id)
1570     if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1571                         sizeof(src_id_data), &src_id_len))
1572       return FALSE;
1573   if (dst_id)
1574     if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1575                         sizeof(dst_id_data), &dst_id_len))
1576       return FALSE;
1577
1578   ret = silc_packet_send_raw(stream, type, flags,
1579                              src_id ? src_id_type : stream->src_id_type,
1580                              src_id ? src_id_data : stream->src_id,
1581                              src_id ? src_id_len : stream->src_id_len,
1582                              dst_id ? dst_id_type : stream->dst_id_type,
1583                              dst_id ? dst_id_data : stream->dst_id,
1584                              dst_id ? dst_id_len : stream->dst_id_len,
1585                              data, data_len,
1586                              cipher ? cipher : stream->send_key[0],
1587                              hmac ? hmac : stream->send_hmac[0]);
1588
1589   /* Write the packet to the stream */
1590   return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1591 }
1592
1593 /* Sends packet after formatting the arguments to buffer */
1594
1595 SilcBool silc_packet_send_va(SilcPacketStream stream,
1596                              SilcPacketType type, SilcPacketFlags flags, ...)
1597 {
1598   SilcBufferStruct buf;
1599   SilcBool ret;
1600   va_list va;
1601
1602   va_start(va, flags);
1603
1604   memset(&buf, 0, sizeof(buf));
1605   if (silc_buffer_format_vp(&buf, va) < 0) {
1606     va_end(va);
1607     return FALSE;
1608   }
1609
1610   ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1611                          silc_buffer_len(&buf));
1612
1613   silc_buffer_purge(&buf);
1614   va_end(va);
1615
1616   return ret;
1617 }
1618
1619 /* Sends packet after formatting the arguments to buffer, extended routine */
1620
1621 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1622                                  SilcPacketType type, SilcPacketFlags flags,
1623                                  SilcIdType src_id_type, void *src_id,
1624                                  SilcIdType dst_id_type, void *dst_id,
1625                                  SilcCipher cipher, SilcHmac hmac, ...)
1626 {
1627   SilcBufferStruct buf;
1628   SilcBool ret;
1629   va_list va;
1630
1631   va_start(va, hmac);
1632
1633   memset(&buf, 0, sizeof(buf));
1634   if (silc_buffer_format_vp(&buf, va) < 0) {
1635     va_end(va);
1636     return FALSE;
1637   }
1638
1639   ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1640                              dst_id_type, dst_id, silc_buffer_data(&buf),
1641                              silc_buffer_len(&buf), cipher, hmac);
1642
1643   silc_buffer_purge(&buf);
1644   va_end(va);
1645
1646   return TRUE;
1647 }
1648
1649 /***************************** Packet Receiving *****************************/
1650
1651 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1652
1653 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1654                                              const unsigned char *data,
1655                                              SilcUInt32 data_len,
1656                                              const unsigned char *packet_mac,
1657                                              const unsigned char *packet_seq,
1658                                              SilcUInt32 sequence)
1659 {
1660   /* Check MAC */
1661   if (silc_likely(hmac)) {
1662     unsigned char mac[32], psn[4];
1663     SilcUInt32 mac_len;
1664
1665     SILC_LOG_DEBUG(("Verifying MAC"));
1666
1667     /* Compute HMAC of packet */
1668     silc_hmac_init(hmac);
1669
1670     if (!packet_seq) {
1671       SILC_PUT32_MSB(sequence, psn);
1672       silc_hmac_update(hmac, psn, 4);
1673     } else
1674       silc_hmac_update(hmac, packet_seq, 4);
1675
1676     silc_hmac_update(hmac, data, data_len);
1677     silc_hmac_final(hmac, mac, &mac_len);
1678
1679     /* Compare the MAC's */
1680     if (silc_unlikely(memcmp(packet_mac, mac, mac_len))) {
1681       SILC_LOG_DEBUG(("MAC failed"));
1682       return FALSE;
1683     }
1684
1685     SILC_LOG_DEBUG(("MAC is Ok"));
1686   }
1687
1688   return TRUE;
1689 }
1690
1691 /* Increments/sets counter when decrypting in counter mode. */
1692
1693 static inline void silc_packet_receive_ctr_increment(SilcPacketStream stream,
1694                                                      unsigned char *iv,
1695                                                      unsigned char *packet_iv)
1696 {
1697   SilcUInt32 pc;
1698
1699   /* If IV Included flag, set the IV from packet to block counter. */
1700   if (stream->iv_included) {
1701     memcpy(iv + 4, packet_iv, 8);
1702   } else {
1703     /* Increment packet counter */
1704     SILC_GET32_MSB(pc, iv + 8);
1705     pc++;
1706     SILC_PUT32_MSB(pc, iv + 8);
1707   }
1708
1709   /* Reset block counter */
1710   memset(iv + 12, 0, 4);
1711
1712   SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1713 }
1714
1715 /* Decrypts SILC packet.  Handles both normal and special packet decryption.
1716    Return 0 when packet is normal and 1 when it it special, -1 on error. */
1717
1718 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1719                                       SilcUInt32 sequence, SilcBuffer buffer,
1720                                       SilcBool normal)
1721 {
1722   if (normal == TRUE) {
1723     if (silc_likely(cipher)) {
1724       /* Decrypt rest of the packet */
1725       SILC_LOG_DEBUG(("Decrypting the packet"));
1726       if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1727                                              buffer->data,
1728                                              silc_buffer_len(buffer), NULL)))
1729         return -1;
1730     }
1731     return 0;
1732
1733   } else {
1734     /* Decrypt rest of the header plus padding */
1735     if (silc_likely(cipher)) {
1736       SilcUInt16 len;
1737       SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1738
1739       SILC_LOG_DEBUG(("Decrypting the header"));
1740
1741       /* Padding length + src id len + dst id len + header length - 16
1742          bytes already decrypted, gives the rest of the encrypted packet */
1743       silc_buffer_push(buffer, block_len);
1744       len = (((SilcUInt8)buffer->data[4] + (SilcUInt8)buffer->data[6] +
1745               (SilcUInt8)buffer->data[7] + SILC_PACKET_HEADER_LEN) -
1746              block_len);
1747       silc_buffer_pull(buffer, block_len);
1748
1749       if (silc_unlikely(len > silc_buffer_len(buffer))) {
1750         SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1751                         "packet dropped"));
1752         return -1;
1753       }
1754       if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1755                                              buffer->data, len, NULL)))
1756         return -1;
1757     }
1758
1759     return 1;
1760   }
1761 }
1762
1763 /* Parses the packet. This is called when a whole packet is ready to be
1764    parsed. The buffer sent must be already decrypted before calling this
1765    function. */
1766
1767 static inline SilcBool silc_packet_parse(SilcPacket packet)
1768 {
1769   SilcBuffer buffer = &packet->buffer;
1770   SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1771   SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1772   int ret;
1773
1774   SILC_LOG_DEBUG(("Parsing incoming packet"));
1775
1776   /* Parse the buffer.  This parses the SILC header of the packet. */
1777   ret = silc_buffer_unformat(buffer,
1778                              SILC_STR_ADVANCE,
1779                              SILC_STR_OFFSET(6),
1780                              SILC_STR_UI_CHAR(&src_id_len),
1781                              SILC_STR_UI_CHAR(&dst_id_len),
1782                              SILC_STR_UI_CHAR(&src_id_type),
1783                              SILC_STR_END);
1784   if (silc_unlikely(ret == -1)) {
1785     if (!packet->stream->udp &&
1786         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1787       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1788     return FALSE;
1789   }
1790
1791   if (silc_unlikely(src_id_len > SILC_PACKET_MAX_ID_LEN ||
1792                     dst_id_len > SILC_PACKET_MAX_ID_LEN)) {
1793     if (!packet->stream->udp &&
1794         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1795       SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1796                       packet->src_id_len, packet->dst_id_len));
1797     return FALSE;
1798   }
1799
1800   ret = silc_buffer_unformat(buffer,
1801                              SILC_STR_ADVANCE,
1802                              SILC_STR_DATA(&packet->src_id, src_id_len),
1803                              SILC_STR_UI_CHAR(&dst_id_type),
1804                              SILC_STR_DATA(&packet->dst_id, dst_id_len),
1805                              SILC_STR_OFFSET(padlen),
1806                              SILC_STR_END);
1807   if (silc_unlikely(ret == -1)) {
1808     if (!packet->stream->udp &&
1809         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1810       SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1811     return FALSE;
1812   }
1813
1814   if (silc_unlikely(src_id_type > SILC_ID_CHANNEL ||
1815                     dst_id_type > SILC_ID_CHANNEL)) {
1816     if (!packet->stream->udp &&
1817         !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1818       SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
1819                       src_id_type, dst_id_type));
1820     return FALSE;
1821   }
1822
1823   packet->src_id_len = src_id_len;
1824   packet->dst_id_len = dst_id_len;
1825   packet->src_id_type = src_id_type;
1826   packet->dst_id_type = dst_id_type;
1827
1828   SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
1829                    silc_buffer_len(buffer)), buffer->head,
1830                    silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
1831
1832   SILC_LOG_DEBUG(("Incoming packet type: %d (%s)", packet->type,
1833                   silc_get_packet_name(packet->type)));
1834
1835   return TRUE;
1836 }
1837
1838 /* Dispatch packet to application.  Called with stream->lock locked.
1839    Returns FALSE if the stream was destroyed while dispatching a packet. */
1840
1841 static SilcBool silc_packet_dispatch(SilcPacket packet)
1842 {
1843   SilcPacketStream stream = packet->stream;
1844   SilcPacketProcess p;
1845   SilcBool default_sent = FALSE;
1846   SilcPacketType *pt;
1847
1848   /* Dispatch packet to all packet processors that want it */
1849
1850   if (silc_likely(!stream->process)) {
1851     /* Send to default processor as no others exist */
1852     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1853     silc_mutex_unlock(stream->lock);
1854     if (silc_unlikely(!stream->sc->engine->callbacks->
1855                       packet_receive(stream->sc->engine, stream, packet,
1856                                      stream->sc->engine->callback_context,
1857                                      stream->stream_context)))
1858       silc_packet_free(packet);
1859     silc_mutex_lock(stream->lock);
1860     return stream->destroyed == FALSE;
1861   }
1862
1863   silc_dlist_start(stream->process);
1864   while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1865
1866     /* If priority is 0 or less, we send to default processor first
1867        because default processor has 0 priority */
1868     if (!default_sent && p->priority <= 0) {
1869       SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1870       default_sent = TRUE;
1871       silc_mutex_unlock(stream->lock);
1872       if (stream->sc->engine->callbacks->
1873           packet_receive(stream->sc->engine, stream, packet,
1874                          stream->sc->engine->callback_context,
1875                          stream->stream_context)) {
1876         silc_mutex_lock(stream->lock);
1877         return stream->destroyed == FALSE;
1878       }
1879       silc_mutex_lock(stream->lock);
1880     }
1881
1882     /* Send to processor */
1883     if (!p->types) {
1884       /* Send all packet types */
1885       SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1886       silc_mutex_unlock(stream->lock);
1887       if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
1888                                        p->callback_context,
1889                                        stream->stream_context)) {
1890         silc_mutex_lock(stream->lock);
1891         return stream->destroyed == FALSE;
1892       }
1893       silc_mutex_lock(stream->lock);
1894     } else {
1895       /* Send specific types */
1896       for (pt = p->types; *pt; pt++) {
1897         if (*pt != packet->type)
1898           continue;
1899         SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
1900         silc_mutex_unlock(stream->lock);
1901         if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
1902                                          p->callback_context,
1903                                          stream->stream_context)) {
1904           silc_mutex_lock(stream->lock);
1905           return stream->destroyed == FALSE;
1906         }
1907         silc_mutex_lock(stream->lock);
1908         break;
1909       }
1910     }
1911   }
1912
1913   if (!default_sent) {
1914     /* Send to default processor as it has not been sent yet */
1915     SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
1916     silc_mutex_unlock(stream->lock);
1917     if (stream->sc->engine->callbacks->
1918         packet_receive(stream->sc->engine, stream, packet,
1919                        stream->sc->engine->callback_context,
1920                        stream->stream_context)) {
1921       silc_mutex_lock(stream->lock);
1922       return stream->destroyed == FALSE;
1923     }
1924     silc_mutex_lock(stream->lock);
1925   }
1926
1927   /* If we got here, no one wanted the packet, so drop it */
1928   silc_packet_free(packet);
1929   return stream->destroyed == FALSE;
1930 }
1931
1932 /* Process incoming data and parse packets.  Called with stream->lock
1933    locked. */
1934
1935 static void silc_packet_read_process(SilcPacketStream stream)
1936 {
1937   SilcBuffer inbuf;
1938   SilcCipher cipher;
1939   SilcHmac hmac;
1940   SilcPacket packet;
1941   SilcUInt8 sid;
1942   SilcUInt16 packetlen;
1943   SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
1944   unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
1945   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
1946   SilcBool normal;
1947   int ret;
1948
1949   /* Get inbuf.  If there is already some data for this stream in the buffer
1950      we already have it.  Otherwise get the current one from list, it will
1951      include the data. */
1952   inbuf = stream->inbuf;
1953   if (!inbuf) {
1954     silc_dlist_start(stream->sc->inbufs);
1955     inbuf = silc_dlist_get(stream->sc->inbufs);
1956   }
1957
1958   /* Parse the packets from the data */
1959   while (silc_buffer_len(inbuf) > 0) {
1960     ivlen = psnlen = 0;
1961     cipher = stream->receive_key[0];
1962     hmac = stream->receive_hmac[0];
1963     normal = FALSE;
1964
1965     if (silc_unlikely(silc_buffer_len(inbuf) <
1966                       (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
1967                        SILC_PACKET_MIN_HEADER_LEN))) {
1968       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
1969       silc_dlist_del(stream->sc->inbufs, inbuf);
1970       stream->inbuf = inbuf;
1971       return;
1972     }
1973
1974     if (silc_likely(hmac))
1975       mac_len = silc_hmac_len(hmac);
1976     else
1977       mac_len = 0;
1978
1979     /* Decrypt first block of the packet to get the length field out */
1980     if (silc_likely(cipher)) {
1981       block_len = silc_cipher_get_block_len(cipher);
1982
1983       if (stream->iv_included) {
1984         /* SID, IV and sequence number is included in the ciphertext */
1985         sid = (SilcUInt8)inbuf->data[0];
1986
1987         if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR) {
1988           /* Set the CTR mode IV from packet to counter block */
1989           memcpy(iv, silc_cipher_get_iv(cipher), block_len);
1990           silc_packet_receive_ctr_increment(stream, iv, inbuf->data + 1);
1991           ivlen = 8 + 1;
1992         } else {
1993           /* Get IV from packet */
1994           memcpy(iv, inbuf->data + 1, block_len);
1995           ivlen = block_len + 1;
1996         }
1997         psnlen = 4;
1998
1999         /* Check SID, and get correct decryption key */
2000         if (sid != stream->sid) {
2001           /* If SID is recent get the previous key and use it */
2002           if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
2003               stream->receive_key[1] && !stream->receive_hmac[1]) {
2004             cipher = stream->receive_key[1];
2005             hmac = stream->receive_hmac[1];
2006           } else {
2007             /* The SID is unknown, drop rest of the data in buffer */
2008             SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
2009                             sid, stream->sid));
2010             silc_mutex_unlock(stream->lock);
2011             SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
2012             silc_mutex_lock(stream->lock);
2013             goto out;
2014           }
2015         }
2016       } else {
2017         memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2018
2019         /* If using CTR mode, increment the counter */
2020         if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2021           silc_packet_receive_ctr_increment(stream, iv, NULL);
2022       }
2023
2024       silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp,
2025                           block_len, iv);
2026
2027       header = tmp;
2028       if (stream->iv_included) {
2029         /* Take sequence number from packet */
2030         packet_seq = header;
2031         header += 4;
2032       }
2033     } else {
2034       /* Unencrypted packet */
2035       block_len = SILC_PACKET_MIN_HEADER_LEN;
2036       header = inbuf->data;
2037     }
2038
2039     /* Get packet length and full packet length with padding */
2040     SILC_PACKET_LENGTH(header, packetlen, paddedlen);
2041
2042     /* Sanity checks */
2043     if (silc_unlikely(packetlen < SILC_PACKET_MIN_LEN)) {
2044       if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
2045         SILC_LOG_ERROR(("Received too short packet"));
2046       silc_mutex_unlock(stream->lock);
2047       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2048       silc_mutex_lock(stream->lock);
2049       memset(tmp, 0, sizeof(tmp));
2050       goto out;
2051     }
2052
2053     if (silc_buffer_len(inbuf) < paddedlen + ivlen + mac_len) {
2054       SILC_LOG_DEBUG(("Received partial packet, waiting for the rest "
2055                       "(%d bytes)",
2056                       paddedlen + mac_len - silc_buffer_len(inbuf)));
2057       memset(tmp, 0, sizeof(tmp));
2058       silc_dlist_del(stream->sc->inbufs, inbuf);
2059       stream->inbuf = inbuf;
2060       return;
2061     }
2062
2063     /* Check MAC of the packet */
2064     if (silc_unlikely(!silc_packet_check_mac(hmac, inbuf->data,
2065                                              paddedlen + ivlen,
2066                                              inbuf->data + ivlen +
2067                                              paddedlen, packet_seq,
2068                                              stream->receive_psn))) {
2069       silc_mutex_unlock(stream->lock);
2070       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
2071       silc_mutex_lock(stream->lock);
2072       memset(tmp, 0, sizeof(tmp));
2073       goto out;
2074     }
2075
2076     /* Get packet */
2077     packet = silc_packet_alloc(stream->sc->engine);
2078     if (silc_unlikely(!packet)) {
2079       silc_mutex_unlock(stream->lock);
2080       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2081       silc_mutex_lock(stream->lock);
2082       memset(tmp, 0, sizeof(tmp));
2083       goto out;
2084     }
2085     packet->stream = stream;
2086
2087     /* Allocate more space to packet buffer, if needed */
2088     if (silc_unlikely(silc_buffer_truelen(&packet->buffer) < paddedlen)) {
2089       if (!silc_buffer_realloc(&packet->buffer,
2090                                silc_buffer_truelen(&packet->buffer) +
2091                                (paddedlen -
2092                                 silc_buffer_truelen(&packet->buffer)))) {
2093         silc_mutex_unlock(stream->lock);
2094         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2095         silc_mutex_lock(stream->lock);
2096         silc_packet_free(packet);
2097         memset(tmp, 0, sizeof(tmp));
2098         goto out;
2099       }
2100     }
2101
2102     /* Parse packet header */
2103     packet->flags = (SilcPacketFlags)header[2];
2104     packet->type = (SilcPacketType)header[3];
2105
2106     if (stream->sc->engine->local_is_router) {
2107       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2108           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2109         normal = FALSE;
2110       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE ||
2111                (packet->type == SILC_PACKET_CHANNEL_MESSAGE &&
2112                 stream->is_router == TRUE))
2113         normal = TRUE;
2114     } else {
2115       if (packet->type == SILC_PACKET_PRIVATE_MESSAGE &&
2116           (packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2117         normal = FALSE;
2118       else if (packet->type != SILC_PACKET_CHANNEL_MESSAGE)
2119         normal = TRUE;
2120     }
2121
2122     SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
2123                       stream->receive_psn, paddedlen + ivlen + mac_len),
2124                      inbuf->data, paddedlen + ivlen + mac_len);
2125
2126     /* Put the decrypted part, and rest of the encrypted data, and decrypt */
2127     silc_buffer_pull_tail(&packet->buffer, paddedlen);
2128     silc_buffer_put(&packet->buffer, header, block_len - psnlen);
2129     silc_buffer_pull(&packet->buffer, block_len - psnlen);
2130     silc_buffer_put(&packet->buffer, (inbuf->data + ivlen +
2131                                       psnlen + (block_len - psnlen)),
2132                     paddedlen - ivlen - psnlen - (block_len - psnlen));
2133     if (silc_likely(cipher)) {
2134       silc_cipher_set_iv(cipher, iv);
2135       ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
2136                                 &packet->buffer, normal);
2137       if (silc_unlikely(ret < 0)) {
2138         silc_mutex_unlock(stream->lock);
2139         SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
2140         silc_mutex_lock(stream->lock);
2141         silc_packet_free(packet);
2142         memset(tmp, 0, sizeof(tmp));
2143         goto out;
2144       }
2145
2146       stream->receive_psn++;
2147     }
2148     silc_buffer_push(&packet->buffer, block_len);
2149
2150     /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
2151     silc_buffer_pull(inbuf, paddedlen + mac_len);
2152
2153     /* Parse the packet */
2154     if (silc_unlikely(!silc_packet_parse(packet))) {
2155       silc_mutex_unlock(stream->lock);
2156       SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2157       silc_mutex_lock(stream->lock);
2158       silc_packet_free(packet);
2159       memset(tmp, 0, sizeof(tmp));
2160       goto out;
2161     }
2162
2163     /* Dispatch the packet to application */
2164     if (!silc_packet_dispatch(packet))
2165       break;
2166   }
2167
2168  out:
2169   /* Add inbuf back to free list, if we owned it. */
2170   if (stream->inbuf) {
2171     silc_dlist_add(stream->sc->inbufs, inbuf);
2172     stream->inbuf = NULL;
2173   }
2174
2175   silc_buffer_reset(inbuf);
2176 }
2177
2178 /****************************** Packet Waiting ******************************/
2179
2180 /* Packet wait receive callback */
2181 static SilcBool
2182 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2183                                 SilcPacketStream stream,
2184                                 SilcPacket packet,
2185                                 void *callback_context,
2186                                 void *stream_context);
2187
2188 /* Packet waiting callbacks */
2189 static SilcPacketCallbacks silc_packet_wait_cbs =
2190 {
2191   silc_packet_wait_packet_receive, NULL, NULL
2192 };
2193
2194 /* Packet waiting context */
2195 typedef struct {
2196   SilcMutex wait_lock;
2197   SilcCond wait_cond;
2198   SilcList packet_queue;
2199   unsigned int stopped     : 1;
2200 } *SilcPacketWait;
2201
2202 /* Packet wait receive callback */
2203
2204 static SilcBool
2205 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2206                                 SilcPacketStream stream,
2207                                 SilcPacket packet,
2208                                 void *callback_context,
2209                                 void *stream_context)
2210 {
2211   SilcPacketWait pw = callback_context;
2212
2213   /* Signal the waiting thread for a new packet */
2214   silc_mutex_lock(pw->wait_lock);
2215
2216   if (silc_unlikely(pw->stopped)) {
2217     silc_mutex_unlock(pw->wait_lock);
2218     return FALSE;
2219   }
2220
2221   silc_list_add(pw->packet_queue, packet);
2222   silc_cond_broadcast(pw->wait_cond);
2223
2224   silc_mutex_unlock(pw->wait_lock);
2225
2226   return TRUE;
2227 }
2228
2229 /* Initialize packet waiting */
2230
2231 void *silc_packet_wait_init(SilcPacketStream stream, ...)
2232 {
2233   SilcPacketWait pw;
2234   SilcBool ret;
2235   va_list ap;
2236
2237   pw = silc_calloc(1, sizeof(*pw));
2238   if (!pw)
2239     return NULL;
2240
2241   /* Allocate mutex and conditional variable */
2242   if (!silc_mutex_alloc(&pw->wait_lock)) {
2243     silc_free(pw);
2244     return NULL;
2245   }
2246   if (!silc_cond_alloc(&pw->wait_cond)) {
2247     silc_mutex_free(pw->wait_lock);
2248     silc_free(pw);
2249     return NULL;
2250   }
2251
2252   /* Link to the packet stream for the requested packet types */
2253   va_start(ap, stream);
2254   ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2255                                    10000000, ap);
2256   va_end(ap);
2257   if (!ret) {
2258     silc_cond_free(pw->wait_cond);
2259     silc_mutex_free(pw->wait_lock);
2260     silc_free(pw);
2261     return NULL;
2262   }
2263
2264   /* Initialize packet queue */
2265   silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2266
2267   return (void *)pw;
2268 }
2269
2270 /* Uninitialize packet waiting */
2271
2272 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2273 {
2274   SilcPacketWait pw = waiter;
2275   SilcPacket packet;
2276
2277   /* Signal any threads to stop waiting */
2278   silc_mutex_lock(pw->wait_lock);
2279   pw->stopped = TRUE;
2280   silc_cond_broadcast(pw->wait_cond);
2281   silc_mutex_unlock(pw->wait_lock);
2282
2283   /* Re-acquire lock and free resources */
2284   silc_mutex_lock(pw->wait_lock);
2285   silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2286
2287   /* Free any remaining packets */
2288   silc_list_start(pw->packet_queue);
2289   while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2290     silc_packet_free(packet);
2291
2292   silc_mutex_unlock(pw->wait_lock);
2293   silc_cond_free(pw->wait_cond);
2294   silc_mutex_free(pw->wait_lock);
2295   silc_free(pw);
2296 }
2297
2298 /* Blocks thread until a packet has been received. */
2299
2300 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2301 {
2302   SilcPacketWait pw = waiter;
2303   SilcBool ret = FALSE;
2304
2305   silc_mutex_lock(pw->wait_lock);
2306
2307   /* Wait here until packet has arrived */
2308   while (silc_list_count(pw->packet_queue) == 0) {
2309     if (silc_unlikely(pw->stopped)) {
2310       silc_mutex_unlock(pw->wait_lock);
2311       return -1;
2312     }
2313     ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2314   }
2315
2316   /* Return packet */
2317   silc_list_start(pw->packet_queue);
2318   *return_packet = silc_list_get(pw->packet_queue);
2319   silc_list_del(pw->packet_queue, *return_packet);
2320
2321   silc_mutex_unlock(pw->wait_lock);
2322
2323   return ret == TRUE ? 1 : 0;
2324 }
2325
2326 /************************** Packet Stream Wrapper ***************************/
2327
2328 /* Packet stream wrapper receive callback */
2329 static SilcBool
2330 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2331                                 SilcPacketStream stream,
2332                                 SilcPacket packet,
2333                                 void *callback_context,
2334                                 void *stream_context);
2335
2336 const SilcStreamOps silc_packet_stream_ops;
2337
2338 /* Packet stream wrapper context */
2339 typedef struct {
2340   const SilcStreamOps *ops;
2341   SilcPacketStream stream;
2342   SilcMutex lock;
2343   void *waiter;                   /* Waiter context in blocking mode */
2344   SilcPacketWrapCoder coder;
2345   void *coder_context;
2346   SilcBuffer encbuf;
2347   SilcStreamNotifier callback;
2348   void *context;
2349   SilcList in_queue;
2350   SilcPacketType type;
2351   SilcPacketFlags flags;
2352   unsigned int closed        : 1;
2353   unsigned int blocking      : 1;
2354   unsigned int read_more     : 1;
2355 } *SilcPacketWrapperStream;
2356
2357 /* Packet wrapper callbacks */
2358 static SilcPacketCallbacks silc_packet_wrap_cbs =
2359 {
2360   silc_packet_wrap_packet_receive, NULL, NULL
2361 };
2362
2363 /* Packet stream wrapper receive callback, non-blocking mode */
2364
2365 static SilcBool
2366 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2367                                 SilcPacketStream stream,
2368                                 SilcPacket packet,
2369                                 void *callback_context,
2370                                 void *stream_context)
2371 {
2372   SilcPacketWrapperStream pws = callback_context;
2373
2374   if (pws->closed || !pws->callback)
2375     return FALSE;
2376
2377   silc_mutex_lock(pws->lock);
2378   silc_list_add(pws->in_queue, packet);
2379   silc_mutex_unlock(pws->lock);
2380
2381   /* Call notifier callback */
2382   pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2383
2384   return TRUE;
2385 }
2386
2387 /* Task callback to notify more data is available for reading */
2388
2389 SILC_TASK_CALLBACK(silc_packet_wrap_read_more)
2390 {
2391   SilcPacketWrapperStream pws = context;
2392
2393   if (pws->closed || !pws->callback)
2394     return;
2395
2396   /* Call notifier callback */
2397   pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2398 }
2399
2400 /* Read SILC packet */
2401
2402 int silc_packet_wrap_read(SilcStream stream, unsigned char *buf,
2403                           SilcUInt32 buf_len)
2404 {
2405   SilcPacketWrapperStream pws = stream;
2406   SilcPacket packet;
2407   SilcBool read_more = FALSE;
2408   int len;
2409
2410   if (pws->closed)
2411     return -2;
2412
2413   if (pws->blocking) {
2414     /* Block until packet is received */
2415     if ((silc_packet_wait(pws->waiter, 0, &packet)) < 0)
2416       return -2;
2417     if (pws->closed)
2418       return -2;
2419   } else {
2420     /* Non-blocking mode */
2421     silc_mutex_lock(pws->lock);
2422     if (!silc_list_count(pws->in_queue)) {
2423       silc_mutex_unlock(pws->lock);
2424       return -1;
2425     }
2426
2427     silc_list_start(pws->in_queue);
2428     packet = silc_list_get(pws->in_queue);
2429     silc_list_del(pws->in_queue, packet);
2430     silc_mutex_unlock(pws->lock);
2431   }
2432
2433   /* Call decoder if set */
2434   if (pws->coder && !pws->read_more)
2435     pws->coder(stream, SILC_STREAM_CAN_READ, &packet->buffer,
2436                pws->coder_context);
2437
2438   len = silc_buffer_len(&packet->buffer);
2439   if (len > buf_len) {
2440     len = buf_len;
2441     read_more = TRUE;
2442   }
2443
2444   /* Read data */
2445   memcpy(buf, packet->buffer.data, len);
2446
2447   if (read_more && !pws->blocking) {
2448     /* More data will be available (in blocking mode not supported). */
2449     silc_buffer_pull(&packet->buffer, len);
2450     silc_list_insert(pws->in_queue, NULL, packet); 
2451     silc_schedule_task_add_timeout(pws->stream->sc->schedule,
2452                                    silc_packet_wrap_read_more, pws, 0, 0);
2453     pws->read_more = TRUE;
2454     return len;
2455   }
2456
2457   pws->read_more = FALSE;
2458   silc_packet_free(packet);
2459   return len;
2460 }
2461
2462 /* Write SILC packet */
2463
2464 int silc_packet_wrap_write(SilcStream stream, const unsigned char *data,
2465                            SilcUInt32 data_len)
2466 {
2467   SilcPacketWrapperStream pws = stream;
2468   SilcBool ret = FALSE;
2469
2470   /* Call decoder if set */
2471   if (pws->coder) {
2472     silc_buffer_reset(pws->encbuf);
2473     ret = pws->coder(stream, SILC_STREAM_CAN_WRITE, pws->encbuf,
2474                      pws->coder_context);
2475   }
2476
2477   /* Send the SILC packet */
2478   if (ret) {
2479     if (!silc_packet_send_va(pws->stream, pws->type, pws->flags,
2480                              SILC_STR_DATA(silc_buffer_data(pws->encbuf),
2481                                            silc_buffer_len(pws->encbuf)),
2482                              SILC_STR_DATA(data, data_len),
2483                              SILC_STR_END))
2484       return -2;
2485   } else {
2486     if (!silc_packet_send(pws->stream, pws->type, pws->flags, data, data_len))
2487       return -2;
2488   }
2489
2490   return data_len;
2491 }
2492
2493 /* Close stream */
2494
2495 SilcBool silc_packet_wrap_close(SilcStream stream)
2496 {
2497   SilcPacketWrapperStream pws = stream;
2498
2499   if (pws->closed)
2500     return TRUE;
2501
2502   if (pws->blocking) {
2503     /* Close packet waiter */
2504     silc_packet_wait_uninit(pws->waiter, pws->stream);
2505   } else {
2506     /* Unlink */
2507     if (pws->callback)
2508       silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2509   }
2510   pws->closed = TRUE;
2511
2512   return TRUE;
2513 }
2514
2515 /* Destroy wrapper stream */
2516
2517 void silc_packet_wrap_destroy(SilcStream stream)
2518
2519 {
2520   SilcPacketWrapperStream pws = stream;
2521   SilcPacket packet;
2522
2523   SILC_LOG_DEBUG(("Destroying wrapped packet stream %p", pws));
2524
2525   silc_stream_close(stream);
2526   silc_list_start(pws->in_queue);
2527   while ((packet = silc_list_get(pws->in_queue)))
2528     silc_packet_free(packet);
2529   if (pws->lock)
2530     silc_mutex_free(pws->lock);
2531   if (pws->encbuf)
2532     silc_buffer_free(pws->encbuf);
2533   silc_packet_stream_unref(pws->stream);
2534
2535   silc_free(pws);
2536 }
2537
2538 /* Link stream to receive packets */
2539
2540 SilcBool silc_packet_wrap_notifier(SilcStream stream,
2541                                    SilcSchedule schedule,
2542                                    SilcStreamNotifier callback,
2543                                    void *context)
2544 {
2545   SilcPacketWrapperStream pws = stream;
2546
2547   if (pws->closed || pws->blocking)
2548     return FALSE;
2549
2550   /* Link to receive packets */
2551   if (callback)
2552     silc_packet_stream_link(pws->stream, &silc_packet_wrap_cbs, pws,
2553                             100000, pws->type, -1);
2554   else
2555     silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2556
2557   pws->callback = callback;
2558   pws->context = context;
2559
2560   return TRUE;
2561 }
2562
2563 /* Return schedule */
2564
2565 SilcSchedule silc_packet_wrap_get_schedule(SilcStream stream)
2566 {
2567   return NULL;
2568 }
2569
2570 /* Wraps packet stream into SilcStream. */
2571
2572 SilcStream silc_packet_stream_wrap(SilcPacketStream stream,
2573                                    SilcPacketType type,
2574                                    SilcPacketFlags flags,
2575                                    SilcBool blocking_mode,
2576                                    SilcPacketWrapCoder coder,
2577                                    void *context)
2578 {
2579   SilcPacketWrapperStream pws;
2580
2581   pws = silc_calloc(1, sizeof(*pws));
2582   if (!pws)
2583     return NULL;
2584
2585   SILC_LOG_DEBUG(("Wrapping packet stream %p to stream %p", stream, pws));
2586
2587   pws->ops = &silc_packet_stream_ops;
2588   pws->stream = stream;
2589   pws->type = type;
2590   pws->flags = flags;
2591   pws->blocking = blocking_mode;
2592   pws->coder = coder;
2593   pws->coder_context = context;
2594
2595   /* Allocate small amount for encoder buffer. */
2596   if (pws->coder)
2597     pws->encbuf = silc_buffer_alloc(8);
2598
2599   if (pws->blocking) {
2600     /* Blocking mode.  Use packet waiter to do the thing. */
2601     pws->waiter = silc_packet_wait_init(pws->stream, pws->type, -1);
2602     if (!pws->waiter) {
2603       silc_free(pws);
2604       return NULL;
2605     }
2606   } else {
2607     /* Non-blocking mode */
2608     if (!silc_mutex_alloc(&pws->lock)) {
2609       silc_free(pws);
2610       return NULL;
2611     }
2612
2613     silc_list_init(pws->in_queue, struct SilcPacketStruct, next);
2614   }
2615
2616   silc_packet_stream_ref(stream);
2617
2618   return (SilcStream)pws;
2619 }
2620
2621 const SilcStreamOps silc_packet_stream_ops =
2622 {
2623   silc_packet_wrap_read,
2624   silc_packet_wrap_write,
2625   silc_packet_wrap_close,
2626   silc_packet_wrap_destroy,
2627   silc_packet_wrap_notifier,
2628   silc_packet_wrap_get_schedule,
2629 };