From: Pekka Riikonen Date: Tue, 18 Jul 2006 13:14:02 +0000 (+0000) Subject: Handle packet wait uninitializing from another thread. X-Git-Tag: silc.client.1.1.beta1~294 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=3a2fc0ecc539b7dd79cf7e2c7b9ccd332d723f65 Handle packet wait uninitializing from another thread. --- diff --git a/lib/silccore/silcpacket.c b/lib/silccore/silcpacket.c index c19b9d08..685b68c5 100644 --- a/lib/silccore/silcpacket.c +++ b/lib/silccore/silcpacket.c @@ -51,7 +51,6 @@ struct SilcPacketStreamStruct { SilcStream stream; /* Underlaying stream */ SilcMutex lock; /* Stream lock */ SilcDList process; /* Packet processors, it set */ - SilcHashTable streamers; /* Valid if streamers exist */ void *stream_context; /* Stream context */ SilcBufferStruct inbuf; /* In buffer */ SilcBufferStruct outbuf; /* Out buffer */ @@ -497,8 +496,10 @@ static SilcBool silc_packet_stream_link_va(SilcPacketStream stream, if (!stream->process) { stream->process = silc_dlist_init(); - if (!stream->process) + if (!stream->process) { + silc_mutex_unlock(stream->lock); return FALSE; + } } /* According to priority set the procesor to correct position. First @@ -787,24 +788,6 @@ void silc_packet_free(SilcPacket packet) silc_mutex_unlock(stream->engine->lock); } -/* Creates streamer */ - -SilcStream silc_packet_streamer_create(SilcPacketStream stream, - SilcPacketType packet_type, - SilcPacketFlags packet_flags) -{ - /* XXX TODO */ - return NULL; -} - -/* Destroyes streamer */ - -void silc_packet_streamer_destroy(SilcStream stream) -{ - -} - - /****************************** Packet Sending ******************************/ /* Prepare outgoing data buffer for packet sending. Returns the @@ -1038,15 +1021,15 @@ SilcBool silc_packet_send_ext(SilcPacketStream stream, return FALSE; return silc_packet_send_raw(stream, type, flags, - src_id_type, - src_id_data, - src_id_len, - dst_id_type, - dst_id_data, - dst_id_len, + src_id ? src_id_type : stream->src_id_type, + src_id ? src_id_data : stream->src_id, + src_id ? src_id_len : stream->src_id_len, + dst_id ? dst_id_type : stream->dst_id_type, + dst_id ? dst_id_data : stream->dst_id, + dst_id ? dst_id_len : stream->dst_id_len, data, data_len, - cipher, - hmac); + cipher ? cipher : stream->send_key, + hmac ? hmac : stream->send_hmac); } @@ -1484,7 +1467,7 @@ typedef struct { SilcMutex wait_lock; SilcCond wait_cond; SilcList packet_queue; - SilcBool waiting; + unsigned int stopped : 1; } *SilcPacketWait; /* Packet wait receive callback */ @@ -1501,7 +1484,7 @@ silc_packet_wait_packet_receive(SilcPacketEngine engine, /* Signal the waiting thread for a new packet */ silc_mutex_lock(pw->wait_lock); - if (!pw->waiting) { + if (pw->stopped) { silc_mutex_unlock(pw->wait_lock); return FALSE; } @@ -1557,11 +1540,18 @@ void *silc_packet_wait_init(SilcPacketStream stream, ...) /* Uninitialize packet waiting */ -void silc_packet_wait_uninit(void *context, SilcPacketStream stream) +void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream) { - SilcPacketWait pw = context; + SilcPacketWait pw = waiter; SilcPacket packet; + /* Signal any threads to stop waiting */ + silc_mutex_lock(pw->wait_lock); + pw->stopped = TRUE; + silc_cond_broadcast(pw->wait_cond); + silc_mutex_unlock(pw->wait_lock); + + /* Re-acquire lock and free resources */ silc_mutex_lock(pw->wait_lock); silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw); @@ -1571,7 +1561,6 @@ void silc_packet_wait_uninit(void *context, SilcPacketStream stream) silc_packet_free(packet); silc_mutex_unlock(pw->wait_lock); - silc_cond_free(pw->wait_cond); silc_mutex_free(pw->wait_lock); silc_free(pw); @@ -1579,17 +1568,21 @@ void silc_packet_wait_uninit(void *context, SilcPacketStream stream) /* Blocks thread until a packet has been received. */ -int silc_packet_wait(void *context, int timeout, SilcPacket *return_packet) +int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet) { - SilcPacketWait pw = context; + SilcPacketWait pw = waiter; SilcBool ret = FALSE; silc_mutex_lock(pw->wait_lock); /* Wait here until packet has arrived */ - pw->waiting = TRUE; - while (silc_list_count(pw->packet_queue) == 0) + while (silc_list_count(pw->packet_queue) == 0) { + if (pw->stopped) { + silc_mutex_unlock(pw->wait_lock); + return -1; + } ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout); + } /* Return packet */ silc_list_start(pw->packet_queue); diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index 6f2c15a7..5bf28c99 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -394,10 +394,6 @@ void silc_packet_engine_stop(SilcPacketEngine engine); * To read packets you will receive the packet receive callback from * packet engine. Destroy the stream with silc_packet_stream_destroy. * - * If you need to send only one type of SILC packets, then it is possible - * to create SILC Packet Streamer with silc_packet_streamer_create, which - * can be used with silc_stream_read and silc_stream_write. - * * The SilcPacketStream is thread safe. Same context can be safely used * in multi threaded environment. * @@ -436,59 +432,6 @@ void silc_packet_stream_destroy(SilcPacketStream stream); ***/ void silc_packet_stream_set_router(SilcPacketStream stream); -/****f* silccore/SilcPacketAPI/silc_packet_streamer_create - * - * SYNOPSIS - * - * SilcStream silc_packet_streamer_create(SilcPacketStream stream, - * SilcPacketType packet_type, - * SilcPacketFlags packet_flags); - * - * DESCRIPTION - * - * This function can be used to create a SILC Packet Streamer that will - * stream only one type of packet indicated by `packet_type' with packet - * flags `packet_flags'. This is special purpose function as usually - * multiple different types of packets need to be sent in application. - * There are cases however when creating streamer is simpler and more - * efficient. Cases such as file transfer stream or other data streams - * that only send and receive one type of packet. While it would be - * possible to use silc_packet_send function to send packets it is - * more efficient to create the SILC Packet Streamer and use the - * silc_stream_read and silc_stream_write functions. - * - * The encryption and decryption keys, and other information will be - * retrieved from the packet stream indicated by `stream', which must be - * created before creating the streamer. - * - * NOTES - * - * The packet type that is assocated with the packet stream `stream' will - * only be available through the returned SilcStream. That packet type - * will not be delivered to the packet callbacks. To return to the - * normal operation destroy the streamer silc_packet_streamer_destroy. - * - ***/ -SilcStream silc_packet_streamer_create(SilcPacketStream stream, - SilcPacketType packet_type, - SilcPacketFlags packet_flags); - -/****f* silccore/SilcPacketAPI/silc_packet_streamer_destroy - * - * SYNOPSIS - * - * void silc_packet_streamer_destroy(SilcStream stream); - * - * DESCRIPTION - * - * Destroys the created packet streamer. Use this function only for - * stream created with silc_packet_streamer_create. The packet type - * that was associated with the streamer can be received in the packet - * callbacks after the streamer is destroyed. - * - ***/ -void silc_packet_streamer_destroy(SilcStream stream); - /****f* silccore/SilcPacketAPI/silc_packet_stream_get_stream * * SYNOPSIS @@ -779,7 +722,8 @@ SilcBool silc_packet_send(SilcPacketStream stream, * Same as silc_packet_send but with this function different sending * parameters can be sent as argument. This function can be used to * set specific IDs, cipher and HMAC to be used in packet sending, - * instead of the ones saved in the `stream'. + * instead of the ones saved in the `stream'. If any of the extra + * pointers are NULL, default values set to the stream will apply. * ***/ SilcBool silc_packet_send_ext(SilcPacketStream stream, @@ -807,6 +751,11 @@ SilcBool silc_packet_send_ext(SilcPacketStream stream, * to the silc_packet_wait function as argument. Returns NULL on * error. To uninitialize the waiting call silc_packet_wait_uninit. * + * NOTES + * + * Note that packets may be available immediately after calling this + * function and they will be buffered, until silc_packet_wait is called. + * * EXAMPLE * * void *waiter; @@ -827,7 +776,9 @@ void *silc_packet_wait_init(SilcPacketStream stream, ...); * * DESCRIPTION * - * Uninitializes the waiting context. + * Uninitializes the waiting context. This may be called also from + * another thread while other thread is waiting for packets. This will + * inform the waiting thread to stop waiting. * ***/ void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream); @@ -871,8 +822,8 @@ void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream); * } * * ... - * // Wait here until packet is received - * if ((silc_packet_wait(waiter, 0, &packet)) != -1) + * // Wait here until private message packet is received + * if ((silc_packet_wait(waiter, 0, &packet)) < 0) * return -1; * * ... process packet ...