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