summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/cf-socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/cf-socket.c')
-rw-r--r--libs/libcurl/src/cf-socket.c293
1 files changed, 151 insertions, 142 deletions
diff --git a/libs/libcurl/src/cf-socket.c b/libs/libcurl/src/cf-socket.c
index 89f19cb317..9e85ee211a 100644
--- a/libs/libcurl/src/cf-socket.c
+++ b/libs/libcurl/src/cf-socket.c
@@ -74,15 +74,17 @@
#include "multiif.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "inet_ntop.h"
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "progress.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "conncache.h"
#include "multihandle.h"
#include "rand.h"
#include "share.h"
#include "strdup.h"
-#include "version_win32.h"
+#include "system_win32.h"
+#include "curlx/version_win32.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -113,8 +115,8 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
int level = IPPROTO_TCP;
char buffer[STRERROR_LEN];
- if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
- sizeof(onoff)) < 0)
+ if(setsockopt(sockfd, level, TCP_NODELAY,
+ (void *)&onoff, sizeof(onoff)) < 0)
infof(data, "Could not set TCP_NODELAY: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
#else
@@ -133,8 +135,8 @@ static void nosigpipe(struct Curl_easy *data,
{
int onoff = 1;
(void)data;
- if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
- sizeof(onoff)) < 0) {
+ if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE,
+ (void *)&onoff, sizeof(onoff)) < 0) {
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char buffer[STRERROR_LEN];
infof(data, "Could not set SO_NOSIGPIPE: %s",
@@ -181,7 +183,7 @@ tcpkeepalive(struct Curl_easy *data,
/* only set IDLE and INTVL if setting KEEPALIVE is successful */
if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
- (void *)&optval, sizeof(optval)) < 0) {
+ (void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set SO_KEEPALIVE on fd "
"%" FMT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
@@ -234,7 +236,7 @@ tcpkeepalive(struct Curl_easy *data,
optval = curlx_sltosi(data->set.tcp_keepidle);
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
- (void *)&optval, sizeof(optval)) < 0) {
+ (void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set TCP_KEEPIDLE on fd "
"%" FMT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
@@ -244,7 +246,7 @@ tcpkeepalive(struct Curl_easy *data,
optval = curlx_sltosi(data->set.tcp_keepidle);
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
- (void *)&optval, sizeof(optval)) < 0) {
+ (void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set TCP_KEEPALIVE on fd "
"%" FMT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
@@ -254,7 +256,7 @@ tcpkeepalive(struct Curl_easy *data,
optval = curlx_sltosi(data->set.tcp_keepidle);
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
- (void *)&optval, sizeof(optval)) < 0) {
+ (void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set TCP_KEEPALIVE_THRESHOLD on fd "
"%" FMT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
@@ -264,7 +266,7 @@ tcpkeepalive(struct Curl_easy *data,
optval = curlx_sltosi(data->set.tcp_keepintvl);
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
- (void *)&optval, sizeof(optval)) < 0) {
+ (void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set TCP_KEEPINTVL on fd "
"%" FMT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
@@ -285,7 +287,7 @@ tcpkeepalive(struct Curl_easy *data,
curlx_sltosi(data->set.tcp_keepintvl);
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD,
- (void *)&optval, sizeof(optval)) < 0) {
+ (void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set TCP_KEEPALIVE_ABORT_THRESHOLD on fd "
"%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO);
}
@@ -293,7 +295,7 @@ tcpkeepalive(struct Curl_easy *data,
#ifdef TCP_KEEPCNT
optval = curlx_sltosi(data->set.tcp_keepcnt);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT,
- (void *)&optval, sizeof(optval)) < 0) {
+ (void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set TCP_KEEPCNT on fd "
"%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO);
}
@@ -306,9 +308,9 @@ tcpkeepalive(struct Curl_easy *data,
* Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
-void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
- const struct Curl_addrinfo *ai,
- int transport)
+CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
+ const struct Curl_addrinfo *ai,
+ int transport)
{
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
@@ -334,9 +336,13 @@ void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
}
dest->addrlen = (unsigned int)ai->ai_addrlen;
- if(dest->addrlen > sizeof(struct Curl_sockaddr_storage))
- dest->addrlen = sizeof(struct Curl_sockaddr_storage);
+ if(dest->addrlen > sizeof(struct Curl_sockaddr_storage)) {
+ DEBUGASSERT(0);
+ return CURLE_TOO_LARGE;
+ }
+
memcpy(&dest->curl_sa_addr, ai->ai_addr, dest->addrlen);
+ return CURLE_OK;
}
static CURLcode socket_open(struct Curl_easy *data,
@@ -395,12 +401,16 @@ CURLcode Curl_socket_open(struct Curl_easy *data,
curl_socket_t *sockfd)
{
struct Curl_sockaddr_ex dummy;
+ CURLcode result;
if(!addr)
/* if the caller does not want info back, use a local temp copy */
addr = &dummy;
- Curl_sock_assign_addr(addr, ai, transport);
+ result = Curl_sock_assign_addr(addr, ai, transport);
+ if(result)
+ return result;
+
return socket_open(data, addr, sockfd);
}
@@ -412,7 +422,7 @@ static int socket_close(struct Curl_easy *data, struct connectdata *conn,
if(use_callback && conn && conn->fclosesocket) {
int rc;
- Curl_multi_closed(data, sock);
+ Curl_multi_will_close(data, sock);
Curl_set_in_callback(data, TRUE);
rc = conn->fclosesocket(conn->closesocket_client, sock);
Curl_set_in_callback(data, FALSE);
@@ -421,7 +431,7 @@ static int socket_close(struct Curl_easy *data, struct connectdata *conn,
if(conn)
/* tell the multi-socket code about this */
- Curl_multi_closed(data, sock);
+ Curl_multi_will_close(data, sock);
sclose(sock);
@@ -452,9 +462,6 @@ int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn,
Windows. Following function trying to detect OS version and skips
SO_SNDBUF adjustment for Windows Vista and above.
*/
-#define DETECT_OS_NONE 0
-#define DETECT_OS_PREVISTA 1
-#define DETECT_OS_VISTA_OR_LATER 2
void Curl_sndbuf_init(curl_socket_t sockfd)
{
@@ -462,17 +469,7 @@ void Curl_sndbuf_init(curl_socket_t sockfd)
int curval = 0;
int curlen = sizeof(curval);
- static int detectOsState = DETECT_OS_NONE;
-
- if(detectOsState == DETECT_OS_NONE) {
- if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
- VERSION_GREATER_THAN_EQUAL))
- detectOsState = DETECT_OS_VISTA_OR_LATER;
- else
- detectOsState = DETECT_OS_PREVISTA;
- }
-
- if(detectOsState == DETECT_OS_VISTA_OR_LATER)
+ if(Curl_isVistaOrGreater)
return;
if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
@@ -600,36 +597,39 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
if(!iface && !host && !port)
/* no local kind of binding was requested */
return CURLE_OK;
+ else if(iface && (strlen(iface) >= 255) )
+ return CURLE_BAD_FUNCTION_ARGUMENT;
memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
- if(iface && (strlen(iface) < 255) ) {
+ if(iface || host) {
char myhost[256] = "";
int done = 0; /* -1 for error, 1 for address found */
if2ip_result_t if2ip_result = IF2IP_NOT_FOUND;
- /* interface */
#ifdef SO_BINDTODEVICE
- /*
- * This binds the local socket to a particular interface. This will
- * force even requests to other local interfaces to go out the external
- * interface. Only bind to the interface when specified as interface,
- * not just as a hostname or ip address.
- *
- * The interface might be a VRF, eg: vrf-blue, which means it cannot be
- * converted to an IP address and would fail Curl_if2ip. Simply try to
- * use it straight away.
- */
- if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
- iface, (curl_socklen_t)strlen(iface) + 1) == 0) {
- /* This is often "errno 1, error: Operation not permitted" if you are
- * not running as root or another suitable privileged user. If it
- * succeeds it means the parameter was a valid interface and not an IP
- * address. Return immediately.
- */
- if(!host_input) {
- infof(data, "socket successfully bound to interface '%s'", iface);
- return CURLE_OK;
+ if(iface) {
+ /*
+ * This binds the local socket to a particular interface. This will
+ * force even requests to other local interfaces to go out the external
+ * interface. Only bind to the interface when specified as interface,
+ * not just as a hostname or ip address.
+ *
+ * The interface might be a VRF, eg: vrf-blue, which means it cannot be
+ * converted to an IP address and would fail Curl_if2ip. Simply try to
+ * use it straight away.
+ */
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+ iface, (curl_socklen_t)strlen(iface) + 1) == 0) {
+ /* This is often "errno 1, error: Operation not permitted" if you are
+ * not running as root or another suitable privileged user. If it
+ * succeeds it means the parameter was a valid interface and not an IP
+ * address. Return immediately.
+ */
+ if(!host_input) {
+ infof(data, "socket successfully bound to interface '%s'", iface);
+ return CURLE_OK;
+ }
}
}
#endif
@@ -674,21 +674,14 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
* of the connection. The resolve functions should really be changed
* to take a type parameter instead.
*/
- unsigned char ipver = conn->ip_version;
- int rc;
-
- if(af == AF_INET)
- conn->ip_version = CURL_IPRESOLVE_V4;
+ int ip_version = (af == AF_INET) ?
+ CURL_IPRESOLVE_V4 : CURL_IPRESOLVE_WHATEVER;
#ifdef USE_IPV6
- else if(af == AF_INET6)
- conn->ip_version = CURL_IPRESOLVE_V6;
+ if(af == AF_INET6)
+ ip_version = CURL_IPRESOLVE_V6;
#endif
- rc = Curl_resolv(data, host, 80, FALSE, &h);
- if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(data, &h);
- conn->ip_version = ipver;
-
+ (void)Curl_resolv_blocking(data, host, 80, ip_version, &h);
if(h) {
int h_af = h->addr->ai_family;
/* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
@@ -721,7 +714,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
if(scope_ptr)
*(scope_ptr++) = '\0';
#endif
- if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
+ if(curlx_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
si6->sin6_family = AF_INET6;
si6->sin6_port = htons(port);
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
@@ -730,10 +723,10 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
Curl_printable_address. The latter returns only numeric scope
IDs and the former returns none at all. So the scope ID, if
present, is known to be numeric */
- unsigned long scope_id = strtoul(scope_ptr, NULL, 10);
- if(scope_id > UINT_MAX)
+ curl_off_t scope_id;
+ if(curlx_str_number((const char **)CURL_UNCONST(&scope_ptr),
+ &scope_id, UINT_MAX))
return CURLE_UNSUPPORTED_PROTOCOL;
-
si6->sin6_scope_id = (unsigned int)scope_id;
}
#endif
@@ -744,7 +737,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
#endif
/* IPv4 address */
if((af == AF_INET) &&
- (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
+ (curlx_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
si4->sin_family = AF_INET;
si4->sin_port = htons(port);
sizeof_sa = sizeof(struct sockaddr_in);
@@ -844,7 +837,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
* Someone got to verify this on Win-NT 4.0, 2000."
*/
-#ifdef _WIN32_WCE
+#ifdef UNDER_CE
Sleep(0);
#else
SleepEx(0, FALSE);
@@ -854,7 +847,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
err = SOCKERRNO;
-#ifdef _WIN32_WCE
+#ifdef UNDER_CE
/* Old Windows CE versions do not support SO_ERROR */
if(WSAENOPROTOOPT == err) {
SET_SOCKERRNO(0);
@@ -868,7 +861,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
err = 0;
}
#endif
- if((0 == err) || (EISCONN == err))
+ if((0 == err) || (SOCKEISCONN == err))
/* we are connected, awesome! */
rc = TRUE;
else
@@ -891,10 +884,10 @@ static CURLcode socket_connect_result(struct Curl_easy *data,
const char *ipaddress, int error)
{
switch(error) {
- case EINPROGRESS:
- case EWOULDBLOCK:
+ case SOCKEINPROGRESS:
+ case SOCKEWOULDBLOCK:
#if defined(EAGAIN)
-#if (EAGAIN) != (EWOULDBLOCK)
+#if (EAGAIN) != (SOCKEWOULDBLOCK)
/* On some platforms EAGAIN and EWOULDBLOCK are the
* same value, and on others they are different, hence
* the odd #if
@@ -921,15 +914,6 @@ static CURLcode socket_connect_result(struct Curl_easy *data,
}
}
-/* We have a recv buffer to enhance reads with len < NW_SMALL_READS.
- * This happens often on TLS connections where the TLS implementation
- * tries to read the head of a TLS record, determine the length of the
- * full record and then make a subsequent read for that.
- * On large reads, we will not fill the buffer to avoid the double copy. */
-#define NW_RECV_CHUNK_SIZE (64 * 1024)
-#define NW_RECV_CHUNKS 1
-#define NW_SMALL_READS (1024)
-
struct cf_socket_ctx {
int transport;
struct Curl_sockaddr_ex addr; /* address to connect to */
@@ -956,42 +940,50 @@ struct cf_socket_ctx {
BIT(active);
};
-static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
- const struct Curl_addrinfo *ai,
- int transport)
+static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx,
+ const struct Curl_addrinfo *ai,
+ int transport)
{
+ CURLcode result;
+
memset(ctx, 0, sizeof(*ctx));
ctx->sock = CURL_SOCKET_BAD;
ctx->transport = transport;
- Curl_sock_assign_addr(&ctx->addr, ai, transport);
+
+ result = Curl_sock_assign_addr(&ctx->addr, ai, transport);
+ if(result)
+ return result;
+
#ifdef DEBUGBUILD
{
- char *p = getenv("CURL_DBG_SOCK_WBLOCK");
+ const char *p = getenv("CURL_DBG_SOCK_WBLOCK");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0 && l <= 100)
+ curl_off_t l;
+ if(!curlx_str_number(&p, &l, 100))
ctx->wblock_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_WPARTIAL");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0 && l <= 100)
+ curl_off_t l;
+ if(!curlx_str_number(&p, &l, 100))
ctx->wpartial_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_RBLOCK");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0 && l <= 100)
+ curl_off_t l;
+ if(!curlx_str_number(&p, &l, 100))
ctx->rblock_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_RMAX");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0)
+ curl_off_t l;
+ if(!curlx_str_number(&p, &l, CURL_OFF_T_MAX))
ctx->recv_max = (size_t)l;
}
}
#endif
+
+ return result;
}
static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -999,7 +991,7 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_socket_ctx *ctx = cf->ctx;
if(ctx && CURL_SOCKET_BAD != ctx->sock) {
- CURL_TRC_CF(data, cf, "cf_socket_close(%" FMT_SOCKET_T ")", ctx->sock);
+ CURL_TRC_CF(data, cf, "cf_socket_close, fd=%" FMT_SOCKET_T, ctx->sock);
if(ctx->sock == cf->conn->sock[cf->sockindex])
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
@@ -1021,7 +1013,7 @@ static CURLcode cf_socket_shutdown(struct Curl_cfilter *cf,
if(cf->connected) {
struct cf_socket_ctx *ctx = cf->ctx;
- CURL_TRC_CF(data, cf, "cf_socket_shutdown(%" FMT_SOCKET_T ")", ctx->sock);
+ CURL_TRC_CF(data, cf, "cf_socket_shutdown, fd=%" FMT_SOCKET_T, ctx->sock);
/* On TCP, and when the socket looks well and non-blocking mode
* can be enabled, receive dangling bytes before close to avoid
* entering RST states unnecessarily. */
@@ -1113,7 +1105,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
(void)data;
DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD);
- ctx->started_at = Curl_now();
+ ctx->started_at = curlx_now();
#ifdef SOCK_NONBLOCK
/* Do not tuck SOCK_NONBLOCK into socktype when opensocket callback is set
* because we would not know how socketype is about to be used in the
@@ -1229,7 +1221,7 @@ out:
}
else if(isconnected) {
set_local_ip(cf, data);
- ctx->connected_at = Curl_now();
+ ctx->connected_at = curlx_now();
cf->connected = TRUE;
}
CURL_TRC_CF(data, cf, "cf_socket_open() -> %d, fd=%" FMT_SOCKET_T,
@@ -1279,7 +1271,7 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
#elif defined(MSG_FASTOPEN) /* old Linux */
- if(cf->conn->given->flags & PROTOPT_SSL)
+ if(Curl_conn_is_ssl(cf->conn, cf->sockindex))
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
else
rc = 0; /* Do nothing */
@@ -1294,7 +1286,7 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
- bool blocking, bool *done)
+ bool *done)
{
struct cf_socket_ctx *ctx = cf->ctx;
CURLcode result = CURLE_COULDNT_CONNECT;
@@ -1306,10 +1298,6 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
return CURLE_OK;
}
- /* TODO: need to support blocking connect? */
- if(blocking)
- return CURLE_UNSUPPORTED_PROTOCOL;
-
*done = FALSE; /* a negative world view is best */
if(ctx->sock == CURL_SOCKET_BAD) {
int error;
@@ -1352,7 +1340,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
else if(rc == CURL_CSELECT_OUT || cf->conn->bits.tcp_fastopen) {
if(verifyconnect(ctx->sock, &ctx->error)) {
/* we are connected with TCP, awesome! */
- ctx->connected_at = Curl_now();
+ ctx->connected_at = curlx_now();
set_local_ip(cf, data);
*done = TRUE;
cf->connected = TRUE;
@@ -1413,7 +1401,7 @@ static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
/* A listening socket filter needs to be connected before the accept
* for some weird FTP interaction. This should be rewritten, so that
* FTP no longer does the socket checks and accept calls and delegates
- * all that to the filter. TODO. */
+ * all that to the filter. */
if(ctx->listening) {
Curl_pollset_set_in_only(data, ps, ctx->sock);
CURL_TRC_CF(data, cf, "adjust_pollset, listening, POLLIN fd=%"
@@ -1440,7 +1428,7 @@ static bool cf_socket_data_pending(struct Curl_cfilter *cf,
(void)data;
readable = SOCKET_READABLE(ctx->sock, 0);
- return (readable > 0 && (readable & CURL_CSELECT_IN));
+ return readable > 0 && (readable & CURL_CSELECT_IN);
}
#ifdef USE_WINSOCK
@@ -1453,9 +1441,9 @@ static void win_update_sndbuf_size(struct cf_socket_ctx *ctx)
{
ULONG ideal;
DWORD ideallen;
- struct curltime n = Curl_now();
+ struct curltime n = curlx_now();
- if(Curl_timediff(n, ctx->last_sndbuf_query_at) > 1000) {
+ if(curlx_timediff(n, ctx->last_sndbuf_query_at) > 1000) {
if(!WSAIoctl(ctx->sock, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
&ideal, sizeof(ideal), &ideallen, 0, 0) &&
ideal != ctx->sndbuf_size &&
@@ -1520,15 +1508,16 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
int sockerr = SOCKERRNO;
if(
-#ifdef WSAEWOULDBLOCK
+#ifdef USE_WINSOCK
/* This is how Windows does it */
- (WSAEWOULDBLOCK == sockerr)
+ (SOCKEWOULDBLOCK == sockerr)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
due to its inability to send off data without blocking. We therefore
treat both error codes the same here */
- (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) || (EINTR == sockerr) ||
- (EINPROGRESS == sockerr)
+ (SOCKEWOULDBLOCK == sockerr) ||
+ (EAGAIN == sockerr) || (SOCKEINTR == sockerr) ||
+ (SOCKEINPROGRESS == sockerr)
#endif
) {
/* this is just a case of EWOULDBLOCK */
@@ -1588,14 +1577,15 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
int sockerr = SOCKERRNO;
if(
-#ifdef WSAEWOULDBLOCK
+#ifdef USE_WINSOCK
/* This is how Windows does it */
- (WSAEWOULDBLOCK == sockerr)
+ (SOCKEWOULDBLOCK == sockerr)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
due to its inability to send off data without blocking. We therefore
treat both error codes the same here */
- (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) || (EINTR == sockerr)
+ (SOCKEWOULDBLOCK == sockerr) ||
+ (EAGAIN == sockerr) || (SOCKEINTR == sockerr)
#endif
) {
/* this is just a case of EWOULDBLOCK */
@@ -1614,7 +1604,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
CURL_TRC_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
*err);
if(nread > 0 && !ctx->got_first_byte) {
- ctx->first_byte_at = Curl_now();
+ ctx->first_byte_at = curlx_now();
ctx->got_first_byte = TRUE;
}
return nread;
@@ -1725,7 +1715,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
return CURLE_OK;
case CF_QUERY_CONNECT_REPLY_MS:
if(ctx->got_first_byte) {
- timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ timediff_t ms = curlx_timediff(ctx->first_byte_at, ctx->started_at);
*pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
}
else
@@ -1802,7 +1792,10 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- cf_socket_ctx_init(ctx, ai, transport);
+
+ result = cf_socket_ctx_init(ctx, ai, transport);
+ if(result)
+ goto out;
result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx);
@@ -1828,6 +1821,8 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
/* QUIC needs a connected socket, nonblocking */
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
+ /* error: The 1st argument to 'connect' is -1 but should be >= 0
+ NOLINTNEXTLINE(clang-analyzer-unix.StdCLibraryFunctions) */
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr,
(curl_socklen_t)ctx->addr.addrlen);
if(-1 == rc) {
@@ -1846,8 +1841,9 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
* non-blocking socket created by cf_socket_open() to it. Thus, we
* do not need to call curlx_nonblock() in cf_udp_setup_quic() anymore.
*/
+#ifdef __linux__
switch(ctx->addr.family) {
-#if defined(__linux__) && defined(IP_MTU_DISCOVER)
+#ifdef IP_MTU_DISCOVER
case AF_INET: {
int val = IP_PMTUDISC_DO;
(void)setsockopt(ctx->sock, IPPROTO_IP, IP_MTU_DISCOVER, &val,
@@ -1855,7 +1851,7 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
break;
}
#endif
-#if defined(__linux__) && defined(IPV6_MTU_DISCOVER)
+#ifdef IPV6_MTU_DISCOVER
case AF_INET6: {
int val = IPV6_PMTUDISC_DO;
(void)setsockopt(ctx->sock, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val,
@@ -1865,24 +1861,24 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
#endif
}
-#if defined(__linux__) && defined(UDP_GRO) && \
+#if defined(UDP_GRO) && \
(defined(HAVE_SENDMMSG) || defined(HAVE_SENDMSG)) && \
((defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || defined(USE_QUICHE))
(void)setsockopt(ctx->sock, IPPROTO_UDP, UDP_GRO, &one,
(socklen_t)sizeof(one));
#endif
+#endif
return CURLE_OK;
}
static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
- bool blocking, bool *done)
+ bool *done)
{
struct cf_socket_ctx *ctx = cf->ctx;
CURLcode result = CURLE_COULDNT_CONNECT;
- (void)blocking;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
@@ -1951,7 +1947,10 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- cf_socket_ctx_init(ctx, ai, transport);
+
+ result = cf_socket_ctx_init(ctx, ai, transport);
+ if(result)
+ goto out;
result = Curl_cf_create(&cf, &Curl_cft_udp, ctx);
@@ -2003,7 +2002,10 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- cf_socket_ctx_init(ctx, ai, transport);
+
+ result = cf_socket_ctx_init(ctx, ai, transport);
+ if(result)
+ goto out;
result = Curl_cf_create(&cf, &Curl_cft_unix, ctx);
@@ -2030,7 +2032,7 @@ static timediff_t cf_tcp_accept_timeleft(struct Curl_cfilter *cf,
timeout_ms = data->set.accepttimeout;
#endif
- now = Curl_now();
+ now = curlx_now();
/* check if the generic timeout possibly is set shorter */
other = Curl_timeleft(data, &now, FALSE);
if(other && (other < timeout_ms))
@@ -2039,7 +2041,7 @@ static timediff_t cf_tcp_accept_timeleft(struct Curl_cfilter *cf,
timeout_ms = other;
else {
/* subtract elapsed time */
- timeout_ms -= Curl_timediff(now, ctx->started_at);
+ timeout_ms -= curlx_timediff(now, ctx->started_at);
if(!timeout_ms)
/* avoid returning 0 as that means no timeout! */
timeout_ms = -1;
@@ -2081,7 +2083,7 @@ static void cf_tcp_set_accepted_remote_ip(struct Curl_cfilter *cf,
static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
- bool blocking, bool *done)
+ bool *done)
{
struct cf_socket_ctx *ctx = cf->ctx;
#ifdef USE_IPV6
@@ -2097,7 +2099,6 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
/* we start accepted, if we ever close, we cannot go on */
(void)data;
- (void)blocking;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
@@ -2136,7 +2137,12 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
if(0 == getsockname(ctx->sock, (struct sockaddr *) &add, &size)) {
size = sizeof(add);
+#ifdef HAVE_ACCEPT4
+ s_accepted = accept4(ctx->sock, (struct sockaddr *) &add, &size,
+ SOCK_NONBLOCK | SOCK_CLOEXEC);
+#else
s_accepted = accept(ctx->sock, (struct sockaddr *) &add, &size);
+#endif
}
if(CURL_SOCKET_BAD == s_accepted) {
@@ -2145,7 +2151,9 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
}
infof(data, "Connection accepted from server");
+#ifndef HAVE_ACCEPT4
(void)curlx_nonblock(s_accepted, TRUE); /* enable non-blocking */
+#endif
/* Replace any filter on SECONDARY with one listening on this socket */
ctx->listening = FALSE;
ctx->accepted = TRUE;
@@ -2156,7 +2164,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
cf_tcp_set_accepted_remote_ip(cf, data);
set_local_ip(cf, data);
ctx->active = TRUE;
- ctx->connected_at = Curl_now();
+ ctx->connected_at = curlx_now();
cf->connected = TRUE;
CURL_TRC_CF(data, cf, "accepted_set(sock=%" FMT_SOCKET_T
", remote=%s port=%d)",
@@ -2174,6 +2182,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
if(error)
return CURLE_ABORTED_BY_CALLBACK;
}
+ *done = TRUE;
return CURLE_OK;
}
@@ -2185,7 +2194,7 @@ struct Curl_cftype Curl_cft_tcp_accept = {
cf_tcp_accept_connect,
cf_socket_close,
cf_socket_shutdown,
- cf_socket_get_host, /* TODO: not accurate */
+ cf_socket_get_host,
cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
@@ -2222,7 +2231,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
- ctx->started_at = Curl_now();
+ ctx->started_at = curlx_now();
conn->sock[sockindex] = ctx->sock;
set_local_ip(cf, data);
CURL_TRC_CF(data, cf, "set filter for listen socket fd=%" FMT_SOCKET_T