Skip to content

Commit 1800eb0

Browse files
committed
Merge branch 'fix/duplicate-client-messages' into refactor/do-not-wait-for-update-call
2 parents c0cad5b + bb17f9f commit 1800eb0

File tree

4 files changed

+21
-23
lines changed

4 files changed

+21
-23
lines changed

.github/workflows/rust-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
run: cargo fmt -- --check
2525

2626
- name: Cargo clippy
27-
run: cargo clippy --all --all-features -- -Dwarnings
27+
run: cargo clippy --all-targets --all-features --workspace -- -Dwarnings
2828

2929
- name: Run unit tests
3030
run: ./scripts/unit_test.sh

src/gateway-state/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,6 @@ mod tests {
399399

400400
{
401401
let gateway_state = gateway_state.clone();
402-
let canister_id = canister_id.clone();
403402
thread::spawn(move || loop {
404403
gateway_state.remove_canister_if_empty(canister_id);
405404
});
@@ -461,7 +460,6 @@ mod tests {
461460

462461
{
463462
let gateway_state = gateway_state.clone();
464-
let canister_id = canister_id.clone();
465463
thread::spawn(move || {
466464
for i in 0.. {
467465
let client_key = ClientKey::new(Principal::anonymous(), i);
@@ -516,7 +514,6 @@ mod tests {
516514

517515
{
518516
let gateway_state = gateway_state.clone();
519-
let canister_id = canister_id.clone();
520517
thread::spawn(move || {
521518
for i in 0.. {
522519
let client_key = ClientKey::new(Principal::anonymous(), i);

src/ic-websocket-gateway/src/client_session.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,7 @@ impl<S: AsyncRead + AsyncWrite + Unpin> ClientSession<S> {
165165
&mut self,
166166
client_update: Result<Message, Error>,
167167
) -> Result<(), IcWsError> {
168-
// upon receiving an update while the session is Setup, check if it is due to
169-
// the client disconnecting without a closing handshake
168+
// upon receiving an update, check if the message is valid and is not a close message
170169
let ws_message = self.check_client_update(client_update)?;
171170
if ws_message.is_close() && !self.session_state.is_closed() {
172171
trace!("Client disconnected while in {} state", self.session_state);
@@ -179,7 +178,7 @@ impl<S: AsyncRead + AsyncWrite + Unpin> ClientSession<S> {
179178
// upon receiving a message while the session is Init, check if the message is valid
180179
// if not return an error, otherwise set the session state to Setup
181180
// if multiple messages are received while in Init state, 'handle_setup_transition' will
182-
// return an error as the client shall not send more than one message while in Init state
181+
// ignore them as the client shall not send more than one message while in Init state
183182
let setup_state = self.handle_setup_transition(ws_message).await?;
184183
self.session_state = setup_state;
185184
},
@@ -244,7 +243,7 @@ impl<S: AsyncRead + AsyncWrite + Unpin> ClientSession<S> {
244243
// this implies a bug in the WS Gateway
245244
error!("Received canister message while in Closed state");
246245
Err(IcWsError::IcWsProtocol(String::from(
247-
"Poller shall not be able tosend messages while the session is in Closed state",
246+
"Poller shall not be able to send messages while the session is in Closed state",
248247
)))
249248
},
250249
}
@@ -290,17 +289,14 @@ impl<S: AsyncRead + AsyncWrite + Unpin> ClientSession<S> {
290289
Ok((client_key, canister_id)) => {
291290
// replace the field with the canister_id received in the first envelope
292291
// this shall not be updated anymore
293-
// if canister_id is already set in the struct, we return an error as inspect_ic_ws_open_message shall only be called once
292+
// if canister_id is already set in the struct, we log a warning as inspect_ic_ws_open_message shall only be called once
294293
if self.canister_id.replace(canister_id).is_some()
295294
|| self.client_key.replace(client_key.clone()).is_some()
296295
{
297296
// if the canister_id or client_key field was already set,
298297
// it means that the client sent the WS open message twice,
299298
// which it shall not do
300-
// therefore, return an error
301-
return Err(IcWsError::IcWsProtocol(String::from(
302-
"canister_id or client_key field was set twice",
303-
)));
299+
warn!("canister_id or client_key field was set twice");
304300
}
305301
trace!("Validated WS open message");
306302

@@ -370,7 +366,7 @@ impl<S: AsyncRead + AsyncWrite + Unpin> ClientSession<S> {
370366
// relay the envelope to the IC
371367
self.relay_envelope_to_canister(serialized_envelope, canister_id);
372368

373-
// there is no need to relay the response back to the client as the response to a request to the /call enpoint is not certified by the canister
369+
// there is no need to relay the response back to the client as the response to a request to the /call endpoint is not certified by the canister
374370
// and therefore could be manufactured by the gateway
375371

376372
trace!("Relayed client message to canister");

src/ic-websocket-gateway/src/tests/canister_poller.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
// mockito::Server is behind a SYNC mutex so that only one test at the same time can access it
2+
// otherwise, as async tests are run on multiple threads, the mock response of one test might overwrite
3+
// the mock response of another, causing the test to fail
4+
// acquiring the mutex and the beginning of each test and dropping the guard only at the end,
5+
// ensures that only one test at the time can set the mock response
6+
// this enables running the tests without specifying each time "-- --test-threads=1"
7+
#[allow(clippy::await_holding_lock)]
18
#[cfg(test)]
29
mod test {
310
use candid::Principal;
@@ -86,14 +93,12 @@ mod test {
8693
}
8794

8895
lazy_static! {
89-
// mockito::Server is behind a SYNC mutex so that only one test at the same time can access it
90-
// otherwise, as async tests are run on multiple threads, the mock response of one test might overwrite
91-
// the mock response of another, causing the test to fail
92-
// acquiring the mutex and the beginning of each test and dropping the guard only at the end,
93-
// ensures that only one test at the time can set the mock response
94-
// this enables running the tests without specifying each time "-- --test-threads=1"
95-
static ref MOCK_SERVER: Arc<Mutex<mockito::Server>> =
96-
Arc::new(Mutex::new(mockito::Server::new_with_opts(mockito::ServerOpts { port: 51558, ..Default::default() })));
96+
static ref MOCK_SERVER: Arc<Mutex<mockito::Server>> = Arc::new(Mutex::new(
97+
mockito::Server::new_with_opts(mockito::ServerOpts {
98+
port: 51558,
99+
..Default::default()
100+
})
101+
));
97102
}
98103

99104
fn create_poller(
@@ -332,7 +337,7 @@ mod test {
332337
.mock("GET", path)
333338
.with_chunked_body(|w| {
334339
thread::sleep(Duration::from_millis(POLLING_TIMEOUT_MS + 10));
335-
w.write_all(&vec![])
340+
w.write_all(&[])
336341
})
337342
.expect(2)
338343
.create_async()

0 commit comments

Comments
 (0)