Targeted say-operation messages
[silc.git] / lib / silcclient / client.c
index 37f757fe77baf17414557223490bb39c3aefe4ec..38afc4537e297fb61f6ad6f1b88cc85c32571286 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2007 Pekka Riikonen
+  Copyright (C) 1997 - 2014 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
@@ -22,9 +22,6 @@
 #include "silcclient.h"
 #include "client_internal.h"
 
-/************************** Types and definitions ***************************/
-
-
 /************************ Static utility functions **************************/
 
 /* Connection machine FSM destructor.  This will finish the thread where
@@ -42,7 +39,8 @@ static void silc_client_connection_destructor(SilcFSM fsm,
   /* Delete connection */
   silc_client_del_connection(conn->client, conn);
 
-  /* Finish the thread were this machine was running */
+  /* Finish the thread were this machine was running.  Its destructor is the
+     silc_client_connection_finished. */
   silc_fsm_finish(thread);
 }
 
@@ -57,7 +55,7 @@ static void silc_client_connection_finished(SilcFSMThread fsm,
   SilcClient client = silc_fsm_get_state_context(fsm);
 
   /* Signal client that we have finished */
-  silc_atomic_sub_int16(&client->internal->conns, 1);
+  silc_atomic_sub_int32(&client->internal->conns, 1);
   client->internal->connection_closed = TRUE;
   SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
 
@@ -454,7 +452,7 @@ SILC_FSM_STATE(silc_client_error)
   msg = silc_memdup(silc_buffer_data(&packet->buffer),
                    silc_buffer_len(&packet->buffer));
   if (msg)
-    client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, msg);
+    client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, msg);
 
   silc_free(msg);
   silc_packet_free(packet);
@@ -517,11 +515,13 @@ SILC_FSM_STATE(silc_client_st_run)
 
   /* Process events */
 
-  if (client->internal->run_callback && client->internal->running) {
+  if (client->internal->run_callback) {
     /* Call running callbcak back to application */
-    SILC_LOG_DEBUG(("We are up, call running callback"));
     client->internal->run_callback = FALSE;
-    client->internal->running(client, client->internal->running_context);
+    if (client->internal->running) {
+      SILC_LOG_DEBUG(("We are up, call running callback"));
+      client->internal->running(client, client->internal->running_context);
+    }
     return SILC_FSM_CONTINUE;
   }
 
@@ -529,7 +529,7 @@ SILC_FSM_STATE(silc_client_st_run)
     /* A connection finished */
     SILC_LOG_DEBUG(("Event: connection closed"));
     client->internal->connection_closed = FALSE;
-    if (silc_atomic_get_int16(&client->internal->conns) == 0 &&
+    if (silc_atomic_get_int32(&client->internal->conns) == 0 &&
        client->internal->stop)
       SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
     return SILC_FSM_CONTINUE;
@@ -538,7 +538,7 @@ SILC_FSM_STATE(silc_client_st_run)
   if (client->internal->stop) {
     /* Stop client libarry.  If we have running connections, wait until
        they finish first. */
-    if (silc_atomic_get_int16(&client->internal->conns) == 0) {
+    if (silc_atomic_get_int32(&client->internal->conns) == 0) {
       SILC_LOG_DEBUG(("Event: stop"));
       silc_fsm_next(fsm, silc_client_st_stop);
     }
@@ -621,8 +621,10 @@ silc_client_add_connection(SilcClient client,
   }
 
   /* Set parameters */
-  if (params)
+  if (params) {
     conn->internal->params = *params;
+    conn->context = params->context;
+  }
   if (!conn->internal->params.rekey_secs)
     conn->internal->params.rekey_secs = 3600;
 #ifndef SILC_DIST_INPLACE
@@ -674,7 +676,7 @@ silc_client_add_connection(SilcClient client,
   silc_fsm_start(thread, silc_client_connection_st_start);
 
   SILC_LOG_DEBUG(("New connection %p", conn));
-  silc_atomic_add_int16(&client->internal->conns, 1);
+  silc_atomic_add_int32(&client->internal->conns, 1);
 
   return conn;
 }
@@ -769,8 +771,14 @@ silc_client_connect_to_server(SilcClient client,
 
   SILC_LOG_DEBUG(("Connecting to server"));
 
-  if (!client || !remote_host)
+  if (!client || !remote_host || !callback)
+    return NULL;
+
+  if (client->internal->run_callback) {
+    SILC_LOG_ERROR(("Client library is not started yet. SilcClientRunning "
+                   "callback has not been called yet."));
     return NULL;
+  }
 
   /* Add new connection */
   conn = silc_client_add_connection(client, SILC_CONN_SERVER, TRUE, params,
@@ -806,9 +814,15 @@ silc_client_connect_to_client(SilcClient client,
 
   SILC_LOG_DEBUG(("Connecting to client"));
 
-  if (!client || !remote_host)
+  if (!client || !remote_host || !callback)
     return NULL;
 
+  if (client->internal->run_callback) {
+    SILC_LOG_ERROR(("Client library is not started yet. SilcClientRunning "
+                   "callback has not been called yet."));
+    return NULL;
+  }
+
   if (params)
     params->no_authentication = TRUE;
 
@@ -845,8 +859,14 @@ silc_client_key_exchange(SilcClient client,
 
   SILC_LOG_DEBUG(("Performing key exchange"));
 
-  if (!client || !stream)
+  if (!client || !stream || !callback)
+    return NULL;
+
+  if (client->internal->run_callback) {
+    SILC_LOG_ERROR(("Client library is not started yet. SilcClientRunning "
+                   "callback has not been called yet."));
     return NULL;
+  }
 
   if (!silc_socket_stream_get_info(stream, NULL, &host, NULL, &port)) {
     SILC_LOG_ERROR(("Socket stream does not have remote host name set"));
@@ -920,7 +940,7 @@ SilcClient silc_client_alloc(SilcClientOperations *ops,
     nickname_format[sizeof(new_client->internal->
                           params->nickname_format) - 1] = 0;
 
-  silc_atomic_init16(&new_client->internal->conns, 0);
+  silc_atomic_init32(&new_client->internal->conns, 0);
 
   return new_client;
 }
@@ -929,7 +949,8 @@ SilcClient silc_client_alloc(SilcClientOperations *ops,
 
 void silc_client_free(SilcClient client)
 {
-  silc_schedule_uninit(client->schedule);
+  if (client->schedule)
+    silc_schedule_uninit(client->schedule);
 
   if (client->rng)
     silc_rng_free(client->rng);
@@ -941,10 +962,13 @@ void silc_client_free(SilcClient client)
     silc_hmac_unregister_all();
   }
 
-  silc_packet_engine_stop(client->internal->packet_engine);
-  silc_dlist_uninit(client->internal->ftp_sessions);
-  silc_atomic_uninit16(&client->internal->conns);
-  silc_mutex_free(client->internal->lock);
+  if (client->internal->packet_engine)
+    silc_packet_engine_stop(client->internal->packet_engine);
+  if (client->internal->ftp_sessions)
+    silc_dlist_uninit(client->internal->ftp_sessions);
+  if (client->internal->lock)
+    silc_mutex_free(client->internal->lock);
+  silc_atomic_uninit32(&client->internal->conns);
   silc_free(client->username);
   silc_free(client->hostname);
   silc_free(client->realname);
@@ -1081,6 +1105,12 @@ void silc_client_stop(SilcClient client, SilcClientStopped stopped,
 {
   SILC_LOG_DEBUG(("Stopping client"));
 
+  if (!silc_fsm_is_started(&client->internal->fsm)) {
+    SILC_LOG_WARNING(("Attempting to stop client library before it has been "
+                     "started (silc_client_init not called)"));
+    return;
+  }
+
   client->internal->running = (SilcClientRunning)stopped;
   client->internal->running_context = context;