-/* Received new channel user packet. Information about new users on a
- channel are distributed between routers using this packet. The
- router receiving this will redistribute it and also sent JOIN notify
- to local clients on the same channel. Normal server sends JOIN notify
- to its local clients on the channel. */
-
-void silc_server_new_channel_user(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
-{
- unsigned char *tmpid1, *tmpid2;
- SilcClientID *client_id = NULL;
- SilcChannelID *channel_id = NULL;
- unsigned short channel_id_len;
- unsigned short client_id_len;
- SilcClientEntry client;
- SilcChannelEntry channel;
- SilcChannelClientEntry chl;
- SilcBuffer clidp;
- int ret;
-
- SILC_LOG_DEBUG(("Start"));
-
- if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
- server->server_type != SILC_ROUTER ||
- packet->src_id_type != SILC_ID_SERVER)
- return;
-
- /* Parse payload */
- ret = silc_buffer_unformat(packet->buffer,
- SILC_STR_UI16_NSTRING_ALLOC(&tmpid1,
- &channel_id_len),
- SILC_STR_UI16_NSTRING_ALLOC(&tmpid2,
- &client_id_len),
- SILC_STR_END);
- if (ret == -1) {
- if (tmpid1)
- silc_free(tmpid1);
- if (tmpid2)
- silc_free(tmpid2);
- return;
- }
-
- /* Decode the channel ID */
- channel_id = silc_id_str2id(tmpid1, channel_id_len, SILC_ID_CHANNEL);
- if (!channel_id)
- goto out;
-
- /* Decode the client ID */
- client_id = silc_id_str2id(tmpid2, client_id_len, SILC_ID_CLIENT);
- if (!client_id)
- goto out;
-
- /* Find the channel */
- channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
- if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
- if (!channel)
- goto out;
- }
-
- /* If we are router and this packet is not already broadcast packet
- we will broadcast it. */
- if (!server->standalone && server->server_type == SILC_ROUTER &&
- !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
- SILC_LOG_DEBUG(("Broadcasting received New Channel User packet"));
- silc_server_packet_send(server, server->router->connection, packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data, packet->buffer->len, FALSE);
- }
-
- /* Get client entry */
- client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
- if (!client) {
- client = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
- if (!client)
- goto out;
- }
-
- /* Join the client to the channel by adding it to channel's user list.
- Add also the channel to client entry's channels list for fast cross-
- referencing. */
- chl = silc_calloc(1, sizeof(*chl));
- chl->client = client;
- chl->channel = channel;
- silc_list_add(channel->user_list, chl);
- silc_list_add(client->channels, chl);
-
- server->stat.chanclients++;
-
- /* Send JOIN notify to local clients on the channel. As we are router
- it is assured that this is sent only to our local clients and locally
- connected servers if needed. */
- clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
- silc_server_send_notify_to_channel(server, sock, channel, FALSE,
- SILC_NOTIFY_TYPE_JOIN,
- 1, clidp->data, clidp->len);
- silc_buffer_free(clidp);
-
- client_id = NULL;
-
- out:
- if (client_id)
- silc_free(client_id);
- if (channel_id)
- silc_free(channel_id);
- silc_free(tmpid1);
- silc_free(tmpid2);
-}
-