diff options
author | Alexander Chekunkov <chekunkov@gmail.com> | 2016-11-07 20:22:59 +0000 |
---|---|---|
committer | Garrett D'Amore <garrett@damore.org> | 2016-11-22 17:34:49 -0800 |
commit | 0665fb4b2e3b887e608282ff09cd5fcac0c9ba5b (patch) | |
tree | 4ec109aea6e42100138522713417784be3648c50 | |
parent | f5b0d1ab0217463c0b96fc37fc77ba5809e569f3 (diff) | |
download | nanomsg-0665fb4b2e3b887e608282ff09cd5fcac0c9ba5b.tar.gz |
Add NN_RCVMAXSIZE socket option implementation for 'ipc' transport
See nn_getsockopt man page for details.
Basic tests are in tests/ipc.c.
-rw-r--r-- | src/transports/ipc/sipc.c | 18 | ||||
-rw-r--r-- | tests/ipc.c | 37 |
2 files changed, 51 insertions, 4 deletions
diff --git a/src/transports/ipc/sipc.c b/src/transports/ipc/sipc.c index 204dc7a..0296073 100644 --- a/src/transports/ipc/sipc.c +++ b/src/transports/ipc/sipc.c @@ -209,6 +209,8 @@ static void nn_sipc_handler (struct nn_fsm *self, int src, int type, int rc; struct nn_sipc *sipc; uint64_t size; + int opt; + size_t opt_sz = sizeof (opt); sipc = nn_cont (self, struct nn_sipc, fsm); @@ -328,10 +330,22 @@ static void nn_sipc_handler (struct nn_fsm *self, int src, int type, switch (sipc->instate) { case NN_SIPC_INSTATE_HDR: - /* Message header was received. Allocate memory for the - message. */ + /* Message header was received. Check that message size + is acceptable by comparing with NN_RCVMAXSIZE; + if it's too large, drop the connection. */ nn_assert (sipc->inhdr [0] == NN_SIPC_MSG_NORMAL); size = nn_getll (sipc->inhdr + 1); + + nn_pipebase_getopt (&sipc->pipebase, NN_SOL_SOCKET, + NN_RCVMAXSIZE, &opt, &opt_sz); + + if (opt >= 0 && size > (unsigned)opt) { + sipc->state = NN_SIPC_STATE_DONE; + nn_fsm_raise (&sipc->fsm, &sipc->done, NN_SIPC_ERROR); + return; + } + + /* Allocate memory for the message. */ nn_msg_term (&sipc->inmsg); nn_msg_init (&sipc->inmsg, (size_t) size); diff --git a/tests/ipc.c b/tests/ipc.c index d086ffb..8a8f7cb 100644 --- a/tests/ipc.c +++ b/tests/ipc.c @@ -37,9 +37,10 @@ int main () int sc; int i; int s1, s2; -#if !defined(NN_HAVE_WINDOWS) + void * dummy_buf; int rc; -#endif + int opt; + size_t opt_sz = sizeof (opt); int size; char * buf; @@ -123,6 +124,38 @@ int main () test_close (s1); #endif + /* Test NN_RCVMAXSIZE limit */ + sb = test_socket (AF_SP, NN_PAIR); + test_bind (sb, SOCKET_ADDRESS); + s1 = test_socket (AF_SP, NN_PAIR); + test_connect (s1, SOCKET_ADDRESS); + opt = 4; + rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, opt_sz); + nn_assert (rc == 0); + nn_sleep (100); + test_send (s1, "ABCD"); + test_recv (sb, "ABCD"); + test_send (s1, "ABCDE"); + /* Without sleep nn_recv returns EAGAIN even for string + of acceptable size, so false positives are possible. */ + nn_sleep (100); + rc = nn_recv (sb, &dummy_buf, NN_MSG, NN_DONTWAIT); + nn_assert (rc < 0); + errno_assert (nn_errno () == EAGAIN); + test_close (sb); + test_close (s1); + + /* Test that NN_RCVMAXSIZE can be -1, but not lower */ + sb = test_socket (AF_SP, NN_PAIR); + opt = -1; + rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, opt_sz); + nn_assert (rc >= 0); + opt = -2; + rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, opt_sz); + nn_assert (rc < 0); + errno_assert (nn_errno () == EINVAL); + test_close (sb); + /* Test closing a socket that is waiting to connect. */ sc = test_socket (AF_SP, NN_PAIR); test_connect (sc, SOCKET_ADDRESS); |