Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 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
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)
+ ERROR_CALLBACK(SILC_STATUS_ERR_TIMEDOUT);
return SILC_FSM_FINISH;
}
nickname, username, realname, mode);
}
+ silc_rwlock_wrlock(client_entry->internal.lock);
+
if (fingerprint && fingerprint_len == sizeof(client_entry->fingerprint))
memcpy(client_entry->fingerprint, fingerprint, fingerprint_len);
client_entry->attrs = silc_attribute_payload_parse(tmp, len);
}
+ silc_rwlock_unlock(client_entry->internal.lock);
+
/* Parse channel and channel user mode list */
if (has_channels) {
channel_list = silc_channel_payload_parse_list(silc_buffer_data(&channels),
goto out;
}
+ silc_rwlock_wrlock(conn->local_entry->internal.lock);
+
/* Change the nickname */
old_client_id = *conn->local_id;
if (!silc_client_change_nickname(client, conn, conn->local_entry,
goto out;
}
+ silc_rwlock_unlock(conn->local_entry->internal.lock);
+
/* Notify application */
silc_client_command_callback(cmd, conn->local_entry,
conn->local_entry->nickname, &old_client_id);
goto out;
}
+ silc_rwlock_wrlock(channel->internal.lock);
+
/* Take topic */
topic = silc_argument_get_arg_type(args, 3, &len);
if (topic) {
channel->topic = silc_memdup(topic, len);
}
+ silc_rwlock_unlock(channel->internal.lock);
+
/* Notify application */
silc_client_command_callback(cmd, channel, channel->topic);
/* Notify application */
silc_client_command_callback(cmd, client_entry);
- /* Remove the client from all channels and free it */
+ /* Remove the client */
if (client_entry) {
silc_client_remove_from_channels(client, conn, client_entry);
silc_client_del_client(client, conn, client_entry);
}
silc_buffer_set(&client_mode_list, tmp, len);
+ silc_rwlock_wrlock(channel->internal.lock);
+
/* Add clients we received in the reply to the channel */
for (i = 0; i < list_count; i++) {
SilcUInt16 idp_len;
continue;
/* Join client to the channel */
+ silc_rwlock_wrlock(client_entry->internal.lock);
silc_client_add_to_channel(client, conn, channel, client_entry, mode);
+ silc_rwlock_unlock(client_entry->internal.lock);
silc_client_unref_client(client, conn, client_entry);
- if (!silc_buffer_pull(&client_id_list, idp_len))
+ if (!silc_buffer_pull(&client_id_list, idp_len)) {
+ silc_rwlock_unlock(channel->internal.lock);
goto out;
- if (!silc_buffer_pull(&client_mode_list, 4))
+ }
+ if (!silc_buffer_pull(&client_mode_list, 4)) {
+ silc_rwlock_unlock(channel->internal.lock);
goto out;
+ }
}
/* Get hmac */
SAY(client, conn, SILC_CLIENT_MESSAGE_ERROR,
"Cannot join channel: Unsupported HMAC `%s'", hmac);
ERROR_CALLBACK(SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
+ silc_rwlock_unlock(channel->internal.lock);
goto out;
}
}
/* Get channel public key list */
tmp = silc_argument_get_arg_type(args, 16, &len);
if (tmp)
- channel->channel_pubkeys =
- silc_argument_list_parse_decoded(tmp, len, SILC_ARGUMENT_PUBLIC_KEY);
+ silc_client_channel_save_public_keys(channel, tmp, len);
/* Set current channel */
conn->current_channel = channel;
- cipher = (channel->internal.channel_key ?
- silc_cipher_get_name(channel->internal.channel_key) : NULL);
+ silc_rwlock_unlock(channel->internal.lock);
+
+ cipher = (channel->internal.send_key ?
+ silc_cipher_get_name(channel->internal.send_key) : NULL);
silc_hash_table_list(channel->user_list, &htl);
/* Notify application */
}
SILC_GET32_MSB(mode, tmp);
+ silc_rwlock_wrlock(conn->local_entry->internal.lock);
conn->local_entry->mode = mode;
+ silc_rwlock_unlock(conn->local_entry->internal.lock);
/* Notify application */
silc_client_command_callback(cmd, mode);
goto out;
}
- /* Save the mode */
- SILC_GET32_MSB(mode, tmp);
- channel->mode = mode;
-
/* Get founder public key */
tmp = silc_argument_get_arg_type(args, 4, &len);
if (tmp)
silc_public_key_payload_decode(tmp, len, &public_key);
+ silc_rwlock_wrlock(channel->internal.lock);
+
+ /* Save the mode */
+ SILC_GET32_MSB(mode, tmp);
+ channel->mode = mode;
+
/* Get user limit */
tmp = silc_argument_get_arg_type(args, 6, &len);
if (tmp && len == 4)
/* Get channel public key(s) */
tmp = silc_argument_get_arg_type(args, 5, &len);
if (tmp)
- channel_pubkeys =
- silc_argument_list_parse_decoded(tmp, len, SILC_ARGUMENT_PUBLIC_KEY);
+ silc_client_channel_save_public_keys(channel, tmp, len);
+
+ silc_rwlock_unlock(channel->internal.lock);
/* Notify application */
silc_client_command_callback(cmd, channel, mode, public_key,
}
/* Save the mode */
+ silc_rwlock_wrlock(channel->internal.lock);
chu = silc_client_on_channel(channel, client_entry);
if (chu)
chu->mode = mode;
+ silc_rwlock_unlock(channel->internal.lock);
/* Notify application */
silc_client_command_callback(cmd, mode, channel, client_entry);
SilcUInt16 idp_len, mode;
SilcHashTableList htl;
SilcBufferStruct client_id_list, client_mode_list;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcClientEntry client_entry;
SilcID id;
int i;
/* Resolve users we do not know about */
if (!cmd->resolved) {
cmd->resolved = TRUE;
+ silc_client_unref_channel(client, conn, channel);
SILC_FSM_CALL(silc_client_get_clients_by_list(
client, conn, list_count, &client_id_list,
silc_client_command_reply_users_resolved, cmd));
SILC_LOG_DEBUG(("channel %s, %d users", channel->channel_name, list_count));
+ silc_rwlock_wrlock(channel->internal.lock);
+
/* Cache the received Client ID's and modes. */
for (i = 0; i < list_count; i++) {
SILC_GET16_MSB(idp_len, client_id_list.data + 2);
/* Save the client on this channel. Unknown clients are ignored as they
clearly do not exist since the resolving didn't find them. */
client_entry = silc_client_get_client_by_id(client, conn, &id.u.client_id);
- if (client_entry)
+ if (client_entry) {
+ silc_rwlock_wrlock(client_entry->internal.lock);
silc_client_add_to_channel(client, conn, channel, client_entry, mode);
+ silc_rwlock_unlock(client_entry->internal.lock);
+ }
silc_client_unref_client(client, conn, client_entry);
- if (!silc_buffer_pull(&client_id_list, idp_len))
+ if (!silc_buffer_pull(&client_id_list, idp_len)) {
+ silc_rwlock_unlock(channel->internal.lock);
goto out;
- if (!silc_buffer_pull(&client_mode_list, 4))
+ }
+ if (!silc_buffer_pull(&client_mode_list, 4)) {
+ silc_rwlock_unlock(channel->internal.lock);
goto out;
+ }
}
/* Notify application */
silc_hash_table_list_reset(&htl);
out:
+ silc_client_unref_channel(client, conn, channel);
silc_fsm_next(fsm, silc_client_command_reply_processed);
return SILC_FSM_CONTINUE;
}
goto out;
}
+ silc_rwlock_wrlock(client_entry->internal.lock);
+
/* Save fingerprint */
if (!client_entry->fingerprint)
silc_hash_make(conn->internal->sha1hash, tmp + 4, len - 4,
public_key = NULL;
}
+ silc_rwlock_unlock(client_entry->internal.lock);
+
/* Notify application */
silc_client_command_callback(cmd, SILC_ID_CLIENT, client_entry,
client_entry->public_key);
goto out;
}
+ silc_rwlock_wrlock(server_entry->internal.lock);
+
if (!server_entry->public_key) {
server_entry->public_key = public_key;
public_key = NULL;
}
+ silc_rwlock_unlock(server_entry->internal.lock);
+
/* Notify application */
silc_client_command_callback(cmd, SILC_ID_SERVER, server_entry,
server_entry->public_key);