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