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