X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient.c;h=3ab7ba17b4aa96fc872496dce38c17ae078227d7;hp=1d7884553696564c1dd8bca8477034cfc25760ce;hb=90e14dc985628e0b0f86e604d511039d302dc956;hpb=3c9b950049601eef814222c501114d6f2865b926 diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 1d788455..3ab7ba17 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -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); @@ -180,11 +178,16 @@ static void silc_client_connect_abort(SilcAsyncOperation op, void *context) /* Connection callback will not be called after user aborted connecting */ conn->callback = NULL; + conn->internal->cop = NULL; /* Signal to close connection */ if (!conn->internal->disconnected) { conn->internal->disconnected = TRUE; - SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event); + + /* If user aborts before connection machine is even up yet, then don't + send signal yet. It will process this event when it comes up. */ + if (silc_fsm_is_started(&conn->internal->fsm)) + SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event); } } @@ -208,7 +211,9 @@ SILC_FSM_STATE(silc_client_connection_st_start) silc_fsm_event_init(&conn->internal->wait_event, connfsm); silc_fsm_start_sync(connfsm, silc_client_connection_st_run); - /* Schedule any events set in initialization */ + /* Schedule any events possibly set in initialization */ + if (conn->internal->disconnected) + SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event); if (conn->internal->connect) SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event); if (conn->internal->key_exchange) @@ -233,6 +238,13 @@ SILC_FSM_STATE(silc_client_connection_st_run) /* Process events */ thread = &conn->internal->event_thread; + if (conn->internal->disconnected) { + /** Event: disconnected */ + SILC_LOG_DEBUG(("Event: disconnected")); + silc_fsm_next(fsm, silc_client_connection_st_close); + return SILC_FSM_YIELD; + } + if (conn->internal->connect) { SILC_LOG_DEBUG(("Event: connect")); conn->internal->connect = FALSE; @@ -269,13 +281,6 @@ SILC_FSM_STATE(silc_client_connection_st_run) return SILC_FSM_CONTINUE; } - if (conn->internal->disconnected) { - /** Event: disconnected */ - SILC_LOG_DEBUG(("Event: disconnected")); - silc_fsm_next(fsm, silc_client_connection_st_close); - return SILC_FSM_YIELD; - } - /* NOT REACHED */ SILC_ASSERT(FALSE); return SILC_FSM_CONTINUE; @@ -427,8 +432,9 @@ SILC_FSM_STATE(silc_client_connection_st_close) SILC_LOG_DEBUG(("Closing remote connection")); - /* Close connection */ - silc_packet_stream_destroy(conn->stream); + /* Close connection. */ + if (conn->stream) + silc_packet_stream_destroy(conn->stream); SILC_LOG_DEBUG(("Finishing connection machine")); return SILC_FSM_FINISH; @@ -509,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; } @@ -521,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; @@ -530,9 +538,10 @@ SILC_FSM_STATE(silc_client_st_run) if (client->internal->stop) { /* Stop client libarry. If we have running connections, wait until they finish first. */ - SILC_LOG_DEBUG(("Event: stop")); - 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); + } return SILC_FSM_CONTINUE; } @@ -665,7 +674,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; } @@ -763,6 +772,12 @@ silc_client_connect_to_server(SilcClient client, if (!client || !remote_host) 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, public_key, private_key, remote_host, @@ -800,6 +815,12 @@ silc_client_connect_to_client(SilcClient client, if (!client || !remote_host) 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; @@ -839,6 +860,12 @@ silc_client_key_exchange(SilcClient client, if (!client || !stream) 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")); callback(client, NULL, SILC_CLIENT_CONN_ERROR, 0, NULL, context); @@ -853,7 +880,7 @@ silc_client_key_exchange(SilcClient client, callback(client, NULL, SILC_CLIENT_CONN_ERROR, 0, NULL, context); return NULL; } - conn->stream = (void *)stream; + conn->internal->user_stream = stream; /* Signal connection to start key exchange */ conn->internal->key_exchange = TRUE; @@ -867,13 +894,6 @@ void silc_client_close_connection(SilcClient client, { SILC_LOG_DEBUG(("Closing connection %p", conn)); - /* If connection machine is not running, we just delete the connection */ - if (!silc_fsm_is_started(&conn->internal->fsm)) { - silc_packet_stream_destroy(conn->stream); - silc_client_del_connection(conn->client, conn); - return; - } - /* Signal to close connection */ conn->internal->status = SILC_CLIENT_CONN_DISCONNECTED; if (!conn->internal->disconnected) { @@ -918,7 +938,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; } @@ -927,7 +947,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); @@ -939,10 +960,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); @@ -1079,6 +1103,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;