+
+ /* 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;
+ }
+ }