Coverage Report

Created: 2026-06-15 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmcurl/lib/connect.c
Line
Count
Source
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
#include "curl_setup.h"
25
26
#ifdef HAVE_NETINET_IN_H
27
#include <netinet/in.h> /* <netinet/tcp.h> may need it */
28
#endif
29
#ifdef HAVE_SYS_UN_H
30
#include <sys/un.h> /* for sockaddr_un */
31
#endif
32
#ifdef HAVE_LINUX_TCP_H
33
#include <linux/tcp.h>
34
#elif defined(HAVE_NETINET_TCP_H)
35
#include <netinet/tcp.h>
36
#endif
37
#ifdef HAVE_SYS_IOCTL_H
38
#include <sys/ioctl.h>
39
#endif
40
#ifdef HAVE_NETDB_H
41
#include <netdb.h>
42
#endif
43
#ifdef HAVE_ARPA_INET_H
44
#include <arpa/inet.h>
45
#endif
46
47
#ifdef __VMS
48
#include <in.h>
49
#include <inet.h>
50
#endif
51
52
#include "urldata.h"
53
#include "curl_trc.h"
54
#include "strerror.h"
55
#include "cfilters.h"
56
#include "connect.h"
57
#include "cf-dns.h"
58
#include "cf-haproxy.h"
59
#include "cf-https-connect.h"
60
#include "cf-ip-happy.h"
61
#include "cf-socket.h"
62
#include "multiif.h"
63
#include "curlx/inet_ntop.h"
64
#include "curlx/strparse.h"
65
#include "vtls/vtls.h" /* for vtls cfilters */
66
#include "progress.h"
67
#include "conncache.h"
68
#include "multihandle.h"
69
#include "http_proxy.h"
70
#include "socks.h"
71
72
#if !defined(CURL_DISABLE_ALTSVC) || defined(USE_HTTPSRR)
73
74
enum alpnid Curl_alpn2alpnid(const unsigned char *name, size_t len)
75
{
76
  if(len == 2) {
77
    if(!memcmp(name, "h1", 2))
78
      return ALPN_h1;
79
    if(!memcmp(name, "h2", 2))
80
      return ALPN_h2;
81
    if(!memcmp(name, "h3", 2))
82
      return ALPN_h3;
83
  }
84
  else if(len == 8) {
85
    if(!memcmp(name, "http/1.1", 8))
86
      return ALPN_h1;
87
  }
88
  return ALPN_none; /* unknown, probably rubbish input */
89
}
90
91
enum alpnid Curl_str2alpnid(const struct Curl_str *cstr)
92
{
93
  return Curl_alpn2alpnid((const unsigned char *)curlx_str(cstr),
94
                          curlx_strlen(cstr));
95
}
96
97
#endif
98
99
/*
100
 * timeleft_now_ms() returns the amount of milliseconds left allowed for the
101
 * transfer/connection. If the value is 0, there is no timeout (ie there is
102
 * infinite time left). If the value is negative, the timeout time has already
103
 * elapsed.
104
 *
105
 * @unittest 1303
106
 */
107
UNITTEST timediff_t timeleft_now_ms(struct Curl_easy *data,
108
                                    const struct curltime *pnow);
109
UNITTEST timediff_t timeleft_now_ms(struct Curl_easy *data,
110
                                    const struct curltime *pnow)
111
0
{
112
0
  timediff_t timeleft_ms = 0;
113
0
  timediff_t ctimeleft_ms = 0;
114
115
0
  if(Curl_shutdown_started(data, FIRSTSOCKET))
116
0
    return Curl_shutdown_timeleft(data, data->conn, FIRSTSOCKET);
117
0
  else if(Curl_is_connecting(data)) {
118
0
    timediff_t ctimeout_ms = (data->set.connecttimeout > 0) ?
119
0
      data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
120
0
    ctimeleft_ms = ctimeout_ms -
121
0
      curlx_ptimediff_ms(pnow, &data->progress.t_startsingle);
122
0
    if(!ctimeleft_ms)
123
0
      ctimeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
124
0
  }
125
0
  else if(!data->set.timeout || data->set.connect_only) {
126
0
    return 0; /* no timeout in place or checked, return "no limit" */
127
0
  }
128
129
0
  if(data->set.timeout) {
130
0
    timeleft_ms = data->set.timeout -
131
0
      curlx_ptimediff_ms(pnow, &data->progress.t_startop);
132
0
    if(!timeleft_ms)
133
0
      timeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
134
0
  }
135
136
0
  if(!ctimeleft_ms)
137
0
    return timeleft_ms;
138
0
  else if(!timeleft_ms)
139
0
    return ctimeleft_ms;
140
0
  return CURLMIN(ctimeleft_ms, timeleft_ms);
141
0
}
142
143
timediff_t Curl_timeleft_ms(struct Curl_easy *data)
144
0
{
145
0
  return timeleft_now_ms(data, Curl_pgrs_now(data));
146
0
}
147
148
void Curl_shutdown_start(struct Curl_easy *data, int sockindex,
149
                         int timeout_ms)
150
0
{
151
0
  struct connectdata *conn = data->conn;
152
153
0
  DEBUGASSERT(conn);
154
0
  conn->shutdown.start[sockindex] = *Curl_pgrs_now(data);
155
0
  conn->shutdown.timeout_ms = (timeout_ms > 0) ?
156
0
    (timediff_t)timeout_ms :
157
0
    ((data->set.shutdowntimeout > 0) ?
158
0
     data->set.shutdowntimeout : DEFAULT_SHUTDOWN_TIMEOUT_MS);
159
  /* Set a timer, unless we operate on the admin handle */
160
0
  if(data->mid)
161
0
    Curl_expire_ex(data, conn->shutdown.timeout_ms, EXPIRE_SHUTDOWN);
162
0
  CURL_TRC_M(data, "shutdown start on%s connection",
163
0
             sockindex ? " secondary" : "");
164
0
}
165
166
timediff_t Curl_shutdown_timeleft(struct Curl_easy *data,
167
                                  struct connectdata *conn,
168
                                  int sockindex)
169
0
{
170
0
  timediff_t left_ms;
171
172
0
  if(!conn->shutdown.start[sockindex].tv_sec ||
173
0
     (conn->shutdown.timeout_ms <= 0))
174
0
    return 0; /* not started or no limits */
175
176
0
  left_ms = conn->shutdown.timeout_ms -
177
0
            curlx_ptimediff_ms(Curl_pgrs_now(data),
178
0
                               &conn->shutdown.start[sockindex]);
179
0
  return left_ms ? left_ms : -1;
180
0
}
181
182
timediff_t Curl_conn_shutdown_timeleft(struct Curl_easy *data,
183
                                       struct connectdata *conn)
184
0
{
185
0
  timediff_t left_ms = 0, ms;
186
0
  int i;
187
188
0
  for(i = 0; conn->shutdown.timeout_ms && (i < 2); ++i) {
189
0
    if(!conn->shutdown.start[i].tv_sec)
190
0
      continue;
191
0
    ms = Curl_shutdown_timeleft(data, conn, i);
192
0
    if(ms && (!left_ms || ms < left_ms))
193
0
      left_ms = ms;
194
0
  }
195
0
  return left_ms;
196
0
}
197
198
void Curl_shutdown_clear(struct Curl_easy *data, int sockindex)
199
0
{
200
0
  struct curltime *pt = &data->conn->shutdown.start[sockindex];
201
0
  memset(pt, 0, sizeof(*pt));
202
0
}
203
204
bool Curl_shutdown_started(struct Curl_easy *data, int sockindex)
205
0
{
206
0
  if(data->conn) {
207
0
    struct curltime *pt = &data->conn->shutdown.start[sockindex];
208
0
    return (pt->tv_sec > 0) || (pt->tv_usec > 0);
209
0
  }
210
0
  return FALSE;
211
0
}
212
213
/* retrieves ip address and port from a sockaddr structure. note it calls
214
   curlx_inet_ntop which sets errno on fail, not SOCKERRNO. */
215
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
216
                      char *addr, uint16_t *port)
217
0
{
218
0
  struct sockaddr_in *si = NULL;
219
0
#ifdef USE_IPV6
220
0
  struct sockaddr_in6 *si6 = NULL;
221
0
#endif
222
#ifdef USE_UNIX_SOCKETS
223
  struct sockaddr_un *su = NULL;
224
#else
225
0
  (void)salen;
226
0
#endif
227
228
0
  switch(sa->sa_family) {
229
0
  case AF_INET:
230
0
    si = (struct sockaddr_in *)(void *)sa;
231
0
    if(curlx_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN)) {
232
0
      *port = ntohs(si->sin_port);
233
0
      return TRUE;
234
0
    }
235
0
    break;
236
0
#ifdef USE_IPV6
237
0
  case AF_INET6:
238
0
    si6 = (struct sockaddr_in6 *)(void *)sa;
239
0
    if(curlx_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, MAX_IPADR_LEN)) {
240
0
      *port = ntohs(si6->sin6_port);
241
0
      return TRUE;
242
0
    }
243
0
    break;
244
0
#endif
245
#ifdef USE_UNIX_SOCKETS
246
  case AF_UNIX:
247
    if(salen > (curl_socklen_t)sizeof(CURL_SA_FAMILY_T)) {
248
      su = (struct sockaddr_un *)sa;
249
      curl_msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
250
    }
251
    else
252
      addr[0] = 0; /* socket with no name */
253
    *port = 0;
254
    return TRUE;
255
#endif
256
0
  default:
257
0
    break;
258
0
  }
259
260
0
  addr[0] = '\0';
261
0
  *port = 0;
262
0
  errno = SOCKEAFNOSUPPORT;
263
0
  return FALSE;
264
0
}
265
266
/*
267
 * Used to extract socket and connectdata struct for the most recent
268
 * transfer on the given Curl_easy.
269
 *
270
 * The returned socket will be CURL_SOCKET_BAD in case of failure!
271
 */
272
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
273
                                  struct connectdata **connp)
274
0
{
275
0
  DEBUGASSERT(data);
276
277
  /* this works for an easy handle:
278
   * - that has been used for curl_easy_perform()
279
   * - that is associated with a multi handle, and whose connection
280
   *   was detached with CURLOPT_CONNECT_ONLY
281
   */
282
0
  if(data->state.lastconnect_id != -1) {
283
0
    struct connectdata *conn;
284
285
0
    conn = Curl_cpool_get_conn(data, data->state.lastconnect_id);
286
0
    if(!conn) {
287
0
      data->state.lastconnect_id = -1;
288
0
      return CURL_SOCKET_BAD;
289
0
    }
290
291
0
    if(connp)
292
      /* only store this if the caller cares for it */
293
0
      *connp = conn;
294
0
    return conn->sock[FIRSTSOCKET];
295
0
  }
296
0
  return CURL_SOCKET_BAD;
297
0
}
298
299
/*
300
 * Curl_conncontrol() marks streams or connection for closure.
301
 */
302
void Curl_conncontrol(struct connectdata *conn,
303
                      int ctrl /* see defines in header */
304
#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
305
                      , const char *reason
306
#endif
307
  )
308
0
{
309
  /* close if a connection, or a stream that is not multiplexed. */
310
  /* This function will be called both before and after this connection is
311
     associated with a transfer. */
312
0
  bool closeit, is_multiplex;
313
0
  DEBUGASSERT(conn);
314
#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
315
  (void)reason; /* useful for debugging */
316
#endif
317
0
  is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
318
0
  closeit = (ctrl == CONNCTRL_CONNECTION) ||
319
0
            ((ctrl == CONNCTRL_STREAM) && !is_multiplex);
320
0
  if((ctrl == CONNCTRL_STREAM) && is_multiplex)
321
0
    ;  /* stream signal on multiplex conn never affects close state */
322
0
  else if((curl_bit)closeit != conn->bits.close) {
323
0
    conn->bits.close = closeit; /* the only place in the source code that
324
                                   should assign this bit */
325
0
  }
326
0
}
327
328
typedef enum {
329
  CF_SETUP_INIT,
330
  CF_SETUP_CNNCT_EYEBALLS,
331
  CF_SETUP_CNNCT_SOCKS,
332
  CF_SETUP_CNNCT_HTTP_PROXY,
333
  CF_SETUP_CNNCT_HAPROXY,
334
  CF_SETUP_CNNCT_SSL,
335
  CF_SETUP_DONE
336
} cf_setup_state;
337
338
struct cf_setup_ctx {
339
  cf_setup_state state;
340
  int ssl_mode;
341
  uint8_t transport;
342
};
343
344
static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
345
                                 struct Curl_easy *data,
346
                                 bool *done)
347
0
{
348
0
  struct cf_setup_ctx *ctx = cf->ctx;
349
0
  CURLcode result = CURLE_OK;
350
351
0
  if(cf->connected) {
352
0
    *done = TRUE;
353
0
    return CURLE_OK;
354
0
  }
355
356
  /* connect current sub-chain */
357
0
connect_sub_chain:
358
359
0
  if(cf->next && !cf->next->connected) {
360
0
    result = Curl_conn_cf_connect(cf->next, data, done);
361
0
    if(result || !*done)
362
0
      return result;
363
0
  }
364
365
0
  if(ctx->state < CF_SETUP_CNNCT_EYEBALLS) {
366
0
    result = cf_ip_happy_insert_after(cf, data, ctx->transport);
367
0
    if(result)
368
0
      return result;
369
0
    ctx->state = CF_SETUP_CNNCT_EYEBALLS;
370
0
    if(!cf->next || !cf->next->connected)
371
0
      goto connect_sub_chain;
372
0
  }
373
374
  /* sub-chain connected, do we need to add more? */
375
0
#ifndef CURL_DISABLE_PROXY
376
0
  if(ctx->state < CF_SETUP_CNNCT_SOCKS && cf->conn->bits.socksproxy) {
377
    /* for the secondary socket (FTP), use the "connect to host"
378
     * but ignore the "connect to port" (use the secondary port)
379
     */
380
0
    const char *hostname =
381
0
      cf->conn->bits.httpproxy ?
382
0
      cf->conn->http_proxy.host.name :
383
0
      cf->conn->bits.conn_to_host ?
384
0
      cf->conn->conn_to_host.name :
385
0
      cf->sockindex == SECONDARYSOCKET ?
386
0
      cf->conn->secondaryhostname : cf->conn->host.name;
387
0
    uint16_t port =
388
0
      cf->conn->bits.httpproxy ? cf->conn->http_proxy.port :
389
0
      cf->sockindex == SECONDARYSOCKET ? cf->conn->secondary_port :
390
0
      cf->conn->bits.conn_to_port ? cf->conn->conn_to_port :
391
0
      cf->conn->remote_port;
392
0
    const char *user = cf->conn->socks_proxy.user;
393
0
    const char *passwd = cf->conn->socks_proxy.passwd;
394
395
0
    result = Curl_cf_socks_proxy_insert_after(
396
0
      cf, data, hostname, port, cf->conn->ip_version,
397
0
      cf->conn->socks_proxy.proxytype, user, passwd);
398
0
    if(result)
399
0
      return result;
400
0
    ctx->state = CF_SETUP_CNNCT_SOCKS;
401
0
    if(!cf->next || !cf->next->connected)
402
0
      goto connect_sub_chain;
403
0
  }
404
405
0
  if(ctx->state < CF_SETUP_CNNCT_HTTP_PROXY && cf->conn->bits.httpproxy) {
406
#ifdef USE_SSL
407
    if(IS_HTTPS_PROXY(cf->conn->http_proxy.proxytype) &&
408
       !Curl_conn_is_ssl(cf->conn, cf->sockindex)) {
409
      result = Curl_cf_ssl_proxy_insert_after(cf, data);
410
      if(result)
411
        return result;
412
    }
413
#endif /* USE_SSL */
414
415
0
#ifndef CURL_DISABLE_HTTP
416
0
    if(cf->conn->bits.tunnel_proxy) {
417
0
      result = Curl_cf_http_proxy_insert_after(cf, data);
418
0
      if(result)
419
0
        return result;
420
0
    }
421
0
#endif /* !CURL_DISABLE_HTTP */
422
0
    ctx->state = CF_SETUP_CNNCT_HTTP_PROXY;
423
0
    if(!cf->next || !cf->next->connected)
424
0
      goto connect_sub_chain;
425
0
  }
426
0
#endif /* !CURL_DISABLE_PROXY */
427
428
0
  if(ctx->state < CF_SETUP_CNNCT_HAPROXY) {
429
0
#ifndef CURL_DISABLE_PROXY
430
0
    if(data->set.haproxyprotocol) {
431
0
      if(Curl_conn_is_ssl(cf->conn, cf->sockindex)) {
432
0
        failf(data, "haproxy protocol not supported with SSL "
433
0
              "encryption in place (QUIC?)");
434
0
        return CURLE_UNSUPPORTED_PROTOCOL;
435
0
      }
436
0
      result = Curl_cf_haproxy_insert_after(cf, data);
437
0
      if(result)
438
0
        return result;
439
0
    }
440
0
#endif /* !CURL_DISABLE_PROXY */
441
0
    ctx->state = CF_SETUP_CNNCT_HAPROXY;
442
0
    if(!cf->next || !cf->next->connected)
443
0
      goto connect_sub_chain;
444
0
  }
445
446
0
  if(ctx->state < CF_SETUP_CNNCT_SSL) {
447
#ifdef USE_SSL
448
    if((ctx->ssl_mode == CURL_CF_SSL_ENABLE ||
449
        (ctx->ssl_mode != CURL_CF_SSL_DISABLE &&
450
         cf->conn->scheme->flags & PROTOPT_SSL)) &&  /* we want SSL */
451
       !Curl_conn_is_ssl(cf->conn, cf->sockindex)) { /* it is missing */
452
      result = Curl_cf_ssl_insert_after(cf, data);
453
      if(result)
454
        return result;
455
    }
456
#endif /* USE_SSL */
457
0
    ctx->state = CF_SETUP_CNNCT_SSL;
458
0
    if(!cf->next || !cf->next->connected)
459
0
      goto connect_sub_chain;
460
0
  }
461
462
0
  ctx->state = CF_SETUP_DONE;
463
0
  cf->connected = TRUE;
464
0
  *done = TRUE;
465
0
  return CURLE_OK;
466
0
}
467
468
static void cf_setup_close(struct Curl_cfilter *cf,
469
                           struct Curl_easy *data)
470
0
{
471
0
  struct cf_setup_ctx *ctx = cf->ctx;
472
473
0
  CURL_TRC_CF(data, cf, "close");
474
0
  cf->connected = FALSE;
475
0
  ctx->state = CF_SETUP_INIT;
476
477
0
  if(cf->next) {
478
0
    cf->next->cft->do_close(cf->next, data);
479
0
    Curl_conn_cf_discard_chain(&cf->next, data);
480
0
  }
481
0
}
482
483
static void cf_setup_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
484
0
{
485
0
  struct cf_setup_ctx *ctx = cf->ctx;
486
487
0
  CURL_TRC_CF(data, cf, "destroy");
488
0
  curlx_safefree(ctx);
489
0
}
490
491
struct Curl_cftype Curl_cft_setup = {
492
  "SETUP",
493
  CF_TYPE_SETUP,
494
  CURL_LOG_LVL_NONE,
495
  cf_setup_destroy,
496
  cf_setup_connect,
497
  cf_setup_close,
498
  Curl_cf_def_shutdown,
499
  Curl_cf_def_adjust_pollset,
500
  Curl_cf_def_data_pending,
501
  Curl_cf_def_send,
502
  Curl_cf_def_recv,
503
  Curl_cf_def_cntrl,
504
  Curl_cf_def_conn_is_alive,
505
  Curl_cf_def_conn_keep_alive,
506
  Curl_cf_def_query,
507
};
508
509
static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
510
                                struct Curl_easy *data,
511
                                uint8_t transport,
512
                                int ssl_mode)
513
0
{
514
0
  struct Curl_cfilter *cf = NULL;
515
0
  struct cf_setup_ctx *ctx;
516
0
  CURLcode result = CURLE_OK;
517
518
0
  (void)data;
519
0
  ctx = curlx_calloc(1, sizeof(*ctx));
520
0
  if(!ctx) {
521
0
    result = CURLE_OUT_OF_MEMORY;
522
0
    goto out;
523
0
  }
524
0
  ctx->state = CF_SETUP_INIT;
525
0
  ctx->ssl_mode = ssl_mode;
526
0
  ctx->transport = transport;
527
528
0
  result = Curl_cf_create(&cf, &Curl_cft_setup, ctx);
529
0
  if(result)
530
0
    goto out;
531
0
  ctx = NULL;
532
533
0
out:
534
0
  *pcf = result ? NULL : cf;
535
0
  if(ctx) {
536
0
    curlx_free(ctx);
537
0
  }
538
0
  return result;
539
0
}
540
541
static CURLcode cf_setup_add(struct Curl_easy *data,
542
                             struct connectdata *conn,
543
                             int sockindex,
544
                             uint8_t transport,
545
                             int ssl_mode)
546
0
{
547
0
  struct Curl_cfilter *cf;
548
0
  CURLcode result = CURLE_OK;
549
550
0
  DEBUGASSERT(data);
551
0
  result = cf_setup_create(&cf, data, transport, ssl_mode);
552
0
  if(result)
553
0
    goto out;
554
0
  Curl_conn_cf_add(data, conn, sockindex, cf);
555
0
out:
556
0
  return result;
557
0
}
558
559
CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
560
                                    struct Curl_easy *data,
561
                                    uint8_t transport,
562
                                    int ssl_mode)
563
0
{
564
0
  struct Curl_cfilter *cf;
565
0
  CURLcode result;
566
567
0
  DEBUGASSERT(data);
568
0
  result = cf_setup_create(&cf, data, transport, ssl_mode);
569
0
  if(result)
570
0
    goto out;
571
0
  Curl_conn_cf_insert_after(cf_at, cf);
572
0
out:
573
0
  return result;
574
0
}
575
576
CURLcode Curl_conn_setup(struct Curl_easy *data,
577
                         struct connectdata *conn,
578
                         int sockindex,
579
                         struct Curl_dns_entry *dns,
580
                         int ssl_mode)
581
0
{
582
0
  CURLcode result = CURLE_OK;
583
0
  uint8_t dns_queries;
584
585
0
  DEBUGASSERT(data);
586
0
  DEBUGASSERT(conn->scheme);
587
0
  DEBUGASSERT(!conn->cfilter[sockindex]);
588
589
0
#ifndef CURL_DISABLE_HTTP
590
0
  if(!conn->cfilter[sockindex] &&
591
0
     conn->scheme->protocol == CURLPROTO_HTTPS) {
592
0
    DEBUGASSERT(ssl_mode != CURL_CF_SSL_DISABLE);
593
0
    result = Curl_cf_https_setup(data, conn, sockindex);
594
0
    if(result)
595
0
      goto out;
596
0
  }
597
0
#endif /* !CURL_DISABLE_HTTP */
598
599
  /* Still no cfilter set, apply default. */
600
0
  if(!conn->cfilter[sockindex]) {
601
0
    result = cf_setup_add(data, conn, sockindex,
602
0
                          conn->transport_wanted, ssl_mode);
603
0
    if(result)
604
0
      goto out;
605
0
  }
606
607
0
  dns_queries = Curl_resolv_dns_queries(data, conn->ip_version);
608
#ifdef USE_HTTPSRR
609
  if(sockindex == FIRSTSOCKET)
610
    dns_queries |= CURL_DNSQ_HTTPS;
611
#endif
612
0
  result = Curl_cf_dns_add(data, conn, sockindex, dns_queries,
613
0
                           conn->transport_wanted, dns);
614
0
  DEBUGASSERT(conn->cfilter[sockindex]);
615
0
out:
616
0
  return result;
617
0
}
618
619
#ifdef USE_UNIX_SOCKETS
620
const char *Curl_conn_get_unix_path(struct connectdata *conn)
621
{
622
  const char *unix_path = conn->unix_domain_socket;
623
624
#ifndef CURL_DISABLE_PROXY
625
  if(!unix_path && conn->bits.proxy && conn->socks_proxy.host.name &&
626
     !strncmp(UNIX_SOCKET_PREFIX "/",
627
              conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX)))
628
    unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1;
629
#endif
630
631
  return unix_path;
632
}
633
#endif /* USE_UNIX_SOCKETS */
634
635
void Curl_conn_set_multiplex(struct connectdata *conn)
636
0
{
637
0
  if(!conn->bits.multiplex) {
638
0
    conn->bits.multiplex = TRUE;
639
0
    if(conn->attached_multi) {
640
0
      Curl_multi_connchanged(conn->attached_multi);
641
0
    }
642
0
  }
643
0
}