channel->user_count++;
channel->disabled = FALSE;
+ /* Update statistics */
+ if (server->server_type == SILC_ROUTER) {
+ if (sock->type != SILC_SOCKET_TYPE_ROUTER)
+ server->stat.cell_chanclients++;
+ server->stat.chanclients++;
+ }
+
break;
case SILC_NOTIFY_TYPE_LEAVE:
}
}
- /* Get target channel entry */
+ /* Get target channel user entry */
if (!silc_server_client_on_channel(client2, channel, &chl))
goto out;
if (mode & SILC_CHANNEL_UMODE_CHANFO &&
- !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && !client &&
- server->server_type == SILC_ROUTER) {
- /* Get the founder of the channel and if found then this client
- cannot be the founder since there already is one. */
- silc_hash_table_list(channel->user_list, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
- if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
- mode &= ~SILC_CHANNEL_UMODE_CHANFO;
- silc_server_force_cumode_change(server, sock, channel, chl, mode);
- notify_sent = TRUE;
- break;
- }
- silc_hash_table_list_reset(&htl);
- if (!(mode & SILC_CHANNEL_UMODE_CHANFO))
- break;
- }
-
- if (client && mode & SILC_CHANNEL_UMODE_CHANFO &&
- !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
- server->server_type == SILC_ROUTER) {
- /* Check whether this client is allowed to be channel founder on
- this channel. */
+ !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
+ server->server_type == SILC_ROUTER &&
+ sock->user_data != server->router) {
SilcPublicKey founder_key = NULL;
/* If channel doesn't have founder auth mode then it's impossible
that someone would be getting founder rights with CUMODE command.
In that case there already either is founder or there isn't
founder at all on the channel. */
- if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
+ if (client && !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
/* Force the mode to not have founder mode */
mode &= ~SILC_CHANNEL_UMODE_CHANFO;
silc_server_force_cumode_change(server, sock, channel, chl, mode);
while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
mode &= ~SILC_CHANNEL_UMODE_CHANFO;
- silc_server_force_cumode_change(server, sock, channel, chl, mode);
+ silc_server_force_cumode_change(server, sock, channel,
+ chl, mode);
notify_sent = TRUE;
break;
}
break;
}
- /* Now match the public key we have cached and public key sent.
- They must match. */
- if (client->data.public_key &&
- !silc_pkcs_public_key_compare(channel->founder_key,
- client->data.public_key)) {
- mode &= ~SILC_CHANNEL_UMODE_CHANFO;
- silc_server_force_cumode_change(server, sock, channel, chl, mode);
- notify_sent = TRUE;
- break;
- }
- if (!silc_pkcs_public_key_compare(channel->founder_key,
- founder_key)) {
- mode &= ~SILC_CHANNEL_UMODE_CHANFO;
- silc_server_force_cumode_change(server, sock, channel, chl, mode);
- notify_sent = TRUE;
- break;
+ if (channel->founder_key) {
+ /* Now match the public key we have cached and public key sent.
+ They must match. */
+ if (client && client->data.public_key &&
+ !silc_pkcs_public_key_compare(channel->founder_key,
+ client->data.public_key)) {
+ mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ silc_server_force_cumode_change(server, sock, channel, chl, mode);
+ notify_sent = TRUE;
+ break;
+ }
+ if (!silc_pkcs_public_key_compare(channel->founder_key,
+ founder_key)) {
+ mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ silc_server_force_cumode_change(server, sock, channel, chl, mode);
+ notify_sent = TRUE;
+ break;
+ }
}
+ /* There cannot be anyone else as founder on the channel now. This
+ client is definitely the founder due to this authentication */
+ silc_hash_table_list(channel->user_list, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
+ if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
+ chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ silc_server_force_cumode_change(server, NULL, channel, chl2,
+ chl2->mode);
+ break;
+ }
+ silc_hash_table_list_reset(&htl);
+
if (founder_key)
silc_pkcs_public_key_free(founder_key);
}
+ if (server->server_type == SILC_ROUTER && chl->mode == mode) {
+ SILC_LOG_DEBUG(("Mode is changed already"));
+ break;
+ }
+
SILC_LOG_DEBUG(("Changing the channel user mode"));
/* Change the mode */
silc_idlist_del_server(local ? server->local_list :
server->global_list, server_entry);
- /* XXX update statistics */
+ /* Update statistics */
+ if (server->server_type == SILC_ROUTER)
+ server->stat.servers--;
break;
if (mode & SILC_UMODE_DETACHED)
client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
+ /* Update statistics */
+ if (server->server_type == SILC_ROUTER) {
+ if (mode & SILC_UMODE_GONE) {
+ if (!(client->mode & SILC_UMODE_GONE))
+ server->stat.aways++;
+ } else {
+ if (client->mode & SILC_UMODE_GONE)
+ server->stat.aways--;
+ }
+ if (mode & SILC_UMODE_DETACHED) {
+ if (!(client->mode & SILC_UMODE_DETACHED))
+ server->stat.detached++;
+ } else {
+ if (client->mode & SILC_UMODE_DETACHED)
+ server->stat.detached--;
+ }
+ }
+
/* Change the mode */
client->mode = mode;
}
channel->disabled = TRUE;
-#if 0
- /* CMODE change notify is expected */
- /* Get the mode and set it to the channel */
- channel->mode = silc_channel_get_mode(payload);
-#endif
-
/* Send the new channel key to the server */
id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
chk->data, chk->len, FALSE);
silc_buffer_free(chk);
-
} else {
/* The channel exist by that name, check whether the ID's match.
If they don't then we'll force the server to use the ID we have.
silc_free(channel_id);
+ /* Update statistics */
+ server->stat.channels++;
+ server->stat.cell_channels++;
+
/* Since the channel is coming from server and we also know about it
then send the JOIN notify to the server so that it see's our
users on the channel "joining" the channel. */
detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
detached_client->mode &= ~SILC_UMODE_DETACHED;
+ server->stat.my_detached--;
/* Send the RESUME_CLIENT packet to our primary router so that others
know this client isn't detached anymore. */