resolve: update sd-resolve to match the other APIs in style and functionality

This commit is contained in:
Lennart Poettering 2014-01-27 20:12:14 +01:00
parent ff975efb2e
commit 968d3d242c
6 changed files with 717 additions and 594 deletions

7
TODO
View File

@ -44,13 +44,6 @@ Features:
and passes this back to PID1 via SCM_RIGHTS. This also could be used
to allow Chown/chgrp on sockets without requiring NSS in PID 1.
* sd-resolve:
- make sure event loop integration works similar to event loop integration in other libs
- maybe drop _free() call, introduce _unref() instead
- maybe simplify function calls that take a sd_resolve_query object, to not also require the matching sd_resolve?
- maybe drop the "n_proc" parameter to sd_resolve_new()?
- change all functions to return "int" and negative errno errors
* New service property: maximum CPU and wallclock runtime for a service
* introduce bus call FreezeUnit(s, b), as well as "systemctl freeze

View File

@ -23,7 +23,7 @@
#include "util.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_resolve*, sd_resolve_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_resolve*, sd_resolve_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct addrinfo*, sd_resolve_freeaddrinfo);
#define _cleanup_resolve_free_ _cleanup_(sd_resolve_freep)
#define _cleanup_resolve_unref_ _cleanup_(sd_resolve_unrefp)
#define _cleanup_resolve_addrinfo_free_ _cleanup_(sd_resolve_freeaddrinfop)

File diff suppressed because it is too large Load Diff

View File

@ -36,55 +36,56 @@
#include "macro.h"
int main(int argc, char *argv[]) {
int r = 1, ret;
_cleanup_resolve_free_ sd_resolve *resolve = NULL;
int r = 1;
_cleanup_resolve_unref_ sd_resolve *resolve = NULL;
_cleanup_resolve_addrinfo_free_ struct addrinfo *ai = NULL;
_cleanup_free_ unsigned char *srv = NULL;
sd_resolve_query *q1, *q2, *q3;
sd_resolve_query *q1 = NULL, *q2 = NULL, *q3 = NULL;
struct addrinfo hints = {};
struct sockaddr_in sa = {};
char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
_cleanup_free_ char *host = NULL, *serv = NULL;
signal(SIGCHLD, SIG_IGN);
resolve = sd_resolve_new(2);
if (!resolve)
log_oom();
assert_se(sd_resolve_new(&resolve) >= 0);
/* Make a name -> address query */
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
q1 = sd_resolve_getaddrinfo(resolve, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints);
if (!q1)
fprintf(stderr, "sd_resolve_getaddrinfo(): %s\n", strerror(errno));
r = sd_resolve_getaddrinfo(resolve, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints, &q1);
if (r < 0)
log_error("sd_resolve_getaddrinfo(): %s\n", strerror(-r));
/* Make an address -> name query */
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71");
sa.sin_port = htons(80);
q2 = sd_resolve_getnameinfo(resolve, (struct sockaddr*) &sa, sizeof(sa), 0, 1, 1);
if (!q2)
fprintf(stderr, "sd_resolve_getnameinfo(): %s\n", strerror(errno));
r = sd_resolve_getnameinfo(resolve, (struct sockaddr*) &sa, sizeof(sa), 0, true, true, &q2);
if (r < 0)
log_error("sd_resolve_getnameinfo(): %s\n", strerror(-r));
/* Make a res_query() call */
q3 = sd_resolve_res_query(resolve, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV);
if (!q3)
fprintf(stderr, "sd_resolve_res_query(): %s\n", strerror(errno));
r = sd_resolve_res_query(resolve, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV, &q3);
if (r < 0)
log_error("sd_resolve_res_query(): %s\n", strerror(-r));
/* Wait until the three queries are completed */
while (!sd_resolve_isdone(resolve, q1) ||
!sd_resolve_isdone(resolve, q2) ||
!sd_resolve_isdone(resolve, q3)) {
if (sd_resolve_wait(resolve, 1) < 0)
fprintf(stderr, "sd_resolve_wait(): %s\n", strerror(errno));
while (sd_resolve_is_done(q1) == 0 ||
sd_resolve_is_done(q2) == 0 ||
sd_resolve_is_done(q3) == 0) {
r = sd_resolve_wait(resolve, (uint64_t) -1);
if (r < 0) {
log_error("sd_resolve_wait(): %s\n", strerror(-r));
assert_not_reached("sd_resolve_wait() failed");
}
}
/* Interpret the result of the name -> addr query */
ret = sd_resolve_getaddrinfo_done(resolve, q1, &ai);
if (ret)
fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
r = sd_resolve_getaddrinfo_done(q1, &ai);
if (r != 0)
log_error("error: %s %i\n", gai_strerror(r), r);
else {
struct addrinfo *i;
@ -99,27 +100,29 @@ int main(int argc, char *argv[]) {
printf("%s\n", p);
}
printf("canonical name: %s\n", strna(ai->ai_canonname));
}
/* Interpret the result of the addr -> name query */
ret = sd_resolve_getnameinfo_done(resolve, q2, host, sizeof(host), serv, sizeof(serv));
if (ret)
fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
r = sd_resolve_getnameinfo_done(q2, &host, &serv);
if (r)
log_error("error: %s %i\n", gai_strerror(r), r);
else
printf("%s -- %s\n", host, serv);
/* Interpret the result of the SRV lookup */
ret = sd_resolve_res_done(resolve, q3, &srv);
if (ret < 0) {
fprintf(stderr, "error: %s %i\n", strerror(errno), ret);
} else if (ret == 0) {
fprintf(stderr, "No reply for SRV lookup\n");
} else {
r = sd_resolve_res_done(q3, &srv);
if (r < 0)
log_error("error: %s %i\n", strerror(-r), r);
else if (r == 0)
log_error("No reply for SRV lookup\n");
else {
int qdcount;
int ancount;
int len;
const unsigned char *pos = srv + sizeof(HEADER);
unsigned char *end = srv + ret;
unsigned char *end = srv + r;
HEADER *head = (HEADER *)srv;
char name[256];

View File

@ -3869,13 +3869,16 @@ int pipe_eof(int fd) {
}
int fd_wait_for_event(int fd, int event, usec_t t) {
int r;
struct pollfd pollfd = {
.fd = fd,
.events = event,
};
r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
struct timespec ts;
int r;
r = ppoll(&pollfd, 1, t == (usec_t) -1 ? NULL : timespec_store(&ts, t), NULL);
if (r < 0)
return -errno;

View File

@ -6,7 +6,7 @@
/***
This file is part of systemd.
Copyright 2005-2008 Lennart Poettering
Copyright 2005-2014 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@ -25,56 +25,50 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
/** \mainpage
*
* \section moo Method of operation
*
* To use sd-resolve allocate an sd_resolve object with
* sd_resolve_new(). This will spawn a number of worker threads (or processes, depending on what is available) which
* are subsequently used to process the queries the controlling
* program issues via sd_resolve_getaddrinfo() and
* sd_resolve_getnameinfo(). Use sd_resolve_free() to shut down the worker
* threads/processes.
*
* Since sd-resolve may fork off new processes you have to make sure that
* your program is not irritated by spurious SIGCHLD signals.
*/
/** An opaque sd-resolve session structure */
typedef struct sd_resolve sd_resolve;
/** An opaque sd-resolve query structure */
typedef struct sd_resolve_query sd_resolve_query;
/** Allocate a new sd-resolve session with n_proc worker processes/threads */
sd_resolve* sd_resolve_new(unsigned n_proc);
/** Allocate a new sd-resolve session */
int sd_resolve_new(sd_resolve **ret);
/** Free a sd-resolve session. This destroys all attached
* sd_resolve_query objects automatically */
void sd_resolve_free(sd_resolve *resolve);
sd_resolve* sd_resolve_unref(sd_resolve *resolve);
/** Return the UNIX file descriptor to select() for readability
* on. Use this function to integrate sd-resolve with your custom main
* loop. */
int sd_resolve_fd(sd_resolve *resolve);
/** Return the UNIX file descriptor to poll() for events on. Use this
* function to integrate sd-resolve with your custom main loop. */
int sd_resolve_get_fd(sd_resolve *resolve);
/** Return the poll() events (a combination of flags like POLLIN,
* POLLOUT, ...) to check for. */
int sd_resolve_get_events(sd_resolve *resolve);
/** Return the poll() timeout to pass. Returns (uint64_t) -1 as time
* out if no time out is needed */
int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *timeout_usec);
/** Process pending responses. After this function is called you can
* get the next completed query object(s) using sd_resolve_get_next(). If
* block is non-zero wait until at least one response has been
* processed. If block is zero, process all pending responses and
* return. */
int sd_resolve_wait(sd_resolve *resolve, int block);
* get the next completed query object(s) using
* sd_resolve_get_next(). */
int sd_resolve_process(sd_resolve *resolve);
/** Wait for a resolve event to complete */
int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec);
/** Issue a name to address query on the specified session. The
* arguments are compatible with the ones of libc's
* getaddrinfo(3). The function returns a new query object. When the
* query is completed you may retrieve the results using
* sd_resolve_getaddrinfo_done().*/
sd_resolve_query* sd_resolve_getaddrinfo(sd_resolve *resolve, const char *node, const char *service, const struct addrinfo *hints);
* sd_resolve_getaddrinfo_done(). */
int sd_resolve_getaddrinfo(sd_resolve *resolve, const char *node, const char *service, const struct addrinfo *hints, sd_resolve_query **q);
/** Retrieve the results of a preceding sd_resolve_getaddrinfo()
* call. Returns a addrinfo structure and a return value compatible
@ -82,8 +76,13 @@ sd_resolve_query* sd_resolve_getaddrinfo(sd_resolve *resolve, const char *node,
* call and may not be used any further. Make sure to free the
* returned addrinfo structure with sd_resolve_freeaddrinfo() and not
* libc's freeaddrinfo(3)! If the query is not completed yet EAI_AGAIN
* is returned.*/
int sd_resolve_getaddrinfo_done(sd_resolve *resolve, sd_resolve_query* q, struct addrinfo **ret_res);
* is returned. */
int sd_resolve_getaddrinfo_done(sd_resolve_query* q, struct addrinfo **ret_ai);
/** Free the addrinfo structure as returned by
* sd_resolve_getaddrinfo_done(). Make sure to use this functions instead
* of the libc's freeaddrinfo()! */
void sd_resolve_freeaddrinfo(struct addrinfo *ai);
/** Issue an address to name query on the specified session. The
* arguments are compatible with the ones of libc's
@ -91,40 +90,39 @@ int sd_resolve_getaddrinfo_done(sd_resolve *resolve, sd_resolve_query* q, struct
* query is completed you may retrieve the results using
* sd_resolve_getnameinfo_done(). Set gethost (resp. getserv) to non-zero
* if you want to query the hostname (resp. the service name). */
sd_resolve_query* sd_resolve_getnameinfo(sd_resolve *resolve, const struct sockaddr *sa, socklen_t salen, int flags, int gethost, int getserv);
int sd_resolve_getnameinfo(sd_resolve *resolve, const struct sockaddr *sa, socklen_t salen, int flags, int gethost, int getserv, sd_resolve_query **q);
/** Retrieve the results of a preceding sd_resolve_getnameinfo()
* call. Returns the hostname and the service name in ret_host and
* ret_serv. The query object q is destroyed by this call and may not
* be used any further. If the query is not completed yet EAI_AGAIN is
* returned. */
int sd_resolve_getnameinfo_done(sd_resolve *resolve, sd_resolve_query* q, char *ret_host, size_t hostlen, char *ret_serv, size_t servlen);
int sd_resolve_getnameinfo_done(sd_resolve_query* q, char **ret_host, char **ret_serv);
/** Issue a resolveer query on the specified session. The arguments are
/** Issue a resolver query on the specified session. The arguments are
* compatible with the ones of libc's res_query(3). The function returns a new
* query object. When the query is completed you may retrieve the results using
* sd_resolve_res_done(). */
sd_resolve_query* sd_resolve_res_query(sd_resolve *resolve, const char *dname, int class, int type);
int sd_resolve_res_query(sd_resolve *resolve, const char *dname, int class, int type, sd_resolve_query **q);
/** Issue an resolveer query on the specified session. The arguments are
/** Issue an resolver query on the specified session. The arguments are
* compatible with the ones of libc's res_search(3). The function returns a new
* query object. When the query is completed you may retrieve the results using
* sd_resolve_res_done(). */
sd_resolve_query* sd_resolve_res_search(sd_resolve *resolve, const char *dname, int class, int type);
int sd_resolve_res_search(sd_resolve *resolve, const char *dname, int class, int type, sd_resolve_query **q);
/** Retrieve the results of a preceding sd_resolve_res_query() or
* resolve_res_search call. The query object q is destroyed by this
* call and may not be used any further. Returns a pointer to the
* answer of the res_query call. If the query is not completed yet
* -EAGAIN is returned, on failure -errno is returned, otherwise the
* length of answer is returned. Make sure to free the answer is a
* call to sd_resolve_freeanswer(). */
int sd_resolve_res_done(sd_resolve *resolve, sd_resolve_query* q, unsigned char **answer);
* length of answer is returned. */
int sd_resolve_res_done(sd_resolve_query* q, unsigned char **answer);
/** Return the next completed query object. If no query has been
* completed yet, return NULL. Please note that you need to run
* sd_resolve_wait() before this function will return sensible data. */
sd_resolve_query* sd_resolve_get_next(sd_resolve *resolve);
int sd_resolve_get_next(sd_resolve *resolve, sd_resolve_query **q);
/** Return the number of query objects (completed or not) attached to
* this session */
@ -132,23 +130,18 @@ int sd_resolve_get_n_queries(sd_resolve *resolve);
/** Cancel a currently running query. q is is destroyed by this call
* and may not be used any futher. */
void sd_resolve_cancel(sd_resolve *resolve, sd_resolve_query* q);
/** Free the addrinfo structure as returned by
* sd_resolve_getaddrinfo_done(). Make sure to use this functions instead
* of the libc's freeaddrinfo()! */
void sd_resolve_freeaddrinfo(struct addrinfo *ai);
int sd_resolve_cancel(sd_resolve_query* q);
/** Returns non-zero when the query operation specified by q has been completed */
int sd_resolve_isdone(sd_resolve *resolve, sd_resolve_query*q);
int sd_resolve_is_done(sd_resolve_query*q);
/** Assign some opaque userdata with a query object */
void sd_resolve_setuserdata(sd_resolve *resolve, sd_resolve_query *q, void *userdata);
void* sd_resolve_set_userdata(sd_resolve_query *q, void *userdata);
/** Return userdata assigned to a query object. Use
* sd_resolve_setuserdata() to set this data. If no data has been set
* prior to this call it returns NULL. */
void* sd_resolve_getuserdata(sd_resolve *resolve, sd_resolve_query *q);
void* sd_resolve_get_userdata(sd_resolve_query *q);
_SD_END_DECLARATIONS;