From ed3133837d3466b1d9eb15278677d82971bbd35f Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 11 Apr 2002 19:42:02 +0000 Subject: [PATCH] updates. --- CHANGES | 6 + apps/irssi/src/silc/core/client_ops.c | 6 +- apps/irssi/src/silc/core/silc-servers.c | 2 +- apps/silcd/command.c | 22 +-- apps/silcd/command_reply.c | 2 +- apps/silcd/packet_receive.c | 193 ++++++++++++++++------ apps/silcd/server.c | 12 +- apps/silcd/server.h | 1 + apps/silcd/silcd.c | 2 +- doc/Makefile.am.pre | 72 ++++---- doc/draft-riikonen-silc-commands-03.nroff | 13 +- doc/draft-riikonen-silc-pp-05.nroff | 2 + doc/draft-riikonen-silc-spec-05.nroff | 4 +- lib/silcclient/client_notify.c | 27 ++- lib/silcutil/silcschedule.c | 8 +- 15 files changed, 250 insertions(+), 122 deletions(-) diff --git a/CHANGES b/CHANGES index 3a357a62..99dde0ab 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +Thu Apr 11 22:29:33 EEST 2002 Pekka Riikonen + + * Defined that server receives USERS command reply for private + and secret channels too. Updated protocol specs and the + code in server. Affected file silcd/command.c. + Thu Apr 11 16:32:08 EEST 2002 Pekka Riikonen * Changed the UMODE's mode mask argument to be optional. If diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index b4f71907..664d625a 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -335,6 +335,9 @@ void silc_notify(SilcClient client, SilcClientConnection conn, client_entry = va_arg(va, SilcClientEntry); client_entry2 = va_arg(va, SilcClientEntry); + + if (!strcmp(client_entry->nickname, client_entry2->nickname)) + break; memset(userhost, 0, sizeof(userhost)); snprintf(userhost, sizeof(userhost) - 1, "%s@%s", @@ -1913,8 +1916,7 @@ silc_detach(SilcClient client, SilcClientConnection conn, /* Save the detachment data to file. */ memset(file, 0, sizeof(file)); - snprintf(file, sizeof(file) - 1, "%s/session.%s.%d", get_irssi_dir(), - conn->remote_host, conn->remote_port); + snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir()); silc_file_writefile(file, detach_data, detach_data_len); } diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index fdcbd431..9ae0003b 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -204,7 +204,7 @@ static void sig_connected(SILC_SERVER_REC *server) /* Try to read detached session data and use it if found. */ memset(¶ms, 0, sizeof(params)); memset(file, 0, sizeof(file)); - snprintf(file, sizeof(file) - 1, "%s/session.%s.%d", get_irssi_dir(), + snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir(), server->connrec->address, server->connrec->port); params.detach_data = silc_file_readfile(file, ¶ms.detach_data_len); diff --git a/apps/silcd/command.c b/apps/silcd/command.c index afb9e539..dd8a43fe 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -791,9 +791,8 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd, SILC_PUT32_MSB(entry->mode, mode); - if (entry->connection) { + if (entry->connection) SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle); - } packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS, @@ -2457,7 +2456,7 @@ SILC_SERVER_CMD_FUNC(invite) } /* Get the client entry */ - dest = silc_server_get_client_resolve(server, dest_id, &resolve); + dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve); if (!dest) { if (server->server_type != SILC_SERVER || !resolve) { silc_server_command_send_status_reply( @@ -3074,7 +3073,8 @@ static void silc_server_command_join_channel(SilcServer server, if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) { client = (SilcClientEntry)sock->user_data; } else { - client = silc_server_get_client_resolve(server, client_id, &resolve); + client = silc_server_get_client_resolve(server, client_id, FALSE, + &resolve); if (!client) { if (cmd->pending) goto out; @@ -5102,20 +5102,13 @@ SILC_SERVER_CMD_FUNC(users) } /* If the channel is private or secret do not send anything, unless the - user requesting this command is on the channel. */ + user requesting this command is on the channel or is server */ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) { if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET) && !silc_server_client_on_channel(cmd->sock->user_data, channel, NULL)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS, - SILC_STATUS_ERR_NO_SUCH_CHANNEL); - goto out; - } - } else { - if (channel->mode & - (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS, - SILC_STATUS_ERR_NO_SUCH_CHANNEL); + SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } } @@ -5198,7 +5191,8 @@ SILC_SERVER_CMD_FUNC(getkey) client_id, TRUE, NULL); if ((!client && !cmd->pending && !server->standalone) || - (client && !client->connection && !cmd->pending) || + (client && !client->connection && !cmd->pending && + !(client->mode & SILC_UMODE_DETACHED)) || (client && !client->data.public_key && !cmd->pending)) { SilcBuffer tmpbuf; SilcUInt16 old_ident; diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index ccb425f0..c524111b 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -988,7 +988,7 @@ SILC_SERVER_CMD_REPLY_FUNC(stats) } out: - SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS); + SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS); } SILC_SERVER_CMD_REPLY_FUNC(users) diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 29752416..eddd848a 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -464,7 +464,7 @@ void silc_server_notify(SilcServer server, if (client) { /* Send the NICK_CHANGE notify type to local clients on the channels this client is joined to. */ - silc_server_send_notify_on_channels(server, NULL, client, + silc_server_send_notify_on_channels(server, client, client, SILC_NOTIFY_TYPE_NICK_CHANGE, 3, id, tmp_len, id2, tmp_len, nickname, nickname ? @@ -1460,8 +1460,7 @@ void silc_server_private_message(SilcServer server, SilcBuffer idp; if (client && client->mode & SILC_UMODE_DETACHED) { - SILC_LOG_DEBUG(("Locally connected client is detached, " - "discarding packet")); + SILC_LOG_DEBUG(("Client is detached, discarding packet")); return; } @@ -1747,9 +1746,8 @@ SilcClientEntry silc_server_new_client(SilcServer server, SilcBuffer buffer = packet->buffer; SilcClientEntry client; SilcClientID *client_id; - SilcBuffer reply; SilcIDListData idata; - char *username = NULL, *realname = NULL, *id_string; + char *username = NULL, *realname = NULL; SilcUInt16 username_len; SilcUInt32 id_len; int ret; @@ -1925,17 +1923,8 @@ SilcClientEntry silc_server_new_client(SilcServer server, client->id, SILC_ID_CLIENT, id_len); /* Send the new client ID to the client. */ - id_string = silc_id_id2str(client->id, SILC_ID_CLIENT); - reply = silc_buffer_alloc_size(2 + 2 + id_len); - silc_buffer_format(reply, - SILC_STR_UI_SHORT(SILC_ID_CLIENT), - SILC_STR_UI_SHORT(id_len), - SILC_STR_UI_XNSTRING(id_string, id_len), - SILC_STR_END); - silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID, 0, - reply->data, reply->len, FALSE); - silc_free(id_string); - silc_buffer_free(reply); + silc_server_send_new_id(server, sock, FALSE, client->id, SILC_ID_CLIENT, + silc_id_get_len(client->id, SILC_ID_CLIENT)); /* Send some nice info to the client */ silc_server_send_connect_notifys(server, sock, client); @@ -2816,6 +2805,7 @@ typedef struct { SilcServer server; SilcSocketConnection sock; SilcPacketContext *packet; + void *data; } *SilcServerResumeResolve; SILC_SERVER_CMD_FUNC(resume_resolve) @@ -2824,8 +2814,11 @@ SILC_SERVER_CMD_FUNC(resume_resolve) SilcServer server = r->server; SilcSocketConnection sock = r->sock; SilcServerCommandReplyContext reply = context2; + SilcClientEntry client; + + SILC_LOG_DEBUG(("Start")); - if (!context2 || !silc_command_get_status(reply->payload, NULL, NULL)) { + if (!reply || !silc_command_get_status(reply->payload, NULL, NULL)) { SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, " "closing connection", sock->hostname, sock->ip)); silc_server_disconnect_remote(server, sock, @@ -2834,12 +2827,40 @@ SILC_SERVER_CMD_FUNC(resume_resolve) goto out; } + if (reply && silc_command_get(reply->payload) == SILC_COMMAND_WHOIS) { + /* Get entry to the client, and resolve it if we don't have it. */ + client = silc_idlist_find_client_by_id(server->local_list, + r->data, TRUE, NULL); + if (!client) { + client = silc_idlist_find_client_by_id(server->global_list, + r->data, TRUE, NULL); + if (!client) { + SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, " + "closing connection", sock->hostname, sock->ip)); + silc_server_disconnect_remote(server, sock, + "Server closed connection: " + "Incomplete resume information"); + goto out; + } + } + + if (!(client->mode & SILC_UMODE_DETACHED)) { + SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, " + "closing connection", sock->hostname, sock->ip)); + silc_server_disconnect_remote(server, sock, + "Server closed connection: " + "Incomplete resume information"); + goto out; + } + } + /* Reprocess the packet */ silc_server_resume_client(server, sock, r->packet); out: silc_socket_free(r->sock); silc_packet_context_free(r->packet); + silc_free(r->data); silc_free(r); } @@ -2859,9 +2880,14 @@ void silc_server_resume_client(SilcServer server, unsigned char *id_string, *auth = NULL; SilcUInt16 id_len, auth_len = 0; int ret, nickfail = 0; - bool resolved, local; + bool resolved, local, nick_change = FALSE; + SilcChannelEntry channel; + SilcHashTableList htl; + SilcChannelClientEntry chl; SilcServerResumeResolve r; + SILC_LOG_DEBUG(("Start")); + ret = silc_buffer_unformat(buffer, SILC_STR_UI16_NSTRING(&id_string, &id_len), SILC_STR_END); @@ -2871,9 +2897,6 @@ void silc_server_resume_client(SilcServer server, if (sock->type == SILC_SOCKET_TYPE_CLIENT) { /* Client send this and is attempting to resume to old client session */ SilcClientEntry client; - SilcChannelEntry channel; - SilcHashTableList htl; - SilcChannelClientEntry chl; SilcBuffer keyp; if (ret != -1) { @@ -2896,19 +2919,20 @@ void silc_server_resume_client(SilcServer server, idata = (SilcIDListData)client; /* Get entry to the client, and resolve it if we don't have it. */ - detached_client = silc_server_get_client_resolve(server, client_id, + detached_client = silc_server_get_client_resolve(server, client_id, FALSE, &resolved); if (!detached_client) { if (resolved) { /* The client info is being resolved. Reprocess this packet after receiving the reply to the query. */ + SILC_LOG_DEBUG(("Resolving client")); r = silc_calloc(1, sizeof(*r)); if (!r) return; - r->server = server; r->sock = silc_socket_dup(sock); r->packet = silc_packet_context_dup(packet); + r->data = silc_id_dup(client_id, SILC_ID_CLIENT); silc_server_command_pending(server, SILC_COMMAND_WHOIS, server->cmd_ident, silc_server_command_resume_resolve, r); @@ -2924,10 +2948,28 @@ void silc_server_resume_client(SilcServer server, /* Check that the client is detached */ if (!(detached_client->mode & SILC_UMODE_DETACHED)) { - SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, " - "closing connection", sock->hostname, sock->ip)); - silc_server_disconnect_remote(server, sock, "Server closed connection: " - "Incomplete resume information"); + if (server->server_type == SILC_SERVER && !server->standalone) { + /* The client info is being resolved. Reprocess this packet after + receiving the reply to the query. */ + SILC_LOG_DEBUG(("Resolving client mode")); + silc_server_get_client_resolve(server, client_id, TRUE, NULL); + r = silc_calloc(1, sizeof(*r)); + if (!r) + return; + r->server = server; + r->sock = silc_socket_dup(sock); + r->packet = silc_packet_context_dup(packet); + r->data = silc_id_dup(client_id, SILC_ID_CLIENT); + silc_server_command_pending(server, SILC_COMMAND_WHOIS, + server->cmd_ident, + silc_server_command_resume_resolve, r); + } else { + SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, " + "closing connection", sock->hostname, sock->ip)); + silc_server_disconnect_remote(server, sock, + "Server closed connection: " + "Incomplete resume information"); + } return; } @@ -2945,10 +2987,12 @@ void silc_server_resume_client(SilcServer server, SilcSocketConnection dest_sock = silc_server_get_client_route(server, NULL, 0, client_id, NULL, NULL); + SILC_LOG_DEBUG(("Resolving client public key")); + silc_server_send_command(server, dest_sock ? dest_sock : server->router->connection, SILC_COMMAND_GETKEY, ++server->cmd_ident, - 1, idp->data, idp->len); + 1, 1, idp->data, idp->len); r = silc_calloc(1, sizeof(*r)); if (!r) @@ -2993,17 +3037,27 @@ void silc_server_resume_client(SilcServer server, /* Send the RESUME_CLIENT packet to our primary router so that others know this client isn't detached anymore. */ - if (!server->standalone) { - buf = silc_buffer_alloc_size(2 + id_len); - silc_buffer_format(buf, - SILC_STR_UI_SHORT(id_len), - SILC_STR_UI_XNSTRING(id_string, id_len), - SILC_STR_END); + buf = silc_buffer_alloc_size(2 + id_len); + silc_buffer_format(buf, + SILC_STR_UI_SHORT(id_len), + SILC_STR_UI_XNSTRING(id_string, id_len), + SILC_STR_END); + + /* Send to primary router */ + if (!server->standalone) silc_server_packet_send(server, server->router->connection, SILC_PACKET_RESUME_CLIENT, 0, buf->data, buf->len, TRUE); - silc_buffer_free(buf); - } + + /* As router we must deliver this packet directly to the original + server whom this client was earlier. */ + if (server->server_type == SILC_ROUTER && detached_client->router) + silc_server_packet_send(server, detached_client->router->connection, + SILC_PACKET_RESUME_CLIENT, 0, + buf->data, buf->len, TRUE); + silc_buffer_free(buf); + + detached_client->router = NULL; /* Delete this client entry since we're resuming to old one. */ server->stat.my_clients--; @@ -3028,39 +3082,54 @@ void silc_server_resume_client(SilcServer server, snprintf(&client->nickname[strlen(client->nickname) - 1], 1, "%d", nickfail); } + nick_change = TRUE; + } + if (nick_change) { /* Notify about Client ID change, nickname doesn't actually change. */ if (!server->standalone) silc_server_send_notify_nick_change(server, server->router->connection, FALSE, client->id, client_id, client->nickname); - - silc_free(client->id); - client->id = client_id; + } + + /* Send the new client ID to the client. After this client may start + receiving other packets, and may start sending packets too. */ + silc_server_send_new_id(server, sock, FALSE, client_id, SILC_ID_CLIENT, + silc_id_get_len(client_id, SILC_ID_CLIENT)); + + if (nick_change) { + /* Send NICK change notify to channels as well. */ + SilcBuffer oidp, nidp; + oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); + nidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT); + silc_server_send_notify_on_channels(server, NULL, client, + SILC_NOTIFY_TYPE_NICK_CHANGE, 3, + oidp->data, oidp->len, + nidp->data, nidp->len, + client->nickname, + strlen(client->nickname)); + silc_buffer_free(oidp); + silc_buffer_free(nidp); } /* Add the client again to the ID cache to get it to correct list */ if (!silc_idcache_del_by_context(server->local_list->clients, client)) silc_idcache_del_by_context(server->global_list->clients, client); + silc_free(client->id); + client->id = client_id; + client_id = NULL; silc_idcache_add(server->local_list->clients, client->nickname, - client->id, client, client->mode, NULL); - - /* Send the new client ID to the client. */ - id_string = silc_id_id2str(client->id, SILC_ID_CLIENT); - buf = silc_buffer_alloc_size(2 + 2 + id_len); - silc_buffer_format(buf, - SILC_STR_UI_SHORT(SILC_ID_CLIENT), - SILC_STR_UI_SHORT(id_len), - SILC_STR_UI_XNSTRING(id_string, id_len), - SILC_STR_END); - silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID, 0, - buf->data, buf->len, FALSE); - silc_free(id_string); - silc_buffer_free(buf); + client->id, client, 0, NULL); /* Send some nice info to the client */ silc_server_send_connect_notifys(server, sock, client); + /* XXX normal server may not know about any joined channels!!! + Do this by saving the joined list in the resume_resolve callback. + Resolve it here with USERS per channel. */ + + /* Send all channel keys of channels the client has joined */ silc_hash_table_list(client->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void **)&chl)) { @@ -3079,6 +3148,7 @@ void silc_server_resume_client(SilcServer server, /* Send the key packet to client */ silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, keyp->data, keyp->len, FALSE); + channel->global_users = silc_server_channel_has_global(channel); } silc_hash_table_list_reset(&htl); @@ -3146,19 +3216,32 @@ void silc_server_resume_client(SilcServer server, } } + SILC_LOG_DEBUG(("Resuming detached client")); + /* Change the client to correct list. */ if (!silc_idcache_del_by_context(server->local_list->clients, detached_client)) silc_idcache_del_by_context(server->global_list->clients, detached_client); - silc_idcache_add(local ? server->local_list->clients : - server->global_list->clients, detached_client->nickname, + silc_idcache_add(local && server->server_type == SILC_ROUTER ? + server->local_list->clients : + server->global_list->clients, + detached_client->nickname, detached_client->id, detached_client, FALSE, NULL); /* Change the owner of the client if needed */ if (detached_client->router != server_entry) detached_client->router = server_entry; + /* Update channel information regarding global clients on channel. */ + if (server->server_type == SILC_SERVER) { + silc_hash_table_list(detached_client->channels, &htl); + while (silc_hash_table_get(&htl, NULL, (void **)&chl)) + chl->channel->global_users = + silc_server_channel_has_global(chl->channel); + silc_hash_table_list_reset(&htl); + } + /* If the sender of this packet is server and we are router we need to broadcast this packet to other routers in the network. */ if (!server->standalone && server->server_type == SILC_ROUTER && diff --git a/apps/silcd/server.c b/apps/silcd/server.c index bb633a65..064ff386 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -3888,6 +3888,7 @@ void silc_server_save_users_on_channel(SilcServer server, SilcClientID *client_id; SilcClientEntry client; SilcIDCacheEntry cache; + SilcChannelClientEntry chl; bool global; SILC_LOG_DEBUG(("Start")); @@ -3951,15 +3952,18 @@ void silc_server_save_users_on_channel(SilcServer server, silc_free(client_id); - if (!silc_server_client_on_channel(client, channel, NULL)) { + if (!silc_server_client_on_channel(client, channel, &chl)) { /* Client was not on the channel, add it. */ - SilcChannelClientEntry chl = silc_calloc(1, sizeof(*chl)); + chl = silc_calloc(1, sizeof(*chl)); chl->client = client; chl->mode = mode; chl->channel = channel; silc_hash_table_add(channel->user_list, chl->client, chl); silc_hash_table_add(client->channels, chl->channel, chl); channel->user_count++; + } else { + /* Update mode */ + chl->mode = mode; } } } @@ -4107,6 +4111,7 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server, SilcClientEntry silc_server_get_client_resolve(SilcServer server, SilcClientID *client_id, + bool always_resolve, bool *resolved) { SilcClientEntry client; @@ -4126,7 +4131,8 @@ SilcClientEntry silc_server_get_client_resolve(SilcServer server, if (!client && server->standalone) return NULL; - if (!client || !client->nickname || !client->username) { + if (!client || !client->nickname || !client->username || + always_resolve) { SilcBuffer buffer, idp; client->data.status |= SILC_IDLIST_STATUS_RESOLVING; diff --git a/apps/silcd/server.h b/apps/silcd/server.h index a90e7dd1..74326d19 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -219,6 +219,7 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server, SilcClientEntry client); SilcClientEntry silc_server_get_client_resolve(SilcServer server, SilcClientID *client_id, + bool always_resolve, bool *resolved); void silc_server_stderr(char *message); diff --git a/apps/silcd/silcd.c b/apps/silcd/silcd.c index 35693a71..53b7f81e 100644 --- a/apps/silcd/silcd.c +++ b/apps/silcd/silcd.c @@ -426,8 +426,8 @@ int main(int argc, char **argv) /* Stop the server and free it. */ silc_server_stop(silcd); - silc_server_free(silcd); silc_server_config_destroy(silcd->config); + silc_server_free(silcd); /* Flush the logging system */ silc_log_flush_all(); diff --git a/doc/Makefile.am.pre b/doc/Makefile.am.pre index 778714a4..504b53ce 100644 --- a/doc/Makefile.am.pre +++ b/doc/Makefile.am.pre @@ -24,19 +24,21 @@ DIST_SUBDIRS = SILC_DISTRIBUTION_SUBDIRS makerfc = ../scripts/makerfc all: - touch draft-riikonen-silc-spec-04.txt - touch draft-riikonen-silc-pp-04.txt - touch draft-riikonen-silc-ke-auth-04.txt - touch draft-riikonen-silc-commands-02.txt + touch draft-riikonen-silc-spec-05.txt + touch draft-riikonen-silc-pp-05.txt + touch draft-riikonen-silc-ke-auth-05.txt + touch draft-riikonen-silc-commands-03.txt + touch draft-riikonen-silc-flags-payloads-00.txt -cd .. if SILC_DIST_CLIENT dist-hook: rm draft-riikonen*.txt - touch draft-riikonen-silc-spec-04.txt - touch draft-riikonen-silc-pp-04.txt - touch draft-riikonen-silc-ke-auth-04.txt - touch draft-riikonen-silc-commands-02.txt + touch draft-riikonen-silc-spec-05.txt + touch draft-riikonen-silc-pp-05.txt + touch draft-riikonen-silc-ke-auth-05.txt + touch draft-riikonen-silc-commands-03.txt + touch draft-riikonen-silc-flags-payloads-00.txt else if SILC_DIST_TOOLKIT dist-hook: @@ -48,32 +50,38 @@ dist-hook: else \ echo ROBODoc is not compiled! Cannot generate documentation! ; \ fi - touch draft-riikonen-silc-spec-04.txt - touch draft-riikonen-silc-pp-04.txt - touch draft-riikonen-silc-ke-auth-04.txt - touch draft-riikonen-silc-commands-02.txt - $(makerfc) draft-riikonen-silc-spec-04.nroff \ - draft-riikonen-silc-spec-04.txt - $(makerfc) draft-riikonen-silc-pp-04.nroff \ - draft-riikonen-silc-pp-04.txt - $(makerfc) draft-riikonen-silc-ke-auth-04.nroff \ - draft-riikonen-silc-ke-auth-04.txt - $(makerfc) draft-riikonen-silc-commands-02.nroff \ - draft-riikonen-silc-commands-02.txt + touch draft-riikonen-silc-spec-05.txt + touch draft-riikonen-silc-pp-05.txt + touch draft-riikonen-silc-ke-auth-05.txt + touch draft-riikonen-silc-commands-03.txt + touch draft-riikonen-silc-flags-payloads-00.txt + $(makerfc) draft-riikonen-silc-spec-05.nroff \ + draft-riikonen-silc-spec-05.txt + $(makerfc) draft-riikonen-silc-pp-05.nroff \ + draft-riikonen-silc-pp-05.txt + $(makerfc) draft-riikonen-silc-ke-auth-05.nroff \ + draft-riikonen-silc-ke-auth-05.txt + $(makerfc) draft-riikonen-silc-commands-03.nroff \ + draft-riikonen-silc-commands-03.txt + $(makerfc) draft-riikonen-silc-flags-payloads-00.nroff \ + draft-riikonen-silc-flags-payloads-00.txt else dist-hook: - touch draft-riikonen-silc-spec-04.txt - touch draft-riikonen-silc-pp-04.txt - touch draft-riikonen-silc-ke-auth-04.txt - touch draft-riikonen-silc-commands-02.txt - $(makerfc) draft-riikonen-silc-spec-04.nroff \ - draft-riikonen-silc-spec-04.txt - $(makerfc) draft-riikonen-silc-pp-04.nroff \ - draft-riikonen-silc-pp-04.txt - $(makerfc) draft-riikonen-silc-ke-auth-04.nroff \ - draft-riikonen-silc-ke-auth-04.txt - $(makerfc) draft-riikonen-silc-commands-02.nroff \ - draft-riikonen-silc-commands-02.txt + touch draft-riikonen-silc-spec-05.txt + touch draft-riikonen-silc-pp-05.txt + touch draft-riikonen-silc-ke-auth-05.txt + touch draft-riikonen-silc-commands-03.txt + touch draft-riikonen-silc-flags-payloads-00.txt + $(makerfc) draft-riikonen-silc-spec-05.nroff \ + draft-riikonen-silc-spec-05.txt + $(makerfc) draft-riikonen-silc-pp-05.nroff \ + draft-riikonen-silc-pp-05.txt + $(makerfc) draft-riikonen-silc-ke-auth-05.nroff \ + draft-riikonen-silc-ke-auth-05.txt + $(makerfc) draft-riikonen-silc-commands-03.nroff \ + draft-riikonen-silc-commands-03.txt + $(makerfc) draft-riikonen-silc-flags-payloads-00.nroff \ + draft-riikonen-silc-flags-payloads-00.txt endif endif diff --git a/doc/draft-riikonen-silc-commands-03.nroff b/doc/draft-riikonen-silc-commands-03.nroff index c915a498..421013fe 100644 --- a/doc/draft-riikonen-silc-commands-03.nroff +++ b/doc/draft-riikonen-silc-commands-03.nroff @@ -1631,16 +1631,13 @@ List of all defined commands in SILC follows. This command is used to list user names currently on the requested channel; either the argument or the . One of these arguments must be present. The server MUST resolve - the user names and send a comma (`,') separated list of user names - on the channel. Server or router MAY resolve the names by sending - SILC_COMMAND_WHOIS or SILC_COMMAND_IDENTIFY commands. + the joined clients and reply with a lists of users on the channel + and with list of user modes on the channel. If the requested channel is a private or secret channel, this - command MUST NOT send the list of users, as private and secret - channels cannot be seen by outside. In this case the returned - name list MAY include a indication that the server could not - resolve the names of the users on the channel. Also, in this case - Client ID's or client modes are not sent either. + command MUST NOT send the list of users, but error is returned + to the sender, except if the sender is on the channel, or the + sender is server. Reply messages to the command: diff --git a/doc/draft-riikonen-silc-pp-05.nroff b/doc/draft-riikonen-silc-pp-05.nroff index b991f5a2..fcc4b850 100644 --- a/doc/draft-riikonen-silc-pp-05.nroff +++ b/doc/draft-riikonen-silc-pp-05.nroff @@ -1321,6 +1321,8 @@ UTF-8 [RFC2279] encoded. The is the old ID of the client which changed the nickname. The is the new ID generated by the change of the nickname. The is the new nickname. + Note that it is possible to send this notify even if the nickname + hasn't changed, but client ID has changed. 7 SILC_NOTIFY_TYPE_CMODE_CHANGE diff --git a/doc/draft-riikonen-silc-spec-05.nroff b/doc/draft-riikonen-silc-spec-05.nroff index e8ee4842..f039a94d 100644 --- a/doc/draft-riikonen-silc-spec-05.nroff +++ b/doc/draft-riikonen-silc-spec-05.nroff @@ -2164,7 +2164,9 @@ in the SKE protocol for this connection. If the signature is valid the server MUST unset the SILC_UMODE_DETACHED flag, and send the SILC_PACKET_RESUME_CLIENT packet to its primary router. The routers MUST broadcast the packet and unset the SILC_UMODE_DETACHED flag -when the packet is received. +when the packet is received. If the server is router server it also +MUST send the SILC_PACKET_RESUME_CLIENT packet to the original server +whom owned the detached client. The servers and routers that receives the SILC_PACKET_RESUME_CLIENT packet MUST know whether the packet already has been received for diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index 1e777858..50aebb3c 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -456,7 +456,7 @@ void silc_client_notify_by_server(SilcClient client, goto out; /* Ignore my ID */ - if (SILC_ID_CLIENT_COMPARE(client_id, conn->local_id)) + if (conn->local_id && SILC_ID_CLIENT_COMPARE(client_id, conn->local_id)) break; /* Find old Client entry */ @@ -482,6 +482,31 @@ void silc_client_notify_by_server(SilcClient client, tmp = silc_argument_get_arg_type(args, 3, NULL); if (tmp) { /* Protocol version 1.1 */ + char *tmp_nick; + + /* Check whether nickname changed at all. It is possible that nick + change notify is received but nickname didn't changed, only the + ID changes. */ + if (client->internal->params->nickname_parse) + client->internal->params->nickname_parse(client_entry->nickname, + &tmp_nick); + else + tmp_nick = strdup(tmp); + + if (!strcmp(tmp, tmp_nick)) { + /* Nickname didn't change. Update only the ID */ + silc_idcache_del_by_context(conn->client_cache, client_entry); + silc_free(client_entry->id); + client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT); + silc_idcache_add(conn->client_cache, strdup(tmp), + client_entry->id, client_entry, 0, NULL); + + /* Notify application */ + client->internal->ops->notify(client, conn, type, + client_entry, client_entry); + break; + } + silc_free(tmp_nick); /* Create new client entry, and save all old information with the new nickname and client ID */ diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index 828e7874..db939c3a 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -936,6 +936,7 @@ static void silc_task_queue_alloc(SilcTaskQueue *queue) static void silc_task_queue_free(SilcTaskQueue queue) { silc_mutex_free(queue->lock); + memset(queue, 'F', sizeof(*queue)); silc_free(queue); } @@ -1172,10 +1173,11 @@ static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task) next = first; while(1) { - next = next->next; - silc_free(next->prev); - if (next == first) + old = next->next; + silc_free(next); + if (old == first) break; + next = old; } queue->task = NULL; -- 2.24.0