aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordberg.se>2019-02-25 16:32:41 +0100
committerLinus Nordberg <linus@nordberg.se>2019-02-25 16:32:41 +0100
commit71c30c7efc4c872f060837ac1276753538c20924 (patch)
tree94ad7a8050dbe475e12d1012c3e9016a409ca4e9
parentMove the google doc into the git repository (diff)
downloadwg-dynamic-71c30c7efc4c872f060837ac1276753538c20924.tar.xz
wg-dynamic-71c30c7efc4c872f060837ac1276753538c20924.zip
WIP send response
-rw-r--r--common.c41
-rw-r--r--common.h8
-rw-r--r--wg-dynamic-server.c60
3 files changed, 89 insertions, 20 deletions
diff --git a/common.c b/common.c
index 10883fe..ed4a0be 100644
--- a/common.c
+++ b/common.c
@@ -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;
+}
diff --git a/common.h b/common.h
index 10ddf61..777a3ec 100644
--- a/common.h
+++ b/common.h
@@ -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]);
}
}