From 618e5d34127e0517ac5e440c5b45a8b912c25f97 Mon Sep 17 00:00:00 2001 From: Victor Uvarov Date: Thu, 26 Sep 2024 14:39:05 -0700 Subject: [PATCH 1/2] replace usage of direction as a string with an CallDirection enum --- example/lib/src/callscreen.dart | 4 ++-- lib/sip_ua.dart | 3 +-- lib/src/direction.dart | 1 + lib/src/message.dart | 13 +++++++------ lib/src/options.dart | 13 +++++++------ lib/src/rtc_session.dart | 13 +++++++------ lib/src/rtc_session/dtmf.dart | 9 +++++---- lib/src/rtc_session/info.dart | 9 +++++---- lib/src/sip_ua_helper.dart | 12 +++++------- 9 files changed, 40 insertions(+), 37 deletions(-) create mode 100644 lib/src/direction.dart diff --git a/example/lib/src/callscreen.dart b/example/lib/src/callscreen.dart index 976c0307..a7c34242 100644 --- a/example/lib/src/callscreen.dart +++ b/example/lib/src/callscreen.dart @@ -47,7 +47,7 @@ class _MyCallScreenWidget extends State String? get remoteIdentity => call!.remote_identity; - String get direction => call!.direction; + CallDirection? get direction => call!.direction; Call? get call => widget._call; @@ -412,7 +412,7 @@ class _MyCallScreenWidget extends State switch (_state) { case CallStateEnum.NONE: case CallStateEnum.CONNECTING: - if (direction == 'INCOMING') { + if (direction == CallDirection.incoming) { basicActions.add(ActionButton( title: "Accept", fillColor: Colors.green, diff --git a/lib/sip_ua.dart b/lib/sip_ua.dart index c7f2efe7..b3df26a4 100644 --- a/lib/sip_ua.dart +++ b/lib/sip_ua.dart @@ -1,7 +1,6 @@ +export 'src/direction.dart'; export 'src/enum_helper.dart'; export 'src/sip_message.dart'; export 'src/sip_ua_helper.dart'; export 'src/transport_type.dart'; export 'src/uri.dart'; - - diff --git a/lib/src/direction.dart b/lib/src/direction.dart new file mode 100644 index 00000000..c13039af --- /dev/null +++ b/lib/src/direction.dart @@ -0,0 +1 @@ +enum CallDirection { outgoing, incoming } diff --git a/lib/src/message.dart b/lib/src/message.dart index 2aeffe49..d89ce791 100644 --- a/lib/src/message.dart +++ b/lib/src/message.dart @@ -1,3 +1,4 @@ +import 'package:sip_ua/src/direction.dart'; import 'package:sip_ua/src/name_addr_header.dart'; import 'constants.dart' as DartSIP_C; import 'constants.dart'; @@ -17,14 +18,14 @@ class Message extends EventManager with Applicant { final UA _ua; dynamic _request; bool _closed = false; - String? _direction; + CallDirection? _direction; NameAddrHeader? _local_identity; NameAddrHeader? _remote_identity; // Whether an incoming message has been replied. bool _is_replied = false; // Custom message empty object for high level use. final Map _data = {}; - String? get direction => _direction; + CallDirection? get direction => _direction; NameAddrHeader? get local_identity => _local_identity; @@ -103,7 +104,7 @@ class Message extends EventManager with Applicant { List extraHeaders = Utils.cloneArray(options['extraHeaders']); String? body = options['body']; - if (_direction != 'incoming') { + if (_direction != CallDirection.incoming) { throw Exceptions.NotSupportedError( '"accept" not supported for outgoing Message'); } @@ -126,7 +127,7 @@ class Message extends EventManager with Applicant { List extraHeaders = Utils.cloneArray(options['extraHeaders']); String? body = options['body']; - if (_direction != 'incoming') { + if (_direction != CallDirection.incoming) { throw Exceptions.NotSupportedError( '"reject" not supported for outgoing Message'); } @@ -186,11 +187,11 @@ class Message extends EventManager with Applicant { void _newMessage(String originator, dynamic request) { if (originator == 'remote') { - _direction = 'incoming'; + _direction = CallDirection.incoming; _local_identity = request.to; _remote_identity = request.from; } else if (originator == 'local') { - _direction = 'outgoing'; + _direction = CallDirection.outgoing; _local_identity = request.from; _remote_identity = request.to; } diff --git a/lib/src/options.dart b/lib/src/options.dart index cff29729..1bc0ef1d 100644 --- a/lib/src/options.dart +++ b/lib/src/options.dart @@ -1,3 +1,4 @@ +import 'package:sip_ua/src/direction.dart'; import 'package:sip_ua/src/name_addr_header.dart'; import 'constants.dart' as DartSIP_C; import 'constants.dart'; @@ -17,14 +18,14 @@ class Options extends EventManager with Applicant { final UA _ua; dynamic _request; bool _closed = false; - String? _direction; + CallDirection? _direction; NameAddrHeader? _local_identity; NameAddrHeader? _remote_identity; // Whether an incoming Options has been replied. bool _is_replied = false; // Custom Options empty object for high level use. final Map _data = {}; - String? get direction => _direction; + CallDirection? get direction => _direction; NameAddrHeader? get local_identity => _local_identity; @@ -102,7 +103,7 @@ class Options extends EventManager with Applicant { List extraHeaders = Utils.cloneArray(options['extraHeaders']); String? body = options['body']; - if (_direction != 'incoming') { + if (_direction != CallDirection.incoming) { throw Exceptions.NotSupportedError( '"accept" not supported for outgoing Options'); } @@ -125,7 +126,7 @@ class Options extends EventManager with Applicant { List extraHeaders = Utils.cloneArray(options['extraHeaders']); String? body = options['body']; - if (_direction != 'incoming') { + if (_direction != CallDirection.incoming) { throw Exceptions.NotSupportedError( '"reject" not supported for outgoing Options'); } @@ -184,11 +185,11 @@ class Options extends EventManager with Applicant { void _newOptions(String originator, dynamic request) { if (originator == 'remote') { - _direction = 'incoming'; + _direction = CallDirection.incoming; _local_identity = request.to; _remote_identity = request.from; } else if (originator == 'local') { - _direction = 'outgoing'; + _direction = CallDirection.outgoing; _local_identity = request.from; _remote_identity = request.to; } diff --git a/lib/src/rtc_session.dart b/lib/src/rtc_session.dart index 9fc9da52..0aaf020e 100644 --- a/lib/src/rtc_session.dart +++ b/lib/src/rtc_session.dart @@ -7,6 +7,7 @@ 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 'package:sip_ua/src/direction.dart'; import 'constants.dart' as DartSIP_C; import 'constants.dart'; import 'dialog.dart'; @@ -126,7 +127,7 @@ class RTCSession extends EventManager implements Owner { final SIPTimers _timers = SIPTimers(); // Session info. - String? _direction; + CallDirection? _direction; NameAddrHeader? _local_identity; NameAddrHeader? _remote_identity; DateTime? _start_time; @@ -176,7 +177,7 @@ class RTCSession extends EventManager implements Owner { String? get contact => _contact; - String? get direction => _direction; + CallDirection? get direction => _direction; NameAddrHeader? get local_identity => _local_identity; @@ -340,7 +341,7 @@ class RTCSession extends EventManager implements Owner { await _createRTCConnection(pcConfig, rtcConstraints); // Set internal properties. - _direction = 'outgoing'; + _direction = CallDirection.outgoing; _local_identity = _request.from; _remote_identity = _request.to; @@ -427,7 +428,7 @@ class RTCSession extends EventManager implements Owner { } // Set internal properties. - _direction = 'incoming'; + _direction = CallDirection.incoming; _local_identity = request.to; _remote_identity = request.from; @@ -487,7 +488,7 @@ class RTCSession extends EventManager implements Owner { data = options['data'] ?? data; // Check Session Direction and Status. - if (_direction != 'incoming') { + if (_direction != CallDirection.incoming) { throw Exceptions.NotSupportedError( '"answer" not supported for outgoing RTCSession'); } @@ -802,7 +803,7 @@ class RTCSession extends EventManager implements Owner { * transaction times out." */ if (_status == C.STATUS_WAITING_FOR_ACK && - _direction == 'incoming' && + _direction == CallDirection.incoming && _request.server_transaction.state != TransactionState.TERMINATED) { /// Save the dialog for later restoration. Dialog dialog = _dialog!; diff --git a/lib/src/rtc_session/dtmf.dart b/lib/src/rtc_session/dtmf.dart index df8269e3..1e6b5877 100644 --- a/lib/src/rtc_session/dtmf.dart +++ b/lib/src/rtc_session/dtmf.dart @@ -1,6 +1,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:sip_ua/sip_ua.dart'; +import 'package:sip_ua/src/direction.dart'; import '../constants.dart'; import '../event_manager/event_manager.dart'; import '../event_manager/internal_events.dart'; @@ -25,7 +26,7 @@ class DTMF extends EventManager { final rtc.RTCSession _session; DtmfMode? _mode; - String? _direction; + CallDirection? _direction; String? _tone; int? _duration; int? _interToneGap; @@ -36,14 +37,14 @@ class DTMF extends EventManager { int? get duration => _duration; - String? get direction => _direction; + CallDirection? get direction => _direction; void send(String tone, Map options) { if (tone == null) { throw Exceptions.TypeError('Not enough arguments'); } - _direction = 'outgoing'; + _direction = CallDirection.outgoing; // Check RTCSession Status. if (_session.status != rtc.C.STATUS_CONFIRMED && @@ -113,7 +114,7 @@ class DTMF extends EventManager { String reg_tone = r'^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*'; String reg_duration = r'^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*'; - _direction = 'incoming'; + _direction = CallDirection.incoming; _request = request; request.reply(200); diff --git a/lib/src/rtc_session/info.dart b/lib/src/rtc_session/info.dart index 6eca4c2d..289acad9 100644 --- a/lib/src/rtc_session/info.dart +++ b/lib/src/rtc_session/info.dart @@ -1,3 +1,4 @@ +import 'package:sip_ua/src/direction.dart'; import 'package:sip_ua/src/sip_message.dart'; import '../constants.dart'; import '../event_manager/event_manager.dart'; @@ -10,7 +11,7 @@ class Info extends EventManager { Info(this._session); final rtc.RTCSession _session; - String? _direction; + CallDirection? _direction; String? _contentType; String? _body; IncomingRequest? _request; @@ -19,10 +20,10 @@ class Info extends EventManager { String? get body => _body; - String? get direction => _direction; + CallDirection? get direction => _direction; void send(String contentType, String body, Map options) { - _direction = 'outgoing'; + _direction = CallDirection.outgoing; if (contentType == null) { throw Exceptions.TypeError('Not enough arguments'); @@ -68,7 +69,7 @@ class Info extends EventManager { } void init_incoming(IncomingRequest request) { - _direction = 'incoming'; + _direction = CallDirection.incoming; _request = request; request.reply(200); diff --git a/lib/src/sip_ua_helper.dart b/lib/src/sip_ua_helper.dart index 71de9291..373c0d07 100644 --- a/lib/src/sip_ua_helper.dart +++ b/lib/src/sip_ua_helper.dart @@ -4,6 +4,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:logger/logger.dart'; import 'package:sdp_transform/sdp_transform.dart' as sdp_transform; import 'package:sip_ua/sip_ua.dart'; +import 'package:sip_ua/src/direction.dart'; 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'; @@ -232,7 +233,7 @@ class SIPUAHelper extends EventManager { _ua!.on(EventNewRTCSession(), (EventNewRTCSession event) { logger.d('newRTCSession => $event'); RTCSession session = event.session!; - if (session.direction == 'incoming') { + if (session.direction == CallDirection.incoming) { // Set event handlers. session.addAllEventHandlers( buildCallOptions()['eventHandlers'] as EventManager); @@ -250,7 +251,7 @@ class SIPUAHelper extends EventManager { _ua!.on(EventNewMessage(), (EventNewMessage event) { logger.d('newMessage => $event'); //Only notify incoming message to listener - if (event.message!.direction == 'incoming') { + if (event.message!.direction == CallDirection.incoming) { SIPMessageRequest message = SIPMessageRequest(event.message, event.originator, event.request); _notifyNewMessageListeners(message); @@ -657,12 +658,9 @@ class Call { return ''; } - String get direction { + CallDirection? get direction { assert(_session != null, 'ERROR(get direction): rtc session is invalid!'); - if (_session.direction != null) { - return _session.direction!.toUpperCase(); - } - return ''; + return _session.direction; } bool get remote_has_audio => _peerHasMediaLine('audio'); From 1af1b5d659c704b27f481a01d8b955870c87ddb6 Mon Sep 17 00:00:00 2001 From: Victor Uvarov Date: Thu, 26 Sep 2024 15:27:16 -0700 Subject: [PATCH 2/2] convert more string enums to actual enums --- example/lib/src/callscreen.dart | 12 +- example/pubspec.yaml | 2 +- lib/sip_ua.dart | 2 +- lib/src/config.dart | 4 +- lib/src/direction.dart | 1 - lib/src/enums.dart | 39 ++ lib/src/event_manager/call_events.dart | 23 +- lib/src/event_manager/internal_events.dart | 13 +- lib/src/event_manager/message_events.dart | 3 +- lib/src/event_manager/options_events.dart | 3 +- lib/src/message.dart | 37 +- lib/src/options.dart | 54 +- lib/src/rtc_session.dart | 586 ++++++++------------- lib/src/rtc_session/dtmf.dart | 38 +- lib/src/rtc_session/info.dart | 26 +- lib/src/sip_ua_helper.dart | 153 ++---- lib/src/ua.dart | 7 +- 17 files changed, 405 insertions(+), 598 deletions(-) delete mode 100644 lib/src/direction.dart create mode 100644 lib/src/enums.dart diff --git a/example/lib/src/callscreen.dart b/example/lib/src/callscreen.dart index a7c34242..be698480 100644 --- a/example/lib/src/callscreen.dart +++ b/example/lib/src/callscreen.dart @@ -34,7 +34,7 @@ class _MyCallScreenWidget extends State bool _speakerOn = false; bool _hold = false; bool _mirror = true; - String? _holdOriginator; + Originator? _holdOriginator; bool _callConfirmed = false; CallStateEnum _state = CallStateEnum.NONE; @@ -47,7 +47,7 @@ class _MyCallScreenWidget extends State String? get remoteIdentity => call!.remote_identity; - CallDirection? get direction => call!.direction; + Direction? get direction => call!.direction; Call? get call => widget._call; @@ -177,7 +177,7 @@ class _MyCallScreenWidget extends State void _handleStreams(CallState event) async { MediaStream? stream = event.stream; - if (event.originator == 'local') { + if (event.originator == Originator.local) { if (_localRenderer != null) { _localRenderer!.srcObject = stream; } @@ -186,7 +186,7 @@ class _MyCallScreenWidget extends State } _localStream = stream; } - if (event.originator == 'remote') { + if (event.originator == Originator.remote) { if (_remoteRenderer != null) { _remoteRenderer!.srcObject = stream; } @@ -412,7 +412,7 @@ class _MyCallScreenWidget extends State switch (_state) { case CallStateEnum.NONE: case CallStateEnum.CONNECTING: - if (direction == CallDirection.incoming) { + if (direction == Direction.incoming) { basicActions.add(ActionButton( title: "Accept", fillColor: Colors.green, @@ -597,7 +597,7 @@ class _MyCallScreenWidget extends State child: Text( (voiceOnly ? 'VOICE CALL' : 'VIDEO CALL') + (_hold - ? ' PAUSED BY ${_holdOriginator!.toUpperCase()}' + ? ' PAUSED BY ${_holdOriginator!.name}' : ''), style: TextStyle(fontSize: 24, color: textColor), ), diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 1e834d69..0eabefa1 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -15,7 +15,7 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.15.0 <3.0.0" flutter: ">=1.10.0" dependencies: diff --git a/lib/sip_ua.dart b/lib/sip_ua.dart index b3df26a4..8fe2256f 100644 --- a/lib/sip_ua.dart +++ b/lib/sip_ua.dart @@ -1,5 +1,5 @@ -export 'src/direction.dart'; export 'src/enum_helper.dart'; +export 'src/enums.dart'; export 'src/sip_message.dart'; export 'src/sip_ua_helper.dart'; export 'src/transport_type.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/direction.dart b/lib/src/direction.dart deleted file mode 100644 index c13039af..00000000 --- a/lib/src/direction.dart +++ /dev/null @@ -1 +0,0 @@ -enum CallDirection { outgoing, incoming } diff --git a/lib/src/enums.dart b/lib/src/enums.dart new file mode 100644 index 00000000..814b6f8a --- /dev/null +++ b/lib/src/enums.dart @@ -0,0 +1,39 @@ +/// Defines the direction of a communication, +/// indicating whether it is outgoing or incoming. +/// +/// Used to specify the flow of calls or messages. +enum Direction { + /// Represents an outgoing call or message. + outgoing, + + /// Represents an incoming call or message. + incoming +} + +/// Identifies the originator of a communication, +/// specifying whether the initiator is local or remote. +/// +/// This is useful for determining who started the call or message. +enum Originator { + /// Represents the user of this device initiated the communication. + local, + + /// Represents the communication was initiated by someone else. + remote, + + /// Represents that the communication was initiated by the system (e.g., automated processes). + system, +} + +/// Represents the type of SDP (Session Description Protocol) message +/// used in a communication session. +/// +/// SDP messages are exchanged between peers during the setup of a media connection. +enum SdpType { + /// Represents an SDP offer, which is the initial proposal sent to set up a media session. + offer, + + /// Represents an SDP answer, which is the response to an SDP offer, + /// confirming or adjusting the session parameters. + answer +} diff --git a/lib/src/event_manager/call_events.dart b/lib/src/event_manager/call_events.dart index 0270a8cc..cb1ca218 100644 --- a/lib/src/event_manager/call_events.dart +++ b/lib/src/event_manager/call_events.dart @@ -1,4 +1,5 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; +import 'package:sip_ua/src/enums.dart'; import '../rtc_session.dart'; import '../sip_message.dart'; @@ -11,9 +12,9 @@ class CallEvent extends EventType { } class EventNewRTCSession extends CallEvent { - EventNewRTCSession({RTCSession? session, String? originator, dynamic request}) + EventNewRTCSession({RTCSession? session, Originator? originator, dynamic request}) : super(session); - String? originator; + Originator? originator; dynamic request; } @@ -25,7 +26,7 @@ class EventCallEnded extends CallEvent { EventCallEnded( {RTCSession? session, this.originator, this.cause, this.request}) : super(session); - String? originator; + Originator? originator; ErrorCause? cause; IncomingRequest? request; } @@ -34,7 +35,7 @@ class EventCallProgress extends CallEvent { EventCallProgress( {RTCSession? session, this.originator, this.response, this.cause}) : super(session); - String? originator; + Originator? originator; dynamic response; ErrorCause? cause; } @@ -42,18 +43,18 @@ class EventCallProgress extends CallEvent { class EventCallConfirmed extends CallEvent { EventCallConfirmed({RTCSession? session, this.originator, this.ack}) : super(session); - String? originator; + Originator? originator; dynamic ack; } class EventCallHold extends CallEvent { EventCallHold({RTCSession? session, this.originator}) : super(session); - String? originator; + Originator? originator; } class EventCallUnhold extends CallEvent { - EventCallUnhold({RTCSession? session, String? originator}) : super(session); - String? originator; + EventCallUnhold({RTCSession? session, Originator? originator}) : super(session); + Originator? originator; } class EventCallMuted extends CallEvent { @@ -73,7 +74,7 @@ class EventCallUnmuted extends CallEvent { class EventCallAccepted extends CallEvent { EventCallAccepted({RTCSession? session, this.originator, this.response}) : super(session); - String? originator; + Originator? originator; dynamic response; } @@ -89,7 +90,7 @@ class EventCallFailed extends CallEvent { this.status_line}) : super(session); dynamic response; - String? originator; + Originator? originator; ErrorCause? cause; dynamic request; String? status_line; @@ -98,7 +99,7 @@ class EventCallFailed extends CallEvent { class EventStream extends CallEvent { EventStream({RTCSession? session, this.originator, this.stream}) : super(session); - String? originator; + Originator? originator; MediaStream? stream; } diff --git a/lib/src/event_manager/internal_events.dart b/lib/src/event_manager/internal_events.dart index 0d2f3ed8..2313f6e0 100644 --- a/lib/src/event_manager/internal_events.dart +++ b/lib/src/event_manager/internal_events.dart @@ -1,4 +1,5 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; +import 'package:sip_ua/src/enums.dart'; import '../rtc_session.dart' show RTCSession; import '../rtc_session/dtmf.dart'; @@ -33,8 +34,8 @@ class EventOnAuthenticated extends EventType { class EventSdp extends EventType { EventSdp({this.originator, this.type, this.sdp}); - String? originator; - String? type; + Originator? originator; + SdpType? type; String? sdp; } @@ -55,7 +56,7 @@ class EventSetLocalDescriptionFailed extends EventType { class EventFailedUnderScore extends EventType { EventFailedUnderScore({this.originator, this.cause}); - String? originator; + Originator? originator; ErrorCause? cause; } @@ -66,14 +67,14 @@ class EventGetUserMediaFailed extends EventType { class EventNewDTMF extends EventType { EventNewDTMF({this.originator, this.request, this.dtmf}); - String? originator; + Originator? originator; dynamic request; DTMF? dtmf; } class EventNewInfo extends EventType { EventNewInfo({this.originator, this.request, this.info}); - String? originator; + Originator? originator; dynamic request; Info? info; } @@ -127,7 +128,7 @@ class EventOnFialed extends EventType {} class EventSucceeded extends EventType { EventSucceeded({this.response, this.originator}); - String? originator; + Originator? originator; IncomingMessage? response; } diff --git a/lib/src/event_manager/message_events.dart b/lib/src/event_manager/message_events.dart index ccc15b68..445f61f9 100644 --- a/lib/src/event_manager/message_events.dart +++ b/lib/src/event_manager/message_events.dart @@ -1,9 +1,10 @@ +import '../enums.dart'; import '../message.dart'; import 'events.dart'; class EventNewMessage extends EventType { EventNewMessage({this.message, this.originator, this.request}); dynamic request; - String? originator; + Originator? originator; Message? message; } diff --git a/lib/src/event_manager/options_events.dart b/lib/src/event_manager/options_events.dart index 668c2b5d..2bfe65a7 100644 --- a/lib/src/event_manager/options_events.dart +++ b/lib/src/event_manager/options_events.dart @@ -1,9 +1,10 @@ +import '../enums.dart'; import '../options.dart'; import 'events.dart'; class EventNewOptions extends EventType { EventNewOptions({this.message, this.originator, this.request}); dynamic request; - String? originator; + Originator? originator; Options? message; } diff --git a/lib/src/message.dart b/lib/src/message.dart index d89ce791..ec9a0b19 100644 --- a/lib/src/message.dart +++ b/lib/src/message.dart @@ -1,5 +1,6 @@ -import 'package:sip_ua/src/direction.dart'; +import 'package:sip_ua/src/enums.dart'; import 'package:sip_ua/src/name_addr_header.dart'; + import 'constants.dart' as DartSIP_C; import 'constants.dart'; import 'event_manager/event_manager.dart'; @@ -18,14 +19,14 @@ class Message extends EventManager with Applicant { final UA _ua; dynamic _request; bool _closed = false; - CallDirection? _direction; + Direction? _direction; NameAddrHeader? _local_identity; NameAddrHeader? _remote_identity; // Whether an incoming message has been replied. bool _is_replied = false; // Custom message empty object for high level use. final Map _data = {}; - CallDirection? get direction => _direction; + Direction? get direction => _direction; NameAddrHeader? get local_identity => _local_identity; @@ -77,7 +78,7 @@ class Message extends EventManager with Applicant { RequestSender request_sender = RequestSender(_ua, _request, handlers); - _newMessage('local', _request); + _newMessage(Originator.local, _request); request_sender.send(); } @@ -85,7 +86,7 @@ class Message extends EventManager with Applicant { void init_incoming(IncomingRequest request) { _request = request; - _newMessage('remote', request); + _newMessage(Originator.remote, request); // Reply with a 200 OK if the user didn't reply. if (!_is_replied) { @@ -104,7 +105,7 @@ class Message extends EventManager with Applicant { List extraHeaders = Utils.cloneArray(options['extraHeaders']); String? body = options['body']; - if (_direction != CallDirection.incoming) { + if (_direction != Direction.incoming) { throw Exceptions.NotSupportedError( '"accept" not supported for outgoing Message'); } @@ -127,7 +128,7 @@ class Message extends EventManager with Applicant { List extraHeaders = Utils.cloneArray(options['extraHeaders']); String? body = options['body']; - if (_direction != CallDirection.incoming) { + if (_direction != Direction.incoming) { throw Exceptions.NotSupportedError( '"reject" not supported for outgoing Message'); } @@ -152,10 +153,10 @@ class Message extends EventManager with Applicant { // Ignore provisional responses. } else if (RegExp(r'^2[0-9]{2}$') .hasMatch(response.status_code.toString())) { - _succeeded('remote', response); + _succeeded(Originator.remote, response); } else { String cause = Utils.sipErrorCause(response.status_code); - _failed('remote', response.status_code, cause, response.reason_phrase); + _failed(Originator.remote, response.status_code, cause, response.reason_phrase); } } @@ -164,14 +165,14 @@ class Message extends EventManager with Applicant { return; } _failed( - 'system', 408, DartSIP_C.CausesType.REQUEST_TIMEOUT, 'Request Timeout'); + Originator.system, 408, DartSIP_C.CausesType.REQUEST_TIMEOUT, 'Request Timeout'); } void _onTransportError() { if (_closed) { return; } - _failed('system', 500, DartSIP_C.CausesType.CONNECTION_ERROR, + _failed(Originator.system, 500, DartSIP_C.CausesType.CONNECTION_ERROR, 'Transport Error'); } @@ -185,13 +186,13 @@ class Message extends EventManager with Applicant { * Internal Callbacks */ - void _newMessage(String originator, dynamic request) { - if (originator == 'remote') { - _direction = CallDirection.incoming; + void _newMessage(Originator originator, dynamic request) { + if (originator == Originator.remote) { + _direction = Direction.incoming; _local_identity = request.to; _remote_identity = request.from; - } else if (originator == 'local') { - _direction = CallDirection.outgoing; + } else if (originator == Originator.local) { + _direction = Direction.outgoing; _local_identity = request.from; _remote_identity = request.to; } @@ -199,7 +200,7 @@ class Message extends EventManager with Applicant { _ua.newMessage(this, originator, request); } - void _failed(String originator, int? status_code, String cause, + void _failed(Originator originator, int? status_code, String cause, String? reason_phrase) { logger.d('MESSAGE failed'); close(); @@ -212,7 +213,7 @@ class Message extends EventManager with Applicant { reason_phrase: reason_phrase))); } - void _succeeded(String originator, IncomingResponse? response) { + void _succeeded(Originator originator, IncomingResponse? response) { logger.d('MESSAGE succeeded'); close(); diff --git a/lib/src/options.dart b/lib/src/options.dart index 1bc0ef1d..4f9847f7 100644 --- a/lib/src/options.dart +++ b/lib/src/options.dart @@ -1,5 +1,6 @@ -import 'package:sip_ua/src/direction.dart'; +import 'package:sip_ua/src/enums.dart'; import 'package:sip_ua/src/name_addr_header.dart'; + import 'constants.dart' as DartSIP_C; import 'constants.dart'; import 'event_manager/event_manager.dart'; @@ -18,14 +19,14 @@ class Options extends EventManager with Applicant { final UA _ua; dynamic _request; bool _closed = false; - CallDirection? _direction; + Direction? _direction; NameAddrHeader? _local_identity; NameAddrHeader? _remote_identity; // Whether an incoming Options has been replied. bool _is_replied = false; // Custom Options empty object for high level use. final Map _data = {}; - CallDirection? get direction => _direction; + Direction? get direction => _direction; NameAddrHeader? get local_identity => _local_identity; @@ -57,8 +58,7 @@ class Options extends EventManager with Applicant { extraHeaders.add('Content-Type: $contentType'); - _request = - OutgoingRequest(SipMethod.OPTIONS, normalized, _ua, null, extraHeaders); + _request = OutgoingRequest(SipMethod.OPTIONS, normalized, _ua, null, extraHeaders); if (body != null) { _request.body = body; } @@ -76,7 +76,7 @@ class Options extends EventManager with Applicant { RequestSender request_sender = RequestSender(_ua, _request, handlers); - _newOptions('local', _request); + _newOptions(Originator.local, _request); request_sender.send(); } @@ -84,7 +84,7 @@ class Options extends EventManager with Applicant { void init_incoming(IncomingRequest request) { _request = request; - _newOptions('remote', request); + _newOptions(Originator.remote, request); // Reply with a 200 OK if the user didn't reply. if (!_is_replied) { @@ -103,9 +103,8 @@ class Options extends EventManager with Applicant { List extraHeaders = Utils.cloneArray(options['extraHeaders']); String? body = options['body']; - if (_direction != CallDirection.incoming) { - throw Exceptions.NotSupportedError( - '"accept" not supported for outgoing Options'); + if (_direction != Direction.incoming) { + throw Exceptions.NotSupportedError('"accept" not supported for outgoing Options'); } if (_is_replied) { @@ -126,9 +125,8 @@ class Options extends EventManager with Applicant { List extraHeaders = Utils.cloneArray(options['extraHeaders']); String? body = options['body']; - if (_direction != CallDirection.incoming) { - throw Exceptions.NotSupportedError( - '"reject" not supported for outgoing Options'); + if (_direction != Direction.incoming) { + throw Exceptions.NotSupportedError('"reject" not supported for outgoing Options'); } if (_is_replied) { @@ -150,10 +148,10 @@ class Options extends EventManager with Applicant { if (RegExp(r'^1[0-9]{2}$').hasMatch(response!.status_code)) { // Ignore provisional responses. } else if (RegExp(r'^2[0-9]{2}$').hasMatch(response.status_code)) { - _succeeded('remote', response); + _succeeded(Originator.remote, response); } else { String cause = Utils.sipErrorCause(response.status_code); - _failed('remote', response.status_code, cause, response.reason_phrase); + _failed(Originator.remote, response.status_code, cause, response.reason_phrase); } } @@ -161,16 +159,14 @@ class Options extends EventManager with Applicant { if (_closed != null) { return; } - _failed( - 'system', 408, DartSIP_C.CausesType.REQUEST_TIMEOUT, 'Request Timeout'); + _failed(Originator.system, 408, DartSIP_C.CausesType.REQUEST_TIMEOUT, 'Request Timeout'); } void _onTransportError() { if (_closed != null) { return; } - _failed('system', 500, DartSIP_C.CausesType.CONNECTION_ERROR, - 'Transport Error'); + _failed(Originator.system, 500, DartSIP_C.CausesType.CONNECTION_ERROR, 'Transport Error'); } @override @@ -183,13 +179,13 @@ class Options extends EventManager with Applicant { * Internal Callbacks */ - void _newOptions(String originator, dynamic request) { - if (originator == 'remote') { - _direction = CallDirection.incoming; + void _newOptions(Originator originator, dynamic request) { + if (originator == Originator.remote) { + _direction = Direction.incoming; _local_identity = request.to; _remote_identity = request.from; - } else if (originator == 'local') { - _direction = CallDirection.outgoing; + } else if (originator == Originator.local) { + _direction = Direction.outgoing; _local_identity = request.from; _remote_identity = request.to; } @@ -197,20 +193,16 @@ class Options extends EventManager with Applicant { _ua.newOptions(this, originator, request); } - void _failed(String originator, int? status_code, String cause, - String? reason_phrase) { + void _failed(Originator originator, int? status_code, String cause, String? reason_phrase) { logger.d('OPTIONS failed'); close(); logger.d('emit "failed"'); emit(EventCallFailed( originator: originator, - cause: ErrorCause( - cause: cause, - status_code: status_code, - reason_phrase: reason_phrase))); + cause: ErrorCause(cause: cause, status_code: status_code, reason_phrase: reason_phrase))); } - void _succeeded(String originator, IncomingResponse? response) { + void _succeeded(Originator originator, IncomingResponse? response) { logger.d('OPTIONS succeeded'); close(); diff --git a/lib/src/rtc_session.dart b/lib/src/rtc_session.dart index 0aaf020e..ee5690af 100644 --- a/lib/src/rtc_session.dart +++ b/lib/src/rtc_session.dart @@ -1,13 +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 'package:sip_ua/src/direction.dart'; + import 'constants.dart' as DartSIP_C; import 'constants.dart'; import 'dialog.dart'; @@ -23,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 { @@ -57,8 +51,8 @@ class SIPTimers { } class RFC4028Timers { - RFC4028Timers(this.enabled, this.refreshMethod, this.defaultExpires, - this.currentExpires, this.running, this.refresher, this.timer); + RFC4028Timers(this.enabled, this.refreshMethod, this.defaultExpires, this.currentExpires, + this.running, this.refresher, this.timer); bool enabled; SipMethod refreshMethod; int? defaultExpires; @@ -127,7 +121,7 @@ class RTCSession extends EventManager implements Owner { final SIPTimers _timers = SIPTimers(); // Session info. - CallDirection? _direction; + Direction? _direction; NameAddrHeader? _local_identity; NameAddrHeader? _remote_identity; DateTime? _start_time; @@ -143,8 +137,7 @@ class RTCSession extends EventManager implements Owner { late RFC4028Timers _sessionTimers; // Map of ReferSubscriber instances indexed by the REFER's CSeq number. - final Map _referSubscribers = - {}; + final Map _referSubscribers = {}; // Custom session empty object for high level use. Map? data = {}; @@ -177,7 +170,7 @@ class RTCSession extends EventManager implements Owner { String? get contact => _contact; - CallDirection? get direction => _direction; + Direction? get direction => _direction; NameAddrHeader? get local_identity => _local_identity; @@ -236,26 +229,23 @@ class RTCSession extends EventManager implements Owner { } void connect(dynamic target, - [Map? options, - InitSuccessCallback? initCallback]) async { + [Map? options, InitSuccessCallback? initCallback]) async { logger.d('connect()'); options = options ?? {}; dynamic originalTarget = target; EventManager eventHandlers = options['eventHandlers'] ?? EventManager(); List extraHeaders = utils.cloneArray(options['extraHeaders']); - Map mediaConstraints = options['mediaConstraints'] ?? - {'audio': true, 'video': true}; + Map mediaConstraints = + options['mediaConstraints'] ?? {'audio': true, 'video': true}; MediaStream? mediaStream = options['mediaStream']; Map pcConfig = options['pcConfig'] ?? {'iceServers': []}; - Map rtcConstraints = - options['rtcConstraints'] ?? {}; + Map rtcConstraints = options['rtcConstraints'] ?? {}; Map rtcOfferConstraints = options['rtcOfferConstraints'] ?? {}; _rtcOfferConstraints = rtcOfferConstraints; - _rtcAnswerConstraints = - options['rtcAnswerConstraints'] ?? {}; + _rtcAnswerConstraints = options['rtcAnswerConstraints'] ?? {}; data = options['data'] ?? data; data?['video'] = !(options['mediaConstraints']['video'] == false); @@ -301,9 +291,7 @@ class RTCSession extends EventManager implements Owner { // Set anonymous property. bool anonymous = options['anonymous'] ?? false; - Map requestParams = { - 'from_tag': _from_tag - }; + Map requestParams = {'from_tag': _from_tag}; _ua.contact!.anonymous = anonymous; _ua.contact!.outbound = true; _contact = _ua.contact.toString(); @@ -314,15 +302,13 @@ class RTCSession extends EventManager implements Owner { if (isFromUriOptionPresent) { 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()}'); + extraHeaders.add('P-Preferred-Identity: ${_ua.configuration.uri.toString()}'); } if (anonymous) { requestParams['from_display_name'] = 'Anonymous'; requestParams['from_uri'] = URI('sip', 'anonymous', 'anonymous.invalid'); - extraHeaders - .add('P-Preferred-Identity: ${_ua.configuration.uri.toString()}'); + extraHeaders.add('P-Preferred-Identity: ${_ua.configuration.uri.toString()}'); extraHeaders.add('Privacy: id'); } @@ -332,8 +318,7 @@ class RTCSession extends EventManager implements Owner { extraHeaders.add('Session-Expires: ${_sessionTimers.defaultExpires}'); } - _request = - InitialOutgoingInviteRequest(target, _ua, requestParams, extraHeaders); + _request = InitialOutgoingInviteRequest(target, _ua, requestParams, extraHeaders); _id = _request.call_id + _from_tag; @@ -341,7 +326,7 @@ class RTCSession extends EventManager implements Owner { await _createRTCConnection(pcConfig, rtcConstraints); // Set internal properties. - _direction = CallDirection.outgoing; + _direction = Direction.outgoing; _local_identity = _request.from; _remote_identity = _request.to; @@ -350,13 +335,11 @@ class RTCSession extends EventManager implements Owner { initCallback(this); } - _newRTCSession('local', _request); - await _sendInitialRequest( - pcConfig, mediaConstraints, rtcOfferConstraints, mediaStream); + _newRTCSession(Originator.local, _request); + await _sendInitialRequest(pcConfig, mediaConstraints, rtcOfferConstraints, mediaStream); } - void init_incoming(IncomingRequest request, - [Function(RTCSession)? initCallback]) { + void init_incoming(IncomingRequest request, [Function(RTCSession)? initCallback]) { logger.d('init_incoming()'); int? expires; @@ -383,8 +366,7 @@ class RTCSession extends EventManager implements Owner { : num.tryParse(request.getHeader('expires'))!) * 1000; } catch (e) { - logger.e( - 'Invalid Expires header value: ${request.getHeader('expires')}, error $e'); + logger.e('Invalid Expires header value: ${request.getHeader('expires')}, error $e'); } } @@ -410,8 +392,7 @@ class RTCSession extends EventManager implements Owner { // Set userNoAnswerTimer. _timers.userNoAnswerTimer = setTimeout(() { request.reply(408); - _failed('local', null, null, null, 408, DartSIP_C.CausesType.NO_ANSWER, - 'No Answer'); + _failed(Originator.local, null, null, null, 408, DartSIP_C.CausesType.NO_ANSWER, 'No Answer'); }, _ua.configuration.no_answer_timeout); /* Set expiresTimer @@ -421,14 +402,13 @@ class RTCSession extends EventManager implements Owner { _timers.expiresTimer = setTimeout(() { if (_status == C.STATUS_WAITING_FOR_ANSWER) { request.reply(487); - _failed('system', null, null, null, 487, DartSIP_C.CausesType.EXPIRES, - 'Timeout'); + _failed(Originator.system, null, null, null, 487, DartSIP_C.CausesType.EXPIRES, 'Timeout'); } }, expires); } // Set internal properties. - _direction = CallDirection.incoming; + _direction = Direction.incoming; _local_identity = request.to; _remote_identity = request.from; @@ -438,7 +418,7 @@ class RTCSession extends EventManager implements Owner { } // Fire 'newRTCSession' event. - _newRTCSession('remote', request); + _newRTCSession(Originator.remote, request); // The user may have rejected the call in the 'newRTCSession' event. if (_status == C.STATUS_TERMINATED) { @@ -450,7 +430,7 @@ class RTCSession extends EventManager implements Owner { // Fire 'progress' event. // TODO(cloudwebrtc): Document that 'response' field in 'progress' event is null for incoming calls. - _progress('local', null); + _progress(Originator.local, null); } /** @@ -460,13 +440,11 @@ class RTCSession extends EventManager implements Owner { logger.d('answer()'); dynamic request = _request; List extraHeaders = utils.cloneArray(options['extraHeaders']); - Map mediaConstraints = - options['mediaConstraints'] ?? {}; + Map mediaConstraints = options['mediaConstraints'] ?? {}; MediaStream? mediaStream = options['mediaStream'] ?? null; Map pcConfig = options['pcConfig'] ?? {'iceServers': []}; - Map rtcConstraints = - options['rtcConstraints'] ?? {}; + Map rtcConstraints = options['rtcConstraints'] ?? {}; Map rtcAnswerConstraints = options['rtcAnswerConstraints'] ?? {}; @@ -488,9 +466,8 @@ class RTCSession extends EventManager implements Owner { data = options['data'] ?? data; // Check Session Direction and Status. - if (_direction != CallDirection.incoming) { - throw Exceptions.NotSupportedError( - '"answer" not supported for outgoing RTCSession'); + if (_direction != Direction.incoming) { + throw Exceptions.NotSupportedError('"answer" not supported for outgoing RTCSession'); } // Check Session status. @@ -589,27 +566,20 @@ class RTCSession extends EventManager implements Owner { // A local MediaStream is given, use it. if (mediaStream != null) { stream = mediaStream; - emit(EventStream(session: this, originator: 'local', stream: stream)); + emit(EventStream(session: this, originator: Originator.local, stream: stream)); } // Audio and/or video requested, prompt getUserMedia. - else if (mediaConstraints['audio'] != null || - mediaConstraints['video'] != null) { + else if (mediaConstraints['audio'] != null || mediaConstraints['video'] != null) { _localMediaStreamLocallyGenerated = true; try { stream = await navigator.mediaDevices.getUserMedia(mediaConstraints); - emit(EventStream(session: this, originator: 'local', stream: stream)); + emit(EventStream(session: this, originator: Originator.local, stream: stream)); } catch (error) { if (_status == C.STATUS_TERMINATED) { throw Exceptions.InvalidStateError('terminated'); } request.reply(480); - _failed( - 'local', - null, - null, - null, - 480, - DartSIP_C.CausesType.USER_DENIED_MEDIA_ACCESS, + _failed(Originator.local, null, null, null, 480, DartSIP_C.CausesType.USER_DENIED_MEDIA_ACCESS, 'User Denied Media Access'); logger.e('emit "getusermediafailed" [error:${error.toString()}]'); emit(EventGetUserMediaFailed(exception: error)); @@ -645,26 +615,18 @@ class RTCSession extends EventManager implements Owner { logger.d('emit "sdp"'); final String? processedSDP = _sdpOfferToWebRTC(request.body); - emit(EventSdp(originator: 'remote', type: 'offer', sdp: processedSDP)); + emit(EventSdp(originator: Originator.remote, type: SdpType.offer, sdp: processedSDP)); - RTCSessionDescription offer = RTCSessionDescription(processedSDP, 'offer'); + RTCSessionDescription offer = RTCSessionDescription(processedSDP, SdpType.offer.name); try { await _connection!.setRemoteDescription(offer); } catch (error) { request.reply(488); - _failed( - 'system', - null, - null, - null, - 488, - DartSIP_C.CausesType.WEBRTC_ERROR, + _failed(Originator.system, null, null, null, 488, DartSIP_C.CausesType.WEBRTC_ERROR, 'SetRemoteDescription(offer) failed'); - logger.e( - 'emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); + logger.e('emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); emit(EventSetRemoteDescriptionFailed(exception: error)); - throw Exceptions.TypeError( - 'peerconnection.setRemoteDescription() failed'); + throw Exceptions.TypeError('peerconnection.setRemoteDescription() failed'); } // Create local description. @@ -677,9 +639,9 @@ class RTCSession extends EventManager implements Owner { RTCSessionDescription desc; try { if (!_late_sdp) { - desc = await _createLocalDescription('answer', rtcAnswerConstraints); + desc = await _createLocalDescription(SdpType.answer, rtcAnswerConstraints); } else { - desc = await _createLocalDescription('offer', _rtcOfferConstraints); + desc = await _createLocalDescription(SdpType.offer, _rtcOfferConstraints); } } catch (e) { request.reply(500); @@ -697,17 +659,16 @@ class RTCSession extends EventManager implements Owner { _status = C.STATUS_WAITING_FOR_ACK; _setInvite2xxTimer(request, desc.sdp); _setACKTimer(); - _accepted('local'); + _accepted(Originator.local); }, () { - _failed('system', null, null, null, 500, - DartSIP_C.CausesType.CONNECTION_ERROR, 'Transport Error'); + _failed(Originator.system, null, null, null, 500, DartSIP_C.CausesType.CONNECTION_ERROR, + 'Transport Error'); }); } catch (error, s) { if (_status == C.STATUS_TERMINATED) { return; } - logger.e('Failed to answer(): ${error.toString()}', - error: error, stackTrace: s); + logger.e('Failed to answer(): ${error.toString()}', error: error, stackTrace: s); } } @@ -721,9 +682,8 @@ class RTCSession extends EventManager implements Owner { Object 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? cancel_reason; @@ -760,8 +720,8 @@ class RTCSession extends EventManager implements Owner { _status = C.STATUS_CANCELED; cancel_reason = cancel_reason ?? 'Canceled by local'; status_code = status_code ?? 100; - _failed('local', null, null, null, status_code, - DartSIP_C.CausesType.CANCELED, cancel_reason); + _failed( + Originator.local, null, null, null, status_code, DartSIP_C.CausesType.CANCELED, cancel_reason); break; // - UAS - @@ -772,28 +732,25 @@ class RTCSession extends EventManager implements Owner { status_code = status_code ?? 480; if (status_code < 300 || status_code >= 700) { - throw Exceptions.InvalidStateError( - 'Invalid status_code: $status_code'); + throw Exceptions.InvalidStateError('Invalid status_code: $status_code'); } _request.reply(status_code, reason_phrase, extraHeaders, body); - _failed('local', null, null, null, status_code, - DartSIP_C.CausesType.REJECTED, reason_phrase); + _failed( + Originator.local, null, null, null, status_code, DartSIP_C.CausesType.REJECTED, reason_phrase); break; case C.STATUS_WAITING_FOR_ACK: 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['reason_phrase'] as String? ?? DartSIP_C.REASON_PHRASE[status_code ?? 0]; if (status_code != null && (status_code < 200 || status_code >= 700)) { - throw Exceptions.InvalidStateError( - 'Invalid status_code: $status_code'); + throw Exceptions.InvalidStateError('Invalid status_code: $status_code'); } else if (status_code != null) { - extraHeaders - .add('Reason: SIP ;case=$status_code; text="$reason_phrase"'); + extraHeaders.add('Reason: SIP ;case=$status_code; text="$reason_phrase"'); } /* RFC 3261 section 15 (Terminating a session): @@ -803,7 +760,7 @@ class RTCSession extends EventManager implements Owner { * transaction times out." */ if (_status == C.STATUS_WAITING_FOR_ACK && - _direction == CallDirection.incoming && + _direction == Direction.incoming && _request.server_transaction.state != TransactionState.TERMINATED) { /// Save the dialog for later restoration. Dialog dialog = _dialog!; @@ -811,34 +768,26 @@ class RTCSession extends EventManager implements Owner { // Send the BYE as soon as the ACK is received... receiveRequest = (IncomingMessage request) { if (request.method == SipMethod.ACK) { - sendRequest(SipMethod.BYE, { - 'extraHeaders': extraHeaders, - 'body': body - }); + sendRequest( + SipMethod.BYE, {'extraHeaders': extraHeaders, 'body': body}); dialog.terminate(); } }; // .., or when the INVITE transaction times out - _request.server_transaction.on(EventStateChanged(), - (EventStateChanged state) { - if (_request.server_transaction.state == - TransactionState.TERMINATED) { - sendRequest(SipMethod.BYE, { - 'extraHeaders': extraHeaders, - 'body': body - }); + _request.server_transaction.on(EventStateChanged(), (EventStateChanged state) { + if (_request.server_transaction.state == TransactionState.TERMINATED) { + sendRequest( + SipMethod.BYE, {'extraHeaders': extraHeaders, 'body': body}); dialog.terminate(); } }); _ended( - 'local', + Originator.local, null, ErrorCause( - cause: cause as String?, - status_code: status_code, - reason_phrase: reason_phrase)); + cause: cause as String?, status_code: status_code, reason_phrase: reason_phrase)); // Restore the dialog into 'this' in order to be able to send the in-dialog BYE :-). _dialog = dialog; @@ -846,17 +795,14 @@ class RTCSession extends EventManager implements Owner { // Restore the dialog into 'ua' so the ACK can reach 'this' session. _ua.newDialog(dialog); } else { - sendRequest(SipMethod.BYE, - {'extraHeaders': extraHeaders, 'body': body}); + sendRequest(SipMethod.BYE, {'extraHeaders': extraHeaders, 'body': body}); reason_phrase = reason_phrase ?? 'Terminated by local'; status_code = status_code ?? 200; _ended( - 'local', + Originator.local, null, ErrorCause( - cause: cause as String?, - status_code: status_code, - reason_phrase: reason_phrase)); + cause: cause as String?, status_code: status_code, reason_phrase: reason_phrase)); } } } @@ -871,8 +817,7 @@ class RTCSession extends EventManager implements Owner { // sensible defaults int duration = options['duration'] ?? RTCSession_DTMF.C.DEFAULT_DURATION; - int interToneGap = - options['interToneGap'] ?? RTCSession_DTMF.C.DEFAULT_INTER_TONE_GAP; + int interToneGap = options['interToneGap'] ?? RTCSession_DTMF.C.DEFAULT_INTER_TONE_GAP; int sendInterval = options['sendInterval'] ?? duration + interToneGap; if (tones == null) { @@ -956,8 +901,7 @@ class RTCSession extends EventManager implements Owner { options!['eventHandlers'] = handlers; dtmf.send(tone, options); - await Future.delayed( - Duration(milliseconds: sendInterval), () {}); + await Future.delayed(Duration(milliseconds: sendInterval), () {}); }); } } @@ -1051,7 +995,7 @@ class RTCSession extends EventManager implements Owner { } _localHold = true; - _onhold('local'); + _onhold(Originator.local); EventManager handlers = EventManager(); @@ -1075,10 +1019,8 @@ class RTCSession extends EventManager implements Owner { 'extraHeaders': options['extraHeaders'] }); } else { - _sendReinvite({ - 'eventHandlers': handlers, - 'extraHeaders': options['extraHeaders'] - }); + _sendReinvite( + {'eventHandlers': handlers, 'extraHeaders': options['extraHeaders']}); } return true; @@ -1102,7 +1044,7 @@ class RTCSession extends EventManager implements Owner { } _localHold = false; - _onunhold('local'); + _onunhold(Originator.local); EventManager handlers = EventManager(); handlers.on(EventSucceeded(), (EventSucceeded event) { @@ -1125,19 +1067,15 @@ class RTCSession extends EventManager implements Owner { 'extraHeaders': options['extraHeaders'] }); } else { - _sendReinvite({ - 'eventHandlers': handlers, - 'extraHeaders': options['extraHeaders'] - }); + _sendReinvite( + {'eventHandlers': handlers, 'extraHeaders': options['extraHeaders']}); } return true; } bool renegotiate( - {Map? options, - Function(IncomingMessage)? done, - bool useUpdate = false}) { + {Map? options, Function(IncomingMessage)? done, bool useUpdate = false}) { logger.d('renegotiate()'); options = options ?? {}; @@ -1146,11 +1084,9 @@ class RTCSession extends EventManager implements Owner { Map? rtcOfferConstraints = options['rtcOfferConstraints'] ?? _rtcOfferConstraints; - Map mediaConstraints = - options['mediaConstraints'] ?? {}; + Map mediaConstraints = options['mediaConstraints'] ?? {}; - dynamic sdpSemantics = - options['pcConfig']?['sdpSemantics'] ?? 'unified-plan'; + dynamic sdpSemantics = options['pcConfig']?['sdpSemantics'] ?? 'unified-plan'; if (_status != C.STATUS_WAITING_FOR_ACK && _status != C.STATUS_CONFIRMED) { return false; @@ -1226,8 +1162,7 @@ class RTCSession extends EventManager implements Owner { _referSubscribers[id] = referSubscriber; // Listen for ending events so we can remove it from the map. - referSubscriber.on(EventReferRequestFailed(), - (EventReferRequestFailed data) { + referSubscriber.on(EventReferRequestFailed(), (EventReferRequestFailed data) { _referSubscribers.remove(id); }); referSubscriber.on(EventReferAccepted(), (EventReferAccepted data) { @@ -1243,8 +1178,7 @@ class RTCSession extends EventManager implements Owner { /** * Send a generic in-dialog Request */ - OutgoingRequest sendRequest(SipMethod method, - [Map? options]) { + OutgoingRequest sendRequest(SipMethod method, [Map? options]) { logger.d('sendRequest()'); return _dialog!.sendRequest(method, options); @@ -1268,12 +1202,11 @@ class RTCSession extends EventManager implements Owner { * Terminate the whole session in case the user didn't accept (or yet send the answer) * nor reject the request opening the session. */ - if (_status == C.STATUS_WAITING_FOR_ANSWER || - _status == C.STATUS_ANSWERED) { + if (_status == C.STATUS_WAITING_FOR_ANSWER || _status == C.STATUS_ANSWERED) { _status = C.STATUS_CANCELED; _request.reply(487); - _failed('remote', null, request, null, 487, - DartSIP_C.CausesType.CANCELED, request.reason_phrase); + _failed(Originator.remote, null, request, null, 487, DartSIP_C.CausesType.CANCELED, + request.reason_phrase); } } else { // Requests arriving here are in-dialog requests. @@ -1289,19 +1222,15 @@ class RTCSession extends EventManager implements Owner { if (_late_sdp) { if (request.body == null) { - terminate({ - 'cause': DartSIP_C.CausesType.MISSING_SDP, - 'status_code': 400 - }); + terminate( + {'cause': DartSIP_C.CausesType.MISSING_SDP, 'status_code': 400}); break; } logger.d('emit "sdp"'); - emit(EventSdp( - originator: 'remote', type: 'answer', sdp: request.body)); + emit(EventSdp(originator: Originator.remote, type: SdpType.answer, sdp: request.body)); - RTCSessionDescription answer = - RTCSessionDescription(request.body, 'answer'); + RTCSessionDescription answer = RTCSessionDescription(request.body, SdpType.answer.name); try { await _connection!.setRemoteDescription(answer); } catch (error) { @@ -1315,14 +1244,14 @@ class RTCSession extends EventManager implements Owner { } } if (!_is_confirmed) { - _confirmed('remote', request); + _confirmed(Originator.remote, request); } break; case SipMethod.BYE: if (_status == C.STATUS_CONFIRMED) { request.reply(200); _ended( - 'remote', + Originator.remote, request, ErrorCause( cause: DartSIP_C.CausesType.BYE, @@ -1332,7 +1261,7 @@ class RTCSession extends EventManager implements Owner { request.reply(200); _request.reply(487, 'BYE Received'); _ended( - 'remote', + Originator.remote, request, ErrorCause( cause: DartSIP_C.CausesType.BYE, @@ -1361,8 +1290,7 @@ class RTCSession extends EventManager implements Owner { _status == C.STATUS_CONFIRMED) { String? contentType = request.getHeader('content-type'); if (contentType != null && - contentType.contains(RegExp(r'^application\/dtmf-relay', - caseSensitive: false))) { + contentType.contains(RegExp(r'^application\/dtmf-relay', caseSensitive: false))) { RTCSession_DTMF.DTMF(this).init_incoming(request); } else if (contentType != null) { RTCSession_Info.Info(this).init_incoming(request); @@ -1439,14 +1367,14 @@ class RTCSession extends EventManager implements Owner { } // Called from DTMF handler. - void newDTMF(String originator, DTMF dtmf, dynamic request) { + void newDTMF(Originator originator, DTMF dtmf, dynamic request) { logger.d('newDTMF()'); emit(EventNewDTMF(originator: originator, dtmf: dtmf, request: request)); } // Called from Info handler. - void newInfo(String originator, Info info, dynamic request) { + void newInfo(Originator originator, Info info, dynamic request) { logger.d('newInfo()'); emit(EventNewInfo(originator: originator, info: info, request: request)); @@ -1470,10 +1398,8 @@ class RTCSession extends EventManager implements Owner { } // Another INVITE transaction is in progress. - if (_dialog!.uac_pending_reply == true || - _dialog!.uas_pending_reply == true) { - logger.d( - '_isReadyToReOffer() | there is another INVITE/UPDATE transaction in progress'); + if (_dialog!.uac_pending_reply == true || _dialog!.uas_pending_reply == true) { + logger.d('_isReadyToReOffer() | there is another INVITE/UPDATE transaction in progress'); return false; } @@ -1494,8 +1420,7 @@ class RTCSession extends EventManager implements Owner { await _connection!.dispose(); _connection = null; } catch (error) { - logger.e( - 'close() | error closing the RTCPeerConnection: ${error.toString()}'); + logger.e('close() | error closing the RTCPeerConnection: ${error.toString()}'); } } // Close local MediaStream if it was not given by the user. @@ -1576,7 +1501,7 @@ class RTCSession extends EventManager implements Owner { clearTimeout(_timers.invite2xxTimer); sendRequest(SipMethod.BYE); _ended( - 'remote', + Originator.remote, null, ErrorCause( cause: DartSIP_C.CausesType.NO_ACK, @@ -1609,8 +1534,8 @@ class RTCSession extends EventManager implements Owner { renegotiate(options: offerConstraints); } - Future _createRTCConnection(Map pcConfig, - Map rtcConstraints) async { + Future _createRTCConnection( + Map pcConfig, Map rtcConstraints) async { _connection = await createPeerConnection(pcConfig, rtcConstraints); _connection!.onIceConnectionState = (RTCIceConnectionState state) { // TODO(cloudwebrtc): Do more with different states. @@ -1620,8 +1545,7 @@ class RTCSession extends EventManager implements Owner { 'status_code': 408, 'reason_phrase': DartSIP_C.CausesType.RTP_TIMEOUT }); - } else if (state == - RTCIceConnectionState.RTCIceConnectionStateDisconnected) { + } else if (state == RTCIceConnectionState.RTCIceConnectionStateDisconnected) { _iceRestart(); } }; @@ -1636,15 +1560,13 @@ class RTCSession extends EventManager implements Owner { case 'unified-plan': _connection!.onTrack = (RTCTrackEvent event) { if (event.streams.isNotEmpty) { - emit(EventStream( - session: this, originator: 'remote', stream: event.streams[0])); + emit(EventStream(session: this, originator: Originator.remote, stream: event.streams[0])); } }; break; case 'plan-b': _connection!.onAddStream = (MediaStream stream) { - emit( - EventStream(session: this, originator: 'remote', stream: stream)); + emit(EventStream(session: this, originator: Originator.remote, stream: stream)); }; break; } @@ -1655,11 +1577,10 @@ class RTCSession extends EventManager implements Owner { } Future _createLocalDescription( - String type, Map? constraints) async { + SdpType type, Map? constraints) async { logger.d('createLocalDescription()'); _iceGatheringState ??= RTCIceGatheringState.RTCIceGatheringStateNew; - Completer completer = - Completer(); + Completer completer = Completer(); constraints = constraints ?? { @@ -1667,25 +1588,24 @@ class RTCSession extends EventManager implements Owner { 'optional': [], }; - List Function(RTCSessionDescription)> - modifiers = constraints['offerModifiers'] ?? + List Function(RTCSessionDescription)> modifiers = + constraints['offerModifiers'] ?? Function(RTCSessionDescription)>[]; constraints.remove('offerModifiers'); - if (type != 'offer' && type != 'answer') { - completer.completeError(Exceptions.TypeError( - 'createLocalDescription() | invalid type "$type"')); + if (type != SdpType.offer && type != SdpType.answer) { + completer + .completeError(Exceptions.TypeError('createLocalDescription() | invalid type "$type"')); } _rtcReady = false; late RTCSessionDescription desc; - if (type == 'offer') { + if (type == SdpType.offer) { try { desc = await _connection!.createOffer(constraints); } catch (error) { - logger.e( - 'emit "peerconnection:createofferfailed" [error:${error.toString()}]'); + logger.e('emit "peerconnection:createofferfailed" [error:${error.toString()}]'); emit(EventCreateOfferFailed(exception: error)); completer.completeError(error); } @@ -1693,8 +1613,7 @@ class RTCSession extends EventManager implements Owner { try { desc = await _connection!.createAnswer(constraints); } catch (error) { - logger.e( - 'emit "peerconnection:createanswerfailed" [error:${error.toString()}]'); + logger.e('emit "peerconnection:createanswerfailed" [error:${error.toString()}]'); emit(EventCreateAnswerFialed(exception: error)); completer.completeError(error); } @@ -1703,8 +1622,7 @@ class RTCSession extends EventManager implements Owner { // Add 'pc.onicencandidate' event handler to resolve on last candidate. bool finished = false; - for (Future Function(RTCSessionDescription) modifier - in modifiers) { + for (Future Function(RTCSessionDescription) modifier in modifiers) { desc = await modifier(desc); } @@ -1717,7 +1635,7 @@ class RTCSession extends EventManager implements Owner { _rtcReady = true; RTCSessionDescription? desc = await _connection!.getLocalDescription(); logger.d('emit "sdp"'); - emit(EventSdp(originator: 'local', type: type, sdp: desc!.sdp)); + emit(EventSdp(originator: Originator.local, type: type, sdp: desc!.sdp)); completer.complete(desc); } } @@ -1752,19 +1670,17 @@ class RTCSession extends EventManager implements Owner { await _connection!.setLocalDescription(desc); } catch (error) { _rtcReady = true; - logger.e( - 'emit "peerconnection:setlocaldescriptionfailed" [error:${error.toString()}]'); + logger.e('emit "peerconnection:setlocaldescriptionfailed" [error:${error.toString()}]'); emit(EventSetLocalDescriptionFailed(exception: error)); completer.completeError(error); } // Resolve right away if 'pc.iceGatheringState' is 'complete'. - if (_iceGatheringState == - RTCIceGatheringState.RTCIceGatheringStateComplete) { + if (_iceGatheringState == RTCIceGatheringState.RTCIceGatheringStateComplete) { _rtcReady = true; RTCSessionDescription? desc = await _connection!.getLocalDescription(); logger.d('emit "sdp"'); - emit(EventSdp(originator: 'local', type: type, sdp: desc!.sdp)); + emit(EventSdp(originator: Originator.local, type: type, sdp: desc!.sdp)); return desc; } @@ -1789,13 +1705,7 @@ class RTCSession extends EventManager implements Owner { early_dialog = Dialog(this, message, type, DialogStatus.STATUS_EARLY); } catch (error) { logger.d('$error'); - _failed( - 'remote', - message, - null, - null, - 500, - DartSIP_C.CausesType.INTERNAL_ERROR, + _failed(Originator.remote, message, null, null, 500, DartSIP_C.CausesType.INTERNAL_ERROR, 'Can\'t create Early Dialog'); return false; } @@ -1822,13 +1732,7 @@ class RTCSession extends EventManager implements Owner { return true; } catch (error) { logger.d(error.toString()); - _failed( - 'remote', - message, - null, - null, - 500, - DartSIP_C.CausesType.INTERNAL_ERROR, + _failed(Originator.remote, message, null, null, 500, DartSIP_C.CausesType.INTERNAL_ERROR, 'Can\'t create Confirmed Dialog'); return false; } @@ -1868,8 +1772,7 @@ class RTCSession extends EventManager implements Owner { _late_sdp = true; try { - RTCSessionDescription desc = - await _createLocalDescription('offer', _rtcOfferConstraints); + RTCSessionDescription desc = await _createLocalDescription(SdpType.offer, _rtcOfferConstraints); sendAnswer(desc.sdp); } catch (_) { request.reply(500); @@ -2004,8 +1907,7 @@ class RTCSession extends EventManager implements Owner { } } - Future _processInDialogSdpOffer( - IncomingRequest request) async { + Future _processInDialogSdpOffer(IncomingRequest request) async { logger.d('_processInDialogSdpOffer()'); Map? sdp = request.parseSDP(); @@ -2047,26 +1949,23 @@ class RTCSession extends EventManager implements Owner { 'facingMode': 'user', } }; - MediaStream localStream = - await navigator.mediaDevices.getUserMedia(mediaConstraints); + MediaStream localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints); if (localStream.getVideoTracks().isEmpty) { - logger.w( - 'Remote wants to upgrade to video but failed to get local video'); + logger.w('Remote wants to upgrade to video but failed to get local video'); } for (MediaStreamTrack track in localStream.getTracks()) { if (track.kind == 'video') { _connection!.addTrack(track, localStream); } } - emit( - EventStream(session: this, originator: 'local', stream: localStream)); + emit(EventStream(session: this, originator: Originator.local, stream: localStream)); } logger.d('emit "sdp"'); final String? processedSDP = _sdpOfferToWebRTC(request.body); - emit(EventSdp(originator: 'remote', type: 'offer', sdp: processedSDP)); + emit(EventSdp(originator: Originator.remote, type: SdpType.offer, sdp: processedSDP)); - RTCSessionDescription offer = RTCSessionDescription(processedSDP, 'offer'); + RTCSessionDescription offer = RTCSessionDescription(processedSDP, SdpType.offer.name); if (_status == C.STATUS_TERMINATED) { throw Exceptions.InvalidStateError('terminated'); @@ -2075,13 +1974,11 @@ class RTCSession extends EventManager implements Owner { await _connection!.setRemoteDescription(offer); } catch (error) { request.reply(488); - logger.e( - 'emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); + logger.e('emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); emit(EventSetRemoteDescriptionFailed(exception: error)); - throw Exceptions.TypeError( - 'peerconnection.setRemoteDescription() failed'); + throw Exceptions.TypeError('peerconnection.setRemoteDescription() failed'); } if (_status == C.STATUS_TERMINATED) { @@ -2090,10 +1987,10 @@ class RTCSession extends EventManager implements Owner { if (_remoteHold == true && hold == false) { _remoteHold = false; - _onunhold('remote'); + _onunhold(Originator.remote); } else if (_remoteHold == false && hold == true) { _remoteHold = true; - _onhold('remote'); + _onhold(Originator.remote); } // Create local description. @@ -2103,7 +2000,7 @@ class RTCSession extends EventManager implements Owner { } try { - return await _createLocalDescription('answer', _rtcAnswerConstraints); + return await _createLocalDescription(SdpType.answer, _rtcAnswerConstraints); } catch (_) { request.reply(500); throw Exceptions.TypeError('_createLocalDescription() failed'); @@ -2134,25 +2031,21 @@ class RTCSession extends EventManager implements Owner { ReferNotifier notifier = ReferNotifier(this, request.cseq); - bool accept2( - InitSuccessCallback? initCallback, Map options) { + bool accept2(InitSuccessCallback? initCallback, Map options) { initCallback = (initCallback is Function) ? initCallback : null; - if (_status != C.STATUS_WAITING_FOR_ACK && - _status != C.STATUS_CONFIRMED) { + if (_status != C.STATUS_WAITING_FOR_ACK && _status != C.STATUS_CONFIRMED) { return false; } RTCSession session = RTCSession(_ua); session.on(EventCallProgress(), (EventCallProgress event) { - notifier.notify( - event.response.status_code, event.response.reason_phrase); + notifier.notify(event.response.status_code, event.response.reason_phrase); }); session.on(EventCallAccepted(), (EventCallAccepted event) { - notifier.notify( - event.response.status_code, event.response.reason_phrase); + notifier.notify(event.response.status_code, event.response.reason_phrase); }); session.on(EventFailedUnderScore(), (EventFailedUnderScore data) { @@ -2164,8 +2057,7 @@ class RTCSession extends EventManager implements Owner { }); // Consider the Replaces header present in the Refer-To URI. if (request.refer_to.uri.hasHeader('replaces')) { - String replaces = utils - .decodeURIComponent(request.refer_to.uri.getHeader('replaces')); + String replaces = utils.decodeURIComponent(request.refer_to.uri.getHeader('replaces')); options['extraHeaders'] = utils.cloneArray(options['extraHeaders']); options['extraHeaders'].add('Replaces: $replaces'); @@ -2184,8 +2076,7 @@ class RTCSession extends EventManager implements Owner { emit(EventCallRefer( session: this, aor: request.refer_to.uri.toAor(), - accept: - (InitSuccessCallback initCallback, Map options) { + accept: (InitSuccessCallback initCallback, Map options) { accept2(initCallback, options); }, reject: (_) { @@ -2213,8 +2104,7 @@ class RTCSession extends EventManager implements Owner { id = int.tryParse(request.event!.params!['id'], radix: 10); referSubscriber = _referSubscribers[id]; } else if (_referSubscribers.length == 1) { - referSubscriber = - _referSubscribers[_referSubscribers.keys.toList()[0]]; + referSubscriber = _referSubscribers[_referSubscribers.keys.toList()[0]]; } else { request.reply(400, 'Missing event id parameter'); @@ -2247,8 +2137,7 @@ class RTCSession extends EventManager implements Owner { logger.d('receiveReplaces()'); bool accept(InitSuccessCallback initCallback) { - if (_status != C.STATUS_WAITING_FOR_ACK && - _status != C.STATUS_CONFIRMED) { + if (_status != C.STATUS_WAITING_FOR_ACK && _status != C.STATUS_CONFIRMED) { return false; } @@ -2315,25 +2204,18 @@ class RTCSession extends EventManager implements Owner { // A stream is given, var the app set events such as 'peerconnection' and 'connecting'. if (mediaStream != null) { stream = mediaStream; - emit(EventStream(session: this, originator: 'local', stream: stream)); + emit(EventStream(session: this, originator: Originator.local, stream: stream)); } // Request for user media access. - else if (mediaConstraints['audio'] != null || - mediaConstraints['video'] != null) { + else if (mediaConstraints['audio'] != null || mediaConstraints['video'] != null) { _localMediaStreamLocallyGenerated = true; try { stream = await navigator.mediaDevices.getUserMedia(mediaConstraints); - emit(EventStream(session: this, originator: 'local', stream: stream)); + emit(EventStream(session: this, originator: Originator.local, stream: stream)); } catch (error) { if (_status == C.STATUS_TERMINATED) { throw Exceptions.InvalidStateError('terminated'); } - _failed( - 'local', - null, - null, - null, - 500, - DartSIP_C.CausesType.USER_DENIED_MEDIA_ACCESS, + _failed(Originator.local, null, null, null, 500, DartSIP_C.CausesType.USER_DENIED_MEDIA_ACCESS, 'User Denied Media Access'); logger.e('emit "getusermediafailed" [error:${error.toString()}]'); emit(EventGetUserMediaFailed(exception: error)); @@ -2366,8 +2248,7 @@ class RTCSession extends EventManager implements Owner { // TODO(cloudwebrtc): should this be triggered here? _connecting(_request); try { - RTCSessionDescription desc = - await _createLocalDescription('offer', rtcOfferConstraints); + RTCSessionDescription desc = await _createLocalDescription(SdpType.offer, rtcOfferConstraints); if (_is_canceled || _status == C.STATUS_TERMINATED) { throw Exceptions.InvalidStateError('terminated'); } @@ -2383,7 +2264,7 @@ class RTCSession extends EventManager implements Owner { request_sender.send(); } catch (error, s) { logger.e(error.toString(), error: error, stackTrace: s); - _failed('local', null, null, null, 500, DartSIP_C.CausesType.WEBRTC_ERROR, + _failed(Originator.local, null, null, null, 500, DartSIP_C.CausesType.WEBRTC_ERROR, 'Can\'t create local SDP'); if (_status == C.STATUS_TERMINATED) { return; @@ -2404,8 +2285,7 @@ class RTCSession extends EventManager implements Owner { response.sdp = sdp_transform.parse(response.body ?? ''); /// Handle 2XX retransmissions and responses from forked requests. - if (_dialog != null && - (response.status_code >= 200 && response.status_code <= 299)) { + if (_dialog != null && (response.status_code >= 200 && response.status_code <= 299)) { /// /// If it is a retransmission from the endpoint that established /// the dialog, send an ACK @@ -2466,30 +2346,28 @@ class RTCSession extends EventManager implements Owner { } _status = C.STATUS_1XX_RECEIVED; - _progress('remote', response, int.parse(status_code)); + _progress(Originator.remote, response, int.parse(status_code)); if (response.body == null || response.body!.isEmpty) { return; } logger.d('emit "sdp"'); - emit(EventSdp(originator: 'remote', type: 'answer', sdp: response.body)); + emit(EventSdp(originator: Originator.remote, type: SdpType.answer, sdp: response.body)); - RTCSessionDescription answer = - RTCSessionDescription(response.body, 'answer'); + RTCSessionDescription answer = RTCSessionDescription(response.body, SdpType.answer.name); try { await _connection!.setRemoteDescription(answer); } catch (error) { - logger.e( - 'emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); + logger.e('emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); emit(EventSetRemoteDescriptionFailed(exception: error)); } } else if (utils.test2XX(status_code)) { if (response.body == null || response.body!.isEmpty) { _acceptAndTerminate(response, 400, DartSIP_C.CausesType.MISSING_SDP); - _failed('remote', null, null, response, 400, - DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION, 'Missing SDP'); + _failed(Originator.remote, null, null, response, 400, DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION, + 'Missing SDP'); return; } @@ -2497,8 +2375,8 @@ class RTCSession extends EventManager implements Owner { if (mediaPort == 0 && _ua.configuration.terminateOnAudioMediaPortZero) { _acceptAndTerminate(response, 400, DartSIP_C.CausesType.MISSING_SDP); - _failed('remote', null, null, response, 400, - DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION, 'Media port is zero'); + _failed(Originator.remote, null, null, response, 400, DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION, + 'Media port is zero'); return; } @@ -2510,30 +2388,20 @@ class RTCSession extends EventManager implements Owner { _status = C.STATUS_CONFIRMED; logger.d('emit "sdp"'); - emit(EventSdp(originator: 'remote', type: 'answer', sdp: response.body)); + emit(EventSdp(originator: Originator.remote, type: SdpType.answer, sdp: response.body)); - RTCSessionDescription answer = - RTCSessionDescription(response.body, 'answer'); + RTCSessionDescription answer = RTCSessionDescription(response.body, SdpType.answer.name); // Be ready for 200 with SDP after a 180/183 with SDP. // We created a SDP 'answer' for it, so check the current signaling state. - if (_connection!.signalingState == - RTCSignalingState.RTCSignalingStateStable || - _connection!.signalingState == - RTCSignalingState.RTCSignalingStateHaveLocalOffer) { + if (_connection!.signalingState == RTCSignalingState.RTCSignalingStateStable || + _connection!.signalingState == RTCSignalingState.RTCSignalingStateHaveLocalOffer) { try { - RTCSessionDescription offer = - await _connection!.createOffer(_rtcOfferConstraints!); + RTCSessionDescription offer = await _connection!.createOffer(_rtcOfferConstraints!); await _connection!.setLocalDescription(offer); } catch (error) { _acceptAndTerminate(response, 500, error.toString()); - _failed( - 'local', - null, - null, - response, - 500, - DartSIP_C.CausesType.WEBRTC_ERROR, + _failed(Originator.local, null, null, response, 500, DartSIP_C.CausesType.WEBRTC_ERROR, 'Can\'t create offer ${error.toString()}'); } } @@ -2542,21 +2410,19 @@ class RTCSession extends EventManager implements Owner { await _connection!.setRemoteDescription(answer); // Handle Session Timers. _handleSessionTimersInIncomingResponse(response); - _accepted('remote', response); + _accepted(Originator.remote, response); OutgoingRequest ack = sendRequest(SipMethod.ACK); - _confirmed('local', ack); + _confirmed(Originator.local, ack); } catch (error) { _acceptAndTerminate(response, 488, 'Not Acceptable Here'); - _failed('remote', null, null, response, 488, - DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION, 'Not Acceptable Here'); - logger.e( - 'emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); + _failed(Originator.remote, null, null, response, 488, DartSIP_C.CausesType.BAD_MEDIA_DESCRIPTION, + 'Not Acceptable Here'); + logger.e('emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); emit(EventSetRemoteDescriptionFailed(exception: error)); } } else { String cause = utils.sipErrorCause(response.status_code); - _failed('remote', null, null, response, response.status_code, cause, - response.reason_phrase); + _failed(Originator.remote, null, null, response, response.status_code, cause, response.reason_phrase); } } @@ -2568,29 +2434,24 @@ class RTCSession extends EventManager implements Owner { options = options ?? {}; - List extraHeaders = options['extraHeaders'] != null - ? utils.cloneArray(options['extraHeaders']) - : []; + List extraHeaders = + options['extraHeaders'] != null ? utils.cloneArray(options['extraHeaders']) : []; EventManager eventHandlers = options['eventHandlers'] ?? EventManager(); Map? rtcOfferConstraints = options['rtcOfferConstraints'] ?? _rtcOfferConstraints; - Map mediaConstraints = - options['mediaConstraints'] ?? {}; + Map mediaConstraints = options['mediaConstraints'] ?? {}; - dynamic sdpSemantics = - options['pcConfig']?['sdpSemantics'] ?? 'unified-plan'; + dynamic sdpSemantics = options['pcConfig']?['sdpSemantics'] ?? 'unified-plan'; bool hasVideo = (options['mediaConstraints']?['video'] ?? false) != false; try { - MediaStream localStream = - await navigator.mediaDevices.getUserMedia(mediaConstraints); + MediaStream localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints); _localMediaStreamLocallyGenerated = true; _localMediaStream = localStream; - emit( - EventStream(session: this, originator: 'local', stream: localStream)); + emit(EventStream(session: this, originator: Originator.local, stream: localStream)); switch (sdpSemantics) { case 'unified-plan': @@ -2612,13 +2473,7 @@ class RTCSession extends EventManager implements Owner { throw Exceptions.InvalidStateError('terminated'); } request.reply(480); - _failed( - 'local', - null, - null, - null, - 480, - DartSIP_C.CausesType.USER_DENIED_MEDIA_ACCESS, + _failed(Originator.local, null, null, null, 480, DartSIP_C.CausesType.USER_DENIED_MEDIA_ACCESS, 'User Denied Media Access'); logger.e('emit "getusermediafailed" [error:${error.toString()}]'); emit(EventGetUserMediaFailed(exception: error)); @@ -2665,28 +2520,25 @@ class RTCSession extends EventManager implements Owner { } logger.d('emit "sdp"'); - emit(EventSdp(originator: 'remote', type: 'answer', sdp: response.body)); + emit(EventSdp(originator: Originator.remote, type: SdpType.answer, sdp: response.body)); - RTCSessionDescription answer = - RTCSessionDescription(response.body, 'answer'); + RTCSessionDescription answer = RTCSessionDescription(response.body, SdpType.answer.name); try { await _connection!.setRemoteDescription(answer); eventHandlers.emit(EventSucceeded(response: response)); } catch (error) { onFailed(); - logger.e( - 'emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); + logger.e('emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); emit(EventSetRemoteDescriptionFailed(exception: error)); } } try { - RTCSessionDescription desc = - await _createLocalDescription('offer', rtcOfferConstraints); + RTCSessionDescription desc = await _createLocalDescription(SdpType.offer, rtcOfferConstraints); String? sdp = _mangleOffer(desc.sdp); logger.d('emit "sdp"'); - emit(EventSdp(originator: 'local', type: 'offer', sdp: sdp)); + emit(EventSdp(originator: Originator.local, type: SdpType.offer, sdp: sdp)); EventManager handlers = EventManager(); handlers.on(EventOnSuccessResponse(), (EventOnSuccessResponse event) { @@ -2706,11 +2558,8 @@ class RTCSession extends EventManager implements Owner { onDialogError(); // Do nothing because session ends. }); - sendRequest(SipMethod.INVITE, { - 'extraHeaders': extraHeaders, - 'body': sdp, - 'eventHandlers': handlers - }); + sendRequest(SipMethod.INVITE, + {'extraHeaders': extraHeaders, 'body': sdp, 'eventHandlers': handlers}); } catch (e, s) { logger.e(e.toString(), error: e, stackTrace: s); onFailed(); @@ -2725,12 +2574,10 @@ class RTCSession extends EventManager implements Owner { options = options ?? {}; - List extraHeaders = - utils.cloneArray(options['extraHeaders'] ?? []); + List extraHeaders = utils.cloneArray(options['extraHeaders'] ?? []); EventManager eventHandlers = options['eventHandlers'] ?? EventManager(); - Map rtcOfferConstraints = options['rtcOfferConstraints'] ?? - _rtcOfferConstraints ?? - {}; + Map rtcOfferConstraints = + options['rtcOfferConstraints'] ?? _rtcOfferConstraints ?? {}; bool sdpOffer = options['sdpOffer'] ?? false; bool succeeded = false; @@ -2771,19 +2618,16 @@ class RTCSession extends EventManager implements Owner { } logger.d('emit "sdp"'); - emit( - EventSdp(originator: 'remote', type: 'answer', sdp: response.body)); + emit(EventSdp(originator: Originator.remote, type: SdpType.answer, sdp: response.body)); - RTCSessionDescription answer = - RTCSessionDescription(response.body, 'answer'); + RTCSessionDescription answer = RTCSessionDescription(response.body, SdpType.answer.name); try { await _connection!.setRemoteDescription(answer); eventHandlers.emit(EventSucceeded(response: response)); } catch (error) { onFailed(error); - logger.e( - 'emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); + logger.e('emit "peerconnection:setremotedescriptionfailed" [error:${error.toString()}]'); emit(EventSetRemoteDescriptionFailed(exception: error)); } } @@ -2796,12 +2640,11 @@ class RTCSession extends EventManager implements Owner { if (sdpOffer) { extraHeaders.add('Content-Type: application/sdp'); try { - RTCSessionDescription desc = - await _createLocalDescription('offer', rtcOfferConstraints); + RTCSessionDescription desc = await _createLocalDescription(SdpType.offer, rtcOfferConstraints); String? sdp = _mangleOffer(desc.sdp); logger.d('emit "sdp"'); - emit(EventSdp(originator: 'local', type: 'offer', sdp: sdp)); + emit(EventSdp(originator: Originator.local, type: SdpType.offer, sdp: sdp)); EventManager handlers = EventManager(); handlers.on(EventOnSuccessResponse(), (EventOnSuccessResponse event) { @@ -2849,32 +2692,26 @@ class RTCSession extends EventManager implements Owner { onDialogError(); // Do nothing because session ends. }); - sendRequest(SipMethod.UPDATE, { - 'extraHeaders': extraHeaders, - 'eventHandlers': handlers - }); + sendRequest(SipMethod.UPDATE, + {'extraHeaders': extraHeaders, 'eventHandlers': handlers}); } } void _acceptAndTerminate(IncomingResponse? response, [int? status_code, String? reason_phrase]) async { - logger.d( - 'acceptAndTerminate() status_code: $status_code reason: $reason_phrase'); + logger.d('acceptAndTerminate() status_code: $status_code reason: $reason_phrase'); List extraHeaders = []; if (status_code != null) { - reason_phrase = - reason_phrase ?? DartSIP_C.REASON_PHRASE[status_code] ?? ''; - extraHeaders - .add('Reason: SIP ;cause=$status_code; text="$reason_phrase"'); + reason_phrase = reason_phrase ?? DartSIP_C.REASON_PHRASE[status_code] ?? ''; + extraHeaders.add('Reason: SIP ;cause=$status_code; text="$reason_phrase"'); } // An error on dialog creation will fire 'failed' event. if (_dialog != null || _createDialog(response, 'UAC')) { sendRequest(SipMethod.ACK); - sendRequest( - SipMethod.BYE, {'extraHeaders': extraHeaders}); + sendRequest(SipMethod.BYE, {'extraHeaders': extraHeaders}); } // Update session status. @@ -2938,7 +2775,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) { @@ -3091,7 +2928,7 @@ class RTCSession extends EventManager implements Owner { } } - void _newRTCSession(String originator, dynamic request) { + void _newRTCSession(Originator originator, dynamic request) { logger.d('newRTCSession()'); _ua.newRTCSession(originator: originator, session: this, request: request); } @@ -3102,52 +2939,47 @@ class RTCSession extends EventManager implements Owner { emit(EventCallConnecting(session: this, request: request)); } - void _progress(String originator, dynamic response, [int? status_code]) { + void _progress(Originator originator, dynamic response, [int? status_code]) { logger.d('session progress'); logger.d('emit "progress"'); ErrorCause errorCause = ErrorCause(status_code: status_code); emit(EventCallProgress( - session: this, - originator: originator, - response: response, - cause: errorCause)); + session: this, originator: originator, response: response, cause: errorCause)); } - void _accepted(String originator, [dynamic message]) { + void _accepted(Originator originator, [dynamic message]) { logger.d('session accepted'); _start_time = DateTime.now(); logger.d('emit "accepted"'); - emit(EventCallAccepted( - session: this, originator: originator, response: message)); + emit(EventCallAccepted(session: this, originator: originator, response: message)); } - void _confirmed(String originator, dynamic ack) { + void _confirmed(Originator originator, dynamic ack) { logger.d('session confirmed'); _is_confirmed = true; logger.d('emit "confirmed"'); emit(EventCallConfirmed(session: this, originator: originator, ack: ack)); } - void _ended(String originator, IncomingRequest? request, ErrorCause cause) { + void _ended(Originator originator, IncomingRequest? request, ErrorCause cause) { logger.d('session ended'); _end_time = DateTime.now(); _close(); logger.d('emit "ended"'); - emit(EventCallEnded( - session: this, originator: originator, request: request, cause: cause)); + emit(EventCallEnded(session: this, originator: originator, request: request, cause: cause)); } - void _failed(String originator, dynamic message, dynamic request, - dynamic response, int? status_code, String cause, String? reason_phrase) { + void _failed(Originator originator, dynamic message, dynamic request, dynamic response, + int? status_code, String cause, String? reason_phrase) { logger.d('session failed'); // Emit private '_failed' event first. logger.d('emit "_failed"'); - ErrorCause errorCause = ErrorCause( - cause: cause, status_code: status_code, reason_phrase: reason_phrase); + ErrorCause errorCause = + ErrorCause(cause: cause, status_code: status_code, reason_phrase: reason_phrase); emit(EventFailedUnderScore( originator: originator, @@ -3164,14 +2996,14 @@ class RTCSession extends EventManager implements Owner { response: response)); } - void _onhold(String originator) { + void _onhold(Originator originator) { logger.d('session onhold'); _setLocalMediaStatus(); logger.d('emit "hold"'); emit(EventCallHold(session: this, originator: originator)); } - void _onunhold(String originator) { + void _onunhold(Originator originator) { logger.d('session onunhold'); _setLocalMediaStatus(); logger.d('emit "unhold"'); diff --git a/lib/src/rtc_session/dtmf.dart b/lib/src/rtc_session/dtmf.dart index 1e6b5877..24f13f0f 100644 --- a/lib/src/rtc_session/dtmf.dart +++ b/lib/src/rtc_session/dtmf.dart @@ -1,14 +1,12 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; - import 'package:sip_ua/sip_ua.dart'; -import 'package:sip_ua/src/direction.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 { @@ -26,7 +24,7 @@ class DTMF extends EventManager { final rtc.RTCSession _session; DtmfMode? _mode; - CallDirection? _direction; + Direction? _direction; String? _tone; int? _duration; int? _interToneGap; @@ -37,14 +35,14 @@ class DTMF extends EventManager { int? get duration => _duration; - CallDirection? get direction => _direction; + Direction? get direction => _direction; void send(String tone, Map options) { if (tone == null) { throw Exceptions.TypeError('Not enough arguments'); } - _direction = CallDirection.outgoing; + _direction = Direction.outgoing; // Check RTCSession Status. if (_session.status != rtc.C.STATUS_CONFIRMED && @@ -52,9 +50,8 @@ class DTMF extends EventManager { throw Exceptions.InvalidStateError(_session.status); } - List extraHeaders = options['extraHeaders'] != null - ? Utils.cloneArray(options['extraHeaders']) - : []; + List extraHeaders = + options['extraHeaders'] != null ? Utils.cloneArray(options['extraHeaders']) : []; _eventHandlers = options['eventHandlers'] ?? EventManager(); @@ -71,8 +68,7 @@ class DTMF extends EventManager { if (_mode == DtmfMode.RFC2833) { RTCDTMFSender dtmfSender = _session.dtmfSender; - dtmfSender.insertDTMF(_tone!, - duration: _duration!, interToneGap: _interToneGap!); + dtmfSender.insertDTMF(_tone!, duration: _duration!, interToneGap: _interToneGap!); } else if (_mode == DtmfMode.INFO) { extraHeaders.add('Content-Type: application/dtmf-relay'); @@ -80,16 +76,16 @@ class DTMF extends EventManager { body += 'Duration=$_duration'; - _session.newDTMF('local', this, _request); + _session.newDTMF(Originator.local, this, _request); EventManager handlers = EventManager(); handlers.on(EventOnSuccessResponse(), (EventOnSuccessResponse event) { - emit(EventSucceeded(originator: 'remote', response: event.response)); + emit(EventSucceeded(originator: Originator.remote, response: event.response)); }); handlers.on(EventOnErrorResponse(), (EventOnErrorResponse event) { _eventHandlers.emit(EventOnFialed()); emit(EventOnFialed()); - emit(EventCallFailed(originator: 'remote', response: event.response)); + emit(EventCallFailed(originator: Originator.remote, response: event.response)); }); handlers.on(EventOnRequestTimeout(), (EventOnRequestTimeout event) { _session.onRequestTimeout(); @@ -102,11 +98,8 @@ class DTMF extends EventManager { _session.onDialogError(); }); - _session.sendRequest(SipMethod.INFO, { - 'extraHeaders': extraHeaders, - 'eventHandlers': handlers, - 'body': body - }); + _session.sendRequest(SipMethod.INFO, + {'extraHeaders': extraHeaders, 'eventHandlers': handlers, 'body': body}); } } @@ -114,7 +107,7 @@ class DTMF extends EventManager { String reg_tone = r'^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*'; String reg_duration = r'^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*'; - _direction = CallDirection.incoming; + _direction = Direction.incoming; _request = request; request.reply(200); @@ -129,8 +122,7 @@ class DTMF extends EventManager { } if (body.length >= 2) { if (body[1].contains(RegExp(reg_duration))) { - _duration = - int.tryParse(body[1].replaceAll(reg_duration, '\$2'), radix: 10); + _duration = int.tryParse(body[1].replaceAll(reg_duration, '\$2'), radix: 10); } } } @@ -140,7 +132,7 @@ class DTMF extends EventManager { if (_tone == null) { logger.d('invalid INFO DTMF received, discarded'); } else { - _session.newDTMF('remote', this, request); + _session.newDTMF(Originator.remote, this, request); } } } diff --git a/lib/src/rtc_session/info.dart b/lib/src/rtc_session/info.dart index 289acad9..0b38d6e2 100644 --- a/lib/src/rtc_session/info.dart +++ b/lib/src/rtc_session/info.dart @@ -1,5 +1,6 @@ -import 'package:sip_ua/src/direction.dart'; +import 'package:sip_ua/src/enums.dart'; import 'package:sip_ua/src/sip_message.dart'; + import '../constants.dart'; import '../event_manager/event_manager.dart'; import '../event_manager/internal_events.dart'; @@ -11,7 +12,7 @@ class Info extends EventManager { Info(this._session); final rtc.RTCSession _session; - CallDirection? _direction; + Direction? _direction; String? _contentType; String? _body; IncomingRequest? _request; @@ -20,10 +21,10 @@ class Info extends EventManager { String? get body => _body; - CallDirection? get direction => _direction; + Direction? get direction => _direction; void send(String contentType, String body, Map options) { - _direction = CallDirection.outgoing; + _direction = Direction.outgoing; if (contentType == null) { throw Exceptions.TypeError('Not enough arguments'); @@ -42,14 +43,14 @@ class Info extends EventManager { extraHeaders.add('Content-Type: $contentType'); - _session.newInfo('local', this, _request); + _session.newInfo(Originator.local, this, _request); EventManager handlers = EventManager(); handlers.on(EventOnSuccessResponse(), (EventOnSuccessResponse event) { - emit(EventSucceeded(originator: 'remote', response: event.response)); + emit(EventSucceeded(originator: Originator.remote, response: event.response)); }); handlers.on(EventOnErrorResponse(), (EventOnErrorResponse event) { - emit(EventCallFailed(originator: 'remote', response: event.response)); + emit(EventCallFailed(originator: Originator.remote, response: event.response)); }); handlers.on(EventOnTransportError(), (EventOnTransportError event) { _session.onTransportError(); @@ -61,15 +62,12 @@ class Info extends EventManager { _session.onDialogError(); }); - _session.sendRequest(SipMethod.INFO, { - 'extraHeaders': extraHeaders, - 'eventHandlers': handlers, - 'body': body - }); + _session.sendRequest(SipMethod.INFO, + {'extraHeaders': extraHeaders, 'eventHandlers': handlers, 'body': body}); } void init_incoming(IncomingRequest request) { - _direction = CallDirection.incoming; + _direction = Direction.incoming; _request = request; request.reply(200); @@ -77,6 +75,6 @@ class Info extends EventManager { _contentType = request.getHeader('content-type'); _body = request.body; - _session.newInfo('remote', this, request); + _session.newInfo(Originator.remote, this, request); } } diff --git a/lib/src/sip_ua_helper.dart b/lib/src/sip_ua_helper.dart index 373c0d07..40e9eaee 100644 --- a/lib/src/sip_ua_helper.dart +++ b/lib/src/sip_ua_helper.dart @@ -4,11 +4,11 @@ import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:logger/logger.dart'; import 'package:sdp_transform/sdp_transform.dart' as sdp_transform; import 'package:sip_ua/sip_ua.dart'; -import 'package:sip_ua/src/direction.dart'; 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'; @@ -17,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'; @@ -35,8 +34,7 @@ class SIPUAHelper extends EventManager { UaSettings? _uaSettings; final Map _calls = {}; - RegistrationState _registerState = - RegistrationState(state: RegistrationStateEnum.NONE); + RegistrationState _registerState = RegistrationState(state: RegistrationStateEnum.NONE); /// Sets the logging level for the default logger. Has no effect if custom logger is supplied. set loggingLevel(Level loggingLevel) => Log.loggingLevel = loggingLevel; @@ -58,8 +56,7 @@ class SIPUAHelper extends EventManager { bool get connecting { if (_ua == null) return false; - if (_ua!.socketTransport != null) - return _ua!.socketTransport!.isConnecting(); + if (_ua!.socketTransport != null) return _ua!.socketTransport!.isConnecting(); return false; } @@ -75,8 +72,7 @@ class SIPUAHelper extends EventManager { } void register() { - assert(_ua != null, - 'register called but not started, you must call start first.'); + assert(_ua != null, 'register called but not started, you must call start first.'); _ua!.register(); } @@ -109,8 +105,7 @@ class SIPUAHelper extends EventManager { _ua!.call(target, options); return true; } else { - logger.e('Not connected, you will need to register.', - stackTrace: StackTraceNJ()); + logger.e('Not connected, you will need to register.', stackTrace: StackTraceNJ()); } return false; } @@ -144,9 +139,8 @@ class SIPUAHelper extends EventManager { _settings.sockets = []; if (uaSettings.transportType == TransportType.TCP) { - SIPUATcpSocket socket = SIPUATcpSocket( - uaSettings.host ?? '0.0.0.0', uaSettings.port ?? '5060', - messageDelay: 1); + SIPUATcpSocket socket = + SIPUATcpSocket(uaSettings.host ?? '0.0.0.0', uaSettings.port ?? '5060', messageDelay: 1); _settings.sockets!.add(socket); } @@ -170,88 +164,75 @@ class SIPUAHelper extends EventManager { _settings.register = uaSettings.register; _settings.register_expires = uaSettings.register_expires; _settings.register_extra_headers = uaSettings.registerParams.extraHeaders; - _settings.register_extra_contact_uri_params = - uaSettings.registerParams.extraContactUriParams; + _settings.register_extra_contact_uri_params = uaSettings.registerParams.extraContactUriParams; _settings.dtmf_mode = uaSettings.dtmfMode; _settings.session_timers = uaSettings.sessionTimers; _settings.ice_gathering_timeout = uaSettings.iceGatheringTimeout; - _settings.session_timers_refresh_method = - uaSettings.sessionTimersRefreshMethod; + _settings.session_timers_refresh_method = uaSettings.sessionTimersRefreshMethod; _settings.instance_id = uaSettings.instanceId; _settings.registrar_server = uaSettings.registrarServer; _settings.contact_uri = uaSettings.contact_uri; - _settings.connection_recovery_max_interval = - uaSettings.connectionRecoveryMaxInterval; - _settings.connection_recovery_min_interval = - uaSettings.connectionRecoveryMinInterval; - _settings.terminateOnAudioMediaPortZero = - uaSettings.terminateOnMediaPortZero; + _settings.connection_recovery_max_interval = uaSettings.connectionRecoveryMaxInterval; + _settings.connection_recovery_min_interval = uaSettings.connectionRecoveryMinInterval; + _settings.terminateOnAudioMediaPortZero = uaSettings.terminateOnMediaPortZero; try { _ua = UA(_settings); _ua!.on(EventSocketConnecting(), (EventSocketConnecting event) { logger.d('connecting => $event'); - _notifyTransportStateListeners( - TransportState(TransportStateEnum.CONNECTING)); + _notifyTransportStateListeners(TransportState(TransportStateEnum.CONNECTING)); }); _ua!.on(EventSocketConnected(), (EventSocketConnected event) { logger.d('connected => $event'); - _notifyTransportStateListeners( - TransportState(TransportStateEnum.CONNECTED)); + _notifyTransportStateListeners(TransportState(TransportStateEnum.CONNECTED)); }); _ua!.on(EventSocketDisconnected(), (EventSocketDisconnected event) { logger.d('disconnected => ${event.cause}'); - _notifyTransportStateListeners(TransportState( - TransportStateEnum.DISCONNECTED, - cause: event.cause)); + _notifyTransportStateListeners( + TransportState(TransportStateEnum.DISCONNECTED, cause: event.cause)); }); _ua!.on(EventRegistered(), (EventRegistered event) { logger.d('registered => ${event.cause}'); - _registerState = RegistrationState( - state: RegistrationStateEnum.REGISTERED, cause: event.cause); + _registerState = + RegistrationState(state: RegistrationStateEnum.REGISTERED, cause: event.cause); _notifyRegistrationStateListeners(_registerState); }); _ua!.on(EventUnregister(), (EventUnregister event) { logger.d('unregistered => ${event.cause}'); - _registerState = RegistrationState( - state: RegistrationStateEnum.UNREGISTERED, cause: event.cause); + _registerState = + RegistrationState(state: RegistrationStateEnum.UNREGISTERED, cause: event.cause); _notifyRegistrationStateListeners(_registerState); }); _ua!.on(EventRegistrationFailed(), (EventRegistrationFailed event) { logger.d('registrationFailed => ${event.cause}'); - _registerState = RegistrationState( - state: RegistrationStateEnum.REGISTRATION_FAILED, - cause: event.cause); + _registerState = + RegistrationState(state: RegistrationStateEnum.REGISTRATION_FAILED, cause: event.cause); _notifyRegistrationStateListeners(_registerState); }); _ua!.on(EventNewRTCSession(), (EventNewRTCSession event) { logger.d('newRTCSession => $event'); RTCSession session = event.session!; - if (session.direction == CallDirection.incoming) { + if (session.direction == Direction.incoming) { // Set event handlers. - session.addAllEventHandlers( - buildCallOptions()['eventHandlers'] as EventManager); + session.addAllEventHandlers(buildCallOptions()['eventHandlers'] as EventManager); } bool hasVideo = session.data?['video'] ?? false; - _calls[event.id] = - Call(event.id, session, CallStateEnum.CALL_INITIATION, !hasVideo); + _calls[event.id] = Call(event.id, session, CallStateEnum.CALL_INITIATION, !hasVideo); _notifyCallStateListeners( - event, - CallState(CallStateEnum.CALL_INITIATION, - video: session.data?['video'])); + event, CallState(CallStateEnum.CALL_INITIATION, video: session.data?['video'])); }); _ua!.on(EventNewMessage(), (EventNewMessage event) { logger.d('newMessage => $event'); //Only notify incoming message to listener - if (event.message!.direction == CallDirection.incoming) { + if (event.message!.direction == Direction.incoming) { SIPMessageRequest message = SIPMessageRequest(event.message, event.originator, event.request); _notifyNewMessageListeners(message); @@ -267,8 +248,7 @@ class SIPUAHelper extends EventManager { /// Build the call options. /// You may override this method in a custom SIPUAHelper class in order to /// modify the options to your needs. - Map buildCallOptions([bool voiceonly = false]) => - _options(voiceonly); + Map buildCallOptions([bool voiceonly = false]) => _options(voiceonly); Map _options([bool voiceonly = false]) { // Register callbacks to desired call events @@ -279,25 +259,19 @@ class SIPUAHelper extends EventManager { }); handlers.on(EventCallProgress(), (EventCallProgress event) { logger.d('call is in progress'); - _notifyCallStateListeners( - event, - CallState(CallStateEnum.PROGRESS, - originator: event.originator, cause: event.cause)); + _notifyCallStateListeners(event, + CallState(CallStateEnum.PROGRESS, originator: event.originator, cause: event.cause)); }); handlers.on(EventCallFailed(), (EventCallFailed event) { logger.d('call failed with cause: ${event.cause}'); _notifyCallStateListeners( - event, - CallState(CallStateEnum.FAILED, - originator: event.originator, cause: event.cause)); + event, CallState(CallStateEnum.FAILED, originator: event.originator, cause: event.cause)); _calls.remove(event.id); }); handlers.on(EventCallEnded(), (EventCallEnded event) { logger.d('call ended with cause: ${event.cause}'); _notifyCallStateListeners( - event, - CallState(CallStateEnum.ENDED, - originator: event.originator, cause: event.cause)); + event, CallState(CallStateEnum.ENDED, originator: event.originator, cause: event.cause)); _calls.remove(event.id); }); handlers.on(EventCallAccepted(), (EventCallAccepted event) { @@ -310,8 +284,7 @@ class SIPUAHelper extends EventManager { }); handlers.on(EventCallHold(), (EventCallHold event) { logger.d('call hold'); - _notifyCallStateListeners( - event, CallState(CallStateEnum.HOLD, originator: event.originator)); + _notifyCallStateListeners(event, CallState(CallStateEnum.HOLD, originator: event.originator)); }); handlers.on(EventCallUnhold(), (EventCallUnhold event) { logger.d('call unhold'); @@ -321,24 +294,18 @@ class SIPUAHelper extends EventManager { handlers.on(EventCallMuted(), (EventCallMuted event) { logger.d('call muted'); _notifyCallStateListeners( - event, - CallState(CallStateEnum.MUTED, - audio: event.audio, video: event.video)); + event, CallState(CallStateEnum.MUTED, audio: event.audio, video: event.video)); }); handlers.on(EventCallUnmuted(), (EventCallUnmuted event) { logger.d('call unmuted'); _notifyCallStateListeners( - event, - CallState(CallStateEnum.UNMUTED, - audio: event.audio, video: event.video)); + event, CallState(CallStateEnum.UNMUTED, audio: event.audio, video: event.video)); }); handlers.on(EventStream(), (EventStream event) async { // Waiting for callscreen ready. Timer(Duration(milliseconds: 100), () { - _notifyCallStateListeners( - event, - CallState(CallStateEnum.STREAM, - stream: event.stream, originator: event.originator)); + _notifyCallStateListeners(event, + CallState(CallStateEnum.STREAM, stream: event.stream, originator: event.originator)); }); }); @@ -348,8 +315,7 @@ class SIPUAHelper extends EventManager { }); handlers.on(EventCallRefer(), (EventCallRefer refer) async { logger.d('Refer received, Transfer current call to => ${refer.aor}'); - _notifyCallStateListeners( - refer, CallState(CallStateEnum.REFER, refer: refer)); + _notifyCallStateListeners(refer, CallState(CallStateEnum.REFER, refer: refer)); //Always accept. refer.accept((RTCSession session) { logger.d('session initialized.'); @@ -362,8 +328,7 @@ class SIPUAHelper extends EventManager { 'pcConfig': { 'sdpSemantics': 'unified-plan', 'iceTransportPolicy': - (_uaSettings?.iceTransportPolicy ?? IceTransportPolicy.ALL) - .toParameterString(), + (_uaSettings?.iceTransportPolicy ?? IceTransportPolicy.ALL).toParameterString(), 'iceServers': _uaSettings?.iceServers }, 'mediaConstraints': { @@ -428,8 +393,7 @@ class SIPUAHelper extends EventManager { _ua!.terminateSessions(options); } - final Set _sipUaHelperListeners = - {}; + final Set _sipUaHelperListeners = {}; void addSipUaHelperListener(SipUaHelperListener listener) { _sipUaHelperListeners.add(listener); @@ -556,8 +520,7 @@ class Call { if (peerConnection != null) { for (MediaStream? stream in peerConnection!.getLocalStreams()) { if (stream == null) return; - logger.d( - 'Stopping local stream with tracks: ${stream.getTracks().length}'); + logger.d('Stopping local stream with tracks: ${stream.getTracks().length}'); for (MediaStreamTrack track in stream.getTracks()) { logger.d('Stopping track: ${track.kind}${track.id} '); track.stop(); @@ -565,8 +528,7 @@ class Call { } for (MediaStream? stream in peerConnection!.getRemoteStreams()) { if (stream == null) return; - logger.d( - 'Stopping remote stream with tracks: ${stream.getTracks().length}'); + logger.d('Stopping remote stream with tracks: ${stream.getTracks().length}'); for (MediaStreamTrack track in stream.getTracks()) { logger.d('Stopping track: ${track.kind}${track.id} '); track.stop(); @@ -622,23 +584,19 @@ class Call { options?.putIfAbsent('body', () => body); - _session.sendRequest(DartSIP_C.SipMethod.MESSAGE, - options ?? {'body': body}); + _session.sendRequest(DartSIP_C.SipMethod.MESSAGE, options ?? {'body': body}); } String? get remote_display_name { - assert(_session != null, - 'ERROR(get remote_identity): rtc session is invalid!'); - if (_session.remote_identity != null && - _session.remote_identity!.display_name != null) { + assert(_session != null, 'ERROR(get remote_identity): rtc session is invalid!'); + if (_session.remote_identity != null && _session.remote_identity!.display_name != null) { return _session.remote_identity!.display_name; } return ''; } String? get remote_identity { - assert(_session != null, - 'ERROR(get remote_identity): rtc session is invalid!'); + assert(_session != null, 'ERROR(get remote_identity): rtc session is invalid!'); if (_session.remote_identity != null && _session.remote_identity!.uri != null && _session.remote_identity!.uri!.user != null) { @@ -648,8 +606,7 @@ class Call { } String? get local_identity { - assert( - _session != null, 'ERROR(get local_identity): rtc session is invalid!'); + assert(_session != null, 'ERROR(get local_identity): rtc session is invalid!'); if (_session.local_identity != null && _session.local_identity!.uri != null && _session.local_identity!.uri!.user != null) { @@ -658,7 +615,7 @@ class Call { return ''; } - CallDirection? get direction { + Direction? get direction { assert(_session != null, 'ERROR(get direction): rtc session is invalid!'); return _session.direction; } @@ -668,8 +625,7 @@ class Call { bool get remote_has_video => _peerHasMediaLine('video'); bool _peerHasMediaLine(String media) { - assert( - _session != null, 'ERROR(_peerHasMediaLine): rtc session is invalid!'); + assert(_session != null, 'ERROR(_peerHasMediaLine): rtc session is invalid!'); if (_session.request == null) { return false; } @@ -699,15 +655,10 @@ class Call { class CallState { CallState(this.state, - {this.originator, - this.audio, - this.video, - this.stream, - this.cause, - this.refer}); + {this.originator, this.audio, this.video, this.stream, this.cause, this.refer}); CallStateEnum state; ErrorCause? cause; - String? originator; + Originator? originator; bool? audio; bool? video; MediaStream? stream; @@ -743,7 +694,7 @@ class TransportState { class SIPMessageRequest { SIPMessageRequest(this.message, this.originator, this.request); dynamic request; - String? originator; + Originator? originator; Message? message; } diff --git a/lib/src/ua.dart b/lib/src/ua.dart index 92e581bb..e7310f6b 100644 --- a/lib/src/ua.dart +++ b/lib/src/ua.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:sip_ua/src/enums.dart'; import 'package:sip_ua/src/transport_type.dart'; import 'package:sip_ua/src/transports/socket_interface.dart'; import 'config.dart' as config; @@ -501,7 +502,7 @@ class UA extends EventManager { /** * Message */ - void newMessage(Message message, String originator, dynamic request) { + void newMessage(Message message, Originator originator, dynamic request) { if (_stopping) { return; } @@ -513,7 +514,7 @@ class UA extends EventManager { /** * Options */ - void newOptions(Options message, String originator, dynamic request) { + void newOptions(Options message, Originator originator, dynamic request) { if (_stopping) { return; } @@ -547,7 +548,7 @@ class UA extends EventManager { * RTCSession */ void newRTCSession( - {required RTCSession session, String? originator, dynamic request}) { + {required RTCSession session, Originator? originator, dynamic request}) { _sessions[session.id] = session; emit(EventNewRTCSession( session: session, originator: originator, request: request));