X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient_channel.c;h=7dd4f0a6ad59a23572262fb48970de4decda3616;hp=077399b213db7784ee66ef31876df75426d00f93;hb=HEAD;hpb=54756d9cd19d09d28e1b317810faa961a6ff5d51 diff --git a/lib/silcclient/client_channel.c b/lib/silcclient/client_channel.c index 077399b2..7dd4f0a6 100644 --- a/lib/silcclient/client_channel.c +++ b/lib/silcclient/client_channel.c @@ -24,6 +24,29 @@ /************************** Channel Message Send ****************************/ +typedef struct { + SilcClient client; + SilcClientConnection conn; + SilcChannelEntry channel; +} *SilcClientChannelMessageContext; + +/* Message payload encoding callback */ + +static void silc_client_send_channel_message_final(SilcBuffer message, + void *context) +{ + SilcClientChannelMessageContext c = context; + + /* Send the channel message */ + if (message) + silc_packet_send_ext(c->conn->stream, SILC_PACKET_CHANNEL_MESSAGE, 0, + 0, NULL, SILC_ID_CHANNEL, &c->channel->id, + silc_buffer_datalen(message), NULL, NULL); + + silc_client_unref_channel(c->client, c->conn, c->channel); + silc_free(c); +} + /* Sends channel message to `channel'. */ SilcBool silc_client_send_channel_message(SilcClient client, @@ -35,19 +58,21 @@ SilcBool silc_client_send_channel_message(SilcClient client, unsigned char *data, SilcUInt32 data_len) { + SilcClientChannelMessageContext c; SilcChannelUser chu; - SilcBuffer buffer; SilcCipher cipher; SilcHmac hmac; - SilcBool ret; SilcID sid, rid; SILC_LOG_DEBUG(("Sending channel message")); if (silc_unlikely(!client || !conn || !channel)) return FALSE; - if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash)) + if (silc_unlikely(flags & SILC_MESSAGE_FLAG_SIGNED && !hash)) { + SILC_LOG_ERROR(("Cannot send signed message without hash, missing " + "arguments")); return FALSE; + } if (silc_unlikely(conn->internal->disconnected)) return FALSE; @@ -109,27 +134,26 @@ SilcBool silc_client_send_channel_message(SilcClient client, return FALSE; } - /* Encode the message payload. This also encrypts the message payload. */ + c = silc_calloc(1, sizeof(*c)); + if (!c) + return FALSE; + + c->client = client; + c->conn = conn; + c->channel = silc_client_ref_channel(client, conn, channel); + sid.type = SILC_ID_CLIENT; sid.u.client_id = chu->client->id; rid.type = SILC_ID_CHANNEL; rid.u.channel_id = chu->channel->id; - buffer = silc_message_payload_encode(flags, data, data_len, TRUE, FALSE, - cipher, hmac, client->rng, NULL, - conn->private_key, hash, &sid, &rid, - NULL); - if (silc_unlikely(!buffer)) { - SILC_LOG_ERROR(("Error encoding channel message")); - return FALSE; - } - /* Send the channel message */ - ret = silc_packet_send_ext(conn->stream, SILC_PACKET_CHANNEL_MESSAGE, 0, - 0, NULL, SILC_ID_CHANNEL, &channel->id, - silc_buffer_datalen(buffer), NULL, NULL); + /* Encode the message payload. This also encrypts the message payload. */ + silc_message_payload_encode(flags, data, data_len, TRUE, FALSE, + cipher, hmac, client->rng, NULL, + conn->private_key, hash, &sid, &rid, NULL, + silc_client_send_channel_message_final, c); - silc_buffer_free(buffer); - return ret; + return TRUE; } /************************* Channel Message Receive **************************/ @@ -626,8 +650,14 @@ SilcBool silc_client_del_channel_private_keys(SilcClient client, } channel->internal.curr_key = NULL; - channel->cipher = silc_cipher_get_name(channel->internal.send_key); - channel->hmac = silc_hmac_get_name(channel->internal.hmac); + if (channel->internal.send_key) + channel->cipher = silc_cipher_get_name(channel->internal.send_key); + else + channel->cipher = NULL; + if (channel->internal.hmac) + channel->hmac = silc_hmac_get_name(channel->internal.hmac); + else + channel->hmac = NULL; silc_dlist_uninit(channel->internal.private_keys); channel->internal.private_keys = NULL; @@ -887,12 +917,29 @@ void silc_client_empty_channel(SilcClient client, SilcBool silc_client_channel_save_public_keys(SilcChannelEntry channel, unsigned char *chpk_list, - SilcUInt32 chpk_list_len) + SilcUInt32 chpk_list_len, + SilcBool remove_all) { SilcArgumentDecodedList a, b; SilcDList chpks; SilcBool found; + if (remove_all) { + /* Remove all channel public keys */ + if (!channel->channel_pubkeys) + return FALSE; + + silc_dlist_start(channel->channel_pubkeys); + while ((b = silc_dlist_get(channel->channel_pubkeys))) + silc_dlist_del(channel->channel_pubkeys, b); + + silc_dlist_uninit(channel->channel_pubkeys); + channel->channel_pubkeys = NULL; + + return TRUE; + } + + /* Parse channel public key list and add or remove public keys */ chpks = silc_argument_list_parse_decoded(chpk_list, chpk_list_len, SILC_ARGUMENT_PUBLIC_KEY); if (!chpks)