* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
#include <inet.h>
#endif
-#include "curl_printf.h"
#include "urldata.h"
#include "sendf.h"
#include "if2ip.h"
#include "warnless.h"
#include "conncache.h"
#include "multihandle.h"
+#include "system_win32.h"
-/* The last #include files should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#endif
static void
-tcpkeepalive(struct SessionHandle *data,
+tcpkeepalive(struct Curl_easy *data,
curl_socket_t sockfd)
{
int optval = data->set.tcp_keepalive?1:0;
infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
(int)sockfd, WSAGetLastError());
}
+#elif defined(CURL_WINDOWS_APP)
+ (void)majorVersion;
+ detectOsState = DETECT_OS_VISTA_OR_LATER;
#else
#ifdef TCP_KEEPIDLE
optval = curlx_sltosi(data->set.tcp_keepidle);
*
* @unittest: 1303
*/
-long Curl_timeleft(struct SessionHandle *data,
+long Curl_timeleft(struct Curl_easy *data,
struct timeval *nowp,
bool duringconnect)
{
static CURLcode bindlocal(struct connectdata *conn,
curl_socket_t sockfd, int af, unsigned int scope)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct Curl_sockaddr_storage sa;
struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
switch (sa->sa_family) {
case AF_INET:
- si = (struct sockaddr_in*) sa;
+ si = (struct sockaddr_in*)(void*) sa;
if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
addr, MAX_IPADR_LEN)) {
us_port = ntohs(si->sin_port);
break;
#ifdef ENABLE_IPV6
case AF_INET6:
- si6 = (struct sockaddr_in6*)sa;
+ si6 = (struct sockaddr_in6*)(void*) sa;
if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
addr, MAX_IPADR_LEN)) {
us_port = ntohs(si6->sin6_port);
curl_socklen_t len;
struct Curl_sockaddr_storage ssrem;
struct Curl_sockaddr_storage ssloc;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
if(conn->socktype == SOCK_DGRAM)
/* there's no connection! */
return;
- if(!conn->bits.reuse) {
+ if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
int error;
len = sizeof(struct Curl_sockaddr_storage);
int sockindex,
bool *connected)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
long allow;
int error = 0;
rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
if(rc == 0) { /* no connection yet */
+ error = 0;
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
infof(data, "After %ldms connect time, move on!\n",
conn->timeoutms_per_addr);
trynextip(conn, sockindex, 1);
}
}
- else if(rc == CURL_CSELECT_OUT) {
+ else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
if(verifyconnect(conn->tempsock[i], &error)) {
/* we are connected with TCP, awesome! */
if(result) {
/* no more addresses to try */
+ const char* hostname;
+
/* if the first address family runs out of addresses to try before
the happy eyeball timeout, go ahead and try the next family now */
if(conn->tempaddr[1] == NULL) {
return result;
}
+ if(conn->bits.proxy)
+ hostname = conn->proxy.name;
+ else if(conn->bits.conn_to_host)
+ hostname = conn->conn_to_host.name;
+ else
+ hostname = conn->host.name;
+
failf(data, "Failed to connect to %s port %ld: %s",
- conn->bits.proxy?conn->proxy.name:conn->host.name,
- conn->port, Curl_strerror(conn, error));
+ hostname, conn->port, Curl_strerror(conn, error));
}
return result;
}
-static void tcpnodelay(struct connectdata *conn,
- curl_socket_t sockfd)
+void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
{
-#ifdef TCP_NODELAY
- struct SessionHandle *data= conn->data;
- curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
+#if defined(TCP_NODELAY)
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ struct Curl_easy *data = conn->data;
+#endif
+ curl_socklen_t onoff = (curl_socklen_t) 1;
int level = IPPROTO_TCP;
#if 0
level = pe->p_proto;
#endif
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) conn;
+#endif
+
if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
infof(data, "Could not set TCP_NODELAY: %s\n",
static void nosigpipe(struct connectdata *conn,
curl_socket_t sockfd)
{
- struct SessionHandle *data= conn->data;
+ struct Curl_easy *data= conn->data;
int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0)
/* When you run a program that uses the Windows Sockets API, you may
experience slow performance when you copy data to a TCP server.
- http://support.microsoft.com/kb/823764
+ https://support.microsoft.com/kb/823764
Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
Buffer Size
int val = CURL_MAX_WRITE_SIZE + 32;
int curval = 0;
int curlen = sizeof(curval);
- DWORD majorVersion = 6;
static int detectOsState = DETECT_OS_NONE;
if(detectOsState == DETECT_OS_NONE) {
-#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
- (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
- OSVERSIONINFO osver;
-
- memset(&osver, 0, sizeof(osver));
- osver.dwOSVersionInfoSize = sizeof(osver);
-
- detectOsState = DETECT_OS_PREVISTA;
- if(GetVersionEx(&osver)) {
- if(osver.dwMajorVersion >= majorVersion)
- detectOsState = DETECT_OS_VISTA_OR_LATER;
- }
-#else
- ULONGLONG cm;
- OSVERSIONINFOEX osver;
-
- memset(&osver, 0, sizeof(osver));
- osver.dwOSVersionInfoSize = sizeof(osver);
- osver.dwMajorVersion = majorVersion;
-
- cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
- cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL);
- cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
- cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
-
- if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
- VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
- cm))
+ if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL))
detectOsState = DETECT_OS_VISTA_OR_LATER;
else
detectOsState = DETECT_OS_PREVISTA;
-#endif
}
if(detectOsState == DETECT_OS_VISTA_OR_LATER)
curl_socket_t *sockp)
{
struct Curl_sockaddr_ex addr;
- int rc;
+ int rc = -1;
int error = 0;
bool isconnected = FALSE;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
curl_socket_t sockfd;
CURLcode result;
char ipaddress[MAX_IPADR_LEN];
is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
#endif
if(is_tcp && data->set.tcp_nodelay)
- tcpnodelay(conn, sockfd);
+ Curl_tcpnodelay(conn, sockfd);
nosigpipe(conn, sockfd);
/* Connect TCP sockets, bind UDP */
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
- rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+ if(conn->bits.tcp_fastopen) {
+#if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
+ sa_endpoints_t endpoints;
+ endpoints.sae_srcif = 0;
+ endpoints.sae_srcaddr = NULL;
+ endpoints.sae_srcaddrlen = 0;
+ endpoints.sae_dstaddr = &addr.sa_addr;
+ endpoints.sae_dstaddrlen = addr.addrlen;
+
+ rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
+ CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
+ NULL, 0, NULL, NULL);
+#elif defined(MSG_FASTOPEN) /* Linux */
+ if(conn->given->flags & PROTOPT_SSL)
+ rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+ else
+ rc = 0; /* Do nothing */
+#endif
+ }
+ else {
+ rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+ }
+
if(-1 == rc)
error = SOCKERRNO;
}
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
const struct Curl_dns_entry *remotehost)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct timeval before = Curl_tvnow();
CURLcode result = CURLE_COULDNT_CONNECT;
/*
* Used to extract socket and connectdata struct for the most recent
- * transfer on the given SessionHandle.
+ * transfer on the given Curl_easy.
*
* The returned socket will be CURL_SOCKET_BAD in case of failure!
*/
-curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
+curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp)
{
curl_socket_t sockfd;
}
/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
#ifdef MSG_PEEK
- else {
+ else if(sockfd != CURL_SOCKET_BAD) {
/* use the socket */
char buf;
- if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
+ if(recv((RECV_TYPE_ARG1)sockfd, (RECV_TYPE_ARG2)&buf,
(RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
return CURL_SOCKET_BAD; /* FIN received */
}
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct Curl_sockaddr_ex dummy;
if(!addr)
}
-#ifdef CURLDEBUG
/*
- * Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
- * MUST be called with the connclose() or connkeep() macros with a stated
- * reason. The reason is only shown in debug builds but helps to figure out
- * decision paths when connections are or aren't re-used as expected.
+ * Curl_conncontrol() marks streams or connection for closure.
*/
-void Curl_conncontrol(struct connectdata *conn, bool closeit,
- const char *reason)
-{
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
- (void) reason;
+void Curl_conncontrol(struct connectdata *conn,
+ int ctrl /* see defines in header */
+#ifdef DEBUGBUILD
+ , const char *reason
#endif
- if(closeit != conn->bits.close) {
- infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
- reason);
-
+ )
+{
+ /* close if a connection, or a stream that isn't multiplexed */
+ bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
+ ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
+ if((ctrl == CONNCTRL_STREAM) &&
+ (conn->handler->flags & PROTOPT_STREAM))
+ DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
+ else if(closeit != conn->bits.close) {
+ DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
+ closeit?"closure":"keep alive", reason));
conn->bits.close = closeit; /* the only place in the source code that
should assign this bit */
}
}
-#endif