From: Pavel Šimerda Date: Sun, 9 Feb 2014 13:55:17 +0000 (+0100) Subject: decouple channel and query structures X-Git-Url: https://www.sourceware.org/git/?a=commitdiff_plain;h=c31376f4be92dfb416575fe6c24636b1090dff33;p=netresolve.git decouple channel and query structures --- diff --git a/include/netresolve.h b/include/netresolve.h index 1d034b5..d48e61f 100644 --- a/include/netresolve.h +++ b/include/netresolve.h @@ -30,7 +30,7 @@ /* Channels and queries */ typedef struct netresolve_channel *netresolve_t; -typedef struct netresolve_channel *netresolve_query_t; +typedef struct netresolve_query *netresolve_query_t; netresolve_t netresolve_open(void); void netresolve_close(netresolve_t channel); diff --git a/lib/backend.c b/lib/backend.c index 9a35829..b662123 100644 --- a/lib/backend.c +++ b/lib/backend.c @@ -175,7 +175,7 @@ netresolve_backend_add_path(netresolve_query_t query, debug("added path: %s", netresolve_get_path_string(query, response->pathcount - 1)); - if (query->callbacks.on_bind) + if (query->channel->callbacks.on_bind) netresolve_query_bind(query, response->pathcount - 1); } @@ -251,21 +251,21 @@ netresolve_backend_finished(netresolve_query_t query) /* Restart with the next *mandatory* backend. */ while (*++query->backend) { if ((*query->backend)->mandatory) { - netresolve_start(query); + netresolve_query_start(query); return; } } - if (query->callbacks.on_connect) { + if (query->channel->callbacks.on_connect) { netresolve_connect_start(query); return; } - netresolve_set_state(query, NETRESOLVE_STATE_FINISHED); + netresolve_query_set_state(query, NETRESOLVE_STATE_FINISHED); return; fail: - netresolve_set_state(query, NETRESOLVE_STATE_FAILED); + netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED); } void @@ -283,12 +283,12 @@ netresolve_backend_failed(netresolve_query_t query) /* Restart with the next backend. */ if (*++query->backend) { - netresolve_start(query); + netresolve_query_start(query); return; } fail: - netresolve_set_state(query, NETRESOLVE_STATE_FAILED); + netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED); } bool diff --git a/lib/channel.c b/lib/channel.c index bec2414..a5bd9bb 100644 --- a/lib/channel.c +++ b/lib/channel.c @@ -42,19 +42,15 @@ netresolve_t netresolve_open(void) { netresolve_t channel = calloc(1, sizeof *channel); - if (!channel) return NULL; - channel->channel = channel; channel->epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (channel->epoll_fd == -1) { free(channel); return NULL; } - channel->first_connect_timeout = -1; - channel->request.default_loopback = strtob(secure_getenv("NETRESOLVE_FLAG_DEFAULT_LOOPBACK")); return channel; @@ -65,7 +61,11 @@ netresolve_close(netresolve_t channel) { if (!channel) return; - netresolve_set_state(channel, NETRESOLVE_STATE_INIT); + + /* TODO: Loop through queries when they're decoupled from the channel. */ + if (channel->query) + netresolve_query_done(channel->query); + netresolve_set_backend_string(channel, ""); close(channel->epoll_fd); memset(channel, 0, sizeof *channel); @@ -91,20 +91,20 @@ state_to_string(enum netresolve_state state) } void -netresolve_set_state(netresolve_t channel, enum netresolve_state state) +netresolve_query_set_state(netresolve_query_t query, enum netresolve_state state) { - enum netresolve_state old_state = channel->state; + enum netresolve_state old_state = query->state; - channel->state = state; + query->state = state; debug("state: %s -> %s\n", state_to_string(old_state), state_to_string(state)); /* Leaving state... */ switch (old_state) { case NETRESOLVE_STATE_WAITING: - if (channel->callbacks.watch_fd) - channel->callbacks.watch_fd(channel, channel->epoll_fd, 0, - channel->callbacks.user_data_fd); + if (query->channel->callbacks.watch_fd) + query->channel->callbacks.watch_fd(query, query->channel->epoll_fd, 0, + query->channel->callbacks.user_data_fd); break; default: break; @@ -113,47 +113,47 @@ netresolve_set_state(netresolve_t channel, enum netresolve_state state) /* Entering state... */ switch (state) { case NETRESOLVE_STATE_INIT: - free(channel->response.paths); - free(channel->response.canonname); - memset(&channel->response, 0, sizeof channel->response); + free(query->response.paths); + free(query->response.canonname); + memset(&query->response, 0, sizeof query->response); break; case NETRESOLVE_STATE_WAITING: - if (channel->callbacks.watch_fd) - channel->callbacks.watch_fd(channel, channel->epoll_fd, POLLIN, - channel->callbacks.user_data_fd); - netresolve_start(channel); + if (query->channel->callbacks.watch_fd) + query->channel->callbacks.watch_fd(query, query->channel->epoll_fd, POLLIN, + query->channel->callbacks.user_data_fd); + netresolve_query_start(query); break; case NETRESOLVE_STATE_FINISHED: - if (channel->callbacks.on_connect) - netresolve_connect_cleanup(channel); - if (channel->callbacks.on_success) - channel->callbacks.on_success(channel, channel->callbacks.user_data); + if (query->channel->callbacks.on_connect) + netresolve_connect_cleanup(query); + if (query->channel->callbacks.on_success) + query->channel->callbacks.on_success(query, query->channel->callbacks.user_data); break; case NETRESOLVE_STATE_FAILED: - if (channel->callbacks.on_success) - channel->callbacks.on_success(channel, channel->callbacks.user_data); + if (query->channel->callbacks.on_success) + query->channel->callbacks.on_success(query, query->channel->callbacks.user_data); break; } } void -netresolve_start(netresolve_t channel) +netresolve_query_start(netresolve_query_t query) { - struct netresolve_backend *backend = *channel->backend; + struct netresolve_backend *backend = *query->backend; - backend->start(channel, backend->settings+1); + backend->start(query, backend->settings+1); } static bool dispatch_fd(netresolve_t channel, int fd, int events) { - struct netresolve_backend *backend = *channel->backend; + struct netresolve_backend *backend = *channel->query->backend; - if (!backend && netresolve_connect_dispatch(channel, fd, events)) + if (!backend && netresolve_connect_dispatch(channel->query, fd, events)) return true; if (backend && backend->dispatch) { - backend->dispatch(channel, fd, events); + backend->dispatch(channel->query, fd, events); return true; } @@ -170,16 +170,16 @@ netresolve_epoll(netresolve_t channel, int timeout) /* Sanity check number of descriptors. */ if (channel->epoll_count <= 0) { - netresolve_set_state(channel, NETRESOLVE_STATE_FAILED); + netresolve_query_set_state(channel->query, NETRESOLVE_STATE_FAILED); return; } nevents = epoll_wait(channel->epoll_fd, events, maxevents, channel->callbacks.watch_fd ? 0 : -1); if (nevents == -1) { - netresolve_set_state(channel, NETRESOLVE_STATE_FAILED); + netresolve_query_set_state(channel->query, NETRESOLVE_STATE_FAILED); return; } - for (i = 0; channel->state == NETRESOLVE_STATE_WAITING && i < nevents; i++) + for (i = 0; channel->query->state == NETRESOLVE_STATE_WAITING && i < nevents; i++) dispatch_fd(channel, events[i].data.fd, events[i].events); } @@ -190,7 +190,7 @@ netresolve_watch_fd(netresolve_t channel, int fd, int events) debug("watching file descriptor: %d %d\n", fd, events); - if (!channel->backend || channel->epoll_fd == -1) + if (!channel->query->backend || channel->epoll_fd == -1) abort(); if (epoll_ctl(channel->epoll_fd, EPOLL_CTL_DEL, fd, &event) != -1) @@ -253,31 +253,38 @@ state_to_errno(enum netresolve_state state) netresolve_query_t netresolve_query(netresolve_t channel, const char *node, const char *service) { - if (channel->state == NETRESOLVE_STATE_WAITING) { - errno = EBUSY; - return NULL; - } - netresolve_set_state(channel, NETRESOLVE_STATE_INIT); if (!channel->backends) netresolve_set_backend_string(channel, secure_getenv("NETRESOLVE_BACKENDS")); if (!channel->backends) { errno = ENODATA; return NULL; } - channel->backend = channel->backends; - channel->request.node = node; - channel->request.service = service; + /* TODO: A list of queries will be used. */ + if (channel->query) + return NULL; + channel->query = calloc(1, sizeof *channel->query); + if (!channel->query) + return NULL; + channel->query->channel = channel; + channel->query->first_connect_timeout = -1; + + netresolve_query_set_state(channel->query, NETRESOLVE_STATE_INIT); + channel->query->backend = channel->backends; - netresolve_set_state(channel, NETRESOLVE_STATE_WAITING); + memcpy(&channel->query->request, &channel->request, sizeof channel->request); + channel->query->request.node = node; + channel->query->request.service = service; + + netresolve_query_set_state(channel->query, NETRESOLVE_STATE_WAITING); /* Blocking mode. */ if (!channel->callbacks.watch_fd) - while (channel->state == NETRESOLVE_STATE_WAITING) + while (channel->query->state == NETRESOLVE_STATE_WAITING) netresolve_epoll(channel, -1); - errno = state_to_errno(channel->state); - return channel; + errno = state_to_errno(channel->query->state); + return channel->query; } bool @@ -306,5 +313,9 @@ netresolve_dispatch_fd(netresolve_t channel, int fd, int events) void netresolve_query_done(netresolve_query_t query) { - netresolve_set_state(query, NETRESOLVE_STATE_INIT); + netresolve_query_set_state(query, NETRESOLVE_STATE_INIT); + + /* TODO: Will be removed propery from a query list. */ + query->channel->query = NULL; + free(query); } diff --git a/lib/netresolve-backend.h b/lib/netresolve-backend.h index 0a186b9..52d3011 100644 --- a/lib/netresolve-backend.h +++ b/lib/netresolve-backend.h @@ -33,7 +33,7 @@ #include #include -typedef struct netresolve_channel *netresolve_query_t; +typedef struct netresolve_query *netresolve_query_t; /* Input */ const char *netresolve_backend_get_node(netresolve_query_t query); diff --git a/lib/netresolve-private.h b/lib/netresolve-private.h index 13b4994..b4679be 100644 --- a/lib/netresolve-private.h +++ b/lib/netresolve-private.h @@ -43,9 +43,9 @@ struct netresolve_backend { bool mandatory; char **settings; void *dl_handle; - void (*start)(netresolve_t channel, char **settings); - void (*dispatch)(netresolve_t channel, int fd, int revents); - void (*cleanup)(netresolve_t channel); + void (*start)(netresolve_query_t query, char **settings); + void (*dispatch)(netresolve_query_t query, int fd, int revents); + void (*cleanup)(netresolve_query_t query); void *data; }; @@ -74,13 +74,10 @@ struct netresolve_path { }; struct netresolve_channel { - struct netresolve_channel *channel; int log_level; - enum netresolve_state state; int epoll_fd; int epoll_count; - struct netresolve_backend **backends, **backend; - int first_connect_timeout; + struct netresolve_backend **backends; struct { netresolve_callback_t on_success; netresolve_callback_t on_failure; @@ -110,6 +107,16 @@ struct netresolve_channel { bool default_loopback; bool dns_srv_lookup; } request; + /* TODO: A list of queries will be used. */ + struct netresolve_query *query; +}; + +struct netresolve_query { + struct netresolve_channel *channel; + enum netresolve_state state; + int first_connect_timeout; + struct netresolve_backend **backend; + struct netresolve_request request; struct netresolve_response { struct netresolve_path *paths; size_t pathcount; @@ -124,20 +131,20 @@ struct netresolve_channel { char buffer[1024]; }; -void netresolve_set_state(netresolve_t channel, enum netresolve_state state); +void netresolve_query_set_state(netresolve_query_t query, enum netresolve_state state); -void netresolve_start(netresolve_t channel); +void netresolve_query_start(netresolve_query_t channel); void netresolve_epoll(netresolve_t channel, int timeout); void netresolve_watch_fd(netresolve_t channel, int fd, int events); int netresolve_add_timeout(netresolve_t channel, time_t sec, long nsec); void netresolve_remove_timeout(netresolve_t channel, int fd); -void netresolve_query_bind(netresolve_t query, size_t idx); -void netresolve_query_connect(netresolve_t query, size_t idx); +void netresolve_query_bind(netresolve_query_t query, size_t idx); +void netresolve_query_connect(netresolve_query_t query, size_t idx); -void netresolve_connect_start(netresolve_t channel); -bool netresolve_connect_dispatch(netresolve_t channel, int fd, int events); -void netresolve_connect_cleanup(netresolve_t channel); +void netresolve_connect_start(netresolve_query_t query); +bool netresolve_connect_dispatch(netresolve_query_t query, int fd, int events); +void netresolve_connect_cleanup(netresolve_query_t query); void netresolve_get_service_info(void (*callback)(int, int, int, void *), void *user_data, const char *request_service, int socktype, int protocol); diff --git a/lib/socket.c b/lib/socket.c index 601c12a..99f8e81 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -48,7 +48,7 @@ netresolve_query_bind(netresolve_query_t query, size_t idx) return; } - query->callbacks.on_bind(query, idx, sock, query->callbacks.user_data_sock); + query->channel->callbacks.on_bind(query, idx, sock, query->channel->callbacks.user_data_sock); } void @@ -73,7 +73,7 @@ netresolve_query_connect(netresolve_query_t query, size_t idx) if (connect(path->socket.fd, sa, salen) == -1 && errno != EINPROGRESS) goto fail_connect; - netresolve_watch_fd(query, path->socket.fd, POLLOUT); + netresolve_watch_fd(query->channel, path->socket.fd, POLLOUT); path->socket.state = NETRESOLVE_STATE_WAITING; return; @@ -96,9 +96,9 @@ connect_check(netresolve_query_t query) break; if (path->socket.state == NETRESOLVE_STATE_FINISHED) { - query->callbacks.on_connect(query, idx, path->socket.fd, query->callbacks.user_data_sock); + query->channel->callbacks.on_connect(query, idx, path->socket.fd, query->channel->callbacks.user_data_sock); path->socket.state = NETRESOLVE_STATE_INIT; - netresolve_set_state(query, NETRESOLVE_STATE_FINISHED); + netresolve_query_set_state(query, NETRESOLVE_STATE_FINISHED); break; } } @@ -110,7 +110,7 @@ connect_finished(netresolve_query_t query, struct netresolve_path *path) path->socket.state = NETRESOLVE_STATE_FINISHED; if (query->first_connect_timeout == -1) - query->first_connect_timeout = netresolve_add_timeout(query, FIRST_CONNECT_TIMEOUT, 0); + query->first_connect_timeout = netresolve_add_timeout(query->channel, FIRST_CONNECT_TIMEOUT, 0); connect_check(query); } @@ -164,7 +164,7 @@ netresolve_connect_dispatch(netresolve_query_t query, int fd, int events) struct netresolve_path *path = &query->response.paths[i]; if (fd == path->socket.fd) { - netresolve_watch_fd(query, path->socket.fd, 0); + netresolve_watch_fd(query->channel, path->socket.fd, 0); if (events & POLLOUT) { socklen_t len = sizeof(errno); @@ -225,7 +225,7 @@ netresolve_connect_cleanup(netresolve_query_t query) } if (query->first_connect_timeout != -1) { - netresolve_remove_timeout(query, query->first_connect_timeout); + netresolve_remove_timeout(query->channel, query->first_connect_timeout); query->first_connect_timeout = -1; } } diff --git a/lib/utils.c b/lib/utils.c index 05b24f3..049d3a9 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -29,7 +29,7 @@ #include static void -on_socket(netresolve_t channel, int idx, int sock, void *user_data) +on_socket(netresolve_query_t query, int idx, int sock, void *user_data) { int *psock = user_data; diff --git a/tests/test-async.c b/tests/test-async.c index 4e21882..08e9158 100644 --- a/tests/test-async.c +++ b/tests/test-async.c @@ -32,7 +32,7 @@ #include static void -watch_fd(netresolve_t channel, int fd, int events, void *user_data) +watch_fd(netresolve_query_t query, int fd, int events, void *user_data) { int epoll_fd = *(int *) user_data; diff --git a/tools/netconnect.c b/tools/netconnect.c index 41096f7..0669384 100644 --- a/tools/netconnect.c +++ b/tools/netconnect.c @@ -64,7 +64,7 @@ read_and_write(int rfd, int wfd) } static void -on_connect(netresolve_t channel, int idx, int sock, void *user_data) +on_connect(netresolve_query_t channel, int idx, int sock, void *user_data) { *(int *) user_data = sock; }