1use anyhow::{Context as _, Result};
44use std::collections::HashMap;
45use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
46use std::str::FromStr;
47use std::sync::LazyLock;
48use tokio::net::lookup_host;
49use tokio::time::timeout;
50
51use super::load_connection_timestamp;
52use crate::context::Context;
53use crate::log::warn;
54use crate::tools::time;
55
56async fn update_cache(context: &Context, host: &str, addr: &str, now: i64) -> Result<()> {
59 context
60 .sql
61 .execute(
62 "INSERT INTO dns_cache
63 (hostname, address, timestamp)
64 VALUES (?, ?, ?)
65 ON CONFLICT (hostname, address)
66 DO UPDATE SET timestamp=excluded.timestamp",
67 (host, addr, now),
68 )
69 .await?;
70 Ok(())
71}
72
73pub(crate) async fn prune_dns_cache(context: &Context) -> Result<()> {
74 let now = time();
75 context
76 .sql
77 .execute(
78 "DELETE FROM dns_cache
79 WHERE ? > timestamp + ?",
80 (now, super::CACHE_TTL),
81 )
82 .await?;
83 Ok(())
84}
85
86static LOOKUP_HOST_CACHE: LazyLock<parking_lot::RwLock<HashMap<String, Vec<IpAddr>>>> =
95 LazyLock::new(Default::default);
96
97async fn lookup_ips(host: impl tokio::net::ToSocketAddrs) -> Result<impl Iterator<Item = IpAddr>> {
99 Ok(lookup_host(host)
100 .await
101 .context("DNS lookup failure")?
102 .map(|addr| addr.ip()))
103}
104
105async fn lookup_host_with_memory_cache(
106 context: &Context,
107 hostname: &str,
108 port: u16,
109) -> Result<Vec<IpAddr>> {
110 let stale_result = {
111 let rwlock_read_guard = LOOKUP_HOST_CACHE.read();
112 rwlock_read_guard.get(hostname).cloned()
113 };
114 if let Some(stale_result) = stale_result {
115 {
117 let context = context.clone();
118 let hostname = hostname.to_string();
119 tokio::spawn(async move {
120 match lookup_ips((hostname.clone(), port)).await {
121 Ok(res) => {
122 LOOKUP_HOST_CACHE.write().insert(hostname, res.collect());
123 }
124 Err(err) => {
125 warn!(
126 context,
127 "Failed to revalidate results for {hostname:?}: {err:#}."
128 );
129 }
130 }
131 });
132 }
133
134 info!(
135 context,
136 "Using memory-cached DNS resolution for {hostname}."
137 );
138 Ok(stale_result)
139 } else {
140 info!(
141 context,
142 "No memory-cached DNS resolution for {hostname} available, waiting for the resolver."
143 );
144 let res: Vec<IpAddr> = lookup_ips((hostname, port)).await?.collect();
145
146 LOOKUP_HOST_CACHE
151 .write()
152 .insert(hostname.to_string(), res.clone());
153 Ok(res)
154 }
155}
156
157async fn lookup_host_and_update_cache(
160 context: &Context,
161 hostname: &str,
162 port: u16,
163 now: i64,
164) -> Result<Vec<SocketAddr>> {
165 let res: Vec<IpAddr> = timeout(
166 super::TIMEOUT,
167 lookup_host_with_memory_cache(context, hostname, port),
168 )
169 .await
170 .context("DNS lookup timeout")?
171 .context("DNS lookup with memory cache failure")?;
172
173 for ip in &res {
174 let ip_string = ip.to_string();
175 if ip_string == hostname {
176 continue;
178 }
179
180 info!(context, "Resolved {hostname} into {ip}.");
181
182 update_cache(context, hostname, &ip_string, now).await?;
184 }
185
186 let res = res
187 .into_iter()
188 .map(|ip| SocketAddr::new(ip, port))
189 .collect();
190 Ok(res)
191}
192
193pub(crate) async fn update_connect_timestamp(
208 context: &Context,
209 host: &str,
210 address: &str,
211) -> Result<()> {
212 if host == address {
213 return Ok(());
214 }
215
216 context
217 .sql
218 .execute(
219 "INSERT INTO dns_cache (hostname, address, timestamp)
220 VALUES (?, ?, ?)
221 ON CONFLICT (hostname, address)
222 DO UPDATE SET timestamp=excluded.timestamp",
223 (host, address, time()),
224 )
225 .await?;
226 Ok(())
227}
228
229static DNS_PRELOAD: LazyLock<HashMap<&'static str, Vec<IpAddr>>> = LazyLock::new(|| {
231 HashMap::from([
232 (
233 "imap.163.com",
234 vec![IpAddr::V4(Ipv4Addr::new(111, 124, 203, 45))],
235 ),
236 (
237 "smtp.163.com",
238 vec![IpAddr::V4(Ipv4Addr::new(103, 129, 252, 45))],
239 ),
240 (
241 "newyear.aktivix.org",
242 vec![IpAddr::V4(Ipv4Addr::new(209, 51, 180, 245))],
243 ),
244 (
245 "smtp.aliyun.com",
246 vec![IpAddr::V4(Ipv4Addr::new(47, 246, 136, 232))],
247 ),
248 (
249 "imap.aliyun.com",
250 vec![
251 IpAddr::V4(Ipv4Addr::new(59, 82, 43, 123)),
252 IpAddr::V4(Ipv4Addr::new(59, 82, 9, 176)),
253 ],
254 ),
255 (
256 "imap.aol.com",
257 vec![
258 IpAddr::V4(Ipv4Addr::new(212, 82, 101, 33)),
259 IpAddr::V4(Ipv4Addr::new(87, 248, 98, 69)),
260 ],
261 ),
262 (
263 "imap.arcor.de",
264 vec![
265 IpAddr::V4(Ipv4Addr::new(178, 15, 69, 210)),
266 IpAddr::V4(Ipv4Addr::new(151, 189, 176, 206)),
267 ],
268 ),
269 (
270 "smtp.aol.com",
271 vec![IpAddr::V4(Ipv4Addr::new(87, 248, 97, 31))],
272 ),
273 (
274 "mail.arcor.de",
275 vec![
276 IpAddr::V4(Ipv4Addr::new(151, 189, 176, 206)),
277 IpAddr::V4(Ipv4Addr::new(178, 15, 69, 206)),
278 ],
279 ),
280 (
281 "mail.autistici.org",
282 vec![
283 IpAddr::V4(Ipv4Addr::new(93, 190, 126, 19)),
284 IpAddr::V4(Ipv4Addr::new(185, 218, 207, 228)),
285 IpAddr::V4(Ipv4Addr::new(198, 167, 222, 108)),
286 ],
287 ),
288 (
289 "smtp.autistici.org",
290 vec![
291 IpAddr::V4(Ipv4Addr::new(82, 94, 249, 234)),
292 IpAddr::V4(Ipv4Addr::new(93, 190, 126, 19)),
293 IpAddr::V4(Ipv4Addr::new(198, 167, 222, 108)),
294 ],
295 ),
296 (
297 "imaps.bluewin.ch",
298 vec![
299 IpAddr::V4(Ipv4Addr::new(16, 62, 253, 42)),
300 IpAddr::V4(Ipv4Addr::new(16, 63, 141, 244)),
301 IpAddr::V4(Ipv4Addr::new(16, 63, 146, 183)),
302 ],
303 ),
304 (
305 "smtpauths.bluewin.ch",
306 vec![
307 IpAddr::V4(Ipv4Addr::new(16, 62, 176, 232)),
308 IpAddr::V4(Ipv4Addr::new(16, 62, 15, 25)),
309 IpAddr::V4(Ipv4Addr::new(16, 63, 183, 216)),
310 ],
311 ),
312 (
313 "mail.buzon.uy",
314 vec![IpAddr::V4(Ipv4Addr::new(200, 40, 115, 74))],
315 ),
316 (
317 "daleth.cafe",
318 vec![IpAddr::V4(Ipv4Addr::new(37, 27, 6, 204))],
319 ),
320 (
321 "disroot.org",
322 vec![IpAddr::V4(Ipv4Addr::new(178, 21, 23, 139))],
323 ),
324 (
325 "imap.fastmail.com",
326 vec![
327 IpAddr::V4(Ipv4Addr::new(103, 168, 172, 43)),
328 IpAddr::V4(Ipv4Addr::new(103, 168, 172, 58)),
329 ],
330 ),
331 (
332 "smtp.fastmail.com",
333 vec![
334 IpAddr::V4(Ipv4Addr::new(103, 168, 172, 45)),
335 IpAddr::V4(Ipv4Addr::new(103, 168, 172, 60)),
336 ],
337 ),
338 (
339 "imap.gmail.com",
340 vec![
341 IpAddr::V4(Ipv4Addr::new(142, 250, 110, 108)),
342 IpAddr::V4(Ipv4Addr::new(142, 250, 110, 109)),
343 IpAddr::V4(Ipv4Addr::new(66, 102, 1, 108)),
344 IpAddr::V4(Ipv4Addr::new(66, 102, 1, 109)),
345 IpAddr::V6(Ipv6Addr::new(0x2a00, 0x1450, 0x400c, 0xc1f, 0, 0, 0, 0x6c)),
346 IpAddr::V6(Ipv6Addr::new(0x2a00, 0x1450, 0x400c, 0xc1f, 0, 0, 0, 0x6d)),
347 ],
348 ),
349 (
350 "mail.ecloud.global",
351 vec![IpAddr::V4(Ipv4Addr::new(95, 217, 246, 96))],
352 ),
353 (
354 "mail.ende.in.net",
355 vec![IpAddr::V4(Ipv4Addr::new(95, 217, 5, 72))],
356 ),
357 (
358 "smtp.gmail.com",
359 vec![
360 IpAddr::V4(Ipv4Addr::new(142, 250, 110, 109)),
361 IpAddr::V6(Ipv6Addr::new(0x2a00, 0x1450, 0x4013, 0xc04, 0, 0, 0, 0x6c)),
362 ],
363 ),
364 (
365 "mail.gmx.net",
366 vec![
367 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 190)),
368 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 168)),
369 ],
370 ),
371 (
372 "imap.gmx.net",
373 vec![
374 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 170)),
375 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 186)),
376 ],
377 ),
378 (
379 "mail.sangham.net",
380 vec![
381 IpAddr::V4(Ipv4Addr::new(159, 69, 186, 85)),
382 IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0xc17, 0x798c, 0, 0, 0, 1)),
383 ],
384 ),
385 (
386 "imap.mail.de",
387 vec![IpAddr::V4(Ipv4Addr::new(62, 201, 172, 16))],
388 ),
389 (
390 "smtp.mailbox.org",
391 vec![IpAddr::V4(Ipv4Addr::new(185, 97, 174, 196))],
392 ),
393 (
394 "imap.mailbox.org",
395 vec![IpAddr::V4(Ipv4Addr::new(185, 97, 174, 199))],
396 ),
397 (
398 "imap.naver.com",
399 vec![IpAddr::V4(Ipv4Addr::new(125, 209, 233, 34))],
400 ),
401 (
402 "imap.ouvaton.coop",
403 vec![IpAddr::V4(Ipv4Addr::new(194, 36, 166, 20))],
404 ),
405 (
406 "imap.purelymail.com",
407 vec![IpAddr::V4(Ipv4Addr::new(18, 204, 123, 63))],
408 ),
409 (
410 "mail.systemausfall.org",
411 vec![
412 IpAddr::V4(Ipv4Addr::new(51, 75, 71, 249)),
413 IpAddr::V4(Ipv4Addr::new(80, 153, 252, 42)),
414 ],
415 ),
416 (
417 "mail.systemli.org",
418 vec![IpAddr::V4(Ipv4Addr::new(93, 190, 126, 36))],
419 ),
420 ("testrun.org", vec![IpAddr::V4(Ipv4Addr::new(5, 1, 76, 52))]),
421 (
422 "nine.testrun.org",
423 vec![
424 IpAddr::V4(Ipv4Addr::new(128, 140, 126, 197)),
425 IpAddr::V4(Ipv4Addr::new(116, 202, 233, 236)),
426 IpAddr::V4(Ipv4Addr::new(216, 144, 228, 100)),
427 IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0x241, 0x4ce8, 0, 0, 0, 2)),
428 IpAddr::V6(Ipv6Addr::new(
429 0x2001, 0x41d0, 0x701, 0x1100, 0, 0, 0, 0x8ab1,
430 )),
431 ],
432 ),
433 (
434 "secureimap.t-online.de",
435 vec![
436 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 114)),
437 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 115)),
438 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 50)),
439 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 51)),
440 ],
441 ),
442 (
443 "securesmtp.t-online.de",
444 vec![
445 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 46)),
446 IpAddr::V4(Ipv4Addr::new(194, 25, 134, 110)),
447 ],
448 ),
449 (
450 "mail.riseup.net",
451 vec![
452 IpAddr::V4(Ipv4Addr::new(198, 252, 153, 171)),
453 IpAddr::V4(Ipv4Addr::new(198, 252, 153, 170)),
454 ],
455 ),
456 (
457 "pimap.schulon.org",
458 vec![IpAddr::V4(Ipv4Addr::new(194, 77, 246, 20))],
459 ),
460 (
461 "imap.tiscali.it",
462 vec![IpAddr::V4(Ipv4Addr::new(213, 205, 33, 10))],
463 ),
464 (
465 "smtp.tiscali.it",
466 vec![IpAddr::V4(Ipv4Addr::new(213, 205, 33, 13))],
467 ),
468 (
469 "imap.ukr.net",
470 vec![IpAddr::V4(Ipv4Addr::new(212, 42, 75, 240))],
471 ),
472 (
473 "smtp.ukr.net",
474 vec![IpAddr::V4(Ipv4Addr::new(212, 42, 75, 250))],
475 ),
476 (
477 "imap.web.de",
478 vec![
479 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 162)),
480 IpAddr::V4(Ipv4Addr::new(212, 227, 17, 178)),
481 ],
482 ),
483 (
484 "imap.ziggo.nl",
485 vec![IpAddr::V4(Ipv4Addr::new(84, 116, 6, 3))],
486 ),
487 (
488 "imap.zoho.eu",
489 vec![
490 IpAddr::V4(Ipv4Addr::new(185, 230, 214, 25)),
491 IpAddr::V4(Ipv4Addr::new(185, 230, 214, 206)),
492 ],
493 ),
494 (
495 "mail.infomaniak.com",
496 vec![
497 IpAddr::V4(Ipv4Addr::new(83, 166, 143, 44)),
498 IpAddr::V4(Ipv4Addr::new(83, 166, 143, 45)),
499 ],
500 ),
501 (
502 "mail.mymagenta.at",
503 vec![IpAddr::V4(Ipv4Addr::new(80, 109, 253, 241))],
504 ),
505 (
506 "mail.nubo.coop",
507 vec![IpAddr::V4(Ipv4Addr::new(79, 99, 201, 10))],
508 ),
509 (
510 "mehl.cloud",
511 vec![IpAddr::V4(Ipv4Addr::new(95, 217, 223, 172))],
512 ),
513 (
514 "mx.freenet.de",
515 vec![
516 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 36)),
517 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 34)),
518 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 35)),
519 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 39)),
520 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 37)),
521 IpAddr::V4(Ipv4Addr::new(194, 97, 208, 38)),
522 ],
523 ),
524 (
525 "posteo.de",
526 vec![
527 IpAddr::V4(Ipv4Addr::new(185, 67, 36, 168)),
528 IpAddr::V4(Ipv4Addr::new(185, 67, 36, 169)),
529 ],
530 ),
531 (
532 "psmtp.schulon.org",
533 vec![IpAddr::V4(Ipv4Addr::new(194, 77, 246, 20))],
534 ),
535 (
536 "smtp.mail.de",
537 vec![IpAddr::V4(Ipv4Addr::new(62, 201, 172, 21))],
538 ),
539 (
540 "smtp.mail.ru",
541 vec![
542 IpAddr::V4(Ipv4Addr::new(94, 100, 180, 160)),
543 IpAddr::V4(Ipv4Addr::new(217, 69, 139, 160)),
544 ],
545 ),
546 (
547 "imap.mail.yahoo.com",
548 vec![
549 IpAddr::V4(Ipv4Addr::new(87, 248, 103, 8)),
550 IpAddr::V4(Ipv4Addr::new(212, 82, 101, 24)),
551 ],
552 ),
553 (
554 "smtp.mail.yahoo.com",
555 vec![IpAddr::V4(Ipv4Addr::new(87, 248, 97, 36))],
556 ),
557 (
558 "imap.mailo.com",
559 vec![IpAddr::V4(Ipv4Addr::new(213, 182, 54, 20))],
560 ),
561 (
562 "imap.migadu.com",
563 vec![
564 IpAddr::V4(Ipv4Addr::new(51, 210, 3, 23)),
565 IpAddr::V4(Ipv4Addr::new(51, 210, 3, 20)),
566 ],
567 ),
568 (
569 "smtp.migadu.com",
570 vec![
571 IpAddr::V4(Ipv4Addr::new(37, 59, 57, 117)),
572 IpAddr::V4(Ipv4Addr::new(51, 255, 82, 75)),
573 ],
574 ),
575 (
576 "smtp.mailo.com",
577 vec![IpAddr::V4(Ipv4Addr::new(213, 182, 54, 20))],
578 ),
579 (
580 "smtp.naver.com",
581 vec![IpAddr::V4(Ipv4Addr::new(125, 209, 238, 155))],
582 ),
583 (
584 "smtp.ouvaton.coop",
585 vec![IpAddr::V4(Ipv4Addr::new(194, 36, 166, 20))],
586 ),
587 (
588 "smtp.purelymail.com",
589 vec![IpAddr::V4(Ipv4Addr::new(18, 204, 123, 63))],
590 ),
591 (
592 "imap.qq.com",
593 vec![
594 IpAddr::V4(Ipv4Addr::new(43, 163, 178, 76)),
595 IpAddr::V4(Ipv4Addr::new(43, 129, 255, 54)),
596 ],
597 ),
598 (
599 "smtp.qq.com",
600 vec![
601 IpAddr::V4(Ipv4Addr::new(43, 129, 255, 54)),
602 IpAddr::V4(Ipv4Addr::new(43, 163, 178, 76)),
603 ],
604 ),
605 (
606 "imap.rambler.ru",
607 vec![
608 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 168)),
609 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 169)),
610 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 170)),
611 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 171)),
612 ],
613 ),
614 (
615 "smtp.rambler.ru",
616 vec![
617 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 164)),
618 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 165)),
619 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 166)),
620 IpAddr::V4(Ipv4Addr::new(81, 19, 77, 167)),
621 ],
622 ),
623 (
624 "stinpriza.net",
625 vec![IpAddr::V4(Ipv4Addr::new(5, 9, 122, 184))],
626 ),
627 (
628 "webbox222.server-home.org",
629 vec![IpAddr::V4(Ipv4Addr::new(91, 203, 111, 88))],
630 ),
631 (
632 "undernet.uy",
633 vec![IpAddr::V4(Ipv4Addr::new(200, 40, 115, 74))],
634 ),
635 (
636 "imap.vivaldi.net",
637 vec![IpAddr::V4(Ipv4Addr::new(31, 209, 137, 15))],
638 ),
639 (
640 "smtp.vivaldi.net",
641 vec![IpAddr::V4(Ipv4Addr::new(31, 209, 137, 12))],
642 ),
643 (
644 "imap.vodafonemail.de",
645 vec![
646 IpAddr::V4(Ipv4Addr::new(178, 15, 69, 210)),
647 IpAddr::V4(Ipv4Addr::new(151, 189, 176, 206)),
648 ],
649 ),
650 (
651 "smtp.vodafonemail.de",
652 vec![
653 IpAddr::V4(Ipv4Addr::new(151, 189, 176, 206)),
654 IpAddr::V4(Ipv4Addr::new(178, 15, 69, 206)),
655 ],
656 ),
657 (
658 "smtp.web.de",
659 vec![
660 IpAddr::V4(Ipv4Addr::new(213, 165, 67, 124)),
661 IpAddr::V4(Ipv4Addr::new(213, 165, 67, 108)),
662 ],
663 ),
664 (
665 "imap.yandex.com",
666 vec![IpAddr::V4(Ipv4Addr::new(77, 88, 21, 125))],
667 ),
668 (
669 "smtp.yandex.com",
670 vec![IpAddr::V4(Ipv4Addr::new(77, 88, 21, 158))],
671 ),
672 (
673 "smtp.ziggo.nl",
674 vec![IpAddr::V4(Ipv4Addr::new(84, 116, 6, 3))],
675 ),
676 (
677 "smtp.zoho.eu",
678 vec![
679 IpAddr::V4(Ipv4Addr::new(185, 230, 212, 164)),
680 IpAddr::V4(Ipv4Addr::new(185, 230, 214, 164)),
681 ],
682 ),
683 ])
684});
685
686async fn lookup_cache(
687 context: &Context,
688 host: &str,
689 port: u16,
690 alpn: &str,
691 now: i64,
692) -> Result<Vec<SocketAddr>> {
693 let mut res = Vec::new();
694 for cached_address in context
695 .sql
696 .query_map_vec(
697 "SELECT dns_cache.address
698 FROM dns_cache
699 LEFT JOIN connection_history
700 ON dns_cache.hostname = connection_history.host
701 AND dns_cache.address = connection_history.addr
702 AND connection_history.port = ?
703 AND connection_history.alpn = ?
704 WHERE dns_cache.hostname = ?
705 AND ? < dns_cache.timestamp + ?
706 ORDER BY IFNULL(connection_history.timestamp, dns_cache.timestamp) DESC
707 LIMIT 50",
708 (port, alpn, host, now, super::CACHE_TTL),
709 |row| {
710 let address: String = row.get(0)?;
711 Ok(address)
712 },
713 )
714 .await?
715 {
716 match IpAddr::from_str(&cached_address) {
717 Ok(ip_addr) => {
718 let addr = SocketAddr::new(ip_addr, port);
719 res.push(addr);
720 }
721 Err(err) => {
722 warn!(
723 context,
724 "Failed to parse cached address {:?}: {:#}.", cached_address, err
725 );
726 }
727 }
728 }
729 Ok(res)
730}
731
732async fn sort_by_connection_timestamp(
735 context: &Context,
736 input: Vec<SocketAddr>,
737 alpn: &str,
738 host: &str,
739) -> Result<Vec<SocketAddr>> {
740 let mut res: Vec<(Option<i64>, SocketAddr)> = Vec::with_capacity(input.len());
741 for addr in input {
742 let timestamp = load_connection_timestamp(
743 &context.sql,
744 alpn,
745 host,
746 addr.port(),
747 Some(&addr.ip().to_string()),
748 )
749 .await?;
750 res.push((timestamp, addr));
751 }
752 res.sort_by_key(|(ts, _addr)| std::cmp::Reverse(*ts));
753 Ok(res.into_iter().map(|(_ts, addr)| addr).collect())
754}
755
756pub(crate) async fn lookup_host_with_cache(
767 context: &Context,
768 hostname: &str,
769 port: u16,
770 alpn: &str,
771 load_cache: bool,
772) -> Result<Vec<SocketAddr>> {
773 let now = time();
774 let resolved_addrs = match lookup_host_and_update_cache(context, hostname, port, now).await {
775 Ok(res) => {
776 if alpn.is_empty() {
777 res
778 } else {
779 sort_by_connection_timestamp(context, res, alpn, hostname).await?
780 }
781 }
782 Err(err) => {
783 warn!(
784 context,
785 "DNS resolution for {hostname}:{port} failed: {err:#}."
786 );
787 Vec::new()
788 }
789 };
790
791 if load_cache {
792 let mut cache = lookup_cache(context, hostname, port, alpn, now).await?;
793 if let Some(ips) = DNS_PRELOAD.get(hostname) {
794 for ip in ips {
795 let addr = SocketAddr::new(*ip, port);
796 if !cache.contains(&addr) {
797 cache.push(addr);
798 }
799 }
800 }
801
802 Ok(merge_with_cache(resolved_addrs, cache))
803 } else {
804 Ok(resolved_addrs)
805 }
806}
807
808fn merge_with_cache(
812 mut resolved_addrs: Vec<SocketAddr>,
813 cache: Vec<SocketAddr>,
814) -> Vec<SocketAddr> {
815 let rest = resolved_addrs.split_off(std::cmp::min(resolved_addrs.len(), 2));
816
817 for addr in cache.into_iter().chain(rest.into_iter()) {
818 if !resolved_addrs.contains(&addr) {
819 resolved_addrs.push(addr);
820 if resolved_addrs.len() >= 10 {
821 break;
822 }
823 }
824 }
825
826 resolved_addrs
827}
828
829#[cfg(test)]
830mod tests {
831 use super::*;
832
833 use crate::net::update_connection_history;
834 use crate::test_utils::TestContext;
835
836 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
837 async fn test_sort_by_connection_timestamp() {
838 let alice = &TestContext::new_alice().await;
839 let now = time();
840
841 let ipv6_addr = IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0x241, 0x4ce8, 0, 0, 0, 2));
842 let ipv4_addr = IpAddr::V4(Ipv4Addr::new(116, 202, 233, 236));
843
844 assert_eq!(
845 sort_by_connection_timestamp(
846 alice,
847 vec![
848 SocketAddr::new(ipv6_addr, 993),
849 SocketAddr::new(ipv4_addr, 993)
850 ],
851 "imap",
852 "nine.testrun.org"
853 )
854 .await
855 .unwrap(),
856 vec![
857 SocketAddr::new(ipv6_addr, 993),
858 SocketAddr::new(ipv4_addr, 993)
859 ]
860 );
861 update_connection_history(
862 alice,
863 "imap",
864 "nine.testrun.org",
865 993,
866 "116.202.233.236",
867 now,
868 )
869 .await
870 .unwrap();
871 assert_eq!(
872 sort_by_connection_timestamp(
873 alice,
874 vec![
875 SocketAddr::new(ipv6_addr, 993),
876 SocketAddr::new(ipv4_addr, 993)
877 ],
878 "imap",
879 "nine.testrun.org"
880 )
881 .await
882 .unwrap(),
883 vec![
884 SocketAddr::new(ipv4_addr, 993),
885 SocketAddr::new(ipv6_addr, 993),
886 ]
887 );
888
889 assert_eq!(
890 sort_by_connection_timestamp(
891 alice,
892 vec![
893 SocketAddr::new(ipv6_addr, 465),
894 SocketAddr::new(ipv4_addr, 465)
895 ],
896 "smtp",
897 "nine.testrun.org"
898 )
899 .await
900 .unwrap(),
901 vec![
902 SocketAddr::new(ipv6_addr, 465),
903 SocketAddr::new(ipv4_addr, 465),
904 ]
905 );
906 update_connection_history(
907 alice,
908 "smtp",
909 "nine.testrun.org",
910 465,
911 "116.202.233.236",
912 now,
913 )
914 .await
915 .unwrap();
916 assert_eq!(
917 sort_by_connection_timestamp(
918 alice,
919 vec![
920 SocketAddr::new(ipv6_addr, 465),
921 SocketAddr::new(ipv4_addr, 465)
922 ],
923 "smtp",
924 "nine.testrun.org"
925 )
926 .await
927 .unwrap(),
928 vec![
929 SocketAddr::new(ipv4_addr, 465),
930 SocketAddr::new(ipv6_addr, 465),
931 ]
932 );
933
934 update_connection_history(
935 alice,
936 "imap",
937 "nine.testrun.org",
938 993,
939 "2a01:4f8:241:4ce8::2",
940 now,
941 )
942 .await
943 .unwrap();
944 assert_eq!(
945 sort_by_connection_timestamp(
946 alice,
947 vec![
948 SocketAddr::new(ipv6_addr, 993),
949 SocketAddr::new(ipv4_addr, 993)
950 ],
951 "imap",
952 "nine.testrun.org"
953 )
954 .await
955 .unwrap(),
956 vec![
957 SocketAddr::new(ipv6_addr, 993),
958 SocketAddr::new(ipv4_addr, 993)
959 ]
960 );
961 }
962
963 #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
964 async fn test_lookup_cache() {
965 let alice = &TestContext::new_alice().await;
966
967 let ipv4_addr = IpAddr::V4(Ipv4Addr::new(116, 202, 233, 236));
968 let ipv6_addr = IpAddr::V6(Ipv6Addr::new(0x2a01, 0x4f8, 0x241, 0x4ce8, 0, 0, 0, 2));
969
970 let now = time();
971 assert!(
972 lookup_cache(alice, "nine.testrun.org", 587, "smtp", now)
973 .await
974 .unwrap()
975 .is_empty()
976 );
977
978 update_cache(alice, "nine.testrun.org", "116.202.233.236", now)
979 .await
980 .unwrap();
981
982 assert_eq!(
983 lookup_cache(alice, "nine.testrun.org", 587, "smtp", now)
984 .await
985 .unwrap(),
986 vec![SocketAddr::new(ipv4_addr, 587)]
987 );
988
989 assert_eq!(
992 lookup_cache(alice, "nine.testrun.org", 443, "", now)
993 .await
994 .unwrap(),
995 vec![SocketAddr::new(ipv4_addr, 443)]
996 );
997
998 update_cache(alice, "nine.testrun.org", "2a01:4f8:241:4ce8::2", now + 30)
999 .await
1000 .unwrap();
1001
1002 assert_eq!(
1004 lookup_cache(alice, "nine.testrun.org", 443, "", now + 60)
1005 .await
1006 .unwrap(),
1007 vec![
1008 SocketAddr::new(ipv6_addr, 443),
1009 SocketAddr::new(ipv4_addr, 443)
1010 ],
1011 );
1012
1013 update_connection_history(
1016 alice,
1017 "smtp",
1018 "nine.testrun.org",
1019 465,
1020 "116.202.233.236",
1021 now + 100,
1022 )
1023 .await
1024 .unwrap();
1025 assert_eq!(
1026 lookup_cache(alice, "nine.testrun.org", 465, "smtp", now + 120)
1027 .await
1028 .unwrap(),
1029 vec![
1030 SocketAddr::new(ipv4_addr, 465),
1031 SocketAddr::new(ipv6_addr, 465)
1032 ]
1033 );
1034
1035 assert_eq!(
1037 lookup_cache(alice, "nine.testrun.org", 993, "imap", now + 120)
1038 .await
1039 .unwrap(),
1040 vec![
1041 SocketAddr::new(ipv6_addr, 993),
1042 SocketAddr::new(ipv4_addr, 993)
1043 ],
1044 );
1045 assert_eq!(
1046 lookup_cache(alice, "nine.testrun.org", 465, "imap", now + 120)
1047 .await
1048 .unwrap(),
1049 vec![
1050 SocketAddr::new(ipv6_addr, 465),
1051 SocketAddr::new(ipv4_addr, 465)
1052 ],
1053 );
1054 assert_eq!(
1055 lookup_cache(alice, "nine.testrun.org", 993, "smtp", now + 120)
1056 .await
1057 .unwrap(),
1058 vec![
1059 SocketAddr::new(ipv6_addr, 993),
1060 SocketAddr::new(ipv4_addr, 993)
1061 ],
1062 );
1063 }
1064
1065 #[test]
1066 fn test_merge_with_cache() {
1067 let first_addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
1068 let second_addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 2));
1069
1070 {
1072 let resolved_addrs = vec![
1073 SocketAddr::new(first_addr, 993),
1074 SocketAddr::new(second_addr, 993),
1075 ];
1076 let cache = vec![];
1077 assert_eq!(
1078 merge_with_cache(resolved_addrs.clone(), cache),
1079 resolved_addrs
1080 );
1081 }
1082
1083 {
1086 let resolved_addrs = vec![SocketAddr::new(first_addr, 993)];
1087 let cache = vec![SocketAddr::new(second_addr, 993)];
1088 assert_eq!(
1089 merge_with_cache(resolved_addrs, cache),
1090 vec![
1091 SocketAddr::new(first_addr, 993),
1092 SocketAddr::new(second_addr, 993),
1093 ]
1094 );
1095 }
1096
1097 {
1100 let resolved_addrs = vec![
1101 SocketAddr::new(first_addr, 993),
1102 SocketAddr::new(second_addr, 993),
1103 ];
1104 let cache = vec![SocketAddr::new(second_addr, 993)];
1105 assert_eq!(
1106 merge_with_cache(resolved_addrs, cache),
1107 vec![
1108 SocketAddr::new(first_addr, 993),
1109 SocketAddr::new(second_addr, 993),
1110 ]
1111 );
1112 }
1113
1114 {
1118 let resolved_addrs = vec![
1119 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 993),
1120 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1121 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1122 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1123 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1124 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1125 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1126 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1127 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1128 ];
1129 let cache = vec![SocketAddr::new(second_addr, 993)];
1130 assert_eq!(
1131 merge_with_cache(resolved_addrs, cache),
1132 vec![
1133 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 993),
1134 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1135 SocketAddr::new(second_addr, 993),
1136 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1137 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1138 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1139 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1140 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1141 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1142 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1143 ]
1144 );
1145 }
1146
1147 {
1152 let resolved_addrs = vec![
1153 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 993),
1154 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1155 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1156 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1157 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1158 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1159 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1160 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1161 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1162 ];
1163 let cache = vec![
1164 SocketAddr::new(second_addr, 993),
1165 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1166 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1167 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1168 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1169 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1170 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1171 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1172 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1173 ];
1174 assert_eq!(
1175 merge_with_cache(resolved_addrs, cache),
1176 vec![
1177 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 993),
1178 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 2)), 993),
1179 SocketAddr::new(second_addr, 993),
1180 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 9)), 993),
1181 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 8)), 993),
1182 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 7)), 993),
1183 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 6)), 993),
1184 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 5)), 993),
1185 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 4)), 993),
1186 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3)), 993),
1187 ]
1188 );
1189 }
1190 }
1191}