Created
June 28, 2024 22:37
-
-
Save gisborne/7a714c72444d91cbcd7f93a92aab73b3 to your computer and use it in GitHub Desktop.
Failed webrtc connection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter_webrtc/flutter_webrtc.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: Scaffold( | |
appBar: AppBar(title: const Text('MacOS STUN Test')), | |
body: const STUNTest(), | |
), | |
); | |
} | |
} | |
class STUNTest extends StatefulWidget { | |
const STUNTest({Key? key}) : super(key: key); | |
@override | |
_STUNTestState createState() => _STUNTestState(); | |
} | |
class _STUNTestState extends State<STUNTest> { | |
String _status = 'Initializing...'; | |
RTCPeerConnection? _peerConnection; | |
bool _gatheringComplete = false; | |
@override | |
void initState() { | |
super.initState(); | |
_createPeerConnection(); | |
} | |
Future<void> _createPeerConnection() async { | |
_addLog('Creating peer connection...'); | |
final Map<String, dynamic> configuration = { | |
'iceServers': [ | |
{ | |
'urls': [ | |
'stun:stun1.l.google.com:19302', | |
'stun:stun2.l.google.com:19302', | |
] | |
} | |
], | |
'sdpSemantics': 'unified-plan', | |
'iceTransportPolicy': 'all', | |
'bundlePolicy': 'max-bundle', | |
'rtcpMuxPolicy': 'require', | |
'iceCandidatePoolSize': 0, | |
'enableDscp': true, | |
'enableIPv6': true, | |
}; | |
_peerConnection = await createPeerConnection(configuration); | |
_peerConnection!.onIceCandidate = (RTCIceCandidate candidate) { | |
if (candidate.candidate != null) { | |
_processCandidate(candidate.candidate!); | |
} | |
}; | |
_peerConnection!.onIceGatheringState = (RTCIceGatheringState state) { | |
_addLog('ICE gathering state changed: $state'); | |
if (state == RTCIceGatheringState.RTCIceGatheringStateComplete) { | |
_gatheringComplete = true; | |
_checkGatheringComplete(); | |
} | |
}; | |
_peerConnection!.onConnectionState = (RTCPeerConnectionState state) { | |
_addLog('Peer connection state changed: $state'); | |
}; | |
_addLog('Creating data channel...'); | |
await _peerConnection!.createDataChannel('trigger', RTCDataChannelInit()); | |
_addLog('Creating offer...'); | |
RTCSessionDescription offer = await _peerConnection!.createOffer(); | |
_addLog('Setting local description...'); | |
await _peerConnection!.setLocalDescription(offer); | |
// Set a longer timeout for M1 Macs | |
Future.delayed(const Duration(seconds: 45), () { | |
_checkGatheringComplete(); | |
}); | |
} | |
void _processCandidate(String candidateString) { | |
_addLog('Received candidate: $candidateString'); | |
final parts = candidateString.split(' '); | |
final type = parts.firstWhere((part) => part.startsWith('typ ')).split(' ')[1]; | |
final ip = parts[4]; | |
final port = parts[5]; | |
_addLog('Candidate type: $type, IP: $ip, Port: $port'); | |
} | |
void _checkGatheringComplete() { | |
if (!_gatheringComplete) { | |
_addLog('Gathering timed out or completed'); | |
} | |
if (mounted) { | |
setState(() { | |
_status += '\nGathering process finished.'; | |
}); | |
} | |
} | |
void _addLog(String log) { | |
print(log); | |
if (mounted) { | |
setState(() { | |
_status += '\n$log'; | |
}); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return SingleChildScrollView( | |
child: Padding( | |
padding: const EdgeInsets.all(16.0), | |
child: Text(_status), | |
), | |
); | |
} | |
@override | |
void dispose() { | |
_peerConnection?.close(); | |
super.dispose(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment