-
Notifications
You must be signed in to change notification settings - Fork 0
Nostr Client #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
buttercat1791
wants to merge
40
commits into
ShadowySupercode:master
Choose a base branch
from
buttercat1791:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Nostr Client #2
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
fdaf89f
Link JSON library to project
buttercat1791 5afbca6
Declare nostr namespace classes in header
buttercat1791 c2a661e
Commit in-progress work
buttercat1791 c56882b
Update build.sh
buttercat1791 f106c9e
Line endings
buttercat1791 0e6f70b
Declare Event struct with built-in serialization
buttercat1791 0d187c2
Configure uWebSockets as dependency library
buttercat1791 762a863
Rename nostr.h -> nostr.hpp
buttercat1791 5913f29
Use WebSocket++ instead of uWebSockets
buttercat1791 e7a1733
Remove header files in include dir
buttercat1791 86cb5a2
Handle relay connection in NostrUtils class
buttercat1791 059c32a
Remove unneeded Boost libraries from CMake
buttercat1791 ba272ef
Fully declare the Event struct in the header
buttercat1791 336876a
Define publishEvent util method
buttercat1791 860e4eb
Clearly define required packages and add plog
buttercat1791 3a25d1f
Add logging with plog
buttercat1791 08879bf
Set LF as end-of-line sequence
buttercat1791 3587803
Declare the event struct in a separate file
buttercat1791 7a8ddac
Handle relay lists smarter
buttercat1791 bc39cbe
Don't try to close connections without a handle
buttercat1791 932e141
Make util methods public
buttercat1791 38cf246
Refactor some logic into helper functions
buttercat1791 3256b62
Setup a fail handler for the WebSocket connection
buttercat1791 17d0c58
Threadify connection and disconnection functions
buttercat1791 b970a01
Add concurrency to publishEvent method
buttercat1791 6cd0f71
Fix forward-declared signature
buttercat1791 88b4144
Rework build scheme and fix bugs
buttercat1791 9fe0ff9
Use the this pointer in NostrUtils methods
buttercat1791 c4bcc12
Better forward-declaration for nostr::Event struct
buttercat1791 ee6d786
Wrap event method definitions in namespace
buttercat1791 b2c5ea3
Use underscore naming for private members
buttercat1791 705c32c
Declare public getter for _defaultRelays member
buttercat1791 03f580e
Configure testing for nostr-ndk
buttercat1791 37eb943
gitrepublic-sdk -> NostrSDK
buttercat1791 07085fb
Add unit tests for NostrUtils constructor
buttercat1791 bef9abf
Refactor service layer and WebSocket client layer
buttercat1791 36db5ad
Test Nostr service with IWebSocketClient mock
buttercat1791 832a0a8
Unit tests and other things
buttercat1791 ed0a9c4
Add more unit tests for connection management
buttercat1791 d7f33bb
Report both successes and failures on publish
buttercat1791 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,4 @@ | ||
| .vscode | ||
|
|
||
| build | ||
| out | ||
| out |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,28 @@ | ||
| cmake_minimum_required(VERSION 3.5) | ||
| project(GitRepublic-Core) | ||
| cmake_minimum_required(VERSION 3.10) | ||
| project(gitrepublic-core) | ||
|
|
||
| set(CMAKE_CXX_STANDARD 17) | ||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
|
||
| set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ../../out/bin/${CMAKE_BUILD_TYPE}) | ||
| set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ../../out/lib/${CMAKE_BUILD_TYPE}) | ||
| set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ../../out/bin/${CMAKE_BUILD_TYPE}) | ||
| set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ../../out/lib/${CMAKE_BUILD_TYPE}) | ||
|
|
||
| # ============== HELLO WORLD EXAMPLE ============== | ||
| set (SOURCE_DIR ./src) | ||
| enable_testing() | ||
| include(GoogleTest) | ||
|
|
||
| set (SOURCES | ||
| ${SOURCE_DIR}/gitrepublic.cpp | ||
| ) | ||
| set (INCLUDE_DIR ./include) | ||
| set(SOURCE_DIR ./src) | ||
| set(SOURCES ${SOURCE_DIR}/gitrepublic.cpp) | ||
|
|
||
| set (HEADERS | ||
| ${INCLUDE_DIR}/gitrepublic.h | ||
| ) | ||
| set(INCLUDE_DIR ./include) | ||
| include_directories(${INCLUDE_DIR}) | ||
| set(HEADERS ${INCLUDE_DIR}/gitrepublic.hpp) | ||
|
|
||
| add_subdirectory(${SOURCE_DIR}/nostr) | ||
|
|
||
| add_executable(gitrepublic-core ${SOURCES} ${HEADERS}) | ||
| add_executable(gitrepublic-core-test ${SOURCES} ${HEADERS} ${TESTS}) | ||
|
|
||
| target_include_directories(gitrepublic-core PRIVATE ${INCLUDE_DIR}) | ||
| # ================================================= | ||
| target_include_directories(gitrepublic-core PUBLIC ${DEPENDENCIES_INCLUDE_DIR}) | ||
|
|
||
| target_link_libraries(gitrepublic-core PRIVATE NostrSDK) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| #pragma once | ||
|
|
||
| #include <string> | ||
|
|
||
| namespace client | ||
| { | ||
| /** | ||
| * @brief An interface for a WebSocket client singleton. | ||
| */ | ||
| class IWebSocketClient | ||
| { | ||
| public: | ||
| /** | ||
| * @brief Starts the client. | ||
| * @remark This method must be called before any other client methods. | ||
| */ | ||
| virtual void start() = 0; | ||
|
|
||
| /** | ||
| * @brief Stops the client. | ||
| * @remark This method should be called when the client is no longer needed, before it is | ||
| * destroyed. | ||
| */ | ||
| virtual void stop() = 0; | ||
|
|
||
| /** | ||
| * @brief Opens a connection to the given server. | ||
| */ | ||
| virtual void openConnection(std::string uri) = 0; | ||
|
|
||
| /** | ||
| * @brief Indicates whether the client is connected to the given server. | ||
| * @returns True if the client is connected, false otherwise. | ||
| */ | ||
| virtual bool isConnected(std::string uri) = 0; | ||
|
|
||
| /** | ||
| * @brief Sends the given message to the given server. | ||
| * @returns A tuple indicating the server URI and whether the message was successfully | ||
| * sent. | ||
| */ | ||
| virtual std::tuple<std::string, bool> send(std::string message, std::string uri) = 0; | ||
|
|
||
| /** | ||
| * @brief Closes the connection to the given server. | ||
| */ | ||
| virtual void closeConnection(std::string uri) = 0; | ||
| }; | ||
| } // namespace client |
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #pragma once | ||
|
|
||
| #include <string> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| #pragma once | ||
|
|
||
| #include <mutex> | ||
| #include <string> | ||
| #include <tuple> | ||
| #include <vector> | ||
|
|
||
| #include <nlohmann/json.hpp> | ||
| #include <plog/Log.h> | ||
| #include <websocketpp/client.hpp> | ||
| #include <websocketpp/config/asio_client.hpp> | ||
|
|
||
| #include "client/web_socket_client.hpp" | ||
|
|
||
| namespace nostr | ||
| { | ||
| typedef std::vector<std::string> RelayList; | ||
|
|
||
| // TODO: Add null checking to seralization and deserialization methods. | ||
| /** | ||
| * @brief A Nostr event. | ||
| * @remark All data transmitted over the Nostr protocol is encoded in JSON blobs. This struct | ||
| * is common to every Nostr event kind. The significance of each event is determined by the | ||
| * `tags` and `content` fields. | ||
| */ | ||
| struct Event | ||
| { | ||
| std::string id; ///< SHA-256 hash of the event data. | ||
| std::string pubkey; ///< Public key of the event creator. | ||
| std::string created_at; ///< Unix timestamp of the event creation. | ||
| int kind; ///< Event kind. | ||
| std::vector<std::vector<std::string>> tags; ///< Arbitrary event metadata. | ||
| std::string content; ///< Event content. | ||
| std::string sig; ///< Event signature created with the private key of the event creator. | ||
|
|
||
| nlohmann::json serialize() const; | ||
| void deserialize(std::string jsonString); | ||
| }; | ||
|
|
||
| class NostrService | ||
| { | ||
| public: | ||
| NostrService(plog::IAppender* appender, client::IWebSocketClient* client); | ||
| NostrService(plog::IAppender* appender, client::IWebSocketClient* client, RelayList relays); | ||
| ~NostrService(); | ||
|
|
||
| RelayList defaultRelays() const; | ||
|
|
||
| RelayList activeRelays() const; | ||
|
|
||
| /** | ||
| * @brief Opens connections to the default Nostr relays of the instance, as specified in | ||
| * the constructor. | ||
| * @return A list of the relay URLs to which connections were successfully opened. | ||
| */ | ||
| RelayList openRelayConnections(); | ||
|
|
||
| /** | ||
| * @brief Opens connections to the specified Nostr relays. | ||
| * @returns A list of the relay URLs to which connections were successfully opened. | ||
| */ | ||
| RelayList openRelayConnections(RelayList relays); | ||
|
|
||
| /** | ||
| * @brief Closes all open relay connections. | ||
| */ | ||
| void closeRelayConnections(); | ||
|
|
||
| /** | ||
| * @brief Closes any open connections to the specified Nostr relays. | ||
| */ | ||
| void closeRelayConnections(RelayList relays); | ||
|
|
||
| /** | ||
| * @brief Publishes a Nostr event to all open relay connections. | ||
| * @returns A tuple of `RelayList` objects, of the form `<successes, failures>`, indicating | ||
| * to which relays the event was published successfully, and to which relays the event failed | ||
| * to publish. | ||
| */ | ||
| std::tuple<RelayList, RelayList> publishEvent(Event event); | ||
|
|
||
| // TODO: Add methods for reading events from relays. | ||
|
|
||
| private: | ||
| std::mutex _propertyMutex; | ||
| RelayList _defaultRelays; | ||
| RelayList _activeRelays; | ||
| client::IWebSocketClient* _client; | ||
|
|
||
| /** | ||
| * @brief Determines which of the given relays are currently connected. | ||
| * @returns A list of the URIs of currently-open relay connections from the given list. | ||
| */ | ||
| RelayList getConnectedRelays(RelayList relays); | ||
|
|
||
| /** | ||
| * @brief Determines which of the given relays are not currently connected. | ||
| * @returns A list of the URIs of currently-unconnected relays from the given list. | ||
| */ | ||
| RelayList getUnconnectedRelays(RelayList relays); | ||
|
|
||
| /** | ||
| * @brief Determines whether the given relay is currently connected. | ||
| * @returns True if the relay is connected, false otherwise. | ||
| */ | ||
| bool isConnected(std::string relay); | ||
|
|
||
| /** | ||
| * @brief Removes the given relay from the instance's list of active relays. | ||
| */ | ||
| void eraseActiveRelay(std::string relay); | ||
|
|
||
| /** | ||
| * @brief Opens a connection from the client to the given relay. | ||
| */ | ||
| void connect(std::string relay); | ||
|
|
||
| /** | ||
| * @brief Closes the connection from the client to the given relay. | ||
| */ | ||
| void disconnect(std::string relay); | ||
| }; | ||
| } // namespace nostr | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #! /bin/bash | ||
|
|
||
| set -eux | ||
|
|
||
| # ================ CLONE QT SOURCES ================ | ||
| git clone git@github.com:qt/qtbase.git | ||
|
|
||
| # ================ INSTALLING QT DEPENDENCIES ================ | ||
| sudo apt-get install -y qt6-base-dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| #include <websocketpp/client.hpp> | ||
| #include <websocketpp/config/asio_client.hpp> | ||
|
|
||
| #include "web_socket_client.hpp" | ||
|
|
||
| using std::error_code; | ||
| using std::lock_guard; | ||
| using std::make_tuple; | ||
| using std::mutex; | ||
| using std::string; | ||
| using std::tuple; | ||
| using std::unordered_map; | ||
|
|
||
| namespace client | ||
| { | ||
| /** | ||
| * @brief An implementation of the `IWebSocketClient` interface that uses the WebSocket++ library. | ||
| */ | ||
| class WebsocketppClient : public IWebSocketClient | ||
| { | ||
| public: | ||
| void start() override | ||
| { | ||
| this->_client.init_asio(); | ||
| this->_client.start_perpetual(); | ||
| }; | ||
|
|
||
| void stop() override | ||
| { | ||
| this->_client.stop_perpetual(); | ||
| this->_client.stop(); | ||
| }; | ||
|
|
||
| void openConnection(string uri) override | ||
| { | ||
| error_code error; | ||
| websocketpp_client::connection_ptr connection = this->_client.get_connection(uri, error); | ||
|
|
||
| if (error.value() == -1) | ||
| { | ||
| // PLOG_ERROR << "Error connecting to relay " << relay << ": " << error.message(); | ||
| } | ||
|
|
||
| // Configure the connection here via the connection pointer. | ||
| connection->set_fail_handler([this, uri](auto handle) { | ||
| // PLOG_ERROR << "Error connecting to relay " << relay << ": Handshake failed."; | ||
| lock_guard<mutex> lock(this->_propertyMutex); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isConnected also locks the mutex - I assume it works, but the lock_guard could be placed inside the if |
||
| if (this->isConnected(uri)) | ||
| { | ||
| this->_connectionHandles.erase(uri); | ||
| } | ||
| }); | ||
|
|
||
| lock_guard<mutex> lock(this->_propertyMutex); | ||
| this->_connectionHandles[uri] = connection->get_handle(); | ||
| this->_client.connect(connection); | ||
| }; | ||
|
|
||
| bool isConnected(string uri) override | ||
| { | ||
| lock_guard<mutex> lock(this->_propertyMutex); | ||
| return this->_connectionHandles.find(uri) != this->_connectionHandles.end(); | ||
| }; | ||
|
|
||
| tuple<string, bool> send(string message, string uri) override | ||
| { | ||
| error_code error; | ||
|
|
||
| // Make sure the connection isn't closed from under us. | ||
| lock_guard<mutex> lock(this->_propertyMutex); | ||
| this->_client.send( | ||
| this->_connectionHandles[uri], | ||
| message, | ||
| websocketpp::frame::opcode::text, | ||
| error); | ||
|
|
||
| if (error.value() == -1) | ||
| { | ||
| // PLOG_ERROR << "Error publishing event to relay " << relay << ": " << error.message(); | ||
| return make_tuple(uri, false); | ||
| } | ||
|
|
||
| return make_tuple(uri, true); | ||
| }; | ||
|
|
||
| void closeConnection(string uri) override | ||
| { | ||
| lock_guard<mutex> lock(this->_propertyMutex); | ||
|
|
||
| websocketpp::connection_hdl handle = this->_connectionHandles[uri]; | ||
| this->_client.close( | ||
| handle, | ||
| websocketpp::close::status::going_away, | ||
| "_client requested close."); | ||
|
|
||
| this->_connectionHandles.erase(uri); | ||
| }; | ||
|
|
||
| private: | ||
| typedef websocketpp::client<websocketpp::config::asio_client> websocketpp_client; | ||
| typedef unordered_map<string, websocketpp::connection_hdl>::iterator connection_hdl_iterator; | ||
|
|
||
| websocketpp_client _client; | ||
| unordered_map<string, websocketpp::connection_hdl> _connectionHandles; | ||
| mutex _propertyMutex; | ||
| }; | ||
| } // namespace client | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,8 @@ | ||
| #include <gitrepublic.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "gitrepublic.hpp" | ||
|
|
||
| int main(int argc, char **argv) | ||
| { | ||
| printf("Hello GitRepublic\n"); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.