- silc_client_packet_send_real(client, sock, force_send);
-}
-
-/* Sends packet to a channel. Packet to channel is always encrypted
- differently from "normal" packets. SILC header of the packet is
- encrypted with the next receiver's key and the rest of the packet is
- encrypted with the channel specific key. Padding and HMAC is computed
- with the next receiver's key. */
-
-void silc_client_packet_send_to_channel(SilcClient client,
- SilcSocketConnection sock,
- SilcChannelEntry channel,
- unsigned char *data,
- unsigned int data_len,
- int force_send)
-{
- int i;
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- SilcBuffer payload;
- SilcPacketContext packetdata;
- SilcCipher cipher;
- SilcHmac hmac;
- unsigned char *id_string;
-
- SILC_LOG_DEBUG(("Sending packet to channel"));
-
- if (!channel || !channel->key) {
- client->ops->say(client, conn,
- "Cannot talk to channel: key does not exist");
- return;
- }
-
- /* Generate IV */
- if (!channel->iv)
- for (i = 0; i < 16; i++)
- channel->iv[i] = silc_rng_get_byte(client->rng);
- else
- silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
-
- /* Encode the channel payload */
- payload = silc_channel_encode_payload(strlen(conn->nickname), conn->nickname,
- data_len, data, 16, channel->iv,
- client->rng);
- if (!payload) {
- client->ops->say(client, conn,
- "Error: Could not create packet to be sent to channel");
- return;
- }
-
- /* Get data used in packet header encryption, keys and stuff. Rest
- of the packet (the payload) is, however, encrypted with the
- specified channel key. */
- cipher = conn->send_key;
- hmac = conn->hmac;
- id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
-
- /* Set the packet context pointers. The destination ID is always
- the Channel ID of the channel. Server and router will handle the
- distribution of the packet. */
- packetdata.flags = 0;
- packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
- packetdata.src_id = conn->local_id_data;
- packetdata.src_id_len = SILC_ID_CLIENT_LEN;
- packetdata.src_id_type = SILC_ID_CLIENT;
- packetdata.dst_id = id_string;
- packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
- packetdata.dst_id_type = SILC_ID_CHANNEL;
- packetdata.rng = client->rng;
- packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len + packetdata.dst_id_len;
- packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len +
- packetdata.dst_id_len));
-
- /* Prepare outgoing data buffer for packet sending */
- silc_packet_send_prepare(sock,
- SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len +
- packetdata.dst_id_len,
- packetdata.padlen,
- payload->len);
-
- packetdata.buffer = sock->outbuf;
-
- /* Encrypt payload of the packet. This is encrypted with the channel key. */
- channel->channel_key->cipher->encrypt(channel->channel_key->context,
- payload->data, payload->data,
- payload->len - 16, /* -IV_LEN */
- channel->iv);
-
- /* Put the actual encrypted payload data into the buffer. */
- silc_buffer_put(sock->outbuf, payload->data, payload->len);
-
- /* Create the outgoing packet */
- silc_packet_assemble(&packetdata);
-
- /* Encrypt the header and padding of the packet. This is encrypted
- with normal session key shared with our server. */
- silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len + packetdata.dst_id_len +
- packetdata.padlen);
-
- SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
- sock->outbuf->data, sock->outbuf->len);
-
- /* Now actually send the packet */
- silc_client_packet_send_real(client, sock, force_send);
- silc_buffer_free(payload);
- silc_free(id_string);