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