Fixed TOPIC_SET, CMODE_CHANGE notifys and New Channel packet
[silc.git] / apps / silcd / command.c
index 116de4fd794d18ce7951a64804917502ac396d01..f0889aef33e4c049250ea4ce15a181ae122ea7fe 100644 (file)
@@ -97,15 +97,15 @@ SilcServerCommand silc_command_list[] =
 do {                                                                        \
   SilcUInt32 _argc;                                                         \
                                                                             \
-  SILC_LOG_DEBUG(("Start"));                                                \
-                                                                            \
   if (silc_server_command_pending_error_check(cmd, context2, command)) {     \
+    SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
     silc_server_command_free(cmd);                                          \
     return;                                                                 \
   }                                                                         \
                                                                             \
   _argc = silc_argument_get_arg_num(cmd->args);                                     \
   if (_argc < min) {                                                        \
+    SILC_LOG_DEBUG(("Not enough parameters in command"));                   \
     silc_server_command_send_status_reply(cmd, command,                             \
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
                                          0);                                \
@@ -113,6 +113,7 @@ do {                                                                             \
     return;                                                                 \
   }                                                                         \
   if (_argc > max) {                                                        \
+    SILC_LOG_DEBUG(("Too many parameters in command"));                             \
     silc_server_command_send_status_reply(cmd, command,                             \
                                          SILC_STATUS_ERR_TOO_MANY_PARAMS,   \
                                          0);                                \
@@ -157,6 +158,7 @@ SILC_TASK_CALLBACK(silc_server_command_process_timeout)
   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
 
   if (!client) {
+    SILC_LOG_DEBUG(("Client entry is invalid"));
     silc_server_command_free(timeout->ctx);
     silc_free(timeout);
   }
@@ -164,15 +166,21 @@ SILC_TASK_CALLBACK(silc_server_command_process_timeout)
   /* Update access time */
   client->last_command = time(NULL);
 
-  if (!(timeout->cmd->flags & SILC_CF_REG))
+  if (!(timeout->cmd->flags & SILC_CF_REG)) {
+    SILC_LOG_DEBUG(("Calling %s command",
+                   silc_get_command_name(timeout->cmd->cmd)));
     timeout->cmd->cb(timeout->ctx, NULL);
-  else if (silc_server_is_registered(timeout->ctx->server, 
-                                    timeout->ctx->sock, 
-                                    timeout->ctx, 
-                                    timeout->cmd->cmd))
+  } else if (silc_server_is_registered(timeout->ctx->server, 
+                                      timeout->ctx->sock, 
+                                      timeout->ctx, 
+                                      timeout->cmd->cmd)) {
+    SILC_LOG_DEBUG(("Calling %s command",
+                   silc_get_command_name(timeout->cmd->cmd)));
     timeout->cmd->cb(timeout->ctx, NULL);
-  else
+  } else {
+    SILC_LOG_DEBUG(("Client is not registered"));
     silc_server_command_free(timeout->ctx);
+  }
 
   silc_free(timeout);
 }
@@ -187,8 +195,6 @@ void silc_server_command_process(SilcServer server,
   SilcServerCommand *cmd;
   SilcCommand command;
 
-  SILC_LOG_DEBUG(("Start"));
-
   /* Allocate command context. This must be free'd by the
      command routine receiving it. */
   ctx = silc_server_command_alloc();
@@ -215,6 +221,7 @@ void silc_server_command_process(SilcServer server,
       break;
 
   if (!cmd || !cmd->cb) {
+    SILC_LOG_DEBUG(("Unknown command %d", command));
     silc_server_command_send_status_reply(ctx, command,
                                          SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
     silc_server_command_free(ctx);
@@ -261,12 +268,16 @@ void silc_server_command_process(SilcServer server,
 
   /* Execute for server */
 
-  if (!(cmd->flags & SILC_CF_REG))
+  if (!(cmd->flags & SILC_CF_REG)) {
+    SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
     cmd->cb(ctx, NULL);
-  else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
+  } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
+    SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
     cmd->cb(ctx, NULL);
-  else
+  } else {
+    SILC_LOG_DEBUG(("Server is not registered"));
     silc_server_command_free(ctx);
+  }
 }
 
 /* Allocate Command Context */
@@ -891,7 +902,7 @@ silc_server_command_whois_send_router(SilcServerCommandContext cmd)
 
   /* Send WHOIS command to our router */
   silc_server_packet_send(server, (SilcSocketConnection)
-                         server->router->connection,
+                         SILC_PRIMARY_ROUTE(server),
                          SILC_PACKET_COMMAND, cmd->packet->flags,
                          tmpbuf->data, tmpbuf->len, TRUE);
 
@@ -1255,8 +1266,7 @@ silc_server_command_whowas_process(SilcServerCommandContext cmd)
     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
 
     /* Send WHOWAS command to our router */
-    silc_server_packet_send(server, (SilcSocketConnection)
-                           server->router->connection,
+    silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, cmd->packet->flags,
                            tmpbuf->data, tmpbuf->len, TRUE);
 
@@ -1358,7 +1368,7 @@ silc_server_command_identify_send_router(SilcServerCommandContext cmd)
 
   /* Send IDENTIFY command to our router */
   silc_server_packet_send(server, (SilcSocketConnection)
-                         server->router->connection,
+                         SILC_PRIMARY_ROUTE(server),
                          SILC_PACKET_COMMAND, cmd->packet->flags,
                          tmpbuf->data, tmpbuf->len, TRUE);
 
@@ -2106,11 +2116,9 @@ SILC_SERVER_CMD_FUNC(nick)
   /* Send notify about nickname change to our router. We send the new
      ID and ask to replace it with the old one. If we are router the
      packet is broadcasted. Send NICK_CHANGE notify. */
-  if (!server->standalone)
-    silc_server_send_notify_nick_change(server, server->router->connection, 
-                                       server->server_type == SILC_SERVER ? 
-                                       FALSE : TRUE, client->id,
-                                       new_id, nick);
+  silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
+                                     SILC_BROADCAST(server), client->id,
+                                     new_id, nick);
 
   /* Check if anyone is watching the old nickname */
   if (server->server_type == SILC_ROUTER)
@@ -2305,7 +2313,7 @@ SILC_SERVER_CMD_FUNC(list)
     old_ident = silc_command_get_ident(cmd->payload);
     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
-    silc_server_packet_send(server, server->router->connection,
+    silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, cmd->packet->flags,
                            tmpbuf->data, tmpbuf->len, TRUE);
 
@@ -2432,26 +2440,26 @@ SILC_SERVER_CMD_FUNC(topic)
       goto out;
     }
 
-    /* Set the topic for channel */
-    silc_free(channel->topic);
-    channel->topic = strdup(tmp);
+    if (!channel->topic || strcmp(channel->topic, tmp)) {
+      /* Set the topic for channel */
+      silc_free(channel->topic);
+      channel->topic = strdup(tmp);
 
-    /* Send TOPIC_SET notify type to the network */
-    if (!server->standalone)
-      silc_server_send_notify_topic_set(server, server->router->connection,
-                                       server->server_type == SILC_ROUTER ?
-                                       TRUE : FALSE, channel, 
+      /* Send TOPIC_SET notify type to the network */
+      silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
+                                       SILC_BROADCAST(server), channel,
                                        client->id, SILC_ID_CLIENT,
                                        channel->topic);
 
-    idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-
-    /* Send notify about topic change to all clients on the channel */
-    silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
-                                      SILC_NOTIFY_TYPE_TOPIC_SET, 2,
-                                      idp->data, idp->len,
-                                      channel->topic, strlen(channel->topic));
-    silc_buffer_free(idp);
+      /* Send notify about topic change to all clients on the channel */
+      idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+      silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
+                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
+                                        idp->data, idp->len,
+                                        channel->topic,
+                                        strlen(channel->topic));
+      silc_buffer_free(idp);
+    }
   }
 
   /* Send the topic to client as reply packet */
@@ -2673,11 +2681,9 @@ SILC_SERVER_CMD_FUNC(invite)
   }
 
   /* Send notify to the primary router */
-  if (!server->standalone)
-    silc_server_send_notify_invite(server, server->router->connection,
-                                  server->server_type == SILC_ROUTER ?
-                                  TRUE : FALSE, channel,
-                                  sender->id, add, del);
+  silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
+                                SILC_BROADCAST(server), channel,
+                                sender->id, add, del);
 
   /* Send command reply */
   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
@@ -2967,7 +2973,7 @@ SILC_SERVER_CMD_FUNC(info)
       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
 
-      silc_server_packet_send(server, server->router->connection,
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
                              tmpbuf->data, tmpbuf->len, TRUE);
 
@@ -3100,7 +3106,7 @@ SILC_SERVER_CMD_FUNC(stats)
     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
                                            ++server->cmd_ident, 1,
                                            1, idp->data, idp->len);
-    silc_server_packet_send(server, server->router->connection,
+    silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, 0, packet->data,
                            packet->len, FALSE);
 
@@ -3178,7 +3184,7 @@ static void silc_server_command_join_channel(SilcServer server,
   unsigned char *fkey = NULL;
   SilcUInt32 fkey_len = 0;
 
-  SILC_LOG_DEBUG(("Start"));
+  SILC_LOG_DEBUG(("Joining client to channel"));
 
   if (!channel)
     return;
@@ -3445,10 +3451,8 @@ static void silc_server_command_join_channel(SilcServer server,
 
   if (!cmd->pending) {
     /* Send JOIN notify packet to our primary router */
-    if (!server->standalone)
-      silc_server_send_notify_join(server, server->router->connection,
-                                  server->server_type == SILC_ROUTER ?
-                                  TRUE : FALSE, channel, client->id);
+    silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
+                                SILC_BROADCAST(server), channel, client->id);
 
     if (keyp)
       /* Distribute the channel key to all backup routers. */
@@ -3469,10 +3473,9 @@ static void silc_server_command_join_channel(SilcServer server,
   }
 
   /* Set CUMODE notify type to network */
-  if (founder && !server->standalone)
-    silc_server_send_notify_cumode(server, server->router->connection,
-                                  server->server_type == SILC_ROUTER ?
-                                  TRUE : FALSE, channel,
+  if (founder)
+    silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
+                                  SILC_BROADCAST(server), channel,
                                   chl->mode, client->id, SILC_ID_CLIENT,
                                   client->id, channel->founder_key);
 
@@ -3600,7 +3603,7 @@ SILC_SERVER_CMD_FUNC(join)
          
          /* Send JOIN command to our router */
          silc_server_packet_send(server, (SilcSocketConnection)
-                                 server->router->connection,
+                                 SILC_PRIMARY_ROUTE(server),
                                  SILC_PACKET_COMMAND, cmd->packet->flags,
                                  tmpbuf->data, tmpbuf->len, TRUE);
          
@@ -3817,7 +3820,7 @@ SILC_SERVER_CMD_FUNC(motd)
       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
 
-      silc_server_packet_send(server, server->router->connection,
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
                              tmpbuf->data, tmpbuf->len, TRUE);
 
@@ -3918,9 +3921,9 @@ SILC_SERVER_CMD_FUNC(umode)
     client->mode = mask;
 
     /* Send UMODE change to primary router */
-    if (!server->standalone)
-      silc_server_send_notify_umode(server, server->router->connection, TRUE,
-                                   client->id, client->mode);
+    silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
+                                 SILC_BROADCAST(server), client->id,
+                                 client->mode);
 
     /* Check if anyone is watching this nickname */
     if (server->server_type == SILC_ROUTER)
@@ -4009,6 +4012,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   /* Check that client has rights to change any requested channel modes */
   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl, 
                                                  mode_mask)) {
+    SILC_LOG_DEBUG(("Client does not have rights to change mode"));
     silc_server_command_send_status_reply(
                             cmd, SILC_COMMAND_CMODE,
                             (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ? 
@@ -4310,12 +4314,10 @@ SILC_SERVER_CMD_FUNC(cmode)
                                     fkey, fkey_len);
 
   /* Set CMODE notify type to network */
-  if (!server->standalone)
-    silc_server_send_notify_cmode(server, server->router->connection,
-                                 server->server_type == SILC_ROUTER ? 
-                                 TRUE : FALSE, channel,
-                                 mode_mask, client->id, SILC_ID_CLIENT,
-                                 cipher, hmac, passphrase, founder_key);
+  silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
+                               SILC_BROADCAST(server), channel,
+                               mode_mask, client->id, SILC_ID_CLIENT,
+                               cipher, hmac, passphrase, founder_key);
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
@@ -4669,13 +4671,10 @@ SILC_SERVER_CMD_FUNC(cumode)
                                       fkey, fkey_len);
 
     /* Set CUMODE notify type to network */
-    if (!server->standalone)
-      silc_server_send_notify_cumode(server, server->router->connection,
-                                    server->server_type == SILC_ROUTER ? 
-                                    TRUE : FALSE, channel,
-                                    target_mask, client->id, 
-                                    SILC_ID_CLIENT,
-                                    target_client->id, founder_key);
+    silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
+                                  SILC_BROADCAST(server), channel,
+                                  target_mask, client->id, SILC_ID_CLIENT,
+                                  target_client->id, founder_key);
   }
 
   /* Send command reply to sender */
@@ -4824,11 +4823,9 @@ SILC_SERVER_CMD_FUNC(kick)
     goto out;
 
   /* Send KICKED notify to primary route */
-  if (!server->standalone)
-    silc_server_send_notify_kicked(server, server->router->connection,
-                                  server->server_type == SILC_ROUTER ?
-                                  TRUE : FALSE, channel,
-                                  target_client->id, client->id, comment);
+  silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
+                                SILC_BROADCAST(server), channel,
+                                target_client->id, client->id, comment);
 
   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
     /* Re-generate channel key */
@@ -4930,9 +4927,9 @@ SILC_SERVER_CMD_FUNC(oper)
     server->stat.server_ops++;
 
   /* Send UMODE change to primary router */
-  if (!server->standalone)
-    silc_server_send_notify_umode(server, server->router->connection, TRUE,
-                                 client->id, client->mode);
+  silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
+                               SILC_BROADCAST(server), client->id,
+                               client->mode);
 
   /* Check if anyone is watching this nickname */
   if (server->server_type == SILC_ROUTER)
@@ -4950,18 +4947,27 @@ SILC_SERVER_CMD_FUNC(oper)
 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
 {
   QuitInternal q = (QuitInternal)context;
-  SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
+  SilcClientID *client_id = (SilcClientID *)q->sock;
+  SilcClientEntry client;
+  SilcSocketConnection sock;
 
-  /* If there is pending outgoing data for the client then purge it
-     to the network before closing connection. */
-  silc_server_packet_queue_purge(q->server, q->sock);
+  client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
+                                        TRUE, NULL);
+  if (client && client->connection) {
+    sock = client->connection;
 
-  /* Close the connection on our side */
-  client->router = NULL;
-  client->connection = NULL;
-  q->sock->user_data = NULL;
-  silc_server_close_connection(q->server, q->sock);
+    /* If there is pending outgoing data for the client then purge it
+       to the network before closing connection. */
+    silc_server_packet_queue_purge(q->server, sock);
+
+    /* Close the connection on our side */
+    client->router = NULL;
+    client->connection = NULL;
+    sock->user_data = NULL;
+    silc_server_close_connection(q->server, sock);
+  }
 
+  silc_free(client_id);
   silc_free(q);
 }
 
@@ -4971,14 +4977,13 @@ SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
   SilcClientID *client_id = (SilcClientID *)q->sock;
   SilcClientEntry client;
 
-  SILC_LOG_DEBUG(("Start"));
-
   client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
-                                        FALSE, NULL);
-
-  if (client && client->mode & SILC_UMODE_DETACHED)
+                                        TRUE, NULL);
+  if (client && client->mode & SILC_UMODE_DETACHED) {
+    SILC_LOG_DEBUG(("Detach timeout"));
     silc_server_free_client_data(q->server, NULL, client, TRUE,
                                 "Detach timeout");
+  }
 
   silc_free(client_id);
   silc_free(q);
@@ -5010,10 +5015,9 @@ SILC_SERVER_CMD_FUNC(detach)
   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
   client->last_command = 0;
   client->fast_command = 0;
-  if (!server->standalone)
-    silc_server_send_notify_umode(server, server->router->connection,
-                                 server->server_type == SILC_SERVER ?
-                                 FALSE : TRUE, client->id, client->mode);
+  silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
+                               SILC_BROADCAST(server), client->id,
+                               client->mode);
   server->stat.my_detached++;
 
   /* Check if anyone is watching this nickname */
@@ -5023,7 +5027,7 @@ SILC_SERVER_CMD_FUNC(detach)
 
   q = silc_calloc(1, sizeof(*q));
   q->server = server;
-  q->sock = cmd->sock;
+  q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
                         q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
 
@@ -5070,7 +5074,7 @@ SILC_SERVER_CMD_FUNC(watch)
       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
 
-      silc_server_packet_send(server, server->router->connection,
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
                              tmpbuf->data, tmpbuf->len, TRUE);
 
@@ -5309,9 +5313,9 @@ SILC_SERVER_CMD_FUNC(silcoper)
     server->stat.router_ops++;
 
   /* Send UMODE change to primary router */
-  if (!server->standalone)
-    silc_server_send_notify_umode(server, server->router->connection, TRUE,
-                                 client->id, client->mode);
+  silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
+                               SILC_BROADCAST(server), client->id,
+                               client->mode);
 
   /* Check if anyone is watching this nickname */
   if (server->server_type == SILC_ROUTER)
@@ -5427,10 +5431,9 @@ SILC_SERVER_CMD_FUNC(ban)
   }
 
   /* Send the BAN notify type to our primary router. */
-  if (!server->standalone && (add || del))
-    silc_server_send_notify_ban(server, server->router->connection,
-                               server->server_type == SILC_ROUTER ?
-                               TRUE : FALSE, channel, add, del);
+  if (add || del)
+    silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
+                               SILC_BROADCAST(server), channel, add, del);
 
   /* Send the reply back to the client */
   packet = 
@@ -5500,10 +5503,8 @@ SILC_SERVER_CMD_FUNC(leave)
 
   /* Notify routers that they should remove this client from their list
      of clients on the channel. Send LEAVE notify type. */
-  if (!server->standalone)
-    silc_server_send_notify_leave(server, server->router->connection,
-                                 server->server_type == SILC_ROUTER ?
-                                 TRUE : FALSE, channel, id_entry->id);
+  silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
+                               SILC_BROADCAST(server), channel, id_entry->id);
 
   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
                                       SILC_STATUS_OK, 0, 2, tmp, len);
@@ -5592,7 +5593,7 @@ SILC_SERVER_CMD_FUNC(users)
       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
       
       /* Send USERS command */
-      silc_server_packet_send(server, server->router->connection,
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
                              tmpbuf->data, tmpbuf->len, TRUE);
       
@@ -5695,8 +5696,6 @@ SILC_SERVER_CMD_FUNC(getkey)
   SilcIdType id_type;
   SilcPublicKey public_key;
 
-  SILC_LOG_DEBUG(("Start"));
-
   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   if (!tmp) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
@@ -5807,7 +5806,7 @@ SILC_SERVER_CMD_FUNC(getkey)
       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
       
-      silc_server_packet_send(server, server->router->connection,
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
                              tmpbuf->data, tmpbuf->len, TRUE);