Call the connection callback in disconnection always as the last
authorPekka Riikonen <priikone@silcnet.org>
Thu, 25 Jan 2007 17:41:32 +0000 (17:41 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 25 Jan 2007 17:41:32 +0000 (17:41 +0000)
callback.  No other callbacks may be called after that.

lib/Makefile.ad
lib/silcclient/client.c
lib/silcclient/client_connect.c
lib/silcclient/client_internal.h
lib/silcclient/client_register.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/silcclient.h
lib/silcutil/silcfileutil.c

index 7aebc90088bfec5b953dc8d1469739c1162533c3..96d83d427dc834bf7c1cb4a59b38915dc57fcee1 100644 (file)
@@ -71,7 +71,8 @@ remove:
        -rm -f libsilcclient.a
        -rm -f libsilcserver.a
 
-all:   remove $(SILCLIB) $(SILCSERVERLIB) $(SILCCLIENTLIB)
+all:
+       $(MAKE) remove $(SILCLIB) $(SILCSERVERLIB) $(SILCCLIENTLIB)
 
 #ifdef SILC_DIST_TOOLKIT
 install-exec-hook:
index 98424f427bd0dcef0d737b6ef9ac1f8250cab342..f52ff134d72d7d6223284e02c7480d6aaa6a5f44 100644 (file)
@@ -132,17 +132,11 @@ static void silc_client_packet_eos(SilcPacketEngine engine,
                                   void *stream_context)
 {
   SilcClientConnection conn = stream_context;
-  SilcClient client = conn->client;
 
   SILC_LOG_DEBUG(("Remote disconnected connection"));
 
-  /* Call connection callback */
-  if (!conn->internal->callback_called)
-    conn->callback(client, conn, SILC_CLIENT_CONN_DISCONNECTED, 0, NULL,
-                  conn->callback_context);
-  conn->internal->callback_called = TRUE;
-
   /* Signal to close connection */
+  conn->internal->status = SILC_CLIENT_CONN_DISCONNECTED;
   if (!conn->internal->disconnected) {
     conn->internal->disconnected = TRUE;
     SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
@@ -184,6 +178,9 @@ static void silc_client_connect_abort(SilcAsyncOperation op, void *context)
 
   SILC_LOG_DEBUG(("Connection %p aborted by application", conn));
 
+  /* Connection callback will not be called after user aborted connecting */
+  conn->callback = NULL;
+
   /* Signal to close connection */
   if (!conn->internal->disconnected) {
     conn->internal->disconnected = TRUE;
@@ -379,8 +376,8 @@ SILC_FSM_STATE(silc_client_connection_st_packet)
 
 /* Disconnection event to close remote connection.  We close the connection
    and finish the connection machine in this state.  The connection context
-   is deleted in the machine destructor.  The connection callback must be
-   already called back to application before getting here. */
+   is deleted in the machine destructor.  The connection callback is called
+   in this state if it set. */
 
 SILC_FSM_STATE(silc_client_connection_st_close)
 {
@@ -418,6 +415,13 @@ SILC_FSM_STATE(silc_client_connection_st_close)
     return SILC_FSM_YIELD;
   }
 
+  /* Call the connection callback */
+  if (conn->callback)
+    conn->callback(conn->client, conn, conn->internal->status,
+                  conn->internal->error, conn->internal->disconnect_message,
+                  conn->callback_context);
+  silc_free(conn->internal->disconnect_message);
+
   SILC_LOG_DEBUG(("Closing remote connection"));
 
   /* Close connection */
@@ -453,7 +457,6 @@ SILC_FSM_STATE(silc_client_error)
 SILC_FSM_STATE(silc_client_disconnect)
 {
   SilcClientConnection conn = fsm_context;
-  SilcClient client = conn->client;
   SilcPacket packet = state_context;
   SilcStatus status;
   char *message = NULL;
@@ -475,13 +478,9 @@ SILC_FSM_STATE(silc_client_disconnect)
                          silc_buffer_len(&packet->buffer));
 
   /* Call connection callback */
-  if (!conn->internal->callback_called)
-    conn->callback(client, conn, SILC_CLIENT_CONN_DISCONNECTED, status,
-                  message, conn->callback_context);
-  conn->internal->callback_called = TRUE;
-
-  silc_free(message);
-  silc_packet_free(packet);
+  conn->internal->status = SILC_CLIENT_CONN_DISCONNECTED;
+  conn->internal->error = status;
+  conn->internal->disconnect_message = message;
 
   /* Signal to close connection */
   if (!conn->internal->disconnected) {
@@ -489,6 +488,8 @@ SILC_FSM_STATE(silc_client_disconnect)
     SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
   }
 
+  silc_packet_free(packet);
+
   return SILC_FSM_FINISH;
 }
 
index 87dfe8550fbd4280fd223668419362d472ee191a..78e24c60189ce2bbdb3aa0dd4f50c93d6f8e6c14 100644 (file)
@@ -79,8 +79,7 @@ static void silc_client_connect_callback(SilcNetStatus status,
   if (status != SILC_NET_OK) {
     /* Notify application of failure */
     SILC_LOG_DEBUG(("Connecting failed"));
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0,
-                  NULL, conn->callback_context);
+    conn->internal->status = SILC_CLIENT_CONN_ERROR;
     silc_fsm_next(fsm, silc_client_st_connect_error);
     SILC_FSM_CALL_CONTINUE(fsm);
     return;
@@ -176,9 +175,8 @@ static void silc_client_ke_completion(SilcSKE ske,
                                 conn->remote_host,
                                 silc_ske_map_status(status));
 
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_KE, 0, NULL,
-                  conn->callback_context);
-
+    conn->internal->status = SILC_CLIENT_CONN_ERROR_KE;
+    conn->internal->error = status;
     silc_ske_free_rekey_material(rekey);
 
     silc_fsm_next(fsm, silc_client_st_connect_error);
@@ -200,9 +198,7 @@ static void silc_client_ke_completion(SilcSKE ske,
                       "Error during key exchange with %s: cannot use keys",
                       conn->remote_host);
 
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_KE, 0, NULL,
-                  conn->callback_context);
-
+    conn->internal->status = SILC_CLIENT_CONN_ERROR_KE;
     silc_ske_free_rekey_material(rekey);
 
     silc_fsm_next(fsm, silc_client_st_connect_error);
@@ -223,9 +219,7 @@ static void silc_client_ke_completion(SilcSKE ske,
                       "Error during key exchange with %s: cannot use keys",
                       conn->remote_host);
 
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_KE, 0, NULL,
-                  conn->callback_context);
-
+    conn->internal->status = SILC_CLIENT_CONN_ERROR_KE;
     silc_ske_free_rekey_material(rekey);
 
     silc_fsm_next(fsm, silc_client_st_connect_error);
@@ -314,8 +308,8 @@ static void silc_client_connect_auth_completion(SilcConnAuth connauth,
                        client, conn, SILC_CLIENT_MESSAGE_ERROR,
                        "Authentication failed");
 
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_AUTH, 0, NULL,
-                  conn->callback_context);
+    conn->internal->status = SILC_CLIENT_CONN_ERROR_AUTH;
+    conn->internal->error = SILC_STATUS_ERR_AUTH_FAILED;
     silc_fsm_next(fsm, silc_client_st_connect_error);
   }
 
@@ -365,12 +359,11 @@ SILC_FSM_STATE(silc_client_connect_auth_request)
 SILC_TASK_CALLBACK(silc_client_connect_timeout)
 {
   SilcClientConnection conn = context;
-  SilcClient client = conn->client;
 
   SILC_LOG_DEBUG(("Connection timeout"));
 
-  conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_TIMEOUT, 0, NULL,
-                conn->callback_context);
+  conn->internal->status = SILC_CLIENT_CONN_ERROR_TIMEOUT;
+  conn->internal->error = SILC_STATUS_ERR_TIMEDOUT;
 
   silc_fsm_next(&conn->internal->event_thread, silc_client_st_connect_error);
   silc_fsm_continue_sync(&conn->internal->event_thread);
@@ -381,7 +374,6 @@ SILC_TASK_CALLBACK(silc_client_connect_timeout)
 SILC_FSM_STATE(silc_client_st_connect)
 {
   SilcClientConnection conn = fsm_context;
-  SilcClient client = conn->client;
 
   SILC_LOG_DEBUG(("Connecting to %s:%d", conn->remote_host,
                  conn->remote_port));
@@ -401,8 +393,7 @@ SILC_FSM_STATE(silc_client_st_connect)
     if (!conn->internal->params.local_ip) {
       /** IP address not given */
       SILC_LOG_ERROR(("Local UDP IP address not specified"));
-      conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
-                    conn->callback_context);
+      conn->internal->status = SILC_CLIENT_CONN_ERROR;
       silc_fsm_next(fsm, silc_client_st_connect_error);
       return SILC_FSM_CONTINUE;
     }
@@ -448,8 +439,7 @@ SILC_FSM_STATE(silc_client_st_connect_set_stream)
   if (!conn->stream) {
     /** Cannot create packet stream */
     SILC_LOG_DEBUG(("Could not create packet stream"));
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
-                  conn->callback_context);
+    conn->internal->status = SILC_CLIENT_CONN_ERROR;
     silc_fsm_next(fsm, silc_client_st_connect_error);
     return SILC_FSM_CONTINUE;
   }
@@ -478,8 +468,7 @@ SILC_FSM_STATE(silc_client_st_connect_key_exchange)
                   conn->public_key, conn->private_key, fsm);
   if (!conn->internal->ske) {
     /** Out of memory */
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_KE, 0, NULL,
-                  conn->callback_context);
+    conn->internal->status = SILC_CLIENT_CONN_ERROR_KE;
     silc_fsm_next(fsm, silc_client_st_connect_error);
     return SILC_FSM_CONTINUE;
   }
@@ -520,7 +509,6 @@ SILC_FSM_STATE(silc_client_st_connect_key_exchange)
 SILC_FSM_STATE(silc_client_st_connect_setup_udp)
 {
   SilcClientConnection conn = fsm_context;
-  SilcClient client = conn->client;
   SilcStream stream, old;
   SilcSKESecurityProperties prop;
 
@@ -540,8 +528,7 @@ SILC_FSM_STATE(silc_client_st_connect_setup_udp)
                                conn->internal->schedule);
   if (!stream) {
     /** Cannot create UDP stream */
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
-                  conn->callback_context);
+    conn->internal->status = SILC_CLIENT_CONN_ERROR;
     silc_fsm_next(fsm, silc_client_st_connect_error);
     return SILC_FSM_CONTINUE;
   }
@@ -627,7 +614,6 @@ SILC_FSM_STATE(silc_client_st_connect_auth_data)
 SILC_FSM_STATE(silc_client_st_connect_auth_start)
 {
   SilcClientConnection conn = fsm_context;
-  SilcClient client = conn->client;
   SilcConnAuth connauth;
 
   SILC_LOG_DEBUG(("Starting connection authentication protocol"));
@@ -648,8 +634,8 @@ SILC_FSM_STATE(silc_client_st_connect_auth_start)
                                 conn->internal->params.rekey_secs);
   if (!connauth) {
     /** Out of memory */
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR_AUTH, 0, NULL,
-                  conn->callback_context);
+    conn->internal->status = SILC_CLIENT_CONN_ERROR_AUTH;
+    conn->internal->error = SILC_STATUS_ERR_AUTH_FAILED;
     silc_fsm_next(fsm, silc_client_st_connect_error);
     return SILC_FSM_CONTINUE;
   }
index da5bef0f4b13fb4c6a7e40a2817476880409cb98..91243d8f0564da73ad522eedad4bfbbcf41647a4 100644 (file)
@@ -143,6 +143,7 @@ struct SilcClientConnectionInternalStruct {
   SilcAsyncOperation op;                /* Protocols async operation */
   SilcAsyncOperation cop;               /* Async operation for application */
   SilcHashTable attrs;                  /* Configured user attributes */
+  char *disconnect_message;             /* Disconnection message */
 
   SilcIDCache client_cache;             /* Client entry cache */
   SilcIDCache channel_cache;            /* Channel entry cache */
@@ -151,6 +152,8 @@ struct SilcClientConnectionInternalStruct {
   SilcAtomic16 cmd_ident;               /* Current command identifier */
   SilcUInt8 retry_count;                /* Packet retry counter */
   SilcUInt8 retry_timer;                /* Packet retry timer */
+  SilcClientConnectionStatus status;    /* Connection callback status */
+  SilcStatus error;                     /* Connection callback error */
 
   /* Events */
   unsigned int connect            : 1;  /* Connect remote host */
@@ -162,7 +165,6 @@ struct SilcClientConnectionInternalStruct {
   unsigned int verbose            : 1;   /* Notify application */
   unsigned int registering        : 1;  /* Set when registering to network */
   unsigned int rekey_responder    : 1;   /* Set when rekeying as responder */
-  unsigned int callback_called    : 1;   /* Set when connect callback called */
   unsigned int auth_request       : 1;   /* Set when requesting auth method */
 
   SilcClientAway *away;
index ae5de0011b6243a6a15c5e4b042b6ae4eb0ff1a5..43e15e429768e7ad6eea6856da922f3a0e782c25 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2006 Pekka Riikonen
+  Copyright (C) 2006 - 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
@@ -251,22 +251,16 @@ SILC_FSM_STATE(silc_client_st_register_complete)
 SILC_FSM_STATE(silc_client_st_register_error)
 {
   SilcClientConnection conn = fsm_context;
-  SilcClient client = conn->client;
 
   SILC_LOG_DEBUG(("Error registering to network"));
 
   /* Signal to close connection */
+  conn->internal->status = SILC_CLIENT_CONN_ERROR;
   if (!conn->internal->disconnected) {
     conn->internal->disconnected = TRUE;
     SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
   }
 
-  /* Call connect callback */
-  if (conn->internal->callback_called)
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
-                  conn->callback_context);
-  conn->internal->callback_called = TRUE;
-
   silc_schedule_task_del_by_all(conn->internal->schedule, 0,
                                silc_client_connect_timeout, conn);
 
@@ -599,7 +593,6 @@ SILC_FSM_STATE(silc_client_st_resume_completed)
 SILC_FSM_STATE(silc_client_st_resume_error)
 {
   SilcClientConnection conn = fsm_context;
-  SilcClient client = conn->client;
   SilcClientResumeSession resume = state_context;
 
   if (conn->internal->disconnected) {
@@ -613,17 +606,12 @@ SILC_FSM_STATE(silc_client_st_resume_error)
   SILC_LOG_DEBUG(("Error resuming to network"));
 
   /* Signal to close connection */
+  conn->internal->status = SILC_CLIENT_CONN_ERROR;
   if (!conn->internal->disconnected) {
     conn->internal->disconnected = TRUE;
     SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
   }
 
-  /* Call connect callback */
-  if (conn->internal->callback_called)
-    conn->callback(client, conn, SILC_CLIENT_CONN_ERROR, 0, NULL,
-                  conn->callback_context);
-  conn->internal->callback_called = TRUE;
-
   silc_schedule_task_del_by_all(conn->internal->schedule, 0,
                                silc_client_connect_timeout, conn);
 
index 32d436ac10ff55c8ff833084659223c6afdf08fe..ade3e1b82702ff68d9ee4438378ac3c02d933893 100644 (file)
@@ -1082,20 +1082,14 @@ SILC_FSM_STATE(silc_client_command_quit_final)
 {
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
-  SilcClient client = conn->client;
 
   SILC_LOG_DEBUG(("Quitting"));
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
 
-  /* Call connection callback */
-  if (!conn->internal->callback_called)
-    conn->callback(client, conn, SILC_CLIENT_CONN_DISCONNECTED,
-                  0, NULL, conn->callback_context);
-  conn->internal->callback_called = TRUE;
-
   /* Signal to close connection */
+  conn->internal->status = SILC_CLIENT_CONN_DISCONNECTED;
   if (!conn->internal->disconnected) {
     conn->internal->disconnected = TRUE;
     SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
index a8411cc61c2b3faa4e33e469622231d540807cca..7d5a01e2f6f23d852c321228f428c61a82fd732d 100644 (file)
@@ -233,7 +233,7 @@ SILC_FSM_STATE(silc_client_command_reply_timeout)
   if (conn->internal->disconnected) {
     SILC_LOG_DEBUG(("Command %s canceled", silc_get_command_name(cmd->cmd)));
     silc_list_del(conn->internal->pending_commands, cmd);
-    if (!cmd->called && cmd->cmd != SILC_COMMAND_PING)
+    if (!cmd->called)
       ERROR_CALLBACK(SILC_STATUS_ERR_TIMEDOUT);
     return SILC_FSM_FINISH;
   }
index a6d246841142018282d93fe6f4b4a2e3f58c5b8c..dc4af8b4fca47c46c5aaef5542bc5b80c289628b 100644 (file)
@@ -135,7 +135,9 @@ typedef void (*SilcClientStopped)(SilcClient client, void *context);
  *    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
index 30b2a5e5ce2001df916e0a0ebb7b8f38a309af49..c57cc42beb0457ea33b07c1f317a80457e0fb010 100644 (file)
@@ -82,9 +82,9 @@ int silc_file_writefile(const char *filename, const char *buffer,
     return -1;
   }
 
-  silc_file_close(fd);
+  fsync(fd);
 
-  return 0;
+  return silc_file_close(fd);
 }
 
 /* Writes a buffer to the file.  If the file is created specific mode is
@@ -112,9 +112,9 @@ int silc_file_writefile_mode(const char *filename, const char *buffer,
     return -1;
   }
 
-  silc_file_close(fd);
+  fsync(fd);
 
-  return 0;
+  return silc_file_close(fd);
 }
 
 /* Reads a file to a buffer. The allocated buffer is returned. Length of