Hi, On Mon, Jan 17, 2022 at 4:51 AM Lev Stipakov <lstipa...@gmail.com> wrote:
> From: Lev Stipakov <l...@openvpn.net> > > tun_finalize() is essentially subset of socket_finalize() apart from: > > - using WSAFoo() functions instead of Foo() > > - "from" address is not returned > > There is no clear official statement that one can use non-WSA > API on handles, so let's be on a safe side and use both. > > Introduce sockethandle_t abstraction, which represents > socket and handle. Add SocketHandle* routines which call > proper API depends on underlying type in abstraction. > > Rename socket_finalize() to sockethandle_finalize(), take > sockethandle_t and new routines into use and kick tun_finalize(). > > Signed-off-by: Lev Stipakov <l...@openvpn.net> > --- > v3: replace macros with inline functions > > v2: explicitly initialize .is_handle to false for readablity > > > src/openvpn/forward.c | 3 +- > src/openvpn/socket.c | 37 ++++++++--------- > src/openvpn/socket.h | 49 ++++++++++++++++++---- > src/openvpn/tun.c | 94 +++++++++---------------------------------- > src/openvpn/tun.h | 34 +--------------- > 5 files changed, 80 insertions(+), 137 deletions(-) > > diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c > index f82386a1..a905f993 100644 > --- a/src/openvpn/forward.c > +++ b/src/openvpn/forward.c > @@ -1115,7 +1115,8 @@ read_incoming_tun(struct context *c) > } > else > { > - read_tun_buffered(c->c1.tuntap, &c->c2.buf); > + sockethandle_t sh = { .is_handle = true, .h = c->c1.tuntap->hand > }; > + sockethandle_finalize(sh, &c->c1.tuntap->reads, &c->c2.buf, NULL); > } > #else /* ifdef _WIN32 */ > ASSERT(buf_init(&c->c2.buf, FRAME_HEADROOM(&c->c2.frame))); > diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c > index df736746..780c5cb3 100644 > --- a/src/openvpn/socket.c > +++ b/src/openvpn/socket.c > @@ -3198,7 +3198,8 @@ link_socket_read_tcp(struct link_socket *sock, > if (!sock->stream_buf.residual_fully_formed) > { > #ifdef _WIN32 > - len = socket_finalize(sock->sd, &sock->reads, buf, NULL); > + sockethandle_t sh = { .s = sock->sd }; > + len = sockethandle_finalize(sh, &sock->reads, buf, NULL); > #else > struct buffer frag; > stream_buf_get_next(&sock->stream_buf, &frag); > @@ -3664,10 +3665,10 @@ socket_send_queue(struct link_socket *sock, struct > buffer *buf, const struct lin > } > > int > -socket_finalize(SOCKET s, > - struct overlapped_io *io, > - struct buffer *buf, > - struct link_socket_actual *from) > +sockethandle_finalize(sockethandle_t sh, > + struct overlapped_io *io, > + struct buffer *buf, > + struct link_socket_actual *from) > { > int ret = -1; > BOOL status; > @@ -3675,13 +3676,7 @@ socket_finalize(SOCKET s, > switch (io->iostate) > { > case IOSTATE_QUEUED: > - status = WSAGetOverlappedResult( > - s, > - &io->overlapped, > - &io->size, > - FALSE, > - &io->flags > - ); > + status = SocketHandleGetOverlappedResult(sh, io); > if (status) > { > /* successful return for a queued operation */ > @@ -3693,18 +3688,18 @@ socket_finalize(SOCKET s, > io->iostate = IOSTATE_INITIAL; > ASSERT(ResetEvent(io->overlapped.hEvent)); > > - dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion success > [%d]", ret); > + dmsg(D_WIN32_IO, "WIN32 I/O: Completion success [%d]", > ret); > } > else > { > /* error during a queued operation */ > ret = -1; > - if (WSAGetLastError() != WSA_IO_INCOMPLETE) > + if (SocketHandleGetLastError(sh) != ERROR_IO_INCOMPLETE) > WSA_IO_INCOMPLETE is the same as ERROR_IO_INCOMPLETE, so using them interchangeably looks ok. { > /* if no error (i.e. just not finished yet), then > DON'T execute this code */ > io->iostate = IOSTATE_INITIAL; > ASSERT(ResetEvent(io->overlapped.hEvent)); > - msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Socket > Completion error"); > + msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Completion > error"); > } > } > break; > @@ -3715,9 +3710,9 @@ socket_finalize(SOCKET s, > if (io->status) > { > /* error return for a non-queued operation */ > - WSASetLastError(io->status); > + SocketHandleSetLastError(sh, io->status); > ret = -1; > - msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Socket Completion > non-queued error"); > + msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Completion > non-queued error"); > } > else > { > @@ -3727,14 +3722,14 @@ socket_finalize(SOCKET s, > *buf = io->buf; > } > ret = io->size; > - dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion non-queued > success [%d]", ret); > + dmsg(D_WIN32_IO, "WIN32 I/O: Completion non-queued > success [%d]", ret); > } > break; > > case IOSTATE_INITIAL: /* were we called without proper queueing? > */ > - WSASetLastError(WSAEINVAL); > + SocketHandleSetInvalError(sh); > ret = -1; > - dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion BAD STATE"); > + dmsg(D_WIN32_IO, "WIN32 I/O: Completion BAD STATE"); > break; > > default: > @@ -3742,7 +3737,7 @@ socket_finalize(SOCKET s, > } > > /* return from address if requested */ > - if (from) > + if (!sh.is_handle && from) > { > if (ret >= 0 && io->addr_defined) > { > diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h > index cc1e0c36..77c3d720 100644 > --- a/src/openvpn/socket.h > +++ b/src/openvpn/socket.h > @@ -262,11 +262,44 @@ int socket_send_queue(struct link_socket *sock, > struct buffer *buf, > const struct link_socket_actual *to); > > -int socket_finalize( > - SOCKET s, > - struct overlapped_io *io, > - struct buffer *buf, > - struct link_socket_actual *from); > +typedef struct { > + union { > + SOCKET s; > + HANDLE h; > + }; > + bool is_handle; > +} sockethandle_t; > + > +int sockethandle_finalize(sockethandle_t sh, > + struct overlapped_io *io, > + struct buffer *buf, > + struct link_socket_actual *from); > + > +static inline BOOL > +SocketHandleGetOverlappedResult(sockethandle_t sh, struct overlapped_io > *io) > +{ > + return sh.is_handle ? > + GetOverlappedResult(sh.h, &io->overlapped, &io->size, FALSE) : > + WSAGetOverlappedResult(sh.s, &io->overlapped, &io->size, FALSE, > &io->flags); > +} > + > +static inline int > +SocketHandleGetLastError(sockethandle_t sh) > +{ > + return sh.is_handle ? (int)GetLastError() : WSAGetLastError(); > +} > + > +inline static void > +SocketHandleSetLastError(sockethandle_t sh, DWORD err) > +{ > + sh.is_handle ? SetLastError(err) : WSASetLastError(err); > To be consistent, one could add an explicit cast here too and avoid a potential compiler warning: WSASetLastError((int) err); > +} > + > +static inline void > +SocketHandleSetInvalError(sockethandle_t sh) > +{ > + sh.is_handle ? SetLastError(ERROR_INVALID_FUNCTION) : > WSASetLastError(WSAEINVAL); > +} > I'm not sure whether ERROR_INVALID_FUNCTION is the appropriate error code here. WSAEINVAL is more like invalid-argument (so ERROR_BAD_ARGUMENTS?). But this agrees with the original, so let it be. > > #else /* ifdef _WIN32 */ > > @@ -1020,7 +1053,8 @@ link_socket_read_udp_win32(struct link_socket *sock, > struct buffer *buf, > struct link_socket_actual *from) > { > - return socket_finalize(sock->sd, &sock->reads, buf, from); > + sockethandle_t sh = { .s = sock->sd }; > + return sockethandle_finalize(sh, &sock->reads, buf, from); > } > > #else /* ifdef _WIN32 */ > @@ -1078,9 +1112,10 @@ link_socket_write_win32(struct link_socket *sock, > { > int err = 0; > int status = 0; > + sockethandle_t sh = { .s = sock->sd }; > if (overlapped_io_active(&sock->writes)) > { > - status = socket_finalize(sock->sd, &sock->writes, NULL, NULL); > + status = sockethandle_finalize(sh, &sock->writes, NULL, NULL); > if (status < 0) > { > err = WSAGetLastError(); > diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c > index 12bdd200..fe32127b 100644 > --- a/src/openvpn/tun.c > +++ b/src/openvpn/tun.c > @@ -3561,87 +3561,29 @@ tun_write_queue(struct tuntap *tt, struct buffer > *buf) > } > > int > -tun_finalize( > - HANDLE h, > - struct overlapped_io *io, > - struct buffer *buf) > +tun_write_win32(struct tuntap *tt, struct buffer *buf) > { > - int ret = -1; > - BOOL status; > - > - switch (io->iostate) > + int err = 0; > + int status = 0; > + if (overlapped_io_active(&tt->writes)) > { > - case IOSTATE_QUEUED: > - status = GetOverlappedResult( > - h, > - &io->overlapped, > - &io->size, > - FALSE > - ); > - if (status) > - { > - /* successful return for a queued operation */ > - if (buf) > - { > - *buf = io->buf; > - } > - ret = io->size; > - io->iostate = IOSTATE_INITIAL; > - ASSERT(ResetEvent(io->overlapped.hEvent)); > - dmsg(D_WIN32_IO, "WIN32 I/O: TAP Completion success > [%d]", ret); > - } > - else > - { > - /* error during a queued operation */ > - ret = -1; > - if (GetLastError() != ERROR_IO_INCOMPLETE) > - { > - /* if no error (i.e. just not finished yet), > - * then DON'T execute this code */ > - io->iostate = IOSTATE_INITIAL; > - ASSERT(ResetEvent(io->overlapped.hEvent)); > - msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion > error"); > - } > - } > - break; > - > - case IOSTATE_IMMEDIATE_RETURN: > - io->iostate = IOSTATE_INITIAL; > - ASSERT(ResetEvent(io->overlapped.hEvent)); > - if (io->status) > - { > - /* error return for a non-queued operation */ > - SetLastError(io->status); > - ret = -1; > - msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion > non-queued error"); > - } > - else > - { > - /* successful return for a non-queued operation */ > - if (buf) > - { > - *buf = io->buf; > - } > - ret = io->size; > - dmsg(D_WIN32_IO, "WIN32 I/O: TAP Completion non-queued > success [%d]", ret); > - } > - break; > - > - case IOSTATE_INITIAL: /* were we called without proper queueing? > */ > - SetLastError(ERROR_INVALID_FUNCTION); > - ret = -1; > - dmsg(D_WIN32_IO, "WIN32 I/O: TAP Completion BAD STATE"); > - break; > - > - default: > - ASSERT(0); > + sockethandle_t sh = { .is_handle = true, .h = tt->hand }; > + status = sockethandle_finalize(sh, &tt->writes, NULL, NULL); > + if (status < 0) > + { > + err = GetLastError(); > + } > } > - > - if (buf) > + tun_write_queue(tt, buf); > + if (status < 0) > { > - buf->len = ret; > + SetLastError(err); > + return status; > + } > + else > + { > + return BLEN(buf); > } > - return ret; > } > > static const struct device_instance_id_interface * > diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h > index d4657537..a6661be0 100644 > --- a/src/openvpn/tun.h > +++ b/src/openvpn/tun.h > @@ -437,8 +437,6 @@ int tun_read_queue(struct tuntap *tt, int maxsize); > > int tun_write_queue(struct tuntap *tt, struct buffer *buf); > > -int tun_finalize(HANDLE h, struct overlapped_io *io, struct buffer *buf); > - > static inline bool > tuntap_stop(int status) > { > @@ -466,36 +464,8 @@ tuntap_abort(int status) > return false; > } > > -static inline int > -tun_write_win32(struct tuntap *tt, struct buffer *buf) > -{ > - int err = 0; > - int status = 0; > - if (overlapped_io_active(&tt->writes)) > - { > - status = tun_finalize(tt->hand, &tt->writes, NULL); > - if (status < 0) > - { > - err = GetLastError(); > - } > - } > - tun_write_queue(tt, buf); > - if (status < 0) > - { > - SetLastError(err); > - return status; > - } > - else > - { > - return BLEN(buf); > - } > -} > - > -static inline int > -read_tun_buffered(struct tuntap *tt, struct buffer *buf) > -{ > - return tun_finalize(tt->hand, &tt->reads, buf); > -} > +int > +tun_write_win32(struct tuntap *tt, struct buffer *buf); > Antonio wanted this to be in one line though we are not terribly consistent about this. > static inline ULONG > wintun_ring_packet_align(ULONG size) > In spite of those nits meant to annoy the author, I think this looks good. Acked-by: Selva Nair <selva.n...@gmail.com>
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel