From 59fbe94ee4413d7e900d246cfabecc26258b0b8c Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Mon, 26 Mar 2001 10:25:05 +0000 Subject: [PATCH] updates. --- CHANGES | 12 +++ README | 16 +++ TODO | 10 +- apps/silc/client_ops.c | 25 ++++- apps/silcd/command.c | 114 +++++++++++--------- apps/silcd/packet_receive.c | 101 +++++++++++++++--- apps/silcd/packet_send.c | 30 +++++- apps/silcd/packet_send.h | 7 ++ apps/silcd/server.c | 16 ++- apps/silcd/server.h | 1 + apps/silcd/testi2.conf | 29 +++--- doc/draft-riikonen-silc-pp-01.nroff | 30 +++--- doc/draft-riikonen-silc-spec-01.nroff | 8 +- lib/silcclient/client_notify.c | 36 +++---- lib/silcclient/command.c | 145 ++++++++++++++++++-------- lib/silcclient/command_reply.c | 29 +++++- 16 files changed, 430 insertions(+), 179 deletions(-) diff --git a/CHANGES b/CHANGES index 100651d8..f20ba39e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,15 @@ +Mon Mar 26 12:11:14 EEST 2001 Pekka Riikonen + + * Added silc_server_send_notify_invite to send the INVITE + notify between routers. + + * Implemented the INVITE command correctly to the server. + + * Implemented the INVITE notify type handling in the server. + + * Implemented the INVITE command to the client library and on the + user interface. + Sun Mar 25 20:27:09 EEST 2001 Pekka Riikonen * Added function silc_server_get_client_resolve to find the diff --git a/README b/README index 215f04f9..dfff7705 100644 --- a/README +++ b/README @@ -137,6 +137,22 @@ SILC Commands Gives a little history information about a client. + /INVITE [[@server>] + [+|-[[@[![@hostname>]]]]] + + Invites client to a channel or manages the invite list of + the channel. The first argument is used if an + client is invited to the channel. The second +|- + argument is used to either add or delete invite from the + channel's invite list. Wildcards may be used with this + command. + + /BAN [+|-[[@[![@hostname>]]]]] + + Manages the ban list of the channel. Wildcards may be used + with this command. You must be channel operator to be + able to use this command. + /KICK [@] [] Kicks client from channel. You have to be at least channel diff --git a/TODO b/TODO index 5cab4692..06677ae7 100644 --- a/TODO +++ b/TODO @@ -100,12 +100,9 @@ TODO In SILC Client Library TODO In SILC Server =================== - o TODO in command.c and in command_reply.c: + o TODO in commands (command.c and command_reply.c): - o BAN is not implemented o RESTART is not implemented - o INVITE is not working correctly - o JOIN does not check the invite and ban lists o CMODE should be rewritten as it uses a lot duplicated code. Some of the modes may still not be implemented or is implemented the wrong way. @@ -116,7 +113,10 @@ TODO In SILC Server situation correctly when it is called as pending command (it should most likely check that cmd->pending == TRUE/FALSE). - o Implement the SILC_NOTIFY_TYPE_SERVER_QUIT notify type to the server. + o TODO in notify types (packet_receive.c): + + o CHANNEL_CHANGE notify type is not implemented + o SERVER_SIGNOFF notify type is not implemented o Packet processing can be made faster. All packet function in the packet_receive.c has same prototypes. Instead of calling those from diff --git a/apps/silc/client_ops.c b/apps/silc/client_ops.c index e71e8ac9..b9748452 100644 --- a/apps/silc/client_ops.c +++ b/apps/silc/client_ops.c @@ -102,10 +102,11 @@ void silc_notify(SilcClient client, SilcClientConnection conn, break; case SILC_NOTIFY_TYPE_INVITE: + (void)va_arg(vp, SilcChannelEntry); + tmp = va_arg(vp, char *); client_entry = va_arg(vp, SilcClientEntry); - channel_entry = va_arg(vp, SilcChannelEntry); snprintf(message, sizeof(message), "%s invites you to channel %s", - client_entry->nickname, channel_entry->channel_name); + client_entry->nickname, tmp); break; case SILC_NOTIFY_TYPE_JOIN: @@ -548,6 +549,26 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn, } break; + case SILC_COMMAND_INVITE: + { + SilcChannelEntry channel; + char *invite_list; + + if (!success) + return; + + channel = va_arg(vp, SilcChannelEntry); + invite_list = va_arg(vp, char *); + + if (invite_list) + silc_say(client, conn, "%s invite list: %s", channel->channel_name, + invite_list); + else + silc_say(client, conn, "%s invite list not set", + channel->channel_name); + } + break; + case SILC_COMMAND_JOIN: { unsigned int mode; diff --git a/apps/silcd/command.c b/apps/silcd/command.c index afd888f1..43cc4d21 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -2104,11 +2104,12 @@ SILC_SERVER_CMD_FUNC(invite) SilcChannelEntry channel; SilcChannelID *channel_id = NULL; SilcIDListData idata; - SilcBuffer idp; + SilcBuffer idp, idp2, packet; unsigned char *tmp, *add, *del; unsigned int len; + unsigned short ident = silc_command_get_ident(cmd->payload); - SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2); + SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4); /* Get Channel ID */ tmp = silc_argument_get_arg_type(cmd->args, 1, &len); @@ -2202,13 +2203,10 @@ SILC_SERVER_CMD_FUNC(invite) } /* Get route to the client */ - dest_sock = silc_server_get_client_route(server, tmp, len, &idata); + dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata); + memset(invite, 0, sizeof(invite)); 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, '@')) { @@ -2221,7 +2219,7 @@ SILC_SERVER_CMD_FUNC(invite) channel->invite_list = silc_calloc(len + 2, sizeof(*channel->invite_list)); else - channel->invite_list = silc_realloc(channel->ban_list, + channel->invite_list = silc_realloc(channel->invite_list, sizeof(*channel->invite_list) * (len + strlen(channel->invite_list) + 2)); @@ -2229,23 +2227,27 @@ SILC_SERVER_CMD_FUNC(invite) 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); + idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL); + idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT); 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_NOTIFY_TYPE_INVITE, 3, + idp->data, idp->len, + channel->channel_name, + strlen(channel->channel_name), + idp2->data, idp2->len); silc_buffer_free(idp); + silc_buffer_free(idp2); } /* 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 (add) { if (!channel->invite_list) channel->invite_list = silc_calloc(len + 2, sizeof(*channel->invite_list)); else - channel->invite_list = silc_realloc(channel->ban_list, + channel->invite_list = silc_realloc(channel->invite_list, sizeof(*channel->invite_list) * (len + strlen(channel->invite_list) + 2)); @@ -2265,33 +2267,40 @@ SILC_SERVER_CMD_FUNC(invite) 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; + } else { + 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 */ - + if (!server->standalone) + silc_server_send_notify_invite(server, server->router->connection, + server->server_type == SILC_ROUTER ? + TRUE : FALSE, channel, + sender->id, SILC_ID_CLIENT_LEN, + add, del); /* Send command reply */ - silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE, - SILC_STATUS_OK); - - silc_buffer_free(idp); + tmp = silc_argument_get_arg_type(cmd->args, 1, &len); + packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE, + SILC_STATUS_OK, ident, 2, + 2, tmp, len, + 3, channel->invite_list, + channel->invite_list ? + strlen(channel->invite_list) : + 0); + silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, + packet->data, packet->len, FALSE); + silc_buffer_free(packet); out: if (dest_id) @@ -2699,7 +2708,13 @@ static void silc_server_command_join_channel(SilcServer server, /* Check invite list if channel is invite-only channel */ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && - channel->mode & SILC_CHANNEL_MODE_INVITE && channel->invite_list) { + channel->mode & SILC_CHANNEL_MODE_INVITE) { + if (!channel->invite_list) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_NOT_INVITED); + goto out; + } + if (!silc_string_match(channel->invite_list, check)) { silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, SILC_STATUS_ERR_NOT_INVITED); @@ -4529,7 +4544,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 && strlen(add) == tmp_len) { + if (add) { if (!channel->ban_list) channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list)); else @@ -4552,23 +4567,20 @@ SILC_SERVER_CMD_FUNC(ban) if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) { silc_free(channel->ban_list); channel->ban_list = NULL; - goto out0; - } - - start = strstr(channel->ban_list, del); - if (start && strlen(start) >= tmp_len) { - end = start + tmp_len; - n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n)); - strncat(n, channel->ban_list, start - channel->ban_list); - strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - - end) - 1); - silc_free(channel->ban_list); - channel->ban_list = n; + } else { + start = strstr(channel->ban_list, del); + if (start && strlen(start) >= tmp_len) { + end = start + tmp_len; + n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n)); + strncat(n, channel->ban_list, start - channel->ban_list); + strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - + end) - 1); + silc_free(channel->ban_list); + channel->ban_list = n; + } } } - out0: - /* Send the BAN notify type to our primary router. */ if (!server->standalone && (add || del)) silc_server_send_notify_ban(server, server->router->connection, diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index a938e53c..937cc2e7 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -64,7 +64,7 @@ void silc_server_notify(SilcServer server, /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, - packet->dst_id_len, &idata); + packet->dst_id_len, NULL, &idata); if (dst_sock) /* Relay the packet */ silc_server_relay_packet(server, dst_sock, idata->send_key, @@ -498,7 +498,75 @@ void silc_server_notify(SilcServer server, break; case SILC_NOTIFY_TYPE_INVITE: - SILC_LOG_DEBUG(("INVITE notify (not-impl XXX)")); + + if (packet->dst_id_type == SILC_ID_CLIENT) + goto out; + + SILC_LOG_DEBUG(("INVITE notify")); + + /* Get Channel ID */ + tmp = silc_argument_get_arg_type(args, 1, &tmp_len); + if (!tmp) + goto out; + channel_id = silc_id_payload_parse_id(tmp, tmp_len); + if (!channel_id) + goto out; + + /* Get channel entry */ + channel = silc_idlist_find_channel_by_id(server->global_list, + channel_id, NULL); + if (!channel) { + channel = silc_idlist_find_channel_by_id(server->local_list, + channel_id, NULL); + if (!channel) { + silc_free(channel_id); + goto out; + } + } + silc_free(channel_id); + + /* Get the added invite */ + tmp = silc_argument_get_arg_type(args, 3, &tmp_len); + if (tmp) { + if (!channel->invite_list) + channel->invite_list = silc_calloc(tmp_len + 2, + sizeof(*channel->invite_list)); + else + channel->invite_list = silc_realloc(channel->invite_list, + sizeof(*channel->invite_list) * + (tmp_len + + strlen(channel->invite_list) + + 2)); + if (tmp[tmp_len - 1] == ',') + tmp[tmp_len - 1] = '\0'; + + strncat(channel->invite_list, tmp, tmp_len); + strncat(channel->invite_list, ",", 1); + } + + /* Get the deleted invite */ + tmp = silc_argument_get_arg_type(args, 4, &tmp_len); + if (tmp && channel->invite_list) { + char *start, *end, *n; + + if (!strncmp(channel->invite_list, tmp, + strlen(channel->invite_list) - 1)) { + silc_free(channel->invite_list); + channel->invite_list = NULL; + } else { + start = strstr(channel->invite_list, tmp); + if (start && strlen(start) >= tmp_len) { + end = start + tmp_len; + n = silc_calloc(strlen(channel->invite_list) - tmp_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; + } + } + } + break; case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: @@ -714,18 +782,17 @@ void silc_server_notify(SilcServer server, if (!strcmp(channel->ban_list, tmp)) { silc_free(channel->ban_list); channel->ban_list = NULL; - break; - } - - start = strstr(channel->ban_list, tmp); - if (start && strlen(start) >= tmp_len) { - end = start + tmp_len; - n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n)); - strncat(n, channel->ban_list, start - channel->ban_list); - strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - - end) - 1); - silc_free(channel->ban_list); - channel->ban_list = n; + } else { + start = strstr(channel->ban_list, tmp); + if (start && strlen(start) >= tmp_len) { + end = start + tmp_len; + n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n)); + strncat(n, channel->ban_list, start - channel->ban_list); + strncat(n, end + 1, ((channel->ban_list + + strlen(channel->ban_list)) - end) - 1); + silc_free(channel->ban_list); + channel->ban_list = n; + } } } @@ -820,7 +887,7 @@ void silc_server_private_message(SilcServer server, /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, - packet->dst_id_len, &idata); + packet->dst_id_len, NULL, &idata); if (!dst_sock) return; @@ -852,7 +919,7 @@ void silc_server_private_message_key(SilcServer server, /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, - packet->dst_id_len, &idata); + packet->dst_id_len, NULL, &idata); if (!dst_sock) return; @@ -1741,7 +1808,7 @@ void silc_server_key_agreement(SilcServer server, /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, - packet->dst_id_len, &idata); + packet->dst_id_len, NULL, &idata); if (!dst_sock) return; diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index 2dba70f3..4b271c4d 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -1125,7 +1125,7 @@ void silc_server_send_notify_umode(SilcServer server, silc_buffer_free(idp); } -/* Sends BAN notify type. This tells that `ban' has been either `add'ed +/* Sends BAN notify type. This tells that ban has been either `add'ed or `del'eted on the `channel. This function is used to send the packet between routers as broadcast packet. */ @@ -1146,6 +1146,34 @@ void silc_server_send_notify_ban(SilcServer server, silc_buffer_free(idp); } +/* Sends INVITE notify type. This tells that invite has been either `add'ed + or `del'eted on the `channel. The sender of the invite is the `client_id'. + This function is used to send the packet between routers as broadcast + packet. */ + +void silc_server_send_notify_invite(SilcServer server, + SilcSocketConnection sock, + int broadcast, + SilcChannelEntry channel, + SilcClientID *client_id, + unsigned int client_id_len, + char *add, char *del) +{ + SilcBuffer idp, idp2; + + idp = silc_id_payload_encode((void *)channel->id, SILC_ID_CHANNEL); + idp2 = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT); + silc_server_send_notify(server, sock, broadcast, + SILC_NOTIFY_TYPE_INVITE, 5, + idp->data, idp->len, + channel->channel_name, strlen(channel->channel_name), + idp2->data, idp2->len, + add, add ? strlen(add) : 0, + del, del ? strlen(del) : 0); + silc_buffer_free(idp); + silc_buffer_free(idp2); +} + /* Sends notify message destined to specific entity. */ void silc_server_send_notify_dest(SilcServer server, diff --git a/apps/silcd/packet_send.h b/apps/silcd/packet_send.h index b856e0e4..cef2bbe4 100644 --- a/apps/silcd/packet_send.h +++ b/apps/silcd/packet_send.h @@ -179,6 +179,13 @@ void silc_server_send_notify_ban(SilcServer server, int broadcast, SilcChannelEntry channel, char *add, char *del); +void silc_server_send_notify_invite(SilcServer server, + SilcSocketConnection sock, + int broadcast, + SilcChannelEntry channel, + SilcClientID *client_id, + unsigned int client_id_len, + char *add, char *del); void silc_server_send_notify_dest(SilcServer server, SilcSocketConnection sock, int broadcast, diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 61344524..a82d494c 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -3130,11 +3130,13 @@ void silc_server_save_users_on_channel(SilcServer server, /* Lookups route to the client indicated by `id' client ID. The connection object and internal data object is returned. Returns NULL if route - could not be found to the client. */ + could not be found to the client. If the `client_id' is specified then + it is used and the `id_data' is ignored. */ SilcSocketConnection silc_server_get_client_route(SilcServer server, unsigned char *id_data, unsigned int id_len, + SilcClientID *client_id, SilcIDListData *idata) { SilcClientID *id; @@ -3143,10 +3145,14 @@ SilcSocketConnection silc_server_get_client_route(SilcServer server, SILC_LOG_DEBUG(("Start")); /* Decode destination Client ID */ - id = silc_id_str2id(id_data, id_len, SILC_ID_CLIENT); - if (!id) { - SILC_LOG_ERROR(("Could not decode destination Client ID, dropped")); - return NULL; + if (!client_id) { + id = silc_id_str2id(id_data, id_len, SILC_ID_CLIENT); + if (!id) { + SILC_LOG_ERROR(("Could not decode destination Client ID, dropped")); + return NULL; + } + } else { + id = silc_id_dup(client_id, SILC_ID_CLIENT); } /* If the destination belongs to our server we don't have to route diff --git a/apps/silcd/server.h b/apps/silcd/server.h index ded8b808..d02bda75 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -160,6 +160,7 @@ void silc_server_save_users_on_channel(SilcServer server, SilcSocketConnection silc_server_get_client_route(SilcServer server, unsigned char *id_data, unsigned int id_len, + SilcClientID *client_id, SilcIDListData *idata); SilcBuffer silc_server_get_client_channel_list(SilcServer server, SilcClientEntry client); diff --git a/apps/silcd/testi2.conf b/apps/silcd/testi2.conf index 1eaa6071..42ed3eae 100644 --- a/apps/silcd/testi2.conf +++ b/apps/silcd/testi2.conf @@ -1,23 +1,17 @@ [Cipher] -aes-256-cbc:../lib/silcsim/modules/aes.sim.so:32:16 -aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16 -aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16 -twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16 -twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16 -twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16 -mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16 -mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16 -mars-128-cbc:../lib/silcsim/modules/mars.sim.so:16:16 +rc6:../lib/silcsim/modules/rc6.sim.so:16:16 +twofish:../lib/silcsim/modules/twofish.sim.so:16:16 +mars:../lib/silcsim/modules/mars.sim.so:16:16 none:../lib/silcsim/modules/none.sim.so:0:0 -[Hash] +[Hash] md5::64:16 sha1::64:20 [hmac] hmac-sha1-96:sha1:12 hmac-md5-96:md5:12 -hmac-sha1:sha1:20 +hmac-sha1:sha1:20 hmac-md5:md5:16 #[PKCS] @@ -31,10 +25,10 @@ nobody:nobody Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi [ServerInfo] -lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334 +lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334 [ListenPort] -212.146.42.253:212.146.42.253:1334 +10.2.1.7:10.2.1.7:1334 [Logging] infologfile:silcd2.log:10000 @@ -53,13 +47,16 @@ errorlogfile:silcd2.log:10000 :::1336:1 [AdminConnection] -*:priikone:*:passwd:testi +*:silc:silc:passwd:testi [ServerConnection] -212.146.42.253:passwd:priikone:1333:1:1 +10.2.1.7:passwd:priikone:1333:1:1 [RouterConnection] -212.146.42.253:passwd:priikone:1335:1:1:0 +10.2.1.7:passwd:priikone:1335:1:1:0 [DenyConnection] [RedirectClient] + +[motd] +./motd diff --git a/doc/draft-riikonen-silc-pp-01.nroff b/doc/draft-riikonen-silc-pp-01.nroff index fed19883..0567d6d7 100644 --- a/doc/draft-riikonen-silc-pp-01.nroff +++ b/doc/draft-riikonen-silc-pp-01.nroff @@ -1126,24 +1126,26 @@ ID's sent in arguments are sent inside ID Payload. Sent when an client is invited to a channel. This is also sent when the invite list of the channel is changed. This notify type is sent between routers and if the is argument is - provided to the client as well. + provided to the client as well. In this case the packet is + destined to the client. Max Arguments: 5 - Arguments: (1) (2) [] - (3) [] (3) [] - (4) [] - - The is the client which was invited to the channel. - The is the channel. The is the + Arguments: (1) (2) + (3) [] (4) [] + (5) [] + + The is the channel. The is the name + of the channel and is provided because the client which receives + this notify packet may not have a way to resolve the name of the + channel from the . 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. + 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. The and is never sent to the - client indicated by the . Also note that the lists - include the already. + client indicated by the . 2 SILC_NOTIFY_TYPE_JOIN @@ -1262,7 +1264,7 @@ ID's sent in arguments are sent inside ID Payload. 10 SILC_NOTIFY_TYPE_CHANNEL_CHANGE Sent when channel's ID has changed for a reason or another. This - is sent by noral server to the client. Client must change the + is sent by normal server to the client. Client must change the old Channel ID to the new one. This type must be sent only to the clients who is joined on the channel. diff --git a/doc/draft-riikonen-silc-spec-01.nroff b/doc/draft-riikonen-silc-spec-01.nroff index 7dda5ce7..4bf88c49 100644 --- a/doc/draft-riikonen-silc-spec-01.nroff +++ b/doc/draft-riikonen-silc-spec-01.nroff @@ -2303,10 +2303,12 @@ List of all defined commands in SILC follows. Reply messages to the command: - Max Arguments: 2 - Arguments: (1) + Max Arguments: 3 + Arguments: (1) (2) + (3) [] - This command replies only with Status Payload. + This command replies with the invite list of the channel if it + exists. Status messages: diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index d1668cae..744ad289 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -107,11 +107,26 @@ void silc_client_notify_by_server(SilcClient client, * for the application. */ - /* Get Client ID */ + /* Get Channel ID */ tmp = silc_argument_get_arg_type(args, 1, &tmp_len); if (!tmp) goto out; + channel_id = silc_id_payload_parse_id(tmp, tmp_len); + if (!channel_id) + goto out; + + /* Get the channel entry */ + channel = NULL; + if (silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, + SILC_ID_CHANNEL, &id_cache)) + channel = (SilcChannelEntry)id_cache->context; + + /* Get sender Client ID */ + tmp = silc_argument_get_arg_type(args, 3, &tmp_len); + if (!tmp) + goto out; + client_id = silc_id_payload_parse_id(tmp, tmp_len); if (!client_id) goto out; @@ -123,28 +138,13 @@ void silc_client_notify_by_server(SilcClient client, goto out; } - /* Get Channel ID */ + /* Get the channel name */ tmp = silc_argument_get_arg_type(args, 2, &tmp_len); if (!tmp) goto out; - channel_id = silc_id_payload_parse_id(tmp, tmp_len); - if (!channel_id) - goto out; - - /* XXX Will ALWAYS fail because currently we don't have way to resolve - channel information for channel that we're not joined to. */ - /* XXX ways to fix: use (extended) LIST command, or define the channel - name to the notfy type when name resolving is not mandatory. */ - /* Find channel entry */ - if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, - SILC_ID_CHANNEL, &id_cache)) - goto out; - - channel = (SilcChannelEntry)id_cache->context; - /* Notify application */ - client->ops->notify(client, conn, type, client_entry, channel); + client->ops->notify(client, conn, type, channel, tmp, client_entry); break; case SILC_NOTIFY_TYPE_JOIN: diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 1ef9975d..82b07fb3 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -530,18 +530,20 @@ SILC_CLIENT_CMD_FUNC(topic) silc_client_command_free(cmd); } -/* Command INVITE. Invites specific client to join a channel. */ +/* Command INVITE. Invites specific client to join a channel. This is + also used to mange the invite list of the channel. */ SILC_CLIENT_CMD_FUNC(invite) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; SilcClient client = cmd->client; SilcClientConnection conn = cmd->conn; - SilcClientEntry client_entry; - SilcChannelEntry channel_entry; + SilcClientEntry client_entry = NULL; + SilcChannelEntry channel; SilcBuffer buffer, clidp, chidp; - unsigned int num = 0; - char *nickname = NULL, *server = NULL; + unsigned int num = 0, type = 0; + char *nickname = NULL, *server = NULL, *name; + char *invite = NULL; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -549,63 +551,104 @@ SILC_CLIENT_CMD_FUNC(invite) goto out; } - if (cmd->argc != 3) { + if (cmd->argc < 2) { cmd->client->ops->say(cmd->client, conn, - "Usage: /INVITE [@] "); + "Usage: /INVITE [[@server>]" + "[+|-[[@[![@hostname>]]]]]"); COMMAND_ERROR; goto out; } - /* Parse the typed nickname. */ - if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, "Bad nickname"); - COMMAND_ERROR; - goto out; - } + if (cmd->argv[1][0] == '*') { + if (!conn->current_channel) { + cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + COMMAND_ERROR; + goto out; + } - /* Find client entry */ - client_entry = silc_idlist_get_client(client, conn, nickname, server, num, - TRUE); - if (!client_entry) { - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + channel = conn->current_channel; + } else { + name = cmd->argv[1]; - /* Client entry not found, it was requested thus mark this to be - pending command. */ - silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident, - silc_client_command_destructor, - silc_client_command_invite, - silc_client_command_dup(cmd)); - cmd->pending = 1; - return; + channel = silc_client_get_channel(cmd->client, conn, name); + if (!channel) { + cmd->client->ops->say(cmd->client, conn, "You are on that channel"); + COMMAND_ERROR; + goto out; + } } - /* Find channel entry */ - channel_entry = silc_client_get_channel(client, conn, cmd->argv[2]); - if (!channel_entry) { - cmd->client->ops->say(cmd->client, conn, "You are not on that channel"); - COMMAND_ERROR; - goto out; + /* Parse the typed nickname. */ + if (cmd->argc == 3) { + if (cmd->argv[2][0] != '+' && cmd->argv[2][0] != '-') { + if (!silc_parse_nickname(cmd->argv[2], &nickname, &server, &num)) { + cmd->client->ops->say(cmd->client, conn, "Bad nickname"); + COMMAND_ERROR; + goto out; + } + + /* Find client entry */ + client_entry = silc_idlist_get_client(client, conn, nickname, + server, num, TRUE); + if (!client_entry) { + if (nickname) + silc_free(nickname); + if (server) + silc_free(server); + + if (cmd->pending) { + COMMAND_ERROR; + goto out; + } + + /* Client entry not found, it was requested thus mark this to be + pending command. */ + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, + conn->cmd_ident, + silc_client_command_destructor, + silc_client_command_invite, + silc_client_command_dup(cmd)); + cmd->pending = 1; + return; + } + + cmd->client->ops->say(cmd->client, conn, + "Inviting %s to channel %s", cmd->argv[2], + channel->channel_name); + } else { + invite = cmd->argv[2]; + invite++; + if (cmd->argv[2][0] == '+') + type = 3; + else + type = 4; + } + } + + /* Send the command */ + chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL); + if (client_entry) { + clidp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT); + buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE, + ++conn->cmd_ident, 3, + 1, chidp->data, chidp->len, + 2, clidp->data, clidp->len, + type, invite, invite ? + strlen(invite) : 0); + silc_buffer_free(clidp); + } else { + buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE, + ++conn->cmd_ident, 2, + 1, chidp->data, chidp->len, + type, invite, invite ? + strlen(invite) : 0); } - /* Send command */ - clidp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT); - chidp = silc_id_payload_encode(channel_entry->id, SILC_ID_CHANNEL); - buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE, 0, 2, - 1, clidp->data, clidp->len, - 2, chidp->data, chidp->len); silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 0, NULL, NULL, buffer->data, buffer->len, TRUE); silc_buffer_free(buffer); - silc_buffer_free(clidp); silc_buffer_free(chidp); - cmd->client->ops->say(cmd->client, conn, - "Inviting %s to channel %s", cmd->argv[1], - cmd->argv[2]); - /* Notify application */ COMMAND; @@ -715,6 +758,11 @@ SILC_CLIENT_CMD_FUNC(kill) if (server) silc_free(server); + if (cmd->pending) { + COMMAND_ERROR; + goto out; + } + /* Client entry not found, it was requested thus mark this to be pending command. */ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, @@ -1292,6 +1340,11 @@ SILC_CLIENT_CMD_FUNC(cumode) client_entry = silc_idlist_get_client(cmd->client, conn, nickname, server, num, TRUE); if (!client_entry) { + if (cmd->pending) { + COMMAND_ERROR; + goto out; + } + /* Client entry not found, it was requested thus mark this to be pending command. */ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index a97b2352..f091e8cf 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -712,7 +712,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; SilcCommandStatus status; + SilcChannelEntry channel; + SilcChannelID *channel_id; + SilcIDCacheEntry id_cache; unsigned char *tmp; + unsigned int len; tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); SILC_GET16_MSB(status, tmp); @@ -725,12 +729,35 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite) return; } + /* Take Channel ID */ + tmp = silc_argument_get_arg_type(cmd->args, 2, &len); + if (!tmp) + goto out; + + channel_id = silc_id_payload_parse_id(tmp, len); + if (!channel_id) + goto out; + + /* Get the channel entry */ + if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, + SILC_ID_CHANNEL, &id_cache)) { + silc_free(channel_id); + COMMAND_REPLY_ERROR; + goto out; + } + + channel = (SilcChannelEntry)id_cache->context; + + /* Get the invite list */ + tmp = silc_argument_get_arg_type(cmd->args, 3, &len); + /* Notify application */ - COMMAND_REPLY((ARGS)); + COMMAND_REPLY((ARGS, channel, tmp)); /* Execute any pending command callbacks */ SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_INVITE); + out: SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INVITE); silc_client_command_reply_free(cmd); } -- 2.24.0