Added entry locking using read/write locks.
[silc.git] / lib / silcclient / silcclient.h
index 56852d83361230f5ed4a41f356571701dab44da5..346a166a57ee7214046586ac471ecc78c30e581f 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2006 Pekka Riikonen
+  Copyright (C) 2000 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
  * DESCRIPTION
  *
  * This interface defines the SILC Client Library API for the application.
- * The client operations are defined first.  These are callback functions that
- * the application MUST implement since the library may call the functions
- * at any time.  At the end of file is the API for the application that
- * it can use from the library.  This is the only file that the application
- * may include from the SIlC Client Library.
- *
- * o SILC Client Operations
- *
- *   These functions must be implemented by the application calling the SILC
- *   client library. The client library can call these functions at any time.
- *
- *   To use this structure: define a static SilcClientOperations variable,
- *   fill it and pass its pointer to silc_client_alloc function.
- *
- * o SILC Client Library API
- *
- *   This is the API that is published by the SILC Client Library for the
- *   applications.  These functions are implemented in the SILC Client Library.
- *   Application may freely call these functions from the library.
+ * The Client Library is a full features SILC client without a user interface.
+ * A simple interface called SILC Client Operations (SilcClientOperations)
+ * is provided for applications to implmeent the necessary functions to use
+ * the client library.  The silcclient.h header file includes client library
+ * API, such as command handling and message sending.  The silcclient_entry.h
+ * header file includes entry handling, such as channel and user entry
+ * handling.
+ *
+ * Practically all functions in the Client Library API accepts SilcClient
+ * and SilcClientConnection as their first two argument.  The first argument
+ * is the actual SilcClient context and the second is the SilcClientConnection
+ * context of the connection in question.  Application may create and handle
+ * multiple connections in one SilcClient.  Connections can be created to
+ * servers and other clients.
+ *
+ * The Client Library support multiple threads and is threads safe is used
+ * correctly.  Messages can be sent from multiple threads without any
+ * locking.  Messages however are always received only in one thread unless
+ * message waiting (see silc_client_private_message_wait as an example) is
+ * used.  The threads can be turned on and off by giving a parameter to the
+ * SilcClient.  When turned on, each new connection to remote host is always
+ * executed in an own thread.  All tasks related to that connection are then
+ * executed in that thread.  This means that client operation callbacks for
+ * that connections may be called from threads and application will need to
+ * employ concurrency control if the callbacks need to access shared data
+ * in the application.  Messages are also received in that thread.
+ *
+ * All entries (SilcClientEntry, SilcChannelEntry and SilcServerEntry) are
+ * reference counted.  If application wishes to save an entry pointer it must
+ * always first acquire a reference.  The reference must be released once the
+ * entry is not needed anymore.  If application wants to read any data from
+ * the entry structure it must first lock the entry.  This protects access to
+ * the entries in multithreaded environment.  If threads are not used, locking
+ * the entries is not needed.  They however still must be referenced even
+ * when threads are not used.
  *
  ***/
 
@@ -83,6 +99,39 @@ typedef enum {
 } SilcClientConnectionStatus;
 /***/
 
+/****f* silcclient/SilcClientAPI/SilcClientRunning
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcClientRunning)(SilcClient client, void *context);
+ *
+ * DESCRIPTION
+ *
+ *    The callback given as argument to silc_client_init function.  Once
+ *    this is called the client library is running and application may
+ *    start using the Client library API.
+ *
+ ***/
+typedef void (*SilcClientRunning)(SilcClient client, void *context);
+
+/****f* silcclient/SilcClientAPI/SilcClientStopped
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcClientStopped)(SilcClient client, void *context);
+ *
+ * DESCRIPTION
+ *
+ *    The callback given as argument to silc_client_stop.  Once this is
+ *    called the client library has stopped and can be freed by calling
+ *    silc_client_free.  Note that this won't be called if there are
+ *    active connections in the client.  Connections must first be closed
+ *    by calling silc_client_close_connection or by sending QUIT command to
+ *    the server connection.
+ *
+ ***/
+typedef void (*SilcClientStopped)(SilcClient client, void *context);
+
 /****f* silcclient/SilcClientAPI/SilcClientConnectCallback
  *
  * SYNOPSIS
@@ -90,22 +139,32 @@ typedef enum {
  *    void (*SilcClientConnectCallback)(SilcClient client,
  *                                      SilcClientConnection conn,
  *                                      SilcClientConnectionStatus status,
+ *                                      SilcStatus error,
+ *                                      const char *message,
  *                                      void *context);
  *
  * DESCRIPTION
  *
  *    Connect callbak given as argument to silc_client_connect_to_server,
- *    silc_client_connect_to_client and silc_client_add_connection functions.
+ *    silc_client_connect_to_client and silc_client_key_exchange functions.
  *    It is called to indicate the status of the connection, indicated
  *    by the `status'.  It is called after the connection has been
  *    established to the remote host and when connection is disconnected
  *    by the remote host.  The `context' is the context given as argument
- *    to the connecting function.
+ *    to the connecting function.  If the `status' is an error the `error'
+ *    may indicate more detailed error.  If `error' is SILC_STATUS_OK no
+ *    detailed error message is available.
+ *
+ *    When the `status' is SILC_CLIENT_CONN_DISCONNECTED the `error' will
+ *    indicate the reason for disconnection.  If the `message' is non-NULL
+ *    it delivers error or disconnection message.
  *
  ***/
 typedef void (*SilcClientConnectCallback)(SilcClient client,
                                          SilcClientConnection conn,
                                          SilcClientConnectionStatus status,
+                                         SilcStatus error,
+                                         const char *message,
                                          void *context);
 
 /****s* silcclient/SilcClientAPI/SilcClient
@@ -122,41 +181,21 @@ typedef void (*SilcClientConnectCallback)(SilcClient client,
  *    is initialized with silc_client_init function, and freed with
  *    silc_client_free function.
  *
+ *    This context represents the client.  Each connection to remote server
+ *    is represented by SilcClientConnection context.
+ *
  * SOURCE
  */
 struct SilcClientStruct {
-  /*
-   * The following fields are set by application. Strings MUST be UTF-8
-   * encoded strings.
-   */
-  char *nickname;               /* Nickname, MAY be set by application  */
-  char *username;               /* Username, MUST be set by application */
-  char *hostname;               /* hostname, MUST be set by application */
-  char *realname;               /* Real name, MUST be set be application */
-
-  /*
-   * The following fields are set by the library
-   */
-
-  /* Scheduler, set by library.  Application may use this pointer. */
-  SilcSchedule schedule;
-
-  /* Random Number Generator. Application should use this as its primary
-     random number generator. */
-  SilcRng rng;
-
-  /* Application specific user data pointer. Client library does not
-     touch this.  This the context sent as argument to silc_client_alloc.
-     Application can use it freely. */
-  void *application;
-
-  /* Generic hash context for application usage */
-  /* XXX remove these; not thread safe */
-  SilcHash md5hash;
-  SilcHash sha1hash;
-
-  /* Internal data for client library. Application cannot access this
-     data at all. */
+  char *username;               /* Username */
+  char *hostname;               /* hostname */
+  char *realname;               /* Real name */
+  SilcSchedule schedule;       /* Client scheduler */
+  SilcRng rng;                 /* Random number generator */
+  void *application;           /* Application specific context, set with
+                                  silc_client_alloc. */
+
+  /* Internal data for client library.  Application cannot access this. */
   SilcClientInternal internal;
 };
 /***/
@@ -170,33 +209,21 @@ struct SilcClientStruct {
  *
  * DESCRIPTION
  *
- *    This structure represents a connection.  When connection is created
- *    to server this is context is returned to the application in the
- *    "connected" client operation.  It includes all the important
- *    data for the session, such as nickname, local and remote IDs, and
- *    other information.  All strings in the structure are UTF-8 encoded.
+ *    This structure represents a connection.  It is allocated and freed by
+ *    the library.  It is returned to application in SilcClientConnectCallback.
+ *    It includes all the important data for the session such as local
+ *    client entry (which includes current nickname), local and remote IDs,
+ *    and other information.  All strings in the structure are UTF-8 encoded.
  *
  * SOURCE
  */
 struct SilcClientConnectionStruct {
-  /*
-   * Local data
-   */
-  SilcClientEntry local_entry;        /* Own Client Entry */
-  SilcClientID *local_id;             /* Current Client ID */
-  SilcBuffer local_idp;                       /* Current Client ID Payload */
-
-  /*
-   * Remote data
-   */
-  char *remote_host;                  /* Remote host name, UTF-8 encoded */
+  SilcClientEntry local_entry;        /* Our own Client Entry */
+  SilcClientID *local_id;             /* Our current Client ID */
+
+  char *remote_host;                  /* Remote host name */
   int remote_port;                    /* Remote port */
   SilcID remote_id;                   /* Remote ID */
-  SilcBuffer remote_idp;              /* Remote ID Payload */
-
-  /*
-   * Common data
-   */
 
   SilcChannelEntry current_channel;    /* Current joined channel */
   SilcPublicKey public_key;           /* Public key used in this connection */
@@ -204,9 +231,12 @@ struct SilcClientConnectionStruct {
   SilcPacketStream stream;            /* Connection to remote host */
   SilcConnectionType type;            /* Connection type */
   SilcClientConnectCallback callback;  /* Connection callback */
-  void *context;                      /* Connection context */
+  void *callback_context;             /* Connection context */
   SilcClient client;                  /* Pointer back to SilcClient */
 
+  /* Application specific data.  Application may set here whatever it wants. */
+  void *context;
+
   /* Internal data for client library.  Application cannot access this. */
   SilcClientConnectionInternal internal;
 };
@@ -290,6 +320,7 @@ typedef enum {
   SILC_KEY_AGREEMENT_ABORTED,         /* The protocol aborted */
   SILC_KEY_AGREEMENT_ALREADY_STARTED,  /* Already started */
   SILC_KEY_AGREEMENT_SELF_DENIED,      /* Negotiationg with itself denied */
+  SILC_KEY_AGREEMENT_NO_MEMORY,        /* System out of memory */
 } SilcKeyAgreementStatus;
 /***/
 
@@ -319,7 +350,7 @@ typedef void (*SilcKeyAgreementCallback)(SilcClient client,
                                         SilcClientConnection conn,
                                         SilcClientEntry client_entry,
                                         SilcKeyAgreementStatus status,
-                                        SilcSKEKeyMaterial *key,
+                                        SilcSKEKeyMaterial key,
                                         void *context);
 
 /****s* silcclient/SilcClientAPI/SilcPrivateMessageKeys
@@ -330,8 +361,8 @@ typedef void (*SilcKeyAgreementCallback)(SilcClient client,
  *
  * DESCRIPTION
  *
- *    Structure to hold the list of private message keys. The array of this
- *    structure is returned by the silc_client_list_private_message_keys
+ *    Structure to hold the list of private message keys. The list of these
+ *    structures is returned by the silc_client_list_private_message_keys
  *    function.
  *
  * SOURCE
@@ -340,8 +371,7 @@ typedef struct {
   SilcClientEntry client_entry;       /* The remote client entry */
   char *cipher;                              /* The cipher name */
   unsigned char *key;                /* The original key, If the appliation
-                                        provided it. This is NULL if the
-                                        library generated the key or if
+                                        provided it. This is NULL if
                                         the SKE key material was used. */
   SilcUInt32 key_len;                /* The key length */
 } *SilcPrivateMessageKeys;
@@ -365,8 +395,6 @@ struct SilcChannelPrivateKeyStruct {
   char *name;                        /* Application given name */
   SilcCipher cipher;                 /* The cipher and key */
   SilcHmac hmac;                     /* The HMAC and hmac key */
-  unsigned char *key;                /* The key data */
-  SilcUInt32 key_len;                /* The key length */
 };
 /***/
 
@@ -417,18 +445,23 @@ typedef void (*SilcVerifyPublicKey)(SilcBool success, void *context);
  *
  * DESCRIPTION
  *
- *    Authentication method resolving callback. This is called by the
- *    application to return the resolved authentication method. The client
+ *    Authentication data resolving callback. This is called by the
+ *    application to return the resolved authentication data. The client
  *    library has called the get_auth_method client operation and given
- *    this function pointer as argument. The `success' will indicate whether
- *    the authentication method could be resolved. The `auth_meth' is the
- *    resolved authentication method. The `auth_data' and the `auth_data_len'
+ *    this function pointer as argument. The `auth_meth' is the selected
+ *    authentication method. The `auth_data' and the `auth_data_len'
  *    are the resolved authentication data. The `context' is the libary's
  *    context sent to the get_auth_method client operation.
  *
+ *    If the `auth_method' is SILC_AUTH_PASSWORD then `auth' and `auth_len'
+ *    is the passphrase and its length.  If it is SILC_AUTH_PUBLIC_KEY the
+ *    `auth' must be NULL.  The library will use the private key given as
+ *    argument to silc_client_connect_to_server, silc_client_connect_to_client
+ *    or silc_client_key_exchange.  If it is SILC_AUTH_NONE, both `auth' and
+ *    `auth_len' are ignored.
+ *
  ***/
-typedef void (*SilcGetAuthMeth)(SilcBool success,
-                               SilcAuthMethod auth_meth,
+typedef void (*SilcGetAuthMeth)(SilcAuthMethod auth_meth,
                                void *auth, SilcUInt32 auth_len,
                                void *context);
 
@@ -497,8 +530,7 @@ typedef struct {
      message). */
   void (*private_message)(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, SilcMessagePayload payload,
-                         SilcMessageFlags flags,
-                         const unsigned char *message,
+                         SilcMessageFlags flags, const unsigned char *message,
                          SilcUInt32 message_len);
 
   /* Notify message to the client. The notify arguments are sent in the
@@ -552,19 +584,26 @@ typedef struct {
                        SilcStatus error, va_list ap);
 
   /* Find authentication method and authentication data by hostname and
-     port. The hostname may be IP address as well. When the authentication
-     method has been resolved the `completion' callback with the found
-     authentication method and authentication data is called. The `conn'
-     may be NULL. */
+     port. The hostname may be IP address as well. The `auth_method' is
+     the authentication method the remote connection requires.  It is
+     however possible that remote accepts also some other authentication
+     method.  Application should use the method that may have been
+     configured for this connection.  If none has been configured it should
+     use the required `auth_method'.  If the `auth_method' is
+     SILC_AUTH_NONE, server does not require any authentication or the
+     required authentication method is not known.  The `completion'
+     callback must be called to deliver the chosen authentication method
+     and data. The `conn' may be NULL. */
   void (*get_auth_method)(SilcClient client, SilcClientConnection conn,
                          char *hostname, SilcUInt16 port,
+                         SilcAuthMethod auth_method,
                          SilcGetAuthMeth completion, void *context);
 
   /* Verifies received public key. The `conn_type' indicates which entity
-     (server, client etc.) has sent the public key. If user decides to trust
-     the application may save the key as trusted public key for later
-     use. The `completion' must be called after the public key has been
-     verified. */
+     (server or client) has sent the public key. If user decides to trust
+     the key the application may save the key as trusted public key for
+     later use. The `completion' must be called after the public key has
+     been verified. */
   void (*verify_public_key)(SilcClient client, SilcClientConnection conn,
                            SilcConnectionType conn_type,
                            SilcPublicKey public_key,
@@ -577,18 +616,17 @@ typedef struct {
   void (*ask_passphrase)(SilcClient client, SilcClientConnection conn,
                         SilcAskPassphrase completion, void *context);
 
-  /* Asks whether the user would like to perform the key agreement protocol.
-     This is called after we have received an key agreement packet or an
-     reply to our key agreement packet. This returns TRUE if the user wants
-     the library to perform the key agreement protocol and FALSE if it is not
-     desired (application may start it later by calling the function
-     silc_client_perform_key_agreement). If TRUE is returned also the
-     `completion' and `context' arguments must be set by the application. */
-  SilcBool (*key_agreement)(SilcClient client, SilcClientConnection conn,
-                           SilcClientEntry client_entry,
-                           const char *hostname, SilcUInt16 port,
-                           SilcKeyAgreementCallback *completion,
-                           void **context);
+  /* Called to indicate that incoming key agreement request has been
+     received.  If the application wants to perform key agreement it may
+     call silc_client_perform_key_agreement to initiate key agreementn or
+     silc_client_send_key_agreement to provide connection point to the
+     remote client in case the `hostname' is NULL.  If key agreement is
+     not desired this request can be ignored.  The `protocol' is either
+     value 0 for TCP or value 1 for UDP. */
+  void (*key_agreement)(SilcClient client, SilcClientConnection conn,
+                       SilcClientEntry client_entry,
+                       const char *hostname, SilcUInt16 protocol,
+                       SilcUInt16 port);
 
   /* Notifies application that file transfer protocol session is being
      requested by the remote client indicated by the `client_entry' from
@@ -599,52 +637,9 @@ typedef struct {
   void (*ftp)(SilcClient client, SilcClientConnection conn,
              SilcClientEntry client_entry, SilcUInt32 session_id,
              const char *hostname, SilcUInt16 port);
-
-  /* Delivers SILC session detachment data indicated by `detach_data' to the
-     application.  If application has issued SILC_COMMAND_DETACH command
-     the client session in the SILC network is not quit.  The client remains
-     in the network but is detached.  The detachment data may be used later
-     to resume the session in the SILC Network.  The appliation is
-     responsible of saving the `detach_data', to for example in a file.
-
-     The detachment data can be given as argument to the functions
-     silc_client_connect_to_server, or silc_client_add_connection when
-     creating connection to remote server, inside SilcClientConnectionParams
-     structure.  If it is provided the client library will attempt to resume
-     the session in the network.  After the connection is created
-     successfully, the application is responsible of setting the user
-     interface for user into the same state it was before detaching (showing
-     same channels, channel modes, etc).  It can do this by fetching the
-     information (like joined channels) from the client library. */
-  void (*detach)(SilcClient client, SilcClientConnection conn,
-                const unsigned char *detach_data,
-                SilcUInt32 detach_data_len);
-
-  /* Called when the client library is up and running.  After this callback
-     is called the application may start using the client library APIs. */
-  void (*running)(SilcClient client, void *application);
 } SilcClientOperations;
 /***/
 
-/****f* silcclient/SilcClientAPI/SilcNicknameFormatParse
- *
- * SYNOPSIS
- *
- *    typedef void (*SilcNicknameFormatParse)(const char *nickname,
- *                                            char **ret_nickname);
- *
- * DESCRIPTION
- *
- *    A callback function provided by the application for the library in
- *    SilcClientParams structure. This function parses the formatted
- *    nickname string `nickname' and returns the true nickname to the
- *    `ret_nickname' pointer. The library can call this function at
- *    any time.
- *
- ***/
-typedef void (*SilcNicknameFormatParse)(const char *nickname,
-                                       char **ret_nickname);
-
 /****s* silcclient/SilcClientAPI/SilcClientParams
  *
  * NAME
@@ -667,31 +662,13 @@ typedef struct {
      in the callbacks to protect application specific data. */
   SilcBool threads;
 
-  /* Number of maximum tasks the client library's scheduler can handle.
-     If set to zero, the default value will be used (200). For WIN32
-     systems this should be set to 64 as it is the hard limit dictated
-     by the WIN32. */
-  int task_max;
-
-  /* Rekey timeout in seconds. The client will perform rekey in this
-     time interval. If set to zero, the default value will be used. */
-  unsigned int rekey_secs;
-
-  /* Connection authentication method request timeout. If server does not
-     reply back the current authentication method when we've requested it
-     in this time interval we'll assume the reply will not come at all.
-     If set to zero, the default value (2 seconds) will be used. */
-  unsigned int connauth_request_secs;
-
   /* Nickname format string. This can be used to order the client library
      to save the nicknames in the library in a certain format. Since
      nicknames are not unique in SILC it is possible to have multiple same
      nicknames. Using this format string it is possible to order the library
-     to separate the multiple same nicknames from each other. The format
-     types are defined below and they can appear in any order in the format
-     string. If this is NULL then default format is used which is the
-     default nickname without anything else. The string MUST be NULL
-     terminated.
+     to separate the multiple same nicknames from each other. If this is
+     empty then default format is used which is the default nickname
+     without anything else. The string MUST be NULL terminated.
 
      Following format types are available:
 
@@ -707,11 +684,10 @@ typedef struct {
                              "%a!%n@%s"  (fe. nick@server, 2!nick@server)
                             "%n@%H"     (fe. nick@host.domain.com)
 
-     By default this format is employed to the nicknames by the libary
-     only when there appears multiple same nicknames. If the library has
-     only one nickname cached the nickname is saved as is and without the
-     defined format. If you want always to save the nickname in the defined
-     format set the boolean field `nickname_force_format' to value TRUE.
+     Note that there must always be some separator characters around '%n'
+     format.  It is not possible to put format characters before or after
+     '%n' without separators (such ash '@').  Also note that the separator
+     character should be a character that cannot be part of normal nickname.
   */
   char nickname_format[32];
 
@@ -723,24 +699,6 @@ typedef struct {
      value. */
   SilcBool nickname_force_format;
 
-  /* A callback function provided by the application for the library to
-     parse the nickname from the formatted nickname string. Even though
-     the libary formats the nicknames the application knows generally the
-     format better so this function should be provided for the library
-     if the application sets the `nickname_format' field. The library
-     will call this to get the true nickname from the provided formatted
-     nickname string whenever it needs the true nickname. */
-  SilcNicknameFormatParse nickname_parse;
-
-  /* If this is set to TRUE then the client will ignore all incoming
-     Requested Attributes queries and does not reply anything back.  This
-     usually leads into situation where server does not anymore send
-     the queries after seeing that client does not reply anything back.
-     If your application does not support Requested Attributes or you do
-     not want to use them set this to TRUE.  See SilcAttribute and
-     silc_client_attribute_add for more information on attributes. */
-  SilcBool ignore_requested_attributes;
-
   /* If this is set to TRUE, the silcclient library will not register and
      deregister the cipher, pkcs, hash and hmac algorithms. The application
      itself will need to handle that. */
@@ -796,7 +754,9 @@ void silc_client_free(SilcClient client);
  *
  * SYNOPSIS
  *
- *    SilcBool silc_client_init(SilcClient client);
+ *    SilcBool silc_client_init(SilcClient client, const char *username,
+ *                              const char *hostname, const char *realname,
+ *                              SilcClientRunning running, void *context);
  *
  * DESCRIPTION
  *
@@ -804,8 +764,20 @@ void silc_client_free(SilcClient client);
  *    the client ready to be run. One must call silc_client_run to run the
  *    client. Returns FALSE if error occurred, TRUE otherwise.
  *
+ *    The `username' and `hostname' strings must be given and they must be
+ *    UTF-8 encoded.  The `username' is the client's username in the
+ *    operating system, `hostname' is the client's host name and the
+ *    `realname' is the user's real name.
+ *
+ *    The `running' callback is called after the client is running after
+ *    silc_client_run or silc_client_run_one has been called.  Application
+ *    may start using the Client library API after that.  Setting the
+ *    callback is optional, but recommended.
+ *
  ***/
-SilcBool silc_client_init(SilcClient client);
+SilcBool silc_client_init(SilcClient client, const char *username,
+                         const char *hostname, const char *realname,
+                         SilcClientRunning running, void *context);
 
 /****f* silcclient/SilcClientAPI/silc_client_run
  *
@@ -815,7 +787,7 @@ SilcBool silc_client_init(SilcClient client);
  *
  * DESCRIPTION
  *
- *    Runs the client. This starts the scheduler from the utility library.
+ *    Runs the client.  This starts the scheduler from the utility library.
  *    When this functions returns the execution of the application is over.
  *    The client must be initialized before calling this.
  *
@@ -845,17 +817,25 @@ void silc_client_run_one(SilcClient client);
  *
  * SYNOPSIS
  *
- *    void silc_client_stop(SilcClient client);
+ *    void silc_client_stop(SilcClient client, SilcClientStopped stopped,
+ *                          void *context);
  *
  * DESCRIPTION
  *
  *    Stops the client. This is called to stop the client and thus to stop
  *    the program.  The client context must be freed with the silc_client_free
- *    function.
+ *    function.  All connections that exist in this client must be closed
+ *    before calling this function.  Connections can be closed by calling
+ *    silc_client_close_connection.
+ *
+ *    The `stopped' will be called once the client and all connections have
+ *    finished.  The client may be freed after that.  Note that the `stopped'
+ *    won't be called before all connections have finished.  Setting the
+ *    callback is optional.
  *
  ***/
-void silc_client_stop(SilcClient client);
-
+void silc_client_stop(SilcClient client, SilcClientStopped stopped,
+                     void *context);
 
 /* Connecting functions */
 
@@ -868,18 +848,28 @@ void silc_client_stop(SilcClient client);
  * DESCRIPTION
  *
  *    Client connection parameters.  This can be filled by the application
- *    and given as argument to silc_client_connect_to_server or to
- *    silc_client_add_connection.
+ *    and given as argument to silc_client_connect_to_server,
+ *    silc_client_connect_to_client, silc_client_key_exchange or
+ *    silc_client_send_key_agreement.
  *
  * SOURCE
  */
 typedef struct {
+  /* If this is provided the user's nickname in the network will be the
+     string given here.  If it is given, it must be UTF-8 encoded.  If this
+     string is not given, the user's username by default is used as nickname.
+     The nickname may later be changed by using NICK command.  The maximum
+     length for the nickname string is 128 bytes. */
+  char *nickname;
+
   /* If this key repository pointer is non-NULL then public key received in
      the key exchange protocol will be verified from this repository.  If
      this is not provided then the `verify_public_key' client operation will
      be called back to application.  If the boolean `verify_notfound' is set
      to TRUE then the `verify_public_key' client operation will be called
-     in case the public key is not found in `repository'. */
+     in case the public key is not found in `repository'.  Only public keys
+     added with at least SILC_SKR_USAGE_KEY_AGREEMENT in the repository will
+     be checked, other keys will be ignored. */
   SilcSKR repository;
   SilcBool verify_notfound;
 
@@ -897,14 +887,19 @@ typedef struct {
   void *auth;
   SilcUInt32 auth_len;
 
-  /* If this boolean is set to TRUE then the client's connection to the
-     remote host will use UDP instead of TCP.  The `local_ip' specifies
-     the local IP address used with the UDP connection, and it must be
-     non-NULL.  If the `local_port' is non-zero it will be used as local
-     port with the UDP connection.  The remote host will also send packets
-     to the specified address and port. */
+  /* If this boolean is set to TRUE then the connection will use UDP instead
+     of TCP.  If UDP is set then also the next `local_ip' and `local_port'
+     must be set. */
   SilcBool udp;
+
+  /* The `local_ip' specifies the local IP address used with the connection.
+     It must be non-NULL if `udp' boolean is TRUE.  If the `local_port' is
+     non-zero it will be used as local port with UDP connection.  The remote
+     host will also send packets to the specified address and port.  If the
+     `bind_ip' is non-NULL a listener is bound to that address instead of
+     `local_ip'. */
   char *local_ip;
+  char *bind_ip;
   int local_port;
 
   /* If this boolean is set to TRUE then the key exchange is done with
@@ -917,20 +912,35 @@ typedef struct {
      client, but must be FALSE with server connections. */
   SilcBool no_authentication;
 
-  /* The SILC session detachment data that was returned by `detach' client
-     operation when the application detached from the network.  Application
-     is responsible of saving the data and giving it as argument here
-     for resuming the session in the SILC network.
-
-     If this is provided here the client library will attempt to resume
-     the session in the network.  After the connection is created
-     successfully, the application is responsible of setting the user
-     interface for user into the same state it was before detaching (showing
-     same channels, channel modes, etc).  It can do this by fetching the
-     information (like joined channels) from the client library. */
+  /* The SILC session detachment data that was returned in the `command_reply'
+     client operation for SILC_COMMAND_DETACH command.  If this is provided
+     here the client library will attempt to resume the session in the network.
+     After the connection is created and the session has been resumed the
+     client will receive SILC_COMMAND_NICK command_reply for the client's
+     nickname in the network and SILC_COMMAND_JOIN command reply for all the
+     channels that the client has joined in the network.  It may also receive
+     SILC_COMMAND_UMODE command reply to set user's mode on the network. */
   unsigned char *detach_data;
   SilcUInt32 detach_data_len;
 
+  /* Connection timeout.  If non-zero, the connection will timeout unless
+     the SILC connection is completed in the specified amount of time. */
+  SilcUInt32 timeout_secs;
+
+  /* Rekey timeout in seconds.  The client will perform rekey in this
+     time interval.  If set to zero, the default value will be used
+     (3600 seconds, 1 hour). */
+  SilcUInt32 rekey_secs;
+
+  /* If this is set to TRUE then the client will ignore all incoming
+     Requested Attributes queries and does not reply anything back.  This
+     usually leads into situation where server does not anymore send
+     the queries after seeing that client does not reply anything back.
+     If your application does not support Requested Attributes or you do
+     not want to use them set this to TRUE.  See SilcAttribute and
+     silc_client_attribute_add for more information on attributes. */
+  SilcBool ignore_requested_attributes;
+
 } SilcClientConnectionParams;
 /***/
 
@@ -938,10 +948,11 @@ typedef struct {
  *
  * SYNOPSIS
  *
- *    void
+ *    SilcAsyncOperation
  *    silc_client_connect_to_server(SilcClient client,
  *                                  SilcClientConnectionParams *params,
  *                                  SilcPublicKey public_key,
+ *                                  SilcPrivateKey private_key,
  *                                  char *remote_host, int port,
  *                                  SilcClientConnectCallback callback,
  *                                  void *context);
@@ -959,26 +970,32 @@ typedef struct {
  *    host disconnects.
  *
  *    If application wishes to create the network connection itself, use
- *    the silc_client_add_connection after creating the connection, instead
- *    of using this function.
+ *    the silc_client_key_exchange after creating the connection to start
+ *    key exchange and authentication with the server.
+ *
+ *    Returns SilcAsyncOperation which can be used to cancel the connecting,
+ *    or NULL on error.  Note that the returned pointer becomes invalid
+ *    after the `callback' is called.
  *
  ***/
-void silc_client_connect_to_server(SilcClient client,
-                                  SilcClientConnectionParams *params,
-                                  SilcPublicKey public_key,
-                                  SilcPrivateKey private_key,
-                                  char *remote_host, int port,
-                                  SilcClientConnectCallback callback,
-                                  void *context);
+SilcAsyncOperation
+silc_client_connect_to_server(SilcClient client,
+                             SilcClientConnectionParams *params,
+                             SilcPublicKey public_key,
+                             SilcPrivateKey private_key,
+                             char *remote_host, int port,
+                             SilcClientConnectCallback callback,
+                             void *context);
 
 /****f* silcclient/SilcClientAPI/silc_client_connect_to_client
  *
  * SYNOPSIS
  *
- *    void
+ *    SilcAsyncOperation
  *    silc_client_connect_to_client(SilcClient client,
  *                                  SilcClientConnectionParams *params,
  *                                  SilcPublicKey public_key,
+ *                                  SilcPrivateKey private_key,
  *                                  char *remote_host, int port,
  *                                  SilcClientConnectCallback callback,
  *                                  void *context);
@@ -995,100 +1012,97 @@ void silc_client_connect_to_server(SilcClient client,
  *    when remote host disconnects.
  *
  *    If application wishes to create the network connection itself, use
- *    the silc_client_add_connection after creating the connection, instead
- *    of using this function.
- *
- ***/
-void silc_client_connect_to_client(SilcClient client,
-                                  SilcClientConnectionParams *params,
-                                  SilcPublicKey public_key,
-                                  SilcPrivateKey private_key,
-                                  char *remote_host, int port,
-                                  SilcClientConnectCallback callback,
-                                  void *context);
-
-/****f* silcclient/SilcClientAPI/silc_client_add_connection
- *
- * SYNOPSIS
- *
- *
- *    SilcClientConnection
- *    silc_client_add_connection(SilcClient client,
- *                               SilcConnectionType conn_type,
- *                               SilcClientConnectionParams *params,
- *                               char *hostname, int port, void *context);
- *
- * DESCRIPTION
- *
- *    Allocates and adds new connection to the client. This adds the allocated
- *    connection to the connection table and returns a pointer to it. A client
- *    can have multiple connections to multiple hosts. Every connection must
- *    be added to the client using this function. User data `context' may
- *    be sent as argument.  If the `params' is provided they are used by
- *    the routine.
+ *    the silc_client_key_exchange after creating the connection to start
+ *    key exchange with the client.
  *
- * NOTES
- *
- *    This function is normally used only if the application performed
- *    the connecting outside the library, and did not called the
- *    silc_client_connect_to_server function at all.
- *
- ***/
-SilcClientConnection
-silc_client_add_connection(SilcClient client,
-                          SilcConnectionType conn_type,
-                          SilcClientConnectionParams *params,
-                          SilcPublicKey public_key,
-                          SilcPrivateKey private_key,
-                          char *remote_host, int port,
-                          SilcClientConnectCallback callback,
-                          void *context);
-
-/****f* silcclient/SilcClientAPI/silc_client_del_connection
- *
- * SYNOPSIS
- *
- *    void silc_client_del_connection(SilcClient client,
- *                                    SilcClientConnection conn);
- *
- * DESCRIPTION
- *
- *    Removes connection from client. Frees all memory. The library
- *    call this function automatically for all connection contexts.
- *    The application however may free the connection contexts it has
- *    allocated.
+ *    Returns SilcAsyncOperation which can be used to cancel the connecting,
+ *    or NULL on error.  Note that the returned pointer becomes invalid
+ *    after the `callback' is called.
  *
  ***/
-void silc_client_del_connection(SilcClient client, SilcClientConnection conn);
+SilcAsyncOperation
+silc_client_connect_to_client(SilcClient client,
+                             SilcClientConnectionParams *params,
+                             SilcPublicKey public_key,
+                             SilcPrivateKey private_key,
+                             char *remote_host, int port,
+                             SilcClientConnectCallback callback,
+                             void *context);
 
-/****f* silcclient/SilcClientAPI/silc_client_start_key_exchange
+/****f* silcclient/SilcClientAPI/silc_client_key_exchange
  *
  * SYNOPSIS
  *
- *    void silc_client_start_key_exchange(SilcClient client,
- *                                        SilcClientConnection conn,
- *                                        SilcStream stream);
+ *    SilcAsyncOperation
+ *    silc_client_key_exchange(SilcClient client,
+ *                             SilcClientConnectionParams *params,
+ *                             SilcPublicKey public_key,
+ *                             SilcPrivateKey private_key,
+ *                             SilcStream stream,
+ *                             SilcConnectionType conn_type,
+ *                             SilcClientConnectCallback callback,
+ *                             void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Starts key exchange protocol and authentication protocol in the
+ *    connection indicated by `stream'.  This function can be be used to
+ *    start SILC session with remote host (usually server) when the caller
+ *    has itself created the connection, instead of calling the function
+ *    silc_client_connect_to_server or silc_client_connect_to_client.  If
+ *    one of those functions was used this function must not be called as
+ *    in that case the key exchange is performed automatically.
+ *
+ *    Use this function only if you have created the connection by yourself.
+ *    After creating the connection the socket must be wrapped into a
+ *    socket stream.  See silcsocketstream.h for more information.  Note that
+ *    the `stream' must have valid remote IP address (and optionally also
+ *    hostname) and port set.
+ *
+ *    The `params' may be provided to provide various connection parameters.
+ *    The `public_key' and the `private_key' is your identity used in this
+ *    session.  The `callback' with `context' will be called after the session
+ *    has been set up.  It will also be called later when remote host
+ *    disconnects.  The `conn_type' is the type of session this is going to
+ *    be.
+ *
+ *    Returns SilcAsyncOperation which can be used to cancel the connecting,
+ *    or NULL on error.  Note that the returned pointer becomes invalid
+ *    after the `callback' is called.
  *
- * DESCRIPTION
+ * EXAMPLE
  *
- *    Start SILC Key Exchange (SKE) protocol to negotiate shared secret
- *    key material between client and server.  This function can be called
- *    directly if application is performing its own connecting and does not
- *    use the connecting provided by this library. This function is normally
- *    used only if the application performed the connecting outside the
- *    library. The library however may use this internally.  After the
- *    key exchange is performed the `connect' client operation is called.
+ *    int sock;
  *
- * NOTES
+ *    // Create remote connection stream.  Resolve hostname and IP also.
+ *    sock = create_connection(remote_host, port);
+ *    silc_socket_tcp_stream_create(sock, TRUE, FALSE, schedule,
+ *                                  stream_create_cb, app);
  *
- *    The silc_client_add_connection must be called before calling this
- *    function to create the SilcClientConnection context for this
- *    connection.
+ *    // Stream callback delivers our new SilcStream context
+ *    void stream_create_cb(SilcSocketStreamStatus status, SilcStream stream,
+ *                          void *context)
+ *    {
+ *      ...
+ *      if (status != SILC_SOCKET_OK)
+ *        error(status);
+ *
+ *      // Start key exchange
+ *      silc_client_key_exchange(client, NULL, public_key, private_key,
+ *                               stream, SILC_CONN_SERVER, connection_cb, app);
+ *      ...
+ *    }
  *
  ***/
-void silc_client_start_key_exchange(SilcClient client,
-                                   SilcClientConnection conn,
-                                   SilcStream stream);
+SilcAsyncOperation
+silc_client_key_exchange(SilcClient client,
+                        SilcClientConnectionParams *params,
+                        SilcPublicKey public_key,
+                        SilcPrivateKey private_key,
+                        SilcStream stream,
+                        SilcConnectionType conn_type,
+                        SilcClientConnectCallback callback,
+                        void *context);
 
 /****f* silcclient/SilcClientAPI/silc_client_close_connection
  *
@@ -1099,19 +1113,18 @@ void silc_client_start_key_exchange(SilcClient client,
  *
  * DESCRIPTION
  *
- *    Closes connection to remote end. Free's all allocated data except
- *    for some information such as nickname etc. that are valid at all time.
- *    Usually application does not need to directly call this, except
- *    when explicitly closing the connection, or if an error occurs
- *    during connection to server (see 'connect' client operation for
- *    more information).
+ *    Closes the remote connection `conn'.  The `conn' will become invalid
+ *    after this call.  Usually this function is called only when explicitly
+ *    closing connection for example in case of error, or when the remote
+ *    connection was created by the application or when the remote is client
+ *    connection.  Server connections are usually closed by sending QUIT
+ *    command to the server.  However, this call may also be used.
  *
  ***/
 void silc_client_close_connection(SilcClient client,
                                  SilcClientConnection conn);
 
-
-/* Message sending functions (client_channel.c and client_prvmsg.c) */
+/* Message sending functions */
 
 /****f* silcclient/SilcClientAPI/silc_client_send_channel_message
  *
@@ -1122,6 +1135,7 @@ void silc_client_close_connection(SilcClient client,
  *                                              SilcChannelEntry channel,
  *                                              SilcChannelPrivateKey key,
  *                                              SilcMessageFlags flags,
+ *                                              SilcHash hash,
  *                                              unsigned char *data,
  *                                              SilcUInt32 data_len);
  *
@@ -1140,7 +1154,8 @@ void silc_client_close_connection(SilcClient client,
  *    private key) is used.
  *
  *    If the `flags' includes SILC_MESSAGE_FLAG_SIGNED the message will be
- *    digitally signed with the SILC key pair.
+ *    digitally signed with the SILC key pair.  In this case the `hash'
+ *    pointer must be provided as well.
  *
  *    Returns TRUE if the message was sent, and FALSE if error occurred or
  *    the sending is not allowed due to channel modes (like sending is
@@ -1153,19 +1168,10 @@ SilcBool silc_client_send_channel_message(SilcClient client,
                                          SilcChannelEntry channel,
                                          SilcChannelPrivateKey key,
                                          SilcMessageFlags flags,
+                                         SilcHash hash,
                                          unsigned char *data,
                                          SilcUInt32 data_len);
 
-/* Block process until channel message from `channel' is received */
-SilcBool
-silc_client_receive_channel_message(SilcClient client,
-                                   SilcClientConnection conn,
-                                   SilcChannelEntry channel,
-                                   SilcClientEntry *return_sender,
-                                   SilcMessageFlags *return_flags,
-                                   const unsigned char **return_message,
-                                   SilcUInt32 *return_message_len);
-
 /****f* silcclient/SilcClientAPI/silc_client_send_private_message
  *
  * SYNOPSIS
@@ -1174,6 +1180,7 @@ silc_client_receive_channel_message(SilcClient client,
  *                                              SilcClientConnection conn,
  *                                              SilcClientEntry client_entry,
  *                                              SilcMessageFlags flags,
+ *                                              SilcHash hash,
  *                                              unsigned char *data,
  *                                              SilcUInt32 data_len);
  *
@@ -1182,7 +1189,8 @@ silc_client_receive_channel_message(SilcClient client,
  *    Sends private message to remote client. If private message key has
  *    not been set with this client then the message will be encrypted using
  *    normal session keys.  If the `flags' includes SILC_MESSAGE_FLAG_SIGNED
- *    the message will be digitally signed with the SILC key pair.
+ *    the message will be digitally signed with the SILC key pair.  In this
+ *    case the caller must also provide the `hash' pointer.
  *
  *    Returns TRUE if the message was sent, and FALSE if error occurred.
  *    This function is thread safe and private messages can be sent from
@@ -1193,194 +1201,86 @@ SilcBool silc_client_send_private_message(SilcClient client,
                                          SilcClientConnection conn,
                                          SilcClientEntry client_entry,
                                          SilcMessageFlags flags,
+                                         SilcHash hash,
                                          unsigned char *data,
                                          SilcUInt32 data_len);
 
-/****f* silcclient/SilcClientAPI/SilcGetChannelCallback
- *
- * SYNOPSIS
- *
- *    typedef void (*SilcGetChannelCallback)(SilcClient client,
- *                                           SilcClientConnection conn,
- *                                           SilcChannelEntry *channels,
- *                                           SilcUInt32 channels_count,
- *                                           void *context);
- *
- * DESCRIPTION
- *
- *    Callback function given to the silc_client_get_channel_* functions.
- *    The found entries are allocated into the `channels' array. The array
- *    must not be freed by the receiver, the library will free it later.
- *    If the `channel' is NULL, no such channel exist in the SILC Network.
- *
- ***/
-typedef void (*SilcGetChannelCallback)(SilcClient client,
-                                      SilcClientConnection conn,
-                                      SilcChannelEntry *channels,
-                                      SilcUInt32 channels_count,
-                                      void *context);
-
-/****f* silcclient/SilcClientAPI/silc_client_get_channel
- *
- * SYNOPSIS
- *
- *    SilcChannelEntry silc_client_get_channel(SilcClient client,
- *                                             SilcClientConnection conn,
- *                                             char *channel_name);
- *
- * DESCRIPTION
- *
- *    Finds entry for channel by the channel name. Returns the entry or NULL
- *    if the entry was not found. It is found only if the client is joined
- *    to the channel.  Use silc_client_get_channel_resolve or
- *    silc_client_get_channel_by_id_resolve to resolve channel that client
- *    is not joined.
- *
- ***/
-SilcChannelEntry silc_client_get_channel(SilcClient client,
-                                        SilcClientConnection conn,
-                                        char *channel_name);
-
-/****f* silcclient/SilcClientAPI/silc_client_get_channel_resolve
+/****f* silcclient/SilcClientAPI/silc_client_private_message_wait_init
  *
  * SYNOPSIS
  *
- *    void silc_client_get_channel_resolve(SilcClient client,
- *                                         SilcClientConnection conn,
- *                                         char *channel_name,
- *                                         SilcGetChannelCallback completion,
- *                                         void *context);
+ *    SilcBool
+ *    silc_client_private_message_wait_init(SilcClient client,
+ *                                          SilcClientConnection conn);
  *
  * DESCRIPTION
  *
- *    Resolves entry for channel by the channel name from the server.
- *    The resolving is done with IDENTIFY command. Note that users on
- *    the channel are not resolved at the same time. Use for example
- *    silc_client_get_clients_by_channel to resolve all users on a channel.
+ *    Initializes private message waiting functionality for the connection
+ *    indicated by `conn'.  Once this is called private message from remote
+ *    connection indicated by `conn' for any client entry beloning to that
+ *    connection may be waited for, for example in an thread.  The function
+ *    silc_client_private_message_wait is used to block the current thread
+ *    until a private message is received from a specified client entry.
+ *    Return FALSE on error.
  *
  ***/
-void silc_client_get_channel_resolve(SilcClient client,
-                                    SilcClientConnection conn,
-                                    char *channel_name,
-                                    SilcGetChannelCallback completion,
-                                    void *context);
+SilcBool silc_client_private_message_wait_init(SilcClient client,
+                                              SilcClientConnection conn);
 
-/****f* silcclient/SilcClientAPI/silc_client_get_channel_by_id
- *
- * SYNOPSIS
- *
- *    SilcChannelEntry
- *    silc_client_get_channel_by_id(SilcClient client,
- *                                  SilcClientConnection conn,
- *                                  SilcChannelID *channel_id);
- *
- * DESCRIPTION
- *
- *    Finds channel entry by the channel ID. Returns the entry or NULL
- *    if the entry was not found.  This checks the local cache and does
- *    not resolve anything from server.
- *
- ***/
-SilcChannelEntry silc_client_get_channel_by_id(SilcClient client,
-                                              SilcClientConnection conn,
-                                              SilcChannelID *channel_id);
-
-/****f* silcclient/SilcClientAPI/silc_client_get_channel_by_id_resolve
+/****f* silcclient/SilcClientAPI/silc_client_private_message_wait_uninit
  *
  * SYNOPSIS
  *
  *    void
- *    silc_client_get_channel_by_id_resolve(SilcClient client,
- *                                          SilcClientConnection conn,
- *                                          SilcChannelID *channel_id,
- *                                          SilcGetClientCallback completion,
- *                                          void *context);
- *
- * DESCRIPTION
- *
- *    Resolves the channel information (its name mainly) from the server
- *    by the `channel_id'. Use this only if you know that you do not have
- *    the entry cached locally. The resolving is done with IDENTIFY command.
- *
- *    Note that users on the channel are not resolved at the same time.
- *    Use for example silc_client_get_clients_by_channel to resolve all
- *    users on a channel.
- *
- ***/
-void silc_client_get_channel_by_id_resolve(SilcClient client,
-                                          SilcClientConnection conn,
-                                          SilcChannelID *channel_id,
-                                          SilcGetChannelCallback completion,
-                                          void *context);
-
-/****f* silcclient/SilcClientAPI/silc_client_del_channel
- *
- * SYNOPSIS
- *
- *    SilcBool silc_client_del_channel(SilcClient client,
- *                                 SilcClientConnection conn,
- *                                 SilcChannelEntry channel)
- *
- * DESCRIPTION
- *
- *    Removes channel from local cache by the channel entry indicated by
- *    the `channel'.  Returns TRUE if the deletion were successful.
- *
- ***/
-SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn,
-                                SilcChannelEntry channel);
-
-/****f* silcclient/SilcClientAPI/silc_client_get_server
- *
- * SYNOPSIS
- *
- *    SilcServerEntry silc_client_get_server(SilcClient client,
- *                                           SilcClientConnection conn,
- *                                           char *server_name)
- *
- * DESCRIPTION
- *
- *    Finds entry for server by the server name. Returns the entry or NULL
- *    if the entry was not found.
- *
- ***/
-SilcServerEntry silc_client_get_server(SilcClient client,
-                                      SilcClientConnection conn,
-                                      char *server_name);
-
-/****f* silcclient/SilcClientAPI/silc_client_get_server_by_id
- *
- * SYNOPSIS
- *
- *    SilcServerEntry silc_client_get_server_by_id(SilcClient client,
- *                                                 SilcClientConnection conn,
- *                                                 SilcServerID *server_id);
+ *    silc_client_private_message_wait_uninit(SilcClient client,
+ *                                            SilcClientConnection conn);
  *
  * DESCRIPTION
  *
- *    Finds entry for server by the server ID. Returns the entry or NULL
- *    if the entry was not found.
+ *    Unintializes private message waiting for connection indicated by
+ *    `conn'.  After this call private message cannot be waited anymore.
+ *    This call may be called from any thread.  This call will signal all
+ *    private message waiting threads to stop waiting.
  *
  ***/
-SilcServerEntry silc_client_get_server_by_id(SilcClient client,
-                                            SilcClientConnection conn,
-                                            SilcServerID *server_id);
+void silc_client_private_message_wait_uninit(SilcClient client,
+                                            SilcClientConnection conn);
 
-/****f* silcclient/SilcClientAPI/silc_client_del_server
+/****f* silcclient/SilcClientAPI/silc_client_private_message_wait
  *
  * SYNOPSIS
  *
- *    SilcBool silc_client_del_server(SilcClient client, SilcClientConnection conn,
- *                                SilcServerEntry server);
- *
- * DESCRIPTION
- *
- *    Removes server from local cache by the server entry indicated by
- *    the `server'.  Returns TRUE if the deletion were successful.
+ *    SilcBool
+ *    silc_client_private_message_wait(SilcClient client,
+ *                                     SilcClientConnection conn,
+ *                                     SilcClientEntry client_entry,
+ *                                     SilcMessagePayload *payload);
+ *
+ * DESCRIPTION
+ *
+ *    Blocks current thread or process until a private message has been
+ *    received from the remote client indicated by `client_entry'.  Before
+ *    private messages can be waited the silc_client_private_message_wait_init
+ *    must be called.  This function can be used from a thread to wait for
+ *    private message from the specified client.  Multiple threads can be
+ *    created to wait messages from multiple clients.  Any other private
+ *    message received from the connection indicated by `conn' will be
+ *    forwarded to the normal `private_message' client operation.  The
+ *    private messages from `client_entry' will not be delivered to the
+ *    `private_message' client operation.
+ *
+ *    Returns TRUE and the received private message into `payload'.  The caller
+ *    must free the returned SilcMessagePayload.  If this function returns
+ *    FALSE the private messages cannot be waited anymore.  This happens
+ *    when some other thread calls silc_client_private_message_wait_uninit.
+ *    This returns FALSE also if silc_client_private_message_wait_init has
+ *    not been called.
  *
  ***/
-SilcBool silc_client_del_server(SilcClient client, SilcClientConnection conn,
-                               SilcServerEntry server);
+SilcBool silc_client_private_message_wait(SilcClient client,
+                                         SilcClientConnection conn,
+                                         SilcClientEntry client_entry,
+                                         SilcMessagePayload *payload);
 
 /****f* silcclient/SilcClientAPI/silc_client_on_channel
  *
@@ -1452,8 +1352,40 @@ SilcUInt16 silc_client_command_call(SilcClient client,
                                    SilcClientConnection conn,
                                    const char *command_line, ...);
 
-/* If FALSE is returned the callback will not be called again, even if there
-   is more data coming in in the command reply. */
+/****f* silcclient/SilcClientAPI/SilcClientCommandReply
+ *
+ * SYNOPSIS
+ *
+ *    typedef SilcBool (*SilcClientCommandReply)(SilcClient client,
+ *                                               SilcClientConnection conn,
+ *                                               SilcCommand command,
+ *                                               SilcStatus status,
+ *                                               SilcStatus error,
+ *                                               void *context,
+ *                                               va_list ap);
+ *
+ * DESCRIPTION
+ *
+ *    The command reply callback function given as argument to functions
+ *    silc_client_command_send and silc_client_command_pending.  This is
+ *    called to deliver the command replies to the caller.  Each command
+ *    reply received from the server to the `command' will be delivered
+ *    separately to the caller by calling this callback.  The `status' will
+ *    indicate whether there is only one reply or multiple replies.  The
+ *    `error' will indicate if an error occurred.  The `ap' will include
+ *    command reply arguments.  They are the same arguments as for
+ *    `command_reply' client operation in SilcClientOperations.
+ *
+ *    If `status' is SILC_STATUS_OK only one reply was received and error
+ *    did not occur.  If it is SILC_STATUS_LIST_START, SILC_STATUS_LIST_ITEM
+ *    or SILC_STATUS_LIST_END, there are will be two or more replies.  The
+ *    first reply is SILC_STATUS_LIST_START and last one SILC_STATUS_LIST_END.
+ *
+ *    If FALSE is returned in this function this callback will not be called
+ *    again for `command' even if there are more comand replies.  By returning
+ *    FALSE the caller my stop the command reply handling when needed.
+ *
+ ***/
 typedef SilcBool (*SilcClientCommandReply)(SilcClient client,
                                           SilcClientConnection conn,
                                           SilcCommand command,
@@ -1490,9 +1422,7 @@ typedef SilcBool (*SilcClientCommandReply)(SilcClient client,
  *    The `reply' callback must be provided, and it is called when the
  *    command reply is received from the server.  Note that, when using this
  *    function the default `command_reply' client operation will not be
- *    called, when reply is received.  Note however that, `reply' is
- *    identical with `command_reply' callback, and application may forward
- *    the reply from `reply' to `command_reply' callback, if desired.
+ *    called, when reply is received.
  *
  *    Returns command identifier for this sent command.  It can be used
  *    to additionally attach to the command reply using the function
@@ -1570,7 +1500,7 @@ SilcBool silc_client_command_pending(SilcClientConnection conn,
                                     void *context);
 
 
-/* Private Message key management (client_prvmsg.c) */
+/* Private Message key management */
 
 /****f* silcclient/SilcClientAPI/silc_client_add_private_message_key
  *
@@ -1583,29 +1513,26 @@ SilcBool silc_client_command_pending(SilcClientConnection conn,
  *                                        const char *cipher,
  *                                        const char *hmac,
  *                                        unsigned char *key,
- *                                        SilcUInt32 key_len,
- *                                        SilcBool generate_key,
- *                                        SilcBool responder);
+ *                                        SilcUInt32 key_len);
  *
  * DESCRIPTION
  *
- *    Adds private message key to the client library. The key will be used to
- *    encrypt all private message between the client and the remote client
- *    indicated by the `client_entry'. If the `key' is NULL and the boolean
- *    value `generate_key' is TRUE the library will generate random key.
- *    The `key' maybe for example pre-shared-key, passphrase or similar.
- *    The `cipher' and `hmac' MAY be provided but SHOULD be NULL to assure
- *    that the requirements of the SILC protocol are met. The API, however,
- *    allows to allocate any cipher and HMAC.
+ *    Adds a static private message key to the client library.  The key
+ *    will be used to encrypt all private message between the client and
+ *    the remote client indicated by the `client_entry'.  The `key' can
+ *    be for example a pre-shared-key, passphrase or similar shared secret
+ *    string.  The `cipher' and `hmac' MAY be provided but SHOULD be NULL
+ *    to assure that the requirements of the SILC protocol are met. The
+ *    API, however, allows to allocate any cipher and HMAC.
  *
- *    If `responder' is TRUE then the sending and receiving keys will be
- *    set according the client being the receiver of the private key.  If
- *    FALSE the client is being the sender (or negotiator) of the private
- *    key.
+ *    If the private message key is added to client without first receiving
+ *    a request for it from the remote `client_entry' this function will
+ *    send the request to `client_entry'.  Note that, the actual key is
+ *    not sent to the network.
  *
  *    It is not necessary to set key for normal private message usage. If the
  *    key is not set then the private messages are encrypted using normal
- *    session keys. Setting the private key, however, increases the security.
+ *    session keys.  Setting the private key, however, increases the security.
  *
  *    Returns FALSE if the key is already set for the `client_entry', TRUE
  *    otherwise.
@@ -1617,9 +1544,7 @@ SilcBool silc_client_add_private_message_key(SilcClient client,
                                             const char *cipher,
                                             const char *hmac,
                                             unsigned char *key,
-                                            SilcUInt32 key_len,
-                                            SilcBool generate_key,
-                                            SilcBool responder);
+                                            SilcUInt32 key_len);
 
 /****f* silcclient/SilcClientAPI/silc_client_add_private_message_key_ske
  *
@@ -1636,9 +1561,9 @@ SilcBool silc_client_add_private_message_key(SilcClient client,
  * DESCRIPTION
  *
  *    Same as silc_client_add_private_message_key but takes the key material
- *    from the SKE key material structure. This structure is received if
+ *    from the SKE key material structure.  This structure is received if
  *    the application uses the silc_client_send_key_agreement to negotiate
- *    the key material. The `cipher' and `hmac' SHOULD be provided as it is
+ *    the key material.  The `cipher' and `hmac' SHOULD be provided as it is
  *    negotiated also in the SKE protocol.
  *
  ***/
@@ -1647,8 +1572,7 @@ SilcBool silc_client_add_private_message_key_ske(SilcClient client,
                                                 SilcClientEntry client_entry,
                                                 const char *cipher,
                                                 const char *hmac,
-                                                SilcSKEKeyMaterial key,
-                                                SilcBool responder);
+                                                SilcSKEKeyMaterial key);
 
 /****f* silcclient/SilcClientAPI/silc_client_del_private_message_key
  *
@@ -1694,40 +1618,6 @@ silc_client_list_private_message_keys(SilcClient client,
                                      SilcClientConnection conn,
                                      SilcUInt32 *key_count);
 
-/****f* silcclient/SilcClientAPI/silc_client_send_private_message_key_request
- *
- * SYNOPSIS
- *
- *    SilcBool
- *    silc_client_send_private_message_key_request(SilcClient client,
- *                                               SilcClientConnection conn,
- *                                               SilcClientEntry client_entry);
- *
- * DESCRIPTION
- *
- *    This function can be used to send an private message key indicator
- *    request to the remote client indicated by 'client_entry'.  This can
- *    be used when setting a static or pre-shared private message key.
- *    The sender of this packet is the initiator and must set the 'responder'
- *    argument in silc_client_add_private_message_key function to FALSE.
- *    The receiver of this indicator request must set it to TRUE, if the
- *    receiver decides to set a private message key.  By using this
- *    function applications may automate initiator/responder setting in
- *    private message key functions, without asking from user which one is
- *    the initiator and which one is responder.
- *
- * NOTES
- *
- *    The sender of this packet must set the private message key for
- *    'client_entry' before calling this function.  The 'responder'
- *    argument MUST be set to FALSE when setting the key.
- *
- ***/
-SilcBool
-silc_client_send_private_message_key_request(SilcClient client,
-                                            SilcClientConnection conn,
-                                            SilcClientEntry client_entry);
-
 /****f* silcclient/SilcClientAPI/silc_client_free_private_message_keys
  *
  * SYNOPSIS
@@ -1745,8 +1635,7 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
                                           SilcUInt32 key_count);
 
 
-/* Channel private key management (client_channel.c,
-   SilcChannelPrivateKey is defined in idlist.h) */
+/* Channel private key management */
 
 /****f* silcclient/SilcClientAPI/silc_client_add_channel_private_key
  *
@@ -1854,41 +1743,23 @@ SilcBool silc_client_del_channel_private_key(SilcClient client,
  *
  * SYNOPSIS
  *
- *    SilcChannelPrivateKey *
+ *    SilcDList
  *    silc_client_list_channel_private_keys(SilcClient client,
  *                                          SilcClientConnection conn,
- *                                          SilcChannelEntry channel,
- *                                          SilcUInt32 *key_count);
- *
- * DESCRIPTION
- *
- *    Returns array (pointers) of private keys associated to the `channel'.
- *    The caller must free the array by calling the function
- *    silc_client_free_channel_private_keys. The pointers in the array may be
- *    used to delete the specific key by giving the pointer as argument to the
- *    function silc_client_del_channel_private_key.
- *
- ***/
-SilcChannelPrivateKey *
-silc_client_list_channel_private_keys(SilcClient client,
-                                     SilcClientConnection conn,
-                                     SilcChannelEntry channel,
-                                     SilcUInt32 *key_count);
-
-/****f* silcclient/SilcClientAPI/silc_client_free_channel_private_keys
- *
- * SYNOPSIS
- *
- *    void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
- *                                               SilcUInt32 key_count);
+ *                                          SilcChannelEntry channel);
  *
  * DESCRIPTION
  *
- *    Frees the SilcChannelPrivateKey array.
+ *    Returns list of private keys associated to the `channel'.  The caller
+ *    must free the returned list with silc_dlist_uninit.  The pointers in
+ *    the list may be used to delete the specific key by giving the pointer
+ *    as argument to the function silc_client_del_channel_private_key.  Each
+ *    entry in the list is SilcChannelPrivateKey.
  *
  ***/
-void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
-                                          SilcUInt32 key_count);
+SilcDList silc_client_list_channel_private_keys(SilcClient client,
+                                               SilcClientConnection conn,
+                                               SilcChannelEntry channel);
 
 /****f* silcclient/SilcClientAPI/silc_client_current_channel_private_key
  *
@@ -1912,7 +1783,7 @@ void silc_client_current_channel_private_key(SilcClient client,
                                             SilcChannelPrivateKey key);
 
 
-/* Key Agreement routines (client_keyagr.c) */
+/* Key Agreement routines */
 
 /****f* silcclient/SilcClientAPI/silc_client_send_key_agreement
  *
@@ -1921,62 +1792,63 @@ void silc_client_current_channel_private_key(SilcClient client,
  *    void silc_client_send_key_agreement(SilcClient client,
  *                                        SilcClientConnection conn,
  *                                        SilcClientEntry client_entry,
- *                                        char *hostname,
- *                                        int port,
- *                                        SilcUInt32 timeout_secs,
+ *                                        SilcClientConnectionParams *params,
+ *                                        SilcPublicKey public_key,
+ *                                        SilcPrivateKey private_key,
  *                                        SilcKeyAgreementCallback completion,
  *                                        void *context);
  *
  * DESCRIPTION
  *
  *    Sends key agreement request to the remote client indicated by the
- *    `client_entry'. If the caller provides the `hostname' and the `port'
- *    arguments then the library will bind the client to that hostname and
- *    that port for the key agreement protocol. It also sends the `hostname'
- *    and the `port' in the key agreement packet to the remote client. This
- *    would indicate that the remote client may initiate the key agreement
- *    protocol to the `hostname' on the `port'.  If port is zero then the
- *    bound port is undefined (the operating system defines it).
- *
- *    If the `hostname' and `port' is not provided then empty key agreement
- *    packet is sent to the remote client. The remote client may reply with
- *    the same packet including its hostname and port. If the library receives
- *    the reply from the remote client the `key_agreement' client operation
- *    callback will be called to verify whether the user wants to perform the
- *    key agreement or not.
- *
- * NOTES
- *
- *    NOTE: If the application provided the `hostname' and the `port' and the
- *    remote side initiates the key agreement protocol it is not verified
- *    from the user anymore whether the protocol should be executed or not.
- *    By setting the `hostname' and `port' the user gives permission to
- *    perform the protocol (we are responder in this case).
+ *    `client_entry'.
+ *
+ *    If `params' is non-NULL and it has the `local_ip' and `local_port' set
+ *    the caller will provide the connection endpoint for the key agreement
+ *    connection.  The `bind_ip' can be used to bind to that IP instead of
+ *    `local_ip'.  If the `udp' is set to TRUE the connection will be UDP
+ *    instead of TCP.  Caller may also set the `repository', `verify_notfound'
+ *    and `timeout_secs' fields in `params'.  Other fields are ignored.
+ *    If `params' is NULL, then the `client_entry' is expected to provide
+ *    the connection endpoint for us.  It is recommended the `timeout_secs'
+ *    is specified in case the remote client does not reply anything to
+ *    the request.
+ *
+ *    The `public_key' and `private_key' is our identity in the key agreement.
+ *
+ *    In case we do not provide the connection endpoint, we will receive
+ *    the `key_agreement' client operation when the remote send its own
+ *    key agreement request packet.  We may then there start the key
+ *    agreement with silc_client_perform_key_agreement.  If we provided the
+ *    the connection endpoint, the client operation will not be called.
+ *
+ *    There can be only one active key agreement for `client_entry'.  Old
+ *    key agreement may be aborted by calling silc_client_abort_key_agreement.
  *
- *    NOTE: If the remote side decides not to initiate the key agreement
- *    or decides not to reply with the key agreement packet then we cannot
- *    perform the key agreement at all. If the key agreement protocol is
- *    performed the `completion' callback with the `context' will be called.
- *    If remote side decides to ignore the request the `completion' will be
- *    called after the specified timeout, `timeout_secs'.
- *
- *    NOTE: If the `hostname' and the `port' was not provided the `completion'
- *    will not be called at all since this does nothing more than sending
- *    a packet to the remote host.
+ * EXAMPLE
  *
- *    NOTE: There can be only one active key agreement for one client entry.
- *    Before setting new one, the old one must be finished (it is finished
- *    after calling the completion callback) or the function
- *    silc_client_abort_key_agreement must be called.
+ *    // Send key agreement request (we don't provide connection endpoint)
+ *    silc_client_send_key_agreement(client, conn, remote_client,
+ *                                   NULL, public_key, private_key,
+ *                                   my_keyagr_completion, my_context);
+ *
+ *    // Another example where we provide connection endpoint (TCP).
+ *    SilcClientConnectionParams params;
+ *    memset(&params, 0, sizeof(params));
+ *    params.local_ip = local_ip;
+ *    params.local_port = local_port;
+ *    params.timeout_secs = 60;
+ *    silc_client_send_key_agreement(client, conn, remote_client,
+ *                                   &params, public_key, private_key,
+ *                                   my_keyagr_completion, my_context);
  *
  ***/
 void silc_client_send_key_agreement(SilcClient client,
                                    SilcClientConnection conn,
                                    SilcClientEntry client_entry,
-                                   const char *hostname,
-                                   const char *bindhost,
-                                   int port,
-                                   SilcUInt32 timeout_secs,
+                                   SilcClientConnectionParams *params,
+                                   SilcPublicKey public_key,
+                                   SilcPrivateKey private_key,
                                    SilcKeyAgreementCallback completion,
                                    void *context);
 
@@ -1988,72 +1860,69 @@ void silc_client_send_key_agreement(SilcClient client,
  *    silc_client_perform_key_agreement(SilcClient client,
  *                                      SilcClientConnection conn,
  *                                      SilcClientEntry client_entry,
- *                                      char *hostname,
- *                                      int port,
+ *                                      SilcClientConnectionParams *params,
+ *                                      SilcPublicKey public_key,
+ *                                      SilcPrivateKey private_key,
+ *                                      char *hostname, int port,
  *                                      SilcKeyAgreementCallback completion,
  *                                      void *context);
  *
  * DESCRIPTION
  *
- *    Performs the actual key agreement protocol. Application may use this
- *    to initiate the key agreement protocol. This can be called for example
- *    after the application has received the `key_agreement' client operation,
- *    and did not return TRUE from it.
+ *    Performs the key agreement protocol.  Application may use this to
+ *    initiate the key agreement protocol.  Usually this is called after
+ *    receiving the `key_agreement' client operation.
  *
  *    The `hostname' is the remote hostname (or IP address) and the `port'
- *    is the remote port. The `completion' callback with the `context' will
+ *    is the remote port.  The `completion' callback with the `context' will
  *    be called after the key agreement protocol.
  *
- * NOTES
- *
- *    NOTE: If the application returns TRUE in the `key_agreement' client
- *    operation the library will automatically start the key agreement. In this
- *    case the application must not call this function. However, application
- *    may choose to just ignore the `key_agreement' client operation (and
- *    merely just print information about it on the screen) and call this
- *    function when the user whishes to do so (by, for example, giving some
- *    specific command). Thus, the API provides both, automatic and manual
- *    initiation of the key agreement. Calling this function is the manual
- *    initiation and returning TRUE in the `key_agreement' client operation
- *    is the automatic initiation.
+ *    The `params' is connection parameters and it may be used to define
+ *    the key agreement connection related parameters.  It may be NULL.
  *
  ***/
 void silc_client_perform_key_agreement(SilcClient client,
                                       SilcClientConnection conn,
                                       SilcClientEntry client_entry,
-                                      char *hostname,
-                                      int port,
+                                      SilcClientConnectionParams *params,
+                                      SilcPublicKey public_key,
+                                      SilcPrivateKey private_key,
+                                      char *hostname, int port,
                                       SilcKeyAgreementCallback completion,
                                       void *context);
 
-/****f* silcclient/SilcClientAPI/silc_client_perform_key_agreement_fd
+/****f* silcclient/SilcClientAPI/silc_client_perform_key_agreement_stream
  *
  * SYNOPSIS
  *
  *    void
- *    silc_client_perform_key_agreement_fd(SilcClient client,
- *                                         SilcClientConnection conn,
- *                                         SilcClientEntry client_entry,
- *                                         int sock,
- *                                         char *hostname,
- *                                         SilcKeyAgreementCallback completion,
- *                                         void *context);
+ *    silc_client_perform_key_agreement_stream(
+ *                                      SilcClient client,
+ *                                      SilcClientConnection conn,
+ *                                      SilcClientEntry client_entry,
+ *                                      SilcClientConnectionParams *params,
+ *                                      SilcPublicKey public_key,
+ *                                      SilcPrivateKey private_key,
+ *                                      SilcStream stream,
+ *                                      SilcKeyAgreementCallback completion,
+ *                                      void *context);
  *
  * DESCRIPTION
  *
- *    Same as above but application has created already the connection to
- *    the remote host. The `sock' is the socket to the remote connection.
- *    Application can use this function if it does not want the client library
- *    to create the connection.
+ *    Same as silc_client_perform_key_agreement but the caller has created
+ *    the connection.  The `stream' is the created connection.
  *
  ***/
-void silc_client_perform_key_agreement_fd(SilcClient client,
-                                         SilcClientConnection conn,
-                                         SilcClientEntry client_entry,
-                                         int sock,
-                                         char *hostname,
-                                         SilcKeyAgreementCallback completion,
-                                         void *context);
+void
+silc_client_perform_key_agreement_stream(SilcClient client,
+                                        SilcClientConnection conn,
+                                        SilcClientEntry client_entry,
+                                        SilcClientConnectionParams *params,
+                                        SilcPublicKey public_key,
+                                        SilcPrivateKey private_key,
+                                        SilcStream stream,
+                                        SilcKeyAgreementCallback completion,
+                                        void *context);
 
 /****f* silcclient/SilcClientAPI/silc_client_abort_key_agreement
  *
@@ -2085,9 +1954,9 @@ void silc_client_abort_key_agreement(SilcClient client,
  *
  * SYNOPSIS
  *
- *    void silc_client_set_away_message(SilcClient client,
- *                                      SilcClientConnection conn,
- *                                      char *message);
+ *    SilcBool silc_client_set_away_message(SilcClient client,
+ *                                          SilcClientConnection conn,
+ *                                          char *message);
  *
  * DESCRIPTION
  *
@@ -2097,62 +1966,13 @@ void silc_client_abort_key_agreement(SilcClient client,
  *    automatically back to the the client who send private message.  If
  *    away message is already set this replaces the old message with the
  *    new one.  If `message' is NULL the old away message is removed.
- *    The sender may freely free the memory of the `message'.
- *
- ***/
-void silc_client_set_away_message(SilcClient client,
-                                 SilcClientConnection conn,
-                                 char *message);
-
-/****f* silcclient/SilcClientAPI/SilcConnectionAuthRequest
- *
- * SYNOPSIS
- *
- *    typedef void (*SilcConnectionAuthRequest)(SilcClient client,
- *                                              SilcClientConnection conn,
- *                                              SilcAuthMethod auth_meth,
- *                                              void *context);
- *
- * DESCRIPTION
- *
- *    Connection authentication method request callback. This is called
- *    by the client library after it has received the authentication method
- *    that the application requested by calling the function
- *    silc_client_request_authentication_method.
- *
- ***/
-typedef void (*SilcConnectionAuthRequest)(SilcClient client,
-                                         SilcClientConnection conn,
-                                         SilcAuthMethod auth_meth,
-                                         void *context);
-
-/****f* silcclient/SilcClientAPI/silc_client_request_authentication_method
- *
- * SYNOPSIS
- *
- *    void
- *    silc_client_request_authentication_method(SilcClient client,
- *                                              SilcClientConnection conn,
- *                                              SilcConnectionAuthRequest
- *                                                callback,
- *                                              void *context);
- *
- * DESCRIPTION
- *
- *    This function can be used to request the current authentication method
- *    from the server. This may be called when connecting to the server
- *    and the client library requests the authentication data from the
- *    application. If the application does not know the current authentication
- *    method it can request it from the server using this function.
- *    The `callback' with `context' will be called after the server has
- *    replied back with the current authentication method.
+ *    The sender may freely free the memory of the `message'.  Returns
+ *    FALSE on error.
  *
  ***/
-void
-silc_client_request_authentication_method(SilcClient client,
-                                         SilcClientConnection conn,
-                                         SilcConnectionAuthRequest callback,
-                                         void *context);
+SilcBool silc_client_set_away_message(SilcClient client,
+                                     SilcClientConnection conn,
+                                     char *message);
 
 /****d* silcclient/SilcClientAPI/SilcClientMonitorStatus
  *
@@ -2334,13 +2154,12 @@ typedef void (*SilcClientFileAskName)(SilcClient client,
  ***/
 SilcClientFileError
 silc_client_file_send(SilcClient client,
-                     SilcClientConnection conn,
+                     SilcClientEntry client_entry,
+                     SilcClientConnectionParams *params,
+                     SilcPublicKey public_key,
+                     SilcPrivateKey private_key,
                      SilcClientFileMonitor monitor,
                      void *monitor_context,
-                     const char *local_ip,
-                     SilcUInt32 local_port,
-                     SilcBool do_not_bind,
-                     SilcClientEntry client_entry,
                      const char *filepath,
                      SilcUInt32 *session_id);
 
@@ -2524,6 +2343,41 @@ SilcHashTable silc_client_attributes_get(SilcClient client,
  ***/
 SilcBuffer silc_client_attributes_request(SilcAttribute attribute, ...);
 
+/****f* silcclient/SilcClientAPI/silc_client_nickname_format
+ *
+ * SYNOPSIS
+ *
+ *    SilcClientEntry
+ *    silc_client_nickname_format(SilcClient client,
+ *                                SilcClientConnection conn,
+ *                                SilcClientEntry client_entry,
+ *                                SilcBool priority);
+ *
+ * DESCRIPTION
+ *
+ *    Formats the nickname of `client_entry' according to the nickname
+ *    formatting rules set in SilcClientParams.  If the `priority' is TRUE
+ *    then the `client_entry' will always get the unformatted nickname.
+ *    If FALSE and there are more than one same nicknames in the client
+ *    the nickname will be formatted.
+ *
+ *    This returns NULL on error.  Otherwise, the client entry that was
+ *    formatted is returned.  If `priority' is FALSE this always returns
+ *    the `client_entry'.  If it is TRUE, this may return the client entry
+ *    that was formatted after giving the `client_entry' the unformatted
+ *    nickname.
+ *
+ *    Usually application does not need to call this function, as the library
+ *    automatically formats nicknames.  However, if application wants to
+ *    for example force the `client_entry' to always have the unformatted
+ *    nickname it may call this function to do so.
+ *
+ ***/
+SilcClientEntry silc_client_nickname_format(SilcClient client,
+                                           SilcClientConnection conn,
+                                           SilcClientEntry client_entry,
+                                           SilcBool priority);
+
 #ifdef __cplusplus
 }
 #endif