client_entry = silc_idlist_get_client(client, conn, nickname,
cmd->argv[2], TRUE);
if (!client_entry) {
- silc_free(nickname);
-
if (cmd->pending) {
COMMAND_ERROR;
goto out;
}
+ silc_free(nickname);
/* Client entry not found, it was requested thus mark this to be
pending command. */
q->client = cmd->client;
q->conn = cmd->conn;
+ /* Sleep for a while */
+ sleep(2);
+
/* We quit the connection with little timeout */
silc_schedule_task_add(cmd->client->schedule, cmd->conn->sock->sock,
silc_client_command_quit_cb, (void *)q,
silc_client_command_free(cmd);
}
+/* Timeout callback to remove the killed client from cache */
+
+SILC_TASK_CALLBACK(silc_client_command_kill_remove_later)
+{
+ SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+ SilcClient client = cmd->client;
+ SilcClientConnection conn = cmd->conn;
+ SilcClientEntry target;
+ char *nickname = NULL;
+
+ /* Parse the typed nickname. */
+ if (client->params->nickname_parse)
+ client->params->nickname_parse(cmd->argv[1], &nickname);
+ else
+ nickname = strdup(cmd->argv[1]);
+
+ /* Get the target client */
+ target = silc_idlist_get_client(cmd->client, conn, nickname,
+ cmd->argv[1], FALSE);
+ if (target) {
+ silc_client_remove_from_channels(client, conn, target);
+ silc_client_del_client(client, conn, target);
+ }
+
+ silc_free(nickname);
+ silc_client_command_free(cmd);
+}
+
+/* Kill command's pending command callback to actually remove the killed
+ client from our local cache. */
+
+SILC_CLIENT_CMD_FUNC(kill_remove)
+{
+ SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+ SilcClientCommandReplyContext reply =
+ (SilcClientCommandReplyContext)context2;
+ SilcCommandStatus status;
+
+ SILC_GET16_MSB(status, silc_argument_get_arg_type(reply->args, 1, NULL));
+ if (status == SILC_STATUS_OK) {
+ /* Remove with timeout */
+ silc_schedule_task_add(cmd->client->schedule, cmd->conn->sock->sock,
+ silc_client_command_kill_remove_later, context,
+ 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ return;
+ }
+
+ silc_client_command_free(cmd);
+}
+
/* Command KILL. Router operator can use this command to remove an client
fromthe SILC Network. */
target = silc_idlist_get_client(cmd->client, conn, nickname,
cmd->argv[1], TRUE);
if (!target) {
- silc_free(nickname);
-
if (cmd->pending) {
COMMAND_ERROR;
goto out;
}
+ silc_free(nickname);
+
/* Client entry not found, it was requested thus mark this to be
pending command. */
silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
/* Send the KILL command to the server */
idp = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
if (cmd->argc == 2)
- buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 0, 1,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL,
+ ++conn->cmd_ident, 1,
1, idp->data, idp->len);
else
- buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 0, 2,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL,
+ ++conn->cmd_ident, 2,
1, idp->data, idp->len,
2, cmd->argv[2],
strlen(cmd->argv[2]));
/* Notify application */
COMMAND;
+ /* Register a pending callback that will actually remove the killed
+ client from our cache. */
+ silc_client_command_pending(conn, SILC_COMMAND_KILL, conn->cmd_ident,
+ NULL, silc_client_command_kill_remove,
+ silc_client_command_dup(cmd));
+
out:
silc_free(nickname);
silc_client_command_free(cmd);
/* See if we have joined to the requested channel already */
if (silc_idcache_find_by_name_one(conn->channel_cache, cmd->argv[1],
- &id_cache))
- goto out;
+ &id_cache)) {
+ SilcChannelEntry channel = (SilcChannelEntry)id_cache->context;
+ if (channel->on_channel)
+ goto out;
+ }
idp = silc_id_payload_encode(conn->local_id, SILC_ID_CLIENT);
client_entry = silc_idlist_get_client(cmd->client, conn, nickname,
cmd->argv[3], TRUE);
if (!client_entry) {
- silc_free(nickname);
-
if (cmd->pending) {
COMMAND_ERROR;
goto out;
}
+ silc_free(nickname);
+
/* Client entry not found, it was requested thus mark this to be
pending command. */
silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
}
/* Get the current mode */
+ silc_list_start(channel->clients);
while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
if (chu->client == client_entry) {
mode = chu->mode;
/* Send the command packet. We support sending only one mode at once
that requires an argument. */
- buffer = silc_command_payload_encode_va(SILC_COMMAND_CUMODE, 0, 4,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_CUMODE, 0,
+ auth ? 4 : 3,
1, chidp->data, chidp->len,
2, modebuf, 4,
3, clidp->data, clidp->len,
}
channel = (SilcChannelEntry)id_cache->context;
+ channel->on_channel = FALSE;
/* Send LEAVE command to the server */
idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);