Skip to content

Commit ccc420e

Browse files
cloudwebrtcAleksandar-Argead
authored andcommitted
release: 1.0.1. (flutter-webrtc#508)
* release: 1.0.1. * ci. Add initial TLS support Update register Revert formatting
1 parent 4e8e03f commit ccc420e

File tree

9 files changed

+302
-7
lines changed

9 files changed

+302
-7
lines changed

.github/workflows/dart.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ name: Build
33

44
on:
55
push:
6-
branches: [ master ]
6+
branches: [ main ]
77
pull_request:
8-
branches: [ master ]
8+
branches: [ main ]
99

1010
jobs:
1111
test:

.github/workflows/publish.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ jobs:
2323
run: flutter analyze
2424
- name: Dart Test Check
2525
run: flutter test
26-
#- name: Check Publish Warnings
27-
# run: dart pub publish --dry-run
26+
- name: Check Publish Warnings
27+
run: dart pub publish --dry-run
2828
- name: Publish
2929
uses: k-paxian/[email protected]
3030
with:

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# Changelog
22

33
--------------------------------------------
4+
[1.0.1] -2024.12.19
5+
6+
* make sure the session terminates by @victortive in https://github.com/flutter-webrtc/dart-sip-ua/pull/485
7+
* Hold and video upgrade fixed by @mikaelwills in https://github.com/flutter-webrtc/dart-sip-ua/pull/503
8+
* sip_ua_helper: add sendOptions by @eschmidbauer in https://github.com/flutter-webrtc/dart-sip-ua/pull/476
9+
* Update callscreen.dart by @HVaidehi in https://github.com/flutter-webrtc/dart-sip-ua/pull/427
10+
11+
412
[1.0.0] - 2024.08.24
513

614
* allow to change UA uri in runtime (#425)

example/lib/src/register.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ class _MyRegisterWidget extends State<RegisterWidget>
194194
textAlign: TextAlign.center,
195195
),
196196
],
197-
if (_selectedTransport == TransportType.TCP) ...[
197+
if (_selectedTransport != TransportType.WS) ...[
198198
Text('Port', style: TextStyle(color: textLabelColor)),
199199
SizedBox(height: 5),
200200
TextFormField(
@@ -296,6 +296,13 @@ class _MyRegisterWidget extends State<RegisterWidget>
296296
_selectedTransport = value!;
297297
})),
298298
child: Text("WS")),
299+
RadioMenuButton<TransportType>(
300+
value: TransportType.TLS,
301+
groupValue: _selectedTransport,
302+
onChanged: ((value) => setState(() {
303+
_selectedTransport = value!;
304+
})),
305+
child: Text("TLS")),
299306
],
300307
),
301308
],

lib/src/sip_ua_helper.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'dart:async';
55
import 'package:flutter_webrtc/flutter_webrtc.dart';
66
import 'package:logger/logger.dart';
77
import 'package:sdp_transform/sdp_transform.dart' as sdp_transform;
8+
import 'package:sip_ua/src/transports/tls_socket.dart';
89

910
// Project imports:
1011
import 'package:sip_ua/src/uri.dart';
@@ -158,6 +159,13 @@ class SIPUAHelper extends EventManager {
158159
_settings.sockets!.add(socket);
159160
}
160161

162+
if (uaSettings.transportType == TransportType.TLS) {
163+
SIPUATlsSocket socket = SIPUATlsSocket(
164+
uaSettings.host ?? '0.0.0.0', uaSettings.port ?? '5061',
165+
messageDelay: 1);
166+
_settings.sockets!.add(socket);
167+
}
168+
161169
if (uaSettings.transportType == TransportType.WS) {
162170
SIPUAWebSocket socket = SIPUAWebSocket(
163171
uaSettings.webSocketUrl ?? 'wss://tryit.jssip.net:10443',

lib/src/transport_type.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
enum TransportType { TCP, WS }
1+
enum TransportType { TCP, WS, TLS }

lib/src/transports/tls_socket.dart

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import 'dart:io';
2+
import 'package:sip_ua/src/transports/tls_socket_impl.dart';
3+
4+
import '../../sip_ua.dart';
5+
import '../logger.dart';
6+
import 'socket_interface.dart';
7+
8+
class SIPUATlsSocket extends SIPUASocketInterface {
9+
SIPUATlsSocket(String host, String port,
10+
{required int messageDelay,
11+
TcpSocketSettings? tcpSocketSettings,
12+
int? weight})
13+
: _messageDelay = messageDelay {
14+
15+
String transportScheme = 'tls';
16+
_weight = weight;
17+
_host = host;
18+
_port = port;
19+
20+
_sip_uri = '$_tlsSocketProtocol:$host:$port;transport=$transportScheme';
21+
_via_transport = transportScheme.toUpperCase();
22+
_tcpSocketSettings = tcpSocketSettings ?? TcpSocketSettings();
23+
}
24+
25+
final int _messageDelay;
26+
27+
String? _host;
28+
String? _port;
29+
String? _sip_uri;
30+
late String _via_transport;
31+
final String _tlsSocketProtocol = 'sip';
32+
SIPUATlsSocketImpl? _tlsSocketImpl;
33+
bool _closed = false;
34+
bool _connected = false;
35+
bool _connecting = false;
36+
int? _weight;
37+
int? status;
38+
late TcpSocketSettings _tcpSocketSettings;
39+
40+
@override
41+
String get via_transport => _via_transport;
42+
43+
@override
44+
set via_transport(String value) {
45+
_via_transport = value.toUpperCase();
46+
}
47+
48+
@override
49+
int? get weight => _weight;
50+
51+
@override
52+
String? get sip_uri => _sip_uri;
53+
54+
String? get host => _host;
55+
56+
String? get port => _port;
57+
58+
@override
59+
void connect() async {
60+
print('connect()');
61+
62+
if (_host == null) {
63+
throw AssertionError('Invalid argument: _host');
64+
}
65+
if (_port == null) {
66+
throw AssertionError('Invalid argument: _port');
67+
}
68+
69+
if (isConnected()) {
70+
print('TLSSocket $_host:$_port is already connected');
71+
return;
72+
} else if (isConnecting()) {
73+
print('TLSSocket $_host:$_port is connecting');
74+
return;
75+
}
76+
if (_tlsSocketImpl != null) {
77+
disconnect();
78+
}
79+
print('connecting to TLSSocket $_host:$_port');
80+
_connecting = true;
81+
try {
82+
_tlsSocketImpl =
83+
SIPUATlsSocketImpl(_messageDelay, _host ?? '0.0.0.0', _port ?? '5061');
84+
85+
_tlsSocketImpl!.onOpen = () {
86+
_closed = false;
87+
_connected = true;
88+
_connecting = false;
89+
print('TLS Socket is now connected');
90+
_onOpen();
91+
};
92+
93+
_tlsSocketImpl!.onData = (dynamic data) {
94+
_onMessage(data);
95+
};
96+
97+
_tlsSocketImpl!.onClose = (int? closeCode, String? closeReason) {
98+
print('Closed [$closeCode, $closeReason]!');
99+
_connected = false;
100+
_connecting = false;
101+
_onClose(true, closeCode, closeReason);
102+
};
103+
104+
_tlsSocketImpl!.connect(
105+
protocols: <String>[_tlsSocketProtocol],
106+
tcpSocketSettings: _tcpSocketSettings);
107+
} catch (e, s) {
108+
logger.e(e.toString(), stackTrace: s);
109+
_connected = false;
110+
_connecting = false;
111+
print('TLSSocket error: $e');
112+
}
113+
}
114+
115+
@override
116+
void disconnect() {
117+
print('disconnect()');
118+
if (_closed) return;
119+
_closed = true;
120+
_connected = false;
121+
_connecting = false;
122+
_onClose(true, 0, 'Client sent disconnect');
123+
try {
124+
if (_tlsSocketImpl != null) {
125+
_tlsSocketImpl!.close();
126+
}
127+
} catch (error) {
128+
logger.e('close() | error closing the TLSSocket: $error');
129+
}
130+
}
131+
132+
@override
133+
bool send(dynamic message) {
134+
print('send() $message');
135+
if (_closed) {
136+
throw 'transport closed';
137+
}
138+
try {
139+
_tlsSocketImpl!.send(message);
140+
return true;
141+
} catch (error) {
142+
logger.e('send() | error sending message: $error');
143+
rethrow;
144+
}
145+
}
146+
147+
@override
148+
bool isConnected() => _connected;
149+
150+
void _onOpen() {
151+
print('TLSSocket $_host:$port connected');
152+
onconnect!();
153+
}
154+
155+
void _onClose(bool wasClean, int? code, String? reason) {
156+
print('TLSSocket $_host:$port closed $reason');
157+
if (wasClean == false) {
158+
print('TLSSocket abrupt disconnection');
159+
}
160+
ondisconnect!(this, !wasClean, code, reason);
161+
}
162+
163+
void _onMessage(dynamic data) {
164+
print('Received TLSSocket data');
165+
if (data != null) {
166+
if (data.toString().trim().isNotEmpty) {
167+
ondata!(data);
168+
} else {
169+
print('Received and ignored empty packet');
170+
}
171+
}
172+
}
173+
174+
@override
175+
bool isConnecting() => _connecting;
176+
177+
@override
178+
String? get url {
179+
if (_host == null || _port == null) {
180+
return null;
181+
}
182+
return '$_host:$_port';
183+
}
184+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import 'dart:async';
2+
import 'dart:convert';
3+
import 'dart:io';
4+
import 'dart:math';
5+
6+
import '../logger.dart';
7+
import '../sip_ua_helper.dart';
8+
9+
typedef OnMessageCallback = void Function(dynamic msg);
10+
typedef OnCloseCallback = void Function(int? code, String? reason);
11+
typedef OnOpenCallback = void Function();
12+
13+
class SIPUATlsSocketImpl {
14+
SIPUATlsSocketImpl(this.messageDelay, this._host, this._port);
15+
16+
final String _host;
17+
final String _port;
18+
19+
/// Use SecureSocket for TLS connections.
20+
SecureSocket? _socket;
21+
OnOpenCallback? onOpen;
22+
OnMessageCallback? onData;
23+
OnCloseCallback? onClose;
24+
final int messageDelay;
25+
26+
/// Establishes a secure TLS connection.
27+
void connect({
28+
Iterable<String>? protocols,
29+
required TcpSocketSettings tcpSocketSettings,
30+
}) async {
31+
handleQueue();
32+
logger.i('connect TLS $_host:$_port');
33+
try {
34+
_socket = await SecureSocket.connect(
35+
_host,
36+
int.parse(_port),
37+
onBadCertificate: (X509Certificate certificate) {
38+
// WARNING: Accepting bad certificates should only be done for testing.
39+
return tcpSocketSettings.allowBadCertificate;
40+
},
41+
);
42+
43+
// Notify that the connection is open.
44+
onOpen?.call();
45+
46+
// Listen for incoming data.
47+
_socket!.listen(
48+
(dynamic data) {
49+
onData?.call(data);
50+
},
51+
onDone: () {
52+
onClose?.call(0, 'Connection closed');
53+
},
54+
onError: (dynamic error) {
55+
onClose?.call(500, error.toString());
56+
},
57+
);
58+
} catch (e) {
59+
onClose?.call(500, e.toString());
60+
}
61+
}
62+
63+
/// A StreamController queue to delay outgoing messages.
64+
final StreamController<dynamic> queue = StreamController<dynamic>.broadcast();
65+
66+
void handleQueue() async {
67+
queue.stream.asyncMap((dynamic event) async {
68+
await Future<void>.delayed(Duration(milliseconds: messageDelay));
69+
return event;
70+
}).listen((dynamic event) async {
71+
// Convert the string message to bytes.
72+
_socket!.add(event.codeUnits);
73+
logger.d('send: \n\n$event');
74+
});
75+
}
76+
77+
/// Sends data over the secure socket.
78+
void send(dynamic data) {
79+
if (_socket != null) {
80+
queue.add(data);
81+
}
82+
}
83+
84+
/// Closes the secure socket.
85+
void close() {
86+
_socket?.close();
87+
}
88+
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: sip_ua
2-
version: 1.0.0
2+
version: 1.0.1
33
description: A SIP UA stack for Flutter/Dart, based on flutter-webrtc, support iOS/Android/Destkop/Web.
44
homepage: https://github.com/cloudwebrtc/dart-sip-ua
55
environment:

0 commit comments

Comments
 (0)