Skip to content

Commit

Permalink
Tcp socket implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikael Wills committed Apr 23, 2024
1 parent d4c0a5b commit 425ec98
Show file tree
Hide file tree
Showing 31 changed files with 563 additions and 204 deletions.
66 changes: 55 additions & 11 deletions example/lib/src/register.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sip_ua/sip_ua.dart';
import 'package:flutter/foundation.dart' show kIsWeb;

class RegisterWidget extends StatefulWidget {
final SIPUAHelper? _helper;
Expand All @@ -14,6 +15,7 @@ class RegisterWidget extends StatefulWidget {
class _MyRegisterWidget extends State<RegisterWidget>
implements SipUaHelperListener {
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _portController = TextEditingController();
final TextEditingController _wsUriController = TextEditingController();
final TextEditingController _sipUriController = TextEditingController();
final TextEditingController _displayNameController = TextEditingController();
Expand All @@ -26,6 +28,8 @@ class _MyRegisterWidget extends State<RegisterWidget>
late SharedPreferences _preferences;
late RegistrationState _registerState;

TransportType _selectedTransport = TransportType.TCP;

SIPUAHelper? get helper => widget._helper;

@override
Expand All @@ -34,6 +38,9 @@ class _MyRegisterWidget extends State<RegisterWidget>
_registerState = helper!.registerState;
helper!.addSipUaHelperListener(this);
_loadSettings();
if (kIsWeb) {
_selectedTransport = TransportType.WS;
}
}

@override
Expand All @@ -56,6 +63,7 @@ class _MyRegisterWidget extends State<RegisterWidget>
void _loadSettings() async {
_preferences = await SharedPreferences.getInstance();
setState(() {
_portController.text = '5060';
_wsUriController.text =
_preferences.getString('ws_uri') ?? 'wss://tryit.jssip.net:10443';
_sipUriController.text =
Expand All @@ -69,6 +77,7 @@ class _MyRegisterWidget extends State<RegisterWidget>
}

void _saveSettings() {
_preferences.setString('port', _portController.text);
_preferences.setString('ws_uri', _wsUriController.text);
_preferences.setString('sip_uri', _sipUriController.text);
_preferences.setString('display_name', _displayNameController.text);
Expand Down Expand Up @@ -113,12 +122,15 @@ class _MyRegisterWidget extends State<RegisterWidget>

UaSettings settings = UaSettings();

settings.webSocketUrl = _wsUriController.text;
settings.port = _portController.text;
settings.webSocketSettings.extraHeaders = _wsExtraHeaders;
settings.webSocketSettings.allowBadCertificate = true;
//settings.webSocketSettings.userAgent = 'Dart/2.8 (dart:io) for OpenSIPS.';

settings.tcpSocketSettings.allowBadCertificate = true;
settings.transportType = _selectedTransport;
settings.uri = _sipUriController.text;
settings.webSocketUrl = _wsUriController.text;
settings.host = _sipUriController.text.split('@')[1];
settings.authorizationUser = _authorizationUserController.text;
settings.password = _passwordController.text;
settings.displayName = _displayNameController.text;
Expand All @@ -143,14 +155,24 @@ class _MyRegisterWidget extends State<RegisterWidget>
style: TextStyle(fontSize: 18, color: Colors.black54),
),
),
SizedBox(height: 40),
Text('WebSocket:'),
TextFormField(
controller: _wsUriController,
keyboardType: TextInputType.text,
autocorrect: false,
textAlign: TextAlign.center,
),
SizedBox(height: 20),
if (_selectedTransport == TransportType.WS) ...[
Text('WebSocket:'),
TextFormField(
controller: _wsUriController,
keyboardType: TextInputType.text,
autocorrect: false,
textAlign: TextAlign.center,
),
],
if (_selectedTransport == TransportType.TCP) ...[
Text('Port:'),
TextFormField(
controller: _portController,
keyboardType: TextInputType.text,
textAlign: TextAlign.center,
),
],
SizedBox(height: 20),
Text('SIP URI:'),
TextFormField(
Expand Down Expand Up @@ -192,7 +214,29 @@ class _MyRegisterWidget extends State<RegisterWidget>
hintText: _displayNameController.text.isEmpty ? '[Empty]' : null,
),
),
const SizedBox(height: 40),
const SizedBox(height: 20),
if (!kIsWeb) ...[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RadioMenuButton<TransportType>(
value: TransportType.TCP,
groupValue: _selectedTransport,
onChanged: ((value) => setState(() {
_selectedTransport = value!;
})),
child: Text("TCP")),
RadioMenuButton<TransportType>(
value: TransportType.WS,
groupValue: _selectedTransport,
onChanged: ((value) => setState(() {
_selectedTransport = value!;
})),
child: Text("WS")),
],
),
],
const SizedBox(height: 20),
ElevatedButton(
child: Text('Register'),
onPressed: () => _handleSave(context),
Expand Down
1 change: 1 addition & 0 deletions lib/sip_ua.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// only expose the bare minimum of internals required
export 'src/enum_helper.dart';
export 'src/sip_ua_helper.dart';
export 'src/transport_type.dart';
23 changes: 17 additions & 6 deletions lib/src/config.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
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 'socket.dart' as Socket;
import 'transports/websocket_interface.dart';
import 'transports/web_socket.dart';
import 'uri.dart';
import 'utils.dart' as Utils;

Expand Down Expand Up @@ -43,8 +44,10 @@ class Settings {
// Dtmf mode
DtmfMode dtmf_mode = DtmfMode.INFO;

TransportType? transportType;

// Connection options.
List<WebSocketInterface>? sockets = <WebSocketInterface>[];
List<SIPUASocketInterface>? sockets = <SIPUASocketInterface>[];
int connection_recovery_max_interval = 30;
int connection_recovery_min_interval = 2;

Expand All @@ -71,16 +74,17 @@ class Checks {
Map<String, Null Function(Settings src, Settings? dst)> mandatory =
<String, Null Function(Settings src, Settings? dst)>{
'sockets': (Settings src, Settings? dst) {
List<WebSocketInterface>? sockets = src.sockets;
List<SIPUASocketInterface>? sockets = src.sockets;

/* Allow defining sockets parameter as:
* Socket: socket
* List of Socket: [socket1, socket2]
* List of Objects: [{socket: socket1, weight:1}, {socket: Socket2, weight:0}]
* List of Objects and Socket: [{socket: socket1}, socket2]
*/
List<WebSocketInterface> copy = <WebSocketInterface>[];
List<SIPUASocketInterface> copy = <SIPUASocketInterface>[];
if (sockets is List && sockets!.length > 0) {
for (WebSocketInterface socket in sockets) {
for (SIPUASocketInterface socket in sockets) {
copy.add(socket);
}
} else {
Expand All @@ -105,6 +109,13 @@ class Checks {
} else {
dst!.uri = parsed;
}
},
'transport_type': (Settings src, Settings? dst) {
dynamic transportType = src.transportType;
if (src.transportType == null && dst!.transportType == null) {
throw Exceptions.ConfigurationError('transport type', null);
}
dst!.transportType = transportType;
}
};
Map<String, Null Function(Settings src, Settings? dst)> optional =
Expand Down
11 changes: 6 additions & 5 deletions lib/src/event_manager/transport_events.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import '../transports/websocket_interface.dart';
import 'package:sip_ua/src/transports/socket_interface.dart';
import '../transports/web_socket.dart';
import 'events.dart';

class EventSocketConnected extends EventType {
EventSocketConnected({this.socket});
WebSocketInterface? socket;
SIPUASocketInterface? socket;
}

class EventSocketConnecting extends EventType {
EventSocketConnecting({this.socket});
WebSocketInterface? socket;
SIPUASocketInterface? socket;
}

class EventSocketDisconnected extends EventType {
EventSocketDisconnected({WebSocketInterface? socket, this.cause});
WebSocketInterface? socket;
EventSocketDisconnected({SIPUASocketInterface? socket, this.cause});
SIPUASocketInterface? socket;
ErrorCause? cause;
}
2 changes: 1 addition & 1 deletion lib/src/logger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class AnsiColor {

String call(String msg) {
if (color) {
return '$this$msg$ansiDefault';
return '$msg$ansiDefault';
} else {
return msg;
}
Expand Down
8 changes: 4 additions & 4 deletions lib/src/registrator.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';

import 'package:sip_ua/src/socket_transport.dart';
import 'constants.dart' as DartSIP_C;
import 'constants.dart';
import 'event_manager/event_manager.dart';
Expand All @@ -10,7 +11,6 @@ import 'name_addr_header.dart';
import 'request_sender.dart';
import 'sip_message.dart';
import 'timers.dart';
import 'transport.dart';
import 'ua.dart';
import 'uri.dart';
import 'utils.dart' as utils;
Expand All @@ -24,7 +24,7 @@ class UnHandledResponse {
}

class Registrator {
Registrator(UA ua, [Transport? transport]) {
Registrator(UA ua, [SocketTransport? transport]) {
int reg_id = 1; // Force reg_id to 1.

_ua = ua;
Expand Down Expand Up @@ -71,7 +71,7 @@ class Registrator {
}

late UA _ua;
Transport? _transport;
SocketTransport? _transport;
late URI _registrar;
int? _expires;
String? _call_id;
Expand All @@ -86,7 +86,7 @@ class Registrator {

bool get registered => _registered;

Transport? get transport => _transport;
SocketTransport? get transport => _transport;

void setExtraHeaders(List<String>? extraHeaders) {
_extraHeaders = extraHeaders ?? <String>[];
Expand Down
10 changes: 5 additions & 5 deletions lib/src/request_sender.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ class RequestSender {

switch (_method) {
case SipMethod.INVITE:
clientTransaction =
InviteClientTransaction(_ua, _ua.transport!, _request!, handlers);
clientTransaction = InviteClientTransaction(
_ua, _ua.socketTransport!, _request!, handlers);
break;
case SipMethod.ACK:
clientTransaction =
AckClientTransaction(_ua, _ua.transport!, _request!, handlers);
clientTransaction = AckClientTransaction(
_ua, _ua.socketTransport!, _request!, handlers);
break;
default:
clientTransaction = NonInviteClientTransaction(
_ua, _ua.transport!, _request!, handlers);
_ua, _ua.socketTransport!, _request!, handlers);
}

clientTransaction?.send();
Expand Down
36 changes: 19 additions & 17 deletions lib/src/rtc_session.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import 'dart:async';

import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:sdp_transform/sdp_transform.dart' as sdp_transform;

import 'package:sdp_transform/sdp_transform.dart';
import 'package:sip_ua/sip_ua.dart';
import 'constants.dart' as DartSIP_C;
import 'constants.dart';
Expand Down Expand Up @@ -1950,27 +1951,28 @@ class RTCSession extends EventManager implements Owner {
}

Future<RTCSessionDescription> _processInDialogSdpOffer(
dynamic request) async {
IncomingRequest request) async {
logger.d('_processInDialogSdpOffer()');

Map<String, dynamic> sdp = request.parseSDP();
Map<String, dynamic>? sdp = request.parseSDP();

bool hold = false;
if (sdp != null) {
for (Map<String, dynamic> m in sdp['media']) {
if (holdMediaTypes.indexOf(m['type']) == -1) {
continue;
}

for (Map<String, dynamic> m in sdp['media']) {
if (holdMediaTypes.indexOf(m['type']) == -1) {
continue;
}

String direction = m['direction'] ?? sdp['direction'] ?? 'sendrecv';
String direction = m['direction'] ?? sdp['direction'] ?? 'sendrecv';

if (direction == 'sendonly' || direction == 'inactive') {
hold = true;
}
// If at least one of the streams is active don't emit 'hold'.
else {
hold = false;
break;
if (direction == 'sendonly' || direction == 'inactive') {
hold = true;
}
// If at least one of the streams is active don't emit 'hold'.
else {
hold = false;
break;
}
}
}

Expand Down
1 change: 0 additions & 1 deletion lib/src/rtc_session/dtmf.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class DTMF extends EventManager {
throw Exceptions.InvalidStateError(_session.status);
}

print(options);
List<dynamic> extraHeaders = options['extraHeaders'] != null
? Utils.cloneArray(options['extraHeaders'])
: <dynamic>[];
Expand Down
6 changes: 3 additions & 3 deletions lib/src/sanity_check.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'logger.dart';
import 'sip_message.dart';
import 'transactions/invite_server.dart';
import 'transactions/non_invite_server.dart';
import 'transport.dart';
import 'socket_transport.dart';
import 'ua.dart';
import 'utils.dart' as Utils;

Expand All @@ -28,9 +28,9 @@ const List<bool Function()> responses = <bool Function()>[
// local variables.
late IncomingMessage message;
late UA ua;
late Transport transport;
late SocketTransport transport;

bool sanityCheck(IncomingMessage m, UA u, Transport t) {
bool sanityCheck(IncomingMessage m, UA u, SocketTransport t) {
message = m;
ua = u;
transport = t;
Expand Down
Loading

0 comments on commit 425ec98

Please sign in to comment.