diff options
author | Linus Nordberg <linus@nordberg.se> | 2019-02-25 16:32:41 +0100 |
---|---|---|
committer | Linus Nordberg <linus@nordberg.se> | 2019-02-25 16:32:41 +0100 |
commit | 71c30c7efc4c872f060837ac1276753538c20924 (patch) | |
tree | 94ad7a8050dbe475e12d1012c3e9016a409ca4e9 | |
parent | Move the google doc into the git repository (diff) | |
download | wg-dynamic-71c30c7efc4c872f060837ac1276753538c20924.tar.xz wg-dynamic-71c30c7efc4c872f060837ac1276753538c20924.zip |
WIP send response
-rw-r--r-- | common.c | 41 | ||||
-rw-r--r-- | common.h | 8 | ||||
-rw-r--r-- | wg-dynamic-server.c | 60 |
3 files changed, 89 insertions, 20 deletions
@@ -248,9 +248,9 @@ static int parse_request(struct wg_dynamic_request *req, unsigned char *buf, return 1; } -bool handle_request(int fd, struct wg_dynamic_request *req, - void (*success)(int, struct wg_dynamic_request *req), - void (*error)(int, int)) +bool handle_request(int user_data, int fd, struct wg_dynamic_request *req, + bool (*success)(int, int, struct wg_dynamic_request *), + bool (*error)(int, int, int)) { ssize_t bytes; int ret; @@ -273,14 +273,35 @@ bool handle_request(int fd, struct wg_dynamic_request *req, } ret = parse_request(req, buf, bytes); - if (ret < 0) { - error(fd, -ret); - return true; - } else if (ret == 0) { - success(fd, req); - return true; - } + if (ret < 0) + return error(user_data, fd, -ret); + else if (ret == 0) + return success(user_data, fd, req); } return false; } + +bool send_message(int fd, unsigned char *buf, size_t *len) +{ + ssize_t bytes; + size_t offset = 0; + + while (*len) { + bytes = write(fd, buf + offset, *len); + if (bytes < 0) { + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + + // TODO: need to handle EINTR even though fd is SOCK_NONBLOCK? + + debug("Writing to socket %d failed: %s\n", + fd, strerror(errno)); + return true; + } + + *len -= bytes; + offset += bytes; + } + return *len == 0; +} @@ -65,8 +65,8 @@ struct wg_combined_ip { #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) void free_wg_dynamic_request(struct wg_dynamic_request *req); -bool handle_request(int fd, struct wg_dynamic_request *req, - void (*success)(int, struct wg_dynamic_request *req), - void (*error)(int, int)); - +bool handle_request(int user_data, int fd, struct wg_dynamic_request *req, + bool (*success)(int, int, struct wg_dynamic_request *), + bool (*error)(int, int, int)); +bool send_message(int fd, unsigned char *buf, size_t *len); #endif diff --git a/wg-dynamic-server.c b/wg-dynamic-server.c index 81e53f6..94c7c27 100644 --- a/wg-dynamic-server.c +++ b/wg-dynamic-server.c @@ -29,6 +29,10 @@ static struct in6_addr well_known; static wg_device *device = NULL; static struct pollfd pollfds[MAX_CONNECTIONS + 1]; +static struct outbuf { + unsigned char *buf; + size_t len; +} outbufs[MAX_CONNECTIONS] = { 0 }; struct mnl_cb_data { uint32_t ifindex; @@ -206,28 +210,58 @@ static int accept_connection(int sockfd) return fd; } -static void close_connection(int *fd, struct wg_dynamic_request *req) +static void close_connection(int *fd, struct wg_dynamic_request *req, + struct outbuf *outbuf) { if (close(*fd)) debug("Failed to close socket"); *fd = -1; + free_wg_dynamic_request(req); + + free(outbuf->buf); + outbuf->buf = NULL; + outbuf->len = 0; } -static void send_response(int fd, struct wg_dynamic_request *req) +static bool send_response(int slot, int fd, struct wg_dynamic_request *req) { + unsigned char buf[8192]; /* FIXME */ + ssize_t len; + unsigned char *newbuf; + size_t to_write; + printf("Recieved request of type %s.\n", WG_DYNAMIC_KEY[req->cmd]); struct wg_dynamic_attr *cur = req->first; while (cur) { printf(" with attr %s.\n", WG_DYNAMIC_KEY[cur->key]); cur = cur->next; } + +#define REPLY "reply=fake\n\n" + len = sizeof REPLY - 1; + memcpy(buf, REPLY, len); + + to_write = len; + if (send_message(fd, buf, &to_write)) + return true; + + newbuf = malloc(to_write); + if (!newbuf) + fatal("Failed malloc()"); + memcpy(newbuf, buf + len - to_write, to_write); + free(outbufs[slot].buf); + outbufs[slot].buf = newbuf; + outbufs[slot].len = to_write; + pollfds[slot].events |= POLLOUT; + return false; } -static void send_error(int fd, int ret) +static bool send_error(int slot, int fd, int ret) { debug("Error: %s\n", strerror(ret)); + return true; } static void setup_socket(int *fd) @@ -315,13 +349,27 @@ int main(int argc, char *argv[]) } for (int i = 1; i < MAX_CONNECTIONS + 1; ++i) { + if (!(pollfds[i].revents & POLLOUT)) + continue; + + pollfds[i].revents &= ~POLLOUT; + if (send_message(pollfds[i].fd, outbufs[i - 1].buf, + &outbufs[i - 1].len)) + close_connection(&pollfds[i].fd, + &reqs[i - 1], + &outbufs[i - 1]); + } + + for (int i = 1; i < MAX_CONNECTIONS + 1; ++i) { if (!(pollfds[i].revents & POLLIN)) continue; - pollfds[i].revents = 0; - if (handle_request(pollfds[i].fd, &reqs[i - 1], + pollfds[i].revents &= ~POLLIN; + if (handle_request(i, pollfds[i].fd, &reqs[i - 1], send_response, send_error)) - close_connection(&pollfds[i].fd, &reqs[i - 1]); + close_connection(&pollfds[i].fd, + &reqs[i - 1], + &outbufs[i - 1]); } } |