X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fcommand.c;h=85e33fe38217f0fe7b17c6c70a97270b1d3e2aca;hb=52e57c880aba9c5e89f59d962eb9af75670b76e0;hp=99fe98a974ba7fbccaaee1279782cfaf31944ad7;hpb=5e0534a2c468177c5c2b0c503f529380e8dd3df4;p=silc.git diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 99fe98a9..85e33fe3 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -123,6 +123,32 @@ static void silc_client_command_resolve_continue(SilcClient client, SILC_FSM_CALL_CONTINUE(&cmd->thread); } +/* Dummy command callback. Nothing interesting to do here. Use this when + you just send command but don't care about reply. */ + +SilcBool silc_client_command_called_dummy(SilcClient client, + SilcClientConnection conn, + SilcCommand command, + SilcStatus status, + SilcStatus error, + void *context, + va_list ap) +{ + return FALSE; +} + +/* Dummy resolving callback. Nothing interesting to do here. Use this + when you just resolve entires but don't care about reply. */ + +void silc_client_command_resolve_dummy(SilcClient client, + SilcClientConnection conn, + SilcStatus status, + SilcDList clients, + void *context) +{ + /* Nothing */ +} + /* Register command to client */ static SilcBool @@ -390,7 +416,7 @@ SilcUInt16 silc_client_command_call(SilcClient client, char *arg; if (!conn) { - client->internal->ops->say(client, NULL, SILC_CLIENT_MESSAGE_ERROR, + client->internal->ops->say(client, NULL, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "You are not connected to a server, please connect to server"); return 0; } @@ -610,6 +636,7 @@ SILC_FSM_STATE(silc_client_command_whois) unsigned char count[4], *tmp = NULL; SilcBool details = FALSE, nick = FALSE; unsigned char *pubkey = NULL; + char *nickname = NULL; int i; /* Given without arguments fetches client's own information */ @@ -670,7 +697,7 @@ SILC_FSM_STATE(silc_client_command_whois) SilcPublicKey pk; if (!silc_pkcs_load_public_key(pubkey, &pk)) { - SAY(client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load public key %s, check the filename", pubkey); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); @@ -700,14 +727,22 @@ SILC_FSM_STATE(silc_client_command_whois) SILC_ATTRIBUTE_USER_PUBLIC_KEY, SILC_ATTRIBUTE_FLAG_VALID, &obj, sizeof(obj)); + silc_free(obj.data); + } + + if (nick) { + silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname); + if (!nickname) + nickname = strdup(cmd->argv[1]); } /* Send command */ silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, - 3, 1, nick ? cmd->argv[1] : NULL, - nick ? cmd->argv_lens[1] : 0, + 3, 1, nick ? nickname : NULL, + nick ? strlen(nickname) : 0, 2, tmp ? tmp : NULL, tmp ? 4 : 0, 3, silc_buffer_datalen(attrs)); + silc_free(nickname); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -797,7 +832,7 @@ SILC_FSM_STATE(silc_client_command_identify) SILC_FSM_STATE(silc_client_command_nick) { - SilcClientCommandContext cmd = fsm_context; + SilcClientCommandContext cmd2, cmd = fsm_context; SilcClientConnection conn = cmd->conn; if (cmd->argc < 2) { @@ -825,6 +860,19 @@ SILC_FSM_STATE(silc_client_command_nick) goto out; } + /* If JOIN command is active, wait for it to finish before sending NICK. + To avoid problems locally with changing IDs while joining, we do this. */ + silc_mutex_lock(conn->internal->lock); + silc_list_start(conn->internal->pending_commands); + while ((cmd2 = silc_list_get(conn->internal->pending_commands))) { + if (cmd2->cmd == SILC_COMMAND_JOIN) { + silc_mutex_unlock(conn->internal->lock); + silc_fsm_next_later(fsm, silc_client_command_nick, 0, 300000); + return SILC_FSM_WAIT; + } + } + silc_mutex_unlock(conn->internal->lock); + if (cmd->argv_lens[1] > 128) cmd->argv_lens[1] = 128; @@ -890,7 +938,7 @@ SILC_FSM_STATE(silc_client_command_topic) SilcClient client = conn->client; SilcChannelEntry channel; SilcBuffer idp; - char *name; + char *name, tmp[512]; if (cmd->argc < 2 || cmd->argc > 3) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, @@ -905,7 +953,15 @@ SILC_FSM_STATE(silc_client_command_topic) COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - name = conn->current_channel->channel_name; + + if (client->internal->params->full_channel_names) + silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name); + else + silc_snprintf(tmp, sizeof(tmp), "%s%s%s", + conn->current_channel->channel_name, + conn->current_channel->server[0] ? "@" : "", + conn->current_channel->server); + name = tmp; } else { name = cmd->argv[1]; } @@ -998,13 +1054,12 @@ SILC_FSM_STATE(silc_client_command_invite) silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname); /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[2]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[2], + FALSE); if (!clients) /* Resolve client information */ SILC_FSM_CALL(silc_client_get_clients( - client, conn, nickname, - cmd->argv[2], + client, conn, nickname, NULL, silc_client_command_resolve_continue, cmd)); @@ -1146,12 +1201,10 @@ SILC_FSM_STATE(silc_client_command_kill) return SILC_FSM_FINISH; /* Get the target client */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[1]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[1], FALSE); if (!clients) /* Resolve client information */ - SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, - cmd->argv[1], + SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, NULL, silc_client_command_resolve_continue, cmd)); @@ -1274,7 +1327,7 @@ SILC_FSM_STATE(silc_client_command_ping) SILC_FSM_STATE(silc_client_command_join) { - SilcClientCommandContext cmd = fsm_context; + SilcClientCommandContext cmd2, cmd = fsm_context; SilcClientConnection conn = cmd->conn; SilcClient client = conn->client; SilcChannelEntry channel = NULL; @@ -1292,6 +1345,19 @@ SILC_FSM_STATE(silc_client_command_join) if (channel && silc_client_on_channel(channel, conn->local_entry)) goto out; + /* If NICK command is active, wait for it to finish before sending JOIN. + To avoid problems locally with changing IDs while joining, we do this. */ + silc_mutex_lock(conn->internal->lock); + silc_list_start(conn->internal->pending_commands); + while ((cmd2 = silc_list_get(conn->internal->pending_commands))) { + if (cmd2->cmd == SILC_COMMAND_NICK) { + silc_mutex_unlock(conn->internal->lock); + silc_fsm_next_later(fsm, silc_client_command_join, 0, 300000); + return SILC_FSM_WAIT; + } + } + silc_mutex_unlock(conn->internal->lock); + if (cmd->argv_lens[1] > 256) cmd->argv_lens[1] = 256; @@ -1323,7 +1389,7 @@ SILC_FSM_STATE(silc_client_command_join) } if (!silc_load_key_pair(cmd->argv[i + 1], cmd->argv[i + 2], pass, &pubkey, &privkey)) { - SAY(conn->client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load key pair, check your arguments"); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); goto out; @@ -1743,7 +1809,7 @@ SILC_FSM_STATE(silc_client_command_cmode) pass = cmd->argv[5]; if (!silc_load_key_pair(cmd->argv[3], cmd->argv[4], pass, &pubkey, &privkey)) { - SAY(client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load key pair, check your arguments"); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); goto out; @@ -1778,10 +1844,14 @@ SILC_FSM_STATE(silc_client_command_cmode) NULL, NULL, 1, 1, silc_buffer_datalen(chidp)); silc_buffer_free(chidp); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); - goto out; + + /** Wait for command reply */ + silc_fsm_next(fsm, silc_client_command_reply_wait); + return SILC_FSM_CONTINUE; } if (cmd->argc >= 4) { @@ -1795,7 +1865,7 @@ SILC_FSM_STATE(silc_client_command_cmode) if (cmd->argv[k][0] == '+') chadd = TRUE; if (!silc_pkcs_load_public_key(cmd->argv[k] + 1, &chpk)) { - SAY(conn->client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load public key %s, check the filename", cmd->argv[k]); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); @@ -1909,11 +1979,10 @@ SILC_FSM_STATE(silc_client_command_cumode) silc_client_nickname_parse(client, conn, cmd->argv[3], &nickname); /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[3]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[3], FALSE); if (!clients) /* Resolve client information */ - SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, cmd->argv[3], + SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, NULL, silc_client_command_resolve_continue, cmd)); @@ -1957,7 +2026,7 @@ SILC_FSM_STATE(silc_client_command_cumode) pass = cmd->argv[6]; if (!silc_load_key_pair(cmd->argv[4], cmd->argv[5], pass, &pubkey, &privkey)) { - SAY(conn->client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load key pair, check your arguments"); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); goto out; @@ -2058,8 +2127,7 @@ SILC_FSM_STATE(silc_client_command_kick) SilcBuffer idp, idp2; SilcClientEntry target; SilcDList clients = NULL; - char *name; - char *nickname = NULL; + char *name, tmp[512]; if (cmd->argc < 3) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, @@ -2073,7 +2141,15 @@ SILC_FSM_STATE(silc_client_command_kick) COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - name = conn->current_channel->channel_name; + + if (client->internal->params->full_channel_names) + silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name); + else + silc_snprintf(tmp, sizeof(tmp), "%s%s%s", + conn->current_channel->channel_name, + conn->current_channel->server[0] ? "@" : "", + conn->current_channel->server); + name = tmp; } else { name = cmd->argv[1]; } @@ -2090,12 +2166,8 @@ SILC_FSM_STATE(silc_client_command_kick) goto out; } - /* Parse the typed nickname. */ - silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname); - /* Get the target client */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[2]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[2], FALSE); if (!clients) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, "No such client: %s", cmd->argv[2]); @@ -2119,7 +2191,6 @@ SILC_FSM_STATE(silc_client_command_kick) silc_buffer_free(idp); silc_buffer_free(idp2); - silc_free(nickname); silc_client_list_free(client, conn, clients); silc_client_unref_channel(client, conn, channel); @@ -2132,7 +2203,6 @@ SILC_FSM_STATE(silc_client_command_kick) out: silc_client_unref_channel(client, conn, channel); - silc_free(nickname); return SILC_FSM_FINISH; } @@ -2145,7 +2215,7 @@ typedef struct { /* Ask passphrase callback */ -static void silc_client_command_oper_cb(unsigned char *data, +static void silc_client_command_oper_cb(const unsigned char *data, SilcUInt32 data_len, void *context) { SilcClientCommandContext cmd = context; @@ -2216,6 +2286,8 @@ SILC_FSM_STATE(silc_client_command_oper) return SILC_FSM_FINISH; } + silc_fsm_next(fsm, silc_client_command_oper_send); + /* Get passphrase */ if (cmd->argc < 3) { oper = silc_calloc(1, sizeof(*oper)); @@ -2227,7 +2299,6 @@ SILC_FSM_STATE(silc_client_command_oper) silc_client_command_oper_cb, cmd)); } - silc_fsm_next(fsm, silc_client_command_oper_send); return SILC_FSM_CONTINUE; } @@ -2246,6 +2317,8 @@ SILC_FSM_STATE(silc_client_command_silcoper) return SILC_FSM_FINISH; } + silc_fsm_next(fsm, silc_client_command_oper_send); + /* Get passphrase */ if (cmd->argc < 3) { oper = silc_calloc(1, sizeof(*oper)); @@ -2257,7 +2330,6 @@ SILC_FSM_STATE(silc_client_command_silcoper) silc_client_command_oper_cb, cmd)); } - silc_fsm_next(fsm, silc_client_command_oper_send); return SILC_FSM_CONTINUE; } @@ -2410,7 +2482,7 @@ SILC_FSM_STATE(silc_client_command_watch) SilcBuffer buffer; if (!silc_pkcs_load_public_key(pubkey, &pk)) { - SAY(conn->client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load public key %s, check the filename", pubkey); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); goto out; @@ -2427,6 +2499,12 @@ SILC_FSM_STATE(silc_client_command_watch) silc_pkcs_public_key_free(pk); } + /* If watching by nickname, resolve all users with that nickname so that + we get their information immediately. */ + if (type == 2) + silc_client_get_clients(conn->client, conn, cmd->argv[2], NULL, + silc_client_command_resolve_dummy, NULL); + /* Send the commmand */ silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 2, 1, silc_buffer_datalen(conn->internal-> @@ -2459,7 +2537,7 @@ SILC_FSM_STATE(silc_client_command_leave) SilcClient client = conn->client; SilcChannelEntry channel; SilcBuffer idp; - char *name; + char *name, tmp[512]; if (cmd->argc != 2) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, @@ -2473,7 +2551,15 @@ SILC_FSM_STATE(silc_client_command_leave) COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - name = conn->current_channel->channel_name; + + if (client->internal->params->full_channel_names) + silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name); + else + silc_snprintf(tmp, sizeof(tmp), "%s%s%s", + conn->current_channel->channel_name, + conn->current_channel->server[0] ? "@" : "", + conn->current_channel->server); + name = tmp; } else { name = cmd->argv[1]; } @@ -2518,7 +2604,7 @@ SILC_FSM_STATE(silc_client_command_users) { SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; - char *name; + char *name, tmp[512]; if (cmd->argc != 2) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, @@ -2532,7 +2618,15 @@ SILC_FSM_STATE(silc_client_command_users) COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - name = conn->current_channel->channel_name; + + if (conn->client->internal->params->full_channel_names) + silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name); + else + silc_snprintf(tmp, sizeof(tmp), "%s%s%s", + conn->current_channel->channel_name, + conn->current_channel->server[0] ? "@" : "", + conn->current_channel->server); + name = tmp; } else { name = cmd->argv[1]; } @@ -2564,7 +2658,6 @@ SILC_FSM_STATE(silc_client_command_getkey) SilcClientEntry client_entry; SilcServerEntry server_entry; SilcDList clients; - char *nickname = NULL; SilcBuffer idp; if (cmd->argc < 2) { @@ -2574,15 +2667,8 @@ SILC_FSM_STATE(silc_client_command_getkey) return SILC_FSM_FINISH; } - /* Parse the typed nickname. */ - if (!silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname)) { - COMMAND_ERROR(SILC_STATUS_ERR_RESOURCE_LIMIT); - return SILC_FSM_FINISH; - } - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[1]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[1], FALSE); if (!clients) { /* Check whether user requested server */ server_entry = silc_client_get_server(client, conn, cmd->argv[1]); @@ -2620,7 +2706,6 @@ SILC_FSM_STATE(silc_client_command_getkey) 1, silc_buffer_datalen(idp)); silc_buffer_free(idp); - silc_free(nickname); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -2749,7 +2834,6 @@ static void silc_client_command_process_whois(SilcClient client, SilcCommandPayload payload, SilcArgumentPayload args) { -#if 0 SilcDList attrs; unsigned char *tmp; SilcUInt32 tmp_len; @@ -2773,18 +2857,25 @@ static void silc_client_command_process_whois(SilcClient client, return; } - /* Send the attributes back */ + /* Send the attributes back in COMMAND_REPLY packet */ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS, SILC_STATUS_OK, 0, silc_command_get_ident(payload), - 1, 11, buffer->data, buffer->len); - silc_client_packet_send(client, sock, SILC_PACKET_COMMAND_REPLY, - NULL, 0, NULL, NULL, packet->data, - packet->len, TRUE); + 1, 11, buffer->data, + silc_buffer_len(buffer)); + if (!packet) { + silc_buffer_free(buffer); + return; + } + + SILC_LOG_DEBUG(("Sending back requested WHOIS attributes")); + + silc_packet_send(conn->stream, SILC_PACKET_COMMAND_REPLY, 0, + silc_buffer_datalen(packet)); + silc_buffer_free(packet); silc_buffer_free(buffer); -#endif /* 0 */ } /* Client is able to receive some command packets even though they are