summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Chekunkov <chekunkov@gmail.com>2016-11-07 20:22:59 +0000
committerGarrett D'Amore <garrett@damore.org>2016-11-22 17:34:49 -0800
commit0665fb4b2e3b887e608282ff09cd5fcac0c9ba5b (patch)
tree4ec109aea6e42100138522713417784be3648c50
parentf5b0d1ab0217463c0b96fc37fc77ba5809e569f3 (diff)
downloadnanomsg-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.c18
-rw-r--r--tests/ipc.c37
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);