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