Skip to content

Commit

Permalink
Initial code commit
Browse files Browse the repository at this point in the history
  • Loading branch information
wirg_mo committed Oct 7, 2021
1 parent 4dd86a2 commit 2e5443c
Show file tree
Hide file tree
Showing 11 changed files with 702 additions and 1 deletion.
29 changes: 29 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/
10 changes: 10 additions & 0 deletions .metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: 4b330ddbedab445481cc73d50a4695b9154b4e4f
channel: dev

project_type: package
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## 1.0.0-dev.1

### Add crude implementation of libzmq
- Creating sockets (pair, pub, sub, req, rep, dealer, router, pull, push, xPub, xSub, stream)
- Sending messages (of type `List<int>`)
- Bind (`bind(String address)`)
- Connect (`connect(String address)`)
- Curve (`setCurvePublicKey(String key)`, `setCurveSecretKey(String key)` and `setCurveServerKey(String key)`)
- Socket options (`setOption(int option, String value)`)
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,37 @@
# dartzmq
A simple dart zeromq implementation
A simple dart zeromq implementation/wrapper around the libzmq C++ library

## Features
Currently supported:
- Creating sockets (pair, pub, sub, req, rep, dealer, router, pull, push, xPub, xSub, stream)
- Sending messages (of type `List<int>`)
- Bind (`bind(String address)`)
- Connect (`connect(String address)`)
- Curve (`setCurvePublicKey(String key)`, `setCurveSecretKey(String key)` and `setCurveServerKey(String key)`)
- Socket options (`setOption(int option, String value)`)

## Getting started
Currently only windows is officially supported as a platform, but it depends on the used shared library of `libzmq`.
I have tested this on windows, which works.
Other platforms have not been tested, but should work.
If you have tested this plugin on another platform and got it to work, please share your findings and create an issue to add it to the list.

Once you installed this plugin place the shared library of `libzmq` next to your executable (for example place `libzmq-v142-mt-4_3_5.dll` in the folder `yourproject/build/windows/runner/Debug/`)

> Note that in order for this plugin to work you will need to either get a shared library of `libzmq` or compile it yourself.
> Especially when using this on windows you need to make sure that `libzmq` is compiled using `MSVC-2019` if you are using `clang` it will not work ([more info](https://flutterforum.co/t/windows-desktop-flutter-ffi-and-loading-the-clang-library/3842))
## Usage

TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.

```dart
const like = 'sample';
```

## Additional information

TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.
4 changes: 4 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include: package:flutter_lints/flutter.yaml

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
1 change: 1 addition & 0 deletions lib/dartzmq.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'src/zeromq.dart';
191 changes: 191 additions & 0 deletions lib/src/bindings.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// ignore_for_file: non_constant_identifier_names
import 'dart:ffi';

import 'package:ffi/ffi.dart';

part 'constants.dart';

typedef ZMQContext = Pointer<Void>;
typedef ZMQSocket = Pointer<Void>;
typedef ZMQPoller = Pointer<Void>;
typedef ZMQMessage = Pointer<Void>;

typedef zmq_bind_native = Int32 Function(
ZMQSocket socket, Pointer<Utf8> endpoint);
typedef zmq_bind_dart = int Function(ZMQSocket socket, Pointer<Utf8> endpoint);

typedef zmq_connect_native = Int32 Function(
ZMQSocket socket, Pointer<Utf8> endpoint);
typedef zmq_connect_dart = int Function(
ZMQSocket socket, Pointer<Utf8> endpoint);

typedef zmq_errno_native = Int32 Function();
typedef zmq_errno_dart = int Function();

typedef zmq_ctx_term_native = Int32 Function(ZMQContext context);
typedef zmq_ctx_term_dart = int Function(ZMQContext context);

typedef zmq_ctx_new_native = ZMQContext Function();
typedef zmq_ctx_new_dart = ZMQContext Function();

// IO multiplexing
typedef zmq_poller_new_native = ZMQPoller Function();
typedef zmq_poller_new_dart = ZMQPoller Function();

typedef zmq_poller_destroy_native = Int32 Function(ZMQPoller poller);
typedef zmq_poller_destroy_dart = int Function(ZMQPoller poller);

typedef zmq_poller_add_native = Int32 Function(
ZMQPoller poller, ZMQSocket socket, Pointer<Void> userData, Int16 events);
typedef zmq_poller_add_dart = int Function(
ZMQPoller poller, ZMQSocket socket, Pointer<Void> userData, int events);

typedef zmq_poller_remove_native = Int32 Function(
ZMQPoller poller, ZMQSocket sockeft);
typedef zmq_poller_remove_dart = int Function(
ZMQPoller poller, ZMQSocket socket);

typedef zmq_poller_wait_all_native = Int32 Function(ZMQPoller poller,
Pointer<ZMQPollerEvent> events, Int32 count, Int64 timeout);
typedef zmq_poller_wait_all_dart = int Function(
ZMQPoller poller, Pointer<ZMQPollerEvent> events, int count, int timeout);

// Messages
typedef zmq_msg_init_native = Int32 Function(ZMQMessage message);
typedef zmq_msg_init_dart = int Function(ZMQMessage message);

typedef zmq_msg_size_native = IntPtr Function(ZMQMessage message);
typedef zmq_msg_size_dart = int Function(ZMQMessage message);

typedef zmq_msg_data_native = Pointer<Void> Function(ZMQMessage message);
typedef zmq_msg_data_dart = Pointer<Void> Function(ZMQMessage message);

typedef zmq_msg_recv_native = Int32 Function(
ZMQMessage msg, ZMQSocket socket, Int32 flags);
typedef zmq_msg_recv_dart = int Function(
ZMQMessage msg, ZMQSocket socket, int flags);

typedef zmq_msg_more_native = Int32 Function(ZMQMessage message);
typedef zmq_msg_more_dart = int Function(ZMQMessage message);

typedef zmq_msg_close_native = Int32 Function(ZMQMessage msg);
typedef zmq_msg_close_dart = int Function(ZMQMessage msg);

typedef zmq_socket_native = ZMQSocket Function(ZMQContext context, Int32 type);
typedef zmq_socket_dart = ZMQSocket Function(ZMQContext context, int type);

typedef zmq_close_native = Int32 Function(ZMQSocket socket);
typedef zmq_close_dart = int Function(ZMQSocket socket);

typedef zmq_send_native = Int32 Function(
ZMQSocket socket, Pointer<Void> buffer, IntPtr size, Int32 flags);
typedef zmq_send_dart = int Function(
ZMQSocket socket, Pointer<Void> buffer, int size, int flags);

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

// Native types
// class ZMQContext extends Struct {}

// class ZMQSocket extends Struct {/* void* */}

// class ZMQPoller extends Struct {/* void* */}

// class ZMQMessage extends Struct {
// // this struct actually has some values, but we're supposed to extract data
// // via functions, so we treat this as a typed void*
// }

class ZMQPollerEvent extends Struct {
external ZMQSocket socket;
@Int32()
external int fd;

external Pointer<Void> userData;
@Int16()
external int events;
}

class ZeroMQBindings {
final DynamicLibrary library;

late final zmq_errno_dart zmq_errno;

late final zmq_bind_dart zmq_bind;
late final zmq_connect_dart zmq_connect;
late final zmq_ctx_new_dart zmq_ctx_new;
late final zmq_ctx_term_dart zmq_ctx_term;
late final zmq_socket_dart zmq_socket;
late final zmq_close_dart zmq_close;

late final zmq_send_dart zmq_send;

late final zmq_poller_new_dart zmq_poller_new;
late final zmq_poller_destroy_dart zmq_poller_destroy;
late final zmq_poller_add_dart zmq_poller_add;
late final zmq_poller_remove_dart zmq_poller_remove;
late final zmq_poller_wait_all_dart zmq_poller_wait_all;

late final zmq_msg_init_dart zmq_msg_init;
late final zmq_msg_close_dart zmq_msg_close;
late final zmq_msg_size_dart zmq_msg_size;
late final zmq_msg_data_dart zmq_msg_data;
late final zmq_msg_recv_dart zmq_msg_recv;
late final zmq_msg_more_dart zmq_msg_more;

late final zmq_setsockopt_dart zmq_setsockopt;

ZeroMQBindings(this.library) {
zmq_errno =
library.lookupFunction<zmq_errno_native, zmq_errno_dart>('zmq_errno');
zmq_bind =
library.lookupFunction<zmq_bind_native, zmq_bind_dart>('zmq_bind');
zmq_connect = library
.lookupFunction<zmq_connect_native, zmq_connect_dart>('zmq_connect');
zmq_ctx_new = library
.lookupFunction<zmq_ctx_new_native, zmq_ctx_new_dart>('zmq_ctx_new');
zmq_ctx_term = library
.lookupFunction<zmq_ctx_term_native, zmq_ctx_term_dart>('zmq_ctx_term');
zmq_socket = library
.lookupFunction<zmq_socket_native, zmq_socket_dart>('zmq_socket');
zmq_close =
library.lookupFunction<zmq_close_native, zmq_close_dart>('zmq_close');

zmq_send =
library.lookupFunction<zmq_send_native, zmq_send_dart>('zmq_send');

zmq_poller_new =
library.lookupFunction<zmq_poller_new_native, zmq_poller_new_dart>(
'zmq_poller_new');
zmq_poller_destroy = library.lookupFunction<zmq_poller_destroy_native,
zmq_poller_destroy_dart>('zmq_poller_destroy');
zmq_poller_add =
library.lookupFunction<zmq_poller_add_native, zmq_poller_add_dart>(
'zmq_poller_add');
zmq_poller_remove = library.lookupFunction<zmq_poller_remove_native,
zmq_poller_remove_dart>('zmq_poller_remove');
zmq_poller_wait_all = library.lookupFunction<zmq_poller_wait_all_native,
zmq_poller_wait_all_dart>('zmq_poller_wait_all');

zmq_msg_init = library
.lookupFunction<zmq_msg_init_native, zmq_msg_init_dart>('zmq_msg_init');
zmq_msg_close =
library.lookupFunction<zmq_msg_close_native, zmq_msg_close_dart>(
'zmq_msg_close');
zmq_msg_size = library
.lookupFunction<zmq_msg_size_native, zmq_msg_size_dart>('zmq_msg_size');
zmq_msg_data = library
.lookupFunction<zmq_msg_data_native, zmq_msg_data_dart>('zmq_msg_data');
zmq_msg_recv = library
.lookupFunction<zmq_msg_recv_native, zmq_msg_recv_dart>('zmq_msg_recv');
zmq_msg_more = library
.lookupFunction<zmq_msg_more_native, zmq_msg_more_dart>('zmq_msg_more');

zmq_setsockopt =
library.lookupFunction<zmq_setsockopt_native, zmq_setsockopt_dart>(
'zmq_setsockopt');
}
}
50 changes: 50 additions & 0 deletions lib/src/constants.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// ignore_for_file: constant_identifier_names
part of 'bindings.dart';

// Constants, https://github.com/zeromq/libzmq/blob/9bb6b2142385b78d47811b73745b9c21ec366106/include/zmq.h#L285-L301

const int ZMQ_PAIR = 0;
const int ZMQ_PUB = 1;
const int ZMQ_SUB = 2;
const int ZMQ_REQ = 3;
const int ZMQ_REP = 4;
const int ZMQ_DEALER = 5;
const int ZMQ_ROUTER = 6;
const int ZMQ_PULL = 7;
const int ZMQ_PUSH = 8;
const int ZMQ_XPUB = 9;
const int ZMQ_XSUB = 10;
const int ZMQ_STREAM = 11;

const int ZMQ_POLLIN = 1;
const int ZMQ_POLLOUT = 2;
const int ZMQ_POLLERR = 4;
const int ZMQ_POLLPRI = 8;

const int ZMQ_SNDMORE = 2;

const int ZMQ_CURVE_PUBLICKEY = 48;
const int ZMQ_CURVE_SECRETKEY = 49;
const int ZMQ_CURVE_SERVERKEY = 50;

// https://github.com/zeromq/libzmq/blob/9bb6b2142385b78d47811b73745b9c21ec366106/include/zmq.h#L133
const int _errorBase = 156384712;

const int ENOTSUP = _errorBase + 1;
const int EPROTONOSUPPORT = _errorBase + 2;
const int ENOBUFS = _errorBase + 3;
const int ENETDOWN = _errorBase + 4;
const int EADDRINUSE = _errorBase + 5;
const int EADDRNOTAVAIL = _errorBase + 6;
const int ECONNREFUSED = _errorBase + 7;
const int EINPROGRESS = _errorBase + 8;
const int ENOTSOCK = _errorBase + 9;
const int EMSGSIZE = _errorBase + 10;
const int EAFNOSUPPORT = _errorBase + 11;
const int ENETUNREACH = _errorBase + 12;
const int ECONNABORTED = _errorBase + 13;
const int ECONNRESET = _errorBase + 14;
const int ENOTCONN = _errorBase + 15;
const int ETIMEDOUT = _errorBase + 16;
const int EHOSTUNREACH = _errorBase + 17;
const int ENETRESET = _errorBase + 18;
Loading

0 comments on commit 2e5443c

Please sign in to comment.