Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/reusable/cached-install/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ runs:
id: cache-buildtree
uses: actions/cache/restore@v4
with:
key: ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-buildtree-v1-${{ steps.keys.outputs.vcpkg_sha }}-${{ github.sha }}
key: ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-buildtree-v2-${{ steps.keys.outputs.vcpkg_sha }}-${{ github.sha }}
restore-keys: |
${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-buildtree-v1-${{ steps.keys.outputs.vcpkg_sha }}-
${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-buildtree-v1-
${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-buildtree-v2-${{ steps.keys.outputs.vcpkg_sha }}-
${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-buildtree-v2-
path: |
./build
!./build/vcpkg_installed
Expand Down Expand Up @@ -160,7 +160,7 @@ runs:
if: github.ref == 'refs/heads/main' && steps.cache-buildtree.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
key: ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-buildtree-v1-${{ steps.keys.outputs.vcpkg_sha }}-${{ github.sha }}
key: ${{ runner.arch }}-${{ runner.os }}-${{ steps.keys.outputs.platform }}-buildtree-v2-${{ steps.keys.outputs.vcpkg_sha }}-${{ github.sha }}
path: |
./build
!./build/vcpkg_installed
22 changes: 18 additions & 4 deletions packages/streamr-libstreamrproxyclient/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,23 @@ if (NOT IOS)

add_executable(streamrproxyclient-cpp-wrapper-test ${CMAKE_CURRENT_LIST_DIR}/wrappers/cpp/test/StreamrProxyClientCppWrapperTest.cpp)
target_link_directories(streamrproxyclient-cpp-wrapper-test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/build)

target_include_directories(streamrproxyclient-cpp-wrapper-test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/wrappers/cpp/include)
target_link_libraries(streamrproxyclient-cpp-wrapper-test

target_link_libraries(streamrproxyclient-cpp-wrapper-test
PRIVATE streamrproxyclient
PRIVATE GTest::gtest
PRIVATE GTest::gtest
PRIVATE GTest::gtest_main
)

add_executable(streamrnode-cpp-wrapper-test ${CMAKE_CURRENT_LIST_DIR}/wrappers/cpp/test/StreamrNodeCppWrapperTest.cpp)
target_link_directories(streamrnode-cpp-wrapper-test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/build)

target_include_directories(streamrnode-cpp-wrapper-test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/wrappers/cpp/include)

target_link_libraries(streamrnode-cpp-wrapper-test
PRIVATE streamrproxyclient
PRIVATE GTest::gtest
PRIVATE GTest::gtest_main
)

Expand All @@ -189,6 +200,9 @@ if (NOT IOS)
# default on the 3-core CI runners.
gtest_discover_tests(streamr-streamrnode-test-integration PROPERTIES TIMEOUT 600)
gtest_discover_tests(streamrproxyclient-cpp-wrapper-test)
# Networked two-node round-trip, same budget as the streamrnode
# integration tests.
gtest_discover_tests(streamrnode-cpp-wrapper-test PROPERTIES TIMEOUT 600)
# DISABLED: these tests build the whole streamr-dev/network TS
# monorepo at a 2024 commit (ts-integration/install.sh), which no
# longer works on current CI runners. The streamr network TS
Expand Down
4 changes: 2 additions & 2 deletions packages/streamr-libstreamrproxyclient/VERSION.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set(STREAMRPROXYCLIENT_VERSION
2.0.5
3.0.0
)
set(STREAMRPROXYCLIENT_SOVERSION
2
3
)
102 changes: 102 additions & 0 deletions packages/streamr-libstreamrproxyclient/include/streamrcommon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#ifndef STREAMR_COMMON_H
#define STREAMR_COMMON_H

// Shared infrastructure of the Streamr shared-library C APIs: the result
// and error types, the peer locator struct, and the library lifecycle.
// Used by both the full-node API (streamrnode.h) and the proxy-client API
// (streamrproxyclient.h). These are the FINAL, API-neutral names decided
// in phase D3 of trackerless-network-completion-plan.md; the former
// proxy-prefixed names remain available as deprecated aliases in
// streamrproxyclient.h for one release.

// NOLINTNEXTLINE
#include <stdint.h>

#if defined(__clang__) || defined(__GNUC__)
#define SHARED_EXPORT __attribute__((visibility("default")))
#define SHARED_LOCAL __attribute__((visibility("hidden")))
#define STREAMR_DEPRECATED(msg) __attribute__((deprecated(msg)))
#else
#define SHARED_EXPORT
#define SHARED_LOCAL
#define STREAMR_DEPRECATED(msg)
#endif

#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif

// Error codes shared by both APIs.
#define ERROR_INVALID_ETHEREUM_ADDRESS "INVALID_ETHEREUM_ADDRESS"
#define ERROR_INVALID_STREAM_PART_ID "INVALID_STREAM_PART_ID"

/**
* @brief A peer locator: the websocket URL a node listens on plus the
* ethereum address its node id is derived from. Used both for the proxies
* of the proxy-client API and for the entry points of the full-node API.
*/
// NOLINTNEXTLINE
typedef struct StreamrPeer {
const char* websocketUrl;
const char* ethereumAddress;
} StreamrPeer;

/**
* @brief One error of a failed or partially failed call. code is one of
* the ERROR_* constants; peer points at the peer the error concerns, or
* NULL when the error is not peer-specific.
*/
// NOLINTNEXTLINE
typedef struct StreamrError {
const char* message;
const char* code;
// The peer this error concerns. The member is accessible both as
// `peer` (final name) and as `proxy` (the pre-3.0 spelling, kept for
// source compatibility with proxy-API consumers; same storage).
union {
const struct StreamrPeer* peer;
const struct StreamrPeer* proxy;
};
} StreamrError;

/**
* @brief The result of every call in both APIs, returned through a
* const StreamrResult** out parameter. Every returned result — success or
* error — MUST be freed with streamrResultDelete(). Calls that cannot
* partially succeed leave `successful`/`numSuccessful` unused.
*/
// NOLINTNEXTLINE
typedef struct StreamrResult {
StreamrError* errors;
uint64_t numErrors;
StreamrPeer* successful;
uint64_t numSuccessful;
} StreamrResult;

/**
* @brief Delete a StreamrResult. Must be called on every result returned
* by any call of either API.
*/
EXTERN_C SHARED_EXPORT void streamrResultDelete(
const StreamrResult* streamrResult);

/**
* @brief Initialize the library. Called automatically when the library is
* loaded, but can be called explicitly to force a re-initialization (e.g.
* after streamrCleanupLibrary()).
*/
EXTERN_C SHARED_EXPORT void streamrInitLibrary(void);

/**
* @brief Clean up the library. MUST be called before the program exits:
* the standard dynamic-library destructor runs after static variables
* have already been destroyed, too late to tear down the objects that
* depend on them. Safe to call multiple times. The library may be used
* again after a cleanup: any API call re-initializes it automatically
* (an explicit streamrInitLibrary() call is also fine).
*/
EXTERN_C SHARED_EXPORT void streamrCleanupLibrary(void);

#endif /* STREAMR_COMMON_H */
61 changes: 32 additions & 29 deletions packages/streamr-libstreamrproxyclient/include/streamrnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,25 @@
// trackerless-network-completion-plan.md).
//
// This API lives in the same shared library as the proxy-client API
// (streamrproxyclient.h) and reuses its infrastructure on purpose:
// - Results are reported through the same const ProxyResult** out
// (streamrproxyclient.h) and shares its infrastructure (streamrcommon.h):
// - Results are reported through the same const StreamrResult** out
// parameter in every call; every returned result (success or error)
// MUST be freed with proxyClientResultDelete().
// - The library lifecycle functions proxyClientInitLibrary() /
// proxyClientCleanupLibrary() govern this API too;
// proxyClientCleanupLibrary() stops and deletes any nodes that are
// MUST be freed with streamrResultDelete().
// - The library lifecycle functions streamrInitLibrary() /
// streamrCleanupLibrary() govern this API too;
// streamrCleanupLibrary() stops and deletes any nodes that are
// still alive. As with the proxy API, it MUST be called before the
// process exits (see the note in streamrproxyclient.h).
// - Entry points are (websocketUrl, ethereumAddress) pairs with the
// same layout as struct Proxy; the node id of an entry point is
// derived from its ethereum address exactly like the proxy API
// derives peer ids, so any streamrNode* node can act as an entry
// point for another one.
// NAMING: whether the shared types/lifecycle should be renamed to a
// streamr* prefix (a breaking change for proxy-API users) is left as a
// review decision for this PR.
// process exits (see the note in streamrcommon.h).
// - Entry points are (websocketUrl, ethereumAddress) pairs — struct
// StreamrPeer; the node id of an entry point is derived from its
// ethereum address exactly like the proxy API derives peer ids, so
// any streamrNode* node can act as an entry point for another one.
// (The shared-infrastructure naming decision deferred from the D1 review
// is resolved in phase D3a: neutral streamr* names in streamrcommon.h,
// proxy-prefixed aliases deprecated for one release.)

#include <stdbool.h> // NOLINT
#include "streamrproxyclient.h"
#include "streamrcommon.h"

#define ERROR_NODE_NOT_FOUND "NODE_NOT_FOUND"
#define ERROR_NODE_NOT_STARTED "NODE_NOT_STARTED"
Expand All @@ -37,7 +36,7 @@
// An entry point has the same shape as a proxy: the websocket URL the
// node listens on plus the ethereum address its node id is derived
// from.
typedef Proxy StreamrEntryPoint;
typedef StreamrPeer StreamrEntryPoint;

typedef struct StreamrNodeConfig {
// Entry points of the layer-0 DHT. May be NULL when numEntryPoints
Expand Down Expand Up @@ -87,42 +86,44 @@ typedef void (*StreamrNodeMessageCallback)(
// config may be NULL, which is equivalent to a zeroed config (no entry
// points, no websocket server). Returns the node handle, or 0 on error.
EXTERN_C SHARED_EXPORT uint64_t streamrNodeNew(
const ProxyResult** result,
const StreamrResult** result,
const char* ownEthereumAddress,
const StreamrNodeConfig* config);

// Stops the node if it is still running and releases it. The handle is
// invalid afterwards.
EXTERN_C SHARED_EXPORT void streamrNodeDelete(
const ProxyResult** result, uint64_t nodeHandle);
const StreamrResult** result, uint64_t nodeHandle);

// Starts the node: opens the websocket server (if configured) and
// joins the layer-0 DHT through the configured entry points. Blocks
// until the node is connected to the network. A node cannot be started
// twice, and a stopped node cannot be restarted.
EXTERN_C SHARED_EXPORT void streamrNodeStart(
const ProxyResult** result, uint64_t nodeHandle);
const StreamrResult** result, uint64_t nodeHandle);

// Stops the node and leaves the network. Terminal: the node cannot be
// restarted (create a new one instead). Idempotent.
EXTERN_C SHARED_EXPORT void streamrNodeStop(
const ProxyResult** result, uint64_t nodeHandle);
const StreamrResult** result, uint64_t nodeHandle);

// Joins a stream part. streamPartEntryPoints optionally names nodes
// known to be in the stream part (same convention as the layer-0 entry
// points); when none are given the stream part's entry points are
// discovered through the DHT. Returns once the join has been initiated;
// use streamrNodeGetNeighborCount to observe the topology forming.
EXTERN_C SHARED_EXPORT void streamrNodeJoinStreamPart(
const ProxyResult** result,
const StreamrResult** result,
uint64_t nodeHandle,
const char* streamPartId,
const StreamrEntryPoint* streamPartEntryPoints,
uint64_t numStreamPartEntryPoints);

// Leaves a stream part.
EXTERN_C SHARED_EXPORT void streamrNodeLeaveStreamPart(
const ProxyResult** result, uint64_t nodeHandle, const char* streamPartId);
const StreamrResult** result,
uint64_t nodeHandle,
const char* streamPartId);

// Publishes a message to a stream part (joining it first if needed).
// content is contentLength bytes of opaque payload. ethereumPrivateKey
Expand All @@ -131,7 +132,7 @@ EXTERN_C SHARED_EXPORT void streamrNodeLeaveStreamPart(
// proxyClientPublish. Fire-and-forget: delivery into the overlay is
// not acknowledged.
EXTERN_C SHARED_EXPORT void streamrNodePublish(
const ProxyResult** result,
const StreamrResult** result,
uint64_t nodeHandle,
const char* streamPartId,
const char* content,
Expand All @@ -142,7 +143,7 @@ EXTERN_C SHARED_EXPORT void streamrNodePublish(
// invoked for every message received on it. Returns a subscription
// handle for streamrNodeUnsubscribe, or 0 on error.
EXTERN_C SHARED_EXPORT uint64_t streamrNodeSubscribe(
const ProxyResult** result,
const StreamrResult** result,
uint64_t nodeHandle,
const char* streamPartId,
StreamrNodeMessageCallback callback,
Expand All @@ -151,25 +152,27 @@ EXTERN_C SHARED_EXPORT uint64_t streamrNodeSubscribe(
// Removes a subscription. The callback may still be invoked for
// messages whose dispatch already started when this returns.
EXTERN_C SHARED_EXPORT void streamrNodeUnsubscribe(
const ProxyResult** result,
const StreamrResult** result,
uint64_t nodeHandle,
uint64_t subscriptionHandle);

// Number of neighbors the node currently has in a stream part's
// delivery topology.
EXTERN_C SHARED_EXPORT uint64_t streamrNodeGetNeighborCount(
const ProxyResult** result, uint64_t nodeHandle, const char* streamPartId);
const StreamrResult** result,
uint64_t nodeHandle,
const char* streamPartId);

// Connects the stream part through proxy nodes instead of joining its
// topology (the proxy mode of the old proxy-client API folded into the
// node handle). direction selects publishing or subscribing through
// the proxies; connectionCount 0 means "connect to all given proxies".
// Passing numProxies 0 disconnects the stream part from its proxies.
EXTERN_C SHARED_EXPORT void streamrNodeSetProxies(
const ProxyResult** result,
const StreamrResult** result,
uint64_t nodeHandle,
const char* streamPartId,
const Proxy* proxies,
const StreamrPeer* proxies,
uint64_t numProxies,
StreamrProxyDirection direction,
uint64_t connectionCount);
Expand Down
Loading
Loading