X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fcommand.c;h=781607e3ae676af4807153be70907c11804b9638;hp=b449b1150ed9da09d1d1eccd113d1f948bf63754;hb=e5d8d3db6caa344b3d419b884556c21b15e7d123;hpb=017dec75a98209fbef49eb496c2269b0c49e736d diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index b449b115..781607e3 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -600,12 +600,11 @@ SILC_CLIENT_CMD_FUNC(invite) 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. */ @@ -705,6 +704,9 @@ SILC_CLIENT_CMD_FUNC(quit) 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, @@ -717,6 +719,56 @@ SILC_CLIENT_CMD_FUNC(quit) 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. */ @@ -752,13 +804,13 @@ SILC_CLIENT_CMD_FUNC(kill) 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, @@ -773,10 +825,12 @@ SILC_CLIENT_CMD_FUNC(kill) /* 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])); @@ -788,6 +842,12 @@ SILC_CLIENT_CMD_FUNC(kill) /* 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); @@ -909,8 +969,11 @@ SILC_CLIENT_CMD_FUNC(join) /* 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); @@ -1370,13 +1433,13 @@ SILC_CLIENT_CMD_FUNC(cumode) 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, @@ -1389,6 +1452,7 @@ SILC_CLIENT_CMD_FUNC(cumode) } /* 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; @@ -1453,7 +1517,8 @@ SILC_CLIENT_CMD_FUNC(cumode) /* 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, @@ -1955,6 +2020,7 @@ SILC_CLIENT_CMD_FUNC(leave) } 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); @@ -2053,6 +2119,23 @@ SILC_CLIENT_CMD_FUNC(getkey) goto out; } + if (cmd->pending) { + SilcClientCommandReplyContext reply = + (SilcClientCommandReplyContext)context2; + SilcCommandStatus status; + unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL); + SILC_GET16_MSB(status, tmp); + + if (status == SILC_STATUS_ERR_NO_SUCH_NICK || + status == SILC_STATUS_ERR_NO_SUCH_SERVER) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, + "%s", + silc_client_command_status_message(status)); + COMMAND_ERROR; + goto out; + } + } + /* Parse the typed nickname. */ if (client->params->nickname_parse) client->params->nickname_parse(cmd->argv[1], &nickname); @@ -2066,7 +2149,7 @@ SILC_CLIENT_CMD_FUNC(getkey) /* Check whether user requested server actually */ server_entry = silc_client_get_server(client, conn, cmd->argv[1]); - if (!server_entry) { + if (!server_entry && !cmd->pending) { /* No. what ever user wants we don't have it, so resolve it. We will try to resolve both client and server, one of them is bound to be wrong. */ @@ -2079,13 +2162,12 @@ SILC_CLIENT_CMD_FUNC(getkey) silc_client_command_getkey, silc_client_command_dup(cmd)); - /* This sends the INFO command to resolve the server. */ - silc_client_send_command(client, conn, SILC_COMMAND_INFO, + /* This sends the IDENTIFY command to resolve the server. */ + silc_client_send_command(client, conn, SILC_COMMAND_IDENTIFY, ++conn->cmd_ident, 1, - 1, cmd->argv[1], cmd->argv_lens[1]); + 2, cmd->argv[1], cmd->argv_lens[1]); silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, - conn->cmd_ident, - silc_client_command_destructor, + conn->cmd_ident, NULL, silc_client_command_getkey, silc_client_command_dup(cmd));