Skip to content

Commit

Permalink
Create nng_socket_pair
Browse files Browse the repository at this point in the history
  • Loading branch information
gdamore committed Dec 26, 2023
1 parent 241b210 commit b6d8f8b
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 29 deletions.
7 changes: 7 additions & 0 deletions include/nng/supplemental/util/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ NNG_DECL void nng_cv_wake1(nng_cv *);
// nng_random returns a "strong" (cryptographic sense) random number.
NNG_DECL uint32_t nng_random(void);

// nng_socket_pair is used to create a bound pair of file descriptors
// typically using the socketpair() call. The descriptors are backed
// by reliable, bidirectional, byte streams. This will return NNG_ENOTSUP
// if the platform lacks support for this. The argument is a pointer
// to an array of file descriptors (or HANDLES or similar).
NNG_DECL int nng_socket_pair(int *);

#ifdef __cplusplus
}
#endif
Expand Down
17 changes: 15 additions & 2 deletions src/core/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,9 +386,9 @@ extern int nni_ipc_listener_alloc(nng_stream_listener **, const nng_url *);
typedef struct nni_plat_udp nni_plat_udp;

// nni_plat_udp_open initializes a UDP socket, binding to the local
// address specified specified in the AIO. The remote address is
// address specified in the AIO. The remote address is
// not used. The resulting nni_plat_udp structure is returned in the
// the aio's a_pipe.
// aio's a_pipe.
extern int nni_plat_udp_open(nni_plat_udp **, nni_sockaddr *);

// nni_plat_udp_close closes the underlying UDP socket.
Expand Down Expand Up @@ -434,6 +434,19 @@ extern void nni_plat_pipe_close(int, int);

extern int nni_plat_udp_sockname(nni_plat_udp *, nni_sockaddr *);

// nni_socket_pair is used to create a socket pair using socketpair()
// on POSIX systems. (Windows might provide a similar solution, using
// AF_UNIX at some point, in which case the arguments will actually be
// an array of HANDLEs.) If not supported, this returns NNG_ENOTSUP.
//
// This API can only create a pair of open file descriptors, suitable for use
// with the fdconn transport, each bound to the other. The transport must be
// a bidirectional reliable byte stream. This should be suitable for use
// in APIs to transport file descriptors, or across a fork/exec boundary (so
// that child processes may use these with fdconn to inherit a socket that is
// connected to the parent.)
extern int nni_socket_pair(int *);

//
// File/Store Support
//
Expand Down
4 changes: 3 additions & 1 deletion src/platform/posix/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright 2020 Staysail Systems, Inc. <[email protected]>
# Copyright 2023 Staysail Systems, Inc. <[email protected]>
#
# This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this
Expand Down Expand Up @@ -61,6 +61,7 @@ if (NNG_PLATFORM_POSIX)
nng_check_sym(LOCAL_PEERPID sys/un.h NNG_HAVE_LOCALPEERPID)
nng_check_sym(getpeerucred ucred.h NNG_HAVE_GETPEERUCRED)
nng_check_sym(atomic_flag_test_and_set stdatomic.h NNG_HAVE_STDATOMIC)
nng_check_sym(socketpair sys/socket.h NNG_HAVE_SOCKETPAIR)

nng_sources(
posix_impl.h
Expand All @@ -82,6 +83,7 @@ if (NNG_PLATFORM_POSIX)
posix_pipe.c
posix_resolv_gai.c
posix_sockaddr.c
posix_socketpair.c
posix_tcpconn.c
posix_tcpdial.c
posix_tcplisten.c
Expand Down
37 changes: 37 additions & 0 deletions src/platform/posix/posix_socketpair.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Copyright 2023 Staysail Systems, Inc. <[email protected]>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include "core/nng_impl.h"

#ifdef NNG_HAVE_SOCKETPAIR
// This provides an implementation of socketpair(), which is supposed
// to be present on XPG6 and newer. This trivial implementation
// only supports SOCK_STREAM over AF_UNIX. Which is sufficient for
// most purposes. The fds array should point to an int[2].
#include <errno.h>
#include <sys/socket.h>

int
nni_socket_pair(int *fds)
{
int rv;
rv = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
if (rv != 0) {
return (nni_plat_errno(errno));

Check warning on line 26 in src/platform/posix/posix_socketpair.c

View check run for this annotation

Codecov / codecov/patch

src/platform/posix/posix_socketpair.c#L26

Added line #L26 was not covered by tests
}

return (0);
}
#else
int
nni_socket_pair(int *fds)
{
return (NNG_ENOTSUP);
}
#endif
1 change: 1 addition & 0 deletions src/platform/windows/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ if (NNG_PLATFORM_WINDOWS)
win_rand.c
win_resolv.c
win_sockaddr.c
win_socketpair.c
win_tcp.c
win_tcpconn.c
win_tcpdial.c
Expand Down
37 changes: 37 additions & 0 deletions src/platform/windows/win_socketpair.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Copyright 2023 Staysail Systems, Inc. <[email protected]>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#include "core/nng_impl.h"


#ifdef NNG_HAVE_SOCKETPAIR_TODO
// TODO: Windows lacks socketpair. We can emulate it with an explcit
// implementation based on AF_UNIX.

#include <errno.h>
#include <sys/socket.h>

int
nni_socket_pair(int *fds)
{
int rv;
rv = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
if (rv != 0) {
return (nni_plat_errno(errno));
}

return (0);
}
#else
int
nni_socket_pair(int *fds)
{
return (NNG_ENOTSUP);
}
#endif
31 changes: 5 additions & 26 deletions src/sp/transport/fdconn/fdc_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,6 @@ test_fdc_connect_fail(void)
NUTS_CLOSE(s);
}

void
test_tcp_local_address_connect(void)
{

nng_socket s1;
nng_socket s2;
char addr[NNG_MAXADDRLEN];
uint16_t port;

NUTS_OPEN(s1);
NUTS_OPEN(s2);
port = nuts_next_port();
(void) snprintf(addr, sizeof(addr), "tcp://127.0.0.1:%u", port);
NUTS_PASS(nng_listen(s1, addr, NULL, 0));
(void) snprintf(
addr, sizeof(addr), "tcp://127.0.0.1;127.0.0.1:%u", port);
NUTS_PASS(nng_dial(s2, addr, NULL, 0));
NUTS_CLOSE(s2);
NUTS_CLOSE(s1);
}

void
test_fdc_malformed_address(void)
{
Expand All @@ -64,15 +43,14 @@ test_fdc_listen(void)
NUTS_CLOSE(s1);
}

#include <sys/socket.h>
void
test_fdc_accept(void)
{
nng_socket s1, s2;
nng_listener l;
int fds[2];

NUTS_PASS(socketpair(PF_UNIX, SOCK_STREAM, 0, fds));
NUTS_PASS(nng_socket_pair(fds));
// make sure we won't have to deal with SIGPIPE - EPIPE is better
signal(SIGPIPE, SIG_IGN);
NUTS_OPEN(s1);
Expand All @@ -93,7 +71,7 @@ test_fdc_exchange(void)
nng_listener l1, l2;
int fds[2];

NUTS_PASS(socketpair(PF_UNIX, SOCK_STREAM, 0, fds));
NUTS_PASS(nng_socket_pair(fds));
// make sure we won't have to deal with SIGPIPE - EPIPE is better
signal(SIGPIPE, SIG_IGN);
NUTS_OPEN(s1);
Expand Down Expand Up @@ -127,7 +105,7 @@ test_fdc_recv_max(void)
size_t sz;
int fds[2];

NUTS_PASS(socketpair(PF_UNIX, SOCK_STREAM, 0, fds));
NUTS_PASS(nng_socket_pair(fds));

NUTS_OPEN(s0);
NUTS_PASS(nng_socket_set_ms(s0, NNG_OPT_RECVTIMEO, 100));
Expand Down Expand Up @@ -157,11 +135,12 @@ NUTS_TESTS = {

{ "fdc connect fail", test_fdc_connect_fail },
{ "fdc malformed address", test_fdc_malformed_address },
#ifdef NNG_HAVE_SOCKETPAIR
{ "fdc listen", test_fdc_listen },
{ "fdc accept", test_fdc_accept },
{ "fdc exchange", test_fdc_exchange },
{ "fdc recv max", test_fdc_recv_max },
#endif

// { "fdc recv max", test_tcp_recv_max },
{ NULL, NULL },
};
6 changes: 6 additions & 0 deletions src/supplemental/util/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,9 @@ nng_random(void)
(void) nni_init();
return (nni_random());
}

int
nng_socket_pair(int *fds)
{
return (nni_socket_pair(fds));
}

0 comments on commit b6d8f8b

Please sign in to comment.