@ -14,25 +14,18 @@ namespace llarp
{
llarp_udp_io * udp ;
// we receive queued data in the OVERLAPPED data field,
// much like the pipefds in the UNIX kqueue and loonix
// epoll handles
WSAOVERLAPPED portfd [ 2 ] ;
udp_listener ( SOCKET fd , llarp_udp_io * u ) : ev_io ( fd ) , udp ( u )
{
memset ( ( void * ) & portfd [ 0 ] , 0 , sizeof ( WSAOVERLAPPED ) * 2 ) ;
} ;
udp_listener ( SOCKET fd , llarp_udp_io * u ) : ev_io ( fd ) , udp ( u ) { } ;
~ udp_listener ( )
{
}
virtual void
bool
tick ( )
{
if ( udp - > tick )
udp - > tick ( udp ) ;
return true ;
}
virtual int
@ -95,7 +88,7 @@ namespace llarp
device * tunif ;
OVERLAPPED * tun_async [ 2 ] ;
tun ( llarp_tun_io * tio )
: ev_io ( INVALID_HANDLE_VALUE )
: ev_io ( INVALID_HANDLE_VALUE , new LossyWriteQueue_t ( " tun_write_queue " ) )
, t ( tio )
, tunif ( tuntap_init ( ) )
@ -119,11 +112,13 @@ namespace llarp
ev_io : : flush_write ( ) ;
}
void
bool
tick ( )
{
if ( t - > tick )
t - > tick ( t ) ;
flush_write ( ) ;
return true ;
}
bool
@ -136,9 +131,10 @@ namespace llarp
read ( void * buf , size_t sz )
{
ssize_t ret = tuntap_read ( tunif , buf , sz ) ;
if ( ret > 4 & & t - > recvpkt )
if ( ret > 0 & & t - > recvpkt )
// should have pktinfo
t - > recvpkt ( t , ( ( byte_t * ) buf ) + 4 , ret - 4 ) ;
// I have no idea...
t - > recvpkt ( t , ( byte_t * ) buf , ret ) ;
return ret ;
}
@ -192,6 +188,7 @@ struct llarp_win32_loop : public llarp_ev_loop
{
if ( iocpfd ! = INVALID_HANDLE_VALUE )
: : CloseHandle ( iocpfd ) ;
iocpfd = INVALID_HANDLE_VALUE ;
}
bool
@ -212,7 +209,7 @@ struct llarp_win32_loop : public llarp_ev_loop
{
// The only field we really care about is
// the listener_id, as it contains the address
// of the udp_listener instance.
// of the ev_io instance.
DWORD iolen = 0 ;
// ULONG_PTR is guaranteed to be the same size
// as an arch-specific pointer value
@ -224,13 +221,19 @@ struct llarp_win32_loop : public llarp_ev_loop
if ( result & & qdata )
{
llarp : : udp_listener * ev = reinterpret_cast < llarp : : udp_listener * > ( ev_id ) ;
llarp : : ev_io * ev = reinterpret_cast < llarp : : ev_io * > ( ev_id ) ;
if ( ev )
{
llarp : : LogDebug ( " size: " , iolen , " \t ev_id: " , ev_id ,
" \t qdata: " , qdata ) ;
if ( iolen < = sizeof ( readbuf ) )
if ( ev - > write )
{
ev - > flush_write ( ) ;
}
else
{
ev - > read ( readbuf , iolen ) ;
}
}
+ + idx ;
}
@ -286,6 +289,44 @@ struct llarp_win32_loop : public llarp_ev_loop
return result ;
}
llarp : : ev_io *
bind_tcp ( llarp_tcp_acceptor * tcp , const sockaddr * bindaddr )
{
DWORD on = 1 ;
SOCKET fd = : : socket ( bindaddr - > sa_family , SOCK_STREAM , 0 ) ;
if ( fd = = INVALID_SOCKET )
return nullptr ;
socklen_t sz = sizeof ( sockaddr_in ) ;
if ( bindaddr - > sa_family = = AF_INET6 )
{
sz = sizeof ( sockaddr_in6 ) ;
}
// keep. inexplicably, windows now has unix domain sockets
// for now, use the ID numbers directly until this comes out of
// beta
else if ( bindaddr - > sa_family = = AF_UNIX )
{
sz = 110 ; // current size in 10.0.17763, verify each time the beta PSDK
// is updated
}
if ( : : bind ( fd , bindaddr , sz ) = = SOCKET_ERROR )
{
: : closesocket ( fd ) ;
return nullptr ;
}
if ( : : listen ( fd , 5 ) = = SOCKET_ERROR )
{
: : closesocket ( fd ) ;
return nullptr ;
}
llarp : : ev_io * serv = new llarp : : tcp_serv ( this , fd , tcp ) ;
tcp - > impl = serv ;
// We're non-blocking now, but can't really make use of it
// until we cut over to WSA* functions
ioctlsocket ( fd , FIONBIO , & on ) ;
return serv ;
}
SOCKET
udp_bind ( const sockaddr * addr )
{
@ -339,11 +380,29 @@ struct llarp_win32_loop : public llarp_ev_loop
bool
close_ev ( llarp : : ev_io * ev )
{
// On Windows, just close the socket to decrease the iocp refcount
// On Windows, just close the descriptor to decrease the iocp refcount
// and stop any pending I/O
BOOL stopped =
: : CancelIo ( reinterpret_cast < HANDLE > ( std : : get < SOCKET > ( ev - > fd ) ) ) ;
return closesocket ( std : : get < SOCKET > ( ev - > fd ) ) = = 0 & & stopped = = TRUE ;
BOOL stopped ;
int close_fd ;
switch ( ev - > fd . index ( ) )
{
case 0 :
stopped =
: : CancelIo ( reinterpret_cast < HANDLE > ( std : : get < SOCKET > ( ev - > fd ) ) ) ;
close_fd = closesocket ( std : : get < SOCKET > ( ev - > fd ) ) ;
break ;
case 1 :
stopped = : : CancelIo ( std : : get < HANDLE > ( ev - > fd ) ) ;
close_fd = CloseHandle ( std : : get < HANDLE > ( ev - > fd ) ) ;
if ( close_fd )
close_fd = 0 ; // must be zero
else
close_fd = 1 ;
break ;
default :
return false ;
}
return close_fd = = 0 & & stopped = = TRUE ;
}
llarp : : ev_io *
@ -372,23 +431,53 @@ struct llarp_win32_loop : public llarp_ev_loop
add_ev ( llarp : : ev_io * ev , bool write )
{
uint8_t buf [ 1024 ] ;
llarp : : udp_listener * udp = nullptr ;
llarp : : tun * t = nullptr ;
ev - > listener_id = reinterpret_cast < ULONG_PTR > ( ev ) ;
llarp : : tun * t = nullptr ;
ev - > listener_id = reinterpret_cast < ULONG_PTR > ( ev ) ;
memset ( & buf , 0 , 1024 ) ;
if ( ev - > isTCP )
{
if ( ! : : CreateIoCompletionPort ( ( HANDLE ) std : : get < SOCKET > ( ev - > fd ) , iocpfd ,
ev - > listener_id , 0 ) )
{
delete ev ;
return false ;
}
if ( write )
{
: : WriteFile ( ( HANDLE ) std : : get < SOCKET > ( ev - > fd ) , & buf , 1024 , nullptr ,
& ev - > portfd [ 1 ] ) ;
ev - > write = true ;
}
else
{
: : ReadFile ( ( HANDLE ) std : : get < SOCKET > ( ev - > fd ) , & buf , 1024 , nullptr ,
& ev - > portfd [ 0 ] ) ;
}
handlers . emplace_back ( ev ) ;
return true ;
}
switch ( ev - > fd . index ( ) )
{
case 0 :
udp = dynamic_cast < llarp : : udp_listener * > ( ev ) ;
if ( ! : : CreateIoCompletionPort ( ( HANDLE ) std : : get < 0 > ( ev - > fd ) , iocpfd ,
ev - > listener_id , 0 ) )
{
delete ev ;
return false ;
}
: : ReadFile ( ( HANDLE ) std : : get < 0 > ( ev - > fd ) , & buf , 1024 , nullptr ,
& udp - > portfd [ 0 ] ) ;
if ( write )
{
: : WriteFile ( ( HANDLE ) std : : get < 0 > ( ev - > fd ) , & buf , 1024 , nullptr ,
& ev - > portfd [ 1 ] ) ;
ev - > write = true ;
}
else
{
: : ReadFile ( ( HANDLE ) std : : get < 0 > ( ev - > fd ) , & buf , 1024 , nullptr ,
& ev - > portfd [ 0 ] ) ;
}
break ;
case 1 :
t = dynamic_cast < llarp : : tun * > ( ev ) ;
@ -398,7 +487,17 @@ struct llarp_win32_loop : public llarp_ev_loop
delete ev ;
return false ;
}
: : ReadFile ( std : : get < 1 > ( ev - > fd ) , & buf , 1024 , nullptr , t - > tun_async [ 0 ] ) ;
if ( write )
{
: : WriteFile ( std : : get < 1 > ( ev - > fd ) , & buf , 1024 , nullptr ,
t - > tun_async [ 1 ] ) ;
ev - > write = true ;
}
else
{
: : ReadFile ( std : : get < 1 > ( ev - > fd ) , & buf , 1024 , nullptr ,
t - > tun_async [ 0 ] ) ;
}
break ;
default :
return false ;
@ -415,10 +514,18 @@ struct llarp_win32_loop : public llarp_ev_loop
static_cast < llarp : : udp_listener * > ( l - > impl ) ;
if ( listener )
{
ret = close_ev ( listener ) ;
close_ev ( listener ) ;
// remove handler
auto itr = handlers . begin ( ) ;
while ( itr ! = handlers . end ( ) )
{
if ( itr - > get ( ) = = listener )
itr = handlers . erase ( itr ) ;
else
+ + itr ;
}
l - > impl = nullptr ;
delete listener ;
ret = true ;
ret = true ;
}
return ret ;
}
@ -432,7 +539,12 @@ struct llarp_win32_loop : public llarp_ev_loop
void
stop ( )
{
// still does nothing
// Are we leaking any file descriptors?
// This was part of the reason I had this
// in the destructor.
if ( iocpfd ! = INVALID_HANDLE_VALUE )
: : CloseHandle ( iocpfd ) ;
iocpfd = INVALID_HANDLE_VALUE ;
}
} ;