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
/* Continue after last command reply received */
if (SILC_STATUS_IS_ERROR(status) || status == SILC_STATUS_OK ||
status == SILC_STATUS_LIST_END)
- SILC_FSM_CALL_CONTINUE(notify->fsm);
+ SILC_FSM_CALL_CONTINUE_SYNC(notify->fsm);
return TRUE;
}
}
if (!silc_notify_get_args(payload)) {
- SILC_LOG_DEBUG(("Malformed notify"));
+ SILC_LOG_DEBUG(("Malformed notify %d", silc_notify_get_type(payload)));
silc_notify_payload_free(payload);
silc_packet_free(packet);
return SILC_FSM_FINISH;
return SILC_FSM_FINISH;
}
- /* Save notify payload to packet context during processing */
notify->packet = packet;
notify->payload = payload;
notify->fsm = fsm;
SilcNotifyType type = silc_notify_get_type(payload);
SilcArgumentPayload args = silc_notify_get_args(payload);
+ SILC_LOG_DEBUG(("Notify: NONE"));
+
/* Notify application */
NOTIFY(client, conn, type, silc_argument_get_arg_type(args, 1, NULL));
/* Get the channel entry */
channel = silc_client_get_channel_by_id(client, conn, &id.u.channel_id);
+ if (!channel)
+ goto out;
/* If channel is being resolved handle notify after resolving */
if (channel->internal.resolve_cmd_ident) {
}
if (client_entry != conn->local_entry)
- silc_client_nickname_format(client, conn, client_entry);
+ silc_client_nickname_format(client, conn, client_entry, FALSE);
/* Join the client to channel */
- if (!silc_client_add_to_channel(channel, client_entry, 0))
+ if (!silc_client_add_to_channel(client, conn, channel, client_entry, 0))
goto out;
/* Notify application. */
SilcArgumentPayload args = silc_notify_get_args(payload);
SilcClientEntry client_entry = NULL;
SilcChannelEntry channel = NULL;
- SilcChannelUser chu;
SilcID id;
SILC_LOG_DEBUG(("Notify: LEAVE"));
goto out;
/* Remove client from channel */
- chu = silc_client_on_channel(channel, client_entry);
- if (chu) {
- silc_hash_table_del(client_entry->channels, channel);
- silc_hash_table_del(channel->user_list, client_entry);
- silc_free(chu);
- }
-
-#if 0 /* Kind of useless, server will return error if client keeps using
- non-existing client, and the entry is removed then. */
- /* Some client implementations actually quit network by first doing
- LEAVE and then immediately SIGNOFF. We'll check for this by doing
- check for the client after 5 - 34 seconds. If it is not valid after
- that we'll remove the client from cache. */
- if (!silc_hash_table_count(client_entry->channels)) {
- SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
- res->context = client;
- res->sock = silc_socket_dup(conn->sock);
- res->packet = silc_id_dup(client_id, SILC_ID_CLIENT);
- silc_schedule_task_add(client->schedule, conn->sock->sock,
- silc_client_notify_check_client, res,
- (5 + (silc_rng_get_rn16(client->rng) % 29)),
- 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
- }
-#endif
+ silc_client_remove_from_channel(client, conn, channel, client_entry);
/* Notify application. */
NOTIFY(client, conn, type, client_entry, channel);
SilcClient client = conn->client;
SilcClientNotify notify = state_context;
SilcNotifyPayload payload = notify->payload;
+ SilcPacket packet = notify->packet;
SilcNotifyType type = silc_notify_get_type(payload);
SilcArgumentPayload args = silc_notify_get_args(payload);
SilcClientEntry client_entry;
- unsigned char *tmp;
+ SilcChannelEntry channel;
+ unsigned char *tmp;
SilcUInt32 tmp_len;
SilcID id;
/* Get signoff message */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (tmp_len > 128)
+ if (tmp && tmp_len > 128)
tmp[128] = '\0';
/* Notify application */
NOTIFY(client, conn, type, client_entry, tmp);
- /* Remove from all channels */
- silc_client_remove_from_channels(client, conn, client_entry);
-
-#if 0
- /* Remove from cache */
- silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
-#endif
+ /* Remove from channel */
+ if (packet->dst_id_type == SILC_ID_CHANNEL) {
+ if (silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL,
+ &id.u.channel_id, sizeof(id.u.channel_id))) {
+ channel = silc_client_get_channel_by_id(client, conn, &id.u.channel_id);
+ if (channel) {
+ silc_client_remove_from_channel(client, conn, channel, client_entry);
+ silc_client_unref_channel(client, conn, channel);
+ }
+ }
+ }
- /* Free data */
+ /* Delete client */
+ silc_client_del_client(client, conn, client_entry);
silc_client_unref_client(client, conn, client_entry);
- silc_client_del_client_entry(client, conn, client_entry);
out:
/** Notify processed */
SilcNotifyType type = silc_notify_get_type(payload);
SilcArgumentPayload args = silc_notify_get_args(payload);
SilcClientEntry client_entry = NULL;
- unsigned char *tmp, *nick, oldnick[128 + 1];
+ unsigned char *tmp, oldnick[128 + 1];
SilcUInt32 tmp_len;
SilcID id, id2;
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, &id2.u.client_id, NULL,
- NULL, FALSE);
+ silc_mutex_lock(conn->internal->lock);
+ silc_idcache_update_by_context(conn->internal->client_cache, client_entry,
+ &id2.u.client_id, NULL, FALSE);
+ silc_mutex_unlock(conn->internal->lock);
goto out;
}
- /* Normalize nickname */
- nick = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8, 128, NULL);
- if (!nick)
- goto out;
-
- /* Update nickname */
- if (!silc_idcache_update(conn->internal->client_cache, client_entry,
- NULL, NULL, client_entry->nickname_normalized,
- nick, TRUE)) {
- silc_free(nick);
- goto out;
- }
+ /* Change the nickname */
memcpy(oldnick, client_entry->nickname, sizeof(client_entry->nickname));
- memcpy(client_entry->nickname, tmp, tmp_len);
- client_entry->nickname_normalized = nick;
- silc_client_nickname_format(client, conn, client_entry);
+ if (!silc_client_change_nickname(client, conn, client_entry, tmp,
+ &id2.u.client_id, NULL, 0))
+ goto out;
/* Notify application */
NOTIFY(client, conn, type, client_entry, client_entry->nickname, oldnick);
chpks = silc_argument_list_parse_decoded(tmp, tmp_len,
SILC_ARGUMENT_PUBLIC_KEY);
+ /* XXX add to/remove from channel pubkeys channel->channel_pubkeys */
+
/* Notify application. */
NOTIFY(client, conn, type, id.type, entry, mode, cipher, hmac,
passphrase, channel->founder_key, chpks, channel);
/* NOT REACHED */
}
+ /* Get target Client ID */
+ if (!silc_argument_get_decoded(args, 3, SILC_ARGUMENT_ID, &id2, NULL))
+ goto out;
+
+ /* Find target Client entry */
+ client_entry2 = silc_client_get_client_by_id(client, conn, &id2.u.client_id);
+ if (!client_entry2 || !client_entry2->nickname[0]) {
+ /** Resolve client */
+ silc_client_unref_client(client, conn, client_entry2);
+ SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
+ client, conn, &id2.u.client_id, NULL,
+ silc_client_notify_resolved,
+ notify));
+ /* NOT REACHED */
+ }
+
/* Get the mode */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (!tmp)
entry = channel_entry;
}
- /* Get target Client ID */
- if (!silc_argument_get_decoded(args, 3, SILC_ARGUMENT_ID, &id2, NULL))
- goto out;
-
- /* Find target Client entry */
- client_entry2 = silc_client_get_client_by_id(client, conn, &id2.u.client_id);
- if (!client_entry2 || !client_entry2->nickname[0]) {
- /** Resolve client */
- silc_client_unref_client(client, conn, client_entry);
- silc_client_unref_client(client, conn, client_entry2);
- SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
- client, conn, &id2.u.client_id, NULL,
- silc_client_notify_resolved,
- notify));
- /* NOT REACHED */
- }
-
/* Save the mode */
chu = silc_client_on_channel(channel, client_entry2);
if (chu)
SilcArgumentPayload args = silc_notify_get_args(payload);
SilcClientEntry client_entry, client_entry2;
SilcChannelEntry channel = NULL;
- SilcChannelUser chu;
unsigned char *tmp;
SilcUInt32 tmp_len;
SilcID id;
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
/* Remove kicked client from channel */
- if (client_entry != conn->local_entry) {
- chu = silc_client_on_channel(channel, client_entry);
- if (chu) {
- silc_hash_table_del(client_entry->channels, channel);
- silc_hash_table_del(channel->user_list, client_entry);
- silc_free(chu);
- }
- }
+ if (client_entry != conn->local_entry)
+ silc_client_remove_from_channel(client, conn, channel, client_entry);
/* Notify application. */
NOTIFY(client, conn, type, client_entry, tmp, client_entry2, channel);
if (client_entry == conn->local_entry) {
if (conn->current_channel == channel)
conn->current_channel = NULL;
+ silc_client_empty_channel(client, conn, channel);
silc_client_del_channel(client, conn, channel);
}
NOTIFY(client, conn, type, client_entry, comment, id.type, entry);
/* Delete the killed client */
- if (client_entry != conn->local_entry)
+ if (client_entry != conn->local_entry) {
+ silc_client_remove_from_channels(client, conn, client_entry);
silc_client_del_client(client, conn, client_entry);
+ }
out:
silc_client_unref_client(client, conn, client_entry);
SilcID id;
int i;
- SILC_LOG_DEBUG(("Notify: SIGNOFF"));
+ SILC_LOG_DEBUG(("Notify: SERVER_SIGNOFF"));
clients = silc_dlist_init();
if (!clients)
/* Delete the clients */
silc_dlist_start(clients);
- while ((client_entry = silc_dlist_get(clients)))
+ while ((client_entry = silc_dlist_get(clients))) {
+ silc_client_remove_from_channels(client, conn, client_entry);
silc_client_del_client(client, conn, client_entry);
+ }
out:
/** Notify processed */
goto out;
client_entry = silc_client_get_client_by_id(client, conn, &id.u.client_id);
if (client_entry) {
+ silc_client_remove_from_channels(client, conn, client_entry);
silc_client_del_client(client, conn, client_entry);
silc_client_unref_client(client, conn, client_entry);
}
if (tmp) {
char *tmp_nick = NULL;
- if (client->internal->params->nickname_parse)
- client->internal->params->nickname_parse(client_entry->nickname,
- &tmp_nick);
- else
- tmp_nick = strdup(tmp);
+ silc_client_nickname_parse(client, conn, client_entry->nickname,
+ &tmp_nick);
/* If same nick, the client was new to us and has become "present"
to network. Send NULL as nick to application. */
ntype == SILC_NOTIFY_TYPE_KILLED)
del_client = TRUE;
- if (del_client)
+ if (del_client) {
+ silc_client_remove_from_channels(client, conn, client_entry);
silc_client_del_client(client, conn, client_entry);
+ }
if (public_key)
silc_pkcs_public_key_free(public_key);