unsigned char *arg,
unsigned int arg_len);
static void silc_server_command_free(SilcServerCommandContext cmd);
-void silc_server_command_send_names(SilcServer server,
+void silc_server_command_send_users(SilcServer server,
SilcSocketConnection sock,
SilcChannelEntry channel);
SILC_SERVER_CMD(silcoper, SILCOPER,
SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
- SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
+ SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
{ NULL, 0 },
};
static int
silc_server_command_whois_parse(SilcServerCommandContext cmd,
- SilcClientID **client_id,
+ SilcClientID ***client_id,
+ unsigned int *client_id_count,
char **nickname,
char **server_name,
- int *count)
+ int *count,
+ SilcCommand command)
{
unsigned char *tmp;
unsigned int len;
unsigned int argc = silc_argument_get_arg_num(cmd->args);
+ int i, k;
/* If client ID is in the command it must be used instead of nickname */
tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
*nickname = strdup(tmp);
}
} else {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
+ silc_server_command_send_status_reply(cmd, command,
SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
return FALSE;
}
} else {
+ /* Command includes ID, we must use that. Also check whether the command
+ has more than one ID set - take them all. */
+
+ *client_id = silc_calloc(1, sizeof(**client_id));
+ (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
+ *client_id_count = 1;
+
+ /* Take all ID's from the command packet */
+ if (argc > 3) {
+ for (k = 1, i = 4; i < argc; i++) {
+ tmp = silc_argument_get_arg_type(cmd->args, i, &len);
+ if (tmp) {
+ *client_id = silc_realloc(*client_id, sizeof(**client_id) *
+ (*client_id_count + 1));
+ (*client_id)[k++] = silc_id_payload_parse_id(tmp, len);
+ (*client_id_count)++;
+ }
+ }
+ }
+
/* Command includes ID, use that */
- *client_id = silc_id_payload_parse_id(tmp, len);
}
/* Get the max count of reply messages allowed */
- if (argc == 3) {
- tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
- if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
- SILC_STATUS_ERR_TOO_MANY_PARAMS);
- if (*nickname)
- silc_free(*nickname);
- if (*server_name)
- silc_free(*server_name);
-
- return FALSE;
- }
+ tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
+ if (tmp)
*count = atoi(tmp);
- }
+ else
+ *count = 0;
return TRUE;
}
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count;
- SilcClientID *client_id = NULL;
+ int count = 0, clients_count = 0;
SilcClientEntry *clients = NULL, entry;
- int ret = 0;
-
- /* Parse the whois request */
- if (!silc_server_command_whois_parse(cmd, &client_id, &nick,
- &server_name, &count))
- return 0;
+ SilcClientID **client_id = NULL;
+ unsigned int client_id_count = 0;
+ int i, ret = 0;
/* Protocol dictates that we must always send the received WHOIS request
to our router if we are normal server, so let's do it now unless we
/* We are ready to process the command request. Let's search for the
requested client and send reply to the requesting client. */
+ /* Parse the whois request */
+ if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
+ &nick, &server_name, &count,
+ SILC_COMMAND_WHOIS))
+ return 0;
+
/* Get all clients matching that ID or nickname from local list */
- if (client_id) {
- entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
+ if (client_id_count) {
+ /* Check all Client ID's received in the command packet */
+ for (i = 0; i < client_id_count; i++) {
+ entry = silc_idlist_find_client_by_id(server->local_list,
+ client_id[i], NULL);
+ if (entry) {
+ clients = silc_realloc(clients, sizeof(*clients) *
+ (clients_count + 1));
+ clients[clients_count++] = entry;
+ }
}
} else {
clients = silc_idlist_get_clients_by_nickname(server->local_list,
/* Check global list as well */
if (!clients) {
- if (client_id) {
- entry = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
+ if (client_id_count) {
+ /* Check all Client ID's received in the command packet */
+ for (i = 0; i < client_id_count; i++) {
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ client_id[i], NULL);
+ if (entry) {
+ clients = silc_realloc(clients, sizeof(*clients) *
+ (clients_count + 1));
+ clients[clients_count++] = entry;
+ }
}
} else {
clients = silc_idlist_get_clients_by_nickname(server->global_list,
}
if (!clients) {
- /* Such a client really does not exist in the SILC network. */
- silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
- SILC_STATUS_ERR_NO_SUCH_NICK,
- 3, nick, strlen(nick));
+ /* Such client(s) really does not exist in the SILC network. */
+ if (!client_id_count) {
+ silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
+ SILC_STATUS_ERR_NO_SUCH_NICK,
+ 3, nick, strlen(nick));
+ } else {
+ SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
+ silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+ 2, idp->data, idp->len);
+ silc_buffer_free(idp);
+ }
goto out;
}
silc_server_command_whois_send_reply(cmd, clients, clients_count);
out:
+ if (client_id_count) {
+ for (i = 0; i < client_id_count; i++)
+ silc_free(client_id[i]);
+ silc_free(client_id);
+ }
if (clients)
silc_free(clients);
- if (client_id)
- silc_free(client_id);
if (nick)
silc_free(nick);
if (server_name)
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count;
- SilcClientID *client_id = NULL;
+ int count = 0, clients_count = 0;
SilcClientEntry *clients = NULL, entry;
- int ret = 0;
+ SilcClientID **client_id = NULL;
+ unsigned int client_id_count = 0;
+ int i, ret = 0;
/* Parse the whois request */
- if (!silc_server_command_whois_parse(cmd, &client_id, &nick,
- &server_name, &count))
+ if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
+ &nick, &server_name, &count,
+ SILC_COMMAND_WHOIS))
return 0;
/* Process the command request. Let's search for the requested client and
send reply to the requesting server. */
- if (client_id) {
- entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
+ if (client_id_count) {
+ /* Check all Client ID's received in the command packet */
+ for (i = 0; i < client_id_count; i++) {
+ entry = silc_idlist_find_client_by_id(server->local_list,
+ client_id[i], NULL);
+ if (entry) {
+ clients = silc_realloc(clients, sizeof(*clients) *
+ (clients_count + 1));
+ clients[clients_count++] = entry;
+ }
}
} else {
clients = silc_idlist_get_clients_by_nickname(server->local_list,
/* If we are router we will check our global list as well. */
if (!clients && server->server_type == SILC_ROUTER) {
- if (client_id) {
- entry = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
+ if (client_id_count) {
+ /* Check all Client ID's received in the command packet */
+ for (i = 0; i < client_id_count; i++) {
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ client_id[i], NULL);
+ if (entry) {
+ clients = silc_realloc(clients, sizeof(*clients) *
+ (clients_count + 1));
+ clients[clients_count++] = entry;
+ }
}
} else {
clients = silc_idlist_get_clients_by_nickname(server->global_list,
if (!clients) {
/* Such a client really does not exist in the SILC network. */
- if (!client_id) {
+ if (!client_id_count) {
silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
SILC_STATUS_ERR_NO_SUCH_NICK,
3, nick, strlen(nick));
} else {
- SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+ SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2, idp->data, idp->len);
silc_server_command_whois_send_reply(cmd, clients, clients_count);
out:
+ if (client_id_count) {
+ for (i = 0; i < client_id_count; i++)
+ silc_free(client_id[i]);
+ silc_free(client_id);
+ }
if (clients)
silc_free(clients);
- if (client_id)
- silc_free(client_id);
if (nick)
silc_free(nick);
if (server_name)
******************************************************************************/
-static int
-silc_server_command_identify_parse(SilcServerCommandContext cmd,
- SilcClientID **client_id,
- char **nickname,
- char **server_name,
- int *count)
-{
- unsigned char *tmp;
- unsigned int len;
- unsigned int argc = silc_argument_get_arg_num(cmd->args);
-
- /* If client ID is in the command it must be used instead of nickname */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
- if (!tmp) {
- /* No ID, get the nickname@server string and parse it. */
- tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
- if (tmp) {
- if (strchr(tmp, '@')) {
- len = strcspn(tmp, "@");
- *nickname = silc_calloc(len + 1, sizeof(char));
- memcpy(*nickname, tmp, len);
- *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
- memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
- } else {
- *nickname = strdup(tmp);
- }
- } else {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
- return FALSE;
- }
- } else {
- /* Command includes ID, use that */
- *client_id = silc_id_payload_parse_id(tmp, len);
- }
-
- /* Get the max count of reply messages allowed */
- if (argc == 3) {
- tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
- if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_TOO_MANY_PARAMS);
- if (*nickname)
- silc_free(*nickname);
- if (*server_name)
- silc_free(*server_name);
-
- return FALSE;
- }
- *count = atoi(tmp);
- }
-
- return TRUE;
-}
-
/* Checks that all mandatory fields are present. If not then send WHOIS
request to the server who owns the client. We use WHOIS because we want
to get as much information as possible at once. */
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count;
- SilcClientID *client_id = NULL;
+ int count = 0, clients_count;
SilcClientEntry *clients = NULL, entry;
- int ret = 0;
-
- /* Parse the IDENTIFY request */
- if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
- &server_name, &count))
- return 0;
+ SilcClientID **client_id = NULL;
+ unsigned int client_id_count = 0;
+ int i, ret = 0;
/* Protocol dictates that we must always send the received IDENTIFY request
to our router if we are normal server, so let's do it now unless we
/* We are ready to process the command request. Let's search for the
requested client and send reply to the requesting client. */
+ /* Parse the IDENTIFY request */
+ if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
+ &nick, &server_name, &count,
+ SILC_COMMAND_IDENTIFY))
+ return 0;
+
/* Get all clients matching that ID or nickname from local list */
- if (client_id) {
- entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
+ if (client_id_count) {
+ /* Check all Client ID's received in the command packet */
+ for (i = 0; i < client_id_count; i++) {
+ entry = silc_idlist_find_client_by_id(server->local_list,
+ client_id[i], NULL);
+ if (entry) {
+ clients = silc_realloc(clients, sizeof(*clients) *
+ (clients_count + 1));
+ clients[clients_count++] = entry;
+ }
}
} else {
clients = silc_idlist_get_clients_by_nickname(server->local_list,
/* Check global list as well */
if (!clients) {
- if (client_id) {
- entry = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
+ if (client_id_count) {
+ /* Check all Client ID's received in the command packet */
+ for (i = 0; i < client_id_count; i++) {
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ client_id[i], NULL);
+ if (entry) {
+ clients = silc_realloc(clients, sizeof(*clients) *
+ (clients_count + 1));
+ clients[clients_count++] = entry;
+ }
}
} else {
clients = silc_idlist_get_clients_by_nickname(server->global_list,
if (!clients) {
/* Such a client really does not exist in the SILC network. */
- if (!client_id) {
+ if (!client_id_count) {
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_NICK,
3, nick, strlen(nick));
} else {
- SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+ SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2, idp->data, idp->len);
silc_server_command_identify_send_reply(cmd, clients, clients_count);
out:
+ if (client_id_count) {
+ for (i = 0; i < client_id_count; i++)
+ silc_free(client_id[i]);
+ silc_free(client_id);
+ }
if (clients)
silc_free(clients);
- if (client_id)
- silc_free(client_id);
if (nick)
silc_free(nick);
if (server_name)
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
int count = 0, clients_count;
- SilcClientID *client_id = NULL;
SilcClientEntry *clients = NULL, entry;
- int ret = 0;
+ SilcClientID **client_id = NULL;
+ unsigned int client_id_count = 0;
+ int i, ret = 0;
/* Parse the IDENTIFY request */
- if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
- &server_name, &count))
+ if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
+ &nick, &server_name, &count,
+ SILC_COMMAND_IDENTIFY))
return 0;
/* Process the command request. Let's search for the requested client and
send reply to the requesting server. */
- if (client_id) {
- entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
+ if (client_id_count) {
+ /* Check all Client ID's received in the command packet */
+ for (i = 0; i < client_id_count; i++) {
+ entry = silc_idlist_find_client_by_id(server->local_list,
+ client_id[i], NULL);
+ if (entry) {
+ clients = silc_realloc(clients, sizeof(*clients) *
+ (clients_count + 1));
+ clients[clients_count++] = entry;
+ }
}
} else {
clients = silc_idlist_get_clients_by_nickname(server->local_list,
/* If we are router we will check our global list as well. */
if (!clients && server->server_type == SILC_ROUTER) {
- if (client_id) {
- entry = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
+ if (client_id_count) {
+ /* Check all Client ID's received in the command packet */
+ for (i = 0; i < client_id_count; i++) {
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ client_id[i], NULL);
+ if (entry) {
+ clients = silc_realloc(clients, sizeof(*clients) *
+ (clients_count + 1));
+ clients[clients_count++] = entry;
+ }
}
} else {
clients = silc_idlist_get_clients_by_nickname(server->global_list,
silc_server_command_identify_send_reply(cmd, clients, clients_count);
out:
+ if (client_id_count) {
+ for (i = 0; i < client_id_count; i++)
+ silc_free(client_id[i]);
+ silc_free(client_id);
+ }
if (clients)
silc_free(clients);
- if (client_id)
- silc_free(client_id);
if (nick)
silc_free(nick);
if (server_name)
/* 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 (NAMES command), check from
+ 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,
client->id, SILC_ID_CLIENT_LEN);
#endif
- /* Send NAMES command reply to the joined channel so the user sees who
+ /* Send USERS command reply to the joined channel so the user sees who
is currently on the channel. */
- silc_server_command_send_names(ctx->server, ctx->client->connection,
+ silc_server_command_send_users(ctx->server, ctx->client->connection,
ctx->channel);
silc_buffer_free(clidp);
}
}
-/* Assembles NAMES command and executes it. This is called when client
- joins to a channel and we wan't to send NAMES command reply to the
+/* Assembles USERS command and executes it. This is called when client
+ joins to a channel and we wan't to send USERS command reply to the
client. */
-void silc_server_command_send_names(SilcServer server,
+void silc_server_command_send_users(SilcServer server,
SilcSocketConnection sock,
SilcChannelEntry channel)
{
SilcPacketContext *packet = silc_packet_context_alloc();
idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
- buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1, idp->data, idp->len);
packet->buffer = silc_buffer_copy(buffer);
cmd->packet = silc_packet_context_dup(packet);
cmd->pending = FALSE;
- silc_server_command_names((void *)cmd);
+ silc_server_command_users((void *)cmd);
silc_free(buffer);
silc_free(idp);
channel->id, SILC_ID_CHANNEL_LEN,
client->id, SILC_ID_CLIENT_LEN);
- /* Send NAMES command reply to the joined channel so the user sees who
+ /* Send USERS command reply to the joined channel so the user sees who
is currently on the channel. */
- silc_server_command_send_names(server, sock, channel);
+ silc_server_command_send_users(server, sock, channel);
/*
FAQ:
- * Kuinka NAMES komento händlätään serverissä kun router lähettää sen
+ * Kuinka USERS komento händlätään serverissä kun router lähettää sen
serverille joka on lähettäny sille clientin puolesta JOIN komennon?
- R: Serverin pitää ymmärtää NAMES comman replyjä.
+ R: Serverin pitää ymmärtää USERS comman replyjä.
*/
silc_server_command_free(cmd);
}
-/* Server side of command NAMES. Resolves clients and their names currently
- joined on the requested channel. The name list is sent back to the
- client. */
+/* Server side of command USERS. Resolves clients and their USERS currently
+ joined on the requested channel. The list of Client ID's and their modes
+ on the channel is sent back. */
-SILC_SERVER_CMD_FUNC(names)
+SILC_SERVER_CMD_FUNC(users)
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcChannelClientEntry chl;
SilcChannelID *id;
SilcBuffer packet;
- unsigned int i, len, len2, tmp_len;
unsigned char *tmp;
- char *name_list = NULL, *n;
+ unsigned int tmp_len;
SilcBuffer client_id_list;
SilcBuffer client_mode_list;
SilcBuffer idp;
unsigned short ident = silc_command_get_ident(cmd->payload);
- SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NAMES, cmd, 1, 2);
+ SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 2);
/* Get Channel ID */
tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
if (!tmp) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
SILC_STATUS_ERR_NO_CHANNEL_ID);
goto out;
}
id = silc_id_payload_parse_id(tmp, tmp_len);
- if (server->server_type == SILC_SERVER && !server->standalone &&
- !cmd->pending) {
- SilcBuffer tmpbuf;
-
- silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
- tmpbuf = silc_command_payload_encode_payload(cmd->payload);
-
- /* Send NAMES command */
- silc_server_packet_send(server, server->router->connection,
- SILC_PACKET_COMMAND, cmd->packet->flags,
- tmpbuf->data, tmpbuf->len, TRUE);
-
- /* Reprocess this packet after received reply */
- silc_server_command_pending(server, SILC_COMMAND_NAMES,
- silc_command_get_ident(cmd->payload),
- silc_server_command_names, (void *)cmd);
- cmd->pending = TRUE;
- silc_command_set_ident(cmd->payload, ident);
-
- silc_buffer_free(tmpbuf);
- silc_free(id);
- return;
- }
-
- /* Get the channel entry */
+ /* If we are server and we don't know about this channel we will send
+ the command to our router. If we know about the channel then we also
+ have the list of users already. */
channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
if (!channel) {
+ if (server->server_type == SILC_SERVER && !server->standalone &&
+ !cmd->pending) {
+ SilcBuffer tmpbuf;
+
+ silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+ /* Send USERS command */
+ silc_server_packet_send(server, server->router->connection,
+ SILC_PACKET_COMMAND, cmd->packet->flags,
+ tmpbuf->data, tmpbuf->len, TRUE);
+
+ /* Reprocess this packet after received reply */
+ silc_server_command_pending(server, SILC_COMMAND_USERS,
+ silc_command_get_ident(cmd->payload),
+ silc_server_command_users, (void *)cmd);
+ cmd->pending = TRUE;
+ silc_command_set_ident(cmd->payload, ident);
+
+ silc_buffer_free(tmpbuf);
+ silc_free(id);
+ return;
+ }
+
+ /* We are router and we will check the global list as well. */
channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
if (!channel) {
/* Channel really does not exist */
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
SILC_STATUS_ERR_NO_SUCH_CHANNEL);
goto out;
}
/* Assemble the lists now */
- name_list = NULL;
- len = i = 0;
client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
silc_list_count(channel->user_list));
silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
silc_list_start(channel->user_list);
while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
- /* Nickname */
- n = chl->client->nickname;
- if (n) {
- len2 = strlen(n);
- len += len2;
- name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
- memcpy(name_list + (len - len2), n, len2);
- name_list[len] = 0;
-
- if (i == silc_list_count(channel->user_list) - 1)
- break;
- memcpy(name_list + len, ",", 1);
- len++;
- i++;
- }
-
/* Client ID */
idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
silc_buffer_put(client_id_list, idp->data, idp->len);
client_id_list->data - client_id_list->head);
silc_buffer_push(client_mode_list,
client_mode_list->data - client_mode_list->head);
- if (!name_list)
- name_list = "";
/* Send reply */
- packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
SILC_STATUS_OK, 0, 4,
2, tmp, tmp_len,
- 3, name_list,
- strlen(name_list),
- 4, client_id_list->data,
+ 3, client_id_list->data,
client_id_list->len,
- 5, client_mode_list->data,
+ 4, client_mode_list->data,
client_mode_list->len);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
- silc_free(name_list);
silc_buffer_free(client_id_list);
silc_buffer_free(client_mode_list);
silc_free(id);
SILC_SERVER_CMD_REPLY(join, JOIN),
SILC_SERVER_CMD_REPLY(whois, WHOIS),
SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
- SILC_SERVER_CMD_REPLY(names, NAMES),
+ SILC_SERVER_CMD_REPLY(users, USERS),
{ NULL, 0 },
};
silc_server_command_reply_free(cmd);
}
-SILC_SERVER_CMD_REPLY_FUNC(names)
+SILC_SERVER_CMD_REPLY_FUNC(users)
{
SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
SilcServer server = cmd->server;
SilcBuffer client_id_list;
SilcBuffer client_mode_list;
unsigned char *tmp;
- char *name_list, *cp;
- int i, len1, len2, list_count = 0;
+ unsigned int tmp_len;
+ unsigned int list_count, i;
COMMAND_CHECK_STATUS;
/* Get channel ID */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &len1);
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
if (!tmp)
goto out;
- channel_id = silc_id_payload_parse_id(tmp, len1);
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
- /* Get the name list of the channel */
- name_list = silc_argument_get_arg_type(cmd->args, 3, &len1);
- if (!name_list)
+ /* Get the list count */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+ if (!tmp)
goto out;
+ SILC_GET32_MSB(list_count, tmp);
/* Get Client ID list */
- tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
+ tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
if (!tmp)
goto out;
- client_id_list = silc_buffer_alloc(len2);
- silc_buffer_pull_tail(client_id_list, len2);
- silc_buffer_put(client_id_list, tmp, len2);
+ client_id_list = silc_buffer_alloc(tmp_len);
+ silc_buffer_pull_tail(client_id_list, tmp_len);
+ silc_buffer_put(client_id_list, tmp, tmp_len);
/* Get client mode list */
- tmp = silc_argument_get_arg_type(cmd->args, 5, &len2);
+ tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
if (!tmp)
goto out;
- client_mode_list = silc_buffer_alloc(len2);
- silc_buffer_pull_tail(client_mode_list, len2);
- silc_buffer_put(client_mode_list, tmp, len2);
+ client_mode_list = silc_buffer_alloc(tmp_len);
+ silc_buffer_pull_tail(client_mode_list, tmp_len);
+ silc_buffer_put(client_mode_list, tmp, tmp_len);
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list,
goto out;
}
- /* Remove commas from list */
- for (i = 0; i < len1; i++)
- if (name_list[i] == ',') {
- name_list[i] = ' ';
- list_count++;
- }
- list_count++;
-
- /* Cache the received name list, client ID's and modes. This cache expires
+ /* Cache the received Client ID's and modes. This cache expires
whenever server sends notify message to channel. It means two things;
some user has joined or leaved the channel. XXX! */
- cp = name_list;
for (i = 0; i < list_count; i++) {
- int nick_len = strcspn(name_list, " ");
unsigned short idp_len;
unsigned int mode;
- char *nick, *nickname = silc_calloc(nick_len + 1, sizeof(*nickname));
SilcClientID *client_id;
SilcClientEntry client;
- /* Nickname */
- memcpy(nickname, name_list, nick_len);
+ /* Client ID */
SILC_GET16_MSB(idp_len, client_id_list->data + 2);
idp_len += 4;
-
- /* Client ID */
client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
silc_buffer_pull(client_id_list, idp_len);
if (server->server_type == SILC_ROUTER)
goto out;
- /* Take hostname out of nick string if it includes it. */
- if (strchr(nickname, '@')) {
- int len = strcspn(nickname, "@");
- nick = silc_calloc(len + 1, sizeof(char));
- memcpy(nick, nickname, len);
- } else {
- nick = strdup(nickname);
- }
-
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- silc_idlist_add_client(server->global_list, nick, NULL, NULL,
+ silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
client_id, NULL, NULL);
} else {
/* We have the client already. */
silc_free(client_id);
}
-
- silc_free(nickname);
-
- name_list += nick_len + 1;
}
silc_buffer_free(client_id_list);
silc_buffer_free(client_mode_list);
/* Execute any pending commands */
- SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_NAMES);
+ SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_USERS);
out:
if (channel_id)
SILC_CLIENT_CMD_REPLY(die, DIE),
SILC_CLIENT_CMD_REPLY(silcoper, SILCOPER),
SILC_CLIENT_CMD_REPLY(leave, LEAVE),
- SILC_CLIENT_CMD_REPLY(names, NAMES),
+ SILC_CLIENT_CMD_REPLY(users, USERS),
{ NULL, 0 },
};
silc_client_command_reply_free(cmd);
}
-/* Reply to NAMES command. Received list of client names on the channel
- we requested. */
+/* Reply to USERS command. Received list of client ID's and theirs modes
+ on the channel we requested. */
-SILC_CLIENT_CMD_REPLY_FUNC(names)
+SILC_CLIENT_CMD_REPLY_FUNC(users)
{
SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
SilcBuffer client_id_list;
SilcBuffer client_mode_list;
unsigned char *tmp;
+ unsigned int tmp_len;
+ int i, k, len1, len2, list_count;
+ unsigned char **res_argv = NULL;
+ unsigned int *res_argv_lens = NULL, *res_argv_types = NULL, res_argc = 0;
char *name_list, *cp;
- int i, k, len1, len2, list_count = 0;
SILC_LOG_DEBUG(("Start"));
}
/* Get channel ID */
- tmp = silc_argument_get_arg_type(cmd->args, 2, &len1);
- if (!tmp) {
- cmd->client->ops->say(cmd->client, conn,
- "Cannot Channel ID: Bad reply packet");
- COMMAND_REPLY_ERROR;
+ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+ if (!tmp)
goto out;
- }
- channel_id = silc_id_payload_parse_id(tmp, len1);
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
- /* Get the name list of the channel */
- name_list = silc_argument_get_arg_type(cmd->args, 3, &len1);
- if (!name_list) {
- cmd->client->ops->say(cmd->client, conn,
- "Cannot get user list: Bad reply packet");
- COMMAND_REPLY_ERROR;
+ /* Get the list count */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+ if (!tmp)
goto out;
- }
+ SILC_GET32_MSB(list_count, tmp);
/* Get Client ID list */
- tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
- if (!tmp) {
- cmd->client->ops->say(cmd->client, conn,
- "Cannot get user list: Bad reply packet");
- COMMAND_REPLY_ERROR;
+ tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
+ if (!tmp)
goto out;
- }
- client_id_list = silc_buffer_alloc(len2);
- silc_buffer_pull_tail(client_id_list, len2);
- silc_buffer_put(client_id_list, tmp, len2);
+ client_id_list = silc_buffer_alloc(tmp_len);
+ silc_buffer_pull_tail(client_id_list, tmp_len);
+ silc_buffer_put(client_id_list, tmp, tmp_len);
/* Get client mode list */
- tmp = silc_argument_get_arg_type(cmd->args, 5, &len2);
- if (!tmp) {
- cmd->client->ops->say(cmd->client, conn,
- "Cannot get user list: Bad reply packet");
- COMMAND_REPLY_ERROR;
+ tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
+ if (!tmp)
goto out;
- }
- client_mode_list = silc_buffer_alloc(len2);
- silc_buffer_pull_tail(client_mode_list, len2);
- silc_buffer_put(client_mode_list, tmp, len2);
+ client_mode_list = silc_buffer_alloc(tmp_len);
+ silc_buffer_pull_tail(client_mode_list, tmp_len);
+ silc_buffer_put(client_mode_list, tmp, tmp_len);
- /* Get the channel name */
+ /* Get channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache)) {
+ SILC_ID_CHANNEL, &id_cache)) {
COMMAND_REPLY_ERROR;
goto out;
}
-
channel = (SilcChannelEntry)id_cache->context;
- /* Remove commas from list */
- for (i = 0; i < len1; i++)
- if (name_list[i] == ',') {
- name_list[i] = ' ';
- list_count++;
- }
- list_count++;
-
/* Remove old client list from channel. */
silc_list_start(channel->clients);
while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
silc_free(chu);
}
- /* Cache the received name list, client ID's and modes. This cache expires
+ /* Cache the received Client ID's and modes. This cache expires
whenever server sends notify message to channel. It means two things;
- some user has joined or leaved the channel. */
- cp = name_list;
+ some user has joined or leaved the channel. XXX! */
for (i = 0; i < list_count; i++) {
- int nick_len = strcspn(name_list, " ");
unsigned short idp_len;
unsigned int mode;
- char *nickname = silc_calloc(nick_len + 1, sizeof(*nickname));
SilcClientID *client_id;
SilcClientEntry client;
- memcpy(nickname, name_list, nick_len);
+ /* Client ID */
SILC_GET16_MSB(idp_len, client_id_list->data + 2);
idp_len += 4;
client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
silc_buffer_pull(client_id_list, idp_len);
-
+
+ /* Mode */
SILC_GET32_MSB(mode, client_mode_list->data);
silc_buffer_pull(client_mode_list, 4);
/* Check if we have this client cached already. */
if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
SILC_ID_CLIENT, &id_cache)) {
- client = silc_calloc(1, sizeof(*client));
- client->id = client_id;
- silc_parse_nickname(nickname, &client->nickname, &client->server,
- &client->num);
- silc_free(nickname);
-
- /* Add client to cache */
- silc_idcache_add(conn->client_cache, client->nickname, SILC_ID_CLIENT,
- client_id, (void *)client, TRUE);
+ /* No we don't have it, query it from the server. Assemble argument
+ table that will be sent fr the IDENTIFY command later. */
+ res_argv = silc_realloc(res_argv, sizeof(*res_argv) *
+ (res_argc + 1));
+ res_argv_lens = silc_realloc(res_argv_lens, sizeof(*res_argv_lens) *
+ (res_argc + 1));
+ res_argv_types = silc_realloc(res_argv_types, sizeof(*res_argv_types) *
+ (res_argc + 1));
+ res_argv[res_argc] = client_id_list->data;
+ res_argv_lens[res_argc] = idp_len;
+ res_argv_types[res_argc] = res_argc + 3;
+ res_argc++;
} else {
+ /* Found the client, join it to the channel */
client = (SilcClientEntry)id_cache->context;
+ chu = silc_calloc(1, sizeof(*chu));
+ chu->client = client;
+ chu->mode = mode;
+ silc_list_add(channel->clients, chu);
+
silc_free(client_id);
- silc_free(nickname);
id_cache = NULL;
}
+ }
- chu = silc_calloc(1, sizeof(*chu));
- chu->client = client;
- chu->mode = mode;
- silc_list_add(channel->clients, chu);
-
- name_list += nick_len + 1;
+ /* Query the client information from server if the list included clients
+ that we don't know about. */
+ if (res_argc) {
+#if 0
+ SilcBuffer res_cmd;
+
+ res_cmd = silc_command_payload_encode(SILC_COMMAND_IDENTIFY,
+ res_argc, res_argv, res_argv_lens,
+ res_argv_types, 0);
+ silc_client_packet_send(cmd->client, cmd->conn->sock,
+ SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
+ buffer->data, buffer->len, TRUE);
+ goto out;
+#endif
}
name_list = cp;