+/* Uninitializes private message waiter. */
+
+void silc_client_private_message_wait_uninit(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry client_entry)
+{
+ if (!client_entry->internal.prv_waiter)
+ return;
+ silc_packet_wait_uninit(client_entry->internal.prv_waiter, conn->stream);
+ client_entry->internal.prv_waiter = NULL;
+}
+
+/* Blocks the calling process or thread until private message has been
+ received from the specified client. */
+
+SilcBool silc_client_private_message_wait(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry client_entry,
+ SilcMessagePayload *payload)
+{
+ SilcPacket packet;
+
+ if (!client_entry->internal.prv_waiter)
+ return FALSE;
+
+ /* Block until private message arrives */
+ do {
+ if ((silc_packet_wait(client_entry->internal.prv_waiter, 0, &packet)) < 0)
+ return FALSE;
+
+ /* Parse the payload and decrypt it also if private message key is set */
+ *payload =
+ silc_message_payload_parse(silc_buffer_data(&packet->buffer),
+ silc_buffer_len(&packet->buffer),
+ TRUE, !client_entry->internal.generated,
+ client_entry->internal.receive_key,
+ client_entry->internal.hmac_receive,
+ packet->src_id, packet->src_id_len,
+ packet->dst_id, packet->dst_id_len,
+ NULL, FALSE, NULL);
+ if (!(*payload)) {
+ silc_packet_free(packet);
+ continue;
+ }
+
+ break;
+ } while (1);
+
+ silc_packet_free(packet);
+ return TRUE;
+}
+
+/*************************** Private Message Key ****************************/
+
+/* Sends private message key request. Sender of this packet is initiator
+ when setting the private message key. */
+
+static SilcBool
+silc_client_send_private_message_key_request(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry client_entry)
+{
+ const char *cipher, *hmac;
+
+ SILC_LOG_DEBUG(("Sending private message key request"));
+
+ cipher = silc_cipher_get_name(client_entry->internal.send_key);
+ hmac = silc_hmac_get_name(client_entry->internal.hmac_send);
+
+ /* Send the packet */
+ return silc_packet_send_va_ext(conn->stream,
+ SILC_PACKET_PRIVATE_MESSAGE_KEY,
+ 0, 0, NULL, SILC_ID_CLIENT,
+ &client_entry->id, NULL, NULL,
+ SILC_STR_UI_SHORT(strlen(cipher)),
+ SILC_STR_DATA(cipher, strlen(cipher)),
+ SILC_STR_UI_SHORT(strlen(hmac)),
+ SILC_STR_DATA(hmac, strlen(hmac)),
+ SILC_STR_END);
+}
+
+/* Client resolving callback. Here we simply mark that we are the responder
+ side of this private message key request. */