From d4938a564e358e8072c30290305a68cef665eaa0 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sat, 11 Nov 2006 20:29:09 +0000 Subject: [PATCH] silc_client_unref_client fixes. --- lib/silcclient/client.c | 119 ++------------------------------- lib/silcclient/client_entry.c | 33 ++++----- lib/silcclient/client_prvmsg.c | 6 +- lib/silcclient/command.c | 16 ++--- lib/silcclient/command_reply.c | 34 ++++++++-- 5 files changed, 61 insertions(+), 147 deletions(-) diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 8834c272..7f29c4ad 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -38,7 +38,6 @@ static SilcBool silc_client_packet_receive(SilcPacketEngine engine, void *callback_context, void *stream_context) { - SilcClient client = callback_context; SilcClientConnection conn = stream_context; /* Packets we do not handle */ @@ -329,9 +328,10 @@ SILC_FSM_STATE(silc_client_new_id) goto out; /* Create local client entry */ - conn->local_entry = silc_client_add_client(client, conn, (client->nickname ? - client->nickname : - client->username), + conn->local_entry = silc_client_add_client(client, conn, + (client->nickname ? + client->nickname : + client->username), client->username, client->realname, &id.u.client_id, 0); @@ -1098,117 +1098,6 @@ static void silc_client_resume_session_cb(SilcClient client, } } -/* Processes the received new Client ID from server. Old Client ID is - deleted from cache and new one is added. */ - -void silc_client_receive_new_id(SilcClient client, - SilcClientConnection conn, - SilcIDPayload idp) -{ - SilcClientConnection conn = (SilcClientConnection)sock->user_data; - int connecting = FALSE; - SilcClientID *client_id = silc_id_payload_get_id(idp); - char *nickname; - - if (!conn->local_entry) - connecting = TRUE; - - /* Delete old ID from ID cache */ - if (conn->local_id) { - /* Check whether they are different */ - if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) { - silc_free(client_id); - return; - } - - silc_idcache_del_by_context(conn->internal->client_cache, - conn->local_entry); - silc_free(conn->local_id); - } - - /* Save the new ID */ - - if (conn->local_id_data) - silc_free(conn->local_id_data); - - conn->local_id = client_id; - conn->local_id_data = silc_id_payload_get_data(idp); - conn->local_id_data_len = silc_id_payload_get_len(idp);; - - if (!conn->local_entry) - conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry)); - - conn->local_entry->nickname = conn->nickname; - if (!conn->local_entry->username) - conn->local_entry->username = strdup(client->username); - if (!conn->local_entry->server) - conn->local_entry->server = strdup(conn->remote_host); - conn->local_entry->id = conn->local_id; - conn->local_entry->valid = TRUE; - if (!conn->local_entry->channels) - conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, - NULL, NULL, - NULL, NULL, NULL, - TRUE); - - /* Normalize nickname */ - nickname = silc_identifier_check(conn->nickname, strlen(conn->nickname), - SILC_STRING_UTF8, 128, NULL); - if (!nickname) - return; - - /* Put it to the ID cache */ - silc_idcache_add(conn->internal->client_cache, nickname, conn->local_id, - (void *)conn->local_entry, 0, NULL); - -#if 0 - if (connecting) { - SilcBuffer sidp; - - /* Issue IDENTIFY command for itself to get resolved hostname - correctly from server. */ - silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL, - silc_client_command_reply_identify_i, 0, - ++conn->cmd_ident); - sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT); - silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY, - conn->cmd_ident, 1, 5, sidp->data, sidp->len); - silc_buffer_free(sidp); - - if (!conn->internal->params.detach_data) { - /* Send NICK command if the nickname was set by the application (and is - not same as the username). Send this with little timeout. */ - if (client->nickname && - !silc_utf8_strcasecmp(client->nickname, client->username)) - silc_schedule_task_add(client->schedule, 0, - silc_client_send_auto_nick, conn, - 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); - - /* Notify application of successful connection. We do it here now that - we've received the Client ID and are allowed to send traffic. */ - client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_SUCCESS); - - /* Issue INFO command to fetch the real server name and server - information and other stuff. */ - silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL, - silc_client_command_reply_info_i, 0, - ++conn->cmd_ident); - sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER); - silc_client_command_send(client, conn, SILC_COMMAND_INFO, - conn->cmd_ident, 1, 2, sidp->data, sidp->len); - silc_buffer_free(sidp); - } else { - /* We are resuming session. Start resolving informations from the - server we need to set the client libary in the state before - detaching the session. The connect client operation is called - after this is successfully completed */ - silc_client_resume_session(client, conn, silc_client_resume_session_cb, - NULL); - } - } -#endif /* 0 */ -} - /* Removes a client entry from all channels it has joined. */ void silc_client_remove_from_channels(SilcClient client, diff --git a/lib/silcclient/client_entry.c b/lib/silcclient/client_entry.c index 4db54f03..87f2c658 100644 --- a/lib/silcclient/client_entry.c +++ b/lib/silcclient/client_entry.c @@ -345,10 +345,8 @@ static SilcBool silc_client_get_clients_list_cb(SilcClient client, /* Get client entry */ client_entry = silc_client_get_client_by_id(client, conn, &id.u.client_id); - if (client_entry) { - silc_client_ref_client(client, conn, client_entry); + if (client_entry) silc_dlist_add(clients, client_entry); - } if (!silc_buffer_pull(i->client_id_list, idp_len)) { status = SILC_STATUS_ERR_BAD_CLIENT_ID; @@ -416,13 +414,16 @@ void silc_client_get_clients_by_list(SilcClient client, /* Check if we have this client cached already. If we don't have the entry or it has incomplete info, then resolve it from the server. */ entry = silc_client_get_client_by_id(client, conn, &id.u.client_id); - if (!entry || !entry->nickname || !entry->username || !entry->realname) { + if (!entry || !entry->nickname[0] || !entry->username[0] || + !entry->realname) { if (!res_argv) { res_argv = silc_calloc(list_count, sizeof(*res_argv)); res_argv_lens = silc_calloc(list_count, sizeof(*res_argv_lens)); res_argv_types = silc_calloc(list_count, sizeof(*res_argv_types)); - if (!res_argv || !res_argv_lens || !res_argv_types) + if (!res_argv || !res_argv_lens || !res_argv_types) { + silc_client_unref_client(client, conn, entry); goto err; + } } res_argv[res_argc] = client_id_list->data; @@ -430,6 +431,7 @@ void silc_client_get_clients_by_list(SilcClient client, res_argv_types[res_argc] = res_argc + 5; res_argc++; } + silc_client_unref_client(client, conn, entry); if (!silc_buffer_pull(client_id_list, idp_len)) goto err; @@ -557,7 +559,7 @@ void silc_client_get_clients_by_channel(SilcClient client, entry = chu->client; /* If the entry has incomplete info, then resolve it from the server. */ - if (!entry->nickname || !entry->realname) { + if (!entry->nickname[0] || !entry->realname) { if (entry->status & SILC_CLIENT_STATUS_RESOLVING) { /* Attach to this resolving and wait until it finishes */ silc_client_command_pending( @@ -809,10 +811,9 @@ void silc_client_ref_client(SilcClient client, SilcClientConnection conn, void silc_client_unref_client(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry) { - if (silc_atomic_sub_int8(&client_entry->internal.refcnt, 1) == 0) { + if (client_entry && + silc_atomic_sub_int8(&client_entry->internal.refcnt, 1) == 0) silc_client_del_client(client, conn, client_entry); - return; - } } /* Free client entry list */ @@ -822,11 +823,13 @@ void silc_client_list_free(SilcClient client, SilcClientConnection conn, { SilcClientEntry client_entry; - silc_dlist_start(client_list); - while ((client_entry = silc_dlist_get(client_list))) - silc_client_unref_client(client, conn, client_entry); + if (client_list) { + silc_dlist_start(client_list); + while ((client_entry = silc_dlist_get(client_list))) + silc_client_unref_client(client, conn, client_entry); - silc_dlist_uninit(client_list); + silc_dlist_uninit(client_list); + } } @@ -1347,7 +1350,7 @@ void silc_client_nickname_format(SilcClient client, if (!client->internal->params->nickname_format[0]) return; - if (!client_entry->nickname) + if (!client_entry->nickname[0]) return; /* Get all clients with same nickname. Do not perform the formatting @@ -1469,5 +1472,5 @@ void silc_client_nickname_format(SilcClient client, newnick[off] = 0; memcpy(client_entry->nickname, newnick, strlen(newnick)); - silc_dlist_uninit(clients); + silc_client_list_free(client, conn, clients); } diff --git a/lib/silcclient/client_prvmsg.c b/lib/silcclient/client_prvmsg.c index 6c6c56ca..ec0e3b8d 100644 --- a/lib/silcclient/client_prvmsg.c +++ b/lib/silcclient/client_prvmsg.c @@ -107,7 +107,7 @@ SILC_FSM_STATE(silc_client_private_message) SilcPacket packet = state_context; SilcMessagePayload payload = NULL; SilcClientID remote_id; - SilcClientEntry remote_client; + SilcClientEntry remote_client = NULL; SilcMessageFlags flags; unsigned char *message; SilcUInt32 message_len; @@ -122,9 +122,10 @@ SILC_FSM_STATE(silc_client_private_message) /* Check whether we know this client already */ remote_client = silc_client_get_client_by_id(client, conn, &remote_id); - if (!remote_client || !remote_client->nickname) { + if (!remote_client || !remote_client->nickname[0]) { /* Resolve the client info. We return back to packet thread to receive other packets while we wait for the resolving to finish. */ + silc_client_unref_client(client, conn, remote_client); silc_client_get_client_by_id_resolve(client, conn, &remote_id, NULL, silc_client_private_message_resolved, packet); @@ -195,6 +196,7 @@ SILC_FSM_STATE(silc_client_private_message) out: /** Packet processed */ + silc_client_unref_client(client, conn, remote_client); if (payload) silc_message_payload_free(payload); silc_packet_free(packet); diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index ce4a03ea..de95e743 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -925,7 +925,7 @@ SILC_FSM_STATE(silc_client_command_invite) SilcChannelEntry channel; SilcBuffer clidp, chidp, args = NULL; SilcPublicKey pubkey = NULL; - SilcDList clients; + SilcDList clients = NULL; char *nickname = NULL, *name; char *invite = NULL; unsigned char action[1]; @@ -975,7 +975,6 @@ SILC_FSM_STATE(silc_client_command_invite) cmd)); client_entry = silc_dlist_get(clients); - silc_dlist_uninit(clients); } else { if (cmd->argv[2][0] == '+') action[0] = 0x00; @@ -1026,6 +1025,7 @@ SILC_FSM_STATE(silc_client_command_invite) silc_buffer_free(chidp); silc_buffer_free(args); silc_free(nickname); + silc_client_list_free(client, conn, clients); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -1123,7 +1123,6 @@ SILC_FSM_STATE(silc_client_command_kill) cmd)); target = silc_dlist_get(clients); - silc_dlist_uninit(clients); if (cmd->argc >= 3) { if (strcasecmp(cmd->argv[2], "-pubkey")) @@ -1149,6 +1148,7 @@ SILC_FSM_STATE(silc_client_command_kill) silc_buffer_free(idp); silc_buffer_free(auth); silc_free(nickname); + silc_client_list_free(client, conn, clients); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -1836,7 +1836,7 @@ SILC_FSM_STATE(silc_client_command_cumode) SilcChannelUser chu; SilcClientEntry client_entry; SilcBuffer clidp, chidp, auth = NULL; - SilcDList clients; + SilcDList clients = NULL; unsigned char *name, *cp, modebuf[4]; SilcUInt32 mode = 0, add, len; char *nickname = NULL; @@ -1882,7 +1882,6 @@ SILC_FSM_STATE(silc_client_command_cumode) cmd)); client_entry = silc_dlist_get(clients); - silc_dlist_uninit(clients); /* Get the current mode */ chu = silc_client_on_channel(channel, client_entry); @@ -1997,6 +1996,7 @@ SILC_FSM_STATE(silc_client_command_cumode) COMMAND(SILC_STATUS_OK); out: + silc_client_list_free(client, conn, clients); silc_free(nickname); return SILC_FSM_FINISH; } @@ -2013,7 +2013,7 @@ SILC_FSM_STATE(silc_client_command_kick) SilcChannelEntry channel; SilcBuffer idp, idp2; SilcClientEntry target; - SilcDList clients; + SilcDList clients = NULL; char *name; char *nickname = NULL; @@ -2062,7 +2062,6 @@ SILC_FSM_STATE(silc_client_command_kick) goto out; } target = silc_dlist_get(clients); - silc_dlist_uninit(clients); /* Send KICK command to the server */ idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL); @@ -2080,6 +2079,7 @@ SILC_FSM_STATE(silc_client_command_kick) silc_buffer_free(idp); silc_buffer_free(idp2); silc_free(nickname); + silc_client_list_free(client, conn, clients); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -2553,7 +2553,7 @@ SILC_FSM_STATE(silc_client_command_getkey) } else { client_entry = silc_dlist_get(clients); idp = silc_id_payload_encode(&client_entry->id, SILC_ID_CLIENT); - silc_dlist_uninit(clients); + silc_client_list_free(client, conn, clients); } /* Send the commmand */ diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 0fd79903..9eea6bf1 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -111,8 +111,10 @@ static void silc_client_command_process_error(SilcClientCommandContext cmd, return; client_entry = silc_client_get_client_by_id(client, conn, &id.u.client_id); - if (client_entry) + if (client_entry) { + silc_client_unref_client(client, conn, client_entry); silc_client_del_client(client, conn, client_entry); + } } } @@ -438,6 +440,7 @@ SILC_FSM_STATE(silc_client_command_reply_whois) realname, channel_list, mode, idle, fingerprint, umodes, client_entry->attrs); + silc_client_unref_client(client, conn, client_entry); if (has_channels) { silc_dlist_uninit(channel_list); silc_free(umodes); @@ -459,7 +462,7 @@ SILC_FSM_STATE(silc_client_command_reply_whowas) SilcClient client = conn->client; SilcCommandPayload payload = state_context; SilcArgumentPayload args = silc_command_get_args(payload); - SilcClientEntry client_entry; + SilcClientEntry client_entry = NULL; SilcID id; char *nickname, *username; char *realname = NULL; @@ -491,6 +494,7 @@ SILC_FSM_STATE(silc_client_command_reply_whowas) realname); out: + silc_client_unref_client(client, conn, client_entry); silc_fsm_next(fsm, silc_client_command_reply_process); return SILC_FSM_CONTINUE; } @@ -548,6 +552,7 @@ SILC_FSM_STATE(silc_client_command_reply_identify) /* Notify application */ silc_client_command_callback(cmd, client_entry, name, info); + silc_client_unref_client(client, conn, client_entry); break; case SILC_ID_SERVER: @@ -863,8 +868,10 @@ SILC_FSM_STATE(silc_client_command_reply_kill) silc_client_command_callback(cmd, client_entry); /* Remove the client from all channels and free it */ - if (client_entry) + if (client_entry) { silc_client_del_client(client, conn, client_entry); + silc_client_unref_client(client, conn, client_entry); + } out: silc_fsm_next(fsm, silc_client_command_reply_process); @@ -1153,17 +1160,22 @@ SILC_FSM_STATE(silc_client_command_reply_join) /* Join client to the channel */ if (!silc_client_on_channel(channel, client_entry)) { chu = silc_calloc(1, sizeof(*chu)); - if (!chu) + if (!chu) { + silc_client_unref_client(client, conn, client_entry); goto out; + } chu->client = client_entry; chu->channel = channel; chu->mode = mode; silc_hash_table_add(channel->user_list, client_entry, chu); silc_hash_table_add(client_entry->channels, channel, chu); } + silc_client_unref_client(client, conn, client_entry); - silc_buffer_pull(client_id_list, idp_len); - silc_buffer_pull(client_mode_list, 4); + if (!silc_buffer_pull(client_id_list, idp_len)) + goto out; + if (!silc_buffer_pull(client_mode_list, 4)) + goto out; } silc_buffer_start(client_id_list); silc_buffer_start(client_mode_list); @@ -1443,6 +1455,8 @@ SILC_FSM_STATE(silc_client_command_reply_cumode) /* Notify application */ silc_client_command_callback(cmd, mode, channel, client_entry); + silc_client_unref_client(client, conn, client_entry); + out: silc_fsm_next(fsm, silc_client_command_reply_process); return SILC_FSM_CONTINUE; @@ -1494,6 +1508,8 @@ SILC_FSM_STATE(silc_client_command_reply_kick) /* Notify application */ silc_client_command_callback(cmd, channel, client_entry); + silc_client_unref_client(client, conn, client_entry); + out: silc_fsm_next(fsm, silc_client_command_reply_process); return SILC_FSM_CONTINUE; @@ -1807,14 +1823,17 @@ SILC_FSM_STATE(silc_client_command_reply_users) client_entry = silc_client_get_client_by_id(client, conn, &id.u.client_id); if (client_entry && !silc_client_on_channel(channel, client_entry)) { chu = silc_calloc(1, sizeof(*chu)); - if (!chu) + if (!chu) { + silc_client_unref_client(client, conn, client_entry); goto out; + } chu->client = client_entry; chu->mode = mode; chu->channel = channel; silc_hash_table_add(channel->user_list, client_entry, chu); silc_hash_table_add(client_entry->channels, channel, chu); } + silc_client_unref_client(client, conn, client_entry); if (!silc_buffer_pull(&client_id_list, idp_len)) goto out; @@ -1892,6 +1911,7 @@ SILC_FSM_STATE(silc_client_command_reply_getkey) /* Notify application */ silc_client_command_callback(cmd, SILC_ID_CLIENT, client_entry, client_entry->public_key); + silc_client_unref_client(client, conn, client_entry); } else if (id.type == SILC_ID_SERVER) { /* Received server's public key */ server_entry = silc_client_get_server_by_id(client, conn, &id.u.server_id); -- 2.24.0