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