tiberius_rustls/sql_browser/
async_std.rs1use super::SqlBrowser;
2use async_std::{
3 io,
4 net::{self, ToSocketAddrs},
5};
6use async_trait::async_trait;
7use futures_util::future::TryFutureExt;
8use std::time;
9use tracing::Level;
10
11#[async_trait]
12impl SqlBrowser for net::TcpStream {
13 async fn connect_named(builder: &crate::client::Config) -> crate::Result<Self> {
17 let addrs = builder.get_addr().to_socket_addrs().await?;
18
19 for mut addr in addrs {
20 if let Some(ref instance_name) = builder.instance_name {
21 let local_bind: std::net::SocketAddr = if addr.is_ipv4() {
26 "0.0.0.0:0".parse().unwrap()
27 } else {
28 "[::]:0".parse().unwrap()
29 };
30
31 tracing::event!(
32 Level::TRACE,
33 "Connecting to instance `{}` using SQL Browser in port `{}`",
34 instance_name,
35 builder.get_port()
36 );
37
38 let msg = [&[4u8], instance_name.as_bytes()].concat();
39 let mut buf = vec![0u8; 4096];
40
41 let socket = net::UdpSocket::bind(&local_bind).await?;
42 socket.send_to(&msg, &addr).await?;
43
44 let timeout = time::Duration::from_millis(1000);
45
46 let len = io::timeout(timeout, socket.recv(&mut buf))
47 .map_err(|_| {
48 crate::error::Error::Conversion(
49 format!(
50 "SQL browser timeout during resolving instance {}. Please check if browser is running in port {} and does the instance exist.",
51 instance_name,
52 builder.get_port(),
53 )
54 .into(),
55 )
56 })
57 .await?;
58
59 let port = super::get_port_from_sql_browser_reply(buf, len, instance_name)?;
60 tracing::event!(Level::TRACE, "Found port `{}` from SQL Browser", port);
61 addr.set_port(port);
62 };
63
64 if let Ok(stream) = net::TcpStream::connect(addr).await {
65 stream.set_nodelay(true)?;
66 return Ok(stream);
67 }
68 }
69
70 Err(io::Error::new(io::ErrorKind::NotFound, "Could not resolve server host").into())
71 }
72}