Skip to content

Commit c1d0f1d

Browse files
committed
add web socket
1 parent c124d54 commit c1d0f1d

File tree

12 files changed

+529
-44
lines changed

12 files changed

+529
-44
lines changed

lib/core/shared/data/config/dev_config.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:injectable/injectable.dart';
55
@Injectable(as: Config)
66
class DevConfig implements Config {
77
@override
8-
String get baseUrl => '';
8+
String get baseUrl => 'api.ourglass.cc';
99

1010
@override
1111
bool get enableLogging => true;
@@ -14,6 +14,9 @@ class DevConfig implements Config {
1414
String get flavorName => dev.name;
1515

1616
@override
17-
// String get turnUrl => 'stun.dev.ourglass.cc';
1817
String get turnUrl => 'stun:stun.dev.ourglass.cc:3479';
18+
19+
@override
20+
String get accesToken =>
21+
'eyJhbGciOiJSUzI1NiIsImtpZCI6IkNEOENENEFCMUMzREY3MjgyM0UwM0M3ODMyRTlENTQ1MTYzQjU5QkRSUzI1NiIsIng1dCI6InpZelVxeHc5OXlnajREeDRNdW5WUlJZN1diMCIsInR5cCI6ImF0K2p3dCJ9.eyJpc3MiOiJodHRwczovL2FwaS5vdXJnbGFzcy5jYyIsIm5iZiI6MTY3MzU1NTc1NSwiaWF0IjoxNjczNTU1NzU1LCJleHAiOjE2NzM1NTkzNTUsImF1ZCI6WyJhdWRpb21hbmFnZXIiLCJjaGFubmVsIiwiY2hhdCIsImNvbW1lbnRzIiwiZmlsZW1hbmFnZXIiLCJmb2xsb3ciLCJmcmllbmRzIiwiaWRlbnRpdHkiLCJpbWFnZXNtYW5hZ2VyIiwibGFuZ3VhZ2VtYW5hZ2VyIiwibGl2ZWNvbmNlcnQiLCJsaXZlZXZlbnRtYW5hZ2VyIiwibm90aWZpY2F0aW9ubWFuYWdlciIsInBvc3R2aWRlbyIsInJlYWN0aW9ucyIsInNjaGVkdWxpbmciLCJ0ZXh0cG9zdCIsInRpZXIiLCJ1c2VycHJvZmlsZWRhdGFhZ2dyZWdhdGUiLCJ2aWRlb21hbmFnZXIiLCJ3YWxsYWdncmVnYXRlIl0sInNjb3BlIjpbImF1ZGlvbWFuYWdlci5mdWxsIiwiY2hhbm5lbC5mdWxsIiwiY2hhdC5mdWxsIiwiY29tbWVudHMuZnVsbCIsImZpbGVtYW5hZ2VyLmZ1bGwiLCJmb2xsb3cuZnVsbCIsImZyaWVuZHMuZnVsbCIsImlkZW50aXR5LmZ1bGwiLCJpbWFnZXNtYW5hZ2VyLmZ1bGwiLCJsYW5ndWFnZW1hbmFnZXIuZnVsbCIsImxpdmVjb25jZXJ0LmZ1bGwiLCJsaXZlZXZlbnRtYW5hZ2VyLmZ1bGwiLCJub3RpZmljYXRpb25tYW5hZ2VyLmZ1bGwiLCJvcGVuaWQiLCJwb3N0dmlkZW8uZnVsbCIsInByb2ZpbGUiLCJyZWFjdGlvbnMuZnVsbCIsInNjaGVkdWxpbmcuZnVsbCIsInN0YXRpc3RpY3MuZnVsbCIsInRleHRwb3N0LmZ1bGwiLCJ0aWVyLmZ1bGwiLCJ1c2VycHJvZmlsZWRhdGFhZ2dyZWdhdGUuZnVsbCIsInZpZGVvbWFuYWdlci5mdWxsIiwid2FsbGFnZ3JlZ2F0ZS5mdWxsIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdLCJjbGllbnRfaWQiOiJmbHV0dGVyIiwic3ViIjoiZjg1Y2E5NzAtYjg0ZC00YjczLTgwZmItMGMzZWRiMmY4ODAzIiwiYXV0aF90aW1lIjoxNjczNTQ0NjA0LCJpZHAiOiJsb2NhbCIsImp0aSI6IkI2NDBCRjRDMDlBNjZCM0M5MzdBNjM4OEIyRDZBNEEzIn0.fh77k21QQyPArgKQtD2p-diufgzMVxB9alV49owIqlPB-A44FhAbT1KMIcPX2yYRQPOOnshQVk4qY7wKiFFKSEae0pnGfuUmuNBDK69qSJ48wgGYPaQTp4o-12VGiJYpuRmeqceu_KyR45ZE46YHmVCQrG5XoEu2nnRplPExNG4s61gTW1wljaONl6-4rZ49Zz9ptLYk91LwYNwT9HG_-HYFk3Jc6g1KCyS78s4aEuGgOun7cmjsocmDWoqHECpvXp7YNsgZ4jvd69EHTmRpYQi9fVzpDxIawgsyXmv8-8STNxHl5LiY6OAQZk8Xnd70bYLjb-lZUEupwRisxX-PUQ';
1922
}

lib/core/shared/data/config/prod_config.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ class ProdConfig implements Config {
1515

1616
@override
1717
String get turnUrl => '';
18+
19+
@override
20+
String get accesToken => '';
1821
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
abstract class Config {
22
String get flavorName;
33
String get baseUrl;
4+
String get accesToken;
45
String get turnUrl;
56
bool get enableLogging;
67
}

lib/features/home/data/repositories/web_rtc_repository.dart

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import 'package:demo_webrtc/core/core.dart';
88
import 'package:demo_webrtc/features/home/home.dart';
99
import 'package:flutter_webrtc/flutter_webrtc.dart';
1010
import 'package:injectable/injectable.dart';
11+
import 'package:sdp_transform/sdp_transform.dart';
12+
import 'package:signalr_core/signalr_core.dart';
1113

1214
@Injectable(as: IWebRTCRepository)
1315
class WebRtcRepository implements IWebRTCRepository {
@@ -19,9 +21,65 @@ class WebRtcRepository implements IWebRTCRepository {
1921
RTCPeerConnection? _peerConnection;
2022
MediaStream? _localStream;
2123

24+
HubConnection? _connection;
25+
26+
bool _offer = false;
27+
2228
late final RTCVideoRenderer _localVideoRenderer;
2329
late final RTCVideoRenderer _remoteVideoRenderer;
2430

31+
@override
32+
Future<void> initSockets() async {
33+
try {
34+
_connection ??= HubConnectionBuilder()
35+
.withUrl(
36+
Uri.https(_config.baseUrl, 'chat/messaging').toString(),
37+
HttpConnectionOptions(
38+
accessTokenFactory: _accessTokenFactory,
39+
),
40+
)
41+
.withAutomaticReconnect()
42+
.build();
43+
await _connection!.start();
44+
_connection!.on('ReceiveMessage', _recivedMessage);
45+
} catch (_) {
46+
rethrow;
47+
}
48+
}
49+
50+
@override
51+
Future<void> sendSdp(String value) async {
52+
try {
53+
await _connection?.invoke(
54+
'Send',
55+
args: [
56+
'52A0C3A5-F2B2-4877-A184-08DAF413495A',
57+
value,
58+
],
59+
);
60+
} catch (_) {
61+
rethrow;
62+
}
63+
}
64+
65+
void _recivedMessage(List<dynamic>? messages) {
66+
if (messages != null) {
67+
final message = messages.first;
68+
final sdp = message['message'] as String;
69+
// final userFromUsername = message['userFromUsername'] as String;
70+
71+
_addToStream(RemoteSDPRecived(sdp));
72+
}
73+
}
74+
75+
Future<String?> _accessTokenFactory() {
76+
try {
77+
return Future.value(_config.accesToken);
78+
} catch (_) {
79+
return Future.value();
80+
}
81+
}
82+
2583
@override
2684
Future<RTCVideoRenderer> initLocalRender() async {
2785
try {
@@ -55,6 +113,7 @@ class WebRtcRepository implements IWebRTCRepository {
55113
@override
56114
Future<void> close() async {
57115
await _localVideoRenderer.dispose();
116+
await _connection?.stop();
58117
}
59118

60119
Future<MediaStream> _getUserMedia() async {
@@ -63,7 +122,8 @@ class WebRtcRepository implements IWebRTCRepository {
63122
'audio': true,
64123
'video': {'facingMode': 'user'}
65124
};
66-
_localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
125+
_localStream =
126+
await navigator.mediaDevices.getUserMedia(mediaConstraints);
67127
_localVideoRenderer.srcObject = _localStream;
68128
_addToStream(LocalAudioTracks(_localStream!.getAudioTracks()));
69129
_addToStream(LocalVideoTracks(_localStream!.getVideoTracks()));
@@ -114,8 +174,7 @@ class WebRtcRepository implements IWebRTCRepository {
114174
Future<RTCPeerConnection> _createPeerConnection() async {
115175
final peerConnection = await createPeerConnection(
116176
_configuration,
117-
// _offerSdpConstraints,
118-
_loopbackConstraints,
177+
_offerSdpConstraints,
119178
);
120179
await peerConnection.addStream(await _getUserMedia());
121180
peerConnection
@@ -129,6 +188,7 @@ class WebRtcRepository implements IWebRTCRepository {
129188
Future<String> createOffer() async {
130189
final description = await _peerConnection!.createOffer(_constraints);
131190
await _peerConnection!.setLocalDescription(description);
191+
_offer = true;
132192
return _session(description);
133193
}
134194

@@ -148,8 +208,7 @@ class WebRtcRepository implements IWebRTCRepository {
148208
// final sdp = write(parse(value), null);
149209
final description = RTCSessionDescription(
150210
value,
151-
'answer',
152-
// 'offer',
211+
_offer ? 'answer' : 'offer',
153212
);
154213
// log(sdp);
155214
// log(description.toMap().toString());
@@ -170,14 +229,14 @@ class WebRtcRepository implements IWebRTCRepository {
170229

171230
String _session(RTCSessionDescription description) {
172231
try {
232+
final j2 = parse(description.sdp!);
233+
log('$j2');
173234
return description.sdp!;
174235
// final j = jsonDecode(description.sdp!);
175-
// final j2 = parse(description.sdp!);
176236
// print(j);
177237
// log('$j2');
178238
// return j2;
179239
} catch (e) {
180-
print(e);
181240
rethrow;
182241
}
183242
}
@@ -191,3 +250,11 @@ class WebRtcRepository implements IWebRTCRepository {
191250
],
192251
};
193252
}
253+
254+
extension HubConnectionStateX on HubConnectionState {
255+
bool get connecting => this == HubConnectionState.connecting;
256+
bool get reconnecting => this == HubConnectionState.reconnecting;
257+
bool get disconnecting => this == HubConnectionState.disconnecting;
258+
bool get connected => this == HubConnectionState.connected;
259+
bool get disconnected => this == HubConnectionState.disconnected;
260+
}

lib/features/home/domain/repositories/i_web_rtc_repository.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter_webrtc/flutter_webrtc.dart';
22

33
abstract class IWebRTCRepository {
4+
Future<void> initSockets();
45
Future<RTCVideoRenderer> initLocalRender();
56
Future<RTCVideoRenderer> initRemoteRender();
67
Stream<WebRTCData> get onLocalWebRTC;
@@ -9,6 +10,7 @@ abstract class IWebRTCRepository {
910
Future<String> createAnswer();
1011
Future<void> setRemoteDescription(String value);
1112
Future<void> addCandidate(String value);
13+
Future<void> sendSdp(String value);
1214
}
1315

1416
abstract class WebRTCData {}
@@ -36,3 +38,9 @@ class RemoteVideoTracks implements WebRTCData {
3638

3739
final List<MediaStreamTrack> videoTracks;
3840
}
41+
42+
class RemoteSDPRecived implements WebRTCData {
43+
RemoteSDPRecived(this.sdp);
44+
45+
final String sdp;
46+
}

lib/features/home/presentation/bloc/home_bloc.dart

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
2222
on<_Answer>(_answerToState);
2323
on<_Description>(_descriptionToState);
2424
on<_Candidate>(_candidateToState);
25+
on<_SdpRecived>(_sdpRecivedToState);
2526
}
2627

2728
final IWebRTCRepository _repository;
@@ -37,6 +38,11 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
3738

3839
void init() {
3940
_controller = TextEditingController();
41+
try {
42+
_repository.initSockets();
43+
} catch (_) {
44+
print(_);
45+
}
4046
}
4147

4248
Future<void> _startToState(_, Emitter<HomeState> emit) async {
@@ -72,6 +78,9 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
7278
log('local-video-track: $videoTrack');
7379
}
7480
}
81+
if (data is RemoteSDPRecived) {
82+
add(HomeEvent.onSdpRecived(sdp: data.sdp));
83+
}
7584
}
7685

7786
Future<void> _remoteConnectToState(_, Emitter<HomeState> emit) async {
@@ -96,7 +105,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
96105
Future<void> _offerToState(_, Emitter<HomeState> emit) async {
97106
try {
98107
final session = await _repository.createOffer();
99-
log(session);
108+
await _repository.sendSdp(session);
100109
} catch (_) {
101110
print(_);
102111
}
@@ -105,28 +114,45 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
105114
Future<void> _answerToState(_, Emitter<HomeState> emit) async {
106115
try {
107116
final session = await _repository.createAnswer();
108-
log(session);
117+
await _repository.sendSdp(session);
109118
} catch (_) {
110119
print(_);
111120
}
112121
}
113122

114123
Future<void> _descriptionToState(_, Emitter<HomeState> emit) async {
115124
try {
116-
log(value);
117-
await _repository.setRemoteDescription(value);
125+
await _repository.setRemoteDescription(
126+
state.sdpForDescription ?? state.sdpForSetCandidate!,
127+
);
118128
} catch (_) {
119129
print(_);
120130
}
121131
}
122132

123133
Future<void> _candidateToState(_, Emitter<HomeState> emit) async {
124134
try {
125-
await _repository.addCandidate(value);
135+
await _repository.addCandidate(
136+
state.sdpForDescription ?? state.sdpForSetCandidate!,
137+
);
126138
} catch (_) {
127139
print(_);
128140
}
129141
}
130142

131143
String get value => _controller.text;
144+
145+
void _sdpRecivedToState(
146+
_SdpRecived event,
147+
Emitter<HomeState> emit,
148+
) {
149+
final state = this.state.copyWith(
150+
activeAnswer: true,
151+
activeSetCandidate: true,
152+
activeSetDescription: true,
153+
sdpForDescription: event.sdp,
154+
sdpForSetCandidate: event.sdp,
155+
);
156+
emit(state);
157+
}
132158
}

0 commit comments

Comments
 (0)