Skip to content

Commit

Permalink
Free pointers before throwing a ZeroMQException
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed Oct 25, 2021
1 parent 8f38746 commit ddda421
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 15 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 1.0.0-dev.6

### Free pointers before throwing a ZeroMQException
- Free pointers before throwing a ZeroMQException
- Add return code to `zmq_setsockopt` function
- Add return code check to `ZSocket.setOption` function
- Add `zmq_has` function for checking supported capabilities
- Add helper functions for `zmq_has`


## 1.0.0-dev.5

### Fix destroying poller and loading shared library
Expand Down
10 changes: 8 additions & 2 deletions lib/src/bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class ZMQPollItem extends Struct {
external int revents;
}

typedef ZmqHasNative = Int32 Function(Pointer<Utf8> capability);
typedef ZmqHasDart = int Function(Pointer<Utf8> capability);

typedef ZmqBindNative = Int32 Function(
ZMQSocket socket, Pointer<Utf8> endpoint);
typedef ZmqBindDart = int Function(ZMQSocket socket, Pointer<Utf8> endpoint);
Expand Down Expand Up @@ -107,14 +110,16 @@ typedef ZmqSendNative = Int32 Function(
typedef ZmqSendDart = int Function(
ZMQSocket socket, Pointer<Void> buffer, int size, int flags);

typedef ZmqsetsockoptNative = Void Function(
typedef ZmqsetsockoptNative = Int32 Function(
ZMQSocket socket, Int32 option, Pointer<Uint8> optval, IntPtr optvallen);
typedef ZmqSetsockoptDart = void Function(
typedef ZmqSetsockoptDart = int Function(
ZMQSocket socket, int option, Pointer<Uint8> optval, int optvallen);

class ZMQBindings {
final DynamicLibrary library;

late final ZmqHasDart zmq_has;

late final ZmqErrnoDart zmq_errno;

late final ZmqBindDart zmq_bind;
Expand Down Expand Up @@ -143,6 +148,7 @@ class ZMQBindings {
late final ZmqSetsockoptDart zmq_setsockopt;

ZMQBindings(this.library) {
zmq_has = library.lookupFunction<ZmqHasNative, ZmqHasDart>('zmq_has');
zmq_errno =
library.lookupFunction<ZmqErrnoNative, ZmqErrnoDart>('zmq_errno');
zmq_bind = library.lookupFunction<ZmqBindNative, ZmqBindDart>('zmq_bind');
Expand Down
100 changes: 88 additions & 12 deletions lib/src/zeromq.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ class ZContext {
}

void _initBindings() {
final loaded = _loadBinding('zmq') || _loadBinding('libzmq-v142-mt-4_3_5');
final loaded = _loadBinding('zmq') ||
_loadBinding('libzmq') ||
_loadBinding('libzmq-v142-mt-4_3_5');
if (!loaded) {
throw Exception('Could not load any zeromq library');
}
Expand Down Expand Up @@ -169,6 +171,79 @@ class ZContext {
_stopCompleter?.complete(null);
}

/// Check whether a specified [capability] is available in the library.
/// This allows bindings and applications to probe a library directly,
/// for transport and security options.
///
/// Capabilities shall be lowercase strings. The following capabilities are defined:
/// * `ipc` - the library supports the ipc:// protocol
/// * `pgm` - the library supports the pgm:// protocol
/// * `tipc` - the library supports the tipc:// protocol
/// * `norm` - the library supports the norm:// protocol
/// * `curve` - the library supports the CURVE security mechanism
/// * `gssapi` - the library supports the GSSAPI security mechanism
/// * `draft` - the library is built with the draft api
///
/// You can also use one of the direct functions [hasIPC], [hasPGM],
/// [hasTIPC], [hasNORM], [hasCURVE], [hasGSSAPI] and [hasDRAFT] instead.
///
/// Returns true if supported, false if not
bool hasCapability(final String capability) {
final ptr = capability.toNativeUtf8();
final result = _bindings.zmq_has(ptr);
malloc.free(ptr);
return result == 1;
}

/// Check if the library supports the ipc:// protocol
///
/// Returns true if supported, false if not
bool hasIPC() {
return hasCapability('ipc');
}

/// Check if the library supports the pgm:// protocol
///
/// Returns true if supported, false if not
bool hasPGM() {
return hasCapability('pgm');
}

/// Check if the library supports the tipc:// protocol
///
/// Returns true if supported, false if not
bool hasTIPC() {
return hasCapability('tipc');
}

/// Check if the library supports the norm:// protocol
///
/// Returns true if supported, false if not
bool hasNORM() {
return hasCapability('norm');
}

/// Check if the library supports the CURVE security mechanism
///
/// Returns true if supported, false if not
bool hasCURVE() {
return hasCapability('curve');
}

/// Check if the library supports the GSSAPI security mechanism
///
/// Returns true if supported, false if not
bool hasGSSAPI() {
return hasCapability('gssapi');
}

/// Check if the library is built with the draft api
///
/// Returns true if supported, false if not
bool hasDRAFT() {
return hasCapability('draft');
}

/// Create a new socket of the given [mode]
ZSocket createSocket(SocketType mode) {
final socket = _bindings.zmq_socket(_context, mode.index);
Expand Down Expand Up @@ -476,8 +551,8 @@ class ZSocket {
final sendParams = more ? ZMQ_SNDMORE : 0;
final result = _context._bindings
.zmq_send(_socket, ptr.cast(), data.length, sendParams);
_context._checkReturnCode(result);
malloc.free(ptr);
_context._checkReturnCode(result);
}

/// Sends the given [frame] over this socket
Expand Down Expand Up @@ -508,8 +583,8 @@ class ZSocket {
_checkNotClosed();
final endpointPointer = address.toNativeUtf8();
final result = _context._bindings.zmq_bind(_socket, endpointPointer);
_context._checkReturnCode(result);
malloc.free(endpointPointer);
_context._checkReturnCode(result);
}

/// Connects the socket to an endpoint and then accepts incoming connections on that endpoint.
Expand All @@ -521,8 +596,8 @@ class ZSocket {
_checkNotClosed();
final endpointPointer = address.toNativeUtf8();
final result = _context._bindings.zmq_connect(_socket, endpointPointer);
_context._checkReturnCode(result);
malloc.free(endpointPointer);
_context._checkReturnCode(result);
}

/// Closes the socket and releases underlying resources.
Expand All @@ -539,9 +614,10 @@ class ZSocket {
/// Set a socket [option] to a specific [value]
void setOption(final int option, final String value) {
final ptr = value.toNativeUtf8();
_context._bindings
final result = _context._bindings
.zmq_setsockopt(_socket, option, ptr.cast<Uint8>(), ptr.length);
malloc.free(ptr);
_context._checkReturnCode(result);
}

/// Sets the socket's long term secret key.
Expand Down Expand Up @@ -614,13 +690,13 @@ class ZeroMQException implements Exception {
/// Maps error codes to messages
static const Map<int, String> _errorMessages = {
// errno
EINTR: 'The operation was interrupted',
EBADF: 'Bad file descriptor',
// EAGAIN: '', // denpendant on what function has been called before
EACCES: 'Permission denied',
// EFAULT: '', // denpendant on what function has been called before
// EINVAL: '', // denpendant on what function has been called before
// EMFILE: '', // denpendant on what function has been called before
EINTR: 'EINTR: The operation was interrupted',
EBADF: 'EBADF: Bad file descriptor',
EAGAIN: 'EAGAIN', // denpendant on what function has been called before
EACCES: 'EACCES: Permission denied',
EFAULT: 'EFAULT', // denpendant on what function has been called before
EINVAL: 'EINVAL', // denpendant on what function has been called before
EMFILE: 'EMFILE', // denpendant on what function has been called before

// 0MQ errors
ENOTSUP: 'Not supported',
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: dartzmq
description: A simple dart zeromq implementation/wrapper around the libzmq C++ library
version: 1.0.0-dev.5
version: 1.0.0-dev.6
homepage: https://github.com/enwi/dartzmq

environment:
Expand Down

0 comments on commit ddda421

Please sign in to comment.