/* Send notify about nickname change to our router. We send the new
ID and ask to replace it with the old one. If we are router the
- packet is broadcasted. */
+ packet is broadcasted. Send NICK_CHANGE notify. */
if (!server->standalone)
- silc_server_send_replace_id(server, server->router->connection,
- server->server_type == SILC_SERVER ?
- FALSE : TRUE, client->id,
- SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
- new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
+ silc_server_send_notify_nick_change(server, server->router->connection,
+ server->server_type == SILC_SERVER ?
+ FALSE : TRUE, client->id,
+ new_id, SILC_ID_CLIENT_LEN);
/* Remove old cache entry */
silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- /* Send NICK_CHANGE notify */
+ /* Send NICK_CHANGE notify to the client's channels */
silc_server_send_notify_on_channels(server, client,
SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
oidp->data, oidp->len,
/* See whether has rights to change topic */
silc_list_start(channel->user_list);
- while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
- if (chl->client == client) {
- if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
- SILC_STATUS_ERR_NO_CHANNEL_PRIV);
- goto out;
- } else {
- break;
- }
+ while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+ if (chl->client == client)
+ break;
+
+ if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
+ if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
+ SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+ goto out;
}
}
silc_free(channel->topic);
channel->topic = strdup(tmp);
+ /* Send TOPIC_SET notify type to the network */
+ if (!server->standalone)
+ silc_server_send_notify_topic_set(server, server->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, channel, client->id,
+ SILC_ID_CLIENT_LEN, channel->topic);
+
idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Send notify about topic change to all clients on the channel */
sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
/* Send notify to the client that is invited to the channel */
- silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
+ silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
+ SILC_ID_CLIENT,
SILC_NOTIFY_TYPE_INVITE, 2,
sidp->data, sidp->len, tmp, len);
silc_server_command_free(cmd);
}
+typedef struct {
+ SilcServer server;
+ SilcSocketConnection sock;
+ char *signoff;
+} *QuitInternal;
+
/* Quits connection to client. This gets called if client won't
close the connection even when it has issued QUIT command. */
SILC_TASK_CALLBACK(silc_server_command_quit_cb)
{
- SilcServer server = (SilcServer)context;
- SilcSocketConnection sock = server->sockets[fd];
+ QuitInternal q = (QuitInternal)context;
/* Free all client specific data, such as client entry and entires
on channels this client may be on. */
- silc_server_free_sock_user_data(server, sock);
+ silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
+ q->signoff);
+ q->sock->user_data = NULL;
/* Close the connection on our side */
- silc_server_close_connection(server, sock);
+ silc_server_close_connection(q->server, q->sock);
+
+ silc_free(q->signoff);
+ silc_free(q);
}
/* Quits SILC session. This is the normal way to disconnect client. */
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcSocketConnection sock = cmd->sock;
+ QuitInternal q;
+ unsigned char *tmp = NULL;
+ unsigned int len = 0;
- SILC_LOG_DEBUG(("Start"));
+ SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
+
+ /* Get destination ID */
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
+ if (len > 128)
+ tmp = NULL;
+
+ q = silc_calloc(1, sizeof(*q));
+ q->server = server;
+ q->sock = sock;
+ q->signoff = tmp ? strdup(tmp) : NULL;
/* We quit the connection with little timeout */
silc_task_register(server->timeout_queue, sock->sock,
- silc_server_command_quit_cb, server,
- 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ silc_server_command_quit_cb, (void *)q,
+ 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
silc_server_command_free(cmd);
}
if (!cmd->pending) {
/* Send JOIN notify to locally connected clients on the channel */
silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
- SILC_NOTIFY_TYPE_JOIN, 1,
- clidp->data, clidp->len);
+ SILC_NOTIFY_TYPE_JOIN, 2,
+ clidp->data, clidp->len,
+ chidp->data, chidp->len);
- /* Send NEW_CHANNEL_USER packet to our primary router */
+ /* Send JOIN notify packet to our primary router */
if (!server->standalone)
- silc_server_send_new_channel_user(server, server->router->connection,
- server->server_type == SILC_SERVER ?
- FALSE : TRUE,
- channel->id, SILC_ID_CHANNEL_LEN,
- client->id, SILC_ID_CLIENT_LEN);
+ silc_server_send_notify_join(server, server->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, channel, client->id,
+ SILC_ID_CLIENT_LEN);
}
/* Send USERS command reply to the joined channel so the user sees who
/* Send CMODE_CHANGE notify */
cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
+ silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
cidp->data, cidp->len,
tmp_mask, tmp_len);
- silc_free(cidp);
+
+ /* Set CMODE notify type to network */
+ if (!server->standalone)
+ silc_server_send_notify_cmode(server, server->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, channel,
+ mode_mask, client->id, SILC_ID_CLIENT_LEN);
/* Send command reply to sender */
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
silc_buffer_free(packet);
silc_free(channel_id);
+ silc_free(cidp);
out:
silc_server_command_free(cmd);
SilcClientEntry target_client;
SilcChannelClientEntry chl;
SilcBuffer packet, idp;
- unsigned char *tmp_id, *tmp_mask;
- unsigned int target_mask, sender_mask, tmp_len;
+ unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
+ unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
int notify = FALSE;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
/* Get Channel ID */
- tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
- if (!tmp_id) {
+ tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
+ if (!tmp_ch_id) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_CHANNEL_ID);
goto out;
}
- channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
+ channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
if (!channel_id) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_NO_CHANNEL_ID);
target_client = silc_idlist_find_client_by_id(server->local_list,
client_id, NULL);
if (!target_client) {
- /* XXX If target client is not one of mine send to primary route */
+ target_client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
}
/* Check whether target client is on the channel */
}
}
+ idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+
/* Send notify to channel, notify only if mode was actually changed. */
if (notify) {
- idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
- silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
+ silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
idp->data, idp->len,
- tmp_mask, 4, tmp_id, tmp_len);
- silc_buffer_free(idp);
+ tmp_mask, 4,
+ tmp_id, tmp_len);
+
+ /* Set CUMODE notify type to network */
+ if (!server->standalone)
+ silc_server_send_notify_cumode(server, server->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, channel,
+ target_mask, client->id,
+ SILC_ID_CLIENT_LEN,
+ target_client->id,
+ SILC_ID_CLIENT_LEN);
}
/* Send command reply to sender */
silc_buffer_free(packet);
silc_free(channel_id);
silc_free(client_id);
+ silc_buffer_free(idp);
out:
silc_server_command_free(cmd);
}
/* Notify routers that they should remove this client from their list
- of clients on the channel. */
+ of clients on the channel. Send LEAVE notify type. */
if (!server->standalone)
- silc_server_send_remove_channel_user(server,
- server->router->connection,
- server->server_type == SILC_ROUTER ?
- TRUE : FALSE, id_entry->id, id);
+ silc_server_send_notify_leave(server, server->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, channel, id_entry->id,
+ SILC_ID_CLIENT_LEN);
/* Remove client from channel */
i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,