{
void *dst_id = NULL;
SilcIdType dst_id_type = SILC_ID_NONE;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
+ SilcIDListData idata;
if (!sock)
return;
+ idata = (SilcIDListData)sock->user_data;
+
/* If disconnecting, ignore the data */
if (SILC_IS_DISCONNECTING(sock))
return;
/* If entry is disabled do not sent anything. */
- if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED)
+ if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) ||
+ sock->user_data == server->id_entry) {
+ SILC_LOG_DEBUG(("Connection is disabled"));
return;
+ }
/* Get data used in the packet sending, keys and stuff */
switch(sock->type) {
{
SilcPacketContext packetdata;
const SilcBufferStruct packet;
- SilcIDListData idata = (SilcIDListData)sock->user_data;
+ SilcIDListData idata;
SilcCipher cipher = NULL;
SilcHmac hmac = NULL;
SilcUInt32 sequence = 0;
int block_len = 0;
/* If disconnecting, ignore the data */
- if (SILC_IS_DISCONNECTING(sock))
+ if (!sock || SILC_IS_DISCONNECTING(sock))
return;
+ idata = (SilcIDListData)sock->user_data;
+
/* If entry is disabled do not sent anything. */
- if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED)
+ if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) ||
+ sock->user_data == server->id_entry) {
+ SILC_LOG_DEBUG(("Connection is disabled"));
return;
+ }
- SILC_LOG_DEBUG(("Sending packet, type %d", type));
+ SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
if (dst_id) {
dst_id_data = silc_id_id2str(dst_id, dst_id_type);
SilcUInt32 src_id_len = 0;
int block_len = 0;
- SILC_LOG_DEBUG(("Sending packet, type %d", type));
+ SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
+
+ if (!sock)
+ return;
/* Get data used in the packet sending, keys and stuff */
idata = (SilcIDListData)sock->user_data;
+ /* If entry is disabled do not sent anything. */
+ if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) ||
+ sock->user_data == server->id_entry) {
+ SILC_LOG_DEBUG(("Connection is disabled"));
+ return;
+ }
+
+ if (idata) {
+ cipher = idata->send_key;
+ hmac = idata->hmac_send;
+ sequence = idata->psn_send++;
+ block_len = silc_cipher_get_block_len(cipher);
+ }
+
if (dst_id) {
dst_id_data = silc_id_id2str(dst_id, dst_id_type);
dst_id_len = silc_id_get_len(dst_id, dst_id_type);
src_id_len = silc_id_get_len(src_id, src_id_type);
}
- if (idata) {
- cipher = idata->send_key;
- hmac = idata->hmac_send;
- sequence = idata->psn_send++;
- block_len = silc_cipher_get_block_len(cipher);
- }
-
/* Set the packet context pointers */
packetdata.type = type;
packetdata.flags = flags;
SilcIDListData idata;
void *id;
+ if (!sock)
+ return;
+
SILC_LOG_DEBUG(("Broadcasting received broadcast packet"));
/* If the packet is originated from our primary route we are
clients (for server locally connected, and for router local cell). */
void silc_server_packet_send_clients(SilcServer server,
- SilcClientEntry *clients,
- SilcUInt32 clients_count,
+ SilcHashTable clients,
SilcPacketType type,
SilcPacketFlags flags,
bool route,
bool force_send)
{
SilcSocketConnection sock = NULL;
+ SilcHashTableList htl;
SilcClientEntry client = NULL;
SilcServerEntry *routed = NULL;
SilcUInt32 routed_count = 0;
bool gone = FALSE;
- int i, k;
+ int 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];
-
+ silc_hash_table_list(clients, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void **)&client)) {
/* 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. */
client->id, SILC_ID_CLIENT,
data, data_len, force_send);
}
-
+ silc_hash_table_list_reset(&htl);
silc_free(routed);
}
/* This doesn't send channel message packets */
assert(type != SILC_PACKET_CHANNEL_MESSAGE);
- SILC_LOG_DEBUG(("Sending packet to channel"));
-
/* Set the packet context pointers. */
packetdata.flags = 0;
packetdata.type = type;
if (sock != sender) {
SILC_LOG_DEBUG(("Sending packet to router for routing"));
-
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
idata->send_key,
idata->hmac_send,
}
}
+ if (!silc_hash_table_count(channel->user_list)) {
+ SILC_LOG_DEBUG(("Channel %s is empty", channel->channel_name));
+ goto out;
+ }
+
+ SILC_LOG_DEBUG(("Sending %s packet to channel %s",
+ silc_get_packet_name(type), channel->channel_name));
+
routed = silc_calloc(silc_hash_table_count(channel->user_list),
sizeof(*routed));
/* Send the message to clients on the channel's client list. */
silc_hash_table_list(channel->user_list, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
client = chl->client;
if (!client)
continue;
gone = TRUE;
}
+ SILC_LOG_DEBUG(("Sending packet to client %s",
+ client->nickname ? client->nickname :
+ (unsigned char *)""));
+
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
idata->send_key,
if (!sock || (sender && sock == sender))
continue;
+ SILC_LOG_DEBUG(("Sending packet to client %s",
+ client->nickname ? client->nickname :
+ (unsigned char *)""));
+
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
idata->send_key,
data, data_len, FALSE,
force_send);
}
-
silc_hash_table_list_reset(&htl);
+
+ out:
silc_free(routed);
silc_free(packetdata.src_id);
silc_free(packetdata.dst_id);
bool gone = FALSE;
int k;
- SILC_LOG_DEBUG(("Relaying packet to channel"));
-
if (!silc_server_client_on_channel(sender_entry, channel, &chl_sender))
return;
+ SILC_LOG_DEBUG(("Relaying packet to channel %s", channel->channel_name));
+
/* This encrypts the packet, if needed. It will be encrypted if
it came from the router thus it needs to be encrypted with the
channel key. If the channel key does not exist, then we know we
/* Send the message to clients on the channel's client list. */
silc_hash_table_list(channel->user_list, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
client = chl->client;
if (!client || client == sender_entry)
continue;
SilcHashTableList htl;
SilcSocketConnection sock = NULL;
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Send packet to local clients on channel %s",
+ channel->channel_name));
/* Send the message to clients on the channel's client list. */
silc_hash_table_list(channel->user_list, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
if (chl->client && !chl->client->router) {
sock = (SilcSocketConnection)chl->client->connection;
packet->data, packet->len, FALSE);
/* Send to backup routers if this is being broadcasted to primary
- router. */
- if (server->router && server->router->connection &&
- sock == server->router->connection && broadcast)
+ router. The silc_server_backup_send checks further whether to
+ actually send it or not. */
+ if ((broadcast && sock && sock == SILC_PRIMARY_ROUTE(server)) ||
+ (broadcast && !sock && !SILC_PRIMARY_ROUTE(server)))
silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
packet->data, packet->len, FALSE, TRUE);
bool force_send = FALSE;
va_list ap;
- SILC_LOG_DEBUG(("Start"));
-
- if (!silc_hash_table_count(client->channels))
+ if (!silc_hash_table_count(client->channels)) {
+ SILC_LOG_DEBUG(("Client is not joined to any channels"));
return;
+ }
+
+ SILC_LOG_DEBUG(("Sending notify to joined channels"));
va_start(ap, argc);
packet = silc_notify_payload_encode(type, argc, ap);
packetdata.src_id_type = SILC_ID_SERVER;
silc_hash_table_list(client->channels, &htl);
- while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+ while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
channel = chl->channel;
/* Send the message to all clients on the channel's client list. */
silc_hash_table_list(channel->user_list, &htl2);
- while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
+ while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
c = chl2->client;
if (sender && c == sender)
{
SilcBuffer idp;
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Sending new ID"));
idp = silc_id_payload_encode(id, id_type);
silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID,
unsigned char *cid;
SilcUInt32 name_len = strlen(channel_name);
- SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Sending new channel"));
cid = silc_id_id2str(channel_id, SILC_ID_CHANNEL);
if (!cid)
silc_buffer_clear(sock->outbuf);
}
}
+
+/* Send packet to clients that are known to be operators. If server
+ is router and `route' is TRUE then the packet would go to all operators
+ in the SILC network. If `route' is FALSE then only local operators
+ (local for server and cell wide for router). If `local' is TRUE then
+ only locally connected operators receive the packet. If `local' is
+ TRUE then `route' is ignored. If server is normal server and `route'
+ is FALSE it is equivalent to `local' being TRUE. */
+
+void silc_server_send_opers(SilcServer server,
+ SilcPacketType type,
+ SilcPacketFlags flags,
+ bool route, bool local,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ bool force_send)
+{
+ SilcIDCacheList list = NULL;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcClientEntry client = NULL;
+ SilcSocketConnection sock;
+ SilcServerEntry *routed = NULL;
+ SilcUInt32 routed_count = 0;
+ bool gone = FALSE;
+ int k;
+
+ SILC_LOG_DEBUG(("Sending %s packet to operators",
+ silc_get_packet_name(type)));
+
+ /* If local was requested send only locally connected operators. */
+ if (local || (server->server_type == SILC_SERVER && !route)) {
+ if (!silc_idcache_get_all(server->local_list->clients, &list) ||
+ !silc_idcache_list_first(list, &id_cache))
+ return;
+ while (id_cache) {
+ client = (SilcClientEntry)id_cache->context;
+ if (!client->router && SILC_IS_LOCAL(client) &&
+ (client->mode & SILC_UMODE_SERVER_OPERATOR ||
+ client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+
+ /* Send the packet to locally connected operator */
+ silc_server_packet_send_dest(server, client->connection, type, flags,
+ client->id, SILC_ID_CLIENT,
+ data, data_len, force_send);
+ }
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ silc_idcache_list_free(list);
+ return;
+ }
+
+ if (!silc_idcache_get_all(server->local_list->clients, &list) ||
+ !silc_idcache_list_first(list, &id_cache))
+ return;
+ while (id_cache) {
+ client = (SilcClientEntry)id_cache->context;
+ if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
+ !(client->mode & SILC_UMODE_ROUTER_OPERATOR))
+ goto next;
+
+ if (server->server_type != SILC_SERVER && 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)
+ goto next;
+
+ /* Route only once to router */
+ sock = (SilcSocketConnection)client->router->connection;
+ if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ if (gone)
+ goto next;
+ gone = TRUE;
+ }
+
+ /* Send the packet */
+ silc_server_packet_send_dest(server, sock, type, flags,
+ client->id, SILC_ID_CLIENT,
+ data, data_len, force_send);
+
+ /* Mark this route routed already */
+ routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
+ routed[routed_count++] = client->router;
+ goto next;
+ }
+
+ if (client->router || !client->connection)
+ goto next;
+
+ /* 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);
+
+ next:
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ silc_idcache_list_free(list);
+
+ if (!silc_idcache_get_all(server->global_list->clients, &list) ||
+ !silc_idcache_list_first(list, &id_cache))
+ return;
+ while (id_cache) {
+ client = (SilcClientEntry)id_cache->context;
+ if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
+ !(client->mode & SILC_UMODE_ROUTER_OPERATOR))
+ goto nextg;
+
+ if (server->server_type != SILC_SERVER && 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)
+ goto nextg;
+
+ /* Route only once to router */
+ sock = (SilcSocketConnection)client->router->connection;
+ if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ if (gone)
+ goto nextg;
+ gone = TRUE;
+ }
+
+ /* Send the packet */
+ silc_server_packet_send_dest(server, sock, type, flags,
+ client->id, SILC_ID_CLIENT,
+ data, data_len, force_send);
+
+ /* Mark this route routed already */
+ routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
+ routed[routed_count++] = client->router;
+ goto nextg;
+ }
+
+ if (client->router || !client->connection)
+ goto nextg;
+
+ /* 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);
+
+ nextg:
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+ silc_idcache_list_free(list);
+ silc_free(routed);
+}
+
+/* Send a notify packet to operators */
+
+void silc_server_send_opers_notify(SilcServer server,
+ bool route,
+ bool local,
+ SilcNotifyType type,
+ SilcUInt32 argc, ...)
+{
+ va_list ap;
+ SilcBuffer packet;
+
+ va_start(ap, argc);
+ packet = silc_notify_payload_encode(type, argc, ap);
+ silc_server_send_opers(server, SILC_PACKET_NOTIFY, 0,
+ route, local, packet->data, packet->len,
+ FALSE);
+ silc_buffer_free(packet);
+ va_end(ap);
+}