res_argv[res_argc] = client_id_list->data;
res_argv_lens[res_argc] = idp_len;
- res_argv_types[res_argc] = res_argc + 5;
+ res_argv_types[res_argc] = res_argc + 4;
res_argc++;
}
silc_client_unref_client(client, conn, entry);
if (!client_entry)
return NULL;
+ silc_atomic_init8(&client_entry->internal.refcnt, 0);
client_entry->id = *id;
client_entry->internal.valid = TRUE;
client_entry->mode = mode;
SilcClientEntry client_entry)
{
silc_atomic_add_int8(&client_entry->internal.refcnt, 1);
+ SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
+ silc_atomic_get_int8(&client_entry->internal.refcnt) - 1,
+ silc_atomic_get_int8(&client_entry->internal.refcnt)));
}
/* Release reference of client entry */
void silc_client_unref_client(SilcClient client, SilcClientConnection conn,
SilcClientEntry client_entry)
{
+ if (client_entry)
+ SILC_LOG_DEBUG(("Client %p refcnt %d->%d", client_entry,
+ silc_atomic_get_int8(&client_entry->internal.refcnt),
+ silc_atomic_get_int8(&client_entry->internal.refcnt) - 1));
if (client_entry &&
silc_atomic_sub_int8(&client_entry->internal.refcnt, 1) == 0)
silc_client_del_client(client, conn, client_entry);
memset(newnick, 0, sizeof(newnick));
cp = client->internal->params->nickname_format;
- while (*cp) {
+ while (cp && *cp) {
if (*cp == '%') {
cp++;
continue;
if (!channel)
return NULL;
+ silc_atomic_init8(&channel->internal.refcnt, 0);
channel->id = *channel_id;
channel->mode = mode;
if (!server_entry || !server_id)
return NULL;
+ silc_atomic_init8(&server_entry->internal.refcnt, 0);
server_entry->id = *server_id;
if (server_name)
server_entry->server_name = strdup(server_name);
conn, SILC_COMMAND_NONE,
channel->internal.resolve_cmd_ident,
silc_client_notify_wait_continue,
- fsm));
+ notify));
/* NOT REACHED */
}
silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
conn, SILC_COMMAND_NONE,
channel->internal.resolve_cmd_ident,
silc_client_notify_wait_continue,
- fsm));
+ notify));
/* NOT REACHED */
}
silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
conn, SILC_COMMAND_NONE,
channel->internal.resolve_cmd_ident,
silc_client_notify_wait_continue,
- fsm));
+ notify));
/* NOT REACHED */
}
conn, SILC_COMMAND_NONE,
channel->internal.resolve_cmd_ident,
silc_client_notify_wait_continue,
- fsm));
+ notify));
/* NOT REACHED */
}
silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = client_entry;
silc_client_get_server_by_id_resolve(
client, conn, &id.u.server_id,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = server;
silc_client_get_channel_by_id_resolve(
client, conn, &id.u.channel_id,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = channel_entry;
SilcClientEntry client_entry = NULL;
unsigned char *tmp, *nick, oldnick[128 + 1];
SilcUInt32 tmp_len;
- SilcID id;
+ SilcID id, id2;
SILC_LOG_DEBUG(("Notify: NICK_CHANGE"));
SILC_ID_CLIENT_COMPARE(&id.u.client_id, conn->local_id))
goto out;
+ /* Get new Client ID */
+ if (!silc_argument_get_decoded(args, 2, SILC_ARGUMENT_ID, &id2, NULL))
+ goto out;
+
+ /* Ignore my ID */
+ if (conn->local_id &&
+ SILC_ID_CLIENT_COMPARE(&id2.u.client_id, conn->local_id))
+ goto out;
+
/* Find old Client entry */
client_entry = silc_client_get_client_by_id(client, conn, &id.u.client_id);
if (!client_entry || !client_entry->nickname[0]) {
SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
- /* Get new Client ID */
- if (!silc_argument_get_decoded(args, 2, SILC_ARGUMENT_ID, &id, NULL))
- goto out;
-
/* Take the new nickname */
tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
if (!tmp)
/* Check whether nickname changed at all. It is possible that nick
change notify is received but nickname didn't change, only the
ID changes. If Client ID hash match, nickname didn't change. */
- if (SILC_ID_COMPARE_HASH(&client_entry->id, &id.u.client_id) &&
+ if (SILC_ID_COMPARE_HASH(&client_entry->id, &id2.u.client_id) &&
silc_utf8_strcasecmp(tmp, client_entry->nickname)) {
/* Nickname didn't change. Update only Client ID. We don't notify
application because nickname didn't change. */
silc_idcache_update(conn->internal->client_cache, client_entry,
- &client_entry->id, &id.u.client_id, NULL, NULL, FALSE);
+ &client_entry->id, &id2.u.client_id, NULL,
+ NULL, FALSE);
goto out;
}
conn, SILC_COMMAND_NONE,
channel->internal.resolve_cmd_ident,
silc_client_notify_wait_continue,
- fsm));
+ notify));
/* NOT REACHED */
}
silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = client_entry;
silc_client_get_server_by_id_resolve(
client, conn, &id.u.server_id,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = server;
silc_client_get_channel_by_id_resolve(
client, conn, &id.u.channel_id,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = channel_entry;
conn, SILC_COMMAND_NONE,
channel->internal.resolve_cmd_ident,
silc_client_notify_wait_continue,
- fsm));
+ notify));
/* NOT REACHED */
}
silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = client_entry;
silc_client_get_server_by_id_resolve(
client, conn, &id.u.server_id,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = server;
silc_client_get_channel_by_id_resolve(
client, conn, &id.u.channel_id,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = channel_entry;
SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
client, conn, &id2.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
conn, SILC_COMMAND_NONE,
channel->internal.resolve_cmd_ident,
silc_client_notify_wait_continue,
- fsm));
+ notify));
/* NOT REACHED */
}
conn, SILC_COMMAND_NONE,
channel->internal.resolve_cmd_ident,
silc_client_notify_wait_continue,
- fsm));
+ notify));
/* NOT REACHED */
}
silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = client_entry2;
SILC_FSM_CALL(silc_client_get_server_by_id_resolve(
client, conn, &id.u.server_id,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = server;
SILC_FSM_CALL(silc_client_get_channel_by_id_resolve(
client, conn, &id.u.channel_id,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
entry = channel_entry;
SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
client, conn, &id.u.client_id, NULL,
silc_client_notify_resolved,
- fsm));
+ notify));
/* NOT REACHED */
}
silc_status_get_args(cmd->status, args, &arg1, &arg2); \
else \
cmd->status = error; \
- SILC_LOG_DEBUG(("Error in command reply")); \
+ SILC_LOG_DEBUG(("Error in command reply: %s", \
+ silc_get_status_message(cmd->status))); \
silc_client_command_callback(cmd, arg1, arg2); \
} while(0)
/* Check for error */
#define CHECK_STATUS(msg) \
- SILC_LOG_DEBUG(("Start")); \
+ SILC_LOG_DEBUG(("%s", silc_get_command_name(cmd->cmd))); \
if (cmd->error != SILC_STATUS_OK) { \
if (cmd->verbose) \
SAY(cmd->conn->client, cmd->conn, SILC_CLIENT_MESSAGE_ERROR, \
ERROR_CALLBACK(cmd->error); \
silc_client_command_process_error(cmd, state_context, cmd->error); \
silc_fsm_next(fsm, silc_client_command_reply_process); \
- return SILC_FSM_YIELD; \
+ return SILC_FSM_CONTINUE; \
}
/* Check for correct arguments */
silc_argument_get_arg_num(args) > max) { \
ERROR_CALLBACK(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
silc_fsm_next(fsm, silc_client_command_reply_process); \
- return SILC_FSM_YIELD; \
+ return SILC_FSM_CONTINUE; \
}
#define SAY cmd->conn->client->internal->ops->say
/* Default reply callback */
if (cmd->called) {
- SILC_LOG_DEBUG(("cp %p, ap %p", cp, ap));
silc_va_copy(cp, ap);
- SILC_LOG_DEBUG(("cp %p, ap %p", cp, ap));
cmd->conn->client->internal->ops->command_reply(
cmd->conn->client, cmd->conn, cmd->cmd, cmd->status,
cmd->error, cp);
silc_list_start(cmd->reply_callbacks);
while ((cb = silc_list_get(cmd->reply_callbacks)))
if (!cb->do_not_call) {
- SILC_LOG_DEBUG(("cp %p, ap %p", cp, ap));
silc_va_copy(cp, ap);
- SILC_LOG_DEBUG(("cp %p, ap %p", cp, ap));
- cb->do_not_call = cb->reply(cmd->conn->client, cmd->conn, cmd->cmd,
- cmd->status, cmd->error, cb->context, cp);
+ cb->do_not_call = !cb->reply(cmd->conn->client, cmd->conn, cmd->cmd,
+ cmd->status, cmd->error, cb->context, cp);
va_end(cp);
}
silc_mutex_lock(conn->internal->lock);
silc_list_start(conn->internal->pending_commands);
while ((cmd = silc_list_get(conn->internal->pending_commands))) {
- SILC_LOG_DEBUG(("cmd %p, command %d, ident %d", cmd, cmd->cmd,
- cmd->cmd_ident));
if ((cmd->cmd == command || cmd->cmd == SILC_COMMAND_NONE)
&& cmd->cmd_ident == cmd_ident) {
silc_list_del(conn->internal->pending_commands, cmd);
return SILC_FSM_FINISH;
}
- SILC_LOG_DEBUG(("cmd %p, command %d", cmd, cmd->cmd));
-
/* Signal command thread that command reply has arrived */
silc_fsm_set_state_context(&cmd->thread, payload);
silc_fsm_next(&cmd->thread, silc_client_command_reply_process);
SILC_FSM_STATE(silc_client_command_reply_processed)
{
SilcClientCommandContext cmd = fsm_context;
+ SilcClientConnection conn = cmd->conn;
SilcCommandPayload payload = state_context;
silc_command_payload_free(payload);
SILC_STATUS_IS_ERROR(cmd->status))
return SILC_FSM_FINISH;
+ /* Add back to pending command reply list */
+ silc_mutex_lock(conn->internal->lock);
+ cmd->resolved = FALSE;
+ silc_list_add(conn->internal->pending_commands, cmd);
+ silc_mutex_unlock(conn->internal->lock);
+
/** Wait more command payloads */
silc_fsm_next(fsm, silc_client_command_reply_wait);
return SILC_FSM_CONTINUE;
ERROR_CALLBACK(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
}
+ silc_client_ref_client(client, conn, client_entry);
} else {
silc_client_update_client(client, conn, client_entry,
nickname, username, realname, mode);
ERROR_CALLBACK(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
}
+ silc_client_ref_client(client, conn, client_entry);
} else {
silc_client_update_client(client, conn, client_entry,
name, info, NULL, 0);