1 /*
2 
3   silcpacket.h
4 
5   Author: Pekka Riikonen <priikone@silcnet.org>
6 
7   Copyright (C) 1997 - 2014 Pekka Riikonen
8 
9   The contents of this file are subject to one of the Licenses specified
10   in the COPYING file;  You may not use this file except in compliance
11   with the License.
12 
13   The software distributed under the License is distributed on an "AS IS"
14   basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
15   KIND, either expressed or implied.  See the COPYING file for more
16   information.
17 
18 */
19 
20 /****h* silccore/SILC Packet Engine Interface
21  *
22  * DESCRIPTION
23  *
24  * The SILC secure binary packet protocol interface, provides interface for
25  * sending and receiving SILC packets.  The interface provides a packet
26  * engine, that can be used to receive packets from packet streams, and
27  * routines for sending all kinds of SILC packets.
28  *
29  * The packet engine and packet stream are thread safe.  They can be safely
30  * used in multi threaded environment.
31  *
32  ***/
33 
34 #ifndef SILCPACKET_H
35 #define SILCPACKET_H
36 
37 /* Maximum packet length */
38 #define SILC_PACKET_MAX_LEN 0xffff
39 
40 /* Maximum length of ID */
41 #define SILC_PACKET_MAX_ID_LEN 28
42 
43 /****d* silccore/SilcPacketAPI/SilcPacketType
44  *
45  * NAME
46  *
47  *    typedef SilcUInt8 SilcPacketType;
48  *
49  * DESCRIPTION
50  *
51  *    SILC packet type definition and all the packet types.
52  *
53  * SOURCE
54  */
55 typedef SilcUInt8 SilcPacketType;
56 
57 /* SILC Packet types. */
58 #define SILC_PACKET_DISCONNECT		 1	 /* Disconnection */
59 #define SILC_PACKET_SUCCESS		 2	 /* Success */
60 #define SILC_PACKET_FAILURE		 3	 /* Failure */
61 #define SILC_PACKET_REJECT		 4	 /* Rejected */
62 #define SILC_PACKET_NOTIFY               5       /* Notify message */
63 #define SILC_PACKET_ERROR                6       /* Error message */
64 #define SILC_PACKET_CHANNEL_MESSAGE	 7	 /* Message for channel */
65 #define SILC_PACKET_CHANNEL_KEY          8       /* Key of the channel */
66 #define SILC_PACKET_PRIVATE_MESSAGE      9       /* Private message */
67 #define SILC_PACKET_PRIVATE_MESSAGE_KEY  10      /* Private message key*/
68 #define SILC_PACKET_COMMAND              11      /* Command */
69 #define SILC_PACKET_COMMAND_REPLY        12      /* Reply to a command */
70 #define SILC_PACKET_KEY_EXCHANGE         13      /* Start of KE */
71 #define SILC_PACKET_KEY_EXCHANGE_1       14      /* KE1 */
72 #define SILC_PACKET_KEY_EXCHANGE_2       15      /* KE2 */
73 #define SILC_PACKET_CONNECTION_AUTH_REQUEST 16   /* Request of auth meth */
74 #define SILC_PACKET_CONNECTION_AUTH      17      /* Connectinon auth */
75 #define SILC_PACKET_NEW_ID               18      /* Sending new ID */
76 #define SILC_PACKET_NEW_CLIENT           19      /* Client registering */
77 #define SILC_PACKET_NEW_SERVER           20      /* Server registering */
78 #define SILC_PACKET_NEW_CHANNEL          21      /* Channel registering */
79 #define SILC_PACKET_REKEY                22      /* Re-key start */
80 #define SILC_PACKET_REKEY_DONE           23      /* Re-key done */
81 #define SILC_PACKET_HEARTBEAT            24      /* Heartbeat */
82 #define SILC_PACKET_KEY_AGREEMENT        25      /* Key Agreement request */
83 #define SILC_PACKET_RESUME_ROUTER        26      /* Backup router resume */
84 #define SILC_PACKET_FTP                  27      /* File Transfer */
85 #define SILC_PACKET_RESUME_CLIENT        28      /* Client resume */
86 #define SILC_PACKET_ACK                  29      /* Acknowledgement */
87 
88 #define SILC_PACKET_PRIVATE              200     /* Private range start  */
89 #define SILC_PACKET_MAX                  255     /* RESERVED */
90 
91 #define SILC_PACKET_NONE		 0       /* RESERVED */
92 #define SILC_PACKET_ANY                  0
93 /***/
94 
95 /****d* silccore/SilcPacketAPI/SilcPacketFlags
96  *
97  * NAME
98  *
99  *    typedef SilcUInt8 SilcPacketFlags;
100  *
101  * DESCRIPTION
102  *
103  *    SILC packet flags type definition and all the packet flags.
104  *
105  * SOURCE
106  */
107 typedef SilcUInt8 SilcPacketFlags;
108 
109 /* All defined packet flags */
110 #define SILC_PACKET_FLAG_NONE             0x00    /* No flags */
111 #define SILC_PACKET_FLAG_PRIVMSG_KEY      0x01	  /* Private message key */
112 #define SILC_PACKET_FLAG_LIST             0x02	  /* Packet is a list */
113 #define SILC_PACKET_FLAG_BROADCAST        0x04	  /* Packet is a broadcast */
114 #define SILC_PACKET_FLAG_COMPRESSED       0x08    /* Payload is compressed */
115 #define SILC_PACKET_FLAG_ACK              0x10    /* Acknowledge packet */
116 
117 /* Impelemntation specific flags */
118 #define SILC_PACKET_FLAG_LONG_PAD         0x20    /* Use maximum padding */
119 /***/
120 
121 /****s* silccore/SilcPacketAPI/SilcPacketEngine
122  *
123  * NAME
124  *
125  *    typedef struct SilcPacketEngineStruct *SilcPacketEngine;
126  *
127  * DESCRIPTION
128  *
129  *    The packet engine context, allocated by silc_packet_engine_start.
130  *    The engine is destroyed with silc_packet_engine_stop.
131  *
132  ***/
133 typedef struct SilcPacketEngineStruct *SilcPacketEngine;
134 
135 /****s* silccore/SilcPacketAPI/SilcPacketStream
136  *
137  * NAME
138  *
139  *    typedef struct SilcPacketStreamStruct *SilcPacketStream;
140  *
141  * DESCRIPTION
142  *
143  *    The packet stream context, allocated by silc_packet_stream_create.
144  *    The stream is destroyed with silc_packet_stream_destroy.
145  *
146  ***/
147 typedef struct SilcPacketStreamStruct *SilcPacketStream;
148 
149 /****s* silccore/SilcPacketAPI/SilcPacket
150  *
151  * NAME
152  *
153  *    typedef struct SilcPacketStruct *SilcPacket;
154  *
155  * DESCRIPTION
156  *
157  *    The SilcPacket is returned by the packet engine in the SilcPacketReceive
158  *    callback.  The application can parse the data payload from the
159  *    SilcPacket.  Also packet type, flags, and sender and destination
160  *    IDs are available.  The application must free the packet with the
161  *    silc_packet_free function if it takes it in for processing.
162  *
163  *    The `buffer' field contains the parsed packet payload and the start
164  *    of the data area will point to the start of the packet payload.
165  *
166  *    The list pointer `next' can be used by the application to put the
167  *    packet context in a list during processing, if needed.
168  *
169  * SOURCE
170  */
171 typedef struct SilcPacketStruct {
172   struct SilcPacketStruct *next;     /* List pointer, application may set */
173   SilcPacketStream stream;	     /* Packet stream this packet is from */
174   SilcBufferStruct buffer;	     /* Packet data payload */
175   unsigned char *src_id;	     /* Source ID */
176   unsigned char *dst_id;	     /* Destination ID */
177   unsigned int src_id_len  : 6;	     /* Source ID length */
178   unsigned int src_id_type : 2;	     /* Source ID type */
179   unsigned int dst_id_len  : 6;	     /* Destination ID length */
180   unsigned int dst_id_type : 2;	     /* Destination ID type */
181   SilcPacketType type;		     /* Packet type */
182   SilcPacketFlags flags;	     /* Packet flags */
183 } *SilcPacket;
184 /***/
185 
186 /****d* silcutil/SilcPacketAPI/SilcPacketError
187  *
188  * NAME
189  *
190  *    typedef enum { ... } SilcPacketError
191  *
192  * DESCRIPTION
193  *
194  *    Packet errors.  This is returned in the error callback.  If application
195  *    needs the actual lower level stream error, it needs to retrieve it
196  *    from the actual stream.  It can retrieve the underlaying stream from
197  *    the packet stream by calling silc_packet_stream_get_stream function.
198  *
199  *    You may retrieve string version of the SilcPacketError by calling
200  *    silc_packet_error_string.
201  *
202  * SOURCE
203  */
204 typedef enum {
205   SILC_PACKET_ERR_READ,			 /* Error while reading */
206   SILC_PACKET_ERR_WRITE,       		 /* Error while writing */
207   SILC_PACKET_ERR_MAC_FAILED,     	 /* Packet MAC check failed */
208   SILC_PACKET_ERR_DECRYPTION_FAILED,   	 /* Packet decryption failed */
209   SILC_PACKET_ERR_UNKNOWN_SID,		 /* Unknown SID (with IV included) */
210   SILC_PACKET_ERR_MALFORMED,		 /* Packet is malformed */
211   SILC_PACKET_ERR_NO_MEMORY,	 	 /* System out of memory */
212 } SilcPacketError;
213 /***/
214 
215 /****f* silccore/SilcPacketAPI/SilcPacketReceiveCb
216  *
217  * SYNOPSIS
218  *
219  *    typedef SilcBool (*SilcPacketReceiveCb)(SilcPacketEngine engine,
220  *                                            SilcPacketStream stream,
221  *                                            SilcPacket packet,
222  *                                            void *callback_context,
223  *                                            void *stream_context);
224  *
225  * DESCRIPTION
226  *
227  *    The packet receive callback is called by the packet engine when a new
228  *    SILC Packet has arrived.  The application must free the returned
229  *    SilcPacket with silc_packet_free if it takes the packet in for
230  *    processing.  This callback is set in the SilcPacketCallbacks structure.
231  *    The `callback_context' is the context set as argument in the
232  *    silc_packet_engine_start function.  The `stream_context' is stream
233  *    specific context that was set by calling silc_packet_set_context.
234  *
235  *    If the application takes the received packet `packet' into processing
236  *    TRUE must be returned.  If FALSE is returned the packet engine will
237  *    pass the packet to other packet processor, if one has been linked
238  *    to the stream with silc_packet_stream_link function.  If no extra
239  *    processor is linked the packet is dropped.
240  *
241  * EXAMPLE
242  *
243  *    SilcBool
244  *    silc_foo_packet_receive_cb(SilcPacketEngine engine,
245  *                               SilcPacketStream stream, SilcPacket packet,
246  *                               void *callback_context, void *stream_context)
247  *    {
248  *      Application ctx = callback_context;
249  *
250  *      // If we're not up yet, let's not process the packet
251  *      if (ctx->initialized == FALSE)
252  *        return FALSE;
253  *
254  *      // Process the incoming packet...
255  *      ...
256  *
257  *      // It's our packet now, no one else will get it
258  *      return TRUE;
259  *    }
260  *
261  ***/
262 typedef SilcBool (*SilcPacketReceiveCb)(SilcPacketEngine engine,
263 					SilcPacketStream stream,
264 					SilcPacket packet,
265 					void *callback_context,
266 					void *stream_context);
267 
268 /****f* silccore/SilcPacketAPI/SilcPacketEosCb
269  *
270  * SYNOPSIS
271  *
272  *    typedef void (*SilcPacketEosCb)(SilcPacketEngine engine,
273  *                                    SilcPacketStream stream,
274  *                                    void *callback_context,
275  *                                    void *stream_context);
276  *
277  * DESCRIPTION
278  *
279  *    The End Of Stream (EOS) callback, that is called by the packet engine
280  *    when the underlaying stream has ended.  No more data can be sent to
281  *    the stream or read from it.  The `stream' must be destroyed by
282  *    calling the silc_packet_stream_destroy.  This callback is set in the
283  *    SilcPacketCallbacks structure.
284  *
285  ***/
286 typedef void (*SilcPacketEosCb)(SilcPacketEngine engine,
287 				SilcPacketStream stream,
288 				void *callback_context,
289 				void *stream_context);
290 
291 /****f* silccore/SilcPacketAPI/SilcPacketErrorCb
292  *
293  * SYNOPSIS
294  *
295  *    typedef void (*SilcPacketErrorCb)(SilcPacketEngine engine,
296  *                                      SilcPacketStream stream,
297  *                                      SilcPacketError error,
298  *                                      void *callback_context,
299  *                                      void *stream_context);
300  *
301  * DESCRIPTION
302  *
303  *    The error callback that is called by the packet engine if an error
304  *    occurs.  The `error' will indicate the error.  This callback is set
305  *    in the SilcPacketCallbacks structure.
306  *
307  ***/
308 typedef void (*SilcPacketErrorCb)(SilcPacketEngine engine,
309 				  SilcPacketStream stream,
310 				  SilcPacketError error,
311 				  void *callback_context,
312 				  void *stream_context);
313 
314 /****s* silccore/SilcPacketAPI/SilcPacketCallbacks
315  *
316  * NAME
317  *
318  *    typedef struct { ... } *SilcPacketCallbacks;
319  *
320  * DESCRIPTION
321  *
322  *    This structure is sent as argument to the silc_packet_engine_start
323  *    function to set the callback functions for the packet engine.  The
324  *    packet engine will call the callbacks when necessary.  Application
325  *    must always be provided for the packet engine.
326  *
327  * SOURCE
328  */
329 typedef struct {
330   SilcPacketReceiveCb packet_receive;	 /* Called when packet is received */
331   SilcPacketEosCb eos;		         /* Called on end of stream */
332   SilcPacketErrorCb error;	         /* Called on an error */
333 } SilcPacketCallbacks;
334 /***/
335 
336 /* Prototypes */
337 
338 /****f* silccore/SilcPacketAPI/silc_packet_engine_start
339  *
340  * SYNOPSIS
341  *
342  *    SilcPacketEngine
343  *    silc_packet_engine_start(SilcRng rng, SilcBool router,
344  *                             SilcPacketCallbacks *callbacks,
345  *                             void *callback_context);
346  *
347  * DESCRIPTION
348  *
349  *    Create new packet engine for processing incoming and outgoing packets.
350  *    If `router' is  TRUE then the application is considered to be router
351  *    server, and certain packets are handled differently.  Client and normal
352  *    server must set it to FALSE.  The `callbacks' is a SilcPacketCallbacks
353  *    structure provided by the caller which includes the callbacks that is
354  *    called when for example packet is received, or end of stream is called.
355  *
356  * NOTES
357  *
358  *    The packet engine is thread safe.  You can use one packet engine in
359  *    multi threaded application.
360  *
361  ***/
362 SilcPacketEngine
363 silc_packet_engine_start(SilcRng rng, SilcBool router,
364 			 const SilcPacketCallbacks *callbacks,
365 			 void *callback_context);
366 
367 /****f* silccore/SilcPacketAPI/silc_packet_engine_stop
368  *
369  * SYNOPSIS
370  *
371  *    void silc_packet_engine_stop(SilcPacketEngine engine);
372  *
373  * DESCRIPTION
374  *
375  *    Stop the packet engine.  No new packets can be sent or received after
376  *    calling this, and the `engine' will become invalid.
377  *
378  ***/
379 void silc_packet_engine_stop(SilcPacketEngine engine);
380 
381 /****f* silccore/SilcPacketAPI/silc_packet_error_string
382  *
383  * SYNOPSIS
384  *
385  *    const char *silc_packet_error_string(SilcPacketError error);
386  *
387  * DESCRIPTION
388  *
389  *    Return the packet error as string.
390  *
391  ***/
392 const char *silc_packet_error_string(SilcPacketError error);
393 
394 /****f* silccore/SilcPacketAPI/silc_packet_engine_get_streams
395  *
396  * SYNOPSIS
397  *
398  *    SilcDList silc_packet_engine_get_streams(SilcPacketEngine engine);
399  *
400  * DESCRIPTION
401  *
402  *    Returns list of packet streams added to the packet engine.  The caller
403  *    must free the list with silc_packet_engine_free_streams_list.
404  *
405  * NOTES
406  *
407  *    This function may also return disconnected and destroyed streams.  The
408  *    caller should use silc_packet_stream_is_valid to check if the stream
409  *    is valid.
410  *
411  ***/
412 SilcDList silc_packet_engine_get_streams(SilcPacketEngine engine);
413 
414 /****f* silccore/SilcPacketAPI/silc_packet_engine_free_streams_list
415  *
416  * SYNOPSIS
417  *
418  *    void silc_packet_engine_free_streams_list(SilcDList streams);
419  *
420  * DESCRIPTION
421  *
422  *    Free's the streams list returned by silc_packet_engine_get_streams.
423  *
424  ***/
425 void silc_packet_engine_free_streams_list(SilcDList streams);
426 
427 /****f* silccore/SilcPacketAPI/silc_packet_stream_create
428  *
429  * SYNOPSIS
430  *
431  *    SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
432  *                                               SilcSchedule schedule,
433  *                                               SilcStream stream);
434  *
435  * DESCRIPTION
436  *
437  *    Create new packet stream and use the `stream' as underlaying stream.
438  *    Usually the `stream' would be a socket stream, but it can be any
439  *    stream.  After this function returns, packets can immediately be
440  *    sent to and received from the stream.
441  *
442  *    The `stream' will be owned by the packet stream and will be closed
443  *    and destroyed when the packet stream is destroyed.  If the packet
444  *    stream creation fails the `stream' is left intact.
445  *
446  * NOTES
447  *
448  *    SilcPacketStream cannot be used with silc_stream_* routines (such as
449  *    silc_stream_read and silc_stream_write) because of its special nature.
450  *    Use the silc_packet_send and the silc_packet_send_ext to send packets.
451  *    To read packets you will receive the packet receive callback from
452  *    packet engine.  Destroy the stream with silc_packet_stream_destroy.
453  *
454  *    The SilcPacketStream is thread safe.  Same context can be safely used
455  *    in multi threaded environment.
456  *
457  ***/
458 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
459 					   SilcSchedule schedule,
460 					   SilcStream stream);
461 
462 /****f* silccore/SilcPacketAPI/silc_packet_stream_add_remote
463  *
464  * SYNOPSIS
465  *
466  *    SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
467  *                                                   const char *remote_ip,
468  *                                                   SilcUInt16 remote_port,
469  *                                                   SilcPacket packet);
470  *
471  * DESCRIPTION
472  *
473  *    This function is used to add remote receivers in packet stream `stream'
474  *    that has UDP/IP socket stream as the underlaying stream.  This function
475  *    cannot be used with other type of streams.  This returns new packet
476  *    stream context that can be used to send to and receive packets from
477  *    the specified remote IP and remote port, or NULL on error.  The `stream'
478  *    is the actual stream that is used to send and receive the data.
479  *
480  *    When the parent `stream' receives packets from remote IP address
481  *    and port that does not have its own remote packet stream, it returns
482  *    the packet to the packet callback set for `stream'.  The sender's
483  *    IP address and port can then be retrieved by using the
484  *    silc_packet_get_sender function and to create new packet stream by
485  *    calling this function.  After that, all packets from that IP address
486  *    and port will be received by the new packet stream.
487  *
488  *    If the `packet' is non-NULL it will be injected into the new packet
489  *    stream as soon as the scheduler associated with `stream' schedules
490  *    new tasks.  It can be used to inject an incoming packet to the stream.
491  *
492  *    This interface is for connectionless UDP streams.  If it is possible
493  *    to create connected stream it should be done for performance reasons.
494  *
495  * EXAMPLE
496  *
497  *    // Create parent packet stream, it can receive packets from anywhere
498  *    listener = silc_net_udp_connect("0.0.0.0", 500, NULL, 0, schedule);
499  *    parent = silc_packet_stream_create(engine, schedule, listener);
500  *
501  *    ...
502  *    // Received a packet to the parent stream, get the sender information.
503  *    silc_packet_get_sender(packet, &ip, &port);
504  *
505  *    // Create new packet stream for this remote location.
506  *    remote = silc_packet_stream_add_remote(parent, ip, port, packet);
507  *
508  ***/
509 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
510 					       const char *remote_ip,
511 					       SilcUInt16 remote_port,
512 					       SilcPacket packet);
513 
514 /****f* silccore/SilcPacketAPI/silc_packet_stream_inject
515  *
516  * SYNOPSIS
517  *
518  * SilcBool silc_packet_stream_inject(SilcPacketStream stream,
519  *                                    SilcPacket packet);
520  *
521  * DESCRIPTION
522  *
523  *    This function can be used to inject the `packet' to the given
524  *    packet `stream'.  The packet will appear in the packet stream's
525  *    packet handler(s).  If this returns FALSE the packet was not
526  *    injected.
527  *
528  ***/
529 SilcBool silc_packet_stream_inject(SilcPacketStream stream,
530 				   SilcPacket packet);
531 
532 /****f* silccore/SilcPacketAPI/silc_packet_stream_destroy
533  *
534  * SYNOPSIS
535  *
536  *    void silc_packet_stream_destroy(SilcPacketStream stream);
537  *
538  * DESCRIPTION
539  *
540  *    Destroy packet stream and the underlaying stream.  This will also
541  *    close and destroy the underlaying stream.
542  *
543  ***/
544 void silc_packet_stream_destroy(SilcPacketStream stream);
545 
546 /****f* silccore/SilcPacketAPI/silc_packet_stream_is_valid
547  *
548  * SYNOPSIS
549  *
550  *    SilcBool silc_packet_stream_is_valid(SilcPacketStream stream);
551  *
552  * DESCRIPTION
553  *
554  *    Returns TRUE if the packet stream indicated by `stream' is valid and
555  *    has not been disconnected or destroyed.
556  *
557  ***/
558 SilcBool silc_packet_stream_is_valid(SilcPacketStream stream);
559 
560 /****f* silccore/SilcPacketAPI/silc_packet_stream_set_router
561  *
562  * SYNOPSIS
563  *
564  *    void silc_packet_stream_set_router(SilcPacketStream stream);
565  *
566  * DESCRIPTION
567  *
568  *    When called sets the stream indicates by `stream' as SILC router
569  *    connection stream.  This causes that certain packets are handled
570  *    differently.  This must be called for router connection streams and
571  *    must not be called for any other stream.
572  *
573  ***/
574 void silc_packet_stream_set_router(SilcPacketStream stream);
575 
576 /****f* silccore/SilcPacketAPI/silc_packet_stream_set_iv_included
577  *
578  * SYNOPSIS
579  *
580  *    void silc_packet_stream_set_iv_included(SilcPacketStream stream);
581  *
582  * DESCRIPTION
583  *
584  *    Sets an IV Included property for the stream indicated by `stream'.
585  *    This means that the IV used in the encryption will be included in
586  *    the resulted ciphertext.  This makes it possible to send and receive
587  *    packets on unreliable network transport protocol, such as UDP/IP.
588  *    This must be called if the underlaying stream in the `stream' is UDP
589  *    stream.
590  *
591  *    When this is set to the stream the silc_packet_set_sid must be called
592  *    to set new Security ID.  The Security ID will be included with the IV
593  *    in the ciphertext.
594  *
595  ***/
596 void silc_packet_stream_set_iv_included(SilcPacketStream stream);
597 
598 /****f* silccore/SilcPacketAPI/silc_packet_stream_set_stream
599  *
600  * SYNOPSIS
601  *
602  *    void silc_packet_stream_set_stream(SilcPacketStream packet_stream,
603  *                                       SilcStream stream);
604  *
605  * DESCRIPTION
606  *
607  *    This function may be used to change the underlaying stream in the
608  *    packet stream indicated by `packet_stream'.  Note that the old
609  *    stream will not be used after calling this function.  The caller is
610  *    responsible destroying the old stream.  The `stream' will use
611  *    the same scheduler as the `packet_stream'.
612  *
613  ***/
614 void silc_packet_stream_set_stream(SilcPacketStream packet_stream,
615 				   SilcStream stream);
616 
617 /****f* silccore/SilcPacketAPI/silc_packet_stream_get_stream
618  *
619  * SYNOPSIS
620  *
621  *    SilcStream silc_packet_stream_get_stream(SilcPacketStream stream);
622  *
623  * DESCRIPTION
624  *
625  *    Returns the actual stream that is associated with the packet stream
626  *    `stream'.  The caller must not free the returned stream.  The returned
627  *    stream is the same pointer that was set for silc_packet_stream_create.
628  *    This function could be used for example when an error callback is
629  *    called by the packet engine to retrieve the actual lower level error
630  *    from the stream.
631  *
632  ***/
633 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream);
634 
635 /****f* silccore/SilcPacketAPI/silc_packet_stream_link
636  *
637  * SYNOPSIS
638  *
639  *    SilcBool silc_packet_stream_link(SilcPacketStream stream,
640  *                                     SilcPacketCallbacks *callbacks,
641  *                                     void *callback_context,
642  *                                     int priority, ...);
643  *
644  * DESCRIPTION
645  *
646  *    Links the packet processing callbacks indicated by `callbacks' into
647  *    the packet stream indicated by `stream' with priority `priority' for
648  *    the packet types given in the variable argument list.  This function
649  *    can be used to link to the packet stream for specific packet types
650  *    and receive them in the specified callbacks.  This way, a third party,
651  *    for example some library may attach itself into the packet stream
652  *    and receive and process certain packets.  The variable argument
653  *    list is ended with -1.  To link to receive all packets use
654  *    SILC_PACKET_ANY.
655  *
656  *    The default packet processing callbacks given as argument to the
657  *    silc_packet_engine_start has the priority 0.  Any priority higher
658  *    than 0 will then take precedence over the default callbacks.  Any
659  *    priority lower than 0 (negative value) will be processed after the
660  *    default callbacks.
661  *
662  *    Note that setting only the 'packet_receive' callback in the `callbacks'
663  *    is required.
664  *
665  * EXAMPLE
666  *
667  *    // Link to this packet stream, with high priority, for
668  *    // SILC_PACKET_CONNECTION_AUTH and SILC_PACKET_CONNECTION_AUTH_REQUEST
669  *    // packets. We don't care about other packets.
670  *    silc_packet_stream_link(stream, our_callbacks, our_context,
671  *                            1000000, SILC_PACKET_CONNECTION_AUTH,
672  *                            SILC_PACKET_CONNECTION_AUTH_REQUEST, -1);
673  *
674  ***/
675 SilcBool silc_packet_stream_link(SilcPacketStream stream,
676 				 const SilcPacketCallbacks *callbacks,
677 				 void *callback_context,
678 				 int priority, ...);
679 
680 /****f* silccore/SilcPacketAPI/silc_packet_stream_unlink
681  *
682  * SYNOPSIS
683  *
684  *    void silc_packet_stream_unlink(SilcPacketStream stream,
685  *                                   SilcPacketCallbacks *callbacks,
686  *                                   void *callback_context);
687  *
688  * DESCRIPTION
689  *
690  *    Unlinks the `callbacks' with `callback_context' from the packet stream
691  *    indicated by `stream'.  This function must be called for the callbacks
692  *    that was linked to `stream' when they are not needed anymore.
693  *
694  ***/
695 void silc_packet_stream_unlink(SilcPacketStream stream,
696 			       const SilcPacketCallbacks *callbacks,
697 			       void *callback_context);
698 
699 /****f* silccore/SilcPacketAPI/SilcPacketWrapCoder
700  *
701  * SYNOPSIS
702  *
703  *    typedef SilcBool (*SilcPacketWrapCoder)(SilcStream stream,
704  *                                            SilcStreamStatus status,
705  *                                            SilcBuffer buffer,
706  *                                            void *context);
707  *
708  * DESCRIPTION
709  *
710  *    The encoder/decoder callback for silc_packet_stream_wrap.
711  *
712  *    If the `status' is SILC_STREAM_CAN_WRITE then additional data can
713  *    be added to `buffer' which contains the data that is being written
714  *    to the stream.  There is at least 16 bytes of free space in head
715  *    space of the buffer in case new headers need to be added.
716  *    The silc_buffer_enlarge should be called to verify that there is
717  *    enough room before adding data to it.  The `buffer' must not be freed.
718  *    If the return value is FALSE the encoding failed and the packet is
719  *    not sent at all and the stream will receive error.  Return TRUE if
720  *    the encoding succeeded.
721  *
722  *    If the `status' is SILC_STREAM_CAN_READ then data from the `buffer'
723  *    may be read before it is passed to reader when silc_stream_read is
724  *    called.  The `buffer' may be advanced also to hide data in it.  If
725  *    return value is FALSE the decoding failed (or the packet is ignored)
726  *    and the packet will not be processed by the wrapped packet stream.
727  *    If there are other packet streams wanting the same packet, they will
728  *    get it, and if not the packet will drop.  Return TRUE if decoding
729  *    succeeded.
730  *
731  ***/
732 typedef SilcBool (*SilcPacketWrapCoder)(SilcStream stream,
733 					SilcStreamStatus status,
734 					SilcBuffer buffer,
735 					void *context);
736 
737 /****f* silccore/SilcPacketAPI/silc_packet_stream_wrap
738  *
739  * SYNOPSIS
740  *
741  *    SilcStream silc_packet_stream_wrap(SilcPacketStream stream,
742  *                                       SilcPacketType type,
743  *                                       SilcPacketFlags flags,
744  *                                       SilcBool blocking_mode,
745  *                                       SilcIdType src_id_type, void *src_id,
746  *                                       SilcIdType dst_id_type, void *dst_id,
747  *                                       SilcPacketWrapCoder coder,
748  *                                       void *context);
749  *
750  * DESCRIPTION
751  *
752  *    Wraps the packet stream indicated by `stream' into a SilcStream for
753  *    the packet type indicated by `type' with packet flags indicated by
754  *    `flags'.  The returned SilcStream can be used to read and write the
755  *    specified SILC packets with the specified packet flags, by calling
756  *    silc_stream_read and silc_stream_write, respectively.  The returned
757  *    stream can be destroyed by calling silc_stream_destroy.  It does not
758  *    destroy the wrapped packet stream.
759  *
760  *    If the `blocking_mode' mode is TRUE then the silc_stream_read and
761  *    silc_stream_write may block the calling process or thread until SILC
762  *    packet is read or written.  If it is FALSE the stream is in non-blocking
763  *    mode and the calls never block.  The returned stream is thread-safe and
764  *    packets may be read and written in multi-threaded environment.
765  *
766  *    In non-blocking mode the silc_stream_set_notifier must be called before
767  *    the returned stream can be used to read packets.  The stream status
768  *    SILC_STREAM_CAN_READ will be returned to the notifier callback to
769  *    indicate that a packet is ready for reading.  Calling silc_stream_read
770  *    once returns one complete SILC packet data payload (which is of type of
771  *    `type').
772  *
773  *    If src_id and/or dst_id are set they will be used as the ids in the
774  *    sent SILC packets.  If the dst_id is set then the stream will receive
775  *    packets only originating from that id.
776  *
777  *    The `coder' is optional encoder/decoder callback which the packet engine
778  *    will call if it is non-NULL.  It can be used to encode additional data
779  *    into each packet when silc_stream_write is called or decode data before
780  *    it is passed to reader when silc_stream_read is called.  The `context'
781  *    is passed to `coder'.
782  *
783  *    The returned SilcStream can be used as any normal stream and all
784  *    SilcStream API functions may be used with the stream.  This returns
785  *    NULL on error.
786  *
787  ***/
788 SilcStream silc_packet_stream_wrap(SilcPacketStream stream,
789 				   SilcPacketType type,
790 				   SilcPacketFlags flags,
791 				   SilcBool blocking_mode,
792 				   SilcIdType src_id_type, void *src_id,
793 				   SilcIdType dst_id_type, void *dst_id,
794 				   SilcPacketWrapCoder coder,
795 				   void *context);
796 
797 /****f* silccore/SilcPacketAPI/silc_packet_stream_is_udp
798  *
799  * SYNOPSIS
800  *
801  *    SilcBool silc_packet_stream_is_udp(SilcPacketStream stream);
802  *
803  * DESCRIPTION
804  *
805  *    Returns TRUE if the packet stream indicated by `stream' is using
806  *    UDP transport.
807  *
808  ***/
809 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream);
810 
811 /****f* silccore/SilcPacketAPI/silc_packet_get_sender
812  *
813  * SYNOPSIS
814  *
815  *    SilcBool silc_packet_get_sender(SilcPacket packet,
816  *                                    const char **sender_ip,
817  *                                    SilcUInt16 *sender_port);
818  *
819  * DESCRIPTION
820  *
821  *    Returns the packet sender's IP address and port from UDP packet
822  *    indicated by `packet'.  This can be called only from the packet
823  *    callback to retrieve the information of the packet's sender.  Returns
824  *    FALSE if the information is not available.
825  *
826  ***/
827 SilcBool silc_packet_get_sender(SilcPacket packet,
828 				const char **sender_ip,
829 				SilcUInt16 *sender_port);
830 
831 /****f* silccore/SilcPacketAPI/silc_packet_stream_ref
832  *
833  * SYNOPSIS
834  *
835  *    void silc_packet_stream_ref(SilcPacketStream stream);
836  *
837  * DESCRIPTION
838  *
839  *    Increase reference counter for the stream indicated by `stream'.  This
840  *    can be used to take a reference for the stream.  To unreference the
841  *    stream call silc_packet_stream_unref function.
842  *
843  ***/
844 void silc_packet_stream_ref(SilcPacketStream stream);
845 
846 /****f* silccore/SilcPacketAPI/silc_packet_stream_unref
847  *
848  * SYNOPSIS
849  *
850  *    void silc_packet_stream_unref(SilcPacketStream stream);
851  *
852  * DESCRIPTION
853  *
854  *    Decrease reference counter for the stream indicated by `stream'.  If
855  *    the counter hits zero the stream will be destroyed automatically.
856  *
857  ***/
858 void silc_packet_stream_unref(SilcPacketStream stream);
859 
860 /****f* silccore/SilcPacketAPI/silc_packet_get_engine
861  *
862  * SYNOPSIS
863  *
864  *    SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream);
865  *
866  * DESCRIPTION
867  *
868  *    Returns the packet engine from the `stream'.
869  *
870  ***/
871 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream);
872 
873 /****f* silccore/SilcPacketAPI/silc_packet_set_context
874  *
875  * SYNOPSIS
876  *
877  *    void silc_packet_set_context(SilcPacketStream stream,
878  *                                 void *stream_context);
879  *
880  * DESCRIPTION
881  *
882  *    Sets a stream specific context to the stream.  The context will
883  *    be delivered to all callback functions, and it can be retrieved by
884  *    calling silc_packet_get_context function as well.  Note that this is
885  *    separate packet stream specific context, and not the same as
886  *    `callback_context' in silc_packet_engine_start.  Both will be delivered
887  *    to the callbacks, and this context as the `stream_context' argument.
888  *
889  ***/
890 void silc_packet_set_context(SilcPacketStream stream, void *stream_context);
891 
892 /****f* silccore/SilcPacketAPI/silc_packet_get_context
893  *
894  * SYNOPSIS
895  *
896  *    void *silc_packet_get_context(SilcPacketStream stream);
897  *
898  * DESCRIPTION
899  *
900  *    Returns the current set application context, or NULL if none is set.
901  *
902  ***/
903 void *silc_packet_get_context(SilcPacketStream stream);
904 
905 /****f* silccore/SilcPacketAPI/silc_packet_set_keys
906  *
907  * SYNOPSIS
908  *
909  *    void silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
910  *                              SilcCipher receive_key, SilcHmac send_hmac,
911  *                              SilcHmac receive_hmac, SilcBool rekey);
912  *
913  * DESCRIPTION
914  *
915  *    Set ciphers and HMACs to be used to encrypt sent packets, and decrypt
916  *    received packets.  This can be called multiple times to change the
917  *    ciphers and HMACs.
918  *
919  *    If the `rekey' is TRUE this function will send SILC_PACKET_REKEY_DONE
920  *    to the `stream' and will set the new keys.  If it is FALSE the keys
921  *    are changed but the packet is not changed.
922  *
923  *    When changing keys the old cipher and HMACs will be freed.  If the keys
924  *    are not set at all, packets will not be encrypted or decrypted.
925  *
926  ***/
927 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
928                               SilcCipher receive_key, SilcHmac send_hmac,
929                               SilcHmac receive_hmac, SilcBool rekey);
930 
931 /****f* silccore/SilcPacketAPI/silc_packet_get_keys
932  *
933  * SYNOPSIS
934  *
935  *    SilcBool silc_packet_get_keys(SilcPacketStream stream,
936  *                                  SilcCipher *send_key,
937  *                                  SilcCipher *receive_key,
938  *                                  SilcHmac *send_hmac,
939  *                                  SilcHmac *receive_hmac);
940  *
941  * DESCRIPTION
942  *
943  *    Returns the pointers of current ciphers and HMACs from the `stream'.
944  *    Returns FALSE if keys are not set.
945  *
946  ***/
947 SilcBool silc_packet_get_keys(SilcPacketStream stream,
948 			      SilcCipher *send_key, SilcCipher *receive_key,
949 			      SilcHmac *send_hmac, SilcHmac *receive_hmac);
950 
951 /****f* silccore/SilcPacketAPI/silc_packet_set_ids
952  *
953  * SYNOPSIS
954  *
955  *    SilcBool silc_packet_set_ids(SilcPacketStream stream,
956  *                                 SilcIdType src_id_type, const void *src_id
957  *                                 SilcIdType dst_id_type, const void *dst_id);
958  *
959  * DESCRIPTION
960  *
961  *    Set the source ID and destination ID to be used when sending packets to
962  *    this packet stream.  The IDs to be used for a packet stream can be
963  *    overridden when sending packets.  However, if the IDs do not ever change
964  *    for the packet stream it is recommended they are set using this function.
965  *    In this case they can be omitted when sending packets to the stream.
966  *    It is also possible to set only source or destination ID.
967  *
968  ***/
969 SilcBool silc_packet_set_ids(SilcPacketStream stream,
970 			     SilcIdType src_id_type, const void *src_id,
971 			     SilcIdType dst_id_type, const void *dst_id);
972 
973 /****f* silccore/SilcPacketAPI/silc_packet_get_ids
974  *
975  * SYNOPSIS
976  *
977  *    SilcBool silc_packet_get_ids(SilcPacketStream stream,
978  *                                 SilcBool *src_id_set, SilcID *src_id,
979  *                                 SilcBool *dst_id_set, SilcID *dst_id);
980  *
981  * DESCRIPTION
982  *
983  *    Returns source and destination IDs from the packet stream.  The
984  *    `src_id_set' is set to TRUE if the source ID was returned.  The
985  *    `dst_id_set' is set to TRUE if the destination ID was returned.
986  *
987  ***/
988 SilcBool silc_packet_get_ids(SilcPacketStream stream,
989 			     SilcBool *src_id_set, SilcID *src_id,
990 			     SilcBool *dst_id_set, SilcID *dst_id);
991 
992 /****f* silccore/SilcPacketAPI/silc_packet_set_sid
993  *
994  * SYNOPSIS
995  *
996  *    SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid);
997  *
998  * DESCRIPTION
999  *
1000  *    Sets new Security ID to the packet stream indicated by `stream'.  This
1001  *    is called only if the IV Included property was set to the stream
1002  *    by calling silc_packet_stream_set_iv_included.  This function sets
1003  *    new Security ID to the stream which is then included in the ciphertext
1004  *    of a packet.  The `sid' must be 0 when it is set for the very first
1005  *    time and must be increased by one after each rekey.  This function must
1006  *    be called every time new keys are added to the stream after a rekey.
1007  *
1008  *    If this function is called when the IV Included property has not been
1009  *    set to the stream the `sid' will be ignored.  Returns FALSE if the
1010  *    IV Included has not been set, TRUE otherwise.
1011  *
1012  ***/
1013 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid);
1014 
1015 /****f* silccore/SilcPacketAPI/silc_packet_send
1016  *
1017  * SYNOPSIS
1018  *
1019  *    SilcBool silc_packet_send(SilcPacketStream stream,
1020  *                              SilcPacketType type, SilcPacketFlags flags,
1021  *                              const unsigned char *data,
1022  *                              SilcUInt32 data_len);
1023  *
1024  * DESCRIPTION
1025  *
1026  *    Send `data' of length of `data_len' to the packet stream indicated by
1027  *    `stream'.  If ciphers and HMACs were set using silc_packet_set_keys
1028  *    the packet will be encrypted and MAC will be computed for it.  If
1029  *    silc_packet_set_ids was used to set source and destination ID for the
1030  *    packet stream those IDs are used in the packet.  If IDs have not been
1031  *    set and they need to be provided then silc_packet_send_ext function
1032  *    should be used.  Otherwise, the packet will not have IDs set at all.
1033  *    Returns FALSE if packet could not be sent.
1034  *
1035  ***/
1036 SilcBool silc_packet_send(SilcPacketStream stream,
1037 			  SilcPacketType type, SilcPacketFlags flags,
1038 			  const unsigned char *data, SilcUInt32 data_len);
1039 
1040 /****f* silccore/SilcPacketAPI/silc_packet_send_ext
1041  *
1042  * SYNOPSIS
1043  *
1044  *    SilcBool
1045  *    silc_packet_send_ext(SilcPacketStream stream,
1046  *                         SilcPacketType type, SilcPacketFlags flags,
1047  *                         SilcIdType src_id_type, void *srd_id,
1048  *                         SilcIdType dst_id_type, void *dst_id,
1049  *                         const unsigned char *data, SilcUInt32 data_len,
1050  *                         SilcCipher cipher, SilcHmac hmac);
1051  *
1052  * DESCRIPTION
1053  *
1054  *    Same as silc_packet_send but with this function different sending
1055  *    parameters can be sent as argument.  This function can be used to
1056  *    set specific IDs, cipher and HMAC to be used in packet sending,
1057  *    instead of the ones saved in the `stream'.  If any of the extra
1058  *    pointers are NULL, default values set to the stream will apply.
1059  *
1060  ***/
1061 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1062 			      SilcPacketType type, SilcPacketFlags flags,
1063 			      SilcIdType src_id_type, void *src_id,
1064 			      SilcIdType dst_id_type, void *dst_id,
1065 			      const unsigned char *data, SilcUInt32 data_len,
1066 			      SilcCipher cipher, SilcHmac hmac);
1067 
1068 /****f* silccore/SilcPacketAPI/silc_packet_send_va
1069  *
1070  * SYNOPSIS
1071  *
1072  *    SilcBool silc_packet_send_va(SilcPacketStream stream,
1073  *                                 SilcPacketType type,
1074  *                                 SilcPacketFlags flags, ...);
1075  *
1076  * DESCRIPTION
1077  *
1078  *    Same as silc_packet_send but takes the data in as variable argument
1079  *    formatted buffer (see silcbuffmt.h).  The arguments must be ended
1080  *    with SILC_STR_END.  Returns FALSE if packet could not be sent or
1081  *    the buffer could not be formatted.
1082  *
1083  * EXAMPLE
1084  *
1085  *    // Send NEW_CLIENT packet
1086  *    silc_packet_send_va(stream, SILC_PACKET_NEW_CLIENT, 0,
1087  *                        SILC_STR_UI_SHORT(username_len),
1088  *                        SILC_STR_DATA(username, username_len),
1089  *                        SILC_STR_UI_SHORT(realname_len),
1090  *                        SILC_STR_DATA(realname, realname_len),
1091  *                        SILC_STR_END);
1092  *
1093  ***/
1094 SilcBool silc_packet_send_va(SilcPacketStream stream,
1095 			     SilcPacketType type, SilcPacketFlags flags, ...);
1096 
1097 /****f* silccore/SilcPacketAPI/silc_packet_send_va_ext
1098  *
1099  * SYNOPSIS
1100  *
1101  *    SilcBool
1102  *    silc_packet_send_va_ext(SilcPacketStream stream,
1103  *                            SilcPacketType type, SilcPacketFlags flags,
1104  *                            SilcIdType src_id_type, void *srd_id,
1105  *                            SilcIdType dst_id_type, void *dst_id,
1106  *                            SilcCipher cipher, SilcHmac hmac, ...);
1107  *
1108  * DESCRIPTION
1109  *
1110  *    Same as silc_packet_send_va but with this function different sending
1111  *    parameters can be sent as argument.  This function can be used to
1112  *    set specific IDs, cipher and HMAC to be used in packet sending,
1113  *    instead of the ones saved in the `stream'.  If any of the extra
1114  *    pointers are NULL, default values set to the stream will apply.
1115  *
1116  ***/
1117 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1118 				 SilcPacketType type, SilcPacketFlags flags,
1119 				 SilcIdType src_id_type, void *src_id,
1120 				 SilcIdType dst_id_type, void *dst_id,
1121 				 SilcCipher cipher, SilcHmac hmac, ...);
1122 
1123 /****f* silccore/SilcPacketAPI/silc_packet_wait_init
1124  *
1125  * SYNOPSIS
1126  *
1127  *    void *silc_packet_wait_init(SilcPacketStream stream,
1128  *                                const SilcID *source_id, ...);
1129  *
1130  * DESCRIPTION
1131  *
1132  *    Initializes a packet waiter for the packet stream `stream' and
1133  *    for the variable argument list of packet types.  The function
1134  *    silc_packet_wait can be used to block the thread until a packet
1135  *    has been received.
1136  *
1137  *    This function is used to initialize the waiting and to give the list
1138  *    of packet types that caller wish to receive.  The variable argument
1139  *    list must end with -1.  To receive all packets use SILC_PACKET_ANY.
1140  *    If the `source_id' is non-NULL then only packets of the specified
1141  *    type from the specified `source_id' are received.  If it is NULL
1142  *    then the packet source is ignored.
1143  *
1144  *    Returns a context that must be given to the silc_packet_wait function
1145  *    as argument.  Returns NULL on error.  To uninitialize the waiting
1146  *    call silc_packet_wait_uninit.
1147  *
1148  * NOTES
1149  *
1150  *    Note that packets may be available immediately after calling this
1151  *    function and they will be buffered, until silc_packet_wait is called.
1152  *
1153  * EXAMPLE
1154  *
1155  *    void *waiter;
1156  *
1157  *    // Will wait for private message packets
1158  *    waiter = silc_packet_wait_init(stream, NULL,
1159  *                                   SILC_PACKET_PRIVATE_MESSAGE, -1);
1160  *
1161  ***/
1162 void *silc_packet_wait_init(SilcPacketStream stream,
1163 			    const SilcID *source_id, ...);
1164 
1165 /****f* silccore/SilcPacketAPI/silc_packet_wait_uninit
1166  *
1167  * SYNOPSIS
1168  *
1169  *    void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream);
1170  *
1171  * DESCRIPTION
1172  *
1173  *    Uninitializes the waiting context.  This may be called also from
1174  *    another thread while other thread is waiting for packets.  This will
1175  *    inform the waiting thread to stop waiting.
1176  *
1177  ***/
1178 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream);
1179 
1180 /****f* silccore/SilcPacketAPI/silc_packet_wait
1181  *
1182  * SYNOPSIS
1183  *
1184  *    int silc_packet_wait(void *waiter, int timeout,
1185  *                         SilcPacket *return_packet)
1186  *
1187  * DESCRIPTION
1188  *
1189  *    A special function that can be used to wait for a packet to arrive.
1190  *    This function will block the calling process or thread until either
1191  *    a packet is received into the `return_packet' pointer or the specified
1192  *    timeout value `timeout', which is in milliseconds, will expire.  If
1193  *    the timeout is 0, no timeout exist.  Before calling this function the
1194  *    silc_packet_wait_init must be called.  The caller is responsible for
1195  *    freeing the returned packet with silc_packet_free.
1196  *
1197  *    This function can be used for example from a thread that wants to
1198  *    block until SILC packet has been received.
1199  *
1200  *    Returns 1 when packet was received, 0 if timeout occurred and -1 if
1201  *    error occurred.
1202  *
1203  * EXAMPLE
1204  *
1205  *    static int foo_read_data(FooContext c)
1206  *    {
1207  *      SilcPacket packet;
1208  *      void *waiter;
1209  *      ...
1210  *
1211  *      // Will wait for private message packets
1212  *      if (c->initialized == FALSE) {
1213  *        waiter = silc_packet_wait_init(stream,
1214  *                                       SILC_PACKET_PRIVATE_MESSAGE, -1);
1215  *        c->initialized = TRUE;
1216  *      }
1217  *
1218  *      ...
1219  *      // Wait here until private message packet is received
1220  *      if ((silc_packet_wait(waiter, 0, &packet)) < 0)
1221  *        return -1;
1222  *
1223  *      ... process packet ...
1224  *
1225  *      return 1;
1226  *    }
1227  *
1228  ***/
1229 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet);
1230 
1231 /****f* silccore/SilcPacketAPI/silc_packet_free
1232  *
1233  * SYNOPSIS
1234  *
1235  *    void silc_packet_free(SilcPacket packet);
1236  *
1237  * DESCRIPTION
1238  *
1239  *    This function is used to free the SilcPacket pointer that application
1240  *    receives in the SilcPacketReceive callback.  Application must free
1241  *    the packet if it takes it in to processing.
1242  *
1243  ***/
1244 void silc_packet_free(SilcPacket packet);
1245 
1246 #endif /* SILCPACKET_H */
1247