1- use std:: { collections:: HashMap , str:: FromStr } ;
2-
3- use maybe_async:: maybe_async;
4-
51use crate :: {
62 Connection , Error , FileCreateArgs , Resource , Session , Tree ,
73 packets:: {
@@ -10,15 +6,19 @@ use crate::{
106 smb2:: Status ,
117 } ,
128 resource:: Pipe ,
9+ sync_helpers:: * ,
1310} ;
11+ use maybe_async:: maybe_async;
12+ use std:: sync:: Arc ;
13+ use std:: { collections:: HashMap , str:: FromStr } ;
1414
1515use super :: { config:: ClientConfig , unc_path:: UncPath } ;
1616
1717/// A High-level SMB client interface.
1818pub struct Client {
1919 config : ClientConfig ,
2020
21- connections : HashMap < UncPath , OpenedConnectionInfo > ,
21+ connections : Mutex < HashMap < UncPath , Arc < OpenedConnectionInfo > > > ,
2222}
2323
2424struct OpenedConnectionInfo {
@@ -33,13 +33,13 @@ impl Client {
3333 pub fn new ( config : ClientConfig ) -> Self {
3434 Client {
3535 config,
36- connections : HashMap :: new ( ) ,
36+ connections : Mutex :: new ( HashMap :: new ( ) ) ,
3737 }
3838 }
3939
4040 #[ maybe_async]
41- pub async fn close ( & mut self ) -> crate :: Result < ( ) > {
42- self . connections . clear ( ) ;
41+ pub async fn close ( & self ) -> crate :: Result < ( ) > {
42+ self . connections . lock ( ) . await ? . clear ( ) ;
4343 Ok ( ( ) )
4444 }
4545
@@ -67,7 +67,7 @@ impl Client {
6767
6868 #[ maybe_async]
6969 pub async fn share_connect (
70- & mut self ,
70+ & self ,
7171 unc : & UncPath ,
7272 user_name : & str ,
7373 password : String ,
@@ -80,7 +80,8 @@ impl Client {
8080
8181 let share_unc = unc. clone ( ) . with_no_path ( ) ;
8282
83- if self . connections . contains_key ( & share_unc) {
83+ let mut connections = self . connections . lock ( ) . await ?;
84+ if connections. contains_key ( & share_unc) {
8485 log:: warn!( "Connection already exists for this UNC path. Reusing it." ) ;
8586 return Ok ( ( ) ) ;
8687 }
@@ -102,14 +103,19 @@ impl Client {
102103 }
103104
104105 log:: debug!( "Connected to share {share_unc} with user {user_name}" ) ;
105- self . connections . insert ( share_unc, opened_conn_info) ;
106+ connections. insert ( share_unc, Arc :: new ( opened_conn_info) ) ;
106107
107108 Ok ( ( ) )
108109 }
109110
110- fn get_opened_conn_for_path ( & self , unc : & UncPath ) -> crate :: Result < & OpenedConnectionInfo > {
111- if let Some ( cst) = self . connections . get ( & unc. clone ( ) . with_no_path ( ) ) {
112- Ok ( cst)
111+ #[ maybe_async]
112+ async fn get_opened_conn_for_path (
113+ & self ,
114+ unc : & UncPath ,
115+ ) -> crate :: Result < Arc < OpenedConnectionInfo > > {
116+ let connections = self . connections . lock ( ) . await ?;
117+ if let Some ( cst) = connections. get ( & unc. clone ( ) . with_no_path ( ) ) {
118+ Ok ( cst. clone ( ) )
113119 } else {
114120 Err ( crate :: Error :: InvalidArgument ( format ! (
115121 "No connection found for {unc}. Use `share_connect` to create one." ,
@@ -123,7 +129,7 @@ impl Client {
123129 path : & UncPath ,
124130 args : & FileCreateArgs ,
125131 ) -> crate :: Result < Resource > {
126- let conn_info = self . get_opened_conn_for_path ( path) ?;
132+ let conn_info = self . get_opened_conn_for_path ( path) . await ?;
127133 conn_info
128134 . tree
129135 . create ( path. path . as_deref ( ) . unwrap_or ( "" ) , args)
@@ -132,7 +138,7 @@ impl Client {
132138
133139 #[ maybe_async]
134140 pub async fn create_file (
135- & mut self ,
141+ & self ,
136142 path : & UncPath ,
137143 args : & FileCreateArgs ,
138144 ) -> crate :: Result < Resource > {
@@ -173,10 +179,10 @@ impl Client {
173179 }
174180}
175181
176- struct DfsResolver < ' a > ( & ' a mut Client ) ;
182+ struct DfsResolver < ' a > ( & ' a Client ) ;
177183
178184impl < ' a > DfsResolver < ' a > {
179- fn new ( client : & ' a mut Client ) -> Self {
185+ fn new ( client : & ' a Client ) -> Self {
180186 DfsResolver ( client)
181187 }
182188
@@ -192,7 +198,8 @@ impl<'a> DfsResolver<'a> {
192198 // Re-use the same credentials for the DFS referral.
193199 let dfs_creds = self
194200 . 0
195- . get_opened_conn_for_path ( dfs_path) ?
201+ . get_opened_conn_for_path ( dfs_path)
202+ . await ?
196203 . creds
197204 . clone ( )
198205 . ok_or_else ( || {
@@ -232,14 +239,17 @@ impl<'a> DfsResolver<'a> {
232239 log:: debug!( "Resolving DFS referral for {unc}" ) ;
233240 let dfs_path_string = unc. to_string ( ) ;
234241
235- let dfs_root = self . 0 . get_opened_conn_for_path ( unc) ?. tree . as_dfs_tree ( ) ?;
236-
237- let dfs_refs = dfs_root. dfs_get_referrals ( & dfs_path_string) . await ?;
242+ let dfs_refs = {
243+ let conn = & self . 0 . get_opened_conn_for_path ( unc) . await ?;
244+ let dfs_root = conn. tree . as_dfs_tree ( ) ?;
245+ dfs_root. dfs_get_referrals ( & dfs_path_string) . await ?
246+ } ;
238247 if !dfs_refs. referral_header_flags . storage_servers ( ) {
239248 return Err ( Error :: InvalidMessage (
240249 "DFS referral does not contain storage servers" . to_string ( ) ,
241250 ) ) ;
242251 }
252+
243253 let mut paths = vec ! [ ] ;
244254 // Resolve the DFS referral entries.
245255 for ( indx, curr_referral) in dfs_refs. referral_entries . iter ( ) . enumerate ( ) {
0 commit comments