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