Skip to content

Commit bb68e1f

Browse files
committed
fix(decode): catch possible errors thrown by decode function
1 parent beddfbf commit bb68e1f

File tree

5 files changed

+107
-80
lines changed

5 files changed

+107
-80
lines changed

src/Channel.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,12 @@ export class Channel {
8383
})
8484
)
8585
this.wsOrDc.onmessage = ({ data }: { data: ArrayBuffer }) => {
86-
this.handleInitMessage(proto.Message.decode(new Uint8Array(data)))
86+
try {
87+
const msg = proto.Message.decode(new Uint8Array(data))
88+
this.handleInitMessage(msg)
89+
} catch (err) {
90+
log.warn('Decode inner Channel message error: ', err)
91+
}
8792
}
8893
}
8994
}
@@ -188,27 +193,32 @@ export class Channel {
188193
private initHandlers() {
189194
// Configure handlers
190195
this.wsOrDc.onmessage = ({ data }: { data: ArrayBuffer }) => {
191-
const msg = Message.decode(new Uint8Array(data))
192-
193-
// 0: broadcast message
194-
if (msg.recipientId === 0 || msg.recipientId === this.wc.myId) {
195-
// User Message
196-
if (msg.serviceId === UserMessage.SERVICE_ID) {
197-
const userData = this.wc.userMsg.decodeUserMessage(msg.content, msg.senderId)
198-
if (userData) {
199-
this.wc.onMessage(msg.senderId as number, userData)
196+
try {
197+
const msg = Message.decode(new Uint8Array(data))
198+
199+
// 0: broadcast message or a message to me
200+
if (msg.recipientId === 0 || msg.recipientId === this.wc.myId) {
201+
// User Message
202+
if (msg.serviceId === UserMessage.SERVICE_ID) {
203+
const userData = this.wc.userMsg.decodeUserMessage(msg.content, msg.senderId)
204+
if (userData) {
205+
this.wc.onMessage(msg.senderId as number, userData)
206+
}
207+
208+
// Heartbeat message
209+
} else if (msg.serviceId === 0) {
210+
this.missedHeartbeat = 0
211+
212+
// Service Message
213+
} else {
214+
this.wc.streamSubject.next(Object.assign({ channel: this }, msg))
200215
}
201-
202-
// Heartbeat message
203-
} else if (msg.serviceId === 0) {
204-
this.missedHeartbeat = 0
205-
// Service Message
206-
} else {
207-
this.wc.streamSubject.next(Object.assign({ channel: this }, msg))
208216
}
209-
}
210-
if (msg.recipientId !== this.wc.myId) {
211-
this.wc.topology.forward(msg)
217+
if (msg.recipientId !== this.wc.myId) {
218+
this.wc.topology.forward(msg)
219+
}
220+
} catch (err) {
221+
log.warn('Decode general Channel message error: ', err)
212222
}
213223
}
214224
this.wsOrDc.onclose = (evt: Event) => {

src/Signaling.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -141,26 +141,30 @@ export class Signaling implements IStream<OutSigMsg, InSigMsg> {
141141
}
142142

143143
private handleMessage(bytes: ArrayBuffer) {
144-
const msg = proto.Message.decode(new Uint8Array(bytes))
145-
switch (msg.type) {
146-
case 'heartbeat':
147-
this.missedHeartbeat = 0
148-
break
149-
case 'connected':
150-
this.connected = msg.connected
151-
this.setState(SignalingState.CHECKED)
152-
if (!msg.connected) {
153-
this.wc.channelBuilder.connectOverSignaling().catch(() => this.check())
144+
try {
145+
const msg = proto.Message.decode(new Uint8Array(bytes))
146+
switch (msg.type) {
147+
case 'heartbeat':
148+
this.missedHeartbeat = 0
149+
break
150+
case 'connected':
151+
this.connected = msg.connected
152+
this.setState(SignalingState.CHECKED)
153+
if (!msg.connected) {
154+
this.wc.channelBuilder.connectOverSignaling().catch(() => this.check())
155+
}
156+
break
157+
case 'content': {
158+
const { data, id } = msg.content as proto.Content
159+
const streamMessage = Message.decode(data)
160+
streamMessage.senderId = id
161+
log.signaling('StreamMessage RECEIVED: ', streamMessage)
162+
this.streamSubject.next(streamMessage)
163+
break
154164
}
155-
break
156-
case 'content': {
157-
const { data, id } = msg.content as proto.Content
158-
const streamMessage = Message.decode(data)
159-
streamMessage.senderId = id
160-
log.signaling('StreamMessage RECEIVED: ', streamMessage)
161-
this.streamSubject.next(streamMessage)
162-
break
163165
}
166+
} catch (err) {
167+
log.warn('Decode Signaling message error: ', err)
164168
}
165169
}
166170

src/service/Service.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ export abstract class Service<OutMsg, InMsg extends OutMsg> {
6969
senderId,
7070
recipientId,
7171
msg: this.decode(content),
72-
}))
72+
})),
73+
filter(({ msg }: any) => msg && msg.type)
7374
),
7475
send: (content: Uint8Array | OutMsg, id?: number) => {
7576
wc.sendOverStream({
@@ -87,7 +88,8 @@ export abstract class Service<OutMsg, InMsg extends OutMsg> {
8788
id: sig.STREAM_ID,
8889
message: sig.messageFromStream.pipe(
8990
filter(({ serviceId }) => serviceId === this.serviceId),
90-
map(({ senderId, content }) => ({ senderId, msg: this.decode(content) }))
91+
map(({ senderId, content }) => ({ senderId, msg: this.decode(content) })),
92+
filter(({ msg }: any) => msg && msg.type)
9193
),
9294
send: (content: Uint8Array | OutMsg, id?: number) => {
9395
sig.sendOverStream({

src/service/UserMessage.ts

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { env } from '../misc/env'
2+
import { log } from '../misc/util'
23
import { userMessage as proto } from '../proto'
34
import { Service } from '../service/Service'
45

@@ -65,45 +66,50 @@ export class UserMessage extends Service<proto.IMessage, proto.Message> {
6566
* Decode user message received from the network.
6667
*/
6768
decodeUserMessage(bytes: Uint8Array, senderId: number): UserDataType | undefined {
68-
const { length, type, contentType, full, chunk } = super.decode(bytes) as {
69-
length: number
70-
type: proto.Message.Type
71-
contentType: string
72-
full: Uint8Array | undefined
73-
chunk: proto.Message.Chunk
74-
}
75-
let result
76-
switch (contentType) {
77-
case 'full': {
78-
result = full
79-
break
69+
try {
70+
const { length, type, contentType, full, chunk } = super.decode(bytes) as {
71+
length: number
72+
type: proto.Message.Type
73+
contentType: string
74+
full: Uint8Array | undefined
75+
chunk: proto.Message.Chunk
8076
}
81-
case 'chunk': {
82-
let buffer = this.getBuffer(senderId, chunk.id)
83-
if (buffer === undefined) {
84-
buffer = new Buffer(length, chunk.content, chunk.nb)
85-
this.setBuffer(senderId, chunk.id, buffer)
86-
result = undefined
87-
} else {
88-
result = buffer.append(chunk.content, chunk.nb)
77+
let result
78+
switch (contentType) {
79+
case 'full': {
80+
result = full
81+
break
82+
}
83+
case 'chunk': {
84+
let buffer = this.getBuffer(senderId, chunk.id)
85+
if (buffer === undefined) {
86+
buffer = new Buffer(length, chunk.content, chunk.nb)
87+
this.setBuffer(senderId, chunk.id, buffer)
88+
result = undefined
89+
} else {
90+
result = buffer.append(chunk.content, chunk.nb)
91+
}
92+
break
93+
}
94+
default: {
95+
throw new Error('Unknown message integrity')
8996
}
90-
break
91-
}
92-
default: {
93-
throw new Error('Unknown message integrity')
9497
}
95-
}
96-
if (result !== undefined) {
97-
switch (type) {
98-
case proto.Message.Type.U_INT_8_ARRAY:
99-
return result
100-
case proto.Message.Type.STRING:
101-
return textDecoder.decode(result)
102-
default:
103-
throw new Error('Unknown message type')
98+
if (result !== undefined) {
99+
switch (type) {
100+
case proto.Message.Type.U_INT_8_ARRAY:
101+
return result
102+
case proto.Message.Type.STRING:
103+
return textDecoder.decode(result)
104+
default:
105+
throw new Error('Unknown message type')
106+
}
104107
}
108+
return result
109+
} catch (err) {
110+
log.warn('Decode user message error: ', err)
111+
return undefined
105112
}
106-
return result
107113
}
108114

109115
/**

src/service/topology/FullMesh.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,17 @@ export class FullMesh extends Topology<proto.IMessage, proto.Message> implements
6060

6161
// Set onConnectionRequest callback for ChannelBuilder
6262
this.wc.channelBuilder.onConnectionRequest = (streamId: number, data: Uint8Array) => {
63-
const { id, adjacentIds } = proto.ConnectionRequest.decode(data)
64-
if (streamId === this.wc.STREAM_ID) {
65-
log.topology(`CONNECTION REQUEST from ${id}, where adjacent members are: `, adjacentIds)
66-
return this.createOrUpdateDistantMember(id, adjacentIds)
67-
} else {
68-
return true
63+
try {
64+
const { id, adjacentIds } = proto.ConnectionRequest.decode(data)
65+
if (streamId === this.wc.STREAM_ID) {
66+
log.topology(`CONNECTION REQUEST from ${id}, where adjacent members are: `, adjacentIds)
67+
return this.createOrUpdateDistantMember(id, adjacentIds)
68+
} else {
69+
return true
70+
}
71+
} catch (err) {
72+
log.warn('Decode Fullmesh onConnectionRequest message error: ', err)
73+
return false
6974
}
7075
}
7176

0 commit comments

Comments
 (0)