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;
SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
/* Wait until this thread is terminated from the machine destructor */
- SILC_FSM_WAIT;
+ return SILC_FSM_WAIT;
}
/* Connection machine main state. This handles various connection related
silc_fsm_thread_init(thread, &conn->internal->fsm, conn,
NULL, NULL, FALSE);
silc_fsm_start_sync(thread, silc_client_st_connect);
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
if (conn->internal->key_exchange) {
silc_fsm_thread_init(thread, &conn->internal->fsm, conn,
NULL, NULL, FALSE);
silc_fsm_start_sync(thread, silc_client_st_connect_set_stream);
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
if (conn->internal->rekeying) {
silc_fsm_thread_init(thread, &conn->internal->fsm, conn,
NULL, NULL, FALSE);
silc_fsm_start_sync(thread, silc_client_st_rekey);
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
if (conn->internal->disconnected) {
/** Event: disconnected */
SILC_LOG_DEBUG(("Event: disconnected"));
silc_fsm_next(fsm, silc_client_connection_st_close);
- SILC_FSM_YIELD;
+ return SILC_FSM_YIELD;
}
/* NOT REACHED */
SILC_ASSERT(FALSE);
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
/* Packet processor thread. Each incoming packet is processed in FSM
SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
silc_packet_free(packet);
- SILC_FSM_FINISH;
+ return SILC_FSM_FINISH;
break;
default:
silc_packet_free(packet);
- SILC_FSM_FINISH;
+ return SILC_FSM_FINISH;
break;
}
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
/* 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)
{
}
/* Give threads time to finish */
- SILC_FSM_YIELD;
+ return SILC_FSM_YIELD;
}
/* Abort ongoing event */
if (silc_fsm_is_started(&conn->internal->event_thread)) {
SILC_LOG_DEBUG(("Finish event thread"));
silc_fsm_continue_sync(&conn->internal->event_thread);
- SILC_FSM_YIELD;
+ 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_packet_stream_destroy(conn->stream);
SILC_LOG_DEBUG(("Finishing connection machine"));
- SILC_FSM_FINISH;
+ return SILC_FSM_FINISH;
}
/* Received error packet from server. Send it to application. */
silc_free(msg);
silc_packet_free(packet);
- SILC_FSM_FINISH;
+ return SILC_FSM_FINISH;
}
/* Received disconnect packet from server. We close the connection and
SILC_FSM_STATE(silc_client_disconnect)
{
SilcClientConnection conn = fsm_context;
- SilcClient client = conn->client;
SilcPacket packet = state_context;
SilcStatus status;
char *message = NULL;
if (silc_buffer_len(&packet->buffer) < 1) {
silc_packet_free(packet);
- SILC_FSM_FINISH;
+ return SILC_FSM_FINISH;
}
status = (SilcStatus)packet->buffer.data[0];
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_FSM_FINISH;
+ silc_packet_free(packet);
+
+ return SILC_FSM_FINISH;
}
/*************************** Main client machine ****************************/
SILC_LOG_DEBUG(("We are up, call running callback"));
client->internal->run_callback = FALSE;
client->internal->running(client, client->internal->running_context);
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
if (client->internal->connection_closed) {
if (silc_atomic_get_int16(&client->internal->conns) == 0 &&
client->internal->stop)
SILC_FSM_EVENT_SIGNAL(&client->internal->wait_event);
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
if (client->internal->stop) {
SILC_LOG_DEBUG(("Event: stop"));
if (silc_atomic_get_int16(&client->internal->conns) == 0)
silc_fsm_next(fsm, silc_client_st_stop);
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
/* NOT REACHED */
SILC_ASSERT(FALSE);
- SILC_FSM_CONTINUE;
+ return SILC_FSM_CONTINUE;
}
/* Stop event. Stops the client library. */
if (client->internal->running)
client->internal->running(client, client->internal->running_context);
- SILC_FSM_FINISH;
+ return SILC_FSM_FINISH;
}
/******************************* Private API ********************************/
return NULL;
}
- conn->internal->ftp_sessions = silc_dlist_init();
+ // conn->internal->ftp_sessions = silc_dlist_init();
/* Initialize our async operation so that application may abort us
while we're connecting. */