Added SILC Thread Queue API
[crypto.git] / lib / silcclient / README
index 499298dbf9e8ce227046c144ac0892dc7e4fc086..7a475336b636ff7bdb2e546f0b0f04ae10d616e5 100644 (file)
-SILC Client Library
-===================
-
-This directory includes the SILC Client implementation.  The library uses
-common and core components of SILC protocol from lib/silccore library and
-normal utility routines from lib/silcutil library.  The library has been
-designed to be complete SILC Client implementation without actual user
-interface.  The library provides the API for the application which it can
-use to implement generally whatever user interface it wants.
-
-The `silcapi.h' file defines the function prototypes that application must
-implement in order to be able to create the user interface with the
-library.  The idea is that the application can implement whatever user
-interface routines in the functions and display the data whatever way
-it wants.  The library is entirely transparent to the user interface and
-it does not include any user interface specific issues such as window
-handling or item handling on the screen etc.  These does not interest
-the library.
-
-
-Creating Client
-===============
-
-The client is context or entity based (which ever) thus several client
-entitites can be created in the application if needed.  However, it should
-be noted that they are completely independent from each other and can
-be seen as different applications.  Usually only one client entity is
-needed per application.
-
-The client object is SilcClient which is usually allocated in following
-manner:
-
-       SilcClient client = silc_client_alloc(&ops, context);
-
-`ops' is the static structure of client operations that library will call.
-`context' can be some application specific context that will be saved into
-the SilcClient object.  It is up to the caller to free this context.
-SilcClient is always passed to the application thus the application specific
-context can be retrieved from the SilcClient object.  See `client.h' file
-for detailed definition of SilcClient object.
-
-`ops' can be defined for example as follows:
-
-SilcClientOperations ops = {
-  silc_say,
-  silc_channel_message,
-  silc_private_message,
-  silc_notify,
-  silc_command,
-  silc_command_reply,
-  silc_connect,
-  silc_disconnect,
-  silc_get_auth_method,
-  silc_verify_public_key,
-  silc_ask_passphrase,
-  silc_failure,
-  silc_key_agreement,
-};
-
-
-Initializing the Client
-=======================
-
-The client must be initialized before running.  However, there are also
-some other tasks that must be done before initializing the client.  Following
-pointers must be set before calling the initializing function:
-
-       client->username
-       client->hostname
-       client->realname
-       client->pkcs
-       client->public_key
-       client->private_key
-
-After setting the pointers one must call:
-
-       silc_client_init(client);
-
-which then initializes the client library for the `client'.  If the pointers
-mentioned above are not initialized the silc_client_init will fail.
-
-
-Running the Client
-==================
-
-The client is run by calling silc_client_run.  The function will call
-the scheduler from utility library that will be run until the program is
-ended.  When silc_client_run returns the application is ended.  Thus,
-to run the client, call:
-
-       silc_client_run(client);
-
-Usually application may do some other initializations before calling
-this function.  For example before calling this function application should
-initialize the user interface.
-
-
-Creating Connection to Server
-=============================
-
-Connection to remote SILC server is done by calling:
-
-       silc_client_connect_to_server(client, port, hostname, context);
-
-The function will create the connection asynchronously to the server, ie.
-the function will return before the actual connection is created.  After
-the connection is created the client->ops->connect operation is called.
-
-Generally speaking the connections are associated with windows' on the
-screen.  IRC is usually implemented this way, however it is not the necessary
-way to associate the client's connections.  SilcClientConnection object
-is provided by the library (and is always passed to the application) that
-can be used in the application to associate the connection from the library.
-Application specific context can be saved to the SilcClientConnection object
-which then can be retrieved in the application, thus perhaps associate
-the connection with what ever object in the application (window or something
-else).
-
-
-Using Own Connecting
-====================
-
-Application might not want to use silc_client_connect_to_server function
-if it wants to perform its own connecting for some reason.  In this case
-application must call function silc_client_start_key_exchange after it
-has created the connection by itself.  This function starts the key exhange
-protocol between the client and server and the library takes care of
-everything after that.
-
-After connection has been created application must call:
-
-       SilcClientConnection conn;
-
-       /* Add new connection to client */
-       conn = silc_client_add_connection(client, hostname, port, context);
-
-       /* Start key exchange and let the library handle everything
-          after this point on. */
-       silc_client_start_key_exchange(client, conn, sock);
-
-These calls are performed only and only if application did not call
-silc_client_connect_to_server function.
+During client library implementation, few things to keep in mind.
+
+Threads and locking in client library
+
+   The client library is multithreaded in so that the actual SilcClient
+   runs in one main thread (may be application main thread or its created
+   thread for the client), and each connection to a remote host runs in
+   an own thread.  There are no other threads in client library.  If there
+   is only one connection in the client, then most likely there is only
+   one thread in addition of main thread.
+
+   The SilcClient context must be protected with lock (client->internal->lock),
+   because it may be accessed from connection threads and by application.
+   It is guaranteed that the client main thread never access the connection
+   thread, and it is guaranteed that no other connection thread access
+   another connection thread.  Even still, the SilcClientConnection has
+   a lock (conn->internal->lock) because it may be accessed by application.
+
+   Practically everything in the client is executed in the connection thread.
+   Receiving packets, commands, notifys, etc all happen in connection thread.
+   It is not possible to receive packets in two different threads that would
+   be destined to one specific connection thread.  But, because packets and
+   commands may be sent from application thread the connection lock is
+   used to protect shared data in the SilcClientConnection.  It is, however,
+   guaranteed that the main client thread, or other connection thread will
+   not send any packets or commands to another connection.  When remembered
+   this makes programming easier.  Everything happens in one thread that
+   has something to do with the connection.  When packet is received and
+   it is processed asynchronously, it is always guaranteed that it is
+   processed in that same thread, even if it is processed asynchronously.
+   No other thread will process it.  If it is processed synchronously, no
+   other packet may arrive at the same time, not for that connection.
+   But it is possible that while we are processing incoming command reply,
+   application sends another command from application thread.  Because of
+   this, the lock exist in the connection context.
+
+
+Using locks
+
+   Use locking only if necessary.  For performance reasons SILC Atomic
+   Operations API should be preferred if it can be used to achieve what
+   needs to be achieved.  All reference counters must be atomic integers
+   and locking must not be used with them.
+
+
+Using FSM
+
+   The client library internals are to be rewritten with SILC FSM and all
+   major operations should be implemented as FSM.
+
+   Always return SILC_FSM_CONTINUE if you need to move to next state
+   synchronously.  Use SILC_FSM_YIELD if you are in FSM thread and
+   peformance is not an issue, but only if there really are other FSM
+   threads that need execution time also.
+
+
+When to use FSM event signalling?
+
+   FSM event signalling should be used only when multiple threads
+   (FSM threads) may be waiting for something to happen.  If only one thread
+   is waiting for something it should merely return SILC_FSM_WAIT and when
+   that something happens it should use silc_fsm_continue or
+   silc_fsm_continue_sync to continue in the waiting thread.  OTOH, if
+   multiple threads are waiting SILC_FSM_EVENT_SIGNAL is the only way to
+   deliver the signal.  Always remember that posting is signal is not
+   donbe synchronously (it won't be delivered immediately).
+
+   OTOH, if there is only one thread waiting for somtehing to happen but
+   there can be multiple threads signalling that something has happened
+   only way to do this is to use event signalling.
+
+   Event signals should be pre-allocated SilcFSMEventStruct structures
+   and for signalling use they are always initialized as:
+
+     silc_fsm_event_init(&event, fsm);
+
+   The call cannot fail.  Events need not be uninitialized and the same
+   context may be reused.
+
+Finishing threads when closing connection
+
+   When closing SilcClientConnection all threads must first be finished
+   before the connection machine is finished.  This is done by finishing
+   all running command threads.  That will also finish all waiting packet
+   and notify threads as they are always waiting for a command.  If any
+   thread is waiting for something else than a command (such as event
+   threads) they must be explicitly finished.  The threads are finished by
+   continuing them synchronously.  The threads will detect that we are
+   disconnected (see below).  SILC_FSM_YIELD must be returned in
+   st_close() as that gives the FSM scheduler time to finish the threads
+   first.  After that the machine can be finished.
+
+   Also, any thread that runs in SilcClientConnection machine must always
+   after returning from wait state to check if we are disconnected by doing
+
+     if (conn->internal->disconnected) {
+       xxx;
+       return SILC_FSM_FINISH;
+     }
+
+   If disconnected the thread must finish immediately by returning
+   SILC_FSM_FINISH.
+
+Entry locking
+
+   All entires have a read/write lock.  It is used to protect the entries
+   when library updates them at the same time application is reading data
+   from the entries.  An API for application to read-lock the entires
+   exist.  Library only needs to use write-lock.  Using read-lock is not
+   necessary inside library because all connection related stuff, including
+   updating connection related entries are done in one thread.  When library
+   is reading data from the entries it cannot be updating them at the same
+   time.  Hence, using read-lock inside library is not necessary.