callback. No other callbacks may be called after that.
-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:
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);
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;
/* 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)
{
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 */
SILC_FSM_STATE(silc_client_disconnect)
{
SilcClientConnection conn = fsm_context;
- SilcClient client = conn->client;
SilcPacket packet = state_context;
SilcStatus status;
char *message = NULL;
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) {
SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
}
+ silc_packet_free(packet);
+
return SILC_FSM_FINISH;
}
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;
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);
"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);
"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);
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);
}
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);
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));
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;
}
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;
}
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;
}
SILC_FSM_STATE(silc_client_st_connect_setup_udp)
{
SilcClientConnection conn = fsm_context;
- SilcClient client = conn->client;
SilcStream stream, old;
SilcSKESecurityProperties prop;
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;
}
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"));
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;
}
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 */
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 */
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;
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
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);
SILC_FSM_STATE(silc_client_st_resume_error)
{
SilcClientConnection conn = fsm_context;
- SilcClient client = conn->client;
SilcClientResumeSession resume = state_context;
if (conn->internal->disconnected) {
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);
{
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);
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;
}
* 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
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
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