Simple Flutter client for testing SIP-over-WebSocket calls against the FreeSWITCH/WebRTC signaling hub.
The app uses:
sip_uafor SIP registration, INVITE, ACK, BYE, and SIP-over-WS transport.flutter_webrtcfor local/remote media streams, camera, microphone, and screen sharing.- The local signaling hub as the SIP-over-WebSocket endpoint.
Clone and start the signaling hub first:
git clone https://github.com/Jerome-Jumah/free-switch-webrtc.git
cd free-switch-webrtc
npm install
npm run devHub repo: Jerome-Jumah/free-switch-webrtc
Then run this Flutter app:
cd /Users/quing/projects/sip
flutter runFor local testing against the hub, use:
- WebSocket:
ws://localhost:4500/ - SIP URI:
sip:1001@localhost:4500 - Transport:
WS - Password: leave empty unless the hub is changed to enforce auth
For a physical phone on the same network, replace localhost with the computer LAN IP, for example:
- WebSocket:
ws://192.168.1.5:4500/ - SIP URI:
sip:1004@192.168.1.5:4500
Use wss:// with a valid certificate for production or remote/mobile network testing.
Web to Flutter:
- Register the web client in the hub UI.
- Register this Flutter client with a different extension.
- Dial the Flutter extension from the web UI.
- Accept on mobile.
Flutter to web:
- Register both clients.
- In the Flutter dial pad, enter the web SIP URI or extension, for example
sip:1001@192.168.1.5:4500. - Start an audio or video call.
- Accept on the web UI.
- The hub expects SIP-native clients to include ICE candidates inside SDP. This app sets a longer SIP UA ICE gathering timeout for that reason.
- The web client uses JSON signaling internally, and the hub translates between JSON WebRTC messages and SIP-over-WS messages.
- After a call ends, keep the current SIP registration active. Avoid forced unregister/re-register loops unless the transport actually disconnected.
- If only local video appears, check that both clients are on reachable network addresses and that the SDP contains ICE candidates.
- If the hub cannot see the Flutter app after hangup, fully restart the app and register again. The app should not auto re-register after every ended call.
- If Android/iOS cannot connect to
localhost, use the computer LAN IP instead. - If browser media fails, make sure the web UI is opened from a secure context when required by the browser.