diff --git a/CHANGES b/CHANGES index 225a8cd..ac17961 100644 --- a/CHANGES +++ b/CHANGES @@ -49,6 +49,9 @@ Features: queue before starting to transfer data. Test: LINUX_POSIXMQ_FLUSH + New options posixmq-maxmsg, posixmq-msgsize. + Tests: POSIXMQ_MAXMSG POSIXMQ_MSGSIZE + Building: Disabling certain features during configure could break build process. diff --git a/doc/socat.yo b/doc/socat.yo index a478fbb..3786ebd 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -2168,7 +2168,7 @@ label(OPTION_NETNS)dit(bf(tt(netns=<net-namespace-name>))) Before opening the address it tries to switch to the named network namespace. After opening the address it switches back to the previous namespace. (link(Example with TCP forwarder)(EXAMPLE_OPTION_NETNS), - link(example with virtual network connection)(EXAMPLE_TUN_NETNS).nl() + link(example with virtual network connection)(EXAMPLE_TUN_NETNS)).nl() Only on Linux; requires root; use option tt(--experimental).nl() enddit() @@ -3495,6 +3495,14 @@ label(OPTION_POSIXMQ_PRIORITY)dit(bf(tt(posixmq-priority (mq-prio)))) label(OPTION_POSIXMQ_FLUSH)dit(bf(tt(posixmq-flush (mq-flush)))) "Consumes" (drops) all messages currently in the queue before starting transfers. +label(OPTION_POSIXMQ_MAXMSG)dit(bf(tt(posixmq-maxmsg (mq-maxmsg)))) + Sets the maxmsg parameter of the POSIX message queue when creating it. + Note: You need root or CAP_SYS_RESOURCE to exceed the default value + (<tt>/proc/sys/fs/mqueue/msg_default</tt>). +label(OPTION_POSIXMQ_MSGSIZE)dit(bf(tt(posixmq-msgsize (mq-msgsize)))) + Sets the msgsize parameter of the POSIX message queue when creating it. + Note: You need root or CAP_SYS_RESOURCE to exceed the default value + (<tt>/proc/sys/fs/mqueue/msgsize_default</tt>). enddit() diff --git a/test.sh b/test.sh index 7dcb0da..3bc44e8 100755 --- a/test.sh +++ b/test.sh @@ -15106,8 +15106,8 @@ tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" -CMD0="$TRACE $SOCAT $opts TCP4-LISTEN:$PORT,reuseaddr EXEC:'$FILAN -s',nofork" -CMD1="$TRACE $SOCAT $opts -t $T4 - TCP4:localhost:$PORT" +CMD0="$TRACE $SOCAT $opts -t $T4 TCP4-LISTEN:$PORT,reuseaddr EXEC:'$FILAN -s',nofork" +CMD1="$TRACE $SOCAT $opts -t $T8 - TCP4:localhost:$PORT" printf "test $F_n $TEST... " $N eval "$CMD0" >/dev/null 2>"${te}0" & pid0=$! diff --git a/xio-posixmq.c b/xio-posixmq.c index 5168781..ff5842d 100644 --- a/xio-posixmq.c +++ b/xio-posixmq.c @@ -25,8 +25,10 @@ const struct addrdesc xioaddr_posixmq_read = { "POSIXMQ-READ", 1+XIO const struct addrdesc xioaddr_posixmq_receive = { "POSIXMQ-RECEIVE", 1+XIO_RDONLY, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD, XIO_RDONLY, XIOREAD_RECV_ONESHOT, 0 HELP(":<mqname>") }; const struct addrdesc xioaddr_posixmq_send = { "POSIXMQ-SEND", 1+XIO_WRONLY, xioopen_posixmq, GROUP_FD|GROUP_NAMED|GROUP_POSIXMQ|GROUP_RETRY|GROUP_CHILD, XIO_WRONLY, 0, 0 HELP(":<mqname>") }; -const struct optdesc opt_posixmq_priority = { "posixmq-priority", "mq-pri", OPT_POSIXMQ_PRIORITY, GROUP_POSIXMQ, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.posixmq.prio), XIO_SIZEOF(para.posixmq.prio), 0 }; +const struct optdesc opt_posixmq_priority = { "posixmq-priority", "mq-prio", OPT_POSIXMQ_PRIORITY, GROUP_POSIXMQ, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.posixmq.prio), XIO_SIZEOF(para.posixmq.prio), 0 }; const struct optdesc opt_posixmq_flush = { "posixmq-flush", "mq-flush", OPT_POSIXMQ_FLUSH, GROUP_POSIXMQ, PH_EARLY, TYPE_BOOL, OFUNC_SPEC, 0, 0, 0 }; +const struct optdesc opt_posixmq_maxmsg = { "posixmq-maxmsg", "mq-maxmsg", OPT_POSIXMQ_MAXMSG, GROUP_POSIXMQ, PH_OPEN, TYPE_LONG, OFUNC_SPEC, 0, 0, 0 }; +const struct optdesc opt_posixmq_msgsize = { "posixmq-msgsize", "mq-msgsize", OPT_POSIXMQ_MSGSIZE, GROUP_POSIXMQ, PH_OPEN, TYPE_LONG, OFUNC_SPEC, 0, 0, 0 }; /* _read(): open immediately, stay in transfer loop _recv(): wait until data (how we know there is??), oneshot, opt.fork @@ -47,11 +49,12 @@ static int xioopen_posixmq( bool opt_unlink_early = false; bool nonblock = 0; bool flush = false; + struct mq_attr attr = { 0 }; + bool setopts = false; int oflag; bool opt_o_excl = false; mode_t opt_mode = 0666; mqd_t mqd; - struct mq_attr attr; int _errno; bool dofork = false; int maxchildren = 0; @@ -100,6 +103,47 @@ static int xioopen_posixmq( retropt_bool(opts, OPT_O_EXCL, &opt_o_excl); retropt_mode(opts, OPT_PERM, &opt_mode); retropt_bool(opts, OPT_POSIXMQ_FLUSH, &flush); + retropt_long(opts, OPT_POSIXMQ_MAXMSG, &attr.mq_maxmsg) || + (setopts = true); + retropt_long(opts, OPT_POSIXMQ_MSGSIZE, &attr.mq_msgsize) || + (setopts = true); + + /* When only one of mq-maxmsg and mq-msgsize options has been provided, + we must nevertheless set the other option value in strucht mq_attr. + For this we have to find the default, read it from /proc fs */ + if (setopts) { + int pfd; + const static char *PROC_MAXMSG = "/proc/sys/fs/mqueue/msg_default"; + const static char *PROC_MSGSIZE = "/proc/sys/fs/mqueue/msgsize_default"; + char buff[21]; /* fit a 64bit num in decimal */ + ssize_t bytes; + + if (attr.mq_maxmsg == 0) { + if ((pfd = Open(PROC_MAXMSG, O_RDONLY, 0)) < 0) { + Warn2("open(\"%s\", O_RDONLY, 0): %s", PROC_MAXMSG, strerror(errno)); + } else if ((bytes = Read(pfd, buff, sizeof(buff)-1)) < 0) { + Warn4("read(%d /* \"%s\" */, buff, "F_Zd"): %s", + pfd, PROC_MAXMSG, sizeof(buff)-1, strerror (errno)); + Close(pfd); + } else { + sscanf(buff, "%ld", &attr.mq_maxmsg); + Close(pfd); + } + } + + if (attr.mq_msgsize == 0) { + if ((pfd = Open(PROC_MSGSIZE, O_RDONLY, 0)) < 0) { + Warn2("open(\"%s\", O_RDONLY, 0): %s", PROC_MSGSIZE, strerror(errno)); + } else if ((bytes = Read(pfd, buff, sizeof(buff)-1)) < 0) { + Warn4("read(%d /* \"%s\" */, buff, "F_Zd"): %s", + pfd, PROC_MSGSIZE, sizeof(buff)-1, strerror (errno)); + Close(pfd); + } else { + sscanf(buff, "%ld", &attr.mq_msgsize); + Close(pfd); + } + } + } retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); if (opt_unlink_early) { @@ -126,12 +170,18 @@ static int xioopen_posixmq( } /* Now open the message queue */ - Debug3("mq_open(\"%s\", %d, "F_mode", NULL)", name, oflag, opt_mode); - mqd = mq_open(name, oflag, opt_mode, NULL); + if (setopts) + Debug8("%s: mq_open(\"%s\", "F_mode", "F_mode", {flags=%ld, maxmsg=%ld, msgsize=%ld, curmsgs=%ld} )", argv[0], name, oflag, opt_mode, attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs); + else + Debug4("%s: mq_open(\"%s\", "F_mode", "F_mode", NULL)", argv[0], name, oflag, opt_mode); + mqd = mq_open(name, oflag, opt_mode, setopts ? &attr : NULL); _errno = errno; Debug1("mq_open() -> %d", mqd); if (mqd < 0) { - Error3("%s: mq_open(\"%s\"): %s", argv[0], name, strerror(errno)); + if (setopts) + Error9("%s: mq_open(\"%s\", "F_mode", "F_mode", {flags=%ld, maxmsg=%ld, msgsize=%ld, curmsgs=%ld} ): %s", argv[0], name, oflag, opt_mode, attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs, strerror(errno)); + else + Error5("%s: mq_open(\"%s\", "F_mode", "F_mode", NULL): %s", argv[0], name, oflag, opt_mode, strerror(errno)); errno = _errno; return STAT_RETRYLATER; } diff --git a/xio-posixmq.h b/xio-posixmq.h index b7242e0..4779f1a 100644 --- a/xio-posixmq.h +++ b/xio-posixmq.h @@ -10,6 +10,8 @@ extern const struct addrdesc xioaddr_posixmq_read; extern const struct addrdesc xioaddr_posixmq_receive; extern const struct addrdesc xioaddr_posixmq_send; +extern const struct optdesc opt_posixmq_maxmsg; +extern const struct optdesc opt_posixmq_msgsize; extern const struct optdesc opt_posixmq_priority; extern const struct optdesc opt_posixmq_flush; diff --git a/xioopts.c b/xioopts.c index 3824014..0f48c40 100644 --- a/xioopts.c +++ b/xioopts.c @@ -1032,8 +1032,10 @@ const struct optname optionnames[] = { #endif IF_ANY ("mode", &opt_perm) #if WITH_POSIXMQ - IF_ANY ("mq-flush", &opt_posixmq_flush) - IF_ANY ("mq-prio", &opt_posixmq_priority) + IF_ANY ("mq-flush", &opt_posixmq_flush) + IF_ANY ("mq-maxmsg", &opt_posixmq_maxmsg) + IF_ANY ("mq-msgsize", &opt_posixmq_msgsize) + IF_ANY ("mq-prio", &opt_posixmq_priority) #endif #ifdef TCP_MAXSEG IF_TCP ("mss", &opt_tcp_maxseg) @@ -1350,6 +1352,8 @@ const struct optname optionnames[] = { #endif #if WITH_POSIXMQ IF_ANY ("posixmq-flush", &opt_posixmq_flush) + IF_ANY ("posixmq-maxmsg", &opt_posixmq_maxmsg) + IF_ANY ("posixmq-msgsize", &opt_posixmq_msgsize) IF_ANY ("posixmq-priority", &opt_posixmq_priority) #endif #if (WITH_IP4 || WITH_IP6) && HAVE_RESOLV_H && WITH_RES_PRIMARY diff --git a/xioopts.h b/xioopts.h index 4796fb2..2cdd3ac 100644 --- a/xioopts.h +++ b/xioopts.h @@ -483,6 +483,8 @@ enum e_optcode { OPT_MAX_CHILDREN, #if WITH_POSIXMQ OPT_POSIXMQ_FLUSH, + OPT_POSIXMQ_MAXMSG, + OPT_POSIXMQ_MSGSIZE, OPT_POSIXMQ_PRIORITY, #endif #ifdef NLDLY