}
}
-int sk_hostname_is_local(char *name)
+int sk_hostname_is_local(const char *name)
{
return !strcmp(name, "localhost") ||
!strcmp(name, "::1") ||
extern char *do_select(SOCKET skt, int startup);
-Socket sk_register(void *sock, Plug plug)
+static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
{
static const struct socket_function_table fn_table = {
sk_tcp_plug,
ret->parent = ret->child = NULL;
ret->addr = NULL;
- ret->s = (SOCKET)sock;
+ ret->s = (SOCKET)ctx.p;
if (ret->s == INVALID_SOCKET) {
err = p_WSAGetLastError();
sfree(s);
}
+/*
+ * Deal with socket errors detected in try_send().
+ */
+static void socket_error_callback(void *vs)
+{
+ Actual_Socket s = (Actual_Socket)vs;
+
+ /*
+ * Just in case other socket work has caused this socket to vanish
+ * or become somehow non-erroneous before this callback arrived...
+ */
+ if (!find234(sktree, s, NULL) || !s->pending_error)
+ return;
+
+ /*
+ * An error has occurred on this socket. Pass it to the plug.
+ */
+ plug_closing(s->plug, winsock_error_string(s->pending_error),
+ s->pending_error, 0);
+}
+
/*
* The function which tries to send on a socket once it's deemed
* writable.
* plug_closing()) at some suitable future moment.
*/
s->pending_error = err;
+ queue_toplevel_callback(socket_error_callback, s);
return;
} else {
/* We're inside the Windows frontend here, so we know
#endif
int addrlen = sizeof(isa);
SOCKET t; /* socket of connection */
+ accept_ctx_t actx;
memset(&isa, 0, sizeof(isa));
err = 0;
if (err == WSATRY_AGAIN)
break;
}
+
+ actx.p = (void *)t;
+
#ifndef NO_IPV6
if (isa.ss_family == AF_INET &&
s->localhost_only &&
#endif
{
p_closesocket(t); /* dodgy WinSock let nonlocal through */
- } else if (plug_accepting(s->plug, (void*)t)) {
+ } else if (plug_accepting(s->plug, sk_tcp_accept, actx)) {
p_closesocket(t); /* denied or error */
}
}
return 1;
}
-/*
- * Deal with socket errors detected in try_send().
- */
-void net_pending_errors(void)
-{
- int i;
- Actual_Socket s;
-
- /*
- * This might be a fiddly business, because it's just possible
- * that handling a pending error on one socket might cause
- * others to be closed. (I can't think of any reason this might
- * happen in current SSH implementation, but to maintain
- * generality of this network layer I'll assume the worst.)
- *
- * So what we'll do is search the socket list for _one_ socket
- * with a pending error, and then handle it, and then search
- * the list again _from the beginning_. Repeat until we make a
- * pass with no socket errors present. That way we are
- * protected against the socket list changing under our feet.
- */
-
- do {
- for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
- if (s->pending_error) {
- /*
- * An error has occurred on this socket. Pass it to the
- * plug.
- */
- plug_closing(s->plug,
- winsock_error_string(s->pending_error),
- s->pending_error, 0);
- break;
- }
- }
- } while (s);
-}
-
/*
* Each socket abstraction contains a `void *' private field in
* which the client can keep state.