• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 12247231368

10 Dec 2024 12:57AM UTC coverage: 66.418% (+1.6%) from 64.777%
12247231368

Pull #14948

github

web-flow
Merge 432a0b93c into d0a62cc2d
Pull Request #14948: use boost algorithms

26100 of 54734 branches covered (47.69%)

Branch coverage included in aggregate %.

87 of 101 new or added lines in 28 files covered. (86.14%)

2076 existing lines in 52 files now uncovered.

85923 of 113929 relevant lines covered (75.42%)

4735022.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

27.55
/pdns/tcpiohandler.hh
1

2
#pragma once
3
#include <memory>
4
/* needed for proper TCP_FASTOPEN_CONNECT detection */
5
#include <netinet/tcp.h>
6

7
#include "iputils.hh"
8
#include "libssl.hh"
9
#include "misc.hh"
10
#include "noinitvector.hh"
11

12
/* Async is only returned for TLS connections, if OpenSSL's async mode has been enabled */
13
enum class IOState : uint8_t { Done, NeedRead, NeedWrite, Async };
14

15
class TLSSession
16
{
17
public:
18
  virtual ~TLSSession() = default;
19
};
20

21
class TLSConnection
22
{
23
public:
24
  virtual ~TLSConnection() = default;
25
  virtual void doHandshake() = 0;
26
  virtual IOState tryConnect(bool fastOpen, const ComboAddress& remote) = 0;
27
  virtual void connect(bool fastOpen, const ComboAddress& remote, const struct timeval& timeout) = 0;
28
  virtual IOState tryHandshake() = 0;
29
  virtual size_t read(void* buffer, size_t bufferSize, const struct timeval& readTimeout, const struct timeval& totalTimeout={0,0}, bool allowIncomplete=false) = 0;
30
  virtual size_t write(const void* buffer, size_t bufferSize, const struct timeval& writeTimeout) = 0;
31
  virtual IOState tryWrite(const PacketBuffer& buffer, size_t& pos, size_t toWrite) = 0;
32
  virtual IOState tryRead(PacketBuffer& buffer, size_t& pos, size_t toRead, bool allowIncomplete=false) = 0;
33
  virtual std::string getServerNameIndication() const = 0;
34
  virtual std::vector<uint8_t> getNextProtocol() const = 0;
35
  virtual LibsslTLSVersion getTLSVersion() const = 0;
36
  virtual bool hasSessionBeenResumed() const = 0;
37
  virtual std::vector<std::unique_ptr<TLSSession>> getSessions() = 0;
38
  virtual void setSession(std::unique_ptr<TLSSession>& session) = 0;
39
  virtual bool isUsable() const = 0;
40
  virtual std::vector<int> getAsyncFDs() = 0;
41
  virtual void close() = 0;
42

43
  void setUnknownTicketKey()
UNCOV
44
  {
×
UNCOV
45
    d_unknownTicketKey = true;
×
UNCOV
46
  }
×
47

48
  bool getUnknownTicketKey() const
UNCOV
49
  {
×
UNCOV
50
    return d_unknownTicketKey;
×
UNCOV
51
  }
×
52

53
  void setResumedFromInactiveTicketKey()
UNCOV
54
  {
×
UNCOV
55
    d_resumedFromInactiveTicketKey = true;
×
UNCOV
56
  }
×
57

58
  bool getResumedFromInactiveTicketKey() const
UNCOV
59
  {
×
UNCOV
60
    return d_resumedFromInactiveTicketKey;
×
UNCOV
61
  }
×
62

63
protected:
64
  int d_socket{-1};
65
  bool d_unknownTicketKey{false};
66
  bool d_resumedFromInactiveTicketKey{false};
67
};
68

69
class TLSCtx
70
{
71
public:
72
  TLSCtx()
73
  {
4✔
74
    d_rotatingTicketsKey.clear();
4✔
75
  }
4✔
76
  virtual ~TLSCtx() = default;
77
  virtual std::unique_ptr<TLSConnection> getConnection(int socket, const struct timeval& timeout, time_t now) = 0;
78
  virtual std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, bool hostIsAddr, int socket, const struct timeval& timeout) = 0;
79
  virtual void rotateTicketsKey(time_t now) = 0;
80
  virtual void loadTicketsKeys(const std::string& /* file */)
81
  {
×
82
    throw std::runtime_error("This TLS backend does not have the capability to load a tickets key from a file");
×
83
  }
×
84
  virtual void loadTicketsKey(const std::string& /* key */)
85
  {
×
86
    throw std::runtime_error("This TLS backend does not have the capability to load a ticket key");
×
87
  }
×
88
  void handleTicketsKeyRotation(time_t now)
UNCOV
89
  {
×
UNCOV
90
    if (d_ticketsKeyRotationDelay != 0 && now > d_ticketsKeyNextRotation) {
×
UNCOV
91
      if (d_rotatingTicketsKey.test_and_set()) {
×
92
        /* someone is already rotating */
93
        return;
×
94
      }
×
UNCOV
95
      try {
×
UNCOV
96
        rotateTicketsKey(now);
×
UNCOV
97
        d_rotatingTicketsKey.clear();
×
UNCOV
98
      }
×
UNCOV
99
      catch(const std::runtime_error& e) {
×
100
        d_rotatingTicketsKey.clear();
×
101
        throw std::runtime_error(std::string("Error generating a new tickets key for TLS context:") + e.what());
×
102
      }
×
UNCOV
103
      catch(...) {
×
104
        d_rotatingTicketsKey.clear();
×
105
        throw;
×
106
      }
×
UNCOV
107
    }
×
UNCOV
108
  }
×
109

110
  time_t getNextTicketsKeyRotation() const
UNCOV
111
  {
×
UNCOV
112
    return d_ticketsKeyNextRotation;
×
UNCOV
113
  }
×
114

115
  virtual size_t getTicketsKeysCount() = 0;
116
  virtual std::string getName() const = 0;
117

118
  using tickets_key_added_hook = std::function<void(const std::string& key)>;
119

120
  static void setTicketsKeyAddedHook(const tickets_key_added_hook& hook)
UNCOV
121
  {
×
UNCOV
122
    TLSCtx::s_ticketsKeyAddedHook = hook;
×
UNCOV
123
  }
×
124
  static const tickets_key_added_hook& getTicketsKeyAddedHook()
UNCOV
125
  {
×
UNCOV
126
    return TLSCtx::s_ticketsKeyAddedHook;
×
UNCOV
127
  }
×
128
  static bool hasTicketsKeyAddedHook()
UNCOV
129
  {
×
UNCOV
130
    return TLSCtx::s_ticketsKeyAddedHook != nullptr;
×
UNCOV
131
  }
×
132
protected:
133
  std::atomic_flag d_rotatingTicketsKey;
134
  std::atomic<time_t> d_ticketsKeyNextRotation{0};
135
  time_t d_ticketsKeyRotationDelay{0};
136

137
private:
138
  static tickets_key_added_hook s_ticketsKeyAddedHook;
139
};
140

141
class TLSFrontend
142
{
143
public:
144
  enum class ALPN : uint8_t { Unset, DoT, DoH };
145

146
  TLSFrontend(ALPN alpn): d_alpn(alpn)
UNCOV
147
  {
×
UNCOV
148
  }
×
149

150
  TLSFrontend(std::shared_ptr<TLSCtx> ctx): d_ctx(std::move(ctx))
UNCOV
151
  {
×
UNCOV
152
  }
×
153

154
  bool setupTLS();
155

156
  void rotateTicketsKey(time_t now)
UNCOV
157
  {
×
UNCOV
158
    if (d_ctx != nullptr) {
×
UNCOV
159
      d_ctx->rotateTicketsKey(now);
×
UNCOV
160
    }
×
UNCOV
161
  }
×
162

163
  void loadTicketsKeys(const std::string& file)
UNCOV
164
  {
×
UNCOV
165
    if (d_ctx != nullptr) {
×
UNCOV
166
      d_ctx->loadTicketsKeys(file);
×
UNCOV
167
    }
×
UNCOV
168
  }
×
169

170
  void loadTicketsKey(const std::string& key)
171
  {
×
172
    if (d_ctx != nullptr) {
×
173
      d_ctx->loadTicketsKey(key);
×
174
    }
×
175
  }
×
176

177
  std::shared_ptr<TLSCtx> getContext()
UNCOV
178
  {
×
UNCOV
179
    return std::atomic_load_explicit(&d_ctx, std::memory_order_acquire);
×
UNCOV
180
  }
×
181

182
  void cleanup()
183
  {
×
184
    d_ctx.reset();
×
185
  }
×
186

187
  size_t getTicketsKeysCount()
UNCOV
188
  {
×
UNCOV
189
    if (d_ctx != nullptr) {
×
UNCOV
190
      return d_ctx->getTicketsKeysCount();
×
UNCOV
191
    }
×
UNCOV
192

×
193
    return 0;
×
UNCOV
194
  }
×
195

196
  static std::string timeToString(time_t rotationTime)
UNCOV
197
  {
×
UNCOV
198
    char buf[20];
×
UNCOV
199
    struct tm date_tm;
×
UNCOV
200

×
UNCOV
201
    localtime_r(&rotationTime, &date_tm);
×
UNCOV
202
    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &date_tm);
×
UNCOV
203

×
UNCOV
204
    return std::string(buf);
×
UNCOV
205
  }
×
206

207
  time_t getTicketsKeyRotationDelay() const
208
  {
×
209
    return d_tlsConfig.d_ticketsKeyRotationDelay;
×
210
  }
×
211

212
  std::string getNextTicketsKeyRotation() const
UNCOV
213
  {
×
UNCOV
214
    std::string res;
×
UNCOV
215

×
UNCOV
216
    if (d_ctx != nullptr) {
×
UNCOV
217
      res = timeToString(d_ctx->getNextTicketsKeyRotation());
×
UNCOV
218
    }
×
UNCOV
219

×
UNCOV
220
    return res;
×
UNCOV
221
  }
×
222

223
  std::string getRequestedProvider() const
224
  {
×
225
    return d_provider;
×
226
  }
×
227

228
  std::string getEffectiveProvider() const
UNCOV
229
  {
×
UNCOV
230
    if (d_ctx) {
×
UNCOV
231
      return d_ctx->getName();
×
UNCOV
232
    }
×
233
    return "";
×
UNCOV
234
  }
×
235

236
  TLSConfig d_tlsConfig;
237
  TLSErrorCounters d_tlsCounters;
238
  ComboAddress d_addr;
239
  std::string d_provider;
240
  ALPN d_alpn{ALPN::Unset};
241
  /* whether the proxy protocol is inside or outside the TLS layer */
242
  bool d_proxyProtocolOutsideTLS{false};
243
protected:
244
  std::shared_ptr<TLSCtx> d_ctx{nullptr};
245
};
246

247
class TCPIOHandler
248
{
249
public:
250
  TCPIOHandler(const std::string& host, bool hostIsAddr, int socket, const struct timeval& timeout, const std::shared_ptr<TLSCtx>& ctx) :
251
    d_socket(socket)
252
  {
176✔
253
    if (ctx) {
176✔
254
      d_conn = ctx->getClientConnection(host, hostIsAddr, d_socket, timeout);
4✔
255
    }
4✔
256
  }
176✔
257

258
  TCPIOHandler(int socket, const struct timeval& timeout, const std::shared_ptr<TLSCtx>& ctx, time_t now) :
259
    d_socket(socket)
UNCOV
260
  {
×
UNCOV
261
    if (ctx) {
×
UNCOV
262
      d_conn = ctx->getConnection(d_socket, timeout, now);
×
UNCOV
263
    }
×
UNCOV
264
  }
×
265

266
  ~TCPIOHandler()
267
  {
169✔
268
    close();
169✔
269
  }
169✔
270

271
  void close()
272
  {
338✔
273
    if (d_conn) {
338!
UNCOV
274
      d_conn->close();
×
UNCOV
275
      d_conn.reset();
×
UNCOV
276
    }
×
277

278
    if (d_socket != -1) {
338✔
279
      shutdown(d_socket, SHUT_RDWR);
169✔
280
      ::close(d_socket);
169✔
281
      d_socket = -1;
169✔
282
    }
169✔
283
  }
338✔
284

285
  int getDescriptor() const
286
  {
248✔
287
    return d_socket;
248✔
288
  }
248✔
289

290
  IOState tryConnect(bool fastOpen, const ComboAddress& remote)
291
  {
11✔
292
    d_remote = remote;
11✔
293

294
#ifdef TCP_FASTOPEN_CONNECT /* Linux >= 4.11 */
11✔
295
    if (fastOpen) {
11!
UNCOV
296
      int value = 1;
×
UNCOV
297
      int res = setsockopt(d_socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &value, sizeof(value));
×
UNCOV
298
      if (res == 0) {
×
UNCOV
299
        fastOpen = false;
×
UNCOV
300
      }
×
UNCOV
301
    }
×
302
#endif /* TCP_FASTOPEN_CONNECT */
11✔
303

304
#ifdef MSG_FASTOPEN
11✔
305
    if (!d_conn && fastOpen) {
11!
306
      d_fastOpen = true;
×
307
    }
×
308
    else {
11✔
309
      if (!s_disableConnectForUnitTests) {
11!
310
        SConnectWithTimeout(d_socket, remote, /* no timeout, we will handle it ourselves */ timeval{0,0});
11✔
311
      }
11✔
312
    }
11✔
313
#else
314
    if (!s_disableConnectForUnitTests) {
315
      SConnectWithTimeout(d_socket, remote, /* no timeout, we will handle it ourselves */ timeval{0,0});
316
    }
317
#endif /* MSG_FASTOPEN */
318

319
    if (d_conn) {
11✔
320
      return d_conn->tryConnect(fastOpen, remote);
4✔
321
    }
4✔
322

323
    return IOState::Done;
7✔
324
  }
11✔
325

326
  void connect(bool fastOpen, const ComboAddress& remote, const struct timeval& timeout)
UNCOV
327
  {
×
UNCOV
328
    d_remote = remote;
×
UNCOV
329

×
UNCOV
330
#ifdef TCP_FASTOPEN_CONNECT /* Linux >= 4.11 */
×
UNCOV
331
    if (fastOpen) {
×
332
      int value = 1;
×
333
      int res = setsockopt(d_socket, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &value, sizeof(value));
×
334
      if (res == 0) {
×
335
        fastOpen = false;
×
336
      }
×
337
    }
×
UNCOV
338
#endif /* TCP_FASTOPEN_CONNECT */
×
UNCOV
339

×
UNCOV
340
#ifdef MSG_FASTOPEN
×
UNCOV
341
    if (!d_conn && fastOpen) {
×
342
      d_fastOpen = true;
×
343
    }
×
UNCOV
344
    else {
×
UNCOV
345
      if (!s_disableConnectForUnitTests) {
×
UNCOV
346
        SConnectWithTimeout(d_socket, remote, timeout);
×
UNCOV
347
      }
×
UNCOV
348
    }
×
UNCOV
349
#else
×
UNCOV
350
    if (!s_disableConnectForUnitTests) {
×
UNCOV
351
      SConnectWithTimeout(d_socket, remote, timeout);
×
UNCOV
352
    }
×
UNCOV
353
#endif /* MSG_FASTOPEN */
×
UNCOV
354

×
UNCOV
355
    if (d_conn) {
×
UNCOV
356
      d_conn->connect(fastOpen, remote, timeout);
×
UNCOV
357
    }
×
UNCOV
358
  }
×
359

360
  IOState tryHandshake()
UNCOV
361
  {
×
UNCOV
362
    if (d_conn) {
×
UNCOV
363
      return d_conn->tryHandshake();
×
UNCOV
364
    }
×
UNCOV
365
    return IOState::Done;
×
UNCOV
366
  }
×
367

368
  size_t read(void* buffer, size_t bufferSize, const struct timeval& readTimeout, const struct timeval& totalTimeout = {0,0}, bool allowIncomplete=false)
369
  {
×
370
    if (d_conn) {
×
371
      return d_conn->read(buffer, bufferSize, readTimeout, totalTimeout, allowIncomplete);
×
372
    } else {
×
373
      return readn2WithTimeout(d_socket, buffer, bufferSize, readTimeout, totalTimeout, allowIncomplete);
×
374
    }
×
375
  }
×
376

377
  /* Tries to read exactly toRead - pos bytes into the buffer, starting at position pos.
378
     Updates pos everytime a successful read occurs,
379
     throws an std::runtime_error in case of IO error,
380
     return Done when toRead bytes have been read, needRead or needWrite if the IO operation
381
     would block.
382
  */
383
  IOState tryRead(PacketBuffer& buffer, size_t& pos, size_t toRead, bool allowIncomplete=false, bool bypassFilters=false)
384
  {
214✔
385
    if (buffer.size() < toRead || pos >= toRead) {
214!
386
      throw std::out_of_range("Calling tryRead() with a too small buffer (" + std::to_string(buffer.size()) + ") for a read of " + std::to_string(toRead - pos) + " bytes starting at " + std::to_string(pos));
×
387
    }
×
388

389
    if (!bypassFilters && d_conn) {
214!
390
      return d_conn->tryRead(buffer, pos, toRead, allowIncomplete);
29✔
391
    }
29✔
392

393
    do {
329✔
394
      ssize_t res = ::read(d_socket, reinterpret_cast<char*>(&buffer.at(pos)), toRead - pos);
329✔
395
      if (res == 0) {
329✔
396
        throw runtime_error("EOF while reading message");
22✔
397
      }
22✔
398
      if (res < 0) {
307✔
399
        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN) {
157!
400
          return IOState::NeedRead;
157✔
401
        }
157✔
UNCOV
402
        else {
×
UNCOV
403
          throw std::runtime_error("Error while reading message: " + stringerror());
×
UNCOV
404
        }
×
405
      }
157✔
406

407
      pos += static_cast<size_t>(res);
150✔
408
      if (allowIncomplete) {
150!
UNCOV
409
        break;
×
UNCOV
410
      }
×
411
    }
150✔
412
    while (pos < toRead);
185✔
413

414
    return IOState::Done;
6✔
415
  }
185✔
416

417
  /* Tries to write exactly toWrite - pos bytes from the buffer, starting at position pos.
418
     Updates pos everytime a successful write occurs,
419
     throws an std::runtime_error in case of IO error,
420
     return Done when toWrite bytes have been written, needRead or needWrite if the IO operation
421
     would block.
422
  */
423
  IOState tryWrite(const PacketBuffer& buffer, size_t& pos, size_t toWrite)
424
  {
190✔
425
    if (buffer.size() < toWrite || pos >= toWrite) {
190!
426
      throw std::out_of_range("Calling tryWrite() with a too small buffer (" + std::to_string(buffer.size()) + ") for a write of " + std::to_string(toWrite - pos) + " bytes starting at " + std::to_string(pos));
×
427
    }
×
428
    if (d_conn) {
190✔
429
      return d_conn->tryWrite(buffer, pos, toWrite);
17✔
430
    }
17✔
431

432
#ifdef MSG_FASTOPEN
173✔
433
    if (d_fastOpen) {
173!
434
      int socketFlags = MSG_FASTOPEN;
×
435
      size_t sent = sendMsgWithOptions(d_socket, reinterpret_cast<const char *>(&buffer.at(pos)), toWrite - pos, &d_remote, nullptr, 0, socketFlags);
×
436
      if (sent > 0) {
×
437
        d_fastOpen = false;
×
438
        pos += sent;
×
439
      }
×
440

441
      if (pos < toWrite) {
×
442
        return IOState::NeedWrite;
×
443
      }
×
444

445
      return IOState::Done;
×
446
    }
×
447
#endif /* MSG_FASTOPEN */
173✔
448

449
    do {
173✔
450
      ssize_t res = ::write(d_socket, reinterpret_cast<const char*>(&buffer.at(pos)), toWrite - pos);
173✔
451

452
      if (res == 0) {
173!
453
        throw runtime_error("EOF while sending message");
×
454
      }
×
455
      if (res < 0) {
173✔
456
        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN) {
1!
457
          return IOState::NeedWrite;
1✔
458
        }
1✔
459
        else {
×
460
          throw std::runtime_error("Error while writing message: " + stringerror());
×
461
        }
×
462
      }
1✔
463

464
      pos += static_cast<size_t>(res);
172✔
465
    }
172✔
466
    while (pos < toWrite);
173!
467

468
    return IOState::Done;
172✔
469
  }
173✔
470

471
  size_t write(const void* buffer, size_t bufferSize, const struct timeval& writeTimeout)
472
  {
×
473
    if (d_conn) {
×
474
      return d_conn->write(buffer, bufferSize, writeTimeout);
×
475
    }
×
476

×
477
#ifdef MSG_FASTOPEN
×
478
    if (d_fastOpen) {
×
479
      int socketFlags = MSG_FASTOPEN;
×
480
      size_t sent = sendMsgWithOptions(d_socket, reinterpret_cast<const char *>(buffer), bufferSize, &d_remote, nullptr, 0, socketFlags);
×
481
      if (sent > 0) {
×
482
        d_fastOpen = false;
×
483
      }
×
484

×
485
      return sent;
×
486
    }
×
487
#endif /* MSG_FASTOPEN */
×
488

×
489
    return writen2WithTimeout(d_socket, buffer, bufferSize, writeTimeout);
×
490
  }
×
491

492
  std::string getServerNameIndication() const
UNCOV
493
  {
×
UNCOV
494
    if (d_conn) {
×
UNCOV
495
      return d_conn->getServerNameIndication();
×
UNCOV
496
    }
×
UNCOV
497
    return std::string();
×
UNCOV
498
  }
×
499

500
  std::vector<uint8_t> getNextProtocol() const
UNCOV
501
  {
×
UNCOV
502
    if (d_conn) {
×
UNCOV
503
      return d_conn->getNextProtocol();
×
UNCOV
504
    }
×
505
    return std::vector<uint8_t>();
×
UNCOV
506
  }
×
507

508
  LibsslTLSVersion getTLSVersion() const
UNCOV
509
  {
×
UNCOV
510
    if (d_conn) {
×
UNCOV
511
      return d_conn->getTLSVersion();
×
UNCOV
512
    }
×
513
    return LibsslTLSVersion::Unknown;
×
UNCOV
514
  }
×
515

516
  bool isTLS() const
UNCOV
517
  {
×
UNCOV
518
    return d_conn != nullptr;
×
UNCOV
519
  }
×
520

521
  bool hasTLSSessionBeenResumed() const
UNCOV
522
  {
×
UNCOV
523
    return d_conn && d_conn->hasSessionBeenResumed();
×
UNCOV
524
  }
×
525

526
  bool getResumedFromInactiveTicketKey() const
UNCOV
527
  {
×
UNCOV
528
    return d_conn && d_conn->getResumedFromInactiveTicketKey();
×
UNCOV
529
  }
×
530

531
  bool getUnknownTicketKey() const
UNCOV
532
  {
×
UNCOV
533
    return d_conn && d_conn->getUnknownTicketKey();
×
UNCOV
534
  }
×
535

536
  void setTLSSession(std::unique_ptr<TLSSession>& session)
UNCOV
537
  {
×
UNCOV
538
    if (d_conn != nullptr) {
×
UNCOV
539
      d_conn->setSession(session);
×
UNCOV
540
    }
×
UNCOV
541
  }
×
542

543
  std::vector<std::unique_ptr<TLSSession>> getTLSSessions()
UNCOV
544
  {
×
UNCOV
545
    if (!d_conn) {
×
546
      throw std::runtime_error("Trying to get TLS sessions from a non-TLS handler");
×
547
    }
×
UNCOV
548

×
UNCOV
549
    return d_conn->getSessions();
×
UNCOV
550
  }
×
551

552
  bool isUsable() const
UNCOV
553
  {
×
UNCOV
554
    if (!d_conn) {
×
UNCOV
555
      return isTCPSocketUsable(d_socket);
×
UNCOV
556
    }
×
UNCOV
557
    return d_conn->isUsable();
×
UNCOV
558
  }
×
559

560
  std::vector<int> getAsyncFDs()
UNCOV
561
  {
×
UNCOV
562
    if (!d_conn) {
×
UNCOV
563
      return {};
×
UNCOV
564
    }
×
UNCOV
565
    return d_conn->getAsyncFDs();
×
UNCOV
566
  }
×
567

568
  static const bool s_disableConnectForUnitTests;
569

570
private:
571
  std::unique_ptr<TLSConnection> d_conn{nullptr};
572
  ComboAddress d_remote;
573
  int d_socket{-1};
574
#ifdef MSG_FASTOPEN
575
  bool d_fastOpen{false};
576
#endif
577
};
578

579
struct TLSContextParameters
580
{
581
  std::string d_provider;
582
  std::string d_ciphers;
583
  std::string d_ciphers13;
584
  std::string d_caStore;
585
  std::string d_keyLogFile;
586
  TLSFrontend::ALPN d_alpn{TLSFrontend::ALPN::Unset};
587
  bool d_validateCertificates{true};
588
  bool d_releaseBuffers{true};
589
  bool d_enableRenegotiation{false};
590
  bool d_ktls{false};
591
};
592

593
std::shared_ptr<TLSCtx> getTLSContext(const TLSContextParameters& params);
594
bool setupDoTProtocolNegotiation(std::shared_ptr<TLSCtx>& ctx);
595
bool setupDoHProtocolNegotiation(std::shared_ptr<TLSCtx>& ctx);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc