mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
New address SOCKETPAIR for echoing datagrams
This commit is contained in:
parent
f152c55584
commit
c311542e11
18 changed files with 285 additions and 13 deletions
6
CHANGES
6
CHANGES
|
@ -13,6 +13,12 @@ Features:
|
||||||
The number of warnings has been reduced, e.g.removing a non existing
|
The number of warnings has been reduced, e.g.removing a non existing
|
||||||
file does in most cases no longer log a warning.
|
file does in most cases no longer log a warning.
|
||||||
|
|
||||||
|
Added address type internal SOCKETPAIR. This is similar to the unnamed
|
||||||
|
PIPE address (only for internal echoing) but it provides datagram mode
|
||||||
|
(the default) and thus keeps packet boundaries.
|
||||||
|
Tests: SOCKETPAIR_STREAM SOCKETPAIR_DATAGRAM SOCKETPAIR_SEQPACKET
|
||||||
|
SOCKETPAIR_BOUNDARIES
|
||||||
|
|
||||||
New option -S <mask> controls catching and logging of signals that are
|
New option -S <mask> controls catching and logging of signals that are
|
||||||
not internally used by Socat.
|
not internally used by Socat.
|
||||||
Tests: SIGTERM_NOLOG SIG31_LOG
|
Tests: SIGTERM_NOLOG SIG31_LOG
|
||||||
|
|
|
@ -45,7 +45,7 @@ XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
|
||||||
xiosignal.c xiosigchld.c xioread.c xiowrite.c \
|
xiosignal.c xiosigchld.c xioread.c xiowrite.c \
|
||||||
xiolayer.c xioshutdown.c xioclose.c xioexit.c \
|
xiolayer.c xioshutdown.c xioclose.c xioexit.c \
|
||||||
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
|
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
|
||||||
xio-gopen.c xio-creat.c xio-file.c xio-named.c \
|
xio-socketpair.c xio-gopen.c xio-creat.c xio-file.c xio-named.c \
|
||||||
xio-socket.c xio-interface.c xio-listen.c xio-unix.c xio-vsock.c \
|
xio-socket.c xio-interface.c xio-listen.c xio-unix.c xio-vsock.c \
|
||||||
xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \
|
xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \
|
||||||
xio-sctp.c xio-rawip.c \
|
xio-sctp.c xio-rawip.c \
|
||||||
|
@ -64,7 +64,7 @@ HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.
|
||||||
xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.h \
|
xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.h \
|
||||||
xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \
|
xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \
|
||||||
xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \
|
xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \
|
||||||
xio-socket.h xio-interface.h xio-listen.h xio-unix.h xio-vsock.h \
|
xio-socketpair.h xio-socket.h xio-interface.h xio-listen.h xio-unix.h xio-vsock.h \
|
||||||
xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \
|
xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h \
|
||||||
xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \
|
xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h \
|
||||||
xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \
|
xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \
|
||||||
|
|
|
@ -692,6 +692,7 @@
|
||||||
#undef WITH_GOPEN
|
#undef WITH_GOPEN
|
||||||
#undef WITH_TERMIOS
|
#undef WITH_TERMIOS
|
||||||
#undef WITH_PIPE
|
#undef WITH_PIPE
|
||||||
|
#undef WITH_SOCKETPAIR
|
||||||
#undef WITH_UNIX
|
#undef WITH_UNIX
|
||||||
#undef WITH_ABSTRACT_UNIXSOCKET
|
#undef WITH_ABSTRACT_UNIXSOCKET
|
||||||
#undef WITH_IP4
|
#undef WITH_IP4
|
||||||
|
|
|
@ -219,6 +219,14 @@ AC_ARG_ENABLE(pipe, [ --disable-pipe disable pipe support],
|
||||||
esac],
|
esac],
|
||||||
[AC_DEFINE(WITH_PIPE) AC_MSG_RESULT(yes)])
|
[AC_DEFINE(WITH_PIPE) AC_MSG_RESULT(yes)])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(whether to include explicit socketpair support)
|
||||||
|
AC_ARG_ENABLE(socketpair, [ --disable-socketpair disable socketpair support],
|
||||||
|
[case "$enableval" in
|
||||||
|
no) AC_MSG_RESULT(no);;
|
||||||
|
*) AC_DEFINE(WITH_SOCKETPAIR) AC_MSG_RESULT(yes);;
|
||||||
|
esac],
|
||||||
|
[AC_DEFINE(WITH_SOCKETPAIR) AC_MSG_RESULT(yes)])
|
||||||
|
|
||||||
AC_MSG_CHECKING(whether to include explicit termios support)
|
AC_MSG_CHECKING(whether to include explicit termios support)
|
||||||
AC_ARG_ENABLE(termios, [ --disable-termios disable termios support],
|
AC_ARG_ENABLE(termios, [ --disable-termios disable termios support],
|
||||||
[case "$enableval" in
|
[case "$enableval" in
|
||||||
|
|
15
doc/socat.yo
15
doc/socat.yo
|
@ -682,13 +682,22 @@ label(ADDRESS_NAMED_PIPE)dit(bf(tt(PIPE:<filename>)))
|
||||||
See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE)
|
See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE)
|
||||||
label(ADDRESS_UNNAMED_PIPE)dit(bf(tt(PIPE)))
|
label(ADDRESS_UNNAMED_PIPE)dit(bf(tt(PIPE)))
|
||||||
Creates an unnamed pipe and uses it for reading and writing. It works as an
|
Creates an unnamed pipe and uses it for reading and writing. It works as an
|
||||||
echo, because everything written
|
echo, because everything written to it appeares immediately as read
|
||||||
to it appeares immediately as read data.nl()
|
data.nl()
|
||||||
Note: When socat tries to write more bytes than the pipe can queue (Linux
|
Note: When socat tries to write more bytes than the pipe can queue (Linux
|
||||||
2.4: 2048 bytes), socat might block. Consider, e.g., using
|
2.4: 2048 bytes), socat might block. Consider, e.g., using
|
||||||
option code(-b 2048) nl()
|
option code(-b 2048) nl()
|
||||||
Option groups: link(FD)(GROUP_FD) nl()
|
Option groups: link(FD)(GROUP_FD) nl()
|
||||||
See also: link(named pipe)(ADDRESS_NAMED_PIPE)
|
See also: link(named pipe)(ADDRESS_NAMED_PIPE), link(SOCKETPAIR)(ADDRESS_SOCKETPAIR)
|
||||||
|
label(ADDRESS_SOCKETPAIR)dit(bf(tt(SOCKETPAIR)))
|
||||||
|
Creates a socketpair and uses it for reading and writing. It works as an
|
||||||
|
echo, because everything written to it appeares immediately as read
|
||||||
|
data. The default socket type is datagram, so it keeps packet boundaries.
|
||||||
|
nl()
|
||||||
|
Option groups: link(FD)(GROUP_FD) nl()
|
||||||
|
Useful options:
|
||||||
|
link(socktype)(OPTION_SO_TYPE)nl()
|
||||||
|
See also: link(unnamed pipe)(ADDRESS_UNNAMED_PIPE)
|
||||||
label(ADDRESS_PROXY_CONNECT)dit(bf(tt(PROXY:<proxy>:<hostname>:<port>)))
|
label(ADDRESS_PROXY_CONNECT)dit(bf(tt(PROXY:<proxy>:<hostname>:<port>)))
|
||||||
Connects to an HTTP proxy server on port 8080 using TCP/IP version 4 or 6
|
Connects to an HTTP proxy server on port 8080 using TCP/IP version 4 or 6
|
||||||
depending on address specification, name resolution, or option
|
depending on address specification, name resolution, or option
|
||||||
|
|
5
socat.c
5
socat.c
|
@ -540,6 +540,11 @@ void socat_version(FILE *fd) {
|
||||||
#else
|
#else
|
||||||
fputs(" #undef WITH_PIPE\n", fd);
|
fputs(" #undef WITH_PIPE\n", fd);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WITH_SOCKETPAIR
|
||||||
|
fprintf(fd, " #define WITH_SOCKETPAIR %d\n", WITH_SOCKETPAIR);
|
||||||
|
#else
|
||||||
|
fputs(" #undef WITH_SOCKETPAIR\n", fd);
|
||||||
|
#endif
|
||||||
#ifdef WITH_UNIX
|
#ifdef WITH_UNIX
|
||||||
fprintf(fd, " #define WITH_UNIX %d\n", WITH_UNIX);
|
fprintf(fd, " #define WITH_UNIX %d\n", WITH_UNIX);
|
||||||
#else
|
#else
|
||||||
|
|
102
test.sh
102
test.sh
|
@ -16546,6 +16546,108 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
NAME=SOCKETPAIR_STREAM
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%stdio%*|*%socketpair%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: stdio and internal socketpair with stream"
|
||||||
|
testecho "$N" "$TEST" "STDIO" "SOCKETPAIR" "$opts"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=SOCKETPAIR_DATAGRAM
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%stdio%*|*%socketpair%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: stdio and internal socketpair with datagram"
|
||||||
|
testecho "$N" "$TEST" "STDIO" "SOCKETPAIR,socktype=2" "$opts"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=SOCKETPAIR_SEQPACKET
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%stdio%*|*%socketpair%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: stdio and internal socketpair with seqpacket"
|
||||||
|
testecho "$N" "$TEST" "STDIO" "SOCKETPAIR,socktype=$SOCK_SEQPACKET" "$opts"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
# Test if SOCKETPAIR address with SOCK_DGRAM keeps packet boundaries
|
||||||
|
NAME=SOCKETPAIR_BOUNDARIES
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%socketpair%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: Internal socketpair keeps packet boundaries"
|
||||||
|
# Start a UDP4-DATAGRAM process that echoes data with datagram SOCKETPAIR;
|
||||||
|
# a client sends two packets with 24 and ~18 bytes using a UDP4-DATAGRAM. The
|
||||||
|
# client truncates packets to size 24, so when a large merged packet comes from
|
||||||
|
# server some data will be lost. If the original data is received, the test
|
||||||
|
# succeeded.
|
||||||
|
if ! eval $NUMCOND; then :;
|
||||||
|
elif ! F=$(testfeats STDIO IP4 UDP SOCKETPAIR); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! A=$(testaddrs - STDIO UDP4-DATAGRAM SOCKETPAIR); 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 bind socktype ) >/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
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
ts1p=$PORT; PORT=$((PORT+1))
|
||||||
|
ts2p=$PORT; PORT=$((PORT+1))
|
||||||
|
da="test$N $(date) $RANDOM"
|
||||||
|
CMD1="$TRACE $SOCAT $opts -T 0.2 UDP4-DATAGRAM:$LOCALHOST:$ts2p,bind=$LOCALHOST:$ts1p SOCKETPAIR,socktype=$SOCK_DGRAM"
|
||||||
|
CMD2="$TRACE $SOCAT $opts -b 24 -t 0.2 -T 0.3 - UDP4-DATAGRAM:$LOCALHOST:$ts1p,bind=$LOCALHOST:$ts2p"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
export SOCAT_TRANSFER_WAIT=0.2
|
||||||
|
$CMD1 2>"${te}1" &
|
||||||
|
pid1="$!"
|
||||||
|
unset SOCAT_TRANSFER_WAIT
|
||||||
|
waitudp4port $ts1p 1
|
||||||
|
{ echo -n "${da:0:20}"; usleep 100000; echo "${da:20}"; } |$CMD2 >>"$tf" 2>>"${te}2"
|
||||||
|
rc2="$?"
|
||||||
|
kill "$pid1" 2>/dev/null; wait;
|
||||||
|
if [ "$rc2" -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED (rc2=$rc2): $TRACE $SOCAT:\n"
|
||||||
|
echo "$CMD1 &"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||||
|
$PRINTF "$FAILED\n"
|
||||||
|
echo "$CMD1 &"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2" >&2
|
||||||
|
echo diff:
|
||||||
|
cat "$tdiff"
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
PORT=$((PORT+1))
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include "xio-named.h"
|
#include "xio-named.h"
|
||||||
|
|
||||||
|
#include "xio-pipe.h"
|
||||||
|
|
||||||
|
|
||||||
#if WITH_PIPE
|
#if WITH_PIPE
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
||||||
sock->stream.dtype = XIODATA_PIPE;
|
sock->stream.dtype = XIODATA_PIPE;
|
||||||
sock->stream.fd = filedes[0];
|
sock->stream.fd = filedes[0];
|
||||||
sock->stream.para.bipipe.fdout = filedes[1];
|
sock->stream.para.bipipe.fdout = filedes[1];
|
||||||
|
sock->stream.para.bipipe.socktype = SOCK_STREAM; /* due to socketpair reuse */
|
||||||
applyopts_cloexec(sock->stream.fd, opts);
|
applyopts_cloexec(sock->stream.fd, opts);
|
||||||
applyopts_cloexec(sock->stream.para.bipipe.fdout, opts);
|
applyopts_cloexec(sock->stream.para.bipipe.fdout, opts);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,4 @@
|
||||||
|
|
||||||
extern const struct addrdesc xioaddr_pipe;
|
extern const struct addrdesc xioaddr_pipe;
|
||||||
|
|
||||||
extern int xioopen_fifo_unnamed(char *arg, xiofile_t *sock);
|
|
||||||
|
|
||||||
#endif /* !defined(__xio_pipe_h_included) */
|
#endif /* !defined(__xio_pipe_h_included) */
|
||||||
|
|
|
@ -202,7 +202,6 @@ const struct optdesc opt_siocspgrp = { "siocspgrp", NULL, OPT_SIOCSPGRP, GRO
|
||||||
const struct optdesc opt_bind = { "bind", NULL, OPT_BIND, GROUP_SOCKET, PH_BIND, TYPE_STRING,OFUNC_SPEC };
|
const struct optdesc opt_bind = { "bind", NULL, OPT_BIND, GROUP_SOCKET, PH_BIND, TYPE_STRING,OFUNC_SPEC };
|
||||||
const struct optdesc opt_connect_timeout = { "connect-timeout", NULL, OPT_CONNECT_TIMEOUT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.connect_timeout) };
|
const struct optdesc opt_connect_timeout = { "connect-timeout", NULL, OPT_CONNECT_TIMEOUT, GROUP_SOCKET, PH_PASTSOCKET, TYPE_TIMEVAL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.connect_timeout) };
|
||||||
const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
||||||
const struct optdesc opt_protocol = { "protocol", NULL, OPT_PROTOCOL, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
|
||||||
|
|
||||||
/* generic setsockopt() options */
|
/* generic setsockopt() options */
|
||||||
const struct optdesc opt_setsockopt = { "setsockopt", "sockopt", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_CONNECTED, TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
const struct optdesc opt_setsockopt = { "setsockopt", "sockopt", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_CONNECTED, TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||||
|
|
102
xio-socketpair.c
Normal file
102
xio-socketpair.c
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/* source: xio-socketpair.c */
|
||||||
|
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
/* this file contains the source for opening addresses of socketpair type */
|
||||||
|
|
||||||
|
#include "xiosysincludes.h"
|
||||||
|
#include "xioopen.h"
|
||||||
|
|
||||||
|
#include "xio-named.h"
|
||||||
|
|
||||||
|
#include "xio-socketpair.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if WITH_SOCKETPAIR
|
||||||
|
|
||||||
|
static int xioopen_socketpair(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
|
|
||||||
|
const struct addrdesc xioaddr_socketpair = { "SOCKETPAIR", 3, xioopen_socketpair, GROUP_FD|GROUP_SOCKET, 0, 0, 0 HELP(":<filename>") };
|
||||||
|
|
||||||
|
|
||||||
|
/* open a socketpair */
|
||||||
|
static int xioopen_socketpair(
|
||||||
|
int argc,
|
||||||
|
const char *argv[],
|
||||||
|
struct opt *opts,
|
||||||
|
int xioflags,
|
||||||
|
xiofile_t *xfd,
|
||||||
|
groups_t groups ,
|
||||||
|
int dummy1,
|
||||||
|
int dummy2,
|
||||||
|
int dummy3)
|
||||||
|
{
|
||||||
|
struct single *sfd;
|
||||||
|
struct opt *opts2;
|
||||||
|
int pf = PF_UNIX;
|
||||||
|
int protocol = 0;
|
||||||
|
int filedes[2];
|
||||||
|
int numleft;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (argc != 1) {
|
||||||
|
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sfd = &xfd->stream;
|
||||||
|
sfd->para.bipipe.socktype = SOCK_DGRAM;
|
||||||
|
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
retropt_int(opts, OPT_PROTOCOL_FAMILY, &pf);
|
||||||
|
retropt_int(opts, OPT_SO_TYPE, &sfd->para.bipipe.socktype);
|
||||||
|
retropt_int(opts, OPT_SO_PROTOTYPE, &protocol);
|
||||||
|
|
||||||
|
if (Socketpair(pf, sfd->para.bipipe.socktype, protocol, filedes) != 0) {
|
||||||
|
Error5("socketpair(%d, %d, %d, %p): %s", pf, sfd->para.bipipe.socktype, protocol, filedes, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Info2("socketpair({%d,%d})", filedes[0], filedes[1]);
|
||||||
|
|
||||||
|
sfd->tag = XIO_TAG_RDWR;
|
||||||
|
if (sfd->para.bipipe.socktype == SOCK_STREAM) {
|
||||||
|
sfd->dtype = XIOREAD_STREAM|XIOWRITE_PIPE;
|
||||||
|
} else {
|
||||||
|
sfd->dtype = XIOREAD_RECV|XIOREAD_RECV_NOCHECK|XIOWRITE_PIPE;
|
||||||
|
}
|
||||||
|
sfd->fd = filedes[0];
|
||||||
|
sfd->para.bipipe.fdout = filedes[1];
|
||||||
|
applyopts_cloexec(sfd->fd, opts);
|
||||||
|
applyopts_cloexec(sfd->para.bipipe.fdout, opts);
|
||||||
|
|
||||||
|
/* one-time and input-direction options, no second application */
|
||||||
|
retropt_bool(opts, OPT_IGNOREEOF, &sfd->ignoreeof);
|
||||||
|
|
||||||
|
/* here we copy opts! */
|
||||||
|
if ((opts2 = copyopts(opts, GROUP_SOCKET)) == NULL) {
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply options to first FD */
|
||||||
|
if ((result = applyopts(sfd->fd, opts, PH_ALL)) < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if ((result = applyopts_single(sfd, opts, PH_ALL)) < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply options to second FD */
|
||||||
|
if ((result = applyopts(sfd->para.bipipe.fdout, opts2, PH_ALL)) < 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((numleft = leftopts(opts)) > 0) {
|
||||||
|
Error1("%d option(s) could not be used", numleft);
|
||||||
|
showleft(opts);
|
||||||
|
}
|
||||||
|
Notice("writing to and reading from unnamed socketpair");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_SOCKETPAIR */
|
10
xio-socketpair.h
Normal file
10
xio-socketpair.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/* source: xio-socketpair.h */
|
||||||
|
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
#ifndef __xio_socketpair_h_included
|
||||||
|
#define __xio_socketpair_h_included 1
|
||||||
|
|
||||||
|
const extern struct addrdesc xioaddr_socketpair;
|
||||||
|
|
||||||
|
#endif /* !defined(__xio_socketpair_h_included) */
|
4
xio.h
4
xio.h
|
@ -61,6 +61,7 @@ struct opt;
|
||||||
#define XIOREAD_RECV_ONESHOT 0x0008 /* give EOF after first packet */
|
#define XIOREAD_RECV_ONESHOT 0x0008 /* give EOF after first packet */
|
||||||
#define XIOREAD_RECV_SKIPIP 0x0010 /* recv, skip IPv4 header */
|
#define XIOREAD_RECV_SKIPIP 0x0010 /* recv, skip IPv4 header */
|
||||||
#define XIOREAD_RECV_FROM 0x0020 /* remember peer for replying */
|
#define XIOREAD_RECV_FROM 0x0020 /* remember peer for replying */
|
||||||
|
#define XIOREAD_RECV_NOCHECK 0x0040 /* do not check peer */
|
||||||
|
|
||||||
/* combinations */
|
/* combinations */
|
||||||
#define XIODATA_MASK (XIODATA_READMASK|XIODATA_WRITEMASK)
|
#define XIODATA_MASK (XIODATA_READMASK|XIODATA_WRITEMASK)
|
||||||
|
@ -211,6 +212,7 @@ typedef struct single {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
int fdout; /* use fd for output */
|
int fdout; /* use fd for output */
|
||||||
|
int socktype;
|
||||||
} bipipe;
|
} bipipe;
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
struct {
|
struct {
|
||||||
|
@ -242,8 +244,8 @@ typedef struct single {
|
||||||
} socket;
|
} socket;
|
||||||
#endif /* _WITH_SOCKET */
|
#endif /* _WITH_SOCKET */
|
||||||
struct {
|
struct {
|
||||||
pid_t pid; /* child PID, with EXEC: */
|
|
||||||
int fdout; /* use fd for output if two pipes */
|
int fdout; /* use fd for output if two pipes */
|
||||||
|
pid_t pid; /* child PID, with EXEC: */
|
||||||
struct timeval sitout_eio;
|
struct timeval sitout_eio;
|
||||||
} exec;
|
} exec;
|
||||||
#if WITH_READLINE
|
#if WITH_READLINE
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "xio-creat.h"
|
#include "xio-creat.h"
|
||||||
#include "xio-gopen.h"
|
#include "xio-gopen.h"
|
||||||
#include "xio-pipe.h"
|
#include "xio-pipe.h"
|
||||||
|
#include "xio-socketpair.h"
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
#include "xio-socket.h"
|
#include "xio-socket.h"
|
||||||
#include "xio-listen.h"
|
#include "xio-listen.h"
|
||||||
|
|
|
@ -193,6 +193,9 @@ const struct addrname addressnames[] = {
|
||||||
{ "SOCKET-RECVFROM", &xioaddr_socket_recvfrom },
|
{ "SOCKET-RECVFROM", &xioaddr_socket_recvfrom },
|
||||||
{ "SOCKET-SENDTO", &xioaddr_socket_sendto },
|
{ "SOCKET-SENDTO", &xioaddr_socket_sendto },
|
||||||
#endif
|
#endif
|
||||||
|
#if WITH_SOCKETPAIR
|
||||||
|
{ "SOCKETPAIR", &xioaddr_socketpair },
|
||||||
|
#endif
|
||||||
#if WITH_SOCKS4
|
#if WITH_SOCKS4
|
||||||
{ "SOCKS", &xioaddr_socks4_connect },
|
{ "SOCKS", &xioaddr_socks4_connect },
|
||||||
{ "SOCKS4", &xioaddr_socks4_connect },
|
{ "SOCKS4", &xioaddr_socks4_connect },
|
||||||
|
|
|
@ -152,7 +152,6 @@ enum e_func {
|
||||||
#define GROUP_FILE GROUP_REG
|
#define GROUP_FILE GROUP_REG
|
||||||
#define GROUP_SOCKET 0x00000020
|
#define GROUP_SOCKET 0x00000020
|
||||||
#define GROUP_READLINE 0x00000040
|
#define GROUP_READLINE 0x00000040
|
||||||
|
|
||||||
#define GROUP_NAMED 0x00000100 /* file system entry */
|
#define GROUP_NAMED 0x00000100 /* file system entry */
|
||||||
#define GROUP_OPEN 0x00000200 /* flags for open() */
|
#define GROUP_OPEN 0x00000200 /* flags for open() */
|
||||||
#define GROUP_EXEC 0x00000400 /* program or script execution */
|
#define GROUP_EXEC 0x00000400 /* program or script execution */
|
||||||
|
|
24
xioread.c
24
xioread.c
|
@ -134,7 +134,27 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
|
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
case XIOREAD_RECV:
|
case XIOREAD_RECV:
|
||||||
if (pipe->dtype & XIOREAD_RECV_FROM) {
|
if (pipe->dtype & XIOREAD_RECV_NOCHECK) {
|
||||||
|
/* No need to check peer address */
|
||||||
|
do {
|
||||||
|
bytes =
|
||||||
|
Recv(pipe->fd, buff, bufsiz, 0);
|
||||||
|
} while (bytes < 0 && errno == EINTR);
|
||||||
|
if (bytes < 0) {
|
||||||
|
_errno = errno;
|
||||||
|
Error3("recvfrom(%d, %p, "F_Zu", 0", pipe->fd, buff, bufsiz);
|
||||||
|
errno = _errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Notice1("received packet with "F_Zu" bytes", bytes);
|
||||||
|
if (bytes == 0) {
|
||||||
|
if (!pipe->para.socket.null_eof) {
|
||||||
|
errno = EAGAIN; return -1;
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (pipe->dtype & XIOREAD_RECV_FROM) {
|
||||||
/* Receiving packets in addresses of RECVFROM types, the sender address
|
/* Receiving packets in addresses of RECVFROM types, the sender address
|
||||||
has already been determined in OPEN phase. */
|
has already been determined in OPEN phase. */
|
||||||
Debug1("%s(): XIOREAD_RECV and XIOREAD_RECV_FROM (peer checks already done)",
|
Debug1("%s(): XIOREAD_RECV and XIOREAD_RECV_FROM (peer checks already done)",
|
||||||
|
@ -375,7 +395,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
return -1;
|
return -1;
|
||||||
#endif /* !(WITH_RAWIP || WITH_UDP || WITH_UNIX) */
|
#endif /* !(WITH_RAWIP || WITH_UDP || WITH_UNIX) */
|
||||||
|
|
||||||
} else /* ~XIOREAD_RECV_FROM */ {
|
} else /* ~(XIOREAD_RECV_FROM|XIOREAD_RECV_FROM) */ {
|
||||||
/* Receiving packets without planning to answer to the sender, but we
|
/* Receiving packets without planning to answer to the sender, but we
|
||||||
might need sender info for some checks, thus we use recvfrom() */
|
might need sender info for some checks, thus we use recvfrom() */
|
||||||
struct msghdr msgh = {0};
|
struct msghdr msgh = {0};
|
||||||
|
|
|
@ -114,7 +114,11 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
#endif /* _WITH_SOCKET */
|
#endif /* _WITH_SOCKET */
|
||||||
|
|
||||||
case XIOWRITE_PIPE:
|
case XIOWRITE_PIPE:
|
||||||
|
if (pipe->para.bipipe.socktype == SOCK_STREAM) {
|
||||||
writt = Write(pipe->para.bipipe.fdout, buff, bytes);
|
writt = Write(pipe->para.bipipe.fdout, buff, bytes);
|
||||||
|
} else {
|
||||||
|
writt = Send(pipe->para.bipipe.fdout, buff, bytes, 0);
|
||||||
|
}
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
if (writt < 0) {
|
if (writt < 0) {
|
||||||
Error4("write(%d, %p, "F_Zu"): %s",
|
Error4("write(%d, %p, "F_Zu"): %s",
|
||||||
|
|
Loading…
Reference in a new issue