+Mon Dec 17 18:24:27 EET 2001 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed JOIN command parsing not to crash. Affected file
+ lib/silcclient/command.c.
+
+ * Fied the NICK_CHANGE notify to add the new client entry
+ even it is resolved. This removes an <[unknown]> nick
+ thingy bug in the client. Affected file is
+ lib/silcclient/client_notify.c.
+
+ * Do not try to allocate 0 bytes (efence does not like it)
+ in lib/silccore/silccomand.c when encoding payload.
+
+ * Do not take IRCNICK as nickname in Irssi SILC client since
+ it is not possible to set nickname before hand connecting
+ the server (TODO has an entry about adding auto-nicking
+ support).
+
+ * Changed the silc_server_command_pending to check whether
+ there already exists an pending entry with the specified
+ command, command identifier and pending callback. This is
+ to fix IDENTIFY and WHOIS related crashes that may register
+ multiple pending commands with same identifier. Affected
+ file silcd/command.c.
+
+ * Fixed the server to reconnect to the router even if it
+ was already reconnecting and EOF was received. This to
+ fix a possibility that the server wouldn't ever try to
+ auto-reconnect to the router. Affected file silcd/server.c.
+
Sat Dec 15 20:31:50 EET 2001 Pekka Riikonen <priikone@silcnet.org>
* Fixed the server's password authentication to use the
cipher, hash, hmac and pkcs configuration to the Irssi SILC's config
file.
+ o Add auto-nick support to Irssi, so that the user specified nickname
+ would be sent to the server immediately (automatically) after the
+ client is connected to the server.
+
o Add PERL scripting support from Irssi CVS.
o Extend the /HELP command to support sub commands or something. So
behaviour and maybe should be removed. The changer should always
get the one it wants and not have the formatted nickname.
+ o Additions to do after protocol version 1.1:
-TODO/bugs In SILC Server
-========================
+ o Fix the NICK_CHANGE notify handling not to create new entry
+ for the changed client, but take the nickname from the notify
+ (removes need for resolving as well). Protocol TODO entry 3.
- o It is possible that IDENTIFy's check_client will register two pending
- callbacks for same ident, which must not happen. Check same for WHOIS
- as well.
+ o Add support for list of errors in command replies. Protocol
+ TODO entry 1.
- o If auto-reconnecting to router and EOF is received during the
- connecting phase the server will not try to auto-reconnect anymore
- after that. Fix to auto-reconnect.
+
+TODO/bugs In SILC Server
+========================
o Backup router related issues
TODO in SILC Protocol
=====================
- o Add "request parameters" or similar to the WHOIS command, which can
- be used to request various parameters (something not returned by
- standard WHOIS command) about clients (info that could be fetched
- even from clients). Additional specification (or appendix) should
- be done to define the payload and the parameters. It could be used
- to make the WHOIS command support various search conditions as well.
- This would be the way to extend the WHOIS command to support various
- new features without always making the command incompatible to previous
- version. To be included in protocol version 1.1.
-
- o Re-define the Status Payload: it is now 16 bits, split it into two
- 8 bits fields. First field includes status types from 0 - 9 and
- 10 - n *if* it is not an list of errors. If it is list of errors then
- the first field includes 1, 2 and/or 3, and the second field includes
- the error status 10 - n. This way it is possible to send multiple
- errors (list of errors) and we have a way to tell the receiver that
- there will be other errors as well. The second field is used only
- if there is list of errors. If normal status, or normal (single)
- error status the second field is set to zero, and must be ignored.
- Hence, the status works same way as now except for list of errors.
- To be included in protocol version 1.1.
-
- o Define that WHOIS and IDENTIFY commands must send list of errors
- if multiple Client ID (or Channel ID and Server ID for IDENTIFY) was
- requested and was not found. Each unfound entry must cause an error
- command reply to the sender. Also define that errors must be sent
- *after* sending successfully found entries (this way receiver may
- ignore them). To be included in protocol version 1.1.
+Current protocol version is 1.0. However, it is far from being perfect,
+and needs to include additional features. Following protocol TODO entries
+describe new stuff to be added to protocol versions 1.x.
+
+ 1. Re-define the Status Payload: it is now 16 bits, split it into two
+ 8 bits fields. First field includes status types from 0 - 9 and
+ 10 - n *if* it is not an list of errors. If it is list of errors then
+ the first field includes 1, 2 and/or 3, and the second field includes
+ the error status 10 - n. This way it is possible to send multiple
+ errors (list of errors) and we have a way to tell the receiver that
+ there will be other errors as well. The second field is used only
+ if there is list of errors. If normal status, or normal (single)
+ error status the second field is set to zero, and must be ignored.
+ Hence, the status works same way as now except for list of errors.
+ To be included in protocol version 1.1.
+
+ 2. Define that WHOIS and IDENTIFY commands must send list of errors
+ if multiple Client ID (or Channel ID and Server ID for IDENTIFY) was
+ requested and was not found. Each unfound entry must cause an error
+ command reply to the sender. Also define that errors must be sent
+ *after* sending successfully found entries (this way receiver may
+ ignore them). To be included in protocol version 1.1.
+
+ 3. Define the NICK_CHANGE notify to send the changed nickname as a new
+ third argument. This will make the NICK_CHANGE notify handling easier
+ in the receiver's end (client primarily) since it removes the
+ requirement that receiver must resolve (using IDENTIFY or WHOIS) the
+ new Client ID received in the notify (because of the new nickname is
+ unknown). To be included in protocol version 1.1.
+
+ 4. Add "request parameters" or similar to the WHOIS command, which can
+ be used to request various parameters (something not returned by
+ standard WHOIS command) about clients (info that could be fetched
+ even from clients). Additional specification (or appendix) should
+ be done to define the payload and the parameters. It could be used
+ to make the WHOIS command support various search conditions as well.
+ This would be the way to extend the WHOIS command to support various
+ new features without always making the command incompatible to previous
+ version. To be included in protocol version 1.1.
TODO After 1.0
nick = silc_nicklist_find(chanrec, sender);
if (!nick) {
- /* We didn't find client but it clearly exists, add it. */
+ /* We didn't find client but it clearly exists, add it. It must be
+ found on the channel->clients list. */
SilcChannelUser chu;
silc_list_start(channel->clients);
user_name = settings_get_str("user_name");
}
-
+
/* nick */
+ /* Actually take SILCUSER or IRCUSER since nickname cannot be set
+ beforehand in SILC (XXX auto-nicking support should be added to Irssi). */
nick = settings_get_str("nick");
if (nick == NULL || *nick == '\0') {
- str = g_getenv("SILCNICK");
+ str = g_getenv("SILCUSER");
if (!str)
- str = g_getenv("IRCNICK");
+ str = g_getenv("IRCUSER");
settings_set_str("nick", str != NULL ? str : user_name);
nick = settings_get_str("nick");
with `context' when reply has been received. It can be SILC_COMMAND_NONE
to match any command with the `ident'. If `ident' is non-zero
the `callback' will be executed when received reply with command
- identifier `ident'. */
+ identifier `ident'. If there already exists pending command for the
+ specified command, ident, callback and context this function has no
+ effect. */
-void silc_server_command_pending(SilcServer server,
+bool silc_server_command_pending(SilcServer server,
SilcCommand reply_cmd,
uint16 ident,
SilcServerPendingDestructor destructor,
{
SilcServerCommandPending *reply;
+ /* Check whether identical pending already exists for same command,
+ ident, callback and callback context. If it does then it would be
+ error to register it again. */
+ silc_dlist_start(server->pending_commands);
+ while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
+ if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
+ reply->callback == callback && reply->context == context)
+ return FALSE;
+ }
+
reply = silc_calloc(1, sizeof(*reply));
reply->reply_cmd = reply_cmd;
reply->ident = ident;
reply->callback = callback;
reply->destructor = destructor;
silc_dlist_add(server->pending_commands, reply);
+
+ return TRUE;
}
/* Deletes pending command by reply command type. */
void silc_server_command_free(SilcServerCommandContext ctx);
SilcServerCommandContext
silc_server_command_dup(SilcServerCommandContext ctx);
-void silc_server_command_pending(SilcServer server,
+bool silc_server_command_pending(SilcServer server,
SilcCommand reply_cmd,
uint16 ident,
SilcServerPendingDestructor destructor,
sconn->backup_replace_port = ptr->backup_replace_port;
}
+ if (!server->router_conn && !sconn->backup)
+ server->router_conn = sconn;
+
silc_schedule_task_add(server->schedule, fd,
silc_server_connect_router,
(void *)sconn, 0, 1, SILC_TASK_TIMEOUT,
silc_free(sconn->backup_replace_ip);
silc_free(sconn);
}
+ if (sconn == server->router_conn)
+ server->router_conn = NULL;
/* Free the protocol object */
if (sock->protocol == protocol)
if (sock->user_data)
silc_server_free_sock_user_data(server, sock);
+ else if (server->router_conn && server->router_conn->sock == sock &&
+ !server->router && server->standalone)
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_connect_to_router,
+ server, 1, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+
silc_server_close_connection(server, sock);
return;
}
/* Check whether we have a backup router connection */
if (!backup_router || backup_router == user_data) {
silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
+ silc_server_connect_to_router,
server, 1, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
bool backup_router; /* TRUE if this is backup router */
bool backup_primary; /* TRUE if we've switched our primary
router to a backup router. */
+ SilcServerConnection router_conn; /* non-NULL when connecting to the
+ primary router, and NULL otherwise. */
/* Current command identifier, 0 not used */
uint16 cmd_ident;
SilcClientCommandReplyContext reply =
(SilcClientCommandReplyContext)context2;
+ SILC_LOG_DEBUG(("Start"));
+
if (reply) {
SilcCommandStatus status;
unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL);
/* Find Client entry and if not found resolve it */
client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
if (!client_entry2) {
+ /* Resolve the entry information */
silc_client_notify_by_server_resolve(client, conn, packet, client_id);
- goto out;
+
+ /* Add the new entry even though we resolved it. This is because we
+ want to replace the old entry with the new entry here right now. */
+ client_entry2 =
+ silc_client_add_client(client, conn, NULL, NULL, NULL,
+ silc_id_dup(client_id, SILC_ID_CLIENT),
+ client_entry->mode);
+
+ /* Replace old ID entry with new one on all channels. */
+ silc_client_replace_from_channels(client, conn, client_entry,
+ client_entry2);
} else {
if (client_entry2 != conn->local_entry)
silc_client_nickname_format(client, conn, client_entry2);
- }
- /* Remove the old from cache */
- silc_idcache_del_by_context(conn->client_cache, client_entry);
+ /* Remove the old from cache */
+ silc_idcache_del_by_context(conn->client_cache, client_entry);
- /* Replace old ID entry with new one on all channels. */
- silc_client_replace_from_channels(client, conn, client_entry,
- client_entry2);
+ /* Replace old ID entry with new one on all channels. */
+ silc_client_replace_from_channels(client, conn, client_entry,
+ client_entry2);
- /* Notify application */
- client->internal->ops->notify(client, conn, type,
- client_entry, client_entry2);
+ /* Notify application */
+ client->internal->ops->notify(client, conn, type,
+ client_entry, client_entry2);
- /* Free data */
- silc_client_del_client_entry(client, conn, client_entry);
+ /* Free data */
+ silc_client_del_client_entry(client, conn, client_entry);
+ }
break;
case SILC_NOTIFY_TYPE_CMODE_CHANGE:
name = cmd->argv[1];
for (i = 2; i < cmd->argc; i++) {
- if (!strcasecmp(cmd->argv[i], "-cipher") && cmd->argc >= i + 1) {
+ if (!strcasecmp(cmd->argv[i], "-cipher") && cmd->argc > i + 1) {
cipher = cmd->argv[i + 1];
i++;
- } else if (!strcasecmp(cmd->argv[i], "-hmac") && cmd->argc >= i + 1) {
+ } else if (!strcasecmp(cmd->argv[i], "-hmac") && cmd->argc > i + 1) {
hmac = cmd->argv[i + 1];
i++;
- } else if (!strcasecmp(cmd->argv[i], "-founder") && cmd->argc >= i + 1) {
+ } else if (!strcasecmp(cmd->argv[i], "-founder") && cmd->argc > i + 1) {
if (!strcasecmp(cmd->argv[i + 1], "-pubkey")) {
auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
cmd->client->private_key,
entry = (SilcChannelEntry)id_cache->context;
+ SILC_LOG_DEBUG(("Found"));
+
return entry;
}
entry = (SilcChannelEntry)id_cache->context;
+ SILC_LOG_DEBUG(("Found"));
+
return entry;
}
/* Return MAC. The caller knows the length of the MAC */
-unsigned char *silc_channel_mesage_get_mac(SilcChannelMessagePayload payload)
+unsigned char *silc_channel_message_get_mac(SilcChannelMessagePayload payload)
{
return payload->mac;
}
uint16 ident,
uint32 argc, va_list ap)
{
- unsigned char **argv;
+ unsigned char **argv = NULL;
uint32 *argv_lens = NULL, *argv_types = NULL;
unsigned char *x;
uint32 x_len;
uint32 x_type;
SilcBuffer buffer;
- int i, k;
-
- argv = silc_calloc(argc, sizeof(unsigned char *));
- argv_lens = silc_calloc(argc, sizeof(uint32));
- argv_types = silc_calloc(argc, sizeof(uint32));
-
- for (i = 0, k = 0; i < argc; i++) {
- x_type = va_arg(ap, uint32);
- x = va_arg(ap, unsigned char *);
- x_len = va_arg(ap, uint32);
+ int i, k = 0;
- if (!x_type || !x || !x_len)
- continue;
-
- argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
- memcpy(argv[k], x, x_len);
- argv_lens[k] = x_len;
- argv_types[k] = x_type;
- k++;
+ if (argc) {
+ argv = silc_calloc(argc, sizeof(unsigned char *));
+ argv_lens = silc_calloc(argc, sizeof(uint32));
+ argv_types = silc_calloc(argc, sizeof(uint32));
+
+ for (i = 0, k = 0; i < argc; i++) {
+ x_type = va_arg(ap, uint32);
+ x = va_arg(ap, unsigned char *);
+ x_len = va_arg(ap, uint32);
+
+ if (!x_type || !x || !x_len)
+ continue;
+
+ argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+ memcpy(argv[k], x, x_len);
+ argv_lens[k] = x_len;
+ argv_types[k] = x_type;
+ k++;
+ }
}
buffer = silc_command_payload_encode(cmd, k, argv, argv_lens,