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