@@ -28,8 +28,8 @@ pub type ClientSessionResult = Result<ClientSession, Box<dyn Error + Send + Sync
28
28
29
29
impl ClientSession {
30
30
pub async fn new ( server_address : String ) -> ClientSessionResult {
31
- match tokio:: time:: timeout ( globals:: CONNECTION_TIMEOUT_DURATION , async {
32
- let client_socket = UdpSocket :: bind ( "127 .0.0.1 :0" ) . await ?;
31
+ match tokio:: time:: timeout ( globals:: CONNECTION_TIMEOUT_SEC , async {
32
+ let client_socket = UdpSocket :: bind ( "0 .0.0.0 :0" ) . await ?;
33
33
let client_socket = Arc :: new ( client_socket) ;
34
34
35
35
let session_player = join_server ( & client_socket, & server_address) . await ?;
@@ -58,7 +58,7 @@ impl ClientSession {
58
58
Ok ( client_session) => client_session,
59
59
Err ( _) => Err ( format ! (
60
60
"Connection timed out after {} seconds." ,
61
- globals:: CONNECTION_TIMEOUT_DURATION . as_secs( )
61
+ globals:: CONNECTION_TIMEOUT_SEC . as_secs( )
62
62
)
63
63
. into ( ) ) ,
64
64
}
@@ -68,7 +68,7 @@ impl ClientSession {
68
68
self . session_player
69
69
}
70
70
71
- pub fn receive_server_resposne ( & mut self ) -> Result < String , TryRecvError > {
71
+ pub fn receive_server_response ( & mut self ) -> Result < String , TryRecvError > {
72
72
match self . listen_rx . try_recv ( ) {
73
73
Ok ( response) => {
74
74
if let Ok ( Message :: Ping ) = Message :: deserialize ( & response) {
@@ -87,7 +87,7 @@ impl ClientSession {
87
87
}
88
88
89
89
pub fn is_server_alive ( & self ) -> bool {
90
- self . last_ping . elapsed ( ) < globals:: CONNECTION_TIMEOUT_DURATION
90
+ self . last_ping . elapsed ( ) < globals:: CONNECTION_TIMEOUT_SEC
91
91
}
92
92
93
93
pub fn leave_server ( & self , player_id : PlayerID ) {
@@ -108,33 +108,53 @@ async fn join_server(
108
108
client_socket : & UdpSocket ,
109
109
server_address : & String ,
110
110
) -> Result < Player , Box < dyn Error + Send + Sync > > {
111
- let msg = Message :: Handshake . serialize ( ) ;
112
- client_socket
113
- . send_to ( msg. as_bytes ( ) , server_address)
114
- . await ?;
115
- message:: trace ( format ! ( "Sent: {msg}" ) ) ;
116
-
117
- let mut ack_buf = [ 0u8 ; 32 ] ;
118
- let ( len, _) = client_socket. recv_from ( & mut ack_buf) . await ?;
119
- let response = String :: from_utf8_lossy ( & ack_buf[ ..len] ) . to_string ( ) ;
120
- message:: trace ( format ! ( "Handshake result: {response}" ) ) ;
121
-
122
- let result = match Message :: deserialize ( & response) {
123
- Ok ( Message :: Ack ( new_id, new_color) ) => Ok ( Player :: new ( new_id, new_color) ) ,
124
- Ok ( _) => Err ( "Invalid handshake received" . into ( ) ) ,
125
- Err ( e) => Err ( format ! ( "Handshake failed: {e}" ) . into ( ) ) ,
126
- } ;
127
- result
111
+ let handshake_msg = Message :: Handshake . serialize ( ) ;
112
+ // Loop abort happens on timeout in ClientSession::new()
113
+ loop {
114
+ client_socket
115
+ . send_to ( handshake_msg. as_bytes ( ) , server_address)
116
+ . await ?;
117
+ message:: trace ( format ! ( "Sent: {handshake_msg}" ) ) ;
118
+
119
+ match receive_with_retry_timeout ( client_socket) . await {
120
+ Ok ( response) => {
121
+ if let Ok ( Message :: Ack ( new_id, new_color) ) = Message :: deserialize ( & response) {
122
+ message:: trace ( format ! ( "Handshake result: {response}" ) ) ;
123
+ return Ok ( Player :: new ( new_id, new_color) ) ;
124
+ }
125
+
126
+ message:: trace ( format ! ( "Invalid handshake response: {response}" ) ) ;
127
+ }
128
+ _ => continue , // Keep trying, I know you can do it!
129
+ }
130
+ }
131
+ }
132
+
133
+ async fn receive_with_retry_timeout (
134
+ socket : & UdpSocket ,
135
+ ) -> Result < String , Box < dyn Error + Send + Sync > > {
136
+ let retry_timeout = std:: time:: Duration :: from_millis ( 300 ) ;
137
+ let mut buf = [ 0u8 ; 32 ] ;
138
+ match tokio:: time:: timeout ( retry_timeout, socket. recv_from ( & mut buf) ) . await {
139
+ Ok ( result) => {
140
+ let ( len, _) = result?;
141
+ Ok ( String :: from_utf8_lossy ( & buf[ ..len] ) . to_string ( ) )
142
+ }
143
+ Err ( _) => {
144
+ message:: trace ( "No response (sender or receiver package lost)" . to_string ( ) ) ;
145
+ Err ( "Receive operation timed out" . into ( ) )
146
+ }
147
+ }
128
148
}
129
149
130
- async fn listen_handler ( socket : Arc < UdpSocket > , tx : ChannelSender ) {
150
+ async fn listen_handler ( socket : Arc < UdpSocket > , listen_tx : ChannelSender ) {
131
151
let mut buf = [ 0u8 ; 1024 ] ;
132
152
loop {
133
153
match socket. recv_from ( & mut buf) . await {
134
154
Ok ( ( len, _) ) => {
135
155
if let Ok ( msg) = std:: str:: from_utf8 ( & buf[ ..len] ) {
136
156
// Pass message to main thread
137
- if tx . send ( msg. to_string ( ) ) . is_err ( ) {
157
+ if listen_tx . send ( msg. to_string ( ) ) . is_err ( ) {
138
158
break ;
139
159
}
140
160
}
0 commit comments