/*
* $Id$
* $Log$
+ * Revision 1.13 2000/08/21 14:21:21 priikone
+ * Fixed channel joining and channel message sending inside a
+ * SILC cell. Added silc_server_send_remove_channel_user and
+ * silc_server_remove_channel_user functions.
+ *
+ * Revision 1.12 2000/07/26 07:05:11 priikone
+ * Fixed the server to server (server to router actually) connections
+ * and made the private message work inside a cell. Added functin
+ * silc_server_replace_id.
+ *
+ * Revision 1.11 2000/07/19 07:08:09 priikone
+ * Added version detection support to SKE.
+ *
+ * Revision 1.10 2000/07/17 11:47:30 priikone
+ * Added command lagging support. Added idle counting support.
+ *
* Revision 1.9 2000/07/12 05:59:41 priikone
* Major rewrite of ID Cache system. Support added for the new
* ID cache system. Major rewrite of ID List stuff on server. All
{
SilcServerCommandContext ctx;
SilcServerCommand *cmd;
+
+ /* Check whether it is allowed for this connection to execute any
+ command. */
+ if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
+ time_t curtime;
+ SilcClientEntry client = (SilcClientEntry)sock->user_data;
+
+ if (!client)
+ goto out;
+
+ /* Allow only one command executed in 2 seconds. */
+ curtime = time(NULL);
+ if (client->last_command && (curtime - client->last_command) < 2)
+ goto out;
+
+ /* Update access time */
+ client->last_command = curtime;
+ }
/* Allocate command context. This must be free'd by the
command routine receiving it. */
if (cmd == NULL) {
SILC_LOG_ERROR(("Unknown command, packet dropped"));
silc_free(ctx);
- return;
+ goto out;
}
+ out:
silc_buffer_free(packet->buffer);
}
/* XXX */
if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
char nh[256], uh[256];
+ unsigned char idle[4];
SilcSocketConnection hsock;
memset(uh, 0, sizeof(uh));
len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
+ SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
+
/* XXX */
if (entry->userinfo)
packet =
silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
- SILC_STATUS_OK, 4,
+ SILC_STATUS_OK, 5,
2, id_string, SILC_ID_CLIENT_LEN,
3, nh, strlen(nh),
4, uh, strlen(uh),
5, entry->userinfo,
- strlen(entry->userinfo));
+ strlen(entry->userinfo),
+ 7, idle, 4);
else
packet =
silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
- SILC_STATUS_OK, 3,
+ SILC_STATUS_OK, 4,
2, id_string, SILC_ID_CLIENT_LEN,
3, nh, strlen(nh),
- 4, uh, strlen(uh));
+ 4, uh, strlen(uh),
+ 7, idle, 4);
} else {
/* XXX */
count = atoi(tmp);
}
- /* Then, make the query from our local client list */
+ /* Find client */
entry = silc_idlist_find_client_by_nickname(server->local_list,
nick, NULL);
- if (!entry) {
-
- /* If we are normal server and are connected to a router we will
- make global query from the router. */
- if (server->server_type == SILC_SERVER && !server->standalone) {
- SilcBuffer buffer = cmd->packet->buffer;
-
- SILC_LOG_DEBUG(("Requesting identify from router"));
-
- /* Send IDENTIFY command to our router */
- silc_buffer_push(buffer, buffer->data - buffer->head);
- silc_server_packet_forward(server, (SilcSocketConnection)
- server->id_entry->router->connection,
- buffer->data, buffer->len, TRUE);
- goto out;
- }
+ if (!entry)
+ entry = silc_idlist_find_client_by_hash(server->global_list,
+ nick, server->md5hash);
+
+ /* If client was not found and if we are normal server and are connected
+ to a router we will make global query from the router. */
+ if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
+ !cmd->pending) {
+ SilcBuffer buffer = cmd->packet->buffer;
- /* If we are router then we will check our global list as well. */
- if (server->server_type == SILC_ROUTER) {
- entry =
- silc_idlist_find_client_by_nickname(server->global_list,
- nick, NULL);
- if (!entry) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NO_SUCH_NICK,
- 3, tmp, strlen(tmp));
- goto out;
- }
- goto ok;
- }
+ SILC_LOG_DEBUG(("Requesting identify from router"));
+
+ /* Send IDENTIFY command to our router */
+ silc_buffer_push(buffer, buffer->data - buffer->head);
+ silc_server_packet_forward(server, (SilcSocketConnection)
+ server->id_entry->router->connection,
+ buffer->data, buffer->len, TRUE);
+ return;
+ }
+
+ /* If we are router we have checked our local list by nickname and our
+ global list by hash so far. It is possible that the client is still not
+ found and we'll check it from local list by hash. */
+ if (!entry && server->server_type == SILC_ROUTER)
+ entry = silc_idlist_find_client_by_hash(server->local_list,
+ nick, server->md5hash);
+ if (!entry) {
+ /* The client definitely does not exist */
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_NICK,
3, tmp, strlen(tmp));
goto out;
}
- ok:
/* Send IDENTIFY reply */
id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
tmp = silc_command_get_first_arg(cmd->payload, NULL);
2, id_string,
SILC_ID_CLIENT_LEN,
3, nick, strlen(nick));
-#if 0
if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
silc_server_packet_send_dest(server, cmd->sock,
id, cmd->packet->src_id_type,
packet->data, packet->len, FALSE);
silc_free(id);
- } else
-#endif
+ } else {
silc_server_packet_send(server, cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
+ }
silc_free(id_string);
silc_buffer_free(packet);
goto out;
}
+ /* Notify routers that they should remove this client from their list
+ of clients on the channel. */
+ if (!server->standalone)
+ silc_server_send_remove_channel_user(server,
+ server->id_entry->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, id_entry->id, id);
+
/* Remove client from channel */
- i = silc_server_remove_from_one_channel(server, sock, channel, id_entry);
+ i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
+ TRUE);
silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
SILC_STATUS_OK);
len++;
}
}
+ if (!name_list)
+ name_list = "";
/* Assemble the Client ID list now */
client_id_list = silc_buffer_alloc(SILC_ID_CLIENT_LEN *