From 66b9316f5d654e08655def94f56cfe2898754361 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 25 Jan 2007 17:41:32 +0000 Subject: [PATCH] Call the connection callback in disconnection always as the last callback. No other callbacks may be called after that. --- lib/Makefile.ad | 3 ++- lib/silcclient/client.c | 35 +++++++++++++------------ lib/silcclient/client_connect.c | 44 +++++++++++--------------------- lib/silcclient/client_internal.h | 4 ++- lib/silcclient/client_register.c | 18 +++---------- lib/silcclient/command.c | 8 +----- lib/silcclient/command_reply.c | 2 +- lib/silcclient/silcclient.h | 4 ++- lib/silcutil/silcfileutil.c | 8 +++--- 9 files changed, 50 insertions(+), 76 deletions(-) diff --git a/lib/Makefile.ad b/lib/Makefile.ad index 7aebc900..96d83d42 100644 --- a/lib/Makefile.ad +++ b/lib/Makefile.ad @@ -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: diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 98424f42..f52ff134 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -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; } diff --git a/lib/silcclient/client_connect.c b/lib/silcclient/client_connect.c index 87dfe855..78e24c60 100644 --- a/lib/silcclient/client_connect.c +++ b/lib/silcclient/client_connect.c @@ -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; } diff --git a/lib/silcclient/client_internal.h b/lib/silcclient/client_internal.h index da5bef0f..91243d8f 100644 --- a/lib/silcclient/client_internal.h +++ b/lib/silcclient/client_internal.h @@ -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; diff --git a/lib/silcclient/client_register.c b/lib/silcclient/client_register.c index ae5de001..43e15e42 100644 --- a/lib/silcclient/client_register.c +++ b/lib/silcclient/client_register.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - 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); diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 32d436ac..ade3e1b8 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -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); diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index a8411cc6..7d5a01e2 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -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; } diff --git a/lib/silcclient/silcclient.h b/lib/silcclient/silcclient.h index a6d24684..dc4af8b4 100644 --- a/lib/silcclient/silcclient.h +++ b/lib/silcclient/silcclient.h @@ -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 diff --git a/lib/silcutil/silcfileutil.c b/lib/silcutil/silcfileutil.c index 30b2a5e5..c57cc42b 100644 --- a/lib/silcutil/silcfileutil.c +++ b/lib/silcutil/silcfileutil.c @@ -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 -- 2.24.0