import 'dart:async'; import 'dart:convert'; import 'package:the_paint/src/generated/client.pbgrpc.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; class WebRTCChannels { bool _inCalling = false; RTCPeerConnection? _pc; RTCDataChannel? _dc; PaintClient? _grpcClient; WebRTCChannels(); final Map _iceServers = { 'iceServers': [ { 'url': 'stun:melvans.com:3478', 'username': 'b84e4232f84505e3c3967184df374f2cdaa954f1', 'credential': 'afc39ae0591c132292f73a87f6f3725311fbafa0' // 'url': 'stun:stun.l.google.com:19302' }, ] }; final Map _config = { 'mandatory': {}, 'optional': [ {'DtlsSrtpKeyAgreement': true}, ], }; final Map _constraints = { 'mandatory': {}, 'optional': [], }; final _channel = WebSocketChannel.connect( Uri.parse('ws://localhost:8081/ws'), ); Future connect(Function callback) async { print("Connecting WEBSOCKET..."); _pc = await createPeerConnection( _iceServers, ); _pc!.onIceCandidate = (candidate) async { print('pc2: onIceCandidate: ${candidate.candidate}'); await sendCandidate(candidate); }; _pc!.onDataChannel = (channel) { RTCDataChannel dc = channel; print('\nnew channel'); dc.onDataChannelState = (state) { print('\ndc2: change state: ${state.toString()}'); }; dc.onMessage = (data) { callback(MonitorReply.fromBuffer(data.binary)); // dc.send( // RTCDataChannelMessage('(dc2 ==> dc1) Hello from dc2 echo !!!')); }; }; final rtcData = _channel.stream.map((event) => RTCData.fromBuffer(event)); await for (var msg in rtcData) { print(msg.event); switch (msg.event) { case "offer": await _pc! .setRemoteDescription(RTCSessionDescription(msg.data, msg.event)); var answer = await _pc!.createAnswer(); await _pc!.setLocalDescription(answer); await sendLocalDescription(); break; default: print("invalid event"); } } } sendLocalDescription() async { RTCSessionDescription? answer = await _pc!.getLocalDescription(); if (answer == null) { return; } final encodedData = RTCData(data: answer.sdp, event: answer.type).writeToBuffer(); _channel.sink.add(encodedData); } sendCandidate(RTCIceCandidate candidate) async { final encodedData = RTCData(data: jsonEncode(candidate.toMap()), event: "candidate") .writeToBuffer(); _channel.sink.add(encodedData); } }