I am using mesh architecture for webRTC app for multi-user,the video chat works fine for multi-user, for text chat i created a dataChannel on the peer who creates offer and the onDataChannel handler creates a dataChannel on the other peer. The text chat works for 2 users but when there are 3 users, the 1st client (to join) is able to see all other clients messages but can send message to only 2nd client (to join), the 2nd client (to join) is able to see message from 1st client and send to only 1st client, 3rd client receives message from none but can send to 1st client.
the onDataChannel event handler in PeerConnection.Observer
@Override
public void onDataChannel(DataChannel dataChannel) {
Log.d("DataChannel", "onDataChannel" + " , state: " + dataChannel.state());
DataChannel.Observer dcObserver = new DcObserver(){
@Override
public void onStateChange() {
Log.d(TAG, "onStateChange: remote data channel state: " + dChannel.state().toString());
}
@Override
public void onMessage(DataChannel.Buffer buffer) {
Log.d(TAG, "onMessage: got message");
readMessage(buffer.data);
}
};
dataChannel.registerObserver(dcObserver);
dataChannels.add(dataChannel);
dcObservers.add(dcObserver);
}
});
Creating DataChannel while creating peerConnections
@Override
public void onNewPeerJoined(String socketId, boolean createOffer) {
showToast("Remote Peer Joined");
PeerConnection peerConnection = getOrCreatePeerConnection(socketId);
if (createOffer) {
dChannel = peerConnection.createDataChannel("DataChannel",new DataChannel.Init());
DataChannel.Observer dcObserver = new DcObserver(){
@Override
public void onStateChange() {
Log.d(TAG, "onStateChange: remote data channel state: " + dChannel.state().toString());
}
@Override
public void onMessage(DataChannel.Buffer buffer) {
Log.d(TAG, "onMessage: got message");
readMessage(buffer.data);
}
};
dChannel.registerObserver(dcObserver);
dcObservers.add(dcObserver);
dataChannels.add(dChannel);
sdpConstraints = new MediaConstraints();
sdpConstraints.mandatory.add(
new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
sdpConstraints.mandatory.add(
new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
//sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
peerConnection.createOffer(new CustomSdpObserver("localCreateOffer") {
@Override
public void onCreateSuccess(SessionDescription sessionDescription) {
super.onCreateSuccess(sessionDescription);
peerConnection.setLocalDescription(new CustomSdpObserver("localSetLocalDesc"), sessionDescription);
Log.d("onCreateSuccess", "SignallingClient emit ");
SignallingClient.getInstance(roomName).emitSessionDescription(sessionDescription, socketId);
}
}, sdpConstraints);
}
}
Sending messages
public void sendMessage() {
String message = editText.getText().toString();
if (message.isEmpty()) {
return;
}
editText.setText("");
textView.append(HtmlCompat.fromHtml("<b>" + userName + "</b>",HtmlCompat.FROM_HTML_MODE_LEGACY));
textView.append(": " + message + "\n");
String str = "<b>" + userName + "</b> : " + message;
ByteBuffer data = stringToByteBuffer("-s" + str, Charset.defaultCharset());
for (int i = 0; i < dataChannels.size(); i++){
Log.d("info","send_data dataChannel" + i);
dataChannels.get(i).send(new DataChannel.Buffer(data, false));
}
}