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.
