From: Pekka Riikonen Date: Sun, 25 Mar 2001 18:17:05 +0000 (+0000) Subject: updates. X-Git-Tag: SILC.0.1~102 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=4521e58680586069614f9029d9b925f416ae19ce;p=silc.git updates. --- diff --git a/CHANGES b/CHANGES index c835fdbe..100651d8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +Sun Mar 25 20:27:09 EEST 2001 Pekka Riikonen + + * Added function silc_server_get_client_resolve to find the + client entry by ID from all ID lists and then resolve it + (using WHOIS) if it cannot be found. Affected file is + silcd/server.[ch]. + Sun Mar 25 13:52:51 EEST 2001 Pekka Riikonen * Implemented the BAN command to the client library. diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 7bfbc62d..afd888f1 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -2090,39 +2090,28 @@ SILC_SERVER_CMD_FUNC(topic) silc_server_command_free(cmd); } -/* Server side of INVITE command. Invites some client to join some channel. */ +/* Server side of INVITE command. Invites some client to join some channel. + This command is also used to manage the invite list of the channel. */ SILC_SERVER_CMD_FUNC(invite) { SilcServerCommandContext cmd = (SilcServerCommandContext)context; SilcServer server = cmd->server; SilcSocketConnection sock = cmd->sock, dest_sock; + SilcChannelClientEntry chl; SilcClientEntry sender, dest; - SilcClientID *dest_id; + SilcClientID *dest_id = NULL; SilcChannelEntry channel; - SilcChannelID *channel_id; - SilcBuffer sidp; - unsigned char *tmp; + SilcChannelID *channel_id = NULL; + SilcIDListData idata; + SilcBuffer idp; + unsigned char *tmp, *add, *del; unsigned int len; SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2); - /* Get destination ID */ - tmp = silc_argument_get_arg_type(cmd->args, 1, &len); - if (!tmp) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, - SILC_STATUS_ERR_NO_CLIENT_ID); - goto out; - } - dest_id = silc_id_payload_parse_id(tmp, len); - if (!dest_id) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, - SILC_STATUS_ERR_NO_CLIENT_ID); - goto out; - } - /* Get Channel ID */ - tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + tmp = silc_argument_get_arg_type(cmd->args, 1, &len); if (!tmp) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, SILC_STATUS_ERR_NO_CHANNEL_ID); @@ -2135,7 +2124,7 @@ SILC_SERVER_CMD_FUNC(invite) goto out; } - /* Check whether the channel exists */ + /* Get the channel entry */ channel = silc_idlist_find_channel_by_id(server->local_list, channel_id, NULL); if (!channel) { @@ -2159,8 +2148,6 @@ SILC_SERVER_CMD_FUNC(invite) /* Check whether the channel is invite-only channel. If yes then the sender of this command must be at least channel operator. */ if (channel->mode & SILC_CHANNEL_MODE_INVITE) { - SilcChannelClientEntry chl; - silc_list_start(channel->user_list); while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) if (chl->client == sender) { @@ -2173,39 +2160,144 @@ SILC_SERVER_CMD_FUNC(invite) } } - /* Find the connection data for the destination. If it is local we will - send it directly otherwise we will send it to router for routing. */ - dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL); - if (dest) - dest_sock = (SilcSocketConnection)dest->connection; - else - dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT); + /* Get destination client ID */ + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + if (tmp) { + char invite[512]; - /* Check whether the requested client is already on the channel. */ - /* XXX if we are normal server we don't know about global clients on - the channel thus we must request it (USERS command), check from - local cache as well. */ - if (silc_server_client_on_channel(dest, channel)) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, - SILC_STATUS_ERR_USER_ON_CHANNEL); - goto out; + dest_id = silc_id_payload_parse_id(tmp, len); + if (!dest_id) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, + SILC_STATUS_ERR_NO_CLIENT_ID); + goto out; + } + + /* Get the client entry */ + dest = silc_server_get_client_resolve(server, dest_id); + if (!dest) { + if (server->server_type == SILC_ROUTER) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, + SILC_STATUS_ERR_NO_SUCH_CLIENT_ID); + goto out; + } + + /* The client info is being resolved. Reprocess this packet after + receiving the reply to the query. */ + silc_server_command_pending(server, SILC_COMMAND_WHOIS, + server->cmd_ident, + silc_server_command_destructor, + silc_server_command_invite, + silc_server_command_dup(cmd)); + cmd->pending = TRUE; + silc_free(channel_id); + silc_free(dest_id); + return; + } + + /* Check whether the requested client is already on the channel. */ + if (silc_server_client_on_channel(dest, channel)) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, + SILC_STATUS_ERR_USER_ON_CHANNEL); + goto out; + } + + /* Get route to the client */ + dest_sock = silc_server_get_client_route(server, tmp, len, &idata); + + strncat(invite, dest->nickname, strlen(dest->nickname)); + if (!strchr(dest->nickname, '@')) { + strncat(invite, "@", 1); + strncat(invite, server->server_name, strlen(server->server_name)); + } + strncat(invite, "!", 1); + strncat(invite, dest->username, strlen(dest->username)); + if (!strchr(dest->username, '@')) { + strncat(invite, "@", 1); + strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname)); + } + + len = strlen(invite); + if (!channel->invite_list) + channel->invite_list = silc_calloc(len + 2, + sizeof(*channel->invite_list)); + else + channel->invite_list = silc_realloc(channel->ban_list, + sizeof(*channel->invite_list) * + (len + + strlen(channel->invite_list) + 2)); + strncat(channel->invite_list, invite, len); + strncat(channel->invite_list, ",", 1); + + /* Send notify to the client that is invited to the channel */ + idp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT); + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, + SILC_ID_CLIENT, + SILC_NOTIFY_TYPE_INVITE, 2, + idp->data, idp->len, tmp, len); + silc_buffer_free(idp); } - sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT); + /* Add the client to the invite list of the channel */ + add = silc_argument_get_arg_type(cmd->args, 3, &len); + if (add && strlen(add) == len) { + if (!channel->invite_list) + channel->invite_list = silc_calloc(len + 2, + sizeof(*channel->invite_list)); + else + channel->invite_list = silc_realloc(channel->ban_list, + sizeof(*channel->invite_list) * + (len + + strlen(channel->invite_list) + 2)); + if (add[len - 1] == ',') + add[len - 1] = '\0'; + + strncat(channel->invite_list, add, len); + strncat(channel->invite_list, ",", 1); + } + + /* Get the invite to be removed and remove it from the list */ + del = silc_argument_get_arg_type(cmd->args, 4, &len); + if (del && channel->invite_list) { + char *start, *end, *n; + + if (!strncmp(channel->invite_list, del, + strlen(channel->invite_list) - 1)) { + silc_free(channel->invite_list); + channel->invite_list = NULL; + goto out0; + } + + start = strstr(channel->invite_list, del); + if (start && strlen(start) >= len) { + end = start + len; + n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n)); + strncat(n, channel->invite_list, start - channel->invite_list); + strncat(n, end + 1, ((channel->invite_list + + strlen(channel->invite_list)) - end) - 1); + silc_free(channel->invite_list); + channel->invite_list = n; + } + } + + out0: + + idp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT); + + /* Send notify to the primary router */ - /* Send notify to the client that is invited to the channel */ - silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, - SILC_ID_CLIENT, - SILC_NOTIFY_TYPE_INVITE, 2, - sidp->data, sidp->len, tmp, len); /* Send command reply */ silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, SILC_STATUS_OK); - silc_buffer_free(sidp); + silc_buffer_free(idp); out: + if (dest_id) + silc_free(dest_id); + if (channel_id) + silc_free(channel_id); silc_server_command_free(cmd); } @@ -4437,7 +4529,7 @@ SILC_SERVER_CMD_FUNC(ban) /* Get the new ban and add it to the ban list */ add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); - if (add) { + if (add && strlen(add) == tmp_len) { if (!channel->ban_list) channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list)); else @@ -4445,6 +4537,9 @@ SILC_SERVER_CMD_FUNC(ban) sizeof(*channel->ban_list) * (tmp_len + strlen(channel->ban_list) + 2)); + if (add[tmp_len - 1] == ',') + add[tmp_len - 1] = '\0'; + strncat(channel->ban_list, add, tmp_len); strncat(channel->ban_list, ",", 1); } diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index b5c17daf..f756df13 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -385,7 +385,7 @@ silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname, /* XXX This actually checks the data, which can be hash of the nickname but is not if the client is local client. Global client on global list may have hash. Thus, this is not fully reliable function. - Instead this should probably check the hash from the lists client ID's. */ + Instead this should probably check the hash from the list of client ID's. */ SilcClientEntry * silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname, diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 6df25f7b..61344524 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -3245,3 +3245,40 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server, return buffer; } + +/* Finds client entry by Client ID and if it is not found then resolves + it using WHOIS command. */ + +SilcClientEntry silc_server_get_client_resolve(SilcServer server, + SilcClientID *client_id) +{ + SilcClientEntry client; + + client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL); + if (!client) { + client = silc_idlist_find_client_by_id(server->global_list, + client_id, NULL); + if (!client && server->server_type == SILC_ROUTER) + return NULL; + } + + if (!client && server->standalone) + return NULL; + + if (!client || !client->nickname || !client->username) { + SilcBuffer buffer, idp; + + idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT); + buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS, + ++server->cmd_ident, 1, + 3, idp->data, idp->len); + silc_server_packet_send(server, client ? client->router->connection : + server->router->connection, + SILC_PACKET_COMMAND, 0, + buffer->data, buffer->len, FALSE); + silc_buffer_free(idp); + silc_buffer_free(buffer); + } + + return client; +} diff --git a/apps/silcd/server.h b/apps/silcd/server.h index d65394e1..ded8b808 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -163,5 +163,7 @@ SilcSocketConnection silc_server_get_client_route(SilcServer server, SilcIDListData *idata); SilcBuffer silc_server_get_client_channel_list(SilcServer server, SilcClientEntry client); +SilcClientEntry silc_server_get_client_resolve(SilcServer server, + SilcClientID *client_id); #endif diff --git a/doc/draft-riikonen-silc-pp-01.nroff b/doc/draft-riikonen-silc-pp-01.nroff index 1c8374fd..fed19883 100644 --- a/doc/draft-riikonen-silc-pp-01.nroff +++ b/doc/draft-riikonen-silc-pp-01.nroff @@ -1128,14 +1128,16 @@ ID's sent in arguments are sent inside ID Payload. is sent between routers and if the is argument is provided to the client as well. - Max Arguments: 4 - Arguments: (1) [] (2) - (3) [] (4) [] + Max Arguments: 5 + Arguments: (1) (2) [] + (3) [] (3) [] + (4) [] The is the client which was invited to the channel. - The is the channel. The and the - indicates the added or removed client from the - channel's invite list. The format of the is the channel. The is the + Client ID who invited the client to the channel. The + and the indicates the added or removed client from + the channel's invite list. The format of the is defined in the [SILC1] with SILC_COMMAND_INVITE command. diff --git a/doc/draft-riikonen-silc-spec-01.nroff b/doc/draft-riikonen-silc-spec-01.nroff index d641e083..7dda5ce7 100644 --- a/doc/draft-riikonen-silc-spec-01.nroff +++ b/doc/draft-riikonen-silc-spec-01.nroff @@ -2264,7 +2264,7 @@ List of all defined commands in SILC follows. 7 SILC_COMMAND_INVITE Max Arguments: 4 - Arguments: (1) [] (2) + Arguments: (1) (2) [] (3) [] (4) [] This command is used to invite other clients to join to the