From 0ff9ea389c749836c7c6f23f1e654bc9a5600ebf Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 29 Mar 2003 16:47:06 +0000 Subject: [PATCH] Added uxsel.c, into which I've moved those parts of the uxnet.c functionality that deal with selectable fds in general. The idea is that pty.c will stop passing its fd straight to pterm.c and hand it to this module instead, and pterm.c will start requesting a general list of fds from this module rather than expecting a single one from pty.c, with the ultimate aim of pterm.c being able to form the basis of a Unix PuTTY as well as pterm proper. git-svn-id: svn://svn.tartarus.org/sgt/putty@3015 cda61777-01e9-0310-a592-d414129be87e --- Recipe | 3 +- unix/unix.h | 10 +++-- unix/uxnet.c | 49 +++++++++--------------- unix/uxplink.c | 59 ++++++++++++++--------------- unix/uxsel.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 65 deletions(-) create mode 100644 unix/uxsel.c diff --git a/Recipe b/Recipe index ddc18a1e..1040bb99 100644 --- a/Recipe +++ b/Recipe @@ -115,7 +115,8 @@ SFTP = sftp int64 logging # Pageant or PuTTYgen). WINMISC = misc version winstore settings tree234 winnet proxy cmdline + windefs winmisc -UXMISC = misc version uxstore settings tree234 uxnet proxy cmdline uxmisc +UXMISC = misc version uxstore settings tree234 uxsel uxnet proxy cmdline + + uxmisc MACMISC = misc version macstore settings tree234 macnet mtcpnet otnet proxy + macmisc macabout diff --git a/unix/unix.h b/unix/unix.h index b003ac74..9fd15699 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -61,10 +61,14 @@ char *x_get_default(const char *key); /* Things uxstore.c provides to pterm.c */ void provide_xrm_string(char *string); -/* Things uxnet.c provides to the front end */ +/* The interface used by uxsel.c */ +void uxsel_init(void); +typedef int (*uxsel_callback_fn)(int fd, int event); +void uxsel_set(int fd, int rwx, uxsel_callback_fn callback); +void uxsel_del(int fd); int select_result(int fd, int event); -int first_socket(int *state, int *rwx); -int next_socket(int *state, int *rwx); +int first_fd(int *state, int *rwx); +int next_fd(int *state, int *rwx); /* uxcfg.c */ struct controlbox; diff --git a/unix/uxnet.c b/unix/uxnet.c index 9dd4aa62..0795d4d2 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -73,6 +73,8 @@ struct SockAddr_tag { static tree234 *sktree; +static void uxsel_tell(Actual_Socket s); + static int cmpfortree(void *av, void *bv) { Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv; @@ -347,6 +349,7 @@ Socket sk_register(void *sock, Plug plug) ret->oobinline = 0; + uxsel_tell(ret); add234(sktree, ret); return (Socket) ret; @@ -505,6 +508,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, ret->writable = 1; } + uxsel_tell(ret); add234(sktree, ret); return (Socket) ret; @@ -623,6 +627,7 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) return (Socket) ret; } + uxsel_tell(ret); add234(sktree, ret); return (Socket) ret; @@ -632,6 +637,7 @@ static void sk_tcp_close(Socket sock) { Actual_Socket s = (Actual_Socket) sock; + uxsel_del(s->s); del234(sktree, s); close(s->s); sfree(s); @@ -729,6 +735,7 @@ void try_send(Actual_Socket s) } } } + uxsel_tell(s); } static int sk_tcp_write(Socket sock, const char *buf, int len) @@ -770,7 +777,7 @@ static int sk_tcp_write_oob(Socket sock, const char *buf, int len) return s->sending_oob; } -int select_result(int fd, int event) +static int net_select_result(int fd, int event) { int ret; int err; @@ -888,6 +895,7 @@ int select_result(int fd, int event) * asynchronous connection is completed. */ s->connected = s->writable = 1; + uxsel_tell(s); break; } else { int bufsize_before, bufsize_after; @@ -983,44 +991,21 @@ static void sk_tcp_set_frozen(Socket sock, int is_frozen) recv(s->s, &c, 1, MSG_PEEK); } s->frozen_readable = 0; + uxsel_tell(s); } -/* - * For Unix select()-based frontends: enumerate all sockets - * currently active, and state whether we currently wish to receive - * select events on them for reading, writing and exceptional - * status. - */ -static void set_rwx(Actual_Socket s, int *rwx) +static void uxsel_tell(Actual_Socket s) { - int val = 0; + int rwx = 0; if (!s->connected) - val |= 2; /* write == connect */ + rwx |= 2; /* write == connect */ if (s->connected && !s->frozen) - val |= 1 | 4; /* read, except */ + rwx |= 1 | 4; /* read, except */ if (bufchain_size(&s->output_data)) - val |= 2; /* write */ + rwx |= 2; /* write */ if (s->listener) - val |= 1; /* read == accept */ - *rwx = val; -} - -int first_socket(int *state, int *rwx) -{ - Actual_Socket s; - *state = 0; - s = index234(sktree, (*state)++); - if (s) - set_rwx(s, rwx); - return s ? s->s : -1; -} - -int next_socket(int *state, int *rwx) -{ - Actual_Socket s = index234(sktree, (*state)++); - if (s) - set_rwx(s, rwx); - return s ? s->s : -1; + rwx |= 1; /* read == accept */ + uxsel_set(s->s, rwx, net_select_result); } int net_service_lookup(char *service) diff --git a/unix/uxplink.c b/unix/uxplink.c index e71e6446..a62d34eb 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -273,9 +273,9 @@ int main(int argc, char **argv) { int sending; int portnumber = -1; - int *sklist; - int socket; - int i, skcount, sksize, socketstate; + int *fdlist; + int fd; + int i, fdcount, fdsize, fdstate; int connopen; int exitcode; int errors; @@ -283,8 +283,8 @@ int main(int argc, char **argv) ssh_get_line = console_get_line; - sklist = NULL; - skcount = sksize = 0; + fdlist = NULL; + fdcount = fdsize = 0; /* * Initialise port and protocol to sensible defaults. (These * will be overridden by more or less anything.) @@ -559,6 +559,7 @@ int main(int argc, char **argv) putty_signal(SIGWINCH, sigwinch); sk_init(); + uxsel_init(); /* * Start up the connection. @@ -623,31 +624,31 @@ int main(int argc, char **argv) FD_SET_MAX(2, maxfd, wset); } - /* Count the currently active sockets. */ + /* Count the currently active fds. */ i = 0; - for (socket = first_socket(&socketstate, &rwx); socket >= 0; - socket = next_socket(&socketstate, &rwx)) i++; + for (fd = first_fd(&fdstate, &rwx); fd >= 0; + fd = next_fd(&fdstate, &rwx)) i++; - /* Expand the sklist buffer if necessary. */ - if (i > sksize) { - sksize = i + 16; - sklist = sresize(sklist, sksize, int); + /* Expand the fdlist buffer if necessary. */ + if (i > fdsize) { + fdsize = i + 16; + fdlist = sresize(fdlist, fdsize, int); } /* - * Add all currently open sockets to the select sets, and - * store them in sklist as well. + * Add all currently open fds to the select sets, and store + * them in fdlist as well. */ - skcount = 0; - for (socket = first_socket(&socketstate, &rwx); socket >= 0; - socket = next_socket(&socketstate, &rwx)) { - sklist[skcount++] = socket; + fdcount = 0; + for (fd = first_fd(&fdstate, &rwx); fd >= 0; + fd = next_fd(&fdstate, &rwx)) { + fdlist[fdcount++] = fd; if (rwx & 1) - FD_SET_MAX(socket, maxfd, rset); + FD_SET_MAX(fd, maxfd, rset); if (rwx & 2) - FD_SET_MAX(socket, maxfd, wset); + FD_SET_MAX(fd, maxfd, wset); if (rwx & 4) - FD_SET_MAX(socket, maxfd, xset); + FD_SET_MAX(fd, maxfd, xset); } do { @@ -659,19 +660,19 @@ int main(int argc, char **argv) exit(1); } - for (i = 0; i < skcount; i++) { - socket = sklist[i]; + for (i = 0; i < fdcount; i++) { + fd = fdlist[i]; /* * We must process exceptional notifications before * ordinary readability ones, or we may go straight * past the urgent marker. */ - if (FD_ISSET(socket, &xset)) - select_result(socket, 4); - if (FD_ISSET(socket, &rset)) - select_result(socket, 1); - if (FD_ISSET(socket, &wset)) - select_result(socket, 2); + if (FD_ISSET(fd, &xset)) + select_result(fd, 4); + if (FD_ISSET(fd, &rset)) + select_result(fd, 1); + if (FD_ISSET(fd, &wset)) + select_result(fd, 2); } if (FD_ISSET(signalpipe[0], &rset)) { diff --git a/unix/uxsel.c b/unix/uxsel.c new file mode 100644 index 00000000..aaedc022 --- /dev/null +++ b/unix/uxsel.c @@ -0,0 +1,116 @@ +/* + * uxsel.c + * + * This module is a sort of all-purpose interchange for file + * descriptors. At one end it talks to uxnet.c and pty.c and + * anything else which might have one or more fds that need + * select()-type things doing to them during an extended program + * run; at the other end it talks to pterm.c or uxplink.c or + * anything else which might have its own means of actually doing + * those select()-type things. + */ + +#include + +#include "putty.h" +#include "tree234.h" + +struct fd { + int fd; + int rwx; /* 4=except 2=write 1=read */ + uxsel_callback_fn callback; +}; + +static tree234 *fds; + +static int uxsel_fd_cmp(void *av, void *bv) +{ + struct fd *a = (struct fd *)av; + struct fd *b = (struct fd *)bv; + if (a->fd < b->fd) + return -1; + if (a->fd > b->fd) + return +1; + return 0; +} +static int uxsel_fd_findcmp(void *av, void *bv) +{ + int *a = (int *)av; + struct fd *b = (struct fd *)bv; + if (*a < b->fd) + return -1; + if (*a > b->fd) + return +1; + return 0; +} + +void uxsel_init(void) +{ + fds = newtree234(uxsel_fd_cmp); +} + +/* + * Here is the interface to fd-supplying modules. They supply an + * fd, a set of read/write/execute states, and a callback function + * for when the fd satisfies one of those states. Repeated calls to + * uxsel_set on the same fd are perfectly legal and serve to change + * the rwx state (typically you only want to select an fd for + * writing when you actually have pending data you want to write to + * it!). + */ + +void uxsel_set(int fd, int rwx, uxsel_callback_fn callback) +{ + struct fd *newfd = snew(struct fd); + struct fd *oldfd; + + newfd->fd = fd; + newfd->rwx = rwx; + newfd->callback = callback; + + oldfd = find234(fds, newfd, NULL); + if (oldfd) { + del234(fds, oldfd); + sfree(oldfd); + } + + add234(fds, newfd); +} + +void uxsel_del(int fd) +{ + struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp); + if (oldfd) { + del234(fds, oldfd); + sfree(oldfd); + } +} + +/* + * And here is the interface to select-functionality-supplying + * modules. + */ + +int next_fd(int *state, int *rwx) +{ + struct fd *fd; + fd = index234(fds, (*state)++); + if (fd) { + *rwx = fd->rwx; + return fd->fd; + } else + return -1; +} + +int first_fd(int *state, int *rwx) +{ + *state = 0; + return next_fd(state, rwx); +} + +int select_result(int fd, int event) +{ + struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp); + assert(fdstruct != NULL); + return fdstruct->callback(fd, event); +} -- 2.11.0