diff --git a/example/lib/src/callscreen.dart b/example/lib/src/callscreen.dart index 976c0307..056ce922 100644 --- a/example/lib/src/callscreen.dart +++ b/example/lib/src/callscreen.dart @@ -211,7 +211,8 @@ class _MyCallScreenWidget extends State } void _handleHangup() { - call!.hangup({'status_code': 603}); + final TerminateOptions options = TerminateOptions()..statusCode = 603; + call!.hangup(options); _timer.cancel(); } diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 4e8e53f4..900418a1 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -13,7 +13,7 @@ import 'package:dart_sip_ua_example/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(MyApp()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); diff --git a/lib/sip_ua.dart b/lib/sip_ua.dart index c7f2efe7..9514478d 100644 --- a/lib/sip_ua.dart +++ b/lib/sip_ua.dart @@ -2,6 +2,5 @@ export 'src/enum_helper.dart'; export 'src/sip_message.dart'; export 'src/sip_ua_helper.dart'; export 'src/transport_type.dart'; +export 'src/types.dart'; export 'src/uri.dart'; - - diff --git a/lib/src/config.dart b/lib/src/config.dart index d9849d85..318abf22 100644 --- a/lib/src/config.dart +++ b/lib/src/config.dart @@ -1,13 +1,11 @@ import 'package:sip_ua/sip_ua.dart'; import 'package:sip_ua/src/transports/socket_interface.dart'; -import 'package:sip_ua/src/transports/tcp_socket.dart'; + import 'constants.dart' as DartSIP_C; import 'constants.dart'; import 'exceptions.dart' as Exceptions; import 'grammar.dart'; import 'logger.dart'; -import 'transports/web_socket.dart'; -import 'uri.dart'; import 'utils.dart' as Utils; // Default settings. diff --git a/lib/src/rtc_session.dart b/lib/src/rtc_session.dart index 9fc9da52..af345018 100644 --- a/lib/src/rtc_session.dart +++ b/lib/src/rtc_session.dart @@ -1,12 +1,9 @@ import 'dart:async'; -import 'dart:convert'; -import 'package:crypto/crypto.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:sdp_transform/sdp_transform.dart' as sdp_transform; -import 'package:sdp_transform/sdp_transform.dart'; - import 'package:sip_ua/sip_ua.dart'; + import 'constants.dart' as DartSIP_C; import 'constants.dart'; import 'dialog.dart'; @@ -22,11 +19,9 @@ import 'rtc_session/info.dart' as RTCSession_Info; import 'rtc_session/info.dart'; import 'rtc_session/refer_notifier.dart'; import 'rtc_session/refer_subscriber.dart'; -import 'sip_message.dart'; import 'timers.dart'; import 'transactions/transaction_base.dart'; import 'ua.dart'; -import 'uri.dart'; import 'utils.dart' as utils; class C { @@ -314,7 +309,7 @@ class RTCSession extends EventManager implements Owner { requestParams['from_display_name'] = options['from_display_name'] ?? ''; requestParams['from_uri'] = URI.parse(options['from_uri']); extraHeaders - .add('P-Preferred-Identity: ${_ua.configuration.uri.toString()}'); + .add('P-Preferred-Identity: ${_ua.configuration.uri.toString()}'); } if (anonymous) { @@ -713,21 +708,21 @@ class RTCSession extends EventManager implements Owner { /** * Terminate the call. */ - void terminate([Map? options]) { + void terminate([TerminateOptions? options]) { logger.d('terminate()'); - options = options ?? {}; + options = options ?? TerminateOptions(); - Object cause = options['cause'] ?? DartSIP_C.CausesType.BYE; + String cause = options.cause ?? DartSIP_C.CausesType.BYE; - List extraHeaders = options['extraHeaders'] != null - ? utils.cloneArray(options['extraHeaders']) + List extraHeaders = options.extraHeaders != null + ? utils.cloneArray(options.extraHeaders) : []; - Object? body = options['body']; + String? body = options.body; String? cancel_reason; - int? status_code = options['status_code'] as int?; - String? reason_phrase = options['reason_phrase'] as String?; + int? status_code = options.statusCode; + String? reason_phrase = options.reasonPhrase; // Check Session Status. if (_status == C.STATUS_TERMINATED) { @@ -784,8 +779,8 @@ class RTCSession extends EventManager implements Owner { case C.STATUS_CONFIRMED: logger.d('terminating session'); - reason_phrase = options['reason_phrase'] as String? ?? - DartSIP_C.REASON_PHRASE[status_code ?? 0]; + reason_phrase = + options.reasonPhrase ?? DartSIP_C.REASON_PHRASE[status_code ?? 0]; if (status_code != null && (status_code < 200 || status_code >= 700)) { throw Exceptions.InvalidStateError( @@ -1060,11 +1055,11 @@ class RTCSession extends EventManager implements Owner { } }); handlers.on(EventCallFailed(), (EventCallFailed event) { - terminate({ - 'cause': DartSIP_C.CausesType.WEBRTC_ERROR, - 'status_code': 500, - 'reason_phrase': 'Hold Failed' - }); + final TerminateOptions options = TerminateOptions() + ..cause = DartSIP_C.CausesType.WEBRTC_ERROR + ..statusCode = 500 + ..reasonPhrase = 'Hold Failed'; + terminate(options); }); if (options['useUpdate'] != null) { @@ -1110,11 +1105,11 @@ class RTCSession extends EventManager implements Owner { } }); handlers.on(EventCallFailed(), (EventCallFailed event) { - terminate({ - 'cause': DartSIP_C.CausesType.WEBRTC_ERROR, - 'status_code': 500, - 'reason_phrase': 'Unhold Failed' - }); + final TerminateOptions options = TerminateOptions() + ..cause = DartSIP_C.CausesType.WEBRTC_ERROR + ..statusCode = 500 + ..reasonPhrase = 'Unhold Failed'; + terminate(options); }); if (options['useUpdate'] != null) { @@ -1166,11 +1161,11 @@ class RTCSession extends EventManager implements Owner { }); handlers.on(EventCallFailed(), (EventCallFailed event) { - terminate({ - 'cause': DartSIP_C.CausesType.WEBRTC_ERROR, - 'status_code': 500, - 'reason_phrase': 'Media Renegotiation Failed' - }); + final TerminateOptions options = TerminateOptions() + ..cause = DartSIP_C.CausesType.WEBRTC_ERROR + ..statusCode = 500 + ..reasonPhrase = 'Media Renegotiation Failed'; + terminate(options); }); _setLocalMediaStatus(); @@ -1288,10 +1283,10 @@ class RTCSession extends EventManager implements Owner { if (_late_sdp) { if (request.body == null) { - terminate({ - 'cause': DartSIP_C.CausesType.MISSING_SDP, - 'status_code': 400 - }); + final TerminateOptions options = TerminateOptions() + ..cause = DartSIP_C.CausesType.MISSING_SDP + ..statusCode = 400; + terminate(options); break; } @@ -1304,10 +1299,10 @@ class RTCSession extends EventManager implements Owner { try { await _connection!.setRemoteDescription(answer); } catch (error) { - terminate({ - 'cause': DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION, - 'status_code': 488 - }); + final TerminateOptions options = TerminateOptions() + ..cause = DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION + ..statusCode = 488; + terminate(options); logger.e( 'emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); emit(EventSetRemoteDescriptionFailed(exception: error)); @@ -1405,11 +1400,11 @@ class RTCSession extends EventManager implements Owner { void onTransportError() { logger.e('onTransportError()'); if (_status != C.STATUS_TERMINATED) { - terminate({ - 'status_code': 500, - 'reason_phrase': DartSIP_C.CausesType.CONNECTION_ERROR, - 'cause': DartSIP_C.CausesType.CONNECTION_ERROR - }); + final TerminateOptions options = TerminateOptions() + ..statusCode = 500 + ..reasonPhrase = DartSIP_C.CausesType.CONNECTION_ERROR + ..cause = DartSIP_C.CausesType.CONNECTION_ERROR; + terminate(options); } } @@ -1417,11 +1412,11 @@ class RTCSession extends EventManager implements Owner { logger.e('onRequestTimeout()'); if (_status != C.STATUS_TERMINATED) { - terminate({ - 'status_code': 408, - 'reason_phrase': DartSIP_C.CausesType.REQUEST_TIMEOUT, - 'cause': DartSIP_C.CausesType.REQUEST_TIMEOUT - }); + final TerminateOptions options = TerminateOptions() + ..statusCode = 408 + ..reasonPhrase = DartSIP_C.CausesType.REQUEST_TIMEOUT + ..cause = DartSIP_C.CausesType.REQUEST_TIMEOUT; + terminate(options); } } @@ -1429,11 +1424,11 @@ class RTCSession extends EventManager implements Owner { logger.e('onDialogError()'); if (_status != C.STATUS_TERMINATED) { - terminate({ - 'status_code': 500, - 'reason_phrase': DartSIP_C.CausesType.DIALOG_ERROR, - 'cause': DartSIP_C.CausesType.DIALOG_ERROR - }); + final TerminateOptions options = TerminateOptions() + ..statusCode = 500 + ..reasonPhrase = DartSIP_C.CausesType.DIALOG_ERROR + ..cause = DartSIP_C.CausesType.DIALOG_ERROR; + terminate(options); } } @@ -1598,11 +1593,11 @@ class RTCSession extends EventManager implements Owner { logger.d('ICE Restart was successful'); }); handlers.on(EventCallFailed(), (EventCallFailed event) { - terminate({ - 'cause': DartSIP_C.CausesType.WEBRTC_ERROR, - 'status_code': 500, - 'reason_phrase': 'Media Renegotiation Failed' - }); + final TerminateOptions options = TerminateOptions() + ..cause = DartSIP_C.CausesType.WEBRTC_ERROR + ..statusCode = 500 + ..reasonPhrase = 'Media Renegotiation Failed'; + terminate(options); }); offerConstraints['eventHandlers'] = handlers; renegotiate(options: offerConstraints); @@ -1614,11 +1609,11 @@ class RTCSession extends EventManager implements Owner { _connection!.onIceConnectionState = (RTCIceConnectionState state) { // TODO(cloudwebrtc): Do more with different states. if (state == RTCIceConnectionState.RTCIceConnectionStateFailed) { - terminate({ - 'cause': DartSIP_C.CausesType.RTP_TIMEOUT, - 'status_code': 408, - 'reason_phrase': DartSIP_C.CausesType.RTP_TIMEOUT - }); + final TerminateOptions options = TerminateOptions() + ..cause = DartSIP_C.CausesType.RTP_TIMEOUT + ..statusCode = 408 + ..reasonPhrase = DartSIP_C.CausesType.RTP_TIMEOUT; + terminate(options); } else if (state == RTCIceConnectionState.RTCIceConnectionStateDisconnected) { _iceRestart(); @@ -2937,7 +2932,7 @@ class RTCSession extends EventManager implements Owner { } /// SDP offers may contain text media channels. e.g. Older clients using linphone. - /// + /// /// WebRTC does not support text media channels, so remove them. String? _sdpOfferToWebRTC(String? sdpInput) { if (sdpInput == null) { @@ -3065,11 +3060,11 @@ class RTCSession extends EventManager implements Owner { logger.e('runSessionTimer() | timer expired, terminating the session'); - terminate({ - 'cause': DartSIP_C.CausesType.REQUEST_TIMEOUT, - 'status_code': 408, - 'reason_phrase': 'Session Timer Expired' - }); + final TerminateOptions options = TerminateOptions() + ..cause = DartSIP_C.CausesType.REQUEST_TIMEOUT + ..statusCode = 408 + ..reasonPhrase = 'Session Timer Expired'; + terminate(options); }, expires! * 1100); } } diff --git a/lib/src/rtc_session/dtmf.dart b/lib/src/rtc_session/dtmf.dart index df8269e3..31091ae4 100644 --- a/lib/src/rtc_session/dtmf.dart +++ b/lib/src/rtc_session/dtmf.dart @@ -1,13 +1,12 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; - import 'package:sip_ua/sip_ua.dart'; + import '../constants.dart'; import '../event_manager/event_manager.dart'; import '../event_manager/internal_events.dart'; import '../exceptions.dart' as Exceptions; import '../logger.dart'; import '../rtc_session.dart' as rtc; -import '../sip_message.dart'; import '../utils.dart' as Utils; class C { diff --git a/lib/src/sip_ua_helper.dart b/lib/src/sip_ua_helper.dart index a27d44ae..ece8b3ad 100644 --- a/lib/src/sip_ua_helper.dart +++ b/lib/src/sip_ua_helper.dart @@ -8,6 +8,7 @@ import 'package:sip_ua/src/event_manager/internal_events.dart'; import 'package:sip_ua/src/map_helper.dart'; import 'package:sip_ua/src/transports/socket_interface.dart'; import 'package:sip_ua/src/transports/tcp_socket.dart'; + import 'config.dart'; import 'constants.dart' as DartSIP_C; import 'event_manager/event_manager.dart'; @@ -16,7 +17,6 @@ import 'logger.dart'; import 'message.dart'; import 'rtc_session.dart'; import 'rtc_session/refer_subscriber.dart'; -import 'sip_message.dart'; import 'stack_trace_nj.dart'; import 'subscriber.dart'; import 'transports/web_socket.dart'; @@ -179,9 +179,9 @@ class SIPUAHelper extends EventManager { _settings.instance_id = uaSettings.instanceId; _settings.registrar_server = uaSettings.registrarServer; _settings.contact_uri = uaSettings.contact_uri; - _settings.connection_recovery_max_interval = + _settings.connection_recovery_max_interval = uaSettings.connectionRecoveryMaxInterval; - _settings.connection_recovery_min_interval = + _settings.connection_recovery_min_interval = uaSettings.connectionRecoveryMinInterval; _settings.terminateOnAudioMediaPortZero = uaSettings.terminateOnMediaPortZero; @@ -423,7 +423,7 @@ class SIPUAHelper extends EventManager { s.subscribe(); } - void terminateSessions(Map options) { + void terminateSessions(TerminateOptions? options) { _ua!.terminateSessions(options); } @@ -550,7 +550,7 @@ class Call { refer.on(EventReferFailed(), (EventReferFailed data) {}); } - void hangup([Map? options]) { + void hangup([TerminateOptions? options]) { assert(_session != null, 'ERROR(hangup): rtc session is invalid!'); if (peerConnection != null) { for (MediaStream? stream in peerConnection!.getLocalStreams()) { diff --git a/lib/src/types.dart b/lib/src/types.dart new file mode 100644 index 00000000..fbb1b3c3 --- /dev/null +++ b/lib/src/types.dart @@ -0,0 +1,9 @@ +class TerminateOptions { + TerminateOptions(); + + String? cause; + List? extraHeaders; + String? body; + int? statusCode; + String? reasonPhrase; +} diff --git a/lib/src/ua.dart b/lib/src/ua.dart index 92e581bb..7e827401 100644 --- a/lib/src/ua.dart +++ b/lib/src/ua.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:sip_ua/src/transport_type.dart'; import 'package:sip_ua/src/transports/socket_interface.dart'; +import 'package:sip_ua/src/types.dart'; import 'config.dart' as config; import 'config.dart'; import 'constants.dart' as DartSIP_C; @@ -294,7 +295,7 @@ class UA extends EventManager { /** * Terminate ongoing sessions. */ - void terminateSessions(Map options) { + void terminateSessions(TerminateOptions? options) { logger.d('terminateSessions()'); _sessions.forEach((String? key, _) { if (!_sessions[key]!.isEnded()) {