mirror of
https://github.com/UzixLS/picocom.git
synced 2025-07-19 07:21:18 +03:00
Better RFC2217 socket shutdown / close
When an RFC2217 socket is closed, optionally, try to drain the buffered data allowing the remote server to read and process them. First the socket is shutdown only in the transmit (write) direction. Then data are read from it (and discarded) until the server closes the other direction (read(2) returns zero). Also, don't bother trying to reset the port to its original settings before exiting, since closing the connection to the remote server will do this anyway (as per RFC2217).
This commit is contained in:
34
picocom.c
34
picocom.c
@ -647,20 +647,23 @@ cleanup (int drain, int noreset, int hup)
|
||||
/* Print msg if they fail? Can't do anything, anyway... */
|
||||
if ( drain )
|
||||
term_drain(tty_fd);
|
||||
term_flush(tty_fd);
|
||||
/* term_flush does not work with some drivers. If we try to
|
||||
drain or even close the port while there are still data in
|
||||
it's output buffers *and* flow-control is enabled we may
|
||||
block forever. So we "fake" a flush, by temporarily setting
|
||||
f/c to none, waiting for any data in the output buffer to
|
||||
drain, and then reseting f/c to it's original setting. If
|
||||
the real flush above does works, then the fake one should
|
||||
amount to instantaneously switching f/c to none and then
|
||||
back to its propper setting. */
|
||||
if ( opts.flow != FC_NONE ) term_fake_flush(tty_fd);
|
||||
else {
|
||||
term_flush(tty_fd);
|
||||
/* term_flush does not work with some drivers. If we try
|
||||
to drain or even close the port while there are still
|
||||
data in it's output buffers *and* flow-control is
|
||||
enabled we may block forever. So we "fake" a flush, by
|
||||
temporarily setting f/c to none, waiting for any data
|
||||
in the output buffer to drain, and then reseting f/c to
|
||||
it's original setting. If the real flush above does
|
||||
work, then the fake one should amount to
|
||||
instantaneously switching f/c to none and then back to
|
||||
its propper setting. */
|
||||
if ( opts.flow != FC_NONE ) term_fake_flush(tty_fd);
|
||||
}
|
||||
term_set_hupcl(tty_fd, !noreset || hup);
|
||||
term_apply(tty_fd, 1);
|
||||
if ( noreset ) {
|
||||
if ( noreset || opts.telnet ) {
|
||||
pinfo("Skipping tty reset...\r\n");
|
||||
term_erase(tty_fd);
|
||||
#ifdef USE_FLOCK
|
||||
@ -668,7 +671,14 @@ cleanup (int drain, int noreset, int hup)
|
||||
comments in term.c/term_exitfunc() for more. */
|
||||
flock(tty_fd, LOCK_UN);
|
||||
#endif
|
||||
#ifdef USE_RFC2217
|
||||
if ( opts.telnet )
|
||||
tn2217_close(tty_fd, drain);
|
||||
else
|
||||
close(tty_fd);
|
||||
#else
|
||||
close(tty_fd);
|
||||
#endif
|
||||
tty_fd = -1;
|
||||
}
|
||||
}
|
||||
|
27
tn2217.c
27
tn2217.c
@ -435,6 +435,33 @@ out:
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Closes a TCP socket to a host. See "tn2217.h". */
|
||||
int
|
||||
tn2217_close(int fd, int drain)
|
||||
{
|
||||
char buff[1024];
|
||||
long fl;
|
||||
int n;
|
||||
|
||||
if ( ! drain )
|
||||
return close(fd);
|
||||
|
||||
/* FIXME(npat): Maybe protect the "reading until server closes"
|
||||
with a large-ish timeout? */
|
||||
|
||||
fl = fcntl(fd, F_GETFL);
|
||||
fl &= ~O_NONBLOCK;
|
||||
fcntl(fd, F_SETFL, fl);
|
||||
|
||||
shutdown(fd, SHUT_WR);
|
||||
do {
|
||||
n = read(fd, buff, sizeof(buff));
|
||||
} while ( n > 0 );
|
||||
if ( n < 0 )
|
||||
return n;
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
/* Sends {IAC SB COMPORT <cmd> <data> IAC SE} */
|
||||
static void
|
||||
tn2217_send_comport_cmd(struct term_s *t, unsigned char cmd,
|
||||
|
8
tn2217.h
8
tn2217.h
@ -32,6 +32,14 @@
|
||||
* Returns -1 on failure, and prints an error message to stderr. */
|
||||
int tn2217_open(const char *port);
|
||||
|
||||
/* Close a socket to a telnet service. If "drain" is zero, the socket
|
||||
* is just close(2)ed and the return-value of close(2) is returned. If
|
||||
* "drain" is non-zero, the write-direction of the socket is first
|
||||
* shutdown, and then data are read (and discarded) from the socket,
|
||||
* until the remote end closes it (read(2) returns zero). Returns zero
|
||||
* on success, a negative on error. */
|
||||
int tn2217_close(int fd, int drain);
|
||||
|
||||
struct term_ops;
|
||||
extern const struct term_ops tn2217_ops;
|
||||
|
||||
|
Reference in New Issue
Block a user