Skip to content
This repository was archived by the owner on Oct 23, 2024. It is now read-only.

Commit b506ad4

Browse files
authored
Save socket.io missing messages during reconnection (#937)
* Save socket.io missing messages during reconnection * Change protocol version for compatibility * Add more description in documents
1 parent 00f08f4 commit b506ad4

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed

doc/Client-Portal Protocol.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
|28-06-2017 |Xiande|1.0 reviewed|
77
|08-04-2018 |Tianfang|1.0 final|
88
|08-09-2019 |ChenLi|1.1 reviewed|
9+
|03-10-2021 |ChenLi|1.2 reviewed|
910
-->
1011
# 1. Overview
1112
This documentation covers all signaling messages between Client and MCU component through Socket.io connections.
@@ -90,7 +91,21 @@ This a format for client reconnects.
9091

9192
**RequestName**: "relogin"<br>
9293

93-
**RequestData**: The ReconnectionTicket object defined in 3.3.1 section.<br>
94+
**RequestData**: The ReconnectionTicket object defined in 3.3.1 section and PendingMessages:
95+
96+
```
97+
object(ReloginResponse)::
98+
{
99+
ticket: string(Base64Encoded(object(ReconnectionTicket)))
100+
messages: [
101+
{
102+
event: string(NotificationName),
103+
data: object(NotificationData),
104+
seq: number(InternalSeqNo) // Back to 0 if exceed max value 2147483647
105+
}
106+
]
107+
}
108+
```
94109

95110
**ResponseData**: A refreshed base64-encoded ReconnectionTicket object if ResponseStatus is "ok".
96111
## 3.3 Conferencing

doc/design/pics/relogin1.png

186 KB
Loading

doc/design/pics/relogin2.png

158 KB
Loading

doc/design/relogin-message.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Server and client both maintain an **internal sequence number** for
2+
sent/received messages once a connection established.
3+
4+
For Server:
5+
6+
1. After a client has logged in, allocate a sequence number with
7+
initial value 0 for this connection.
8+
9+
2. Once a message is sent (no matter success or not), bind the message
10+
with current sequence number and time, save them in a buffer.
11+
Increase the current sequence number by 1. Discard the old messages after
12+
a certain period if necessary.
13+
14+
3. Once client “relogin”, sent those messages with sequence number in
15+
buffer in response.
16+
17+
For Client:
18+
19+
1. After login succeed, allocate a sequence number with initial
20+
value 0.
21+
22+
2. Once a message is received, increase the current sequence number
23+
by 1.
24+
25+
3. Once client “relogin” succeed, filter messages with sequence
26+
number &gt;= client sequence number, process those messages in
27+
order. Update its own current sequence number.
28+
29+

source/portal/socketIOServer.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ var Connection = function(spec, socket, reconnectionKey, portal, dock) {
4141
var client_id;
4242
var protocol_version;
4343
var waiting_for_reconnecting_timer = null;
44+
// [{ event, data, seq, time }]
45+
// Use queue instead of array if its size is very large
46+
var message_seq = 0;
47+
var message_buffer = [];
48+
var message_keep_time = spec.pingInterval + spec.pingTimeout + 1;
4449
var pending_messages = [];
4550

4651
let reconnection = {
@@ -225,14 +230,24 @@ var Connection = function(spec, socket, reconnectionKey, portal, dock) {
225230
client_id = connectionInfo.clientId + '';
226231
protocol_version = connectionInfo.protocolVersion + '';
227232
pending_messages = connectionInfo.pendingMessages;
233+
message_seq = connectionInfo.messageSeq;
234+
message_buffer = connectionInfo.messageBuffer;
228235
reconnection.enabled = true;
229236
return client.resetConnection(that);
230237
}
231238
}).then(() => {
232239
let ticket = generateReconnectionTicket();
240+
let messages = message_buffer.map(msg => {
241+
delete msg.time;
242+
return msg;
243+
});
233244
state = 'connected';
234-
safeCall(callback, okWord(), ticket);
235-
drainPendingMessages();
245+
if (protocol_version === '1.2') {
246+
safeCall(callback, okWord(), {ticket, messages});
247+
} else {
248+
safeCall(callback, okWord(), ticket);
249+
drainPendingMessages();
250+
}
236251
}).catch((err) => {
237252
state = 'initialized';
238253
const err_message = getErrorMessage(err);
@@ -298,6 +313,8 @@ var Connection = function(spec, socket, reconnectionKey, portal, dock) {
298313

299314
return {
300315
pendingMessages: pending_messages,
316+
messageSeq: message_seq,
317+
messageBuffer: message_buffer,
301318
clientId: client_id,
302319
protocolVersion: protocol_version,
303320
reconnection: reconnection
@@ -315,6 +332,16 @@ var Connection = function(spec, socket, reconnectionKey, portal, dock) {
315332
} else {
316333
pending_messages.push({event: event, data: data});
317334
}
335+
let currentTime = process.hrtime()[0];
336+
message_seq++;
337+
message_buffer.push({event, data, seq: message_seq, time: currentTime});
338+
while (message_buffer[0]) {
339+
if (currentTime - message_buffer[0].time > message_keep_time) {
340+
message_buffer.shift();
341+
} else {
342+
break;
343+
}
344+
}
318345
};
319346

320347
that.close = (ifLeave) => {

0 commit comments

Comments
 (0)