diff --git a/include/sendspin/client.h b/include/sendspin/client.h index 31be11d..9ec2359 100644 --- a/include/sendspin/client.h +++ b/include/sendspin/client.h @@ -21,6 +21,7 @@ #include "sendspin/types.h" #include +#include #include #include #include @@ -409,9 +410,11 @@ class SendspinClient { /// @brief Processes a JSON message from a connection /// @param conn The connection that received the message - /// @param message The raw JSON text + /// @param data Pointer to the raw JSON text (not null-terminated; valid for the duration of the + /// call only) + /// @param len Length of the JSON text in bytes /// @param timestamp Receive timestamp in microseconds - void process_json_message(SendspinConnection* conn, const std::string& message, + void process_json_message(SendspinConnection* conn, const char* data, size_t len, int64_t timestamp); /// @brief Processes a binary message from a connection diff --git a/src/client.cpp b/src/client.cpp index 45fd5ef..cc08835 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -483,10 +483,10 @@ std::string SendspinClient::build_hello_message() { // Message processing // ============================================================================ -void SendspinClient::process_json_message(SendspinConnection* conn, const std::string& message, +void SendspinClient::process_json_message(SendspinConnection* conn, const char* data, size_t len, int64_t timestamp) { JsonDocument doc = make_json_document(); - DeserializationError error = deserializeJson(doc, message.c_str(), message.size()); + DeserializationError error = deserializeJson(doc, data, len); if (error || doc.isNull()) { SS_LOGW(TAG, "Failed to parse JSON message"); return; diff --git a/src/connection.cpp b/src/connection.cpp index 74eb0e5..022e10d 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -96,13 +96,14 @@ SS_HOT void SendspinConnection::dispatch_completed_message(bool is_text, int64_t } if (is_text) { - // Create string from payload for JSON processing - const std::string message(this->websocket_payload_.data(), - this->websocket_payload_.data() + this->websocket_write_offset_); - - // Invoke JSON message callback + // Hand the JSON callback a pointer straight into the reassembly buffer instead of copying + // it into a std::string. The callback parses synchronously; reset_websocket_payload() + // below makes the buffer reusable as soon as it returns, so the callback must not retain + // the pointer. Not null-terminated; the length is authoritative. if (this->on_json_message_cb) { - this->on_json_message_cb(this, message, receive_time); + this->on_json_message_cb(this, + reinterpret_cast(this->websocket_payload_.data()), + this->websocket_write_offset_, receive_time); } } else { // Binary message - connection retains buffer ownership, callback reads in-place diff --git a/src/connection.h b/src/connection.h index e3e006a..c0363de 100644 --- a/src/connection.h +++ b/src/connection.h @@ -63,7 +63,7 @@ using SendCompleteCallback = std::function; * // Concrete subclass provided by the platform layer * auto conn = std::make_unique(url, config); * conn->on_connected_cb = [](SendspinConnection* c) { c->send_text_message(hello_json, {}); }; - * conn->on_json_message_cb = [](SendspinConnection* c, const std::string& msg, int64_t t) { ... }; + * conn->on_json_message_cb = [](SendspinConnection* c, const char* d, size_t n, int64_t t) {...}; * conn->on_disconnected_cb = [](SendspinConnection* c) { handle_disconnect(); }; * conn->start(); * // Call conn->loop() from a periodic task @@ -165,9 +165,12 @@ class SendspinConnection : public std::enable_shared_from_this on_json_message_cb; + std::function on_json_message_cb; /// @brief Callback invoked when a binary message is received /// @param conn Pointer to this connection. @@ -321,9 +324,10 @@ class SendspinConnection : public std::enable_shared_from_this lock(this->conn_mutex_); this->pending_connected_events_.push_back(c->shared_from_this()); }; - conn->on_json_message_cb = [this](SendspinConnection* c, const std::string& message, + conn->on_json_message_cb = [this](SendspinConnection* c, const char* data, size_t len, int64_t timestamp) { - this->client_->process_json_message(c, message, timestamp); + this->client_->process_json_message(c, data, len, timestamp); }; conn->on_binary_message_cb = [this](SendspinConnection* /*c*/, uint8_t* payload, size_t len) { this->client_->process_binary_message(payload, len); diff --git a/src/host/client_connection.h b/src/host/client_connection.h index c24f8a7..1aead19 100644 --- a/src/host/client_connection.h +++ b/src/host/client_connection.h @@ -42,8 +42,8 @@ namespace sendspin { * * @code * auto conn = std::make_unique("ws://192.168.1.10:8928"); - * conn->on_json_message_cb = [](SendspinConnection*, const std::string& msg, int64_t) { - * handle(msg); + * conn->on_json_message_cb = [](SendspinConnection*, const char* data, size_t len, int64_t) { + * handle(data, len); * }; conn->start(); * // periodically: * conn->loop();