From e61d4b9e21578a5b77118030a6711bbbb9abd7de Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 3 Dec 2008 09:59:50 +0000 Subject: [PATCH] Introduce ares_dup(3) and new thoughts about API/ABI and how to move forwards. Also discussed on the ml. --- CHANGES | 34 ++++++++++++++++++++++++++++++++++ Makefile.inc | 2 +- ares.h | 26 ++++++++++++++++++++++++-- ares_dup.3 | 43 +++++++++++++++++++++++++++++++++++++++++++ ares_init.3 | 3 ++- ares_init.c | 33 +++++++++++++++++++++++++++++++++ ares_save_options.3 | 17 +++++++++++------ 7 files changed, 148 insertions(+), 10 deletions(-) create mode 100644 ares_dup.3 diff --git a/CHANGES b/CHANGES index fcc41f04..6f96bf91 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,39 @@ Changelog for the c-ares project +* Dec 3 2008 (Daniel Stenberg) + + API changes: + + I made sure the public ares_config struct looks like before and yet it + supports the ROTATE option thanks to c-ares now storing the "optmask" + internally. Thus we should be ABI compatible with the past release(s) + now. My efforts mentioned below should not break backwards ABI compliance. + + Here's how I suggest we proceed with the API: + + ares_init() will be primary "channel creator" function. + + ares_init_options() will continue to work exactly like now and before. For + starters, it will be the (only) way to set the existing options. + + ares_save_options() will continue to work like today, but will ONLY save + options that you can set today (including ARES_OPT_ROTATE actually) but new + options that we add may not be saved with this. + + Instead we introduce: + + ares_dup() that instead can make a new channel and clone the config used + from an existing channel. It will then clone all config options, including + future new things we add. + + ares_set_*() style functions that set (new) config options. As a start we + simply add these for new functionality, but over time we can also introduce + them for existing "struct ares_options" so that we can eventually deprecate + the two ares_*_options() functions. + + ares_get_*() style functions for extracting info from a channel handle that + should be used instead of ares_save_options(). + * Nov 26 2008 (Yang Tse) - Brad Spencer provided changes to allow buildconf to work on OS X. diff --git a/Makefile.inc b/Makefile.inc index bdadd334..3f970b86 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -18,5 +18,5 @@ MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3 \ ares_parse_a_reply.3 ares_parse_ptr_reply.3 ares_process.3 \ ares_query.3 ares_search.3 ares_send.3 ares_strerror.3 ares_timeout.3 \ ares_version.3 ares_cancel.3 ares_parse_aaaa_reply.3 ares_getnameinfo.3 \ - ares_getsock.3 ares_parse_ns_reply.3 \ + ares_getsock.3 ares_parse_ns_reply.3 ares_dup.3 \ ares_destroy_options.3 ares_save_options.3 ares_gethostbyname_file.3 diff --git a/ares.h b/ares.h index 0f162e2a..e4dc7e3d 100644 --- a/ares.h +++ b/ares.h @@ -1,7 +1,7 @@ /* $Id$ */ /* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright (C) 2007 by Daniel Stenberg + * Copyright (C) 2007-2008 by Daniel Stenberg * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without @@ -180,6 +180,26 @@ typedef void (*ares_sock_state_cb)(void *data, struct apattern; +/* NOTE about the ares_options struct to users and developers. + + This struct will remain looking like this. It will not be extended nor + shrunk in future releases, but all new options will be set by ares_set_*() + options instead of with the ares_init_options() function. + + Eventually (in a galaxy far far away), all options will be settable by + ares_set_*() options and the ares_init_options() function will become + deprecated. + + ares_save_options() is considered deprecated as of right now. Use ares_dup() + instead! + + So, if new options are added they are not added to this struct. And they + are not "saved" with the ares_save_options() function but instead we + encourage the use of the ares_dup() function. Needless to say, if you add + config options to c-ares you need to make sure ares_dup() duplicates this + new option. + + */ struct ares_options { int flags; int timeout; /* in seconds or milliseconds, depending on options */ @@ -215,8 +235,10 @@ typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts, int ares_init(ares_channel *channelptr); int ares_init_options(ares_channel *channelptr, struct ares_options *options, int optmask); -int ares_save_options(ares_channel channel, struct ares_options *options, int *optmask); +int ares_save_options(ares_channel channel, struct ares_options *options, + int *optmask); void ares_destroy_options(struct ares_options *options); +int ares_dup(ares_channel *dest, ares_channel src); void ares_destroy(ares_channel channel); void ares_cancel(ares_channel channel); void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, diff --git a/ares_dup.3 b/ares_dup.3 new file mode 100644 index 00000000..cdf5a42e --- /dev/null +++ b/ares_dup.3 @@ -0,0 +1,43 @@ +.\" $Id$ +.\" +.\" Copyright (C) 2007-2008 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. +.\" +.TH ARES_DUP 3 "2 Dec 2008" +.SH NAME +ares_dup \- Duplicate a resolver channel +.SH SYNOPSIS +.nf +.B #include +.PP +.B int ares_dup(ares_channel *\fIchannel\fP, ares_channel \fIsource\fP) +.fi +.SH DESCRIPTION +The \fBares_dup(3)\fP function duplicates an existing communications channel +for name service lookups. If it returns successfully, \fBares_dup(3)\fP will +set the variable pointed to by \fIchannel\fP to a handle used to identify the +name service channel. The caller should invoke \fIares_destroy(3)\fP on the +handle when the channel is no longer needed. + +The \fBares_dup_options\fP function also initializes a name service channel, +with additional options set exactly as the \fIsource\fP channel has them +configured. +.SH SEE ALSO +.BR ares_destroy(3), +.BR ares_init(3) +.SH AVAILABILITY +ares_dup(3) was added in c-ares 1.6.0 +.SH AUTHOR +Daniel Stenberg + diff --git a/ares_init.3 b/ares_init.3 index 05fa5981..f7a7b4a2 100644 --- a/ares_init.3 +++ b/ares_init.3 @@ -185,7 +185,8 @@ A configuration file could not be read. .B ARES_ENOMEM The process's available memory was exhausted. .SH SEE ALSO -.BR ares_destroy (3) +.BR ares_destroy(3), +.BR ares_dup(3) .SH AUTHOR Greg Hudson, MIT Information Systems .br diff --git a/ares_init.c b/ares_init.c index 79a9f0f5..faa41581 100644 --- a/ares_init.c +++ b/ares_init.c @@ -257,6 +257,39 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options, return ARES_SUCCESS; } +/* ares_dup() duplicates a channel handle with all its options and returns a + new channel handle */ +int ares_dup(ares_channel *dest, ares_channel src) +{ + struct ares_options opts; + int rc; + int optmask; + + *dest = NULL; /* in case of failure return NULL explicitly */ + + /* First get the options supported by the old ares_save_options() function, + which is most of them */ + rc = ares_save_options(src, &opts, &optmask); + if(rc) + return rc; + + /* Then create the new channel with those options */ + rc = ares_init_options(dest, &opts, optmask); + + /* destroy the options copy to not leak any memory */ + ares_destroy_options(&opts); + + if(rc) + return rc; + + /* Now clone the options that ares_save_options() doesn't support. */ + + /* No such options available yet */ + + return ARES_SUCCESS; /* everything went fine */ + +} + /* Save options from initialized channel */ int ares_save_options(ares_channel channel, struct ares_options *options, int *optmask) diff --git a/ares_save_options.3 b/ares_save_options.3 index 46fd5967..79f9db9a 100644 --- a/ares_save_options.3 +++ b/ares_save_options.3 @@ -24,9 +24,7 @@ ares_save_options \- Save configuration values obtained from initialized ares_ch .B void ares_save_options(ares_channel \fIchannel\fP, struct ares_options *\fIoptions\fP, int *\fIoptmask\fP) .fi .SH DESCRIPTION -The -.B ares_save_options -function saves the channel data identified by +The \fBares_save_options(3)\fP function saves the channel data identified by .IR channel , into the options struct identified by .IR options , @@ -38,11 +36,18 @@ The resultant options and optmask are then able to be passed directly to ares_init_options. When the options are no longer needed, ares_destroy_options should be called to free any associated memory. - - +.SH NOTE +Since c-ares 1.6.0 the ares_options struct has been "locked" meaning that it +won't be extended to cover new funtions. This function will remain +functioning, but it can only return config data that can be represented in +this config struct, which may no longer be the complete set of config +options. \fBares_dup(3)\fP will not have that restriction. .SH SEE ALSO .BR ares_destroy_options (3), -.BR ares_init_options (3) +.BR ares_init_options (3), +.BR ares_dup (3) +.SH AVAILABILITY +ares_save_options(3) was added in c-ares 1.4.0 .SH AUTHOR Brad House .br