diff --git a/channels/drdynvc/tsmf/tsmf_media.c b/channels/drdynvc/tsmf/tsmf_media.c index 134ac7839..40f9701f2 100644 --- a/channels/drdynvc/tsmf/tsmf_media.c +++ b/channels/drdynvc/tsmf/tsmf_media.c @@ -140,7 +140,7 @@ static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync) boolean pending = false; TSMF_PRESENTATION* presentation = stream->presentation; - if (!stream->sample_list->head) + if (list_size(stream->sample_list) == 0) return NULL; if (sync) @@ -210,10 +210,10 @@ static void tsmf_stream_process_ack(TSMF_STREAM* stream) uint64 ack_time; ack_time = get_current_time(); - while (stream->sample_ack_list->head && !freerdp_thread_is_stopped(stream->thread)) + while (list_size(stream->sample_ack_list) > 0 && !freerdp_thread_is_stopped(stream->thread)) { sample = (TSMF_SAMPLE*) list_peek(stream->sample_ack_list); - if (sample->ack_time > ack_time) + if (!sample || sample->ack_time > ack_time) break; sample = list_dequeue(stream->sample_ack_list); @@ -646,9 +646,9 @@ void tsmf_presentation_free(TSMF_PRESENTATION* presentation) tsmf_presentation_stop(presentation); list_remove(presentation_list, presentation); - while (presentation->stream_list->head) + while (list_size(presentation->stream_list) > 0) { - stream = (TSMF_STREAM*) list_peek(presentation->stream_list); + stream = (TSMF_STREAM*) list_dequeue(presentation->stream_list); tsmf_stream_free(stream); } list_free(presentation->stream_list); diff --git a/channels/rdpsnd/rdpsnd_main.c b/channels/rdpsnd/rdpsnd_main.c index 2d9fe27de..f7d383ab8 100644 --- a/channels/rdpsnd/rdpsnd_main.c +++ b/channels/rdpsnd/rdpsnd_main.c @@ -107,11 +107,11 @@ static void rdpsnd_process_interval(rdpSvcPlugin* plugin) struct data_out_item* item; uint32 cur_time; - while (rdpsnd->data_out_list->head) + while (list_size(rdpsnd->data_out_list) > 0) { - item = (struct data_out_item*)rdpsnd->data_out_list->head->data; + item = (struct data_out_item*)list_peek(rdpsnd->data_out_list) ; cur_time = get_mstime(); - if (cur_time <= item->out_timestamp) + if (!item || cur_time <= item->out_timestamp) break; item = (struct data_out_item*)list_dequeue(rdpsnd->data_out_list); @@ -135,7 +135,7 @@ static void rdpsnd_process_interval(rdpSvcPlugin* plugin) } } - if (rdpsnd->data_out_list->head == NULL && !rdpsnd->is_open) + if (list_size(rdpsnd->data_out_list) == 0 && !rdpsnd->is_open) { rdpsnd->plugin.interval_ms = 0; } diff --git a/libfreerdp-channels/libchannels.c b/libfreerdp-channels/libchannels.c index cd3083bc5..c50196675 100644 --- a/libfreerdp-channels/libchannels.c +++ b/libfreerdp-channels/libchannels.c @@ -906,12 +906,15 @@ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instan rdpChannel* lrdp_channel; struct channel_data* lchannel_data; - while (channels->sync_data_list->head != NULL) + while (list_size(channels->sync_data_list) > 0) { freerdp_mutex_lock(channels->sync_data_mutex); item = (struct sync_data*)list_dequeue(channels->sync_data_list); freerdp_mutex_unlock(channels->sync_data_mutex); + if (!item) + break ; + lchannel_data = channels->channels_data + item->index; lrdp_channel = freerdp_channels_find_channel_by_name(channels, instance->settings, lchannel_data->name, &item->index); diff --git a/libfreerdp-channels/wtsvc.c b/libfreerdp-channels/wtsvc.c index 6e3424d06..45aaf6964 100644 --- a/libfreerdp-channels/wtsvc.c +++ b/libfreerdp-channels/wtsvc.c @@ -291,11 +291,12 @@ boolean WTSVirtualChannelRead( /* remove the first element (same as what we just peek) */ freerdp_mutex_lock(channel->mutex); list_dequeue(channel->receive_queue); - if (channel->receive_queue->head == NULL) + if (list_size(channel->receive_queue) == 0) wait_obj_clear(channel->receive_event); freerdp_mutex_unlock(channel->mutex); memcpy(Buffer, item->buffer, item->length); + wts_data_item_free(item) ; return true; } diff --git a/libfreerdp-utils/list.c b/libfreerdp-utils/list.c index 9f7990bff..5cc11be6c 100644 --- a/libfreerdp-utils/list.c +++ b/libfreerdp-utils/list.c @@ -23,15 +23,33 @@ #include #include +/** + * Allocates a new LIST_ITEM element. This will be used to store the data provided by the caller, + * and will be used as a new element in a list. + * + * @param data - pointer to the data that must be stored by the new item. + * + * @return An allocated LIST_ITEM element that contains the 'data' pointer. + */ static LIST_ITEM* list_item_new(void* data) { LIST_ITEM* item; item = xnew(LIST_ITEM); - item->data = data; + if (item) + item->data = data; return item; } +/** + * Searches an element in the list. + * The element is verified by its pointer value - there is no way to verify the buffer's content. + * + * @param list - pointer to a valid LIST structure + * @param data - pointer to the data that must be found. + * + * @return the LIST_ITEM element that contains the 'data' pointer. NULL if 'data' was not found. + */ static LIST_ITEM* list_item_find(LIST* list, void* data) { LIST_ITEM* item; @@ -44,6 +62,18 @@ static LIST_ITEM* list_item_find(LIST* list, void* data) return NULL; } +/** + * Allocates a new LIST structure. + * The list_*() API implements a chainlist and allows to store data of arbitrary type in FIFO mode. + * @see list_enqueue() to add elements to the list. + * @see list_dequeue() to remove the first element of the list and get a pointer to it. + * @see list_peek() to retrieve the first element of the list (and keep it there). + * @see list_free() to deallocate the list. + * @see list_size() to get the current number of elements in the list. + * + * @return A pointer to the allocated LIST structure. It must be deallocated by a call to list_free(). + * + */ LIST* list_new(void) { LIST* list; @@ -53,6 +83,12 @@ LIST* list_new(void) return list; } +/** + * Deallocates a LIST structure. + * All elements of the list will be removed (but not deallocated). Only the list-specific resources are freed. + * + * @param list - pointer to the LIST that must be deallocated. + */ void list_free(LIST* list) { while (list->head) @@ -60,6 +96,12 @@ void list_free(LIST* list) xfree(list); } +/** + * Add an element at the end of an existing list. + * + * @param list - pointer to the LIST that will contain the new element + * @param data - pointer to the buffer that will be added to the list + */ void list_enqueue(LIST* list, void* data) { LIST_ITEM* item; @@ -79,6 +121,14 @@ void list_enqueue(LIST* list, void* data) list->count++; } +/** + * Removes the first element of a list, and returns a pointer to it. + * The list-specific resources associated to this element are freed in the process. + * + * @param list - pointer to a valid LIST structure + * + * @return a pointer to the data of the first element of this list. NULL if the list is empty. + */ void* list_dequeue(LIST* list) { LIST_ITEM* item; @@ -100,6 +150,14 @@ void* list_dequeue(LIST* list) return data; } +/** + * Returns a pointer to the data from the first element of the list. + * The element itself is not removed from the list by this call. + * + * @param list - pointerto a valid LIST structure + * + * @return a pointer to the data of the first element of this list. NULL if the list is empty. + */ void* list_peek(LIST* list) { LIST_ITEM* item; @@ -108,6 +166,18 @@ void* list_peek(LIST* list) return item ? item->data : NULL; } +/** + * Searches for the data provided in parameter, and returns a pointer to the element next to it. + * If the item is not found, or if it is the last in the list, the function will return NULL. + * + * @param list - pointer to the list that must be searched. + * @param data - pointer to the buffer that must be found. The comparison is done on the pointer value - not the buffer's content. + * + * @return a pointer to the data of the element that resides after the 'data' parameter in the list. + * NULL if 'data' was not found in the list, or if it is the last element. + * + * @see list_item_find() for more information on list item searches. + */ void* list_next(LIST* list, void* data) { LIST_ITEM* item; @@ -122,6 +192,15 @@ void* list_next(LIST* list, void* data) return data; } +/** + * Searches for the data provided in parameter, and removes it from the list if it is found. + * + * @param list - pointer to the list that must be searched. + * @param data - pointer to the buffer that must be found. The comparison is done on the pointer value - not the buffer's content. + * + * @return the 'data' pointer, if the element was found, and successfully removed from the list. + * NULL if the element was not found. + */ void* list_remove(LIST* list, void* data) { LIST_ITEM* item; @@ -145,6 +224,14 @@ void* list_remove(LIST* list, void* data) return data; } +/** + * Returns the current size of the list (number of elements). + * This number is kept up to date by the list_enqueue and list_dequeue functions. + * + * @param list - pointer to a valide LIST structure. + * + * @return the number of elements in that list. + */ int list_size(LIST* list) { return list->count;