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