mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
New options so-rcvtimeo, so-sndtimeo
This commit is contained in:
parent
2db04378ae
commit
9faf068949
7 changed files with 139 additions and 24 deletions
5
CHANGES
5
CHANGES
|
@ -32,6 +32,11 @@ Features:
|
|||
|
||||
Added Info log of resulting OpenSSL max fragment length.
|
||||
|
||||
Implemented options rcvtimeo and sndtimeo, the first of which may be
|
||||
useful to prevent endlessly hanging DTLS connection etablishment.
|
||||
Test: RCVTIMEO_DTLS
|
||||
Feature proposed by Vladimir Nikishkin.
|
||||
|
||||
Corrections:
|
||||
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
||||
0, its last sent data might have been lost depending on timing of read/
|
||||
|
|
20
doc/socat.yo
20
doc/socat.yo
|
@ -608,7 +608,8 @@ label(ADDRESS_OPENSSL_DTLS_CLIENT)dit(bf(tt(OPENSSL-DTLS-CLIENT:<host>:<port>)))
|
|||
link(bind)(OPTION_BIND),
|
||||
link(pf)(OPTION_PROTOCOL_FAMILY),
|
||||
link(sourceport)(OPTION_SOURCEPORT),
|
||||
link(retry)(OPTION_RETRY)nl()
|
||||
link(retry)(OPTION_RETRY),
|
||||
link(rcvtimeo)(OPTION_SO_RCVTIMOE)nl()
|
||||
See also:
|
||||
link(OPENSSL-DTLS-SERVER)(ADDRESS_OPENSSL_DTLS_SERVER),
|
||||
link(OPENSSL-CONNECT)(ADDRESS_OPENSSL_CONNECT),
|
||||
|
@ -644,6 +645,7 @@ label(ADDRESS_OPENSSL_DTLS_SERVER)dit(bf(tt(OPENSSL-DTLS-SERVER:<port>)))
|
|||
link(su)(OPTION_SUBSTUSER),
|
||||
link(reuseaddr)(OPTION_REUSEADDR),
|
||||
link(retry)(OPTION_RETRY)nl()
|
||||
link(rcvtimeo)(OPTION_SO_RCVTIMOE)nl()
|
||||
See also:
|
||||
link(OPENSSL-DTLS-CLIENT)(ADDRESS_OPENSSL_DTLS_CLIENT),
|
||||
link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN),
|
||||
|
@ -1983,9 +1985,15 @@ label(OPTION_RCVBUF_LATE)dit(bf(tt(rcvbuf-late=<bytes>)))
|
|||
connected to <bytes> [link(int)(TYPE_INT)].
|
||||
With TCP sockets, this value corresponds to the socket's
|
||||
maximal window size.
|
||||
label(OPTION_RCVLOWAT)dit(bf(tt(rcvlowat=<bytes>)))
|
||||
Specifies the minimum number of received bytes [link(int)(TYPE_INT)] until
|
||||
the socket layer will pass the buffered data to socat().
|
||||
label(OPTION_SO_RCVTIMOE)dit(bf(tt(so-rcvtimeo=<time>, rcvtimeo=<time>)))
|
||||
Specifies the time [link(int)(TYPE_TIMEVAL)] until code(recv()), code(read())
|
||||
etc. functions timeout when no data is received. Note that in the transfer
|
||||
phase socat() only calls these functions when code(select()) has reported
|
||||
that data is available. However this option is useful with DTLS addresses to
|
||||
timeout during connection negotiation.
|
||||
label(OPTION_SO_SNDTIMOE)dit(bf(tt(so-sndtimeo=<time>, sndtimeo=<time>)))
|
||||
Like link(so-recvtimeo)(OPTION_SO_RCVTIMOE), but for code(send). Not usecase
|
||||
known.
|
||||
label(OPTION_REUSEADDR)dit(bf(tt(reuseaddr)))
|
||||
Allows other sockets to bind to an address even if parts of it (e.g. the
|
||||
local port) are already in use by socat() (link(example)(EXAMPLE_OPTION_REUSEADDR)).
|
||||
|
@ -2896,11 +2904,11 @@ label(OPTION_OPENSSL_EGD)dit(bf(tt(egd=<filename>)))
|
|||
On some systems, openssl requires an explicit source of random data. Specify
|
||||
the socket name where an entropy gathering daemon like egd provides random
|
||||
data, e.g. /dev/egd-pool.
|
||||
label(OPTION_OPENSSL_MAXFRAGLEN)dit(bf(tt(maxfraglen=<int>, openssl-maxfraglen=<int>)))
|
||||
label(OPTION_OPENSSL_MAXFRAGLEN)dit(bf(tt(openssl-maxfraglen=<int>, maxfraglen=<int>)))
|
||||
For client connections, make a Max Fragment Length Negotiation Request to the server to limit the
|
||||
maximum size fragment the server will send to us. Supported lengths are: 512, 1024, 2048, or
|
||||
4096. Note that this option is not applicable for link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN).
|
||||
label(OPTION_OPENSSL_MAXSENDFRAG)dit(bf(tt(maxsendfrag=<int>, openssl-maxsendfrag=<int>)))
|
||||
label(OPTION_OPENSSL_MAXSENDFRAG)dit(bf(tt(openssl-maxsendfrag=<int>, maxsendfrag=<int>)))
|
||||
Limit the maximum size of the fragment we will send to the other side. Supported length range:
|
||||
512 - 16384. Note that under link(OPENSSL-LISTEN)(ADDRESS_OPENSSL_LISTEN), the maximum fragment
|
||||
size may be further limited by the client's Maximum Fragment Length Negotiation Request, if it
|
||||
|
|
111
test.sh
111
test.sh
|
@ -5559,7 +5559,7 @@ elif ! feat=$(testoptions connect-timeout); then
|
|||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
else
|
||||
# we need a hanging connection attempt, guess an address for this
|
||||
# We need a hanging connection attempt, guess an address for this
|
||||
case "$UNAME" in
|
||||
Linux) HANGIP=1.0.0.1 ;;
|
||||
*) HANGIP=255.255.255.254 ;;
|
||||
|
@ -5569,31 +5569,35 @@ tk1="$td/test$N.kill1"
|
|||
te2="$td/test$N.stderr2"
|
||||
tk2="$td/test$N.kill2"
|
||||
$PRINTF "test $F_n $TEST... " $N
|
||||
# first, try to make socat hang and see if it can be killed
|
||||
#$TRACE $SOCAT $opts - tcp:$HANGIP:1 >"$te1" 2>&1 </dev/null &
|
||||
CMD="$TRACE $SOCAT $opts - tcp:$HANGIP:1"
|
||||
$CMD >"$te1" 2>&1 </dev/null &
|
||||
# First, try to make socat hang and see if it can be killed
|
||||
CMD="$TRACE $SOCAT $opts - TCP:$HANGIP:1"
|
||||
$CMD >"$te1" 2>$te1 </dev/null &
|
||||
pid1=$!
|
||||
sleep 2
|
||||
if ! kill $pid1 2>"$tk1"; then
|
||||
$PRINTF "${YELLOW}does not hang${NORMAL}\n"
|
||||
echo "$CMD" >&2
|
||||
cat "$te1" >&2
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
else
|
||||
# second, set connect-timeout and see if socat exits before kill
|
||||
$TRACE $SOCAT $opts - tcp:$HANGIP:1,connect-timeout=1.0 >"$te2" 2>&1 </dev/null &
|
||||
# Second, set connect-timeout and see if socat exits before kill
|
||||
CMD="$TRACE $SOCAT $opts - TCP:$HANGIP:1,connect-timeout=1.0"
|
||||
$CMD >"$te1" 2>$te2 </dev/null &
|
||||
pid2=$!
|
||||
sleep 2
|
||||
if kill $pid2 2>"$tk2"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
echo "$CMD"
|
||||
cat "$te1"
|
||||
cat "$te2"
|
||||
echo "$CMD" >&2
|
||||
cat "$te2" >&2
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
numOK=$((numOK+1))
|
||||
if [ "$VERBOSE" ]; then
|
||||
echo "$CMD" >&2
|
||||
fi
|
||||
numOK=$((numOK+1))
|
||||
fi
|
||||
fi
|
||||
wait
|
||||
|
@ -15169,7 +15173,7 @@ elif ! $(type proxyecho.sh >/dev/null 2>&1); then
|
|||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! F=$(testfeats IP4 TCP LISTEN EXEC STDIO PROXY); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! A=$(testaddrs TCP4-LISTEN EXEC STDIO PROXY-CONNECT); then
|
||||
|
@ -15199,12 +15203,12 @@ waittcp4port $PORT 1
|
|||
echo "$da" |$CMD1 >"$tf" 2>"${te}0"
|
||||
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||
echo "$CMD0 &" >&2
|
||||
cat "${te}0"
|
||||
echo "$CMD1" >&2
|
||||
cat "${te}1"
|
||||
echo "diff:"
|
||||
cat "$tdiff"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0" >&2
|
||||
echo "$CMD1"
|
||||
cat "${te}1" >&2
|
||||
echo "diff:" >&2
|
||||
cat "$tdiff" >&2
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
else
|
||||
|
@ -15222,6 +15226,77 @@ esac
|
|||
PORT=$((PORT+1))
|
||||
|
||||
|
||||
# Test the so-rcvtimeo address option with DTLS
|
||||
NAME=RCVTIMEO_DTLS
|
||||
case "$TESTS" in
|
||||
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udp%*|*%timeout%*|*%openssl%*|*%dtls%*|*%$NAME%*)
|
||||
TEST="$NAME: test the so-rcvtimeo option with DTLS"
|
||||
if ! eval $NUMCOND; then :;
|
||||
elif ! F=$(testfeats STDIO OPENSSL); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! A=$(testaddrs STDIO DTLS); then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! o=$(testoptions verify so-rcvtimeo) >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
elif ! runsip4 >/dev/null; then
|
||||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
else
|
||||
# We need a hanging connection attempt, guess an address for this
|
||||
HANGIP=0.0.0.1
|
||||
te1="$td/test$N.stderr1"
|
||||
tk1="$td/test$N.kill1"
|
||||
te2="$td/test$N.stderr2"
|
||||
tk2="$td/test$N.kill2"
|
||||
$PRINTF "test $F_n $TEST... " $N
|
||||
# First, try to make socat hang and see if it can be killed
|
||||
CMD1="$TRACE $SOCAT $opts - DTLS:$HANGIP:1,verify=0"
|
||||
$CMD1 >"$te1" 2>$te1 </dev/null &
|
||||
pid1=$!
|
||||
sleep 2
|
||||
if ! kill -0 $pid1 2>"$tk1"; then
|
||||
$PRINTF "${YELLOW}does not hang${NORMAL}\n"
|
||||
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
|
||||
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||
numCANT=$((numCANT+1))
|
||||
listCANT="$listCANT $N"
|
||||
wait
|
||||
else
|
||||
# DTLS restarts read() a few times
|
||||
while kill $pid1 2>/dev/null; do :; done
|
||||
# Second, set so-rcvtimeo and see if Socat exits before kill
|
||||
CMD2="$TRACE $SOCAT $opts - DTLS:$HANGIP:1,verify=0,so-rcvtimeo=1.0"
|
||||
$CMD2 >"$te1" 2>$te2 </dev/null &
|
||||
pid2=$!
|
||||
sleep 3 # in OpenSSL 1.1.1f DTLS takes two timeouts
|
||||
if kill $pid2 2>"$tk2"; then
|
||||
$PRINTF "$FAILED\n"
|
||||
echo "$CMD2"
|
||||
cat "$te2" >&2
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
while kill $pid2 2>/dev/null; do :; done
|
||||
wait
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ "$VERBOSE" ]; then echo "$CMD2 &"; fi
|
||||
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||
numOK=$((numOK+1))
|
||||
fi
|
||||
fi
|
||||
wait
|
||||
fi ;; # testfeats, NUMCOND
|
||||
esac
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
# end of common tests
|
||||
|
||||
##################################################################################
|
||||
|
|
|
@ -119,6 +119,13 @@ const struct optdesc opt_so_sndlowat = { "so-sndlowat", "sndlowat", OPT_SO_SNDL
|
|||
#endif
|
||||
/* end of setsockopt options of UNIX98 standard */
|
||||
|
||||
#ifdef SO_RCVTIMEO
|
||||
const struct optdesc opt_so_rcvtimeo = { "so-rcvtimeo", "rcvtimeo", OPT_SO_RCVTIMEO, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL, OFUNC_SOCKOPT, SOL_SOCKET, SO_RCVTIMEO };
|
||||
#endif
|
||||
#ifdef SO_SNDTIMEO
|
||||
const struct optdesc opt_so_sndtimeo = { "so-sndtimeo", "sndtimeo", OPT_SO_SNDTIMEO, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL, OFUNC_SOCKOPT, SOL_SOCKET, SO_SNDTIMEO };
|
||||
#endif
|
||||
|
||||
#ifdef SO_AUDIT /* AIX 4.3.3 */
|
||||
const struct optdesc opt_so_audit = { "so-audit", "audit", OPT_SO_AUDIT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_AUDIT };
|
||||
#endif /* SO_AUDIT */
|
||||
|
|
|
@ -44,6 +44,8 @@ extern const struct optdesc opt_so_type;
|
|||
extern const struct optdesc opt_so_dontroute;
|
||||
extern const struct optdesc opt_so_rcvlowat;
|
||||
extern const struct optdesc opt_so_sndlowat;
|
||||
extern const struct optdesc opt_so_rcvtimeo;
|
||||
extern const struct optdesc opt_so_sndtimeo;
|
||||
extern const struct optdesc opt_so_audit;
|
||||
extern const struct optdesc opt_so_attach_filter;
|
||||
extern const struct optdesc opt_so_detach_filter;
|
||||
|
|
12
xioopts.c
12
xioopts.c
|
@ -1310,6 +1310,9 @@ const struct optname optionnames[] = {
|
|||
IF_SOCKET ("rcvbuf-late", &opt_so_rcvbuf_late)
|
||||
#ifdef SO_RCVLOWAT
|
||||
IF_SOCKET ("rcvlowat", &opt_so_rcvlowat)
|
||||
#endif
|
||||
#ifdef SO_RCVTIMEO
|
||||
IF_SOCKET ("rcvtimeo", &opt_so_rcvtimeo)
|
||||
#endif
|
||||
IF_OPEN ("rdonly", &opt_o_rdonly)
|
||||
IF_OPEN ("rdwr", &opt_o_rdwr)
|
||||
|
@ -1485,6 +1488,9 @@ const struct optname optionnames[] = {
|
|||
#ifdef SO_SNDLOWAT
|
||||
IF_SOCKET ("sndlowat", &opt_so_sndlowat)
|
||||
#endif
|
||||
#ifdef SO_SNDTIMEO
|
||||
IF_SOCKET ("sndtimeo", &opt_so_sndtimeo)
|
||||
#endif
|
||||
#if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name)
|
||||
IF_OPENSSL("snihost", &opt_openssl_snihost)
|
||||
#endif
|
||||
|
@ -1548,6 +1554,9 @@ const struct optname optionnames[] = {
|
|||
IF_SOCKET ("so-rcvbuf-late", &opt_so_rcvbuf_late)
|
||||
#ifdef SO_RCVLOWAT
|
||||
IF_SOCKET ("so-rcvlowat", &opt_so_rcvlowat)
|
||||
#endif
|
||||
#ifdef SO_RCVTIMEO
|
||||
IF_SOCKET ("so-rcvtimeo", &opt_so_rcvtimeo)
|
||||
#endif
|
||||
IF_SOCKET ("so-reuseaddr", &opt_so_reuseaddr)
|
||||
#ifdef SO_REUSEPORT /* AIX 4.3.3 */
|
||||
|
@ -1567,6 +1576,9 @@ const struct optname optionnames[] = {
|
|||
#ifdef SO_SNDLOWAT
|
||||
IF_SOCKET ("so-sndlowat", &opt_so_sndlowat)
|
||||
#endif
|
||||
#ifdef SO_SNDTIMEO
|
||||
IF_SOCKET ("so-sndtimeo", &opt_so_sndtimeo)
|
||||
#endif
|
||||
#ifdef SO_TIMESTAMP
|
||||
IF_SOCKET ("so-timestamp", &opt_so_timestamp)
|
||||
#endif
|
||||
|
|
|
@ -701,6 +701,9 @@ enum e_optcode {
|
|||
OPT_SO_RCVBUF_LATE,
|
||||
#ifdef SO_RCVLOWAT
|
||||
OPT_SO_RCVLOWAT,
|
||||
#endif
|
||||
#ifdef SO_RCVTIMEO
|
||||
OPT_SO_RCVTIMEO,
|
||||
#endif
|
||||
OPT_SO_REUSEADDR,
|
||||
#ifdef SO_REUSEPORT
|
||||
|
@ -719,6 +722,9 @@ enum e_optcode {
|
|||
OPT_SO_SNDBUF_LATE,
|
||||
#ifdef SO_SNDLOWAT
|
||||
OPT_SO_SNDLOWAT,
|
||||
#endif
|
||||
#ifdef SO_SNDTIMEO
|
||||
OPT_SO_SNDTIMEO,
|
||||
#endif
|
||||
OPT_SO_TIMESTAMP, /* Linux */
|
||||
OPT_SO_TYPE,
|
||||
|
|
Loading…
Reference in a new issue