summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Tse <yangsita@gmail.com>2009-11-20 08:50:03 +0000
committerYang Tse <yangsita@gmail.com>2009-11-20 08:50:03 +0000
commit2a916ce6e550ba82a413fca9d2e296140c4ac73c (patch)
tree3bed0497a0769fe38c6a50c3c0f8261acc0de012
parent10461d141401e9ffcdce63efaf03541c66edc210 (diff)
downloadc-ares-2a916ce6e550ba82a413fca9d2e296140c4ac73c.tar.gz
c-ares-2a916ce6e550ba82a413fca9d2e296140c4ac73c.tar.bz2
c-ares-2a916ce6e550ba82a413fca9d2e296140c4ac73c.zip
Initial support for the generic ares_free_data() function that will allow
applications to free memory allocated and returned by some c-ares funtions.
-rw-r--r--Makefile.inc2
-rw-r--r--ares.h16
-rw-r--r--ares_data.c142
-rw-r--r--ares_data.h62
4 files changed, 216 insertions, 6 deletions
diff --git a/Makefile.inc b/Makefile.inc
index 8d99afd..bf24934 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -4,6 +4,7 @@ CSOURCES = ares__close_sockets.c \
ares__read_line.c \
ares__timeval.c \
ares_cancel.c \
+ ares_data.c \
ares_destroy.c \
ares_expand_name.c \
ares_expand_string.c \
@@ -41,6 +42,7 @@ CSOURCES = ares__close_sockets.c \
HHEADERS = ares.h \
ares_build.h \
+ ares_data.h \
ares_dns.h \
ares_ipv6.h \
ares_library_init.h \
diff --git a/ares.h b/ares.h
index 63eb681..d2b6cec 100644
--- a/ares.h
+++ b/ares.h
@@ -430,15 +430,17 @@ struct addr6ttl {
};
struct ares_srv_reply {
- unsigned short weight;
- unsigned short priority;
- unsigned short port;
- char *host;
+ struct ares_srv_reply *next;
+ char *host;
+ unsigned short priority;
+ unsigned short weight;
+ unsigned short port;
};
struct ares_txt_reply {
- size_t length; /* length excludes null termination */
- unsigned char *txt;
+ struct ares_txt_reply *next;
+ unsigned char *txt;
+ size_t length; /* length excludes null termination */
};
/*
@@ -486,6 +488,8 @@ CARES_EXTERN void ares_free_string(void *str);
CARES_EXTERN void ares_free_hostent(struct hostent *host);
+CARES_EXTERN void ares_free_data(void *dataptr);
+
CARES_EXTERN const char *ares_strerror(int code);
#ifdef __cplusplus
diff --git a/ares_data.c b/ares_data.c
new file mode 100644
index 0000000..5d710ee
--- /dev/null
+++ b/ares_data.c
@@ -0,0 +1,142 @@
+/* $Id$ */
+
+/* Copyright (C) 2009 by Daniel Stenberg
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+
+#include "ares_setup.h"
+
+#include <stddef.h>
+
+#include "ares.h"
+#include "ares_data.h"
+#include "ares_private.h"
+
+
+/*
+** ares_free_data() - c-ares external API function.
+**
+** This function must be used by the application to free data memory that
+** has been internally allocated by some c-ares function and for which a
+** pointer has already been returned to the calling application. The list
+** of c-ares functions returning pointers that must be free'ed using this
+** function is:
+**
+** FIXME: specify function list.
+*/
+
+void ares_free_data(void *dataptr)
+{
+ struct ares_data *ptr;
+
+ if (!dataptr)
+ return;
+
+ ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data));
+
+ if (ptr->mark != ARES_DATATYPE_MARK)
+ return;
+
+ switch (ptr->type)
+ {
+ case ARES_DATATYPE_SRV_REPLY:
+
+ if (ptr->data.srv_reply.next)
+ ares_free_data(ptr->data.srv_reply.next);
+ if (ptr->data.srv_reply.host)
+ free(ptr->data.srv_reply.host);
+ break;
+
+ case ARES_DATATYPE_TXT_REPLY:
+
+ if (ptr->data.txt_reply.next)
+ ares_free_data(ptr->data.txt_reply.next);
+ if (ptr->data.txt_reply.txt)
+ free(ptr->data.txt_reply.txt);
+ break;
+
+ default:
+ return;
+ }
+
+ free(ptr);
+}
+
+
+/*
+** ares_malloc_data() - c-ares internal helper function.
+**
+** This function allocates memory for a c-ares private ares_data struct
+** for the specified ares_datatype, initializes c-ares private fields
+** and zero initializes those which later might be used from the public
+** API. It returns an interior pointer which can be passed by c-ares
+** functions to the calling application, and that must be free'ed using
+** c-ares external API function ares_free_data().
+*/
+
+void *ares_malloc_data(ares_datatype type)
+{
+ struct ares_data *ptr;
+
+ ptr = malloc(sizeof(struct ares_data));
+ if (!ptr)
+ return NULL;
+
+ switch (type)
+ {
+ case ARES_DATATYPE_SRV_REPLY:
+ ptr->data.srv_reply.next = NULL;
+ ptr->data.srv_reply.host = NULL;
+ ptr->data.srv_reply.priority = 0;
+ ptr->data.srv_reply.weight = 0;
+ ptr->data.srv_reply.port = 0;
+ break;
+
+ case ARES_DATATYPE_TXT_REPLY:
+ ptr->data.txt_reply.next = NULL;
+ ptr->data.txt_reply.txt = NULL;
+ ptr->data.txt_reply.length = 0;
+ break;
+
+ default:
+ free(ptr);
+ return NULL;
+ }
+
+ ptr->mark = ARES_DATATYPE_MARK;
+ ptr->type = type;
+
+ return &ptr->data;
+}
+
+
+/*
+** ares_get_datatype() - c-ares internal helper function.
+**
+** This function returns the ares_datatype of the data stored in a
+** private ares_data struct when given the public API pointer.
+*/
+
+ares_datatype ares_get_datatype(void * dataptr)
+{
+ struct ares_data *ptr;
+
+ ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data));
+
+ if (ptr->mark == ARES_DATATYPE_MARK)
+ return ptr->type;
+
+ return ARES_DATATYPE_UNKNOWN;
+}
diff --git a/ares_data.h b/ares_data.h
new file mode 100644
index 0000000..ffe2aeb
--- /dev/null
+++ b/ares_data.h
@@ -0,0 +1,62 @@
+/* $Id$ */
+
+/* Copyright (C) 2009 by Daniel Stenberg
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+typedef enum {
+ ARES_DATATYPE_UNKNOWN = 1, /* unknown data type */
+#if 0
+ ARES_DATATYPE_ADDR6TTL, /* struct ares_addrttl */
+ ARES_DATATYPE_ADDRTTL, /* struct ares_addr6ttl */
+ ARES_DATATYPE_HOSTENT, /* struct hostent */
+ ARES_DATATYPE_OPTIONS, /* struct ares_options */
+#endif
+ ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply */
+ ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply */
+ ARES_DATATYPE_LAST /* not used */
+} ares_datatype;
+
+#define ARES_DATATYPE_MARK 0xbead
+
+/*
+ * ares_data struct definition is internal to c-ares and shall not
+ * be exposed by the public API in order to allow future changes
+ * and extensions to it without breaking ABI. This will be used
+ * internally by c-ares as the container of multiple types of data
+ * dynamically allocated for which a reference will be returned
+ * to the calling application.
+ *
+ * c-ares API functions returning a pointer to c-ares internally
+ * allocated data will actually be returning an interior pointer
+ * into this ares_data struct.
+ *
+ * All this is 'invisible' to the calling application, the only
+ * requirement is that this kind of data must be free'ed by the
+ * calling application using ares_free_data() with the pointer
+ * it has received from a previous c-ares function call.
+ */
+
+struct ares_data {
+ ares_datatype type; /* Actual data type identifier. */
+ unsigned int mark; /* Private ares_data signature. */
+ union {
+ struct ares_txt_reply txt_reply;
+ struct ares_srv_reply srv_reply;
+ } data;
+};
+
+void *ares_malloc_data(ares_datatype type);
+
+ares_datatype ares_get_datatype(void * dataptr);