Open ibc opened 4 years ago
The data being sent via the SCTP stream is as follows:
data = '{"event":"bomberman-start-game","payload":{"id":"ibc@mycompany","mapName":"cold_map","layerInfo":{"name":"Blocks","width":28,"height":18,"x":0,"y":0,"data":[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,3,3,3,2,1,2,3,2,3,2,3,2,3,2,3,2,3,1,2,3,3,3,2,3,1,1,3,2,1,1,3,2,2,3,2,3,2,3,2,3,2,3,2,3,2,1,3,3,2,2,2,3,1,1,2,3,3,3,3,3,2,3,1,1,1,1,3,1,1,1,1,2,3,2,3,3,1,1,1,2,1,1,1,1,1,2,2,2,2,3,3,3,2,3,3,3,3,3,2,3,3,1,2,3,3,3,3,3,1,1,3,3,3,2,3,3,3,3,2,2,3,3,2,1,1,3,3,2,3,1,2,3,3,2,3,2,1,1,2,2,3,1,1,1,1,2,2,1,1,1,1,1,1,2,2,1,1,3,2,1,1,1,2,1,1,1,2,2,3,2,3,3,1,3,3,1,1,3,3,2,2,3,3,2,2,3,3,2,1,3,3,3,1,1,1,1,1,2,3,3,1,3,2,3,3,2,3,3,3,3,3,3,3,3,3,1,1,3,2,2,1,1,3,3,3,3,3,3,1,3,2,2,2,2,3,1,1,1,1,1,2,3,3,1,2,3,2,1,1,1,3,2,1,1,2,3,1,3,3,3,3,3,3,1,3,3,3,3,2,3,2,3,2,3,2,2,1,1,1,2,2,2,2,3,1,1,1,2,2,2,1,1,2,3,2,3,2,3,2,3,2,2,3,3,1,1,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,2,3,2,1,1,1,1,1,2,3,3,1,1,1,1,2,2,1,1,2,2,2,3,3,2,2,2,3,3,3,3,2,3,2,3,1,1,1,1,1,1,2,3,3,3,3,3,3,3,1,2,3,1,1,1,1,2,2,3,1,2,2,3,2,2,2,2,1,1,3,2,2,1,2,3,2,3,1,3,2,3,2,3,2,3,2,3,2,3,1,1,3,3,3,3,1,1,3,3,2,3,2,1,2,3,1,3,3,2,3,2,3,2,3,3,1,3,3,3,3,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],"opacity":1,"type":"tilelayer","visible":true,"properties":{"max_players":16,"collisionTiles":[1,2],"empty":3,"balk":2,"wall":1,"spawns":[{"col":6,"row":3},{"col":8,"row":14},{"col":20,"row":15},{"col":22,"row":1},{"col":5,"row":5},{"col":3,"row":12},{"col":26,"row":7},{"col":19,"row":4},{"col":13,"row":4},{"col":16,"row":13},{"col":18,"row":10},{"col":2,"row":5},{"col":8,"row":8},{"col":20,"row":8},{"col":5,"row":9},{"col":25,"row":11}]}},"players":{"ijqwgukkizuKNHS5AAAA":{"id":"ijqwgukkizuKNHS5AAAA","spawnGroup":0,"spawn":{"x":192,"y":96},"position":{"x":192,"y":96},"spawnOnGrid":{"col":6,"row":3},"name":"Iñaki","isAlive":true,"power":1}},"playerSpawnsGroups":[[{"col":8,"row":14},{"col":20,"row":15},{"col":22,"row":1}],[{"col":5,"row":5},{"col":3,"row":12},{"col":26,"row":7},{"col":19,"row":4}],[{"col":13,"row":4},{"col":16,"row":13},{"col":18,"row":10},{"col":2,"row":5}],[{"col":8,"row":8},{"col":20,"row":8},{"col":5,"row":9},{"col":25,"row":11}]],"shadowMap":[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,2,0,0,0,0,2,1,2,0,2,0,2,0,2,0,2,0,2,0,1,2,0,0,0,2,0,1],[1,0,2,1,1,0,2,2,0,2,0,2,0,2,0,2,0,2,0,2,1,0,0,2,2,2,0,1],[1,2,0,0,0,0,0,2,0,1,1,1,1,0,1,1,1,1,2,0,2,0,0,1,1,1,2,1],[1,1,1,1,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,1,2,0,0,0,0,0,1],[1,0,0,0,2,0,0,0,0,2,2,0,0,2,1,1,0,0,2,0,1,2,0,0,2,0,2,1],[1,2,2,0,1,1,1,1,2,2,1,1,1,1,1,1,2,2,1,1,0,2,1,1,1,2,1,1],[1,2,2,0,2,0,0,1,0,0,1,1,0,0,2,2,0,0,2,2,0,0,2,1,0,0,0,1],[1,1,1,1,2,0,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,1,1,0,2,2,1],[1,0,0,0,0,0,0,1,0,2,2,2,2,0,1,1,1,1,1,2,0,0,1,2,0,2,1,1],[1,0,2,1,1,2,0,1,0,0,0,0,0,0,1,0,0,0,0,2,0,2,0,2,0,2,2,1],[1,1,2,2,2,2,0,1,1,1,2,2,2,1,1,2,0,2,0,2,0,2,0,2,2,0,0,1],[1,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,2,0,2,1,1,1,1,1,2,0,0,1],[1,1,1,2,2,1,1,2,2,2,0,0,2,2,2,0,0,0,0,2,0,2,0,1,1,1,1,1],[1,2,0,0,0,0,0,0,0,1,2,0,1,1,1,1,2,2,0,1,2,2,0,2,2,2,2,1],[1,0,2,2,1,2,0,2,0,1,0,2,0,2,0,2,0,2,0,2,0,1,1,0,0,0,0,1],[1,0,0,2,0,2,1,2,0,1,0,0,2,0,2,0,2,0,0,1,0,0,0,0,2,2,2,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],"spoils":{},"bombs":{}}}'
...which is 3214 bytes long.
And I'm using it as follows:
const sctp = require('sctp');
const dgram = require('dgram');
// Set node-sctp default PMTU to 1200. <----- UPPS ?
sctp.defaults({ PMTU: 1200 });
const udpSocket = dgram.createSocket({ type: 'udp4' });
// Connect the udpSocket and so on
// [...]
const sctpSocket = sctp.connect({
localPort: 5000, // Required for SCTP over plain UDP in mediasoup.
port: 5000, // Required for SCTP over plain UDP in mediasoup.
OS: 128,
MIS: 128,
unordered: false,
udpTransport: udpSocket, // previously created
udpPeer: {
address: remoteUdpIp,
port: remoteUdpPort,
},
});
// Wait for the SCTP socket to be connected (SCTP association done)
// [...]
// Send data above
const buffer = Buffer.from(JSON.stringify(data));
// Set ppid of type WebRTC DataChannel string.
buffer.ppid = sctp.PPID.WEBRTC_STRING;
sctpStream.write(buffer);
BTW super confirmed that the error happens due the size of data
(3214 bytes). It does not happen with smaller data. It also happens if I remove the sctp.defaults({ PMTU: 1200 });
line.
Thanks for the snippet. I'll look into it.
NOTE: in order to install mediasoup you need this common requirements in your host. And then: npm install mediasoup@3
If one need to control message boundaries (so that they have same SSN), we again need to hijack Buffer object, though it can be done internally, I hope. Currently, socket API splits chunks at about RWND size before feeding into SCTP API. This was done quite ugly, and must be rewritten.
Proper buffering with highWaterMark should be done in sockets, and SCTP API should allow arbitrary buffer size in SEND()
Currently, socket API splits chunks at about RWND size before feeding into SCTP API. This was done quite ugly, and must be rewritten.
Yep, a message given to write()
must not be splitted into N SCTP messages because the remote application is supposed to receive a single "message" rather than 2 messages (that probably will be invalid).
Well, I've written a gist with a more complete test script and failing examples:
https://gist.github.com/ibc/17ed95cd2f08b84222c8820b034cd391
Made comment on gist. Please use new highWaterMark (bytes) value in sctp.connect() for larger buffers. Also pushed version 0.19 of sctp package, addressing multiple callbacks.
Let me know your thoughts.
I'm getting the following fatal error. I don't know yet when/why it happens (on it). However, it's a fatal error because it's an internal unhandled "error" event, so it terminates the Node process.
Note that I'm setting an "error" listener in the node-sctp
Socket
instance, so the problem is that such a "error" exception is not being caught internally.