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 <assert.h> 25 26 #include <avahi-common/strlst.h> 27 #include "avahi-common/avahi-malloc.h" 28 #include <avahi-common/domain.h> 29 30 #include "howl.h" 31 #include "warn.h" 32 33 struct _sw_text_record { 34 AvahiStringList *strlst; 35 uint8_t *buffer; 36 size_t buffer_size; 37 int buffer_valid; 38 }; 39 40 #ifndef HAVE_STRLCPY 41 42 static size_t strlcpy(char *dest, const char *src, size_t n) { 43 assert(dest); 44 assert(src); 45 46 if (n > 0) { 47 strncpy(dest, src, n-1); 48 dest[n-1] = 0; 49 } 50 51 return strlen(src); 52 } 53 54 #endif 55 56 sw_result sw_text_record_init(sw_text_record *self) { 57 assert(self); 58 59 AVAHI_WARN_LINKAGE; 60 61 if (!(*self = avahi_new(struct _sw_text_record, 1))) { 62 *self = NULL; 63 return SW_E_UNKNOWN; 64 } 65 66 (*self)->strlst = NULL; 67 (*self)->buffer = NULL; 68 (*self)->buffer_size = 0; 69 (*self)->buffer_valid = 0; 70 71 return SW_OKAY; 72 } 73 74 sw_result sw_text_record_fina(sw_text_record self) { 75 assert(self); 76 77 AVAHI_WARN_LINKAGE; 78 79 avahi_string_list_free(self->strlst); 80 avahi_free(self->buffer); 81 avahi_free(self); 82 return SW_OKAY; 83 } 84 85 sw_result sw_text_record_add_string( 86 sw_text_record self, 87 sw_const_string string) { 88 89 AvahiStringList *n; 90 91 assert(self); 92 assert(string); 93 94 AVAHI_WARN_LINKAGE; 95 96 if (!(n = avahi_string_list_add(self->strlst, string))) 97 return SW_E_UNKNOWN; 98 99 self->strlst = n; 100 self->buffer_valid = 0; 101 return SW_OKAY; 102 } 103 104 sw_result sw_text_record_add_key_and_string_value( 105 sw_text_record self, 106 sw_const_string key, 107 sw_const_string val) { 108 109 AvahiStringList *n; 110 111 assert(self); 112 assert(key); 113 114 AVAHI_WARN_LINKAGE; 115 116 if (!(n = avahi_string_list_add_pair(self->strlst, key, val))) 117 return SW_E_UNKNOWN; 118 119 self->strlst = n; 120 self->buffer_valid = 0; 121 return SW_OKAY; 122 } 123 124 sw_result sw_text_record_add_key_and_binary_value( 125 sw_text_record self, 126 sw_const_string key, 127 sw_octets val, 128 sw_uint32 len) { 129 130 AvahiStringList *n; 131 132 assert(self); 133 assert(key); 134 assert(len || !val); 135 136 AVAHI_WARN_LINKAGE; 137 138 if (!(n = avahi_string_list_add_pair_arbitrary(self->strlst, key, val, len))) 139 return SW_E_UNKNOWN; 140 141 self->strlst = n; 142 self->buffer_valid = 0; 143 return SW_OKAY; 144 } 145 146 static int rebuild(sw_text_record self) { 147 assert(self); 148 149 if (self->buffer_valid) 150 return 0; 151 152 self->buffer_size = avahi_string_list_serialize(self->strlst, NULL, 0); 153 154 if (!(self->buffer = avahi_realloc(self->buffer, self->buffer_size + 1))) 155 return -1; 156 157 avahi_string_list_serialize(self->strlst, self->buffer, self->buffer_size); 158 self->buffer_valid = 1; 159 160 return 0; 161 } 162 163 sw_octets sw_text_record_bytes(sw_text_record self) { 164 assert(self); 165 166 AVAHI_WARN_LINKAGE; 167 168 if (rebuild(self) < 0) 169 return NULL; 170 171 return self->buffer; 172 } 173 174 sw_uint32 sw_text_record_len(sw_text_record self) { 175 assert(self); 176 177 AVAHI_WARN_LINKAGE; 178 179 if (rebuild(self) < 0) 180 return (uint32_t) -1; 181 182 return self->buffer_size; 183 } 184 185 struct _sw_text_record_iterator { 186 AvahiStringList *strlst, *index; 187 188 }; 189 190 sw_result sw_text_record_iterator_init( 191 sw_text_record_iterator * self, 192 sw_octets text_record, 193 sw_uint32 text_record_len) { 194 195 AvahiStringList *txt; 196 assert(self); 197 198 AVAHI_WARN_LINKAGE; 199 200 if (!(*self = avahi_new(struct _sw_text_record_iterator, 1))) { 201 *self = NULL; 202 return SW_E_UNKNOWN; 203 } 204 205 if (avahi_string_list_parse(text_record, text_record_len, &txt) < 0) { 206 avahi_free(*self); 207 *self = NULL; 208 return SW_E_UNKNOWN; 209 } 210 211 (*self)->index = (*self)->strlst = avahi_string_list_reverse(txt); 212 213 return SW_OKAY; 214 } 215 216 sw_result sw_text_record_iterator_fina(sw_text_record_iterator self) { 217 assert(self); 218 219 AVAHI_WARN_LINKAGE; 220 221 avahi_string_list_free(self->strlst); 222 avahi_free(self); 223 224 return SW_OKAY; 225 } 226 227 sw_result sw_text_record_iterator_next( 228 sw_text_record_iterator self, 229 char key[SW_TEXT_RECORD_MAX_LEN], 230 sw_uint8 val[SW_TEXT_RECORD_MAX_LEN], 231 sw_uint32 * val_len) { 232 233 char *mkey = NULL, *mvalue = NULL; 234 size_t msize = 0; 235 236 assert(self); 237 assert(key); 238 239 AVAHI_WARN_LINKAGE; 240 241 if (!self->index) 242 return SW_E_UNKNOWN; 243 244 if (avahi_string_list_get_pair(self->index, &mkey, &mvalue, &msize) < 0) 245 return SW_E_UNKNOWN; 246 247 strlcpy(key, mkey, SW_TEXT_RECORD_MAX_LEN); 248 memset(val, 0, SW_TEXT_RECORD_MAX_LEN); 249 memcpy(val, mvalue, msize); 250 *val_len = msize; 251 252 avahi_free(mkey); 253 avahi_free(mvalue); 254 255 self->index = self->index->next; 256 257 return SW_OKAY; 258 } 259 260