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