diff options
Diffstat (limited to 'Utilities/cmcurl/lib/cf-socket.c')
-rw-r--r-- | Utilities/cmcurl/lib/cf-socket.c | 147 |
1 files changed, 80 insertions, 67 deletions
diff --git a/Utilities/cmcurl/lib/cf-socket.c b/Utilities/cmcurl/lib/cf-socket.c index 2549f3456b..6d9ace4261 100644 --- a/Utilities/cmcurl/lib/cf-socket.c +++ b/Utilities/cmcurl/lib/cf-socket.c @@ -253,19 +253,6 @@ static CURLcode socket_open(struct Curl_easy *data, else { /* opensocket callback not set, so simply create the socket now */ *sockfd = socket(addr->family, addr->socktype, addr->protocol); - if(!*sockfd && addr->socktype == SOCK_DGRAM) { - /* This is icky and seems, at least, to happen on macOS: - * we get sockfd == 0 and if called again, we get a valid one > 0. - * If we close the 0, we sometimes get failures in multi poll, as - * 0 seems also be the fd for the sockpair used for WAKEUP polling. - * Very strange. Maybe this code should be ifdef'ed for macOS, but - * on "real" OS, fd 0 is stdin and we never see that. So... - */ - fake_sclose(*sockfd); - *sockfd = socket(addr->family, addr->socktype, addr->protocol); - DEBUGF(infof(data, "QUIRK: UDP socket() gave handle 0, 2nd attempt %d", - (int)*sockfd)); - } } if(*sockfd == CURL_SOCKET_BAD) @@ -338,20 +325,6 @@ int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn, return socket_close(data, conn, FALSE, sock); } -bool Curl_socket_is_dead(curl_socket_t sock) -{ - int sval; - bool ret_val = TRUE; - - sval = SOCKET_READABLE(sock, 0); - if(sval == 0) - /* timeout */ - ret_val = FALSE; - - return ret_val; -} - - #ifdef USE_WINSOCK /* When you run a program that uses the Windows Sockets API, you may experience slow performance when you copy data to a TCP server. @@ -522,7 +495,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, conn->ip_version = CURL_IPRESOLVE_V6; #endif - rc = Curl_resolv(data, dev, 0, FALSE, &h); + rc = Curl_resolv(data, dev, 80, FALSE, &h); if(rc == CURLRESOLV_PENDING) (void)Curl_resolver_wait_resolv(data, &h); conn->ip_version = ipver; @@ -1084,6 +1057,11 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, if(result) goto out; + if(cf->connected) { + *done = TRUE; + return CURLE_OK; + } + /* Connect TCP socket */ rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen); if(-1 == rc) { @@ -1449,22 +1427,6 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf, case CF_CTRL_CONN_INFO_UPDATE: cf_socket_active(cf, data); break; - case CF_CTRL_CONN_REPORT_STATS: - switch(ctx->transport) { - case TRNSPRT_UDP: - case TRNSPRT_QUIC: - /* Since UDP connected sockets work different from TCP, we use the - * time of the first byte from the peer as the "connect" time. */ - if(ctx->got_first_byte) { - Curl_pgrsTimeWas(data, TIMER_CONNECT, ctx->first_byte_at); - break; - } - /* FALLTHROUGH */ - default: - Curl_pgrsTimeWas(data, TIMER_CONNECT, ctx->connected_at); - break; - } - break; case CF_CTRL_DATA_SETUP: Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port); break; @@ -1473,38 +1435,39 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf, } static bool cf_socket_conn_is_alive(struct Curl_cfilter *cf, - struct Curl_easy *data) + struct Curl_easy *data, + bool *input_pending) { struct cf_socket_ctx *ctx = cf->ctx; - int sval; + struct pollfd pfd[1]; + int r; + *input_pending = FALSE; (void)data; if(!ctx || ctx->sock == CURL_SOCKET_BAD) return FALSE; - sval = SOCKET_READABLE(ctx->sock, 0); - if(sval == 0) { - /* timeout */ - return TRUE; - } - else if(sval & CURL_CSELECT_ERR) { - /* socket is in an error state */ + /* Check with 0 timeout if there are any events pending on the socket */ + pfd[0].fd = ctx->sock; + pfd[0].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[0].revents = 0; + + r = Curl_poll(pfd, 1, 0); + if(r < 0) { + DEBUGF(LOG_CF(data, cf, "is_alive: poll error, assume dead")); return FALSE; } - else if(sval & CURL_CSELECT_IN) { - /* readable with no error. could still be closed */ -/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ -#ifdef MSG_PEEK - /* use the socket */ - char buf; - if(recv((RECV_TYPE_ARG1)ctx->sock, (RECV_TYPE_ARG2)&buf, - (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { - return FALSE; /* FIN received */ - } -#endif + else if(r == 0) { + DEBUGF(LOG_CF(data, cf, "is_alive: poll timeout, assume alive")); return TRUE; } + else if(pfd[0].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) { + DEBUGF(LOG_CF(data, cf, "is_alive: err/hup/etc events, assume dead")); + return FALSE; + } + DEBUGF(LOG_CF(data, cf, "is_alive: valid events, looks alive")); + *input_pending = TRUE; return TRUE; } @@ -1527,6 +1490,24 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf, else *pres1 = -1; return CURLE_OK; + case CF_QUERY_TIMER_CONNECT: { + struct curltime *when = pres2; + switch(ctx->transport) { + case TRNSPRT_UDP: + case TRNSPRT_QUIC: + /* Since UDP connected sockets work different from TCP, we use the + * time of the first byte from the peer as the "connect" time. */ + if(ctx->got_first_byte) { + *when = ctx->first_byte_at; + break; + } + /* FALLTHROUGH */ + default: + *when = ctx->connected_at; + break; + } + return CURLE_OK; + } default: break; } @@ -1826,7 +1807,6 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data, Curl_conn_cf_add(data, conn, sockindex, cf); conn->sock[sockindex] = ctx->sock; - set_remote_ip(cf, data); set_local_ip(cf, data); ctx->active = TRUE; ctx->connected_at = Curl_now(); @@ -1841,6 +1821,38 @@ out: return result; } +static void set_accepted_remote_ip(struct Curl_cfilter *cf, + struct Curl_easy *data) +{ + struct cf_socket_ctx *ctx = cf->ctx; +#ifdef HAVE_GETPEERNAME + char buffer[STRERROR_LEN]; + struct Curl_sockaddr_storage ssrem; + curl_socklen_t plen; + + ctx->r_ip[0] = 0; + ctx->r_port = 0; + plen = sizeof(ssrem); + memset(&ssrem, 0, plen); + if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) { + int error = SOCKERRNO; + failf(data, "getpeername() failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + return; + } + if(!Curl_addr2string((struct sockaddr*)&ssrem, plen, + ctx->r_ip, &ctx->r_port)) { + failf(data, "ssrem inet_ntop() failed with errno %d: %s", + errno, Curl_strerror(errno, buffer, sizeof(buffer))); + return; + } +#else + ctx->r_ip[0] = 0; + ctx->r_port = 0; + (void)data; +#endif +} + CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data, struct connectdata *conn, int sockindex, curl_socket_t *s) @@ -1857,13 +1869,14 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data, socket_close(data, conn, TRUE, ctx->sock); ctx->sock = *s; conn->sock[sockindex] = ctx->sock; - set_remote_ip(cf, data); + set_accepted_remote_ip(cf, data); set_local_ip(cf, data); ctx->active = TRUE; ctx->accepted = TRUE; ctx->connected_at = Curl_now(); cf->connected = TRUE; - DEBUGF(LOG_CF(data, cf, "Curl_conn_tcp_accepted_set(%d)", (int)ctx->sock)); + DEBUGF(LOG_CF(data, cf, "accepted_set(sock=%d, remote=%s port=%d)", + (int)ctx->sock, ctx->r_ip, ctx->r_port)); return CURLE_OK; } |