mirror of https://github.com/oxen-io/lokinet
Merge branch 'master' into debian/sid
commit
823d86875a
@ -1,69 +0,0 @@
|
||||
#ifndef _UP_H_
|
||||
#define _UP_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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_ */
|
@ -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 <ncm@cantrip.org>
|
||||
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 <kinetik@flim.org>)
|
||||
* 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
|
@ -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 <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
// 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 <io.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <wspiapi.h>
|
||||
|
||||
#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_ */
|
Loading…
Reference in New Issue