@mediafish/rtmp-server
Version:
A server that receives an RTMP live stream and populates a readable object stream of the published audio, video, and data messages
131 lines (122 loc) • 3.92 kB
JavaScript
import {Buffer} from 'node:buffer';
import debug from 'debug';
import {reader, writer} from '@mediafish/buffer-operator';
import {writeProtocolMessage} from './chunk.js';
const print = debug('rtmp-server');
const MAX_MESSAGE_LENGTH = 0xFF_FF_FF;
const buff = Buffer.alloc(4);
const buff5 = Buffer.alloc(5);
const buff6 = Buffer.alloc(6);
function processMessage(connMgr, chunk) {
const {messageHeader, data} = chunk;
const {messageTypeId} = messageHeader;
let offset = 0, chunkSize = 0, chunkStreamId = 0, sequenceNumber = 0, windowSize = 0, limitType = 0;
switch (messageTypeId) {
case 1:
// Set Chunk Size
[offset, chunkSize] = reader.readNumber(data, offset, 4);
if (chunkSize > MAX_MESSAGE_LENGTH) {
chunkSize = MAX_MESSAGE_LENGTH;
}
connMgr.maxChunkSize = chunkSize;
print(`[Set Chunk Size] Recieved: ${chunkSize} bytes`);
break;
case 2:
// Abort Message
[offset, chunkStreamId] = reader.readNumber(data, 0, 4);
connMgr.abortMessage(chunkStreamId);
print(`[Abort Message] Recieved: chunkStreamId = ${chunkStreamId}`);
break;
case 3:
// Acknowledgement
[offset, sequenceNumber] = reader.readNumber(data, 0, 4);
print(`[Acknowledgement] Recieved: sequenceNumber = ${sequenceNumber}`);
break;
case 5:
// Window Acknowledgement Size
[offset, windowSize] = reader.readNumber(data, 0, 4);
connMgr.windowSize = windowSize;
print(`[Window Acknowledgement Size] Recieved: windowSize = ${windowSize}`);
break;
case 6:
// Set Peer Bandwidth
[offset, windowSize] = reader.readNumber(data, 0, 4);
[offset, limitType] = reader.readNumber(data, 0, 1);
// Ignore this message
print(`[Set Peer Bandwidth] Recieved: windowSize = ${windowSize}, limitType = ${limitType}`);
break;
default:
return new Error(`Unsupported messageTypeId: ${messageTypeId}`);
}
return null;
}
function setChunkSize(socket, chunkSize) {
writer.writeNumber(chunkSize, buff, 0, 4);
const msgHeader = {
timestamp: 0,
delta: 0,
messageLength: 4,
messageTypeId: 1,
messageStreamId: 0,
};
writeProtocolMessage(socket, msgHeader, buff);
print(`[Set Chunk Size] Sent: chunkSize = ${chunkSize}`);
}
function sendAck(socket, sequenceNumber) {
writer.writeNumber(sequenceNumber, buff, 0, 4);
const msgHeader = {
timestamp: 0,
delta: 0,
messageLength: 4,
messageTypeId: 3,
messageStreamId: 0,
};
writeProtocolMessage(socket, msgHeader, buff);
print(`[Acknowledgement] Sent: sequenceNumber = ${sequenceNumber}`);
}
function sendWindowAckSize(socket, windowSize) {
writer.writeNumber(windowSize, buff, 0, 4);
const msgHeader = {
timestamp: 0,
delta: 0,
messageLength: 4,
messageTypeId: 5,
messageStreamId: 0,
};
writeProtocolMessage(socket, msgHeader, buff);
print(`[Window Acknowledgement Size] Sent: windowSize = ${windowSize}`);
}
function setPeerBandWidth(socket, windowSize, limitType) {
writer.writeNumber(windowSize, buff5, 0, 4);
writer.writeNumber(limitType, buff5, 4, 1);
const msgHeader = {
timestamp: 0,
delta: 0,
messageLength: 5,
messageTypeId: 6,
messageStreamId: 0,
};
writeProtocolMessage(socket, msgHeader, buff5);
print(`[Set Peer Bandwidth] Sent: windowSize = ${windowSize}, limitType=${limitType}`);
}
function setUserControlMessage(socket, streamId) {
writer.writeNumber(0, buff6, 0, 2);
writer.writeNumber(streamId, buff6, 2, 4);
const msgHeader = {
timestamp: 0,
delta: 0,
messageLength: 6,
messageTypeId: 99,
messageStreamId: 0,
};
writeProtocolMessage(socket, msgHeader, buff6);
print(`[Set User Control Message] Sent: streamId = ${streamId}`);
}
export {
processMessage,
setChunkSize,
sendAck,
sendWindowAckSize,
setPeerBandWidth,
setUserControlMessage,
};