diff --git a/channels/drdynvc/dvcman.c b/channels/drdynvc/dvcman.c index 536473b64..2138ac7e2 100644 --- a/channels/drdynvc/dvcman.c +++ b/channels/drdynvc/dvcman.c @@ -44,7 +44,7 @@ struct _DVCMAN IWTSListener* listeners[MAX_PLUGINS]; int num_listeners; - struct dvcman_channel_list* channels; + LIST* channels; }; typedef struct _DVCMAN_LISTENER DVCMAN_LISTENER; @@ -80,13 +80,6 @@ struct _DVCMAN_CHANNEL STREAM* dvc_data; }; -struct dvcman_channel_list_item -{ - DVCMAN_CHANNEL channel; -}; - -DEFINE_LIST_TYPE(dvcman_channel_list, dvcman_channel_list_item) - static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag) { @@ -192,7 +185,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) dvcman->iface.CreateListener = dvcman_create_listener; dvcman->iface.PushEvent = dvcman_push_event; dvcman->drdynvc = plugin; - dvcman->channels = dvcman_channel_list_new(); + dvcman->channels = list_new(); return (IWTSVirtualChannelManager*)dvcman; } @@ -220,14 +213,24 @@ int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, FRDP_PLUGIN_DATA* return 0; } +static void dvcman_channel_free(DVCMAN_CHANNEL* channel) +{ + if (channel->channel_callback) + channel->channel_callback->OnClose(channel->channel_callback); + xfree(channel); +} + void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) { DVCMAN* dvcman = (DVCMAN*)pChannelMgr; int i; IWTSPlugin* pPlugin; DVCMAN_LISTENER* listener; + DVCMAN_CHANNEL* channel; - dvcman_channel_list_free(dvcman->channels); + while ((channel = (DVCMAN_CHANNEL*)list_dequeue(dvcman->channels)) != NULL) + dvcman_channel_free(channel); + list_free(dvcman->channels); for (i = 0; i < dvcman->num_listeners; i++) { listener = (DVCMAN_LISTENER*)dvcman->listeners[i]; @@ -268,15 +271,6 @@ static int dvcman_write_channel(IWTSVirtualChannel* pChannel, return drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize); } -static void dvcman_channel_list_item_free(struct dvcman_channel_list_item* item) -{ - DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)item; - - if (channel->channel_callback) - channel->channel_callback->OnClose(channel->channel_callback); - xfree(item); -} - static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) { DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel; @@ -284,9 +278,9 @@ static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) DEBUG_DVC("id=%d", channel->channel_id); - if (dvcman_channel_list_remove(dvcman->channels, (struct dvcman_channel_list_item*)channel) == NULL) + if (list_remove(dvcman->channels, channel) == NULL) DEBUG_WARN("channel not found"); - dvcman_channel_list_item_free((struct dvcman_channel_list_item*)channel); + dvcman_channel_free(channel); return 1; } @@ -297,7 +291,6 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel int i; DVCMAN_LISTENER* listener; DVCMAN_CHANNEL* channel; - struct dvcman_channel_list_item* item; int bAccept; IWTSVirtualChannelCallback* pCallback; @@ -306,8 +299,7 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel listener = (DVCMAN_LISTENER*)dvcman->listeners[i]; if (strcmp(listener->channel_name, ChannelName) == 0) { - item = dvcman_channel_list_item_new(); - channel = (DVCMAN_CHANNEL*)item; + channel = xnew(DVCMAN_CHANNEL); channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; channel->dvcman = dvcman; @@ -321,13 +313,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel DEBUG_DVC("listener %s created new channel %d", listener->channel_name, channel->channel_id); channel->channel_callback = pCallback; - dvcman_channel_list_add(dvcman->channels, item); + list_add(dvcman->channels, channel); return 0; } else { DEBUG_WARN("channel rejected by plugin"); - dvcman_channel_list_item_free(item); + dvcman_channel_free(channel); return 1; } } @@ -338,13 +330,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel static DVCMAN_CHANNEL* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId) { DVCMAN* dvcman = (DVCMAN*)pChannelMgr; - struct dvcman_channel_list_item* curr; + LIST_ITEM* curr; - for (curr = dvcman->channels->head; curr; curr = dvcman_channel_list_item_next(curr)) + for (curr = dvcman->channels->head; curr; curr = curr->next) { - if (((DVCMAN_CHANNEL*)curr)->channel_id == ChannelId) + if (((DVCMAN_CHANNEL*)curr->data)->channel_id == ChannelId) { - return (DVCMAN_CHANNEL*)curr; + return (DVCMAN_CHANNEL*)curr->data; } } return NULL; diff --git a/cunit/test_list.c b/cunit/test_list.c index 74553eb0f..c5ef963f9 100644 --- a/cunit/test_list.c +++ b/cunit/test_list.c @@ -44,57 +44,51 @@ int add_list_suite(void) return 0; } -struct my_list_item +struct _my_list_item { uint32 a; uint32 b; }; - -DEFINE_LIST_TYPE(my_list, my_list_item); - -void my_list_item_free(struct my_list_item* item) -{ - item->a = 0; - item->b = 0; -} +typedef struct _my_list_item my_list_item; void test_list(void) { - struct my_list* list; - struct my_list_item* item; - struct my_list_item* item1; - struct my_list_item* item2; + LIST* list; + LIST_ITEM* list_item; + my_list_item* item; + my_list_item* item1; + my_list_item* item2; int i; - list = my_list_new(); + list = list_new(); for (i = 0; i < 10; i++) { - item = my_list_item_new(); + item = xnew(my_list_item); item->a = i; item->b = i * i; - my_list_enqueue(list, item); + list_enqueue(list, item); } - for (i = 0, item = list->head; item; i++, item = my_list_item_next(item)) + for (i = 0, list_item = list->head; list_item; i++, list_item = list_item->next) { - CU_ASSERT(item->a == i); - CU_ASSERT(item->b == i * i); + CU_ASSERT(((my_list_item*)list_item->data)->a == i); + CU_ASSERT(((my_list_item*)list_item->data)->b == i * i); /*printf("%d %d\n", item->a, item->b);*/ } - item1 = my_list_item_new(); - my_list_add(list, item1); - item2 = my_list_item_new(); - my_list_add(list, item2); + item1 = xnew(my_list_item); + list_add(list, item1); + item2 = xnew(my_list_item); + list_add(list, item2); - CU_ASSERT(my_list_remove(list, item1) == item1); - my_list_item_free(item1); + CU_ASSERT(list_remove(list, item1) == item1); xfree(item1); - CU_ASSERT(my_list_remove(list, item2) == item2); - CU_ASSERT(my_list_remove(list, item2) == NULL); - my_list_item_free(item2); + CU_ASSERT(list_remove(list, item2) == item2); + CU_ASSERT(list_remove(list, item2) == NULL); xfree(item2); - my_list_free(list); + while ((item = list_dequeue(list)) != NULL) + xfree(item); + list_free(list); } diff --git a/include/freerdp/utils/list.h b/include/freerdp/utils/list.h index cdc33666f..8116c0275 100644 --- a/include/freerdp/utils/list.h +++ b/include/freerdp/utils/list.h @@ -22,114 +22,27 @@ #include -#define DEFINE_LIST_TYPE(_list_type, _item_type) \ -\ -struct _item_type##_full \ -{ \ - struct _item_type item; \ - struct _item_type* prev; \ - struct _item_type* next; \ -}; \ -\ -static struct _item_type* _item_type##_new(void) \ -{ \ - struct _item_type* item; \ - item = (struct _item_type*)xnew(struct _item_type##_full);\ - return item; \ -} \ -\ -static void _item_type##_free(struct _item_type* item); \ -\ -static struct _item_type* _item_type##_next(struct _item_type* item) \ -{ \ - return ((struct _item_type##_full*)item)->next; \ -} \ -\ -static struct _item_type* _item_type##_prev(struct _item_type* item) \ -{ \ - return ((struct _item_type##_full*)item)->prev; \ -} \ -\ -struct _list_type \ -{ \ - struct _item_type* head; \ - struct _item_type* tail; \ -}; \ -\ -static struct _list_type* _list_type##_new(void) \ -{ \ - struct _list_type* list; \ - list = xnew(struct _list_type); \ - return list; \ -} \ -\ -static void _list_type##_enqueue(struct _list_type* list, struct _item_type* item) \ -{ \ - if (list->tail == NULL) \ - { \ - list->head = item; \ - list->tail = item; \ - } \ - else \ - { \ - ((struct _item_type##_full*)item)->prev = list->tail; \ - ((struct _item_type##_full*)(list->tail))->next = item; \ - list->tail = item; \ - } \ -} \ -\ -static struct _item_type* _list_type##_dequeue(struct _list_type* list) \ -{ \ - struct _item_type* item; \ - item = list->head; \ - if (item != NULL) \ - { \ - list->head = ((struct _item_type##_full*)item)->next; \ - ((struct _item_type##_full*)item)->next = NULL; \ - if (list->head == NULL) \ - list->tail = NULL; \ - else \ - ((struct _item_type##_full*)(list->head))->prev = NULL; \ - } \ - return item; \ -} \ -\ -static void _list_type##_add(struct _list_type* list, struct _item_type* item) \ -{ \ - _list_type##_enqueue(list, item); \ -} \ -\ -static struct _item_type* _list_type##_remove(struct _list_type* list, struct _item_type* item) \ -{ \ - struct _item_type* prev; \ - struct _item_type* curr; \ -\ - for (prev = NULL, curr = (struct _item_type*)list->head; curr; prev = curr, curr = ((struct _item_type##_full*)curr)->next) \ - { \ - if (curr == item) \ - { \ - if (prev) \ - ((struct _item_type##_full*)prev)->next = ((struct _item_type##_full*)curr)->next; \ - if (list->head == item) \ - list->head = ((struct _item_type##_full*)curr)->next; \ - if (list->tail == item) \ - list->tail = prev; \ - return item; \ - } \ - } \ - return NULL; \ -} \ -\ -void _list_type##_free(struct _list_type* list) \ -{ \ - struct _item_type* item; \ - while (list->head) \ - { \ - item = _list_type##_dequeue(list); \ - _item_type##_free(item); \ - xfree(item); \ - } \ - xfree(list); \ -} +typedef struct _LIST_ITEM LIST_ITEM; +struct _LIST_ITEM +{ + void* data; + LIST_ITEM* prev; + LIST_ITEM* next; +}; -#endif +typedef struct _LIST LIST; +struct _LIST +{ + int count; + LIST_ITEM* head; + LIST_ITEM* tail; +}; + +LIST* list_new(void); +void list_free(LIST* list); +void list_enqueue(LIST* list, void* data); +void* list_dequeue(LIST* list); +#define list_add(_l, _d) list_enqueue(_l, _d) +void* list_remove(LIST* list, void* data); + +#endif /* __LIST_UTILS_H */ diff --git a/libfreerdp-utils/CMakeLists.txt b/libfreerdp-utils/CMakeLists.txt index 23e5e6352..0a0b619e0 100644 --- a/libfreerdp-utils/CMakeLists.txt +++ b/libfreerdp-utils/CMakeLists.txt @@ -25,6 +25,7 @@ set(FREERDP_UTILS_SRCS blob.c event.c hexdump.c + list.c load_plugin.c memory.c mutex.c diff --git a/libfreerdp-utils/list.c b/libfreerdp-utils/list.c new file mode 100644 index 000000000..f5b1827bc --- /dev/null +++ b/libfreerdp-utils/list.c @@ -0,0 +1,120 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Double-linked List Utils + * + * Copyright 2011 Vic Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +static LIST_ITEM* list_item_new(void* data) +{ + LIST_ITEM* item; + + item = xnew(LIST_ITEM); + item->data = data; + return item; +} + +static LIST_ITEM* list_item_find(LIST* list, void* data) +{ + LIST_ITEM* item; + + for (item = list->head; item; item = item->next) + { + if (item->data == data) + return item; + } + return NULL; +} + +LIST* list_new(void) +{ + LIST* list; + + list = xnew(LIST); + return list; +} + +void list_free(LIST* list) +{ + while (list->head) + list_dequeue(list); + xfree(list); +} + +void list_enqueue(LIST* list, void* data) +{ + LIST_ITEM* item; + + item = list_item_new(data); + if (list->tail == NULL) + { + list->head = item; + list->tail = item; + } + else + { + item->prev = list->tail; + list->tail->next = item; + list->tail = item; + } +} + +void* list_dequeue(LIST* list) +{ + LIST_ITEM* item; + void* data = NULL; + + item = list->head; + if (item != NULL) + { + list->head = item->next; + if (list->head == NULL) + list->tail = NULL; + else + list->head->prev = NULL; + + data = item->data; + xfree(item); + } + return data; +} + +void* list_remove(LIST* list, void* data) +{ + LIST_ITEM* item; + + item = list_item_find(list, data); + if (item != NULL) + { + if (item->prev != NULL) + item->prev->next = item->next; + if (item->next != NULL) + item->next->prev = item->prev; + if (list->head == item) + list->head = item->next; + if (list->tail == item) + list->tail = item->prev; + xfree(item); + } + else + data = NULL; + return data; +} diff --git a/libfreerdp-utils/svc_plugin.c b/libfreerdp-utils/svc_plugin.c index 8569e58e4..4f5cd5bbd 100644 --- a/libfreerdp-utils/svc_plugin.c +++ b/libfreerdp-utils/svc_plugin.c @@ -48,15 +48,14 @@ static rdpSvcPluginList* g_svc_plugin_list = NULL; static freerdp_mutex g_mutex = NULL; /* Queue for receiving packets */ -struct svc_data_in_item +struct _svc_data_in_item { STREAM* data_in; FRDP_EVENT* event_in; }; +typedef struct _svc_data_in_item svc_data_in_item; -DEFINE_LIST_TYPE(svc_data_in_list, svc_data_in_item); - -void svc_data_in_item_free(struct svc_data_in_item* item) +static void svc_data_in_item_free(svc_data_in_item* item) { if (item->data_in) { @@ -68,6 +67,7 @@ void svc_data_in_item_free(struct svc_data_in_item* item) freerdp_event_free(item->event_in); item->event_in = NULL; } + xfree(item); } struct rdp_svc_plugin_private @@ -76,7 +76,7 @@ struct rdp_svc_plugin_private uint32 open_handle; STREAM* data_in; - struct svc_data_in_list* data_in_list; + LIST* data_in_list; freerdp_mutex* data_in_mutex; struct wait_obj* signals[5]; @@ -150,7 +150,7 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3 uint32 totalLength, uint32 dataFlags) { STREAM* data_in; - struct svc_data_in_item* item; + svc_data_in_item* item; if (dataFlags & CHANNEL_FLAG_FIRST) { @@ -173,11 +173,11 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3 plugin->priv->data_in = NULL; stream_set_pos(data_in, 0); - item = svc_data_in_item_new(); + item = xnew(svc_data_in_item); item->data_in = data_in; freerdp_mutex_lock(plugin->priv->data_in_mutex); - svc_data_in_list_enqueue(plugin->priv->data_in_list, item); + list_enqueue(plugin->priv->data_in_list, item); freerdp_mutex_unlock(plugin->priv->data_in_mutex); wait_obj_set(plugin->priv->signals[1]); @@ -186,13 +186,13 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3 static void svc_plugin_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event_in) { - struct svc_data_in_item* item; + svc_data_in_item* item; - item = svc_data_in_item_new(); + item = xnew(svc_data_in_item); item->event_in = event_in; freerdp_mutex_lock(plugin->priv->data_in_mutex); - svc_data_in_list_enqueue(plugin->priv->data_in_list, item); + list_enqueue(plugin->priv->data_in_list, item); freerdp_mutex_unlock(plugin->priv->data_in_mutex); wait_obj_set(plugin->priv->signals[1]); @@ -228,7 +228,7 @@ static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData, static void svc_plugin_process_data_in(rdpSvcPlugin* plugin) { - struct svc_data_in_item* item; + svc_data_in_item* item; while (1) { @@ -237,7 +237,7 @@ static void svc_plugin_process_data_in(rdpSvcPlugin* plugin) break; freerdp_mutex_lock(plugin->priv->data_in_mutex); - item = svc_data_in_list_dequeue(plugin->priv->data_in_list); + item = list_dequeue(plugin->priv->data_in_list); freerdp_mutex_unlock(plugin->priv->data_in_mutex); if (item != NULL) @@ -298,7 +298,7 @@ static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint return; } - plugin->priv->data_in_list = svc_data_in_list_new(); + plugin->priv->data_in_list = list_new(); plugin->priv->data_in_mutex = freerdp_mutex_new(); /* terminate signal */ @@ -313,6 +313,7 @@ static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) { + svc_data_in_item* item; struct timespec ts; int i; @@ -335,7 +336,10 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) plugin->priv->num_signals = 0; freerdp_mutex_free(plugin->priv->data_in_mutex); - svc_data_in_list_free(plugin->priv->data_in_list); + + while ((item = list_dequeue(plugin->priv->data_in_list)) != NULL) + svc_data_in_item_free(item); + list_free(plugin->priv->data_in_list); if (plugin->priv->data_in != NULL) {