SOCKET: Implement missing non-blocking for TCP sockets opened with connect

Outbound connections are rare and most may have wanted explicit blocking
behavior, so no one noticed the missing non-blocking case.

Any place which did do outbound connects have explicitly added
SIM_SOCK_OPT_BLOCKING so that the prior behavior is preserved.

The SIM_SOCK_OPT_BLOCKING flag is no honored as it was originally
intended to be.
This commit is contained in:
Mark Pizzolato 2020-03-18 00:47:48 -07:00
parent b848cb1234
commit 89cd649c77
4 changed files with 28 additions and 11 deletions

View file

@ -917,7 +917,7 @@ if (sta == SOCKET_ERROR) /* bind error? */
if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) {
sta = sim_setnonblock (newsock); /* set nonblocking */ sta = sim_setnonblock (newsock); /* set nonblocking */
if (sta == SOCKET_ERROR) /* fcntl error? */ if (sta == SOCKET_ERROR) /* fcntl error? */
return sim_err_sock (newsock, "fcntl"); return sim_err_sock (newsock, "setnonblock");
} }
sta = listen (newsock, 1); /* listen on socket */ sta = listen (newsock, 1); /* listen on socket */
if (sta == SOCKET_ERROR) /* listen error? */ if (sta == SOCKET_ERROR) /* listen error? */
@ -989,7 +989,7 @@ if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) {
sta = sim_setnonblock (newsock); /* set nonblocking */ sta = sim_setnonblock (newsock); /* set nonblocking */
if (sta == SOCKET_ERROR) { /* fcntl error? */ if (sta == SOCKET_ERROR) { /* fcntl error? */
p_freeaddrinfo (result); p_freeaddrinfo (result);
return sim_err_sock (newsock, "fcntl"); return sim_err_sock (newsock, "setnonblock");
} }
} }
if ((!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) && (opt_flags & SIM_SOCK_OPT_NODELAY)) { if ((!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) && (opt_flags & SIM_SOCK_OPT_NODELAY)) {
@ -1007,6 +1007,11 @@ if (!(opt_flags & SIM_SOCK_OPT_DATAGRAM)) {
if (sta == -1) if (sta == -1)
return sim_err_sock (newsock, "setsockopt KEEPALIVE"); return sim_err_sock (newsock, "setsockopt KEEPALIVE");
} }
if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) {
sta = sim_setnonblock (newsock); /* set nonblocking */
if (sta == SOCKET_ERROR) /* fcntl error? */
return sim_err_sock (newsock, "setnonblock");
}
sta = connect (newsock, result->ai_addr, result->ai_addrlen); sta = connect (newsock, result->ai_addr, result->ai_addrlen);
p_freeaddrinfo (result); p_freeaddrinfo (result);
if (sta == SOCKET_ERROR) { if (sta == SOCKET_ERROR) {
@ -1076,7 +1081,7 @@ if (connectaddr != NULL) {
if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) { if (!(opt_flags & SIM_SOCK_OPT_BLOCKING)) {
sta = sim_setnonblock (newsock); /* set nonblocking */ sta = sim_setnonblock (newsock); /* set nonblocking */
if (sta == SOCKET_ERROR) /* fcntl error? */ if (sta == SOCKET_ERROR) /* fcntl error? */
return sim_err_sock (newsock, "fcntl"); return sim_err_sock (newsock, "setnonblock");
} }
if ((opt_flags & SIM_SOCK_OPT_NODELAY)) { if ((opt_flags & SIM_SOCK_OPT_NODELAY)) {

View file

@ -120,7 +120,7 @@ int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char
SOCKET sim_master_sock_ex (const char *hostport, int *parse_status, int opt_flags); SOCKET sim_master_sock_ex (const char *hostport, int *parse_status, int opt_flags);
#define sim_master_sock(hostport, parse_status) sim_master_sock_ex(hostport, parse_status, ((sim_switches & SWMASK ('U')) ? SIM_SOCK_OPT_REUSEADDR : 0)) #define sim_master_sock(hostport, parse_status) sim_master_sock_ex(hostport, parse_status, ((sim_switches & SWMASK ('U')) ? SIM_SOCK_OPT_REUSEADDR : 0))
SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, int opt_flags); SOCKET sim_connect_sock_ex (const char *sourcehostport, const char *hostport, const char *default_host, const char *default_port, int opt_flags);
#define sim_connect_sock(hostport, default_host, default_port) sim_connect_sock_ex(NULL, hostport, default_host, default_port, 0) #define sim_connect_sock(hostport, default_host, default_port) sim_connect_sock_ex(NULL, hostport, default_host, default_port, SIM_SOCK_OPT_BLOCKING)
SOCKET sim_accept_conn_ex (SOCKET master, char **connectaddr, int opt_flags); SOCKET sim_accept_conn_ex (SOCKET master, char **connectaddr, int opt_flags);
#define sim_accept_conn(master, connectaddr) sim_accept_conn_ex(master, connectaddr, 0) #define sim_accept_conn(master, connectaddr) sim_accept_conn_ex(master, connectaddr, 0)
int sim_check_conn (SOCKET sock, int rd); int sim_check_conn (SOCKET sock, int rd);

View file

@ -1284,7 +1284,9 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se
(!lp->modem_control || (lp->modembits & TMXR_MDM_DTR))) { (!lp->modem_control || (lp->modembits & TMXR_MDM_DTR))) {
snprintf (msg, sizeof (msg) - 1, "tmxr_poll_conn() - establishing outgoing connection to: %s", lp->destination); snprintf (msg, sizeof (msg) - 1, "tmxr_poll_conn() - establishing outgoing connection to: %s", lp->destination);
tmxr_debug_connect_line (lp, msg); tmxr_debug_connect_line (lp, msg);
lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->mp->packet ? SIM_SOCK_OPT_NODELAY : 0)); lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) |
(lp->mp->packet ? SIM_SOCK_OPT_NODELAY : 0) |
SIM_SOCK_OPT_BLOCKING);
} }
} }
@ -1354,7 +1356,9 @@ if ((lp->destination) && (!lp->serport)) {
if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) { if ((!lp->modem_control) || (lp->modembits & TMXR_MDM_DTR)) {
sprintf (msg, "tmxr_reset_ln_ex() - connecting to %s", lp->destination); sprintf (msg, "tmxr_reset_ln_ex() - connecting to %s", lp->destination);
tmxr_debug_connect_line (lp, msg); tmxr_debug_connect_line (lp, msg);
lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->packet ? SIM_SOCK_OPT_NODELAY : 0)); lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) |
(lp->packet ? SIM_SOCK_OPT_NODELAY : 0) |
SIM_SOCK_OPT_BLOCKING);
} }
} }
tmxr_init_line (lp); /* initialize line state */ tmxr_init_line (lp); /* initialize line state */
@ -1644,7 +1648,9 @@ if (lp->mp && lp->modem_control) { /* This API ONLY works on mo
sprintf (msg, "tmxr_set_get_modem_bits() - establishing outgoing connection to: %s", lp->destination); sprintf (msg, "tmxr_set_get_modem_bits() - establishing outgoing connection to: %s", lp->destination);
tmxr_debug_connect_line (lp, msg); tmxr_debug_connect_line (lp, msg);
lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (lp->packet ? SIM_SOCK_OPT_NODELAY : 0)); lp->connecting = sim_connect_sock_ex (lp->datagram ? lp->port : NULL, lp->destination, "localhost", NULL, (lp->datagram ? SIM_SOCK_OPT_DATAGRAM : 0) |
(lp->packet ? SIM_SOCK_OPT_NODELAY : 0) |
SIM_SOCK_OPT_BLOCKING);
} }
} }
} }
@ -2799,7 +2805,9 @@ while (*tptr) {
else else
return sim_messagef (SCPE_ARG, "Unexpected specifier: %s\n", eptr); return sim_messagef (SCPE_ARG, "Unexpected specifier: %s\n", eptr);
} }
sock = sim_connect_sock_ex (NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); sock = sim_connect_sock_ex (NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) |
(packet ? SIM_SOCK_OPT_NODELAY : 0) |
SIM_SOCK_OPT_BLOCKING);
if (sock != INVALID_SOCKET) if (sock != INVALID_SOCKET)
sim_close_sock (sock); sim_close_sock (sock);
else else
@ -2951,7 +2959,9 @@ while (*tptr) {
return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n"); return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n");
} }
lp->packet = packet; lp->packet = packet;
sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) |
(packet ? SIM_SOCK_OPT_NODELAY : 0) |
SIM_SOCK_OPT_BLOCKING);
if (sock != INVALID_SOCKET) { if (sock != INVALID_SOCKET) {
_mux_detach_line (lp, FALSE, TRUE); _mux_detach_line (lp, FALSE, TRUE);
lp->destination = (char *)malloc(1+strlen(hostport)); lp->destination = (char *)malloc(1+strlen(hostport));
@ -3066,7 +3076,9 @@ while (*tptr) {
else else
return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n"); return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n");
} }
sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) | (packet ? SIM_SOCK_OPT_NODELAY : 0)); sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) |
(packet ? SIM_SOCK_OPT_NODELAY : 0) |
SIM_SOCK_OPT_BLOCKING);
if (sock != INVALID_SOCKET) { if (sock != INVALID_SOCKET) {
_mux_detach_line (lp, FALSE, TRUE); _mux_detach_line (lp, FALSE, TRUE);
lp->destination = (char *)malloc(1+strlen(hostport)); lp->destination = (char *)malloc(1+strlen(hostport));

View file

@ -344,7 +344,7 @@ else {
if ((rnd_val & 0xFFFF) == 0) if ((rnd_val & 0xFFFF) == 0)
++rnd_val; ++rnd_val;
sprintf (db_host, "localhost:%d", (int)(rnd_val & 0xFFFF)); sprintf (db_host, "localhost:%d", (int)(rnd_val & 0xFFFF));
slirp->db_chime = sim_connect_sock_ex (db_host, db_host, NULL, NULL, SIM_SOCK_OPT_DATAGRAM); slirp->db_chime = sim_connect_sock_ex (db_host, db_host, NULL, NULL, SIM_SOCK_OPT_DATAGRAM | SIM_SOCK_OPT_BLOCKING);
} while (slirp->db_chime == INVALID_SOCKET); } while (slirp->db_chime == INVALID_SOCKET);
memset (&pfd, 0, sizeof (pfd)); memset (&pfd, 0, sizeof (pfd));
pfd.fd = slirp->db_chime; pfd.fd = slirp->db_chime;