updates.
[silc.git] / apps / silcd / packet_send.c
index 81305e729b37ca5e12618ee4a8e2b1614343fcec..773c3f3ef39620d842a67bea05953f75df8a5146 100644 (file)
@@ -386,6 +386,78 @@ void silc_server_packet_route(SilcServer server,
   silc_server_packet_send_real(server, sock, TRUE);
 }
 
+/* This routine can be used to send a packet to table of clients provided
+   in `clients'. If `route' is FALSE the packet is routed only to local
+   clients (for server locally connected, and for router local cell). */
+
+void silc_server_packet_send_clients(SilcServer server,
+                                    SilcClientEntry *clients,
+                                    uint32 clients_count,
+                                    SilcPacketType type, 
+                                    SilcPacketFlags flags,
+                                    bool route,
+                                    unsigned char *data, 
+                                    uint32 data_len,
+                                    bool force_send)
+{
+  SilcSocketConnection sock = NULL;
+  SilcClientEntry client = NULL;
+  SilcServerEntry *routed = NULL;
+  uint32 routed_count = 0;
+  bool gone = FALSE;
+  int i, k;
+
+  SILC_LOG_DEBUG(("Sending packet to list of clients"));
+
+  /* Send to all clients in table */
+  for (i = 0; i < clients_count; i++) {
+    client = clients[i];
+
+    /* If client has router set it is not locally connected client and
+       we will route the message to the router set in the client. Though,
+       send locally connected server in all cases. */
+    if (server->server_type == SILC_ROUTER && client->router && 
+       ((!route && client->router->router == server->id_entry) || route)) {
+
+      /* Check if we have sent the packet to this route already */
+      for (k = 0; k < routed_count; k++)
+       if (routed[k] == client->router)
+         break;
+      if (k < routed_count)
+       continue;
+
+      /* Route only once to router */
+      sock = (SilcSocketConnection)client->router->connection;
+      if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+       if (gone)
+         continue;
+       gone = TRUE;
+      }
+
+      /* Send the packet */
+      silc_server_packet_send_dest(server, sock, type, flags,
+                                  client->router->id, SILC_ID_SERVER,
+                                  data, data_len, force_send);
+
+      /* Mark this route routed already */
+      routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
+      routed[routed_count++] = client->router;
+      continue;
+    }
+
+    if (client->router)
+      continue;
+
+    /* Send to locally connected client */
+    sock = (SilcSocketConnection)client->connection;
+    silc_server_packet_send_dest(server, sock, type, flags,
+                                client->id, SILC_ID_CLIENT,
+                                data, data_len, force_send);
+  }
+
+  silc_free(routed);
+}
+
 /* Internal routine to actually create the channel packet and send it
    to network. This is common function in channel message sending. If
    `channel_message' is TRUE this encrypts the message as it is strictly
@@ -403,20 +475,17 @@ silc_server_packet_send_to_channel_real(SilcServer server,
                                        bool channel_message,
                                        bool force_send)
 {
-  int block_len = 0;
+  int block_len;
   packet->truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packet->src_id_len + packet->dst_id_len;
 
-  if (cipher) {
-    block_len = silc_cipher_get_block_len(cipher);
-
-    if (channel_message)
-      packet->padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
-                                          packet->src_id_len +
-                                          packet->dst_id_len), block_len);
-    else
-      packet->padlen = SILC_PACKET_PADLEN(packet->truelen, block_len);
-  }
+  block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
+  if (channel_message)
+    packet->padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
+                                        packet->src_id_len +
+                                        packet->dst_id_len), block_len);
+  else
+    packet->padlen = SILC_PACKET_PADLEN(packet->truelen, block_len);
 
   /* Prepare outgoing data buffer for packet sending */
   silc_packet_send_prepare(sock, 
@@ -578,7 +647,7 @@ void silc_server_packet_send_to_channel(SilcServer server,
     if (sender && sock == sender)
       continue;
 
-      /* Send the packet */
+    /* Send the packet */
     silc_server_packet_send_to_channel_real(server, sock, &packetdata,
                                            idata->send_key, 
                                            idata->hmac_send, 
@@ -965,7 +1034,7 @@ void silc_server_send_motd(SilcServer server,
   if (server->config && server->config->motd && 
       server->config->motd->motd_file) {
 
-    motd = silc_file_read(server->config->motd->motd_file, &motd_len);
+    motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
     if (!motd)
       return;
 
@@ -1419,7 +1488,6 @@ void silc_server_send_notify_on_channels(SilcServer server,
   uint32 data_len;
   bool force_send = FALSE;
   va_list ap;
-  int block_len;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -1471,15 +1539,18 @@ void silc_server_send_notify_on_channels(SilcServer server,
        /* Get data used in packet header encryption, keys and stuff. */
        sock = (SilcSocketConnection)c->router->connection;
        idata = (SilcIDListData)c->router;
-       block_len = idata->send_key ? 
-         silc_cipher_get_block_len(idata->send_key) : 0;
+
+       {
+         SILC_LOG_DEBUG(("*****************"));
+         SILC_LOG_DEBUG(("client->router->id %s",
+                         silc_id_render(c->router->id, SILC_ID_SERVER)));
+         SILC_LOG_DEBUG(("client->router->connection->user_data->id %s",
+                         silc_id_render(((SilcServerEntry)sock->user_data)->id, SILC_ID_SERVER)));
+       }
 
        packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER);
        packetdata.dst_id_len = silc_id_get_len(c->router->id, SILC_ID_SERVER);
        packetdata.dst_id_type = SILC_ID_SERVER;
-       packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
-         packetdata.src_id_len + packetdata.dst_id_len;
-       packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
 
        /* Send the packet */
        silc_server_packet_send_to_channel_real(server, sock, &packetdata,
@@ -1507,15 +1578,10 @@ void silc_server_send_notify_on_channels(SilcServer server,
        /* Get data used in packet header encryption, keys and stuff. */
        sock = (SilcSocketConnection)c->connection;
        idata = (SilcIDListData)c;
-       block_len = idata->send_key ? 
-         silc_cipher_get_block_len(idata->send_key) : 0;
        
        packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
        packetdata.dst_id_len = silc_id_get_len(c->id, SILC_ID_CLIENT);
        packetdata.dst_id_type = SILC_ID_CLIENT;
-       packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
-         packetdata.src_id_len + packetdata.dst_id_len;
-       packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
 
        /* Send the packet */
        silc_server_packet_send_to_channel_real(server, sock, &packetdata,
@@ -1673,6 +1739,28 @@ void silc_server_send_command(SilcServer server,
   va_end(ap);
 }
 
+/* Generic function to send any command reply. The arguments must be sent
+   already encoded into correct form in correct order. */
+
+void silc_server_send_command_reply(SilcServer server, 
+                                   SilcSocketConnection sock,
+                                   SilcCommand command, 
+                                   SilcCommandStatus status,
+                                   uint16 ident,
+                                   uint32 argc, ...)
+{
+  SilcBuffer packet;
+  va_list ap;
+
+  va_start(ap, argc);
+
+  packet = silc_command_reply_payload_encode_vap(command, ident, argc, ap);
+  silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
+                         packet->data, packet->len, TRUE);
+  silc_buffer_free(packet);
+  va_end(ap);
+}
+
 /* Send the heartbeat packet. */
 
 void silc_server_send_heartbeat(SilcServer server,