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