From d1b9b898128058b425e44a5bac8b7ae289147ae1 Mon Sep 17 00:00:00 2001 From: Rick V Date: Tue, 10 Dec 2019 18:45:19 -0600 Subject: [PATCH] add note add libuv build add its dependent libraries to the final link line --- cmake/win32.cmake | 2 +- llarp/ev/ev_win32.hpp | 13 +- llarp/win32/win32_up.h | 69 ----- llarp/win32/win32_upoll.c | 524 -------------------------------------- llarp/win32/win32_upoll.h | 126 --------- win32-setup/Makefile | 9 + 6 files changed, 22 insertions(+), 721 deletions(-) delete mode 100644 llarp/win32/win32_up.h delete mode 100644 llarp/win32/win32_upoll.c delete mode 100644 llarp/win32/win32_upoll.h diff --git a/cmake/win32.cmake b/cmake/win32.cmake index 5e732fe59..af4167eb0 100644 --- a/cmake/win32.cmake +++ b/cmake/win32.cmake @@ -20,7 +20,7 @@ if(NOT MSVC_VERSION) # GNU ld sees fit to merge *all* the .ident sections in object files # to .r[o]data section one after the other! add_compile_options(-fno-ident -Wa,-mbig-obj) - link_libraries( -lshlwapi -ldbghelp ) + link_libraries( -lshlwapi -ldbghelp -luser32 -liphlpapi -lpsapi -luserenv ) add_definitions(-DWINVER=0x0500 -D_WIN32_WINNT=0x0500) endif() diff --git a/llarp/ev/ev_win32.hpp b/llarp/ev/ev_win32.hpp index dbc7b465d..495faeb95 100644 --- a/llarp/ev/ev_win32.hpp +++ b/llarp/ev/ev_win32.hpp @@ -100,7 +100,18 @@ struct win32_tun_io } }; -// UDP event loop (we use select(3SOCKET) because linux) +// UDP event loop (no longer used, we libuv for now) +// PLEASE convert me to IOCPs so we don't have to use that +// EXTREMELY CURSED libuv event loop and its llarp_vpn_io_pipe +// +// For you see, on Windows, we have enough local user permissions to set +// up a VPN tunnel interface internally, and have lokinet consume this +// file descriptor directly. See win32_tun_io for this impl. llarp_vpn_io +// assumes that an external entity or process is required to inject packets +// into the VPN interface provided by the OS. +// +// Not only that, the win32 IOCP facility handles timing on its own, you can +// specify an interval to tick directly into the call to GetQueuedCompletionStatus(2) struct llarp_win32_loop : public llarp_ev_loop { upoll_t* upollfd; diff --git a/llarp/win32/win32_up.h b/llarp/win32/win32_up.h deleted file mode 100644 index 3b89eda23..000000000 --- a/llarp/win32/win32_up.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _UP_H_ -#define _UP_H_ -#ifdef __cplusplus -extern "C" -{ -#endif -#include -#include -#include - -#define UPOLL_CTL_ADD 1 -#define UPOLL_CTL_DEL 2 -#define UPOLL_CTL_MOD 3 - -#define UPOLLIN 0x01 -#define UPOLLOUT 0x02 -#define UPOLLERR 0x04 -#define UPOLLET 0x08 - - typedef struct upoll upoll_t; - - typedef union upoll_data { - void* ptr; - intptr_t fd; - uint32_t u32; - uint64_t u64; - } upoll_data_t; - - typedef struct upoll_event - { - uint32_t events; - upoll_data_t data; - } upoll_event_t; - - upoll_t* - upoll_create(uint32_t size); - int - upoll_ctl(upoll_t* upq, int op, intptr_t fd, upoll_event_t* event); - int - upoll_wait(upoll_t* upq, upoll_event_t* events, int maxevents, int timeout); - void - upoll_destroy(upoll_t* upq); - - intptr_t - usocket(int domain, int type, int proto); - intptr_t - uaccept(intptr_t sock); - - int - ubind(intptr_t sock, const char* name, const char* serv); - int - ulisten(intptr_t sock, int backlog); - int - uconnect(intptr_t sock, const char* name, const char* serv); - int - uclose(intptr_t sock); - - /* TCP sockets */ - int - uread(intptr_t fd, char* buf, size_t len); - int - uwrite(intptr_t fd, const char* buf, size_t len); - - int - usocketpair(intptr_t socks[2], int async); -#ifdef __cplusplus -} -#endif -#endif /* _UP_H_ */ \ No newline at end of file diff --git a/llarp/win32/win32_upoll.c b/llarp/win32/win32_upoll.c deleted file mode 100644 index bd007762a..000000000 --- a/llarp/win32/win32_upoll.c +++ /dev/null @@ -1,524 +0,0 @@ -#ifdef _WIN32 -/* wake me up inside */ -#pragma GCC diagnostic ignored "-Wvla" -/* emulated epoll, because the native async event system does not do - * particularly well with notification - * update: now win32-exclusive - */ -#include "win32_upoll.h" - -#define uhash_slot(K, S) (((K) ^ (K >> 8)) & (S - 1)) - -static uhash_t* -uhash_create(uint32_t size) -{ - unsigned int i; - size--; - size |= size >> 1; - size |= size >> 2; - size |= size >> 4; - size |= size >> 8; - size |= size >> 16; - size++; - - uhash_t* hash = (uhash_t*)calloc(1, sizeof(uhash_t) + size * sizeof(ulist_t)); - hash->count = 0; - hash->size = size; - hash->items = (ulist_t*)(((char*)hash) + sizeof(uhash_t)); - - for(i = 0; i < size; i++) - { - ulist_init(&hash->items[i]); - } - - return hash; -} - -static void* -uhash_lookup(uhash_t* hash, intptr_t key) -{ - uint32_t slot = uhash_slot(key, hash->size); - ulist_t* q; - ulist_scan(q, &hash->items[slot]) - { - uitem_t* i = ulist_data(q, uitem_t, list); - if(i->key == key) - return i->val; - } - return NULL; -} -static void -uhash_insert(uhash_t* hash, intptr_t key, void* val) -{ - uint32_t slot = uhash_slot(key, hash->size); - - uitem_t* item = (uitem_t*)calloc(1, sizeof(uitem_t)); - ulist_init(&item->list); - item->key = key; - item->val = val; - - ulist_append(&hash->items[slot], &item->list); -} -static int -uhash_delete(uhash_t* hash, intptr_t key) -{ - uint32_t slot = uhash_slot(key, hash->size); - ulist_t* q; - ulist_scan(q, &hash->items[slot]) - { - uitem_t* i = ulist_data(q, uitem_t, list); - if(i->key == key) - { - ulist_remove(q); - free(q); - q = NULL; - return 1; - } - } - return 0; -} -static int -uhash_destroy(uhash_t* hash) -{ - int i; - for(i = 0; i < hash->size; i++) - { - while(!ulist_empty(&hash->items[i])) - { - ulist_t* q = ulist_next(&hash->items[i]); - uitem_t* n = ulist_data(q, uitem_t, list); - ulist_remove(q); - free(n); - n = NULL; - } - } - return 0; -} - -upoll_t* -upoll_create(uint32_t size) -{ - assert(size > 0); - upoll_t* upq = (upoll_t*)calloc(1, sizeof(upoll_t)); - - ulist_init(&upq->alive); - - upq->table = uhash_create(size); - return upq; -} - -void -upoll_destroy(upoll_t* upq) -{ - assert(upq != NULL); - uhash_destroy(upq->table); - ulist_t* q = NULL; - unote_t* n = NULL; - while(!ulist_empty(&upq->alive)) - { - q = ulist_next(&upq->alive); - n = ulist_data(n, unote_t, queue); - ulist_remove(q); - free(n); - n = NULL; - } - free(upq); - upq = NULL; -} - -int -upoll_ctl(upoll_t* upq, int op, intptr_t fd, upoll_event_t* event) -{ - if(fd < 0) - return -EBADF; - - unote_t* note = NULL; - switch(op) - { - case UPOLL_CTL_ADD: - { - note = (unote_t*)uhash_lookup(upq->table, fd); - if(!note) - { - note = (unote_t*)calloc(1, sizeof(unote_t)); - note->upoll = upq; - ulist_init(¬e->queue); - note->event = *event; - note->fd = fd; - ulist_append(&upq->alive, ¬e->queue); - uhash_insert(upq->table, fd, (void*)note); - } - break; - } - case UPOLL_CTL_DEL: - { - note = (unote_t*)uhash_lookup(upq->table, fd); - if(!note) - return -ENOENT; - event = ¬e->event; - ulist_remove(¬e->queue); - uhash_delete(upq->table, fd); - free(note); - note = NULL; - break; - } - case UPOLL_CTL_MOD: - { - note = (unote_t*)uhash_lookup(upq->table, fd); - if(!note) - return -ENOENT; - note->event = *event; - break; - } - default: - { - return -EINVAL; - } - } - return 0; -} - -int -upoll_wait_select(upoll_t* upq, upoll_event_t* evs, int nev, int timeout) -{ - if(nev > FD_SETSIZE) - nev = FD_SETSIZE; - - unote_t** nvec = calloc(nev, sizeof(unote_t*)); - int i, maxfd = 0, e = 0, nfds = 0; - - fd_set pollin, pollout, pollerr; - - FD_ZERO(&pollin); - FD_ZERO(&pollout); - FD_ZERO(&pollerr); - - struct timeval tv; - struct timeval* tvp = &tv; - - tv.tv_usec = 0; - if(timeout < 0) - { - tvp = NULL; - } - else if(timeout == 0) - tv.tv_sec = 0; - else - { - tv.tv_sec = (timeout / 1000); - tv.tv_usec = (timeout % 1000) * 1000; - } - - unote_t* n = NULL; - ulist_t* s = ulist_mark(&upq->alive); - ulist_t* q = ulist_next(&upq->alive); - - while(q != s && nfds < nev) - { - n = ulist_data(q, unote_t, queue); - q = ulist_next(q); - - ulist_remove(&n->queue); - ulist_insert(&upq->alive, &n->queue); - - nvec[nfds] = n; - if(n->event.events & UPOLLIN) - { - FD_SET((SOCKET)n->fd, &pollin); - } - if(n->event.events & UPOLLOUT) - { - FD_SET((SOCKET)n->fd, &pollout); - } - FD_SET((SOCKET)n->fd, &pollerr); - if(maxfd < n->fd) - maxfd = n->fd; - nfds++; - } - - int rc = select(0, &pollin, &pollout, &pollerr, tvp); - if(rc == SOCKET_ERROR) - { - assert(WSAGetLastError() == WSAENOTSOCK); - free(nvec); - return -WSAGetLastError(); - } - - e = 0; - for(i = 0; i < nfds && e < nev; i++) - { - uint32_t hint = 0; - unote_t* n = nvec[i]; - if(FD_ISSET(n->fd, &pollin)) - { - hint |= UPOLLIN; - } - - if(FD_ISSET(n->fd, &pollerr)) - { - hint |= (UPOLLERR | UPOLLIN); - } - else if(FD_ISSET(n->fd, &pollout)) - { - hint |= UPOLLOUT; - } - - if(hint) - { - evs[e].data = n->event.data; - evs[e].events = hint; - ++e; - } - } - free(nvec); - return e; -} - -int -upoll_wait(upoll_t* upq, upoll_event_t* evs, int nev, int timeout) -{ - int r = 0; - r = upoll_wait_select(upq, evs, nev, timeout); - return r; -} - -intptr_t -usocket(int domain, int type, int proto) -{ - intptr_t fd = (intptr_t)socket(domain, type, proto); - - if(fd < 0) - return -WSAGetLastError(); - unsigned long flags = 1; - int rc = ioctlsocket((SOCKET)fd, FIONBIO, &flags); - if(rc < 0) - return -WSAGetLastError(); - - return fd; -} - -int -ubind(intptr_t fd, const char* host, const char* serv) -{ - struct addrinfo* info; - struct addrinfo hint; - memset(&hint, 0, sizeof(hint)); - - int optval = 0; - unsigned int optlen = sizeof(optval); - int rc = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, (char*)&optval, - (int*)&optlen); - - hint.ai_family = AF_INET; - hint.ai_socktype = optval; - - rc = getaddrinfo(host, serv, &hint, &info); - - optval = 1; - if(!rc) - { - rc = setsockopt((SOCKET)fd, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, - sizeof(optval)); - if(!rc) - rc = bind(fd, info->ai_addr, info->ai_addrlen); - } - - freeaddrinfo(info); - if(rc) - return WSAGetLastError(); - return 0; -} - -int -uconnect(intptr_t fd, const char* host, const char* serv) -{ - struct addrinfo* info; - - struct addrinfo hint; - memset(&hint, 0, sizeof(hint)); - - int optval = 0; - unsigned int optlen; - - int rc = getsockopt(fd, SOL_SOCKET, SO_TYPE, (char*)&optval, (int*)&optlen); - - hint.ai_family = AF_INET; - hint.ai_socktype = optval; - - rc = getaddrinfo(host, serv, &hint, &info); - - if(!rc) - rc = connect((SOCKET)fd, info->ai_addr, info->ai_addrlen); - - freeaddrinfo(info); - - if(rc) - { - if(WSAGetLastError() != WSAEWOULDBLOCK) - return WSAGetLastError(); - } - return 0; -} - -int -ulisten(intptr_t sock, int backlog) -{ - return listen(sock, backlog); -} - -intptr_t -uaccept(intptr_t sock) -{ - struct sockaddr addr; - - addr.sa_family = AF_INET; - socklen_t addr_len; - - intptr_t fd = (intptr_t)accept((SOCKET)sock, &addr, &addr_len); - if(fd == -1) - return WSAGetLastError(); - - return fd; -} - -int -uclose(intptr_t sock) -{ - return closesocket((SOCKET)sock); -} - -int -uread(intptr_t fd, char* buf, size_t len) -{ - return recv(fd, buf, len, 0); -} -int -uwrite(intptr_t fd, const char* buf, size_t len) -{ - return send(fd, buf, len, 0); -} - -/* adapted from (renamed make_overlapped to async for allergy reasons): */ -/* socketpair.c -Copyright 2007, 2010 by Nathan C. Myers -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - The name of the author must not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* Changes: - * 2014-02-12: merge David Woodhouse, Ger Hobbelt improvements - * git.infradead.org/users/dwmw2/openconnect.git/commitdiff/bdeefa54 - * github.com/GerHobbelt/selectable-socketpair - * always init the socks[] to -1/INVALID_SOCKET on error, both on Win32/64 - * and UNIX/other platforms - * 2013-07-18: Change to BSD 3-clause license - * 2010-03-31: - * set addr to 127.0.0.1 because win32 getsockname does not always set it. - * 2010-02-25: - * set SO_REUSEADDR option to avoid leaking some windows resource. - * Windows System Error 10049, "Event ID 4226 TCP/IP has reached - * the security limit imposed on the number of concurrent TCP connect - * attempts." Bleah. - * 2007-04-25: - * preserve value of WSAGetLastError() on all error returns. - * 2007-04-22: (Thanks to Matthew Gregan ) - * s/EINVAL/WSAEINVAL/ fix trivial compile failure - * s/socket/WSASocket/ enable creation of sockets suitable as stdin/stdout - * of a child process. - * add argument make_overlapped - */ - -int -usocketpair(intptr_t socks[2], int async) -{ - union { - struct sockaddr_in inaddr; - struct sockaddr addr; - } a; - SOCKET listener; - int e; - socklen_t addrlen = sizeof(a.inaddr); - DWORD flags = (async ? WSA_FLAG_OVERLAPPED : 0); - int reuse = 1; - - if(socks == 0) - { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - socks[0] = socks[1] = -1; - - listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(listener == INVALID_SOCKET) - return SOCKET_ERROR; - - memset(&a, 0, sizeof(a)); - a.inaddr.sin_family = AF_INET; - a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - a.inaddr.sin_port = 0; - - for(;;) - { - if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, - (socklen_t)sizeof(reuse)) - == -1) - break; - - if(bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) - break; - - memset(&a, 0, sizeof(a)); - if(getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR) - break; - // win32 getsockname may only set the port number, p=0.0005. - // ( http://msdn.microsoft.com/library/ms738543.aspx ): - a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - a.inaddr.sin_family = AF_INET; - - if(listen(listener, 1) == SOCKET_ERROR) - break; - - socks[0] = (intptr_t)WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags); - if(socks[0] == -1) - break; - if(connect((SOCKET)socks[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) - break; - - socks[1] = (intptr_t)accept(listener, NULL, NULL); - if(socks[1] == -1) - break; - - closesocket(listener); - return 0; - } - - e = WSAGetLastError(); - closesocket(listener); - closesocket((SOCKET)socks[0]); - closesocket((SOCKET)socks[1]); - WSASetLastError(e); - socks[0] = socks[1] = -1; - return SOCKET_ERROR; -} -#endif \ No newline at end of file diff --git a/llarp/win32/win32_upoll.h b/llarp/win32/win32_upoll.h deleted file mode 100644 index 69a54cdf1..000000000 --- a/llarp/win32/win32_upoll.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef _UPOLL_H_ -#define _UPOLL_H_ - -#include "win32_up.h" - -#if(defined(__64BIT__) || defined(__x86_64__)) -#define __IS_64BIT__ -#else -#define __IS_32BIT__ -#endif - -#if(defined WIN32 || defined _WIN32) -#undef __WINDOWS__ -#define __WINDOWS__ -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -// this is probably big enough to get -// the lesser of 4096 sockets or whatever -// the system allows -#ifndef FD_SETSIZE -#define FD_SETSIZE 4096 -#endif - -#include -#include -#include -#include - -#undef HAVE_SELECT -#define HAVE_SELECT 1 - -typedef struct unote unote_t; -typedef struct ulist ulist_t; -typedef struct uitem uitem_t; -typedef struct uhash uhash_t; - -struct ulist -{ - ulist_t* next; - ulist_t* prev; -}; - -struct uitem -{ - ulist_t list; - intptr_t key; - void* val; -}; - -struct uhash -{ - uint16_t count; - uint16_t size; - ulist_t* items; -}; - -struct upoll -{ - int fd; /* backend fd (epoll, kqueue) */ - ulist_t alive; /* all notes this queue knows about */ - uhash_t* table; -}; - -struct unote -{ - upoll_event_t event; - intptr_t fd; - ulist_t queue; /* handle for the queue's notes */ - upoll_t* upoll; -}; - -#define container_of(ptr, type, member) \ - ((type*)((char*)(ptr)-offsetof(type, member))) - -#define ulist_init(q) \ - (q)->prev = q; \ - (q)->next = q - -#define ulist_head(h) (h)->next -#define ulist_next(q) (q)->next - -#define ulist_tail(h) (h)->prev -#define ulist_prev(q) (q)->prev - -#define ulist_empty(h) (h == (h)->prev) - -#define ulist_append(h, x) \ - (x)->prev = (h)->prev; \ - (x)->prev->next = x; \ - (x)->next = h; \ - (h)->prev = x - -#define ulist_insert(h, x) \ - (x)->next = (h)->next; \ - (x)->next->prev = x; \ - (x)->prev = h; \ - (h)->next = x - -#define ulist_remove(x) \ - (x)->next->prev = (x)->prev; \ - (x)->prev->next = (x)->next; \ - (x)->prev = x; \ - (x)->next = x - -#define ulist_mark(h) (h) - -#define ulist_scan(q, h) \ - for((q) = ulist_head(h); (q) != ulist_mark(h); (q) = ulist_next(q)) - -#define ulist_data(q, type, link) container_of(q, type, link) - -#endif /* _UPOLL_H_ */ diff --git a/win32-setup/Makefile b/win32-setup/Makefile index 8ad1632db..84b6acc59 100644 --- a/win32-setup/Makefile +++ b/win32-setup/Makefile @@ -71,6 +71,15 @@ tap-win32: mv tap-windows-9.21.2.7z tuntapv9_n6.7z wget https://snowlight.net/loki/win32-dist/tap-windows-9.9.2_3.7z mv tap-windows-9.9.2_3.7z tuntapv9.7z + +libuv: + git clone https://github.com/libuv/libuv.git + cd libuv; ./autogen.sh; ./configure --host=i686-w64-mingw32 --target=i686-w64-mingw32 CC=$(CC) CXX=$(CXX) CFLAGS="$(CFLAGS)" --disable-shared --prefix=$(PWD) + make -C libuv -j48 install + make -C libuv -j48 distclean + cd libuv; ./configure --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 CC=$(CC64) CXX=$(CXX64) CFLAGS="$(CFLAGS)" --disable-shared + make -C libuv -j48 + cp libuv/.libs/libuv.a $(PWD)/lib64 clean: -rm -rf curl-7* include lib mbedtls-2* *.exe *.dll *.pem *.7z