silc_server_packet_queue_purge(server, sock);
if (client->id) {
+ /* Check if anyone is watching this nickname */
+ if (server->server_type == SILC_ROUTER)
+ silc_server_check_watcher_list(server, client, NULL,
+ SILC_NOTIFY_TYPE_SIGNOFF);
+
/* Send SIGNOFF notify to routers. */
if (notify && !server->standalone && server->router)
silc_server_send_notify_signoff(server, server->router->connection,
silc_server_remove_from_channels(server, NULL, client,
FALSE, NULL, FALSE);
- /* Check if anyone is watching this nickname */
- if (server->server_type == SILC_ROUTER)
- silc_server_check_watcher_list(server, client, NULL,
- SILC_NOTIFY_TYPE_SIGNOFF);
-
/* Remove this client from watcher list if it is */
silc_server_del_from_watcher_list(server, client);
}
void silc_server_announce_get_channel_users(SilcServer server,
SilcChannelEntry channel,
+ SilcBuffer *channel_modes,
SilcBuffer *channel_users,
SilcBuffer *channel_users_modes)
{
SilcChannelClientEntry chl;
SilcHashTableList htl;
- SilcBuffer chidp, clidp;
+ SilcBuffer chidp, clidp, csidp;
SilcBuffer tmp;
int len;
unsigned char mode[4], *fkey = NULL;
SilcUInt32 fkey_len = 0;
+ char *hmac;
SILC_LOG_DEBUG(("Start"));
- /* Now find all users on the channel */
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
+ csidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
+
+ /* CMODE notify */
+ SILC_PUT32_MSB(channel->mode, mode);
+ hmac = channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : NULL;
+ if (channel->founder_key)
+ fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
+ tmp =
+ silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CMODE_CHANGE,
+ 6, csidp->data, csidp->len,
+ mode, sizeof(mode),
+ NULL, 0,
+ hmac, hmac ? strlen(hmac) : 0,
+ channel->passphrase,
+ channel->passphrase ?
+ strlen(channel->passphrase) : 0,
+ fkey, fkey_len);
+ len = tmp->len;
+ *channel_modes =
+ silc_buffer_realloc(*channel_modes,
+ (*channel_modes ?
+ (*channel_modes)->truelen + len : len));
+ silc_buffer_pull_tail(*channel_modes,
+ ((*channel_modes)->end -
+ (*channel_modes)->data));
+ silc_buffer_put(*channel_modes, tmp->data, tmp->len);
+ silc_buffer_pull(*channel_modes, len);
+ silc_buffer_free(tmp);
+ silc_free(fkey);
+
+ /* Now find all users on the channel */
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
clidp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && channel->founder_key)
fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CUMODE_CHANGE,
- 4, clidp->data, clidp->len,
- mode, 4,
+ 4, csidp->data, csidp->len,
+ mode, sizeof(mode),
clidp->data, clidp->len,
fkey, fkey_len);
len = tmp->len;
}
silc_hash_table_list_reset(&htl);
silc_buffer_free(chidp);
+ silc_buffer_free(csidp);
}
/* Returns assembled packets for all channels and users on those channels
void silc_server_announce_get_channels(SilcServer server,
SilcIDList id_list,
SilcBuffer *channels,
+ SilcBuffer **channel_modes,
SilcBuffer *channel_users,
SilcBuffer **channel_users_modes,
SilcUInt32 *channel_users_modes_c,
sizeof(**channel_users_modes) *
(i + 1));
(*channel_users_modes)[i] = NULL;
+ *channel_modes = silc_realloc(*channel_modes,
+ sizeof(**channel_modes) * (i + 1));
+ (*channel_modes)[i] = NULL;
*channel_ids = silc_realloc(*channel_ids,
sizeof(**channel_ids) * (i + 1));
(*channel_ids)[i] = NULL;
silc_server_announce_get_channel_users(server, channel,
+ &(*channel_modes)[i],
channel_users,
&(*channel_users_modes)[i]);
(*channel_ids)[i] = channel->id;
unsigned long creation_time,
SilcSocketConnection remote)
{
- SilcBuffer channels = NULL, channel_users = NULL;
+ SilcBuffer channels = NULL, *channel_modes = NULL, channel_users = NULL;
SilcBuffer *channel_users_modes = NULL;
SilcBuffer *channel_topics = NULL;
SilcUInt32 channel_users_modes_c = 0;
/* Get channels and channel users in local list */
silc_server_announce_get_channels(server, server->local_list,
- &channels, &channel_users,
+ &channels, &channel_modes,
+ &channel_users,
&channel_users_modes,
&channel_users_modes_c,
&channel_topics,
/* Get channels and channel users in global list */
if (server->server_type != SILC_SERVER)
silc_server_announce_get_channels(server, server->global_list,
- &channels, &channel_users,
+ &channels, &channel_modes,
+ &channel_users,
&channel_users_modes,
&channel_users_modes_c,
&channel_topics,
silc_buffer_free(channels);
}
+ if (channel_modes) {
+ int i;
+
+ for (i = 0; i < channel_users_modes_c; i++) {
+ if (!channel_modes[i])
+ continue;
+ silc_buffer_push(channel_modes[i],
+ channel_modes[i]->data -
+ channel_modes[i]->head);
+ SILC_LOG_HEXDUMP(("channel modes"), channel_modes[i]->data,
+ channel_modes[i]->len);
+ silc_server_packet_send_dest(server, remote,
+ SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+ channel_ids[i], SILC_ID_CHANNEL,
+ channel_modes[i]->data,
+ channel_modes[i]->len,
+ FALSE);
+ silc_buffer_free(channel_modes[i]);
+ }
+ silc_free(channel_modes);
+ }
+
if (channel_users) {
silc_buffer_push(channel_users, channel_users->data - channel_users->head);
SILC_LOG_HEXDUMP(("channel users"), channel_users->data,
/* Assembles user list and users mode list from the `channel'. */
-void silc_server_get_users_on_channel(SilcServer server,
+bool silc_server_get_users_on_channel(SilcServer server,
SilcChannelEntry channel,
SilcBuffer *user_list,
SilcBuffer *mode_list,
SilcBuffer idp;
SilcUInt32 list_count = 0, len = 0;
+ if (!silc_hash_table_count(channel->user_list))
+ return FALSE;
+
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl))
len += (silc_id_get_len(chl->client->id, SILC_ID_CLIENT) + 4);
*user_list = client_id_list;
*mode_list = client_mode_list;
*user_count = list_count;
+ return TRUE;
}
/* Saves users and their modes to the `channel'. */