Commit Graph

25 Commits

Author SHA1 Message Date
Jeff Becker 5a41e84378
add operator() overload for defered message that sends reply 2021-09-24 16:01:31 -04:00
Jason Rhinelander 917c7d64c5 Apple test suite hacks
Because macOS is really slow.
2021-08-04 19:54:17 -03:00
Jason Rhinelander a0642a894e Miscellaneous small test suite fixes/improvements
- Allow up to 200ms (instead of 100ms) for the things we are waiting on
to become available, to prevent occasional spurious failures.
- Add unscoped info for how long we waited.
- Avoid calling into oxenmq with the catch lock held in the "hey google"
tests (because this will deadlock if the oxenmq call invokes any
logging).
- Replace an old std::cerr logger with the updated catch2 logger.
2021-06-23 10:55:47 -03:00
Jason Rhinelander 5ccacafdb1 Add support for std::optional<T> send arguments
If the optional is set it gets applied as if you specified the `T` in
the send(...), if unset it works as if you didn't specify the argument
at all.
2021-04-20 13:54:42 -03:00
Jason Rhinelander ac58e5b574 Rename PUBKEY_BASED_ROUTING_ID to EPHEMERAL_ROUTING_ID
And similarly for the connect_option
2021-04-15 15:42:04 -03:00
Jason Rhinelander 506bd65b05 Add better deferred reply capabilities to Message
This provides an interface for sending a reply to a message later (i.e.
after the Message& itself is no longer valid) by using a new
`send_later()` method of the Message instance that returns an object
that can properly route replies (and can outlive the Message it was
called on).

Intended use is:

    run_this_lambda_later([send=msg.send_later()] {
        send.reply("content");
    });

which is equivalent to:

    run_this_lambda_later([&msg] {
        msg.send_reply("content");
    });

except that it works properly even if the lambda is invoked beyond the
lifetime of `msg`.
2021-01-21 11:59:39 -04:00
Jason Rhinelander 2ae6b96016 Rename LokiMQ to OxenMQ 2021-01-14 15:32:38 -04:00
Jason Rhinelander 7049d3cb5a Test suite: use different ports for each test
Apple, in particular, often fails tests with an address already in use
if attempt to reuse a port that the process just closed, because it is a
wonderful OS.
2020-10-15 16:55:33 -03:00
Jason Rhinelander e5cf174b83 Fix & add tests for send_option::data_parts(...)
data_parts() wasn't currently used anywhere, and was broken: it was
calling bt_deserialize which was just wrong.

This repurposes it to take iterators over strings (or string-like types)
and append those parts as message parts.

Also adds tests for it.
2020-07-20 14:37:01 -03:00
Jason Rhinelander 07b31bd8a1 Take lokimq::address as connect_remote argument
Deprecates the existing connect_remote() that takes remote addr and
pubkey as separate strings, just taking a `address` instead (into which
the caller can set pubkey/curve data as desired).

Also slightly changes how `connect_remote()` works when called with a
string remote but no pubkey: that string is now an augmented
lokimq::address string so that it can use the various formats supported
by `lokimq::address`.

(This was meant to be included in the PR that added `address` but
apparently didn't get implemented.)
2020-06-30 13:09:34 -03:00
Jason Rhinelander 278909db77 Resolve race condition in test suite
There can be a spurious failure here if the backdoor_details element
hasn't been added yet, so lock & check it when waiting for the test
conditions.

The weirdest thing about this error is that it can fail but then when
expanding values they expand to *correct* values, i.e. so you get:

FAILED:
  REQUIRE( backdoor_details == all_the_things )
with expansion:
  { "Alaska", "I'm the luckiest man in the world", "Loretta", "because all my
  life are belong to Google", "moustache hatred", "photos", "scallops",
  "snorted when she laughed", "tickled pink" }
  ==
  { "Alaska", "I'm the luckiest man in the world", "Loretta", "because all my
  life are belong to Google", "moustache hatred", "photos", "scallops",
  "snorted when she laughed", "tickled pink" }
2020-06-07 21:28:53 -03:00
Jason Rhinelander d0a07f7c08 Fix test segfault under clang
These (...) lambdas are va_arg which cause corruption under clang on
both linux and macos.  They weren't supposed to be va_args -- switch
them to the intended universal references, which fixes the crash.
2020-05-15 01:27:28 -03:00
Jason Rhinelander c9cf833861 Silence c++17 warnings from cppzmq
In C++17 all the recv calls have a [[nodiscard]], so check them as part
of the test (both to silence the warnings and for better test code).
2020-05-12 15:47:22 -03:00
Jason Rhinelander 7b42537801 Require C++17
Removes lokimq::string_view (the type alias is still provided for
backwards compat, but now is always std::string_view).

Bump version (on dev branch) to 1.2.0
2020-05-12 15:33:59 -03:00
Jason Rhinelander 3aa63c059d Test suite timing tweaks 2020-04-14 17:40:41 -03:00
Jason Rhinelander 3b86eb1341 1.1.0: invocation-time SN auth; failure responses
This replaces the recognition of SN status to be checked per-command
invocation rather than on connection.  As this breaks the API quite
substantially, though doesn't really affect the functionality, it seems
suitable to bump the minor version.

This requires a fundamental shift in how the calling application tells
LokiMQ about service nodes: rather than using a callback invoked on
connection, the application now has to call set_active_sns() (or the
more efficient update_active_sns(), if changes are readily available) to
update the list whenever it changes.  LokiMQ then keeps this list
internally and uses it when determining whether to invoke.

This release also brings better request responses on errors: when a
request fails, the data argument will now be set to the failure reason,
one of:

- TIMEOUT
- UNKNOWNCOMMAND
- NOT_A_SERVICE_NODE (the remote isn't running in SN mode)
- FORBIDDEN (auth level denies the request)
- FORBIDDEN_SN (SN required and the remote doesn't see us as a SN)

Some of these (UNKNOWNCOMMAND, NOT_A_SERVICE_NODE, FORBIDDEN) were
already sent by remotes, but there was no connection to a request and so
they would log a warning, but the request would have to time out.

These errors (minus TIMEOUT, plus NO_REPLY_TAG signalling that a command
is a request but didn't include a reply tag) are also sent in response
to regular commands, but they simply result in a log warning showing the
error type and the command that caused the failure when received.
2020-04-12 19:57:19 -03:00
Jason Rhinelander 716d73d196 All sends use dontwait; add send failure callbacks
We really don't *ever* want send to block, no matter how it is called,
since the send is always in the proxy thread.  This makes the actual
send call always non-blocking, and adds callbacks that we can invoke on
send failures: either on queue full errors (which might be recoverable),
or both full queue and hard failures (which are generally not
recoverable).  These callbacks are both optional: they have to be passed
in using `send_option::queue_full` (if you just want queue full
notifies) or `send_option::queue_failure` (if you want queue full
notifies *and* other send exceptions).
2020-03-29 15:21:20 -03:00
Jason Rhinelander 98b1bd6930 Add more locks around assertions
Catch2 isn't currently thread safe, so if we hit one of these assertions
while some other thread is doing things such as logging we might
segfault.
2020-03-21 12:56:13 -03:00
Jason Rhinelander 3a120efb79 Increase test timeouts for arm
These *sometimes* spurious fail because apparently they weren't quite
long enough to pass tests on my Pi 4.
2020-03-21 11:10:07 -03:00
Jason Rhinelander 922435ca3b Add auth and ConnectionID routing tests 2020-02-29 16:06:55 -04:00
Jason Rhinelander 57f0ca74da Added support for general (non-SN) communications
The existing code was largely set up for SN-to-SN or client-to-SN
communications, where messages can always get to the right place because
we can always send by pubkey.

This doesn't work when we want general communications with a random
remote address.

This commit overhauls the way loki-mq handles communication in a few
important ways:

- Listening instances no longer pass bind addresses into the
constructor; instead they call `listen_curve()` or `listen_plain()`
before invoking `start()`.

- `listen_curve()` is equivalent to the existing bind support: it
listens on a socket and accepts encrypted handshaked connections from
anyone who already knows the server's public key.

- `listen_plain()` is all new: it sets up a plain text listening socket
over which random clients can connect and talk.  End-points aren't
verified, and it isn't encrypted, but if you don't know who you are
talking to then encryption isn't doing anything anyway.

- Connecting to a remote now connections in CURVE encryption or NULL
(plain-text) encryption based on whether you provide a remote_pubkey.
For CURVE, the connection will fail if the pubkey does not match.

- `ConnectionID` objects are now returned when connecting to a remote
address; this object is then passed in to send/request/etc. to direct
the message.  For SN communication, ConnectionID's can be created
implicitly from SN pubkey strings, so the existing interface of
`lmq.send(pubkey, ...)` will still work in most cases.

- A ConnectionID is now passed to the ConnectSuccess and ConnectFailure
callbacks.  This can be used to uniquely identify which connection
succeeded or failed, and can determine whether the remote is a service
node (`.sn()`) and/or the pubkey (`.pubkey()`).  (Obviously the service
node status is only available when the client can do service node
lookups, and the pubkey() is only non-empty for encrypted connections).
2020-02-28 00:16:43 -04:00
Jason Rhinelander e4d371b026 Fixed string_view c++17 compatibility
string_view isn't supposed to be implicitly convertible to std::string
and code would break compiling under c++17 (when our local string_view
is simply a std::string_view typedef).
2020-02-24 22:20:56 -04:00
Jason Rhinelander 58e45db996 Fix truncated pubkey
Fix bug from quorumnet transition; quorumnet set the user id to
something like "S:abc..." or "C:abc..." to indicate SN or non-SN, but
now that gets carried in a separate message property but the +2 on the
copying position was still erroneously being used.
2020-02-16 22:42:03 -04:00
Jason Rhinelander 63e70f9912 Fix delayed proxy-scheduled batch jobs
Batch jobs scheduled by the proxy thread itself were delayed to the next
poll timeout (because nothing ever gets sent on a socket).  Add a
variable to bypass the next poll to handle this case.
2020-02-11 19:08:19 -04:00
Jason Rhinelander ccfb6d080b Add request/reply abstraction
This allows making RPC requests with a callback that gets called when
the response comes back.  The is essentially a wrapper around doing it
yourself (i.e. by setting up a server-side "request" and client-side
"reply" command where "request" responds with a "reply" command), but
abstracted into lokimq itself as it is likely to be very useful when
integrating client/server connections rather than peer-to-peer
connections.
2020-02-11 02:30:07 -04:00