+Mon Dec 3 18:49:45 EET 2001 Pekka Riikonen <priikone@silcnet.org>
+
+ * Do not print "you are now server operator" or similar when
+ giving /away command. Affected files are
+ irssi/src/silc/core/client_ops.c, silc-servers.h.
+
+ * Made the silc_server_command_pending_error_check to send
+ the same command reply payload it received back to the
+ original sender of the command. This way all arguments
+ that was received by the server will be received by the
+ client too. Affected file silcd/command.c.
+
+ * Added the silc_idcache_add to return the created cache entry
+ to a pointer. Affected file lib/silccore/silcidcache.[ch].
+
+ * Add global clients to expire if they are not on any channel.
+ This is because normal server will never know if they signoff
+ if they are not on any channel. The cache expiry will take
+ case of these entries. This is done by normal servers only.
+ The affected files are silcd/command_reply.c,
+ silcd/idlist.[ch], silcd/server and silcd/packet_receive.c.
+
+ * If server receives invalid ID notification for WHOIS or
+ IDENTIFY and the ID exists in the lists, it is removed.
+ Affected file silcd/command_reply.c.
+
+ * If NO_SUCH_CLIENT_ID is received for WHOIS or IDENTIFY command
+ in client then client entry that it matches is searched and
+ the nickname is printed on the screen for user. Affected
+ file irssi/src/silc/core/client_ops.c.
+
Mon Dec 3 11:56:59 EET 2001 Pekka Riikonen <priikone@silcnet.org>
* Use cache entry expire time in the LIST command reply to
TODO/bugs in Irssi SILC client
==============================
- o Setting /away prints server/router operator modes as well.
- Print modes that was just set only.
-
o Add local command to switch the channel's private key when channel has
several private keys. Currently sending channel messages with many
keys is not possible because changing the key is not possible by the
TODO/bugs In SILC Client Library
================================
- o N/A
+ o Process the NO_SUCH_CLIENT_ID for WHOIS and IDENTIFY, since it can
+ be received for example after sending MSG to non-existent client.
+ It actually should be done always when it is received and the old
+ entry should be removed.
+
+ Doing this now however causes that /msg nick might give "no such nick"
+ for the first time, and then after the entry is removed /msg nick
+ may actually to go any nick client, which is not desired behaviour.
+ The /msg must be fixed to use the specific nickname user typed
+ (nick must not match nick@host).
TODO/bugs In SILC Server
========================
- o Make the silc_server_command_pending_error_check function to
- take all arguments it received and put them to the reply it is
- sending. Otherwise for example WHOIS on normal server for bogus
- nickname does not print anything in the client.
-
o Backup router related issues
o Channel user mode changes are notified unnecessarely when
SilcBuffer channels;
SilcClientEntry client_entry;
- if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
- status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
- char *tmp;
- tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
- 3, NULL);
+ if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+ /* Print the unknown nick for user */
+ unsigned char *tmp =
+ silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+ 3, NULL);
if (tmp)
silc_say_error("%s: %s", tmp,
silc_client_command_status_message(status));
break;
+ } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+ /* Try to find the entry for the unknown client ID, since we
+ might have, and print the nickname of it for user. */
+ uint32 tmp_len;
+ unsigned char *tmp =
+ silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+ 2, &tmp_len);
+ if (tmp) {
+ SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (client_id) {
+ client_entry = silc_client_get_client_by_id(client, conn,
+ client_id);
+ if (client_entry && client_entry->nickname)
+ silc_say_error("%s: %s", client_entry->nickname,
+ silc_client_command_status_message(status));
+ silc_free(client_id);
+ }
+ }
}
if (!success)
}
break;
+ case SILC_COMMAND_IDENTIFY:
+ {
+ SilcClientEntry client_entry;
+
+ /* Identify command is used only internally by the client library
+ but it still might send some interesting stuff for user interface
+ so let's print errors. */
+
+ if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+ /* Print the unknown nick for user */
+ unsigned char *tmp =
+ silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+ 3, NULL);
+ if (tmp)
+ silc_say_error("%s: %s", tmp,
+ silc_client_command_status_message(status));
+ break;
+ } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+ /* Try to find the entry for the unknown client ID, since we
+ might have, and print the nickname of it for user. */
+ uint32 tmp_len;
+ unsigned char *tmp =
+ silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+ 2, &tmp_len);
+ if (tmp) {
+ SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (client_id) {
+ client_entry = silc_client_get_client_by_id(client, conn,
+ client_id);
+ if (client_entry && client_entry->nickname)
+ silc_say_error("%s: %s", client_entry->nickname,
+ silc_client_command_status_message(status));
+ silc_free(client_id);
+ }
+ }
+ }
+ }
+ break;
+
case SILC_COMMAND_WHOWAS:
{
char *nickname, *username, *realname;
mode = va_arg(vp, uint32);
- if (mode & SILC_UMODE_SERVER_OPERATOR)
+ if (mode & SILC_UMODE_SERVER_OPERATOR &&
+ !(server->umode & SILC_UMODE_SERVER_OPERATOR))
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
- if (mode & SILC_UMODE_ROUTER_OPERATOR)
+ if (mode & SILC_UMODE_ROUTER_OPERATOR &&
+ !(server->umode & SILC_UMODE_ROUTER_OPERATOR))
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
+
+ server->umode = mode;
}
break;
gpointer chanqueries;
SilcClientConnection conn;
+ uint32 umode;
} SILC_SERVER_REC;
SILC_SERVER_REC *silc_server_connect(SILC_SERVER_CONNECT_REC *conn);
status != SILC_STATUS_LIST_START &&
status != SILC_STATUS_LIST_ITEM &&
status != SILC_STATUS_LIST_END) {
- /* Send the error message */
- silc_server_command_send_status_reply(cmd, command, status);
+ SilcBuffer buffer;
+
+ /* Send the same command reply payload */
+ silc_command_set_ident(cmdr->payload,
+ silc_command_get_ident(cmd->payload));
+ buffer = silc_command_payload_encode_payload(cmdr->payload);
+ silc_server_packet_send(cmd->server, cmd->sock,
+ SILC_PACKET_COMMAND_REPLY, 0,
+ buffer->data, buffer->len, FALSE);
+ silc_buffer_free(buffer);
return TRUE;
}
/* Update client cache */
silc_idcache_add(server->local_list->clients, client->nickname,
- client->id, (void *)client, FALSE);
+ client->id, (void *)client, 0, NULL);
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
char global = FALSE;
char *nick;
uint32 mode = 0, len, id_len, flen;
+ int expire = 0;
id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
client = silc_idlist_add_client(server->global_list, nick,
strdup(username),
strdup(realname), client_id,
- cmd->sock->user_data, NULL);
+ cmd->sock->user_data, NULL,
+ time(NULL) + 300);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
return FALSE;
client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
+ /* If client is global and is not on any channel then add that we'll
+ expire the entry after a while. */
+ if (global && !silc_hash_table_count(client->channels) &&
+ server->server_type == SILC_SERVER)
+ expire = time(NULL) + 300;
+
/* Create new cache entry */
silc_idcache_add(global ? server->global_list->clients :
server->local_list->clients, nick, client->id,
- client, FALSE);
+ client, expire, NULL);
silc_free(client_id);
}
SILC_SERVER_CMD_REPLY_FUNC(whois)
{
SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+ SilcServer server = cmd->server;
SilcCommandStatus status;
COMMAND_CHECK_STATUS_LIST;
}
out:
+ /* If we received notify for invalid ID we'll remove the ID if we
+ have it cached. */
+ if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
+ cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ SilcClientEntry client;
+ uint32 tmp_len;
+ unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+ if (tmp) {
+ SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (client_id) {
+ SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
+ "the entry from cache"));
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, FALSE, NULL);
+ if (client)
+ silc_idlist_del_client(server->global_list, client);
+ silc_free(client_id);
+ }
+ }
+ }
+
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
silc_server_command_reply_free(cmd);
client = silc_idlist_add_client(server->global_list, nick,
strdup(username), strdup(realname),
silc_id_dup(client_id, SILC_ID_CLIENT),
- cmd->sock->user_data, NULL);
+ cmd->sock->user_data, NULL,
+ SILC_ID_CACHE_EXPIRE_DEF);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
return FALSE;
}
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
- client = silc_idlist_find_client_by_id(server->global_list,
- client_id, TRUE, &cache);
- cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
client->servername = servername;
} else {
/* We have the client already, update the data */
server->local_list->clients, client);
silc_idcache_add(global ? server->global_list->clients :
server->local_list->clients, nick, client->id,
- client, FALSE);
+ client, 0, NULL);
}
silc_free(client_id);
char *nick = NULL;
SilcIDPayload idp = NULL;
SilcIdType id_type;
+ int expire = 0;
id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
if (!id_data)
global. */
client = silc_idlist_add_client(server->global_list, nick,
info ? strdup(info) : NULL, NULL,
- client_id, cmd->sock->user_data, NULL);
+ client_id, cmd->sock->user_data, NULL,
+ time(NULL) + 300);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
goto error;
client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
if (name) {
+ /* If client is global and is not on any channel then add that we'll
+ expire the entry after a while. */
+ if (global && !silc_hash_table_count(client->channels) &&
+ server->server_type == SILC_SERVER)
+ expire = time(NULL) + 300;
+
/* Add new cache entry */
silc_idcache_add(global ? server->global_list->clients :
server->local_list->clients, nick, client->id,
- client, FALSE);
+ client, expire, NULL);
}
silc_free(client_id);
/* We don't have that server anywhere, add it. */
channel = silc_idlist_add_channel(server->global_list, strdup(name),
SILC_CHANNEL_MODE_NONE, channel_id,
- server->router,
- NULL, NULL);
+ server->router, NULL, NULL, 0);
if (!channel) {
silc_free(channel_id);
goto error;
SILC_SERVER_CMD_REPLY_FUNC(identify)
{
SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+ SilcServer server = cmd->server;
SilcCommandStatus status;
COMMAND_CHECK_STATUS_LIST;
}
out:
+ /* If we received notify for invalid ID we'll remove the ID if we
+ have it cached. */
+ if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
+ cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ SilcClientEntry client;
+ uint32 tmp_len;
+ unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+ if (tmp) {
+ SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (client_id) {
+ SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
+ "the entry from cache"));
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, FALSE, NULL);
+ if (client)
+ silc_idlist_del_client(server->global_list, client);
+ silc_free(client_id);
+ }
+ }
+ }
+
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
silc_server_command_reply_free(cmd);
/* Add the channel to our local list. */
entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
SILC_CHANNEL_MODE_NONE, id,
- server->router, NULL, hmac);
+ server->router, NULL, hmac, 0);
if (!entry) {
silc_free(id);
goto out;
uint32 len;
unsigned char *tmp, *name, *topic;
uint32 usercount = 0;
+ bool global_list = FALSE;
COMMAND_CHECK_STATUS_LIST;
/* Add the channel entry if we do not have it already */
channel = silc_idlist_find_channel_by_name(server->local_list,
name, &cache);
- if (!channel)
+ if (!channel) {
channel = silc_idlist_find_channel_by_name(server->global_list,
name, &cache);
+ global_list = TRUE;
+ }
if (!channel) {
/* If router did not find such channel in its lists then this must
be bogus channel or some router in the net is buggy. */
channel = silc_idlist_add_channel(server->global_list, strdup(name),
SILC_CHANNEL_MODE_NONE, channel_id,
- server->router, NULL, NULL);
+ server->router, NULL, NULL,
+ time(NULL) + 60);
if (!channel)
goto out;
-
- /* Update cache entry expiry */
- if (silc_idlist_find_channel_by_id(server->global_list, channel_id,
- &cache))
- cache->expire = time(NULL) + 60;
-
channel_id = NULL;
} else {
/* Found, update expiry */
- cache->expire = time(NULL) + 60;
+ if (global_list && server->server_type == SILC_SERVER)
+ cache->expire = time(NULL) + 60;
}
if (topic) {
silc_idcache_purge(i->cache);
silc_schedule_task_add(i->schedule, 0,
silc_idlist_purge,
- (void *)i, 600, 0,
+ (void *)i, i->timeout, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
}
server->connection = connection;
if (!silc_idcache_add(id_list->servers, server->server_name,
- (void *)server->id, (void *)server, FALSE)) {
+ (void *)server->id, (void *)server, 0, NULL)) {
silc_free(server);
return NULL;
}
server->id = new_id;
silc_idcache_add(id_list->servers, server->server_name, server->id,
- server, FALSE);
+ server, 0, NULL);
SILC_LOG_DEBUG(("Found"));
SilcClientEntry
silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
char *userinfo, SilcClientID *id,
- SilcServerEntry router, void *connection)
+ SilcServerEntry router, void *connection,
+ int expire)
{
SilcClientEntry client;
NULL, NULL, NULL, NULL, TRUE);
if (!silc_idcache_add(id_list->clients, nickname, (void *)client->id,
- (void *)client, FALSE)) {
+ (void *)client, expire, NULL)) {
silc_hash_table_free(client->channels);
silc_free(client);
return NULL;
silc_free(client->id);
client->id = new_id;
- silc_idcache_add(id_list->clients, NULL, client->id, client, FALSE);
+ silc_idcache_add(id_list->clients, NULL, client->id, client, 0, NULL);
SILC_LOG_DEBUG(("Replaced"));
SilcChannelEntry
silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
SilcChannelID *id, SilcServerEntry router,
- SilcCipher channel_key, SilcHmac hmac)
+ SilcCipher channel_key, SilcHmac hmac,
+ int expire)
{
SilcChannelEntry channel;
NULL, NULL, NULL, TRUE);
if (!silc_idcache_add(id_list->channels, channel->channel_name,
- (void *)channel->id, (void *)channel, FALSE)) {
+ (void *)channel->id, (void *)channel, expire, NULL)) {
silc_hmac_free(channel->hmac);
silc_hash_table_free(channel->user_list);
silc_free(channel);
channel->id = new_id;
silc_idcache_add(id_list->channels, channel->channel_name, channel->id,
- channel, FALSE);
+ channel, 0, NULL);
SILC_LOG_DEBUG(("Replaced"));
typedef struct {
SilcIDCache cache;
SilcSchedule schedule;
+ uint32 timeout;
} *SilcIDListPurge;
/* Channel key re-key context. */
SilcClientEntry
silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
char *userinfo, SilcClientID *id,
- SilcServerEntry router, void *connection);
+ SilcServerEntry router, void *connection,
+ int expire);
int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
char *server,
SilcChannelEntry
silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
SilcChannelID *id, SilcServerEntry router,
- SilcCipher channel_key, SilcHmac hmac);
+ SilcCipher channel_key, SilcHmac hmac,
+ int expire);
int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry);
SilcChannelEntry
silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
client =
silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
silc_id_dup(client_id, SILC_ID_CLIENT),
- sock->user_data, NULL);
+ sock->user_data, NULL, 0);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
silc_free(client_id);
if (!idp)
return;
- silc_server_send_command_reply(server, sock, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0, 1,
- 2, idp, idp->len);
+ if (packet->src_id_type == SILC_ID_CLIENT) {
+ SilcClientID *client_id = silc_id_str2id(packet->src_id,
+ packet->src_id_len,
+ packet->src_id_type);
+ silc_server_send_dest_command_reply(server, sock,
+ client_id, SILC_ID_CLIENT,
+ SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+ 0, 1, 2, idp->data, idp->len);
+ silc_free(client_id);
+ } else {
+ silc_server_send_command_reply(server, sock, SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+ 0, 1, 2, idp->data, idp->len);
+ }
+
silc_buffer_free(idp);
return;
}
/* Add the client again to the ID cache */
silc_idcache_add(server->local_list->clients, client->nickname,
- client_id, client, FALSE);
+ client_id, client, 0, NULL);
/* Notify our router about new client on the SILC network */
if (!server->standalone)
/* Add again the entry to the ID cache. */
silc_idcache_add(local ? server->local_list->servers :
server->global_list->servers, server_name, server_id,
- new_server, FALSE);
+ new_server, 0, NULL);
/* Distribute the information about new server in the SILC network
to our router. If we are normal server we won't send anything
global list. Cell wide information however is kept in the local
list. */
entry = silc_idlist_add_client(id_list, NULL, NULL, NULL,
- id, router, NULL);
+ id, router, NULL, 0);
if (!entry) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
sock->hostname));
silc_idlist_add_channel(server->global_list, strdup(channel_name),
- 0, channel_id, sock->user_data, NULL, NULL);
+ 0, channel_id, sock->user_data, NULL, NULL, 0);
server->stat.channels++;
}
} else {
va_end(ap);
}
+/* Generic function to send any command reply. The arguments must be sent
+ already encoded into correct form in correct order. */
+
+void silc_server_send_dest_command_reply(SilcServer server,
+ SilcSocketConnection sock,
+ void *dst_id,
+ SilcIdType dst_id_type,
+ SilcCommand command,
+ SilcCommandStatus status,
+ uint16 ident,
+ uint32 argc, ...)
+{
+ SilcBuffer packet;
+ va_list ap;
+
+ va_start(ap, argc);
+
+ packet = silc_command_reply_payload_encode_vap(command, status, ident,
+ argc, ap);
+ silc_server_packet_send_dest(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
+ dst_id, dst_id_type, packet->data,
+ packet->len, TRUE);
+ silc_buffer_free(packet);
+ va_end(ap);
+}
+
/* Send the heartbeat packet. */
void silc_server_send_heartbeat(SilcServer server,
SilcCommandStatus status,
uint16 ident,
uint32 argc, ...);
+void silc_server_send_dest_command_reply(SilcServer server,
+ SilcSocketConnection sock,
+ void *dst_id,
+ SilcIdType dst_id_type,
+ SilcCommand command,
+ SilcCommandStatus status,
+ uint16 ident,
+ uint32 argc, ...);
void silc_server_send_heartbeat(SilcServer server,
SilcSocketConnection sock);
void silc_server_relay_packet(SilcServer server,
purge = silc_calloc(1, sizeof(*purge));
purge->cache = server->local_list->clients;
purge->schedule = server->schedule;
+ purge->timeout = 600;
silc_schedule_task_add(purge->schedule, 0,
silc_idlist_purge,
- (void *)purge, 600, 0,
+ (void *)purge, purge->timeout, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
/* Clients global list */
purge = silc_calloc(1, sizeof(*purge));
purge->cache = server->global_list->clients;
purge->schedule = server->schedule;
+ purge->timeout = 300;
silc_schedule_task_add(purge->schedule, 0,
silc_idlist_purge,
- (void *)purge, 300, 0,
+ (void *)purge, purge->timeout, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
SILC_LOG_DEBUG(("Server initialized"));
and other information is created after we have received NEW_CLIENT
packet from client. */
client = silc_idlist_add_client(server->local_list,
- NULL, NULL, NULL, NULL, NULL, sock);
+ NULL, NULL, NULL, NULL, NULL, sock, 0);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to cache"));
silc_free(sock->user_data);
}
entry = silc_idlist_add_channel(server->local_list, channel_name,
SILC_CHANNEL_MODE_NONE, channel_id,
- NULL, key, newhmac);
+ NULL, key, newhmac, 0);
if (!entry) {
silc_free(channel_name);
silc_cipher_free(key);
/* Create the channel */
entry = silc_idlist_add_channel(server->local_list, channel_name,
SILC_CHANNEL_MODE_NONE, channel_id,
- NULL, key, newhmac);
+ NULL, key, newhmac, 0);
if (!entry) {
silc_free(channel_name);
return NULL;
uint32 user_count)
{
int i;
+ uint16 idp_len;
+ uint32 mode;
+ SilcClientID *client_id;
+ SilcClientEntry client;
+ SilcIDCacheEntry cache;
+ bool global;
for (i = 0; i < user_count; i++) {
- uint16 idp_len;
- uint32 mode;
- SilcClientID *client_id;
- SilcClientEntry client;
-
/* Client ID */
SILC_GET16_MSB(idp_len, user_list->data + 2);
idp_len += 4;
silc_free(client_id);
continue;
}
+
+ global = FALSE;
/* Check if we have this client cached already. */
client = silc_idlist_find_client_by_id(server->local_list, client_id,
- server->server_type, NULL);
- if (!client)
+ server->server_type, &cache);
+ if (!client) {
client = silc_idlist_find_client_by_id(server->global_list,
client_id, server->server_type,
- NULL);
+ &cache);
+ global = TRUE;
+ }
if (!client) {
/* If router did not find such Client ID in its lists then this must
be bogus client or some router in the net is buggy. */
global. */
client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
silc_id_dup(client_id, SILC_ID_CLIENT),
- sock->user_data, NULL);
+ sock->user_data, NULL, 0);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
silc_free(client_id);
}
client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+ } else {
+ /* Found, if it is from global list we'll assure that we won't
+ expire it now that the entry is on channel. */
+ if (global)
+ cache->expire = 0;
}
silc_free(client_id);
SILC_LOG_DEBUG(("Moving client to local list"));
silc_idcache_add(server->local_list->clients, client_cache->name,
client_cache->id, client_cache->context,
- client_cache->expire);
+ client_cache->expire, NULL);
silc_idcache_del_by_context(server->global_list->clients, client);
}
server_entry = server_entry->router;
SILC_LOG_DEBUG(("Moving client to local list"));
silc_idcache_add(server->local_list->clients, client_cache->name,
client_cache->id, client_cache->context,
- client_cache->expire);
+ client_cache->expire, NULL);
silc_idcache_del_by_context(server->global_list->clients, client);
}
}
SILC_LOG_DEBUG(("Moving client to global list"));
silc_idcache_add(server->global_list->clients, client_cache->name,
client_cache->id, client_cache->context,
- client_cache->expire);
+ client_cache->expire, NULL);
silc_idcache_del_by_context(server->local_list->clients, client);
}
server_entry = server_entry->router;
SILC_LOG_DEBUG(("Moving client to global list"));
silc_idcache_add(server->global_list->clients, client_cache->name,
client_cache->id, client_cache->context,
- client_cache->expire);
+ client_cache->expire, NULL);
silc_idcache_del_by_context(server->local_list->clients, client);
}
}
<FONT SIZE="+3" COLOR="#000044"><B>SILC Toolkit Reference Manual</B></FONT>
<BR>
Copyright (C) GNU GPL 2001 The SILC Project<BR>
-Version: 0.6.3<BR>
+Version: 0.7<BR>
Updated: @DATE@
<BR><BR>
<B><FONT SIZE="2">Note that this document is still under work and does not
/* Put it to the ID cache */
silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
- (void *)conn->local_entry, FALSE);
+ (void *)conn->local_entry, 0, NULL);
if (connecting) {
/* Issue INFO comqmand to fetch the real server name and server information
/* Put it to the ID cache */
silc_idcache_add(conn->channel_cache, channel->channel_name,
- (void *)channel->id, (void *)channel, FALSE);
+ (void *)channel->id, (void *)channel, 0, NULL);
return channel;
}
/* Add the channel entry again to ID cache */
silc_idcache_add(conn->channel_cache, channel->channel_name,
- channel->id, channel, FALSE);
+ channel->id, channel, 0, NULL);
/* Notify application */
client->ops->notify(client, conn, type, channel, channel);
conn->nickname = strdup(cmd->argv[1]);
conn->local_entry->nickname = conn->nickname;
silc_idcache_add(conn->client_cache, strdup(cmd->argv[1]),
- conn->local_entry->id, conn->local_entry, FALSE);
+ conn->local_entry->id, conn->local_entry, 0, NULL);
COMMAND;
} else {
COMMAND_ERROR;
/* Add server to cache */
silc_idcache_add(conn->server_cache, server_entry->server_name,
- server_entry->server_id, (void *)server_entry, FALSE);
+ server_entry->server_id, (void *)server_entry,
+ 0, NULL);
} else {
server_entry = (SilcServerEntry)id_cache->context;
}
/* Add it to the cache */
silc_idcache_add(conn->server_cache, server->server_name,
- server->server_id, (void *)server, FALSE);
+ server->server_id, (void *)server, 0, NULL);
if (SILC_ID_SERVER_COMPARE(server_id, conn->remote_id))
goto out;
/* Add client to cache, the non-formatted nickname is saved to cache */
if (!silc_idcache_add(conn->client_cache, nick, client_entry->id,
- (void *)client_entry, FALSE)) {
+ (void *)client_entry, 0, NULL)) {
silc_free(client_entry->nickname);
silc_free(client_entry->username);
silc_free(client_entry->hostname);
/* Remove the old cache entry and create a new one */
silc_idcache_del_by_context(conn->client_cache, client_entry);
silc_idcache_add(conn->client_cache, nick, client_entry->id,
- client_entry, FALSE);
+ client_entry, 0, NULL);
}
}
the entry never expires from the cache. */
bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
- void *context, int expire)
+ void *context, int expire, SilcIDCacheEntry *ret)
{
SilcIDCacheEntry c;
- uint32 curtime = time(NULL);
SILC_LOG_DEBUG(("Adding cache entry"));
c = silc_calloc(1, sizeof(*c));
c->id = id;
c->name = name;
- c->expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0);
+ c->expire = expire;
c->context = context;
/* Add the new entry to the hash tables */
silc_hash_table_rehash(cache->context_table, 0);
}
+ if (ret)
+ *ret = c;
+
return TRUE;
}
* Add new entry to the cache. Returns TRUE if the entry was added and
* FALSE if it could not be added. The `name' is the name associated with
* the ID, the `id' the actual ID and the `context' a used specific context.
- * If the `expire' is TRUE the entry expires in default time and if FALSE
- * the entry never expires from the cache.
+ * If the `expire' is non-zero the entry expires in that specified time.
+ * If zero the entry never expires from the cache.
+ *
+ * If the `ret' is non-NULL the created ID Cache entry is returned to
+ * that pointer.
*
***/
bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
- void *context, int expire);
+ void *context, int expire, SilcIDCacheEntry *ret);
/****f* silccore/SilcIDCacheAPI/silc_idcache_del
*
# SILC Distribution versions. Set here or give the version on the command
# line as argument.
#
-SILC_VERSION=0.6.2 # Base version
+SILC_VERSION=0.7 # Base version
#############################################################################
when necessary. This way we can move the data handling in one
place.
+ o Add silc_id_str2id to accept the destination buffer as argument
+ and thus not require any memory allocation. Same will happen
+ with silc_id_payload_* functions.
+
o Server
o When processing the decrypted and parsed packet we call the