+ silc_packet_free(packet);
+ silc_fsm_next(fsm, silc_client_connection_st_packet);
+ return SILC_FSM_CONTINUE;
+}
+
+#if 0 /* XXX we need to rethink this */
+/* Initialize private message waiting in a thread. */
+
+void *silc_client_private_message_wait_init(SilcClientConnection conn,
+ SilcClientEntry client_entry)
+{
+ SilcClientPrivateMessageWait pmw;
+
+ pmw = silc_calloc(1, sizeof(*pmw));
+ if (!pmw)
+ return NULL;
+
+ pmw->message_queue = silc_dlist_init();
+ if (!pmw->message_queue) {
+ silc_free(pmw);
+ return NULL;
+ }
+
+ /* Allocate mutex and conditional variable */
+ if (!silc_mutex_alloc(&pmw->wait_lock)) {
+ silc_dlist_uninit(pmw->message_queue);
+ silc_free(pmw);
+ return NULL;
+ }
+ if (!silc_cond_alloc(&pmw->wait_cond)) {
+ silc_dlist_uninit(pmw->message_queue);
+ silc_mutex_free(pmw->wait_lock);
+ silc_free(pmw);
+ return NULL;
+ }
+
+ silc_mutex_lock(conn->internal->lock);
+
+ /* Allocate waiting hash table */
+ if (!conn->internal->privmsg_wait) {
+ conn->internal->privmsg_wait =
+ silc_hash_table_alloc(0, silc_hash_id,
+ SILC_32_TO_PTR(SILC_ID_CLIENT),
+ silc_hash_id_compare,
+ SILC_32_TO_PTR(SILC_ID_CLIENT), NULL, NULL, TRUE);
+ if (!conn->internal->privmsg_wait) {
+ silc_mutex_unlock(conn->internal->lock);
+ silc_dlist_uninit(pmw->message_queue);
+ silc_mutex_free(pmw->wait_lock);
+ silc_cond_free(pmw->wait_cond);
+ silc_free(pmw);
+ return NULL;
+ }
+ }
+
+ /* Add to waiting hash table */
+ silc_hash_table_add(conn->internal->privmsg_wait, client_entry->id, pmw);
+
+ silc_mutex_unlock(conn->internal->lock);
+
+ return (void *)pmw;
+}
+
+/* Uninitialize private message waiting. */
+
+void silc_client_private_message_wait_uninit(SilcClientConnection conn,
+ SilcClientEntry client_entry,
+ void *waiter)
+{
+ SilcClientPrivateMessageWait pmw = waiter;
+ SilcMessagePayload payload;
+
+ /* Signal any threads to stop waiting */
+ silc_mutex_lock(pmw->wait_lock);
+ pmw->stopped = TRUE;
+ silc_cond_broadcast(pmw->wait_cond);
+ silc_mutex_unlock(pmw->wait_lock);
+
+ /* Re-acquire lock and free resources */
+ silc_mutex_lock(pmw->wait_lock);
+
+ /* Free any remaining message */
+ silc_dlist_start(pmw->message_queue);
+ while ((payload = silc_dlist_get(pmw->message_queue)))
+ silc_message_payload_free(payload);
+
+ silc_dlist_uninit(pmw->message_queue);
+ silc_cond_free(pmw->wait_cond);
+ silc_mutex_unlock(pmw->wait_lock);
+ silc_mutex_free(pmw->wait_lock);
+
+ silc_mutex_lock(conn->internal->lock);
+ silc_hash_table_del_by_context(conn->internal->privmsg_wait,
+ client_entry->id, pmw);
+ silc_mutex_unlock(conn->internal->lock);
+
+ silc_free(pmw);
+}
+
+/* Blocks the calling process or thread until a private message has been
+ received from the specified client. */
+
+SilcBool silc_client_private_message_wait(SilcClientConnection conn,
+ SilcClientEntry client_entry,
+ void *waiter,
+ SilcMessagePayload *payload)
+{
+ SilcClientPrivateMessageWait pmw = waiter;
+ SilcPacket packet;
+
+ silc_mutex_lock(pmw->wait_lock);
+
+ /* Wait here until private message has been received */
+ while (silc_dlist_count(pmw->message_queue) == 0) {
+ if (pmw->stopped) {
+ silc_mutex_unlock(pmw->wait_lock);
+ return FALSE;
+ }
+ silc_cond_wait(pmw->wait_cond, pmw->wait_lock);
+ }
+
+ /* Return message */
+ silc_dlist_start(pmw->message_queue);
+ *payload = silc_dlist_get(pmw->message_queue);
+ silc_dlist_del(pmw->message_queue, *payload);
+
+ silc_mutex_unlock(pmw->wait_lock);
+
+ return TRUE;