Initial support for the generic ares_free_data() function that will allow

applications to free memory allocated and returned by some c-ares funtions.
This commit is contained in:
Yang Tse 2009-11-20 08:50:03 +00:00
parent 5129442ee7
commit 5a0a473c30
4 changed files with 216 additions and 6 deletions

View File

@ -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 \

View File

@ -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

142
ares/ares_data.c Normal file
View File

@ -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;
}

62
ares/ares_data.h Normal file
View File

@ -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);