Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
if (status != SILC_STATUS_OK)
silc_fsm_next(&cmd->thread, silc_client_command_continue_error);
- if (clients)
- silc_dlist_uninit(clients);
-
/* Continue with the command */
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
SilcClientCommand cmd;
cmd = silc_calloc(1, sizeof(*cmd));
+ if (!cmd)
+ return FALSE;
cmd->cmd = command;
cmd->command = command_func;
cmd->reply = command_reply_func;
- cmd->name = name ? strdup(name) : NULL;
cmd->max_args = max_args;
+ cmd->name = name ? strdup(name) : NULL;
+ if (!cmd->name) {
+ silc_free(cmd);
+ return FALSE;
+ }
silc_list_add(client->internal->commands, cmd);
return NULL;
}
-/* Free command context and its internals */
-
-static void silc_client_command_free(SilcClientCommandContext cmd)
-{
- int i;
-
- for (i = 0; i < cmd->argc; i++)
- silc_free(cmd->argv[i]);
- silc_free(cmd->argv);
- silc_free(cmd->argv_lens);
- silc_free(cmd->argv_types);
- silc_free(cmd);
-}
-
/* Command thread destructor */
static void silc_client_command_destructor(SilcFSMThread thread,
void *fsm_context,
void *destructor_context)
{
- silc_client_command_free(fsm_context);
+ SilcClientCommandContext cmd = fsm_context;
+ SilcClientConnection conn = cmd->conn;
+
+ /* Removes commands that aren't waiting for reply but are waiting
+ for something. They may not have been removed yet. */
+ silc_list_del(conn->internal->pending_commands, cmd);
+
+ silc_client_command_free(cmd);
}
/* Add a command pending a command reply. Used internally by the library. */
SILC_LOG_DEBUG(("Send command %s", silc_get_command_name(command)));
+ if (conn->internal->disconnected)
+ return 0;
+
if (!cmd->cmd_ident)
cmd->cmd_ident = silc_client_cmd_ident(conn);
SILC_LOG_DEBUG(("Send command %s", silc_get_command_name(command)));
+ if (conn->internal->disconnected)
+ return 0;
+
if (!cmd->cmd_ident)
cmd->cmd_ident = silc_client_cmd_ident(conn);
/****************************** Command API *********************************/
+/* Free command context and its internals */
+
+void silc_client_command_free(SilcClientCommandContext cmd)
+{
+ SilcClientCommandReplyCallback cb;
+ int i;
+
+ for (i = 0; i < cmd->argc; i++)
+ silc_free(cmd->argv[i]);
+ silc_free(cmd->argv);
+ silc_free(cmd->argv_lens);
+ silc_free(cmd->argv_types);
+
+ silc_list_start(cmd->reply_callbacks);
+ while ((cb = silc_list_get(cmd->reply_callbacks)))
+ silc_free(cb);
+
+ silc_free(cmd);
+}
+
/* Executes a command */
SilcUInt16 silc_client_command_call(SilcClient client,
SilcUInt32 argc = 0;
unsigned char **argv = NULL;
SilcUInt32 *argv_lens = NULL, *argv_types = NULL;
+ SilcUInt16 cmd_ident;
SilcClientCommand command;
SilcClientCommandContext cmd;
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;
}
argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
if (!argv || !argv_lens || !argv_types)
- return FALSE;
+ return 0;
argv[argc] = silc_memdup(arg, strlen(arg));
if (!argv[argc])
- return FALSE;
+ return 0;
argv_lens[argc] = strlen(arg);
argv_types[argc] = argc;
argc++;
cmd->argv = argv;
cmd->argv_lens = argv_lens;
cmd->argv_types = argv_types;
- cmd->cmd_ident = silc_client_cmd_ident(conn);
+ cmd_ident = cmd->cmd_ident = silc_client_cmd_ident(conn);
cmd->called = TRUE;
cmd->verbose = TRUE;
+ silc_list_init(cmd->reply_callbacks,
+ struct SilcClientCommandReplyCallbackStruct, next);
/*** Call command */
SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
silc_client_command_destructor, NULL, FALSE);
silc_fsm_start_sync(&cmd->thread, command->command);
- return cmd->cmd_ident;
+ return cmd_ident;
}
/* Generic function to send any command. The arguments must be sent already
return 0;
cmd->conn = conn;
cmd->cmd = command;
+ silc_list_init(cmd->reply_callbacks,
+ struct SilcClientCommandReplyCallbackStruct, next);
/* Send the command */
va_start(ap, argc);
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 */
if (cmd->argc < 2) {
- silc_client_command_send(conn->client, conn, SILC_COMMAND_WHOIS,
- NULL, NULL, 1,
- 4, silc_buffer_datalen(conn->local_idp));
- goto out;
+ silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 1, 4,
+ silc_buffer_data(conn->internal->local_idp),
+ silc_buffer_len(conn->internal->local_idp));
+
+ /* Notify application */
+ COMMAND(SILC_STATUS_OK);
+
+ /** Wait for command reply */
+ silc_fsm_next(fsm, silc_client_command_reply_wait);
+ return SILC_FSM_CONTINUE;
}
for (i = 1; i < cmd->argc; i++) {
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);
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);
SILC_FSM_STATE(silc_client_command_nick)
{
- SilcClientCommandContext cmd = fsm_context;
+ SilcClientCommandContext cmd2, cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
if (cmd->argc < 2) {
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;
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
- SilcChannelEntry channel;
+ SilcClient client = conn->client;
+ SilcChannelEntry channel = NULL;
SilcBuffer idp = NULL;
if (cmd->argc == 2) {
1, 1, silc_buffer_datalen(idp));
silc_buffer_free(idp);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
+ 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,
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];
}
1, silc_buffer_datalen(idp));
silc_buffer_free(idp);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
SilcClientEntry client_entry = NULL;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcBuffer clidp, chidp, args = NULL;
SilcPublicKey pubkey = NULL;
SilcDList clients = NULL;
}
channel = conn->current_channel;
+ silc_client_ref_channel(client, conn, channel);
} else {
name = cmd->argv[1];
/* Parse the typed nickname. */
if (cmd->argc == 3) {
if (cmd->argv[2][0] != '+' && cmd->argv[2][0] != '-') {
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[2], &nickname);
- else
- nickname = strdup(cmd->argv[2]);
+ 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));
silc_buffer_free(args);
silc_free(nickname);
silc_client_list_free(client, conn, clients);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
- SilcClient client = conn->client;
+
+ SILC_LOG_DEBUG(("Quitting"));
/* Notify application */
COMMAND(SILC_STATUS_OK);
- /* Call connection callback */
- conn->callback(client, conn, SILC_CLIENT_CONN_DISCONNECTED,
- 0, NULL, conn->context);
-
/* Signal to close connection */
- conn->internal->disconnected = TRUE;
- SILC_FSM_SEMA_POST(&conn->internal->wait_event);
+ conn->internal->status = SILC_CLIENT_CONN_DISCONNECTED;
+ if (!conn->internal->disconnected) {
+ conn->internal->disconnected = TRUE;
+ SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event);
+ }
return SILC_FSM_FINISH;
}
/********************************** KILL ************************************/
-
/* Command KILL. Router operator can use this command to remove an client
fromthe SILC Network. */
}
/* Parse the typed nickname. */
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[1], &nickname);
- else
- nickname = strdup(cmd->argv[1]);
- if (!nickname)
+ if (!silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname))
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));
auth = silc_auth_public_key_auth_generate(conn->public_key,
conn->private_key,
conn->client->rng,
- client->sha1hash,
+ conn->internal->sha1hash,
&target->id, SILC_ID_CLIENT);
}
}
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
- if (cmd->argc < 2) {
- COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return SILC_FSM_FINISH;
- }
-
/* Send the command */
silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 1,
- 1, silc_buffer_datalen(conn->remote_idp));
+ 1, silc_buffer_datalen(conn->internal->
+ remote_idp));
/* Notify application */
COMMAND(SILC_STATUS_OK);
/* Send the command */
silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 1,
- 1, silc_buffer_datalen(conn->remote_idp));
+ 1, silc_buffer_datalen(conn->internal->
+ remote_idp));
/* Save ping time */
cmd->context = SILC_64_TO_PTR(silc_time());
SILC_FSM_STATE(silc_client_command_join)
{
- SilcClientCommandContext cmd = fsm_context;
+ SilcClientCommandContext cmd2, cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
- SilcChannelEntry channel;
+ SilcClient client = conn->client;
+ SilcChannelEntry channel = NULL;
SilcBuffer auth = NULL, cauth = NULL;
char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL;
int i, passphrase_len = 0;
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;
auth = silc_auth_public_key_auth_generate(conn->public_key,
conn->private_key,
conn->client->rng,
- conn->client->sha1hash,
+ conn->internal->sha1hash,
conn->local_id,
SILC_ID_CLIENT);
} else if (!strcasecmp(cmd->argv[i], "-auth")) {
}
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;
}
pk = silc_pkcs_public_key_encode(pubkey, &pk_len);
- silc_hash_make(conn->client->sha1hash, pk, pk_len, pkhash);
+ silc_hash_make(conn->internal->sha1hash, pk, pk_len, pkhash);
silc_free(pk);
pubdata = silc_rng_get_rn_data(conn->client->rng, 128);
memcpy(pubdata, pkhash, 20);
cauth = silc_auth_public_key_auth_generate_wpub(pubkey, privkey,
pubdata, 128,
- conn->client->sha1hash,
+ conn->internal->sha1hash,
conn->local_id,
SILC_ID_CLIENT);
memset(pubdata, 0, 128);
/* Send JOIN command to the server */
silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 7,
1, name, strlen(name),
- 2, silc_buffer_datalen(conn->local_idp),
+ 2, silc_buffer_datalen(conn->internal->
+ local_idp),
3, passphrase, passphrase_len,
4, cipher, cipher ? strlen(cipher) : 0,
5, hmac, hmac ? strlen(hmac) : 0,
if (passphrase)
memset(passphrase, 0, strlen(passphrase));
silc_free(passphrase);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
return SILC_FSM_CONTINUE;
out:
+ silc_client_unref_channel(client, conn, channel);
return SILC_FSM_FINISH;
}
/* Send the command */
silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 2,
- 1, silc_buffer_datalen(conn->local_idp),
+ 1, silc_buffer_datalen(conn->internal->
+ local_idp),
2, modebuf, sizeof(modebuf));
/* Notify application */
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcBuffer chidp, auth = NULL, pk = NULL;
unsigned char *name, *cp, modebuf[4], tmp[4], *arg = NULL;
SilcUInt32 mode, add, type, len, arg_len = 0;
}
channel = conn->current_channel;
+ silc_client_ref_channel(client, conn, channel);
} else {
name = cmd->argv[1];
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;
pk = silc_public_key_payload_encode(pubkey);
auth = silc_auth_public_key_auth_generate(pubkey, privkey,
conn->client->rng,
- conn->client->sha1hash,
+ conn->internal->sha1hash,
conn->local_id,
SILC_ID_CLIENT);
arg = silc_buffer_data(auth);
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) {
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);
silc_buffer_free(chidp);
silc_buffer_free(auth);
silc_buffer_free(pk);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
return SILC_FSM_CONTINUE;
out:
+ silc_client_unref_channel(client, conn, channel);
return SILC_FSM_FINISH;
}
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
SilcChannelUser chu;
SilcClientEntry client_entry;
SilcBuffer clidp, chidp, auth = NULL;
}
channel = conn->current_channel;
+ silc_client_ref_channel(client, conn, channel);
} else {
name = cmd->argv[1];
}
/* Parse the typed nickname. */
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[3], &nickname);
- else
- nickname = strdup(cmd->argv[3]);
+ 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));
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;
auth = silc_auth_public_key_auth_generate(pubkey, privkey,
conn->client->rng,
- conn->client->sha1hash,
+ conn->internal->sha1hash,
conn->local_id,
SILC_ID_CLIENT);
mode |= SILC_CHANNEL_UMODE_CHANFO;
silc_buffer_free(auth);
silc_free(nickname);
silc_client_list_free(client, conn, clients);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
return SILC_FSM_CONTINUE;
out:
+ silc_client_unref_channel(client, conn, channel);
silc_client_list_free(client, conn, clients);
silc_free(nickname);
return SILC_FSM_FINISH;
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
SilcClient client = conn->client;
- SilcChannelEntry channel;
+ SilcChannelEntry channel = NULL;
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,
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];
}
goto out;
}
- /* Parse the typed nickname. */
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[2], &nickname);
- else
- nickname = strdup(cmd->argv[2]);
-
/* 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]);
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);
/* Notify application */
COMMAND(SILC_STATUS_OK);
return SILC_FSM_CONTINUE;
out:
- silc_free(nickname);
+ silc_client_unref_channel(client, conn, channel);
return SILC_FSM_FINISH;
}
/* 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;
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));
silc_client_command_oper_cb, cmd));
}
- silc_fsm_next(fsm, silc_client_command_oper_send);
return SILC_FSM_CONTINUE;
}
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));
silc_client_command_oper_cb, cmd));
}
- silc_fsm_next(fsm, silc_client_command_oper_send);
return SILC_FSM_CONTINUE;
}
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
+ SilcClient client = conn->client;
SilcChannelEntry channel;
SilcBuffer chidp, args = NULL;
char *name, *ban = NULL;
}
channel = conn->current_channel;
+ silc_client_ref_channel(client, conn, channel);
} else {
name = cmd->argv[1];
silc_buffer_free(chidp);
silc_buffer_free(args);
+ silc_client_unref_channel(client, conn, channel);
/* Notify application */
COMMAND(SILC_STATUS_OK);
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;
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->local_idp),
+ 1, silc_buffer_datalen(conn->internal->
+ local_idp),
type, pubkey ? args->data : cmd->argv[2],
pubkey ? silc_buffer_len(args) :
cmd->argv_lens[2]);
{
SilcClientCommandContext cmd = fsm_context;
SilcClientConnection conn = cmd->conn;
+ 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,
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];
}
if (conn->current_channel == channel)
conn->current_channel = NULL;
+ silc_client_unref_channel(client, conn, channel);
+
/** Wait for command reply */
silc_fsm_next(fsm, silc_client_command_reply_wait);
return SILC_FSM_CONTINUE;
{
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,
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];
}
SilcClientEntry client_entry;
SilcServerEntry server_entry;
SilcDList clients;
- char *nickname = NULL;
SilcBuffer idp;
if (cmd->argc < 2) {
return SILC_FSM_FINISH;
}
- /* Parse the typed nickname. */
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(cmd->argv[1], &nickname);
- else
- nickname = strdup(cmd->argv[1]);
- if (!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]);
if (!server_entry) {
+ if (cmd->resolved) {
+ /* Resolving didn't find anything. We should never get here as
+ errors are handled in the resolving callback. */
+ COMMAND_ERROR(SILC_STATUS_ERR_NO_SUCH_NICK);
+ COMMAND_ERROR(SILC_STATUS_ERR_NO_SUCH_SERVER);
+ return SILC_FSM_FINISH;
+ }
+
/* No client or server exist with this name, query for both. */
+ cmd->resolved = TRUE;
SILC_FSM_CALL(silc_client_command_send(client, conn,
SILC_COMMAND_IDENTIFY,
silc_client_command_continue,
strlen(cmd->argv[1]),
2, cmd->argv[1],
strlen(cmd->argv[1])));
+ /* NOT REACHED */
}
idp = silc_id_payload_encode(&server_entry->id, SILC_ID_SERVER);
+ silc_client_unref_server(client, conn, server_entry);
} else {
client_entry = silc_dlist_get(clients);
idp = silc_id_payload_encode(&client_entry->id, SILC_ID_CLIENT);
1, silc_buffer_datalen(idp));
silc_buffer_free(idp);
- silc_free(nickname);
/* Notify application */
COMMAND(SILC_STATUS_OK);
SilcCommandPayload payload,
SilcArgumentPayload args)
{
-#if 0
SilcDList attrs;
unsigned char *tmp;
SilcUInt32 tmp_len;
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
case SILC_COMMAND_WHOIS:
/* Ignore everything if requested by application */
- if (client->internal->params->ignore_requested_attributes)
+ if (conn->internal->params.ignore_requested_attributes)
break;
silc_client_command_process_whois(client, conn, payload, args);