X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fcommand.c;h=6792f3c0f72ad40082c4ea82814b007ceabcbec7;hb=f4502217007852082bc93d144551f576bc9f5428;hp=9f0866a5dbb00e6d6b01826f2dfe69843ff6d1b6;hpb=a67bfbe8a773eac3852d82a7dafb53a421a3769d;p=silc.git diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 9f0866a5..6792f3c0 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -45,23 +45,23 @@ SilcServerCommand silc_command_list[] = SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG), + SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG), + SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), + SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(connect, CONNECT, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), - SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG), + SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG), SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG), - SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG), + SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(restart, RESTART, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER), SILC_SERVER_CMD(close, CLOSE, @@ -70,7 +70,7 @@ SilcServerCommand silc_command_list[] = SILC_CF_OPER), 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(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG), SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG), { NULL, 0 }, @@ -116,9 +116,8 @@ static int silc_server_is_registered(SilcServer server, /* Internal context to hold data when executed command with timeout. */ typedef struct { - SilcServer server; - SilcSocketConnection sock; - SilcPacketContext *packet; + SilcServerCommandContext ctx; + SilcServerCommand *cmd; } *SilcServerCommandTimeout; /* Timeout callback to process commands with timeout for client. Client's @@ -127,67 +126,61 @@ typedef struct { SILC_TASK_CALLBACK(silc_server_command_process_timeout) { SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context; - SilcServerCommandContext ctx; - SilcServerCommand *cmd; - SilcClientEntry client = (SilcClientEntry)timeout->sock->user_data; + SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data; /* Update access time */ client->last_command = time(NULL); + if (!(timeout->cmd->flags & SILC_CF_REG)) + timeout->cmd->cb(timeout->ctx); + else if (silc_server_is_registered(timeout->ctx->server, + timeout->ctx->sock, + timeout->ctx, + timeout->cmd->cmd)) + timeout->cmd->cb(timeout->ctx); + + silc_free(timeout); +} + +/* Processes received command packet. */ + +void silc_server_command_process(SilcServer server, + SilcSocketConnection sock, + SilcPacketContext *packet) +{ + SilcServerCommandContext ctx; + SilcServerCommand *cmd; + /* Allocate command context. This must be free'd by the command routine receiving it. */ ctx = silc_server_command_alloc(); - ctx->server = timeout->server; - ctx->sock = timeout->sock; - ctx->packet = timeout->packet; - + ctx->server = server; + ctx->sock = silc_socket_dup(sock); + ctx->packet = silc_packet_context_dup(packet); /* Save original packet */ + /* Parse the command payload in the packet */ - ctx->payload = silc_command_payload_parse(ctx->packet->buffer); + ctx->payload = silc_command_payload_parse(packet->buffer); if (!ctx->payload) { SILC_LOG_ERROR(("Bad command payload, packet dropped")); - silc_buffer_free(ctx->packet->buffer); + silc_buffer_free(packet->buffer); + silc_packet_context_free(packet); silc_socket_free(ctx->sock); - silc_packet_context_free(ctx->packet); silc_free(ctx); - silc_free(timeout); return; } ctx->args = silc_command_get_args(ctx->payload); - /* Execute command. If this fails the packet is dropped. */ + /* Get the command */ for (cmd = silc_command_list; cmd->cb; cmd++) - if (cmd->cmd == silc_command_get(ctx->payload)) { - - if (!(cmd->flags & SILC_CF_REG)) { - cmd->cb(ctx); - break; - } - - if (silc_server_is_registered(ctx->server, ctx->sock, ctx, cmd->cmd)) { - cmd->cb(ctx); - break; - } - } + if (cmd->cmd == silc_command_get(ctx->payload)) + break; if (cmd == NULL) { SILC_LOG_ERROR(("Unknown command, packet dropped")); silc_server_command_free(ctx); - silc_free(timeout); return; } - silc_free(timeout); -} - -/* Processes received command packet. */ - -void silc_server_command_process(SilcServer server, - SilcSocketConnection sock, - SilcPacketContext *packet) -{ - SilcServerCommandContext ctx; - SilcServerCommand *cmd; - /* Execute client's commands always with timeout. Normally they are executed with zero (0) timeout but if client is sending command more frequently than once in 2 seconds, then the timeout may be 0 to 2 @@ -195,12 +188,22 @@ void silc_server_command_process(SilcServer server, if (sock->type == SILC_SOCKET_TYPE_CLIENT) { SilcClientEntry client = (SilcClientEntry)sock->user_data; SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout)); + int fast; - timeout->server = server; - timeout->sock = silc_socket_dup(sock); - timeout->packet = silc_packet_context_dup(packet); + timeout->ctx = ctx; + timeout->cmd = cmd; - if (client->last_command && (time(NULL) - client->last_command) < 2) + if (client->last_command && (time(NULL) - client->last_command) < 2) { + client->fast_command++; + fast = FALSE; + } else { + client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : + client->fast_command--); + fast = TRUE; + } + + if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) || + (client->fast_command > 5 && cmd->flags & SILC_CF_LAG))) silc_task_register(server->timeout_queue, sock->sock, silc_server_command_process_timeout, (void *)timeout, @@ -217,45 +220,12 @@ void silc_server_command_process(SilcServer server, return; } - /* Allocate command context. This must be free'd by the - command routine receiving it. */ - ctx = silc_server_command_alloc(); - ctx->server = server; - ctx->sock = silc_socket_dup(sock); - ctx->packet = silc_packet_context_dup(packet); /* Save original packet */ - - /* Parse the command payload in the packet */ - ctx->payload = silc_command_payload_parse(packet->buffer); - if (!ctx->payload) { - SILC_LOG_ERROR(("Bad command payload, packet dropped")); - silc_buffer_free(packet->buffer); - silc_packet_context_free(packet); - silc_socket_free(ctx->sock); - silc_free(ctx); - return; - } - ctx->args = silc_command_get_args(ctx->payload); - - /* Execute command. If this fails the packet is dropped. */ - for (cmd = silc_command_list; cmd->cb; cmd++) - if (cmd->cmd == silc_command_get(ctx->payload)) { - - if (!(cmd->flags & SILC_CF_REG)) { - cmd->cb(ctx); - break; - } - - if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) { - cmd->cb(ctx); - break; - } - } + /* Execute for server */ - if (cmd == NULL) { - SILC_LOG_ERROR(("Unknown command, packet dropped")); - silc_server_command_free(ctx); - return; - } + if (!(cmd->flags & SILC_CF_REG)) + cmd->cb(ctx); + else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) + cmd->cb(ctx); } /* Allocate Command Context */