Skip to content

Commit

Permalink
feat: add (experimental) coaps support
Browse files Browse the repository at this point in the history
  • Loading branch information
JKRhb committed May 21, 2022
1 parent 9e2b2b2 commit 40c7b96
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 12 deletions.
73 changes: 66 additions & 7 deletions lib/src/binding_coap/coap_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'dart:convert';
import 'package:coap/coap.dart' as coap;
import 'package:coap/config/coap_config_default.dart';
import 'package:curie/curie.dart';
import 'package:dart_wot/src/definitions/credentials/psk_credentials.dart';

import '../core/content.dart';
import '../core/operation_type.dart';
Expand Down Expand Up @@ -113,7 +114,30 @@ class _InternalCoapConfig extends CoapConfigDefault {
@override
int preferredBlockSize;

_InternalCoapConfig(this.preferredBlockSize);
@override
coap.DtlsBackend? dtlsBackend;

final Form _form;

_InternalCoapConfig(CoapConfig coapConfig, this._form)
: preferredBlockSize =
coapConfig.blocksize ?? coap.CoapConstants.preferredBlockSize {
if (!_dtlsNeeded) {
return;
}

if (_hasPskCredentials(_form) && coapConfig.useTinyDtls) {
dtlsBackend = coap.DtlsBackend.TinyDtls;
} else if (coapConfig.useOpenSsl) {
dtlsBackend = coap.DtlsBackend.OpenSsl;
}
}

bool get _dtlsNeeded => _form.href.startsWith("coaps");
}

bool _hasPskCredentials(Form form) {
return form.credentials.whereType<PskCredentials>().isNotEmpty;
}

class _CoapRequest {
Expand All @@ -137,9 +161,11 @@ class _CoapRequest {
_CoapRequest(
this._form,
this._requestMethod,
_InternalCoapConfig _coapConfig, [
CoapConfig _coapConfig, [
this._subprotocol,
]) : _coapClient = coap.CoapClient(Uri.parse(_form.href), _coapConfig),
]) : _coapClient = coap.CoapClient(
Uri.parse(_form.href), _InternalCoapConfig(_coapConfig, _form),
pskCredentialsCallback: _createPskCallback(_form)),
_requestUri = Uri.parse(_form.href);

// TODO(JKRhb): blockwise parameters cannot be handled at the moment due to
Expand Down Expand Up @@ -181,6 +207,41 @@ class _CoapRequest {
return response;
}

static coap.PskCredentials? _retrievePskCredentials(Form form) {
final pskCredentialsList = form.credentials.whereType<PskCredentials>();

for (final pskCredentials in pskCredentialsList) {
final identity =
pskCredentials.identity ?? pskCredentials.securityScheme?.identity;

if (identity == null) {
continue;
}

final preSharedKey = pskCredentials.preSharedKey;

return coap.PskCredentials(
identity: identity, preSharedKey: preSharedKey);
}

return null;
}

static coap.PskCredentialsCallback? _createPskCallback(Form form) {
if (!_hasPskCredentials(form)) {
return null;
}

final pskCredentials = _retrievePskCredentials(form);

if (pskCredentials == null) {
throw CoapBindingException("No client Identity found for CoAPS request!");
}

// TODO(JKRhb): Should the identityHint be handled?
return (identityHint) => pskCredentials;
}

int _determineContentFormat(_ContentFormatType _contentFormatType) {
final curieString =
_coapPrefixMapping.expandCurieString(_contentFormatType.stringValue);
Expand Down Expand Up @@ -291,10 +352,8 @@ class CoapClient extends ProtocolClient {
final requestMethod = _getRequestMethod(form, operationType);
final _Subprotocol? subprotocol =
_determineSubprotocol(form, operationType);
final internalCoapConfig = _InternalCoapConfig(
_coapConfig?.blocksize ?? coap.CoapConstants.preferredBlockSize);
final request =
_CoapRequest(form, requestMethod, internalCoapConfig, subprotocol);
final coapConfig = _coapConfig ?? CoapConfig();
final request = _CoapRequest(form, requestMethod, coapConfig, subprotocol);
_pendingRequests.add(request);
return request;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/binding_coap/coap_client_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import 'coap_config.dart';
/// A [ProtocolClientFactory] that produces CoAP clients.
class CoapClientFactory extends ProtocolClientFactory {
@override
Set<String> get schemes => {"coap"};
Set<String> get schemes => {"coap", "coaps"};

/// The [CoapConfig] used to configure new clients.
final CoapConfig? coapConfig;
Expand Down
17 changes: 16 additions & 1 deletion lib/src/binding_coap/coap_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,24 @@ class CoapConfig {
/// The port number used by a client or server. Defaults to 5683.
final int port;

/// The coaps port number used by a client or server. Defaults to 5684.
final int securePort;

/// The preferred block size for blockwise transfer.
final int? blocksize;

/// Indicates if tinydtls is available as a DTLS backend.
final bool useTinyDtls;

/// Indicates if openSSL is available as a DTLS backend.
final bool useOpenSsl;

/// Creates a new [CoapConfig] object.
CoapConfig({this.port = 5683, this.blocksize});
CoapConfig({
this.port = 5683,
this.securePort = 5684,
this.blocksize,
this.useTinyDtls = false,
this.useOpenSsl = false,
});
}
9 changes: 6 additions & 3 deletions lib/src/core/consumed_thing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,12 @@ class ConsumedThing implements scripting_api.ConsumedThing {
'$formIndex"');
}
} else {
foundForm = forms.firstWhere((form) =>
hasClientFor(Uri.parse(form.href).scheme) &&
_supportsOperationType(form, affordanceType, operationType));
foundForm = forms.firstWhere(
(form) =>
hasClientFor(Uri.parse(form.href).scheme) &&
_supportsOperationType(form, affordanceType, operationType),
// TODO(JKRhb): Add custom Exception
orElse: () => throw Exception("No matching form found!"));
final scheme = Uri.parse(foundForm.href).scheme;
client = servient.clientFor(scheme);
}
Expand Down

0 comments on commit 40c7b96

Please sign in to comment.