From: Pekka Riikonen Date: Mon, 20 Nov 2000 21:22:30 +0000 (+0000) Subject: updates X-Git-Tag: SILC.0.1~320 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=79e0de593d0490e53709c3cb66b443b06b1fe9f3;p=silc.git updates --- diff --git a/CHANGES b/CHANGES index 9b005e69..98e2f3ac 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,11 @@ +Mon Nov 20 23:47:03 EET 2000 Pekka Riikonen + + * Made joining to a channel working in router environment. + + * Cleaned up JOIN command on server side and create function + silc_server_command_join_channel internal routine to make the + joining happen. + Thu Nov 9 21:12:39 EET 2000 Pekka Riikonen * Changed silc_command_pending list to SilcDList. Also, added diff --git a/apps/silcd/command.c b/apps/silcd/command.c index d937dd36..d027389b 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -38,6 +38,9 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd, unsigned char *arg, unsigned int arg_len); static void silc_server_command_free(SilcServerCommandContext cmd); +void silc_server_command_send_names(SilcServer server, + SilcSocketConnection sock, + SilcChannelEntry channel); /* Server command list. */ SilcServerCommand silc_command_list[] = @@ -75,9 +78,6 @@ SilcServerCommand silc_command_list[] = { NULL, 0 }, }; -/* List of pending commands. */ -SilcDList silc_command_pending; - /* Returns TRUE if the connection is registered. Unregistered connections usually cannot send commands hence the check. */ @@ -176,7 +176,8 @@ void silc_server_command_process(SilcServer server, the `callback' will be executed when received reply with command identifier `ident'. */ -void silc_server_command_pending(SilcCommand reply_cmd, +void silc_server_command_pending(SilcServer server, + SilcCommand reply_cmd, unsigned short ident, SilcCommandCb callback, void *context) @@ -188,19 +189,21 @@ void silc_server_command_pending(SilcCommand reply_cmd, reply->ident = ident; reply->context = context; reply->callback = callback; - silc_dlist_add(silc_command_pending, reply); + silc_dlist_add(server->pending_commands, reply); } /* Deletes pending command by reply command type. */ -void silc_server_command_pending_del(SilcCommand reply_cmd, +void silc_server_command_pending_del(SilcServer server, + SilcCommand reply_cmd, unsigned short ident) { SilcServerCommandPending *r; - while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) { + silc_dlist_start(server->pending_commands); + while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) { if (r->reply_cmd == reply_cmd && r->ident == ident) { - silc_dlist_del(silc_command_pending, r); + silc_dlist_del(server->pending_commands, r); break; } } @@ -209,13 +212,15 @@ void silc_server_command_pending_del(SilcCommand reply_cmd, /* Checks for pending commands and marks callbacks to be called from the command reply function. Returns TRUE if there were pending command. */ -int silc_server_command_pending_check(SilcServerCommandReplyContext ctx, +int silc_server_command_pending_check(SilcServer server, + SilcServerCommandReplyContext ctx, SilcCommand command, unsigned short ident) { SilcServerCommandPending *r; - while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) { + silc_dlist_start(server->pending_commands); + while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) { if (r->reply_cmd == command && r->ident == ident) { ctx->context = r->context; ctx->callback = r->callback; @@ -1169,12 +1174,17 @@ SILC_TASK_CALLBACK(silc_server_command_join_notify) SILC_NOTIFY_TYPE_JOIN, 1, clidp->data, clidp->len); + /* Send NAMES 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, + ctx->channel); + silc_buffer_free(clidp); silc_free(ctx); } else { silc_task_register(ctx->server->timeout_queue, fd, silc_server_command_join_notify, context, - 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); + 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); } } @@ -1205,55 +1215,26 @@ void silc_server_command_send_names(SilcServer server, silc_free(idp); } -/* Server side of command JOIN. Joins client into requested channel. If - the channel does not exist it will be created. */ +/* Internal routine to join channel. The channel sent to this function + has been either created or resolved from ID lists. This joins the sent + client to the channel. */ -SILC_SERVER_CMD_FUNC(join) +static void +silc_server_command_join_channel(SilcServer server, + SilcServerCommandContext cmd, + SilcChannelEntry channel, + unsigned int umode) { - SilcServerCommandContext cmd = (SilcServerCommandContext)context; - SilcServer server = cmd->server; SilcSocketConnection sock = cmd->sock; - SilcBuffer buffer = cmd->packet->buffer; - int argc, i, k, tmp_len; - char *tmp, *channel_name = NULL, *cipher = NULL; + unsigned char *tmp; + unsigned int tmp_len; unsigned char *passphrase = NULL, mode[4]; - unsigned int umode = 0; - SilcChannelEntry channel; + SilcClientEntry client; SilcChannelClientEntry chl; - SilcServerID *router_id; SilcBuffer packet, idp; - SilcClientEntry client; - - SILC_LOG_DEBUG(("Start")); - - /* Check number of parameters */ - argc = silc_argument_get_arg_num(cmd->args); - if (argc < 1) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, - SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); - goto out; - } - if (argc > 3) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, - SILC_STATUS_ERR_TOO_MANY_PARAMS); - goto out; - } - - /* Get channel name */ - tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); - if (!tmp) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, - SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); - goto out; - } - channel_name = tmp; - if (silc_server_command_bad_chars(channel_name) == TRUE) { - silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, - SILC_STATUS_ERR_BAD_CHANNEL); - silc_free(channel_name); - goto out; - } + if (!channel) + return; /* Get passphrase */ tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len); @@ -1262,67 +1243,6 @@ SILC_SERVER_CMD_FUNC(join) memcpy(passphrase, tmp, tmp_len); } - /* Get cipher name */ - cipher = silc_argument_get_arg_type(cmd->args, 3, NULL); - - /* See if the channel exists */ - channel = - silc_idlist_find_channel_by_name(server->local_list, channel_name); - if (!channel) { - /* Channel not found */ - - /* If we are standalone server we don't have a router, we just create - the channel by ourselves. */ - if (server->standalone) { - router_id = server->id; - channel = silc_server_new_channel(server, router_id, cipher, - channel_name); - umode |= SILC_CHANNEL_UMODE_CHANOP; - umode |= SILC_CHANNEL_UMODE_CHANFO; - if (!channel) - goto out; - - goto join_channel; - } - - /* No channel ID found, the channel does not exist on our server. - We send JOIN command to our router which will handle the joining - procedure (either creates the channel if it doesn't exist or - joins the client to it) - if we are normal server. */ - if (server->server_type == SILC_SERVER) { - - /* Forward the original JOIN command to the 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); - - /* Add the command to be pending. It will be re-executed after - router has replied back to us. */ - cmd->pending = TRUE; - silc_server_command_pending(SILC_COMMAND_JOIN, 0, - silc_server_command_join, context); - return; - } - } - - /* If we are router and the channel does not exist we will check our - global list for the channel. */ - if (!channel && server->server_type == SILC_ROUTER) { - - /* Notify all routers about the new channel in SILC network. */ - if (!server->standalone) { -#if 0 - silc_server_send_new_id(server, server->id_entry->router->connection, - TRUE, - xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN); -#endif - } - - } - - join_channel: - /* * Check channel modes */ @@ -1416,16 +1336,16 @@ SILC_SERVER_CMD_FUNC(join) packet = silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN, SILC_STATUS_OK, 0, 3, - 2, channel_name, - strlen(channel_name), + 2, channel->channel_name, + strlen(channel->channel_name), 3, idp->data, idp->len, 4, mode, 4); else packet = silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN, SILC_STATUS_OK, 0, 4, - 2, channel_name, - strlen(channel_name), + 2, channel->channel_name, + strlen(channel->channel_name), 3, idp->data, idp->len, 4, mode, 4, 5, channel->topic, @@ -1477,7 +1397,7 @@ SILC_SERVER_CMD_FUNC(join) /* This is pending command request. Send the notify after we have received the key for the channel from the router. */ JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx)); - ctx->channel_name = channel_name; + ctx->channel_name = channel->channel_name; ctx->nickname = client->nickname; ctx->username = client->username; ctx->hostname = sock->hostname ? sock->hostname : sock->ip; @@ -1488,11 +1408,112 @@ SILC_SERVER_CMD_FUNC(join) silc_server_command_join_notify, ctx, 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW); } + + /* Send NAMES command reply to the joined channel so the user sees who + is currently on the channel. */ + silc_server_command_send_names(server, sock, channel); + } + + out: + if (passphrase) + silc_free(passphrase); +} + +/* Server side of command JOIN. Joins client into requested channel. If + the channel does not exist it will be created. */ + +SILC_SERVER_CMD_FUNC(join) +{ + SilcServerCommandContext cmd = (SilcServerCommandContext)context; + SilcServer server = cmd->server; + int argc, tmp_len; + char *tmp, *channel_name = NULL, *cipher = NULL; + SilcChannelEntry channel; + unsigned int umode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO; + + SILC_LOG_DEBUG(("Start")); + + /* Check number of parameters */ + argc = silc_argument_get_arg_num(cmd->args); + if (argc < 1) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); + goto out; + } + if (argc > 3) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_TOO_MANY_PARAMS); + goto out; + } + + /* Get channel name */ + tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len); + if (!tmp) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); + goto out; + } + channel_name = tmp; + + if (silc_server_command_bad_chars(channel_name) == TRUE) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN, + SILC_STATUS_ERR_BAD_CHANNEL); + silc_free(channel_name); + goto out; + } + + /* Get cipher name */ + cipher = silc_argument_get_arg_type(cmd->args, 3, NULL); + + /* See if the channel exists */ + channel = silc_idlist_find_channel_by_name(server->local_list, channel_name); + if (!channel) { + /* Channel not found */ + + /* If we are standalone server we don't have a router, we just create + the channel by ourselves. */ + if (server->standalone) { + channel = silc_server_new_channel(server, server->id, cipher, + channel_name); + } else { + + /* The channel does not exist on our server. We send JOIN command to + our router which will handle the joining procedure (either creates + the channel if it doesn't exist or joins the client to it) - if we + are normal server. */ + if (server->server_type == SILC_SERVER) { + SilcBuffer buffer = cmd->packet->buffer; + + /* Forward the original JOIN command to the 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); + + /* Add the command to be pending. It will be re-executed after + router has replied back to us. */ + cmd->pending = TRUE; + silc_server_command_pending(server, SILC_COMMAND_JOIN, 0, + silc_server_command_join, context); + return; + } + + /* We are router and the channel does not seem exist so we will check + our global list as well for the channel. */ + channel = silc_idlist_find_channel_by_name(server->global_list, + channel_name); + if (!channel) { + /* Channel really does not exist, create it */ + channel = silc_server_new_channel(server, server->id, cipher, + channel_name); + umode |= SILC_CHANNEL_UMODE_CHANOP; + umode |= SILC_CHANNEL_UMODE_CHANFO; + } + } } - /* Send NAMES command reply to the joined channel so the user sees who - is currently on the channel. */ - silc_server_command_send_names(server, sock, channel); + /* Join to the channel */ + silc_server_command_join_channel(server, cmd, channel, umode); out: silc_server_command_free(cmd); @@ -2374,7 +2395,7 @@ SILC_SERVER_CMD_FUNC(names) /* XXX Send names command */ cmd->pending = TRUE; - silc_server_command_pending(SILC_COMMAND_NAMES, 0, + silc_server_command_pending(server, SILC_COMMAND_NAMES, 0, silc_server_command_names, context); return; } diff --git a/apps/silcd/command.h b/apps/silcd/command.h index 21677e8f..e5fdc06e 100644 --- a/apps/silcd/command.h +++ b/apps/silcd/command.h @@ -62,6 +62,7 @@ typedef struct { /* Structure holding pending commands. If command is pending it will be executed after command reply has been received and executed. */ typedef struct SilcServerCommandPendingStruct { + SilcServer server; SilcCommand reply_cmd; SilcCommandCb callback; void *context; @@ -80,25 +81,28 @@ typedef struct SilcServerCommandPendingStruct { void silc_server_command_##func(void *context) /* Executed pending command */ -#define SILC_SERVER_COMMAND_EXEC_PENDING(ctx, cmd) \ -do { \ - if (ctx->callback) { \ - (*ctx->callback)(ctx->context); \ - silc_server_command_pending_del(cmd, ctx->ident); \ - } \ +#define SILC_SERVER_COMMAND_EXEC_PENDING(ctx, cmd) \ +do { \ + if (ctx->callback) { \ + (*ctx->callback)(ctx->context); \ + silc_server_command_pending_del(ctx->server, cmd, ctx->ident); \ + } \ } while(0) /* Prototypes */ void silc_server_command_process(SilcServer server, SilcSocketConnection sock, SilcPacketContext *packet); -void silc_server_command_pending(SilcCommand reply_cmd, +void silc_server_command_pending(SilcServer server, + SilcCommand reply_cmd, unsigned short ident, SilcCommandCb callback, void *context); -void silc_server_command_pending_del(SilcCommand reply_cmd, +void silc_server_command_pending_del(SilcServer server, + SilcCommand reply_cmd, unsigned short ident); -int silc_server_command_pending_check(SilcServerCommandReplyContext ctx, +int silc_server_command_pending_check(SilcServer server, + SilcServerCommandReplyContext ctx, SilcCommand command, unsigned short ident); SILC_SERVER_CMD_FUNC(whois); diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index 853a52ff..83eb257c 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -67,6 +67,8 @@ void silc_server_command_reply_process(SilcServer server, SilcCommand command; unsigned short ident; + SILC_LOG_DEBUG(("Start")); + /* Get command reply payload from packet */ payload = silc_command_payload_parse(buffer); if (!payload) { @@ -85,8 +87,8 @@ void silc_server_command_reply_process(SilcServer server, ident = silc_command_get_ident(ctx->payload); /* Check for pending commands and mark to be exeucted */ - silc_server_command_pending_check(ctx, silc_command_get(ctx->payload), - ident); + silc_server_command_pending_check(server, ctx, + silc_command_get(ctx->payload), ident); /* Execute command reply */ command = silc_command_get(ctx->payload); @@ -267,9 +269,12 @@ SILC_SERVER_CMD_REPLY_FUNC(join) goto out; channel_name = strdup(tmp); + id = silc_id_payload_parse_id(id_string, len); + + SILC_LOG_DEBUG(("Adding new channel %s id(%s)", channel_name, + silc_id_render(id, SILC_ID_CHANNEL))); /* Add the channel to our local list. */ - id = silc_id_payload_parse_id(id_string, len); entry = silc_idlist_add_channel(server->local_list, channel_name, SILC_CHANNEL_MODE_NONE, id, server->id_entry->router, NULL); @@ -279,10 +284,11 @@ SILC_SERVER_CMD_REPLY_FUNC(join) goto out; } - entry->global_users = TRUE; + //entry->global_users = TRUE; /* Execute pending JOIN command so that the client who originally wanted to join the channel will be joined after all. */ + SILC_LOG_DEBUG(("Re-executing JOIN command")); SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN); out: diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 6f1204a2..ec5359bc 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -57,6 +57,7 @@ int silc_server_alloc(SilcServer *new_server) server->standalone = TRUE; server->local_list = silc_calloc(1, sizeof(*server->local_list)); server->global_list = silc_calloc(1, sizeof(*server->global_list)); + server->pending_commands = silc_dlist_init(); #ifdef SILC_SIM server->sim = silc_dlist_init(); #endif @@ -90,6 +91,9 @@ void silc_server_free(SilcServer server) if (server->params) silc_free(server->params); + if (server->pending_commands) + silc_dlist_uninit(server->pending_commands); + silc_math_primegen_uninit(); /* XXX */ silc_free(server); } @@ -1674,14 +1678,13 @@ void silc_server_packet_forward(SilcServer server, /* Prepare outgoing data buffer for packet sending */ silc_packet_send_prepare(sock, 0, 0, data_len); - /* Mungle the packet flags and add the FORWARDED flag */ - if (data) - data[2] |= (unsigned char)SILC_PACKET_FLAG_FORWARDED; - /* Put the data to the buffer */ if (data && data_len) silc_buffer_put(sock->outbuf, data, data_len); + /* Add the FORWARDED flag to packet flags */ + sock->outbuf->data[2] |= (unsigned char)SILC_PACKET_FLAG_FORWARDED; + if (idata) { cipher = idata->send_key; hmac = idata->hmac; @@ -3099,12 +3102,11 @@ SilcChannelEntry silc_server_new_channel(SilcServer server, SilcServerID *router_id, char *cipher, char *channel_name) { - int i, channel_len, key_len; + int i, key_len; SilcChannelID *channel_id; SilcChannelEntry entry; SilcCipher key; - unsigned char channel_key[32], *id_string; - SilcBuffer packet; + unsigned char channel_key[32]; SILC_LOG_DEBUG(("Creating new channel")); @@ -3139,26 +3141,9 @@ SilcChannelEntry silc_server_new_channel(SilcServer server, /* Notify other routers about the new channel. We send the packet to our primary route. */ if (server->standalone == FALSE) { - channel_len = strlen(channel_name); - id_string = silc_id_id2str(entry->id, SILC_ID_CHANNEL); - packet = silc_buffer_alloc(2 + SILC_ID_CHANNEL_LEN); - - silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet)); - silc_buffer_format(packet, - SILC_STR_UI_SHORT(channel_len), - SILC_STR_UI_XNSTRING(channel_name, channel_len), - SILC_STR_UI_SHORT(SILC_ID_CHANNEL_LEN), - SILC_STR_UI_XNSTRING(id_string, SILC_ID_CHANNEL_LEN), - SILC_STR_END); - - /* Send the packet to our router. */ - silc_server_packet_send(server, (SilcSocketConnection) - server->id_entry->router->connection, - SILC_PACKET_NEW_CHANNEL_USER, 0, - packet->data, packet->len, TRUE); - - silc_free(id_string); - silc_buffer_free(packet); + silc_server_send_new_id(server, server->id_entry->router->connection, + server->server_type == SILC_SERVER ? FALSE : TRUE, + entry->id, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN); } return entry; diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index 0b748b52..7278c6a3 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -97,6 +97,9 @@ struct SilcServerStruct { /* Server statistics */ SilcServerStatistics stats; + /* Pending command queue */ + SilcDList pending_commands; + /* Default parameteres for server */ SilcServerParams params;