1/*** 2 This file is part of avahi. 3 4 avahi is free software; you can redistribute it and/or modify it 5 under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 2.1 of the 7 License, or (at your option) any later version. 8 9 avahi is distributed in the hope that it will be useful, but WITHOUT 10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 12 Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with avahi; if not, write to the Free Software 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 17 USA. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <stdlib.h> 25#include <assert.h> 26 27#include <avahi-common/llist.h> 28#include <avahi-common/malloc.h> 29 30#include "rrlist.h" 31#include "log.h" 32 33typedef struct AvahiRecordListItem AvahiRecordListItem; 34 35struct AvahiRecordListItem { 36 int read; 37 AvahiRecord *record; 38 int unicast_response; 39 int flush_cache; 40 int auxiliary; 41 AVAHI_LLIST_FIELDS(AvahiRecordListItem, items); 42}; 43 44struct AvahiRecordList { 45 AVAHI_LLIST_HEAD(AvahiRecordListItem, read); 46 AVAHI_LLIST_HEAD(AvahiRecordListItem, unread); 47 48 int all_flush_cache; 49}; 50 51AvahiRecordList *avahi_record_list_new(void) { 52 AvahiRecordList *l; 53 54 if (!(l = avahi_new(AvahiRecordList, 1))) { 55 avahi_log_error("avahi_new() failed."); 56 return NULL; 57 } 58 59 AVAHI_LLIST_HEAD_INIT(AvahiRecordListItem, l->read); 60 AVAHI_LLIST_HEAD_INIT(AvahiRecordListItem, l->unread); 61 62 l->all_flush_cache = 1; 63 return l; 64} 65 66void avahi_record_list_free(AvahiRecordList *l) { 67 assert(l); 68 69 avahi_record_list_flush(l); 70 avahi_free(l); 71} 72 73static void item_free(AvahiRecordList *l, AvahiRecordListItem *i) { 74 assert(l); 75 assert(i); 76 77 if (i->read) 78 AVAHI_LLIST_REMOVE(AvahiRecordListItem, items, l->read, i); 79 else 80 AVAHI_LLIST_REMOVE(AvahiRecordListItem, items, l->unread, i); 81 82 avahi_record_unref(i->record); 83 avahi_free(i); 84} 85 86void avahi_record_list_flush(AvahiRecordList *l) { 87 assert(l); 88 89 while (l->read) 90 item_free(l, l->read); 91 while (l->unread) 92 item_free(l, l->unread); 93 94 l->all_flush_cache = 1; 95} 96 97AvahiRecord* avahi_record_list_next(AvahiRecordList *l, int *ret_flush_cache, int *ret_unicast_response, int *ret_auxiliary) { 98 AvahiRecord *r; 99 AvahiRecordListItem *i; 100 101 if (!(i = l->unread)) 102 return NULL; 103 104 assert(!i->read); 105 106 r = avahi_record_ref(i->record); 107 if (ret_unicast_response) 108 *ret_unicast_response = i->unicast_response; 109 if (ret_flush_cache) 110 *ret_flush_cache = i->flush_cache; 111 if (ret_auxiliary) 112 *ret_auxiliary = i->auxiliary; 113 114 AVAHI_LLIST_REMOVE(AvahiRecordListItem, items, l->unread, i); 115 AVAHI_LLIST_PREPEND(AvahiRecordListItem, items, l->read, i); 116 117 i->read = 1; 118 119 return r; 120} 121 122static AvahiRecordListItem *get(AvahiRecordList *l, AvahiRecord *r) { 123 AvahiRecordListItem *i; 124 125 assert(l); 126 assert(r); 127 128 for (i = l->read; i; i = i->items_next) 129 if (avahi_record_equal_no_ttl(i->record, r)) 130 return i; 131 132 for (i = l->unread; i; i = i->items_next) 133 if (avahi_record_equal_no_ttl(i->record, r)) 134 return i; 135 136 return NULL; 137} 138 139void avahi_record_list_push(AvahiRecordList *l, AvahiRecord *r, int flush_cache, int unicast_response, int auxiliary) { 140 AvahiRecordListItem *i; 141 142 assert(l); 143 assert(r); 144 145 if (get(l, r)) 146 return; 147 148 if (!(i = avahi_new(AvahiRecordListItem, 1))) { 149 avahi_log_error("avahi_new() failed."); 150 return; 151 } 152 153 i->unicast_response = unicast_response; 154 i->flush_cache = flush_cache; 155 i->auxiliary = auxiliary; 156 i->record = avahi_record_ref(r); 157 i->read = 0; 158 159 l->all_flush_cache = l->all_flush_cache && flush_cache; 160 161 AVAHI_LLIST_PREPEND(AvahiRecordListItem, items, l->unread, i); 162} 163 164void avahi_record_list_drop(AvahiRecordList *l, AvahiRecord *r) { 165 AvahiRecordListItem *i; 166 167 assert(l); 168 assert(r); 169 170 if (!(i = get(l, r))) 171 return; 172 173 item_free(l, i); 174} 175 176int avahi_record_list_is_empty(AvahiRecordList *l) { 177 assert(l); 178 179 return !l->unread && !l->read; 180} 181 182int avahi_record_list_all_flush_cache(AvahiRecordList *l) { 183 assert(l); 184 185 /* Return TRUE if all entries in this list have flush_cache set */ 186 187 return l->all_flush_cache; 188} 189