|
|
4be148 |
Tweaked a bit to apply to 1.12:
|
|
|
4be148 |
* krb5_int64 hadn't been replaced by int64_t yet.
|
|
|
4be148 |
|
|
|
4be148 |
commit 346883c48f1b9e09b1af2cf73e3b96ee8f934072
|
|
|
4be148 |
Author: Greg Hudson <ghudson@mit.edu>
|
|
|
4be148 |
Date: Wed Mar 26 13:21:45 2014 -0400
|
|
|
4be148 |
|
|
|
4be148 |
Refactor cm functions in sendto_kdc.c
|
|
|
4be148 |
|
|
|
4be148 |
Move get_curtime_ms and the cm functions near the top of the file
|
|
|
4be148 |
right after structure definitions. Except for cm_select_or_poll,
|
|
|
4be148 |
define each cm function separately for poll and for select, since the
|
|
|
4be148 |
implementations don't share much in common. Instead of
|
|
|
4be148 |
cm_unset_write, define cm_read and cm_write functions to put an fd in
|
|
|
4be148 |
read-only or write-only state. Remove the ssflags argument from
|
|
|
4be148 |
cm_add_fd and just expect the caller to make a subsequent call to
|
|
|
4be148 |
cm_read or cm_write. Always select for exceptions when using select.
|
|
|
4be148 |
(Polling for exceptions is implicit with poll).
|
|
|
4be148 |
|
|
|
4be148 |
With these changes, we no longer select/poll for reading on a TCP
|
|
|
4be148 |
connection until we are done writing to it. So in service_tcp_fd,
|
|
|
4be148 |
remove the check for unexpected read events.
|
|
|
4be148 |
|
|
|
4be148 |
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
|
|
4be148 |
index e60a375..e773a0a 100644
|
|
|
4be148 |
--- a/src/lib/krb5/os/sendto_kdc.c
|
|
|
4be148 |
+++ b/src/lib/krb5/os/sendto_kdc.c
|
|
|
4be148 |
@@ -59,8 +59,7 @@
|
|
|
4be148 |
|
|
|
4be148 |
typedef krb5_int64 time_ms;
|
|
|
4be148 |
|
|
|
4be148 |
-/* Since fd_set is large on some platforms (8K on AIX 5.2), this probably
|
|
|
4be148 |
- * shouldn't be allocated in automatic storage. */
|
|
|
4be148 |
+/* This can be pretty large, so should not be stack-allocated. */
|
|
|
4be148 |
struct select_state {
|
|
|
4be148 |
#ifdef USE_POLL
|
|
|
4be148 |
struct pollfd fds[MAX_POLLFDS];
|
|
|
4be148 |
@@ -107,6 +106,183 @@ struct conn_state {
|
|
|
4be148 |
time_ms endtime;
|
|
|
4be148 |
};
|
|
|
4be148 |
|
|
|
4be148 |
+/* Get current time in milliseconds. */
|
|
|
4be148 |
+static krb5_error_code
|
|
|
4be148 |
+get_curtime_ms(time_ms *time_out)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ struct timeval tv;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (gettimeofday(&tv, 0))
|
|
|
4be148 |
+ return errno;
|
|
|
4be148 |
+ *time_out = (time_ms)tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
|
4be148 |
+ return 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+#ifdef USE_POLL
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Find a pollfd in selstate by fd, or abort if we can't find it. */
|
|
|
4be148 |
+static inline struct pollfd *
|
|
|
4be148 |
+find_pollfd(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ int i;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ for (i = 0; i < selstate->nfds; i++) {
|
|
|
4be148 |
+ if (selstate->fds[i].fd == fd)
|
|
|
4be148 |
+ return &selstate->fds[i];
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ abort();
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+cm_init_selstate(struct select_state *selstate)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ selstate->nfds = 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_boolean
|
|
|
4be148 |
+cm_add_fd(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ if (selstate->nfds >= MAX_POLLFDS)
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+ selstate->fds[selstate->nfds].fd = fd;
|
|
|
4be148 |
+ selstate->fds[selstate->nfds].events = 0;
|
|
|
4be148 |
+ selstate->nfds++;
|
|
|
4be148 |
+ return TRUE;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+cm_remove_fd(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ struct pollfd *pfd = find_pollfd(selstate, fd);
|
|
|
4be148 |
+
|
|
|
4be148 |
+ *pfd = selstate->fds[selstate->nfds - 1];
|
|
|
4be148 |
+ selstate->nfds--;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Poll for reading (and not writing) on fd the next time we poll. */
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+cm_read(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ find_pollfd(selstate, fd)->events = POLLIN;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Poll for writing (and not reading) on fd the next time we poll. */
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+cm_write(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ find_pollfd(selstate, fd)->events = POLLOUT;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Get the output events for fd in the form of ssflags. */
|
|
|
4be148 |
+static unsigned int
|
|
|
4be148 |
+cm_get_ssflags(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ struct pollfd *pfd = find_pollfd(selstate, fd);
|
|
|
4be148 |
+
|
|
|
4be148 |
+ return ((pfd->revents & POLLIN) ? SSF_READ : 0) |
|
|
|
4be148 |
+ ((pfd->revents & POLLOUT) ? SSF_WRITE : 0) |
|
|
|
4be148 |
+ ((pfd->revents & POLLERR) ? SSF_EXCEPTION : 0);
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+#else /* not USE_POLL */
|
|
|
4be148 |
+
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+cm_init_selstate(struct select_state *selstate)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ selstate->nfds = 0;
|
|
|
4be148 |
+ selstate->max = 0;
|
|
|
4be148 |
+ FD_ZERO(&selstate->rfds);
|
|
|
4be148 |
+ FD_ZERO(&selstate->wfds);
|
|
|
4be148 |
+ FD_ZERO(&selstate->xfds);
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_boolean
|
|
|
4be148 |
+cm_add_fd(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+#ifndef _WIN32 /* On Windows FD_SETSIZE is a count, not a max value. */
|
|
|
4be148 |
+ if (fd >= FD_SETSIZE)
|
|
|
4be148 |
+ return FALSE;
|
|
|
4be148 |
+#endif
|
|
|
4be148 |
+ FD_SET(fd, &selstate->xfds);
|
|
|
4be148 |
+ if (selstate->max <= fd)
|
|
|
4be148 |
+ selstate->max = fd + 1;
|
|
|
4be148 |
+ selstate->nfds++;
|
|
|
4be148 |
+ return TRUE;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+cm_remove_fd(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ FD_CLR(fd, &selstate->rfds);
|
|
|
4be148 |
+ FD_CLR(fd, &selstate->wfds);
|
|
|
4be148 |
+ FD_CLR(fd, &selstate->xfds);
|
|
|
4be148 |
+ if (selstate->max == fd + 1) {
|
|
|
4be148 |
+ while (selstate->max > 0 &&
|
|
|
4be148 |
+ !FD_ISSET(selstate->max - 1, &selstate->rfds) &&
|
|
|
4be148 |
+ !FD_ISSET(selstate->max - 1, &selstate->wfds) &&
|
|
|
4be148 |
+ !FD_ISSET(selstate->max - 1, &selstate->xfds))
|
|
|
4be148 |
+ selstate->max--;
|
|
|
4be148 |
+ }
|
|
|
4be148 |
+ selstate->nfds--;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Select for reading (and not writing) on fd the next time we select. */
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+cm_read(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ FD_SET(fd, &selstate->rfds);
|
|
|
4be148 |
+ FD_CLR(fd, &selstate->wfds);
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Select for writing (and not reading) on fd the next time we select. */
|
|
|
4be148 |
+static void
|
|
|
4be148 |
+cm_write(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ FD_CLR(fd, &selstate->rfds);
|
|
|
4be148 |
+ FD_SET(fd, &selstate->wfds);
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+/* Get the events for fd from selstate after a select. */
|
|
|
4be148 |
+static unsigned int
|
|
|
4be148 |
+cm_get_ssflags(struct select_state *selstate, int fd)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+ return (FD_ISSET(fd, &selstate->rfds) ? SSF_READ : 0) |
|
|
|
4be148 |
+ (FD_ISSET(fd, &selstate->wfds) ? SSF_WRITE : 0) |
|
|
|
4be148 |
+ (FD_ISSET(fd, &selstate->xfds) ? SSF_EXCEPTION : 0);
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
+#endif /* not USE_POLL */
|
|
|
4be148 |
+
|
|
|
4be148 |
+static krb5_error_code
|
|
|
4be148 |
+cm_select_or_poll(const struct select_state *in, time_ms endtime,
|
|
|
4be148 |
+ struct select_state *out, int *sret)
|
|
|
4be148 |
+{
|
|
|
4be148 |
+#ifndef USE_POLL
|
|
|
4be148 |
+ struct timeval tv;
|
|
|
4be148 |
+#endif
|
|
|
4be148 |
+ krb5_error_code retval;
|
|
|
4be148 |
+ time_ms curtime, interval;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ retval = get_curtime_ms(&curtime);
|
|
|
4be148 |
+ if (retval != 0)
|
|
|
4be148 |
+ return retval;
|
|
|
4be148 |
+ interval = (curtime < endtime) ? endtime - curtime : 0;
|
|
|
4be148 |
+
|
|
|
4be148 |
+ /* We don't need a separate copy of the selstate for poll, but use one for
|
|
|
4be148 |
+ * consistency with how we use select. */
|
|
|
4be148 |
+ *out = *in;
|
|
|
4be148 |
+
|
|
|
4be148 |
+#ifdef USE_POLL
|
|
|
4be148 |
+ *sret = poll(out->fds, out->nfds, interval);
|
|
|
4be148 |
+#else
|
|
|
4be148 |
+ tv.tv_sec = interval / 1000;
|
|
|
4be148 |
+ tv.tv_usec = interval % 1000 * 1000;
|
|
|
4be148 |
+ *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, &tv;;
|
|
|
4be148 |
+#endif
|
|
|
4be148 |
+
|
|
|
4be148 |
+ return (*sret < 0) ? SOCKET_ERRNO : 0;
|
|
|
4be148 |
+}
|
|
|
4be148 |
+
|
|
|
4be148 |
static int
|
|
|
4be148 |
in_addrlist(struct server_entry *entry, struct serverlist *list)
|
|
|
4be148 |
{
|
|
|
4be148 |
@@ -251,18 +427,6 @@ cleanup:
|
|
|
4be148 |
return retval;
|
|
|
4be148 |
}
|
|
|
4be148 |
|
|
|
4be148 |
-/* Get current time in milliseconds. */
|
|
|
4be148 |
-static krb5_error_code
|
|
|
4be148 |
-get_curtime_ms(time_ms *time_out)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- struct timeval tv;
|
|
|
4be148 |
-
|
|
|
4be148 |
- if (gettimeofday(&tv, 0))
|
|
|
4be148 |
- return errno;
|
|
|
4be148 |
- *time_out = (time_ms)tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
|
4be148 |
- return 0;
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
/*
|
|
|
4be148 |
* Notes:
|
|
|
4be148 |
*
|
|
|
4be148 |
@@ -283,144 +447,6 @@ get_curtime_ms(time_ms *time_out)
|
|
|
4be148 |
* connections already in progress
|
|
|
4be148 |
*/
|
|
|
4be148 |
|
|
|
4be148 |
-static void
|
|
|
4be148 |
-cm_init_selstate(struct select_state *selstate)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- selstate->nfds = 0;
|
|
|
4be148 |
-#ifndef USE_POLL
|
|
|
4be148 |
- selstate->max = 0;
|
|
|
4be148 |
- FD_ZERO(&selstate->rfds);
|
|
|
4be148 |
- FD_ZERO(&selstate->wfds);
|
|
|
4be148 |
- FD_ZERO(&selstate->xfds);
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static krb5_boolean
|
|
|
4be148 |
-cm_add_fd(struct select_state *selstate, int fd, unsigned int ssflags)
|
|
|
4be148 |
-{
|
|
|
4be148 |
-#ifdef USE_POLL
|
|
|
4be148 |
- if (selstate->nfds >= MAX_POLLFDS)
|
|
|
4be148 |
- return FALSE;
|
|
|
4be148 |
- selstate->fds[selstate->nfds].fd = fd;
|
|
|
4be148 |
- selstate->fds[selstate->nfds].events = 0;
|
|
|
4be148 |
- if (ssflags & SSF_READ)
|
|
|
4be148 |
- selstate->fds[selstate->nfds].events |= POLLIN;
|
|
|
4be148 |
- if (ssflags & SSF_WRITE)
|
|
|
4be148 |
- selstate->fds[selstate->nfds].events |= POLLOUT;
|
|
|
4be148 |
-#else
|
|
|
4be148 |
-#ifndef _WIN32 /* On Windows FD_SETSIZE is a count, not a max value. */
|
|
|
4be148 |
- if (fd >= FD_SETSIZE)
|
|
|
4be148 |
- return FALSE;
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
- if (ssflags & SSF_READ)
|
|
|
4be148 |
- FD_SET(fd, &selstate->rfds);
|
|
|
4be148 |
- if (ssflags & SSF_WRITE)
|
|
|
4be148 |
- FD_SET(fd, &selstate->wfds);
|
|
|
4be148 |
- if (ssflags & SSF_EXCEPTION)
|
|
|
4be148 |
- FD_SET(fd, &selstate->xfds);
|
|
|
4be148 |
- if (selstate->max <= fd)
|
|
|
4be148 |
- selstate->max = fd + 1;
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
- selstate->nfds++;
|
|
|
4be148 |
- return TRUE;
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static void
|
|
|
4be148 |
-cm_remove_fd(struct select_state *selstate, int fd)
|
|
|
4be148 |
-{
|
|
|
4be148 |
-#ifdef USE_POLL
|
|
|
4be148 |
- int i;
|
|
|
4be148 |
-
|
|
|
4be148 |
- /* Find the FD in the array and move the last entry to its place. */
|
|
|
4be148 |
- assert(selstate->nfds > 0);
|
|
|
4be148 |
- for (i = 0; i < selstate->nfds && selstate->fds[i].fd != fd; i++);
|
|
|
4be148 |
- assert(i < selstate->nfds);
|
|
|
4be148 |
- selstate->fds[i] = selstate->fds[selstate->nfds - 1];
|
|
|
4be148 |
-#else
|
|
|
4be148 |
- FD_CLR(fd, &selstate->rfds);
|
|
|
4be148 |
- FD_CLR(fd, &selstate->wfds);
|
|
|
4be148 |
- FD_CLR(fd, &selstate->xfds);
|
|
|
4be148 |
- if (selstate->max == 1 + fd) {
|
|
|
4be148 |
- while (selstate->max > 0
|
|
|
4be148 |
- && ! FD_ISSET(selstate->max-1, &selstate->rfds)
|
|
|
4be148 |
- && ! FD_ISSET(selstate->max-1, &selstate->wfds)
|
|
|
4be148 |
- && ! FD_ISSET(selstate->max-1, &selstate->xfds))
|
|
|
4be148 |
- selstate->max--;
|
|
|
4be148 |
- }
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
- selstate->nfds--;
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static void
|
|
|
4be148 |
-cm_unset_write(struct select_state *selstate, int fd)
|
|
|
4be148 |
-{
|
|
|
4be148 |
-#ifdef USE_POLL
|
|
|
4be148 |
- int i;
|
|
|
4be148 |
-
|
|
|
4be148 |
- for (i = 0; i < selstate->nfds && selstate->fds[i].fd != fd; i++);
|
|
|
4be148 |
- assert(i < selstate->nfds);
|
|
|
4be148 |
- selstate->fds[i].events &= ~POLLOUT;
|
|
|
4be148 |
-#else
|
|
|
4be148 |
- FD_CLR(fd, &selstate->wfds);
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static krb5_error_code
|
|
|
4be148 |
-cm_select_or_poll(const struct select_state *in, time_ms endtime,
|
|
|
4be148 |
- struct select_state *out, int *sret)
|
|
|
4be148 |
-{
|
|
|
4be148 |
-#ifndef USE_POLL
|
|
|
4be148 |
- struct timeval tv;
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
- krb5_error_code retval;
|
|
|
4be148 |
- time_ms curtime, interval;
|
|
|
4be148 |
-
|
|
|
4be148 |
- retval = get_curtime_ms(&curtime);
|
|
|
4be148 |
- if (retval != 0)
|
|
|
4be148 |
- return retval;
|
|
|
4be148 |
- interval = (curtime < endtime) ? endtime - curtime : 0;
|
|
|
4be148 |
-
|
|
|
4be148 |
- /* We don't need a separate copy of the selstate for poll, but use one for
|
|
|
4be148 |
- * consistency with how we use select. */
|
|
|
4be148 |
- *out = *in;
|
|
|
4be148 |
-
|
|
|
4be148 |
-#ifdef USE_POLL
|
|
|
4be148 |
- *sret = poll(out->fds, out->nfds, interval);
|
|
|
4be148 |
-#else
|
|
|
4be148 |
- tv.tv_sec = interval / 1000;
|
|
|
4be148 |
- tv.tv_usec = interval % 1000 * 1000;
|
|
|
4be148 |
- *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, &tv;;
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
-
|
|
|
4be148 |
- return (*sret < 0) ? SOCKET_ERRNO : 0;
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
-static unsigned int
|
|
|
4be148 |
-cm_get_ssflags(struct select_state *selstate, int fd)
|
|
|
4be148 |
-{
|
|
|
4be148 |
- unsigned int ssflags = 0;
|
|
|
4be148 |
-#ifdef USE_POLL
|
|
|
4be148 |
- int i;
|
|
|
4be148 |
-
|
|
|
4be148 |
- for (i = 0; i < selstate->nfds && selstate->fds[i].fd != fd; i++);
|
|
|
4be148 |
- assert(i < selstate->nfds);
|
|
|
4be148 |
- if (selstate->fds[i].revents & POLLIN)
|
|
|
4be148 |
- ssflags |= SSF_READ;
|
|
|
4be148 |
- if (selstate->fds[i].revents & POLLOUT)
|
|
|
4be148 |
- ssflags |= SSF_WRITE;
|
|
|
4be148 |
- if (selstate->fds[i].revents & POLLERR)
|
|
|
4be148 |
- ssflags |= SSF_EXCEPTION;
|
|
|
4be148 |
-#else
|
|
|
4be148 |
- if (FD_ISSET(fd, &selstate->rfds))
|
|
|
4be148 |
- ssflags |= SSF_READ;
|
|
|
4be148 |
- if (FD_ISSET(fd, &selstate->wfds))
|
|
|
4be148 |
- ssflags |= SSF_WRITE;
|
|
|
4be148 |
- if (FD_ISSET(fd, &selstate->xfds))
|
|
|
4be148 |
- ssflags |= SSF_EXCEPTION;
|
|
|
4be148 |
-#endif
|
|
|
4be148 |
- return ssflags;
|
|
|
4be148 |
-}
|
|
|
4be148 |
-
|
|
|
4be148 |
static int service_tcp_fd(krb5_context context, struct conn_state *conn,
|
|
|
4be148 |
struct select_state *selstate, int ssflags);
|
|
|
4be148 |
static int service_udp_fd(krb5_context context, struct conn_state *conn,
|
|
|
4be148 |
@@ -600,7 +626,6 @@ start_connection(krb5_context context, struct conn_state *state,
|
|
|
4be148 |
struct sendto_callback_info *callback_info)
|
|
|
4be148 |
{
|
|
|
4be148 |
int fd, e;
|
|
|
4be148 |
- unsigned int ssflags;
|
|
|
4be148 |
static const int one = 1;
|
|
|
4be148 |
static const struct linger lopt = { 0, 0 };
|
|
|
4be148 |
|
|
|
4be148 |
@@ -676,15 +701,17 @@ start_connection(krb5_context context, struct conn_state *state,
|
|
|
4be148 |
state->state = READING;
|
|
|
4be148 |
}
|
|
|
4be148 |
}
|
|
|
4be148 |
- ssflags = SSF_READ | SSF_EXCEPTION;
|
|
|
4be148 |
- if (state->state == CONNECTING || state->state == WRITING)
|
|
|
4be148 |
- ssflags |= SSF_WRITE;
|
|
|
4be148 |
- if (!cm_add_fd(selstate, state->fd, ssflags)) {
|
|
|
4be148 |
+
|
|
|
4be148 |
+ if (!cm_add_fd(selstate, state->fd)) {
|
|
|
4be148 |
(void) closesocket(state->fd);
|
|
|
4be148 |
state->fd = INVALID_SOCKET;
|
|
|
4be148 |
state->state = FAILED;
|
|
|
4be148 |
return -1;
|
|
|
4be148 |
}
|
|
|
4be148 |
+ if (state->state == CONNECTING || state->state == WRITING)
|
|
|
4be148 |
+ cm_write(selstate, state->fd);
|
|
|
4be148 |
+ else
|
|
|
4be148 |
+ cm_read(selstate, state->fd);
|
|
|
4be148 |
|
|
|
4be148 |
return 0;
|
|
|
4be148 |
}
|
|
|
4be148 |
@@ -768,9 +795,8 @@ service_tcp_fd(krb5_context context, struct conn_state *conn,
|
|
|
4be148 |
ssize_t nwritten, nread;
|
|
|
4be148 |
SOCKET_WRITEV_TEMP tmp;
|
|
|
4be148 |
|
|
|
4be148 |
- /* Check for a socket exception or readable data before we expect it. */
|
|
|
4be148 |
- if (ssflags & SSF_EXCEPTION ||
|
|
|
4be148 |
- ((ssflags & SSF_READ) && conn->state != READING))
|
|
|
4be148 |
+ /* Check for a socket exception. */
|
|
|
4be148 |
+ if (ssflags & SSF_EXCEPTION)
|
|
|
4be148 |
goto kill_conn;
|
|
|
4be148 |
|
|
|
4be148 |
switch (conn->state) {
|
|
|
4be148 |
@@ -810,7 +836,7 @@ service_tcp_fd(krb5_context context, struct conn_state *conn,
|
|
|
4be148 |
}
|
|
|
4be148 |
if (conn->x.out.sg_count == 0) {
|
|
|
4be148 |
/* Done writing, switch to reading. */
|
|
|
4be148 |
- cm_unset_write(selstate, conn->fd);
|
|
|
4be148 |
+ cm_read(selstate, conn->fd);
|
|
|
4be148 |
conn->state = READING;
|
|
|
4be148 |
conn->x.in.bufsizebytes_read = 0;
|
|
|
4be148 |
conn->x.in.bufsize = 0;
|