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