erizoController负责创建和管理房间,一个erizoController下会有多个房间,一个房间和一个roomController关联,
roomController 负责管理发布者、订阅者。
一、创建room逻辑
房间是通过erizoController下面的room.js来管理和创建的,具体代码: licode/erizo_controller/erizoController/models/Room.js
room.js中有两个类class rooms和class room,其中 rooms本地维护了一个map来管理room。
1、首先创建 rooms
//amqper对应amqper.js
//ecch 是EcCloudHandler
class Rooms extends events.EventEmitter {
constructor(amqper, ecch) {
super();
this.amqper = amqper;
this.ecch = ecch;
this.rooms = new Map();
}
2、创建room
erizoController.js中接收到客户端连接请求,请求中会带着房间id,erizoController会调用rooms中的getOrCreateRoom()创建房间,
具体逻辑如下:见:erizoController.js
const listen = () => {
io.sockets.on('connection', (socket) => {
log.info(`message: socket connected, socketId: ${socket.id}`);
//客户端的socket和Channel进行一对一绑定,后面可以基于该Channel和client通信
const channel = new Channel(socket, nuve);
channel.on('connected', (token, options, callback) => {
options = options || {};
try {//创建房间
const room = rooms.getOrCreateRoom(myId, token.room, token.p2p);
options.singlePC = getSinglePCConfig(options.singlePC);
//一个客户端相当于一个client,创建和该客户端关联的client
const client = room.createClient(channel, token, options);
log.info(`message: client connected, clientId: ${client.id}, ` +
`singlePC: ${options.singlePC}`);
if (!room.p2p && global.config.erizoController.report.session_events) {
const timeStamp = new Date();
//rpc消息队列通知ErizoJs 有用户加入
amqper.broadcast('event', { room: room.id,
user: client.id,
type: 'user_connection',
timestamp: timeStamp.getTime() });
}
const streamList = [];
room.streamManager.forEachPublishedStream((stream) => {
streamList.push(stream.getPublicStream());
});
//把房间内所有的流通知该用户
callback('success', { streams: streamList,
id: room.id,
clientId: client.id,
singlePC: options.singlePC,
p2p: room.p2p,
defaultVideoBW: global.config.erizoController.defaultVideoBW,
maxVideoBW: global.config.erizoController.maxVideoBW,
iceServers: global.config.erizoController.iceServers });
} catch (e) {
log.warn('message: error creating Room or Client, error:', e);
}
});
//客户端重连
channel.on('reconnected', (clientId) => {
rooms.forEachRoom((room) => {
const client = room.getClientById(clientId);
if (client !== undefined) {
client.setNewChannel(channel);
}
});
});
socket.channel = channel;
});
};
房间创建的函数getOrCreateRoom()
//判断房间是否存在,不存在就创建一个房间
//如果存在就返回房间
getOrCreateRoom(erizoControllerId, id, p2p) {
let room = this.rooms.get(id);
if (room === undefined) {
room = new Room(erizoControllerId, this.amqper, this.ecch, id, p2p);
this.rooms.set(room.id, room);
room.on('room-empty', this.deleteRoom.bind(this, id));
this.emit('updated');
}
return room;
}
二、创建RoomController
当创建的房间不是p2p模式时,创建RoomController,即SFU房间。RoomController这个类非常重要,发布与订阅者信息就是通过这个类进行管理的。
代码在room.js的构造函数中
class Room extends events.EventEmitter {
constructor(erizoControllerId, amqper, ecch, id, p2p) {
super();
this.streamManager = new StreamManager();
this.clients = new Map();
this.id = id;
this.erizoControllerId = erizoControllerId;
this.p2p = p2p;
this.amqper = amqper;
this.ecch = ecch;
if (!p2p) {//此处,如果不是p2p模式,就创建RoomController
this.setupRoomController();
}
}
setupRoomController() {
this.controller = controller.RoomController({
amqper: this.amqper,
ecch: this.ecch,
erizoControllerId: this.erizoControllerId,
streamManager: this.streamManager,
});
this.controller.addEventListener(this.onRoomControllerEvent.bind(this));
}
RoomController功能比较多,后面的 文章会再仔细分析。