You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
doctor_app_flutter/lib/screens/live_care/web-rtc/signaling.dart

232 lines
7.3 KiB
Dart

import 'dart:convert';
import 'package:doctor_app_flutter/util/SignalRUtil.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
const PATIENT_PUSH_TOKEN = "eUA6FUiOTbSellej2JQ8yg:APA91bFuDledDvwbeZJ8KU8drHQ7kse7h9UjKPaBZsQgKi-0GCSPRB_yIO9O3PXysWLnLMJYwVmEJWd-jPIqbrLz_Z_yzE--3mC-GZJj92BT0nSzAVd-JVr28pUtejgSjTpZryNFlSn5";
typedef void StreamStateCallback(MediaStream stream);
typedef void RTCIceGatheringStateCallback(RTCIceGatheringState state);
typedef void RTCPeerConnectionStateCallback(RTCPeerConnectionState state);
typedef void RTCSignalingStateCallback(RTCSignalingState state);
Map<String, dynamic> snapsis_ice_config = {
'iceServers': [
{ "urls": 'stun:15.185.116.59:3478' },
{ "urls": "turn:15.185.116.59:3479", "username": "admin", "credential": "admin" },
],
// 'sdpSemantics': 'unified-plan'
};
Map<String, dynamic> twilio_ice_config = {
"ice_servers": [
{
"url": "stun:global.stun.twilio.com:3478?transport=udp",
"urls": "stun:global.stun.twilio.com:3478?transport=udp"
},
{
"url": "turn:global.turn.twilio.com:3478?transport=udp",
"username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
"urls": "turn:global.turn.twilio.com:3478?transport=udp",
"credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
},
{
"url": "turn:global.turn.twilio.com:3478?transport=tcp",
"username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
"urls": "turn:global.turn.twilio.com:3478?transport=tcp",
"credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
},
{
"url": "turn:global.turn.twilio.com:443?transport=tcp",
"username": "ce8042842b62c21bd20b176f80d6067fd3db81b1e9766312418ef5421d9ca2a2",
"urls": "turn:global.turn.twilio.com:443?transport=tcp",
"credential": "UzGOsiLwPZJ32cjafAebfDDpVrqeQjgpFHZEdau/8r4="
}
],
// 'sdpSemantics': 'unified-plan'
};
Map<String, dynamic> google_ice_config = {
'iceServers': [
{
'urls': [
'stun:stun.l.google.com:19302',
'stun:stun1.l.google.com:19302',
'stun:stun2.l.google.com:19302',
'stun:stun3.l.google.com:19302'
]
},
],
// 'sdpSemantics': 'unified-plan'
};
Map<String, dynamic> aws_ice_config = {
'iceServers': [
{'url': "stun:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3478"},
{'url': "turn:ec2-15-185-116-59.me-south-1.compute.amazonaws.com:3479", 'credential': "admin", 'username': "admin"}
],
// 'sdpSemantics': 'unified-plan'
};
final Map<String, dynamic> _peer_config = {
'mandatory': {},
'optional': [
{'DtlsSrtpKeyAgreement': true},
]
};
class Signaling {
dispose(){
if(peerConnection != null)
peerConnection.dispose();
signalR?.closeConnection();
}
init(){
// Create Peer Connection
createPeerConnection(google_ice_config,_peer_config).then((value){
peerConnection = value;
registerPeerConnectionListeners();
});
}
initializeSignalR(String userName) async{
if(signalR != null)
await signalR?.closeConnection();
// https://vcallapi.hmg.com/webRTCHub?source=web&username=zohaib
signalR = SignalRUtil(hubName: "https://vcallapi.hmg.com/webRTCHub?source=mobile&username=$userName");
final connected = await signalR?.openConnection();
if(connected != null && !connected)
throw 'Failed to connect SignalR';
}
SignalRUtil? signalR;
late RTCPeerConnection peerConnection;
MediaStream? localStream;
MediaStream? remoteStream;
RTCDataChannel? dataChannel;
Future<bool> acceptCall(String caller, String receiver, {required MediaStream localMediaStream, required Function(MediaStream) onRemoteMediaStream}) async{
await initializeSignalR(caller);
signalR?.setContributors(caller: caller, receiver: receiver);
await signalR?.acceptCall(receiver, caller).catchError((e) => throw 'Failed to inform signalR that i accepted a call');
peerConnection.addStream(localMediaStream);
peerConnection.onAddStream = (MediaStream stream) {
remoteStream = stream;
onRemoteMediaStream.call(stream);
};
return true;
}
Future<bool> initiateCall(String caller, String receiver, {required MediaStream localMediaStream, required Function(MediaStream) onRemoteMediaStream}) async{
await initializeSignalR(caller);
signalR?.setContributors(caller: caller, receiver: receiver);
await signalR?.callUserMobile(caller, receiver).catchError((e) => throw 'Failed to inform signalR to call user: $receiver');
peerConnection.addStream(localMediaStream);
peerConnection.onAddStream = (MediaStream stream) {
remoteStream = stream;
onRemoteMediaStream.call(stream);
};
return true;
}
Future hangupCall(String caller, String receiver) async{
await signalR?.hangupCall(caller, receiver);
dispose();
}
answerOffer(Map offerSdp) async{
final caller = offerSdp['caller'];
final receiver = offerSdp['target'];
peerConnection.setRemoteDescription(rtcSessionDescriptionFrom(offerSdp))
.then((value) {
return peerConnection.createAnswer();
})
.then((anwser) {
return peerConnection.setLocalDescription(anwser);
})
.then((value) {
return peerConnection.getLocalDescription();
})
.then((answer) {
return signalR?.answerOffer(answer, caller, receiver);
});
}
sdpOfferAnswered(Map sdp){
final answerSdp = rtcSessionDescriptionFrom(sdp);
peerConnection.setRemoteDescription(answerSdp)
.then((value) {
}).catchError((e) => print(e));
}
Future<void> hangUp(RTCVideoRenderer localVideo) async {
}
Future<String> createSdpAnswer(String toOfferSdp) async {
final offerSdp = rtcSessionDescriptionFrom(jsonDecode(toOfferSdp));
peerConnection.setRemoteDescription(offerSdp);
final answer = await peerConnection.createAnswer();
var answerSdp = json.encode(answer); // Send SDP via Push or any channel
return answerSdp;
}
Future<String> createSdpOffer(String caller, String receiver) async {
await Future.delayed(Duration(seconds: 1));
final offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
final map = offer.toMap();
var offerSdp = json.encode({'sdp':map, 'target':receiver, 'caller':caller}); // Send SDP via Push or any channel
return offerSdp;
}
addCandidate(Map candidate){
peerConnection.addCandidate(rtcIceCandidateFrom(candidate));
}
void registerPeerConnectionListeners() {
peerConnection.onIceCandidate = (RTCIceCandidate candidate){
print(json.encode(candidate.toMap()));
signalR?.addIceCandidate(candidate);
};
peerConnection.onIceGatheringState = (RTCIceGatheringState state) {
print('ICE gathering state changed: $state');
};
peerConnection.onConnectionState = (RTCPeerConnectionState state) {
print('Connection state change: $state ${state.index}');
};
peerConnection.onSignalingState = (RTCSignalingState state) {
print('Signaling state change: $state');
};
}
}
rtcSessionDescriptionFrom(Map sdp){
return RTCSessionDescription(
sdp['sdp'],sdp['type'],
);
}
rtcIceCandidateFrom(Map candidate){
final _candidate = candidate['candidate'];
return RTCIceCandidate(_candidate['candidate'], _candidate['sdpMid'], _candidate['sdpMLineIndex']);
}