pub async fn associate<P>(&mut self, proxy: P) -> Result<(), Error>
    where
        P: ToSocketAddrs,
    {
        if self.assoc_client.is_some() {
            let err = io::Error::other("udp is associated");
            return Err(err.into());
        }

        // The actual bind address, tell the proxy that I am going to send packets from this address
        let local_addr = self.socket.local_addr()?;

        let (assoc_client, proxy_addr) = Socks5TcpClient::udp_associate(local_addr, proxy).await?;
        match proxy_addr {
            Address::SocketAddress(sa) => self.socket.connect(sa).await?,
            // FIXME: `connect` will use tokio's builtin DNS resolver.
            // But if we want to use `hickory-dns`, we have to initialize a `Context` instance (for the global `AsyncResolver` instance)
            Address::DomainNameAddress(ref dname, port) => self.socket.connect((dname.as_str(), port)).await?,
        }

        self.assoc_client = Some(assoc_client);

        Ok(())
    }
Create a new UDP associate to `proxy`
crates/shadowsocks-service/src/local/socks/client/socks5/udp_client.rs