mirror of
https://repo.or.cz/socat.git
synced 2025-06-06 02:16:50 +00:00
writefull() respects total inactivity timeout
This commit is contained in:
parent
1878ae93fd
commit
1154e69d3e
12 changed files with 31 additions and 15 deletions
4
CHANGES
4
CHANGES
|
@ -22,6 +22,9 @@ Corrections:
|
||||||
|
|
||||||
On partial write to not poll with sleep() but use select()/poll().
|
On partial write to not poll with sleep() but use select()/poll().
|
||||||
|
|
||||||
|
Partial write situations respect total inactivity timeout when
|
||||||
|
nonblocking.
|
||||||
|
|
||||||
Building:
|
Building:
|
||||||
Disabling certain features during configure could break build process.
|
Disabling certain features during configure could break build process.
|
||||||
|
|
||||||
|
@ -39,6 +42,7 @@ Testing:
|
||||||
SOCKS5 addresses are no longer experimental.
|
SOCKS5 addresses are no longer experimental.
|
||||||
Tests: SOCKS5CONNECT_TCP4 SOCKS5LISTEN_TCP4
|
Tests: SOCKS5CONNECT_TCP4 SOCKS5LISTEN_TCP4
|
||||||
|
|
||||||
|
|
||||||
####################### V 1.8.0.2:
|
####################### V 1.8.0.2:
|
||||||
|
|
||||||
Security:
|
Security:
|
||||||
|
|
2
socat.c
2
socat.c
|
@ -282,6 +282,8 @@ int main(int argc, const char *argv[]) {
|
||||||
socat_opts.total_timeout.tv_usec =
|
socat_opts.total_timeout.tv_usec =
|
||||||
(rto-socat_opts.total_timeout.tv_sec) * 1000000;
|
(rto-socat_opts.total_timeout.tv_sec) * 1000000;
|
||||||
}
|
}
|
||||||
|
xioparms.total_timeout.tv_sec = socat_opts.total_timeout.tv_sec;
|
||||||
|
xioparms.total_timeout.tv_usec = socat_opts.total_timeout.tv_usec;
|
||||||
break;
|
break;
|
||||||
case 'u': if (arg1[0][2]) { socat_opt_hint(stderr, arg1[0][1], arg1[0][2]); Exit(1); }
|
case 'u': if (arg1[0][2]) { socat_opt_hint(stderr, arg1[0][1], arg1[0][2]); Exit(1); }
|
||||||
socat_opts.lefttoright = true; break;
|
socat_opts.lefttoright = true; break;
|
||||||
|
|
13
sysutils.c
13
sysutils.c
|
@ -32,10 +32,15 @@ const int one = 1;
|
||||||
Then we can test partial write with something like:
|
Then we can test partial write with something like:
|
||||||
socat -d4 -lu -b 262144 -u /dev/zero,readbytes=262144 -,o-nonblock |{ sleep 3; wc -c; }
|
socat -d4 -lu -b 262144 -u /dev/zero,readbytes=262144 -,o-nonblock |{ sleep 3; wc -c; }
|
||||||
*/
|
*/
|
||||||
ssize_t writefull(int fd, const void *buff, size_t bytes) {
|
ssize_t writefull(
|
||||||
|
int fd,
|
||||||
|
const void *buff,
|
||||||
|
size_t bytes,
|
||||||
|
const struct timeval *tmo0) {
|
||||||
size_t writt = 0;
|
size_t writt = 0;
|
||||||
ssize_t chk;
|
ssize_t chk;
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
|
struct timeval tmo = { 0 };
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -51,7 +56,11 @@ ssize_t writefull(int fd, const void *buff, size_t bytes) {
|
||||||
pfd.fd = fd;
|
pfd.fd = fd;
|
||||||
pfd.events = POLLOUT;
|
pfd.events = POLLOUT;
|
||||||
pfd.revents = 0;
|
pfd.revents = 0;
|
||||||
rc = xiopoll(&pfd, 1, NULL);
|
if (tmo0 != NULL) {
|
||||||
|
tmo.tv_sec = tmo0->tv_sec;
|
||||||
|
tmo.tv_usec = tmo0->tv_usec;
|
||||||
|
}
|
||||||
|
rc = xiopoll(&pfd, 1, (tmo.tv_sec!=0 || tmo.tv_usec!=0) ? &tmo : NULL);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
Notice("inactivity timeout triggered");
|
Notice("inactivity timeout triggered");
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct xiorange {
|
||||||
extern const int one;
|
extern const int one;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern ssize_t writefull(int fd, const void *buff, size_t bytes);
|
extern ssize_t writefull(int fd, const void *buff, size_t bytes, const struct timeval *tmo0);
|
||||||
|
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
extern socklen_t socket_init(int af, union sockaddr_union *sa);
|
extern socklen_t socket_init(int af, union sockaddr_union *sa);
|
||||||
|
|
6
test.sh
6
test.sh
|
@ -19053,7 +19053,7 @@ else
|
||||||
da="test$N $(date) $RANDOM"
|
da="test$N $(date) $RANDOM"
|
||||||
case X$IPPORT in
|
case X$IPPORT in
|
||||||
XPORT) newport $(tolower $PROTO); _PORT=$PORT ;;
|
XPORT) newport $(tolower $PROTO); _PORT=$PORT ;;
|
||||||
XPROTO) echo "IPPROTO=\"$IPPROTO\""
|
XPROTO) #echo "IPPROTO=\"$IPPROTO\""
|
||||||
_PORT=$IPPROTO ;;
|
_PORT=$IPPROTO ;;
|
||||||
esac
|
esac
|
||||||
CMD0="$TRACE $SOCAT $opts ${ADDR}:$_PORT,$option,$ACCEPT_TIMEOUT PIPE"
|
CMD0="$TRACE $SOCAT $opts ${ADDR}:$_PORT,$option,$ACCEPT_TIMEOUT PIPE"
|
||||||
|
@ -19146,7 +19146,7 @@ else
|
||||||
da="test$N $(date) $RANDOM"
|
da="test$N $(date) $RANDOM"
|
||||||
case X$IPPORT in
|
case X$IPPORT in
|
||||||
XPORT) newport $(tolower $PROTO); _PORT=$PORT ;;
|
XPORT) newport $(tolower $PROTO); _PORT=$PORT ;;
|
||||||
XPROTO) echo "IPPROTO=\"$IPPROTO\""
|
XPROTO) #echo "IPPROTO=\"$IPPROTO\""
|
||||||
_PORT=$IPPROTO ;;
|
_PORT=$IPPROTO ;;
|
||||||
esac
|
esac
|
||||||
CMD0="$TRACE $SOCAT $opts -u /dev/null $ADDR:localhost-6-4.dest-unreach.net:$_PORT,bind=127.0.0.1"
|
CMD0="$TRACE $SOCAT $opts -u /dev/null $ADDR:localhost-6-4.dest-unreach.net:$_PORT,bind=127.0.0.1"
|
||||||
|
@ -19211,7 +19211,7 @@ else
|
||||||
da="test$N $(date) $RANDOM"
|
da="test$N $(date) $RANDOM"
|
||||||
case X$IPPORT in
|
case X$IPPORT in
|
||||||
XPORT) newport $(tolower $PROTO); _PORT=$PORT ;;
|
XPORT) newport $(tolower $PROTO); _PORT=$PORT ;;
|
||||||
XPROTO) echo "IPPROTO=\"$IPPROTO\""
|
XPROTO) #echo "IPPROTO=\"$IPPROTO\""
|
||||||
_PORT=$IPPROTO ;;
|
_PORT=$IPPROTO ;;
|
||||||
esac
|
esac
|
||||||
CMD0="$TRACE $SOCAT $opts ${ADDR%%-*}-LISTEN:$_PORT,pf=ip4 PIPE"
|
CMD0="$TRACE $SOCAT $opts ${ADDR%%-*}-LISTEN:$_PORT,pf=ip4 PIPE"
|
||||||
|
|
|
@ -376,7 +376,7 @@ int _xioopen_proxy_connect(struct single *sfd,
|
||||||
* xiosanitize(request, strlen(request), textbuff) = '\0';
|
* xiosanitize(request, strlen(request), textbuff) = '\0';
|
||||||
Info1("sending \"%s\"", textbuff);
|
Info1("sending \"%s\"", textbuff);
|
||||||
/* write errors are assumed to always be hard errors, no retry */
|
/* write errors are assumed to always be hard errors, no retry */
|
||||||
if (writefull(sfd->fd, request, strlen(request)) < 0) {
|
if (writefull(sfd->fd, request, strlen(request), NULL) < 0) {
|
||||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
sfd->fd, request, strlen(request), strerror(errno));
|
sfd->fd, request, strlen(request), strerror(errno));
|
||||||
if (Close(sfd->fd) < 0) {
|
if (Close(sfd->fd) < 0) {
|
||||||
|
@ -406,7 +406,7 @@ int _xioopen_proxy_connect(struct single *sfd,
|
||||||
*next = '\0';
|
*next = '\0';
|
||||||
Info1("sending \"%s\\r\\n\"", header);
|
Info1("sending \"%s\\r\\n\"", header);
|
||||||
*next++ = '\r'; *next++ = '\n'; *next++ = '\0';
|
*next++ = '\r'; *next++ = '\n'; *next++ = '\0';
|
||||||
if (writefull(sfd->fd, header, strlen(header)) < 0) {
|
if (writefull(sfd->fd, header, strlen(header), NULL) < 0) {
|
||||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
sfd->fd, header, strlen(header), strerror(errno));
|
sfd->fd, header, strlen(header), strerror(errno));
|
||||||
if (Close(sfd->fd) < 0) {
|
if (Close(sfd->fd) < 0) {
|
||||||
|
@ -419,7 +419,7 @@ int _xioopen_proxy_connect(struct single *sfd,
|
||||||
}
|
}
|
||||||
|
|
||||||
Info("sending \"\\r\\n\"");
|
Info("sending \"\\r\\n\"");
|
||||||
if (writefull(sfd->fd, "\r\n", 2) < 0) {
|
if (writefull(sfd->fd, "\r\n", 2, NULL) < 0) {
|
||||||
Msg2(level, "write(%d, \"\\r\\n\", 2): %s",
|
Msg2(level, "write(%d, \"\\r\\n\", 2): %s",
|
||||||
sfd->fd, strerror(errno));
|
sfd->fd, strerror(errno));
|
||||||
if (Close(sfd->fd) < 0) {
|
if (Close(sfd->fd) < 0) {
|
||||||
|
|
|
@ -184,7 +184,7 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) {
|
||||||
/* we must carriage return, because readline will first print the
|
/* we must carriage return, because readline will first print the
|
||||||
prompt */
|
prompt */
|
||||||
ssize_t writt;
|
ssize_t writt;
|
||||||
writt = writefull(pipe->fd, "\r", 1);
|
writt = writefull(pipe->fd, "\r", 1, NULL);
|
||||||
if (writt < 0) {
|
if (writt < 0) {
|
||||||
Warn2("write(%d, \"\\r\", 1): %s",
|
Warn2("write(%d, \"\\r\", 1): %s",
|
||||||
pipe->fd, strerror(errno));
|
pipe->fd, strerror(errno));
|
||||||
|
|
|
@ -370,7 +370,7 @@ int _xioopen_socks4_connect(struct single *sfd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
||||||
if (writefull(sfd->fd, sockhead, headlen) < 0) {
|
if (writefull(sfd->fd, sockhead, headlen, NULL) < 0) {
|
||||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
sfd->fd, sockhead, headlen, strerror(errno));
|
sfd->fd, sockhead, headlen, strerror(errno));
|
||||||
if (Close(sfd->fd) < 0) {
|
if (Close(sfd->fd) < 0) {
|
||||||
|
|
|
@ -136,7 +136,7 @@ static int _xioopen_socks5_handshake(struct single *sfd, int level)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (writefull(sfd->fd, client_hello, client_hello_size) < 0) {
|
if (writefull(sfd->fd, client_hello, client_hello_size, NULL) < 0) {
|
||||||
Msg4(level, "write(%d, %p, %d): %s",
|
Msg4(level, "write(%d, %p, %d): %s",
|
||||||
sfd->fd, client_hello, client_hello_size,
|
sfd->fd, client_hello, client_hello_size,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
@ -426,7 +426,7 @@ static int _xioopen_socks5_request(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (writefull(sfd->fd, req, bytes) < 0) {
|
if (writefull(sfd->fd, req, bytes, NULL) < 0) {
|
||||||
Msg4(level, "write(%d, %p, %d): %s",
|
Msg4(level, "write(%d, %p, %d): %s",
|
||||||
sfd->fd, req, bytes, strerror(errno));
|
sfd->fd, req, bytes, strerror(errno));
|
||||||
if (Close(sfd->fd) < 0) {
|
if (Close(sfd->fd) < 0) {
|
||||||
|
|
1
xio.h
1
xio.h
|
@ -120,6 +120,7 @@ typedef struct xioparms {
|
||||||
const char *sniffleft_name; /* file name with -r */
|
const char *sniffleft_name; /* file name with -r */
|
||||||
const char *sniffright_name; /* file name with -R */
|
const char *sniffright_name; /* file name with -R */
|
||||||
size_t bufsiz;
|
size_t bufsiz;
|
||||||
|
struct timeval total_timeout;/* when nothing happens, die after seconds */
|
||||||
} xioparms_t;
|
} xioparms_t;
|
||||||
|
|
||||||
/* pack the description of a lock file */
|
/* pack the description of a lock file */
|
||||||
|
|
|
@ -52,7 +52,7 @@ int xiogetlock(const char *lockfile) {
|
||||||
|
|
||||||
pid = Getpid();
|
pid = Getpid();
|
||||||
bytes = sprintf(pidbuf, F_pid"\n", pid);
|
bytes = sprintf(pidbuf, F_pid"\n", pid);
|
||||||
if (writefull(fd, pidbuf, bytes) < 0) {
|
if (writefull(fd, pidbuf, bytes, NULL) < 0) {
|
||||||
Error4("write(%d, %p, "F_Zu"): %s", fd, pidbuf, bytes, strerror(errno));
|
Error4("write(%d, %p, "F_Zu"): %s", fd, pidbuf, bytes, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
switch (pipe->dtype & XIODATA_WRITEMASK) {
|
switch (pipe->dtype & XIODATA_WRITEMASK) {
|
||||||
|
|
||||||
case XIOWRITE_STREAM:
|
case XIOWRITE_STREAM:
|
||||||
writt = writefull(pipe->fd, buff, bytes);
|
writt = writefull(pipe->fd, buff, bytes, NULL);
|
||||||
if (writt < 0) {
|
if (writt < 0) {
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
switch (_errno) {
|
switch (_errno) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue