Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004, 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
channel->internal.curr_key = key;
} else {
/* Use normal channel key generated by the server */
- cipher = channel->internal.channel_key;
+ cipher = channel->internal.send_key;
hmac = channel->internal.hmac;
}
} else {
/* Use normal channel key generated by the server */
- cipher = channel->internal.channel_key;
+ cipher = channel->internal.send_key;
hmac = channel->internal.hmac;
}
SILC_LOG_DEBUG(("Received channel message"));
+ SILC_LOG_HEXDUMP(("Channel message"), silc_buffer_data(buffer),
+ silc_buffer_len(buffer));
+
if (silc_unlikely(packet->dst_id_type != SILC_ID_CHANNEL)) {
/** Invalid packet */
silc_fsm_next(fsm, silc_client_channel_message_error);
/* Parse the channel message payload. This also decrypts the payload */
payload = silc_message_payload_parse(silc_buffer_data(buffer),
silc_buffer_len(buffer), FALSE,
- FALSE, channel->internal.channel_key,
+ FALSE, channel->internal.receive_key,
channel->internal.hmac, NULL,
FALSE, NULL);
payload = silc_message_payload_parse(silc_buffer_data(buffer),
silc_buffer_len(buffer),
FALSE, FALSE,
- channel->internal.channel_key,
+ channel->internal.receive_key,
channel->internal.hmac, NULL,
FALSE, NULL);
channel->internal.old_hmacs = silc_dlist_init();
if (channel->internal.old_channel_keys && channel->internal.old_hmacs) {
silc_dlist_add(channel->internal.old_channel_keys,
- channel->internal.channel_key);
+ channel->internal.receive_key);
silc_dlist_add(channel->internal.old_hmacs, channel->internal.hmac);
silc_schedule_task_add_timeout(client->schedule,
silc_client_save_channel_key_rekey,
/* Get channel cipher */
cipher = silc_channel_key_get_cipher(payload, NULL);
- if (!silc_cipher_alloc(cipher, &channel->internal.channel_key)) {
+ if (!silc_cipher_alloc(cipher, &channel->internal.send_key)) {
+ client->internal->ops->say(
+ conn->client, conn,
+ SILC_CLIENT_MESSAGE_AUDIT,
+ "Cannot talk to channel: unsupported cipher %s",
+ cipher);
+ silc_client_unref_channel(client, conn, channel);
+ silc_channel_key_payload_free(payload);
+ return FALSE;
+ }
+ if (!silc_cipher_alloc(cipher, &channel->internal.receive_key)) {
client->internal->ops->say(
conn->client, conn,
SILC_CLIENT_MESSAGE_AUDIT,
return FALSE;
}
- /* Set the cipher key */
+ /* Set the cipher key. Both sending and receiving keys are same */
key = silc_channel_key_get_key(payload, &tmp_len);
- silc_cipher_set_key(channel->internal.channel_key, key, tmp_len * 8, TRUE);
+ silc_cipher_set_key(channel->internal.send_key, key, tmp_len * 8, TRUE);
+ silc_cipher_set_key(channel->internal.receive_key, key, tmp_len * 8, FALSE);
/* Get channel HMAC */
hmac = (channel->internal.hmac ?
if (silc_client_on_channel(channel, client_entry))
return TRUE;
+ SILC_LOG_DEBUG(("Add client %s to channel", client_entry->nickname));
+
chu = silc_calloc(1, sizeof(*chu));
if (!chu)
return FALSE;
if (!chu)
return FALSE;
+ SILC_LOG_DEBUG(("Remove client %s from channel", client_entry->nickname));
+
silc_hash_table_del(chu->client->channels, chu->channel);
silc_hash_table_del(chu->channel->user_list, chu->client);
silc_free(chu);
+ /* If channel became empty, delete it */
+ if (!silc_hash_table_count(channel->user_list))
+ silc_client_del_channel(client, conn, channel);
+
silc_client_unref_client(client, conn, client_entry);
silc_client_unref_channel(client, conn, channel);
SilcHashTableList htl;
SilcChannelUser chu;
+ if (!silc_hash_table_count(client_entry->channels))
+ return;
+
+ SILC_LOG_DEBUG(("Remove client from all joined channels"));
+
silc_hash_table_list(client_entry->channels, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
silc_hash_table_del(chu->client->channels, chu->channel);
silc_hash_table_del(chu->channel->user_list, chu->client);
+
+ /* If channel became empty, delete it */
+ if (!silc_hash_table_count(chu->channel->user_list))
+ silc_client_del_channel(client, conn, chu->channel);
+
silc_client_unref_client(client, conn, chu->client);
silc_client_unref_channel(client, conn, chu->channel);
silc_free(chu);