Skip to content
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

Ledger synchronization #2675

Merged
merged 47 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
80cabba
Define possible states when synchronizing one or more ledgers
sergeuz Jul 21, 2023
8cb5b53
Initial state machine for ledger synchronization
sergeuz Jul 25, 2023
1f21c50
Refactoring
sergeuz Jul 26, 2023
3e68380
Define the new CoAP API
sergeuz Jul 28, 2023
fb270da
Initial implementation of the new CoAP API
sergeuz Aug 14, 2023
f84be3a
Refactoring
sergeuz Aug 16, 2023
895920a
Shut down the new CoAP channel when the connection is closed; support…
sergeuz Aug 17, 2023
4907639
Mark the new CoAP channel as open after the handshake
sergeuz Aug 17, 2023
b762084
Bugfixes
sergeuz Aug 18, 2023
a1d4ace
Update submodule refs; regenerate protocol files
sergeuz Aug 23, 2023
4e55f9b
Use the new CoAP API for sending/receiving ledger requests
sergeuz Aug 23, 2023
ab69a74
Add missing request handlers; refactoring
sergeuz Aug 30, 2023
7651680
Handle reset info requests; support notifications for multiple ledger…
sergeuz Sep 5, 2023
46fe5c5
Bugfixes
sergeuz Sep 6, 2023
22de801
Allow rewinding a ledger reader; bugfixes
sergeuz Sep 12, 2023
395ffdf
Refactoring
sergeuz Sep 13, 2023
f5d3144
Minor fixes
sergeuz Sep 14, 2023
0826556
Encode ledger data as CBOR
sergeuz Sep 14, 2023
a5a0a82
Decode ledger data as CBOR
sergeuz Sep 18, 2023
c6bce08
Make Stream::readBytes virtual
sergeuz Sep 19, 2023
6d66612
Use Wiring streams for encoding/decoding Variant as CBOR
sergeuz Sep 19, 2023
79f56bc
Add unit tests; fix error handling
sergeuz Sep 20, 2023
942c669
Increase the maximum number of arguments supported by PP_COUNT and PP…
sergeuz Sep 22, 2023
6398874
Minor fixes
sergeuz Sep 22, 2023
10d21f9
Initial support for CoAP blockwise transfer
sergeuz Sep 22, 2023
c038451
Refactoring
sergeuz Oct 4, 2023
ff7ae3f
Require the server to use a ETag option with all blockwise responses
sergeuz Oct 4, 2023
5396230
Allow cancelling a request by ID; refactoring
sergeuz Oct 4, 2023
6d62959
Refactoring
sergeuz Oct 5, 2023
8931639
Bugfixes
sergeuz Oct 6, 2023
b7d7f02
Disable error messages on nRF52 platforms to free some flash space
sergeuz Oct 12, 2023
0364a7d
Add ledger_get_names()
sergeuz Oct 23, 2023
0e7af28
Ledger test app; minor bugfixes
sergeuz Oct 24, 2023
2f9f32a
Add docs; minor fixes
sergeuz Oct 25, 2023
40bc132
Store an opaque scope ID along with ledger data
sergeuz Nov 8, 2023
a64f41d
Add batch mode to some commands
sergeuz Nov 8, 2023
d212a25
Bugfixes
sergeuz Nov 8, 2023
3576404
Add a Request-Tag option to blockwise requests
sergeuz Nov 13, 2023
1fadb1e
Take over the message buffer when starting a new request or response …
sergeuz Nov 15, 2023
c082128
Minor fixes
sergeuz Nov 15, 2023
e98287c
Store a counter that gets incremented every time the ledger is changed
sergeuz Nov 15, 2023
99b40c0
Retry synchronization after a delay
sergeuz Nov 15, 2023
198359f
Add Particle.useLedgers() method; minor fixes
sergeuz Nov 17, 2023
d9142af
Minor fixes
sergeuz Dec 6, 2023
9cab5a9
Update submodule refs
sergeuz Dec 6, 2023
12e80f5
Bugfixes
sergeuz Dec 7, 2023
0873de2
Disable mbedTLS server support
sergeuz Dec 8, 2023
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
522 changes: 522 additions & 0 deletions communication/inc/coap_api.h

Large diffs are not rendered by default.

154 changes: 154 additions & 0 deletions communication/inc/coap_channel_new.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* Copyright (c) 2023 Particle Industries, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/

#include <memory>
#include <cstdint>

#include "message_channel.h"
#include "coap_api.h"
#include "coap.h" // For token_t

#include "system_tick_hal.h"

#include "ref_count.h"

namespace particle::protocol {

class CoapMessageDecoder;
class Protocol;

namespace experimental {

// This class implements the new experimental protocol API that allows the system to interact with
// the server at the CoAP level. It's meant to be used through the functions defined in coap_api.h
class CoapChannel {
public:
enum Result {
HANDLED = 1 // Returned by the handle* methods
};

~CoapChannel();

// Methods called by the new CoAP API (coap_api.h)

int beginRequest(coap_message** msg, const char* uri, coap_method method, int timeout);
int endRequest(coap_message* msg, coap_response_callback respCallback, coap_ack_callback ackCallback,
coap_error_callback errorCallback, void* callbackArg);

int beginResponse(coap_message** msg, int code, int requestId);
int endResponse(coap_message* msg, coap_ack_callback ackCallback, coap_error_callback errorCallback,
void* callbackArg);

int writePayload(coap_message* msg, const char* data, size_t& size, coap_block_callback blockCallback,
coap_error_callback errorCallback, void* callbackArg);
int readPayload(coap_message* msg, char* data, size_t& size, coap_block_callback blockCallback,
coap_error_callback errorCallback, void* callbackArg);
int peekPayload(coap_message* msg, char* data, size_t size);

void destroyMessage(coap_message* msg);

void cancelRequest(int requestId);

int addRequestHandler(const char* uri, coap_method method, coap_request_callback callback, void* callbackArg);
void removeRequestHandler(const char* uri, coap_method method);

int addConnectionHandler(coap_connection_callback callback, void* callbackArg);
void removeConnectionHandler(coap_connection_callback callback);

// Methods called by the old protocol implementation

void open();
void close(int error = SYSTEM_ERROR_COAP_CONNECTION_CLOSED);

int handleCon(const Message& msg);
int handleAck(const Message& msg);
int handleRst(const Message& msg);

int run();

static CoapChannel* instance();

private:
// Channel state
enum class State {
CLOSED,
OPENING,
OPEN,
CLOSING
};

enum class MessageType {
REQUEST, // Regular or blockwise request carrying request data
BLOCK_REQUEST, // Blockwise request retrieving a block of response data
RESPONSE // Regular or blockwise response
};

enum class MessageState {
NEW, // Message created
READ, // Reading payload data
WRITE, // Writing payload data
WAIT_ACK, // Waiting for an ACK
WAIT_RESPONSE, // Waiting for a response
WAIT_BLOCK, // Waiting for the next message block
DONE // Message exchange completed
};

struct CoapMessage;
struct RequestMessage;
struct ResponseMessage;
struct RequestHandler;
struct ConnectionHandler;

CoapChannel(); // Use instance()

Message msgBuf_; // Reference to the shared message buffer
ConnectionHandler* connHandlers_; // List of registered connection handlers
RequestHandler* reqHandlers_; // List of registered request handlers
RequestMessage* sentReqs_; // List of requests awaiting a response from the server
RequestMessage* recvReqs_; // List of requests awaiting a response from the device
ResponseMessage* blockResps_; // List of responses for which the next message block is expected to be received
CoapMessage* unackMsgs_; // List of messages awaiting an ACK from the server
Protocol* protocol_; // Protocol instance
State state_; // Channel state
uint32_t lastReqTag_; // Last used request tag
int lastMsgId_; // Last used internal message ID
int curMsgId_; // Internal ID of the message stored in the shared buffer
int sessId_; // Counter incremented every time a new session with the server is started
int pendingCloseError_; // If non-zero, the channel needs to be closed
bool openPending_; // If true, the channel needs to be reopened

int handleRequest(CoapMessageDecoder& d);
int handleResponse(CoapMessageDecoder& d);
int handleAck(CoapMessageDecoder& d);

int prepareMessage(const RefCountPtr<CoapMessage>& msg);
int updateMessage(const RefCountPtr<CoapMessage>& msg);
int sendMessage(RefCountPtr<CoapMessage> msg);
void clearMessage(const RefCountPtr<CoapMessage>& msg);

int sendAck(int coapId, bool rst = false);

int handleProtocolError(ProtocolError error);

void releaseMessageBuffer();

system_tick_t millis() const;
};

} // namespace experimental

} // namespace particle::protocol
1 change: 1 addition & 0 deletions communication/inc/protocol_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ enum ProtocolError
IO_ERROR_SOCKET_SEND_FAILED = 33,
IO_ERROR_SOCKET_RECV_FAILED = 34,
IO_ERROR_REMOTE_END_CLOSED = 35,
COAP_ERROR = 36,
// NOTE: when adding more ProtocolError codes, be sure to update toSystemError() in protocol_defs.cpp
UNKNOWN = 0x7FFFF
};
Expand Down
1 change: 1 addition & 0 deletions communication/src/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ CPPSRC += $(TARGET_SRC_PATH)/coap_message_decoder.cpp
CPPSRC += $(TARGET_SRC_PATH)/coap_util.cpp
CPPSRC += $(TARGET_SRC_PATH)/firmware_update.cpp
CPPSRC += $(TARGET_SRC_PATH)/description.cpp
CPPSRC += $(TARGET_SRC_PATH)/coap_channel_new.cpp

# ASM source files included in this build.
ASRC +=
Expand Down
6 changes: 6 additions & 0 deletions communication/src/coap_channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
#undef LOG_COMPILE_TIME_LEVEL

#include "coap_channel.h"
#include "coap_channel_new.h"
#include "service_debug.h"
#include "messages.h"
#include "communication_diagnostic.h"
#include "system_error.h"

namespace particle { namespace protocol {

Expand Down Expand Up @@ -64,6 +66,9 @@ void CoAPMessageStore::message_timeout(CoAPMessage& msg, Channel& channel)
if (msg.is_request()) {
LOG(ERROR, "CoAP message timeout; ID: %d", (int)msg.get_id());
g_unacknowledgedMessageCounter++;
// XXX: This will cancel _all_ messages with a timeout error, not just the timed out one.
// That's not ideal but should be okay while we're transitioning to the new CoAP API
experimental::CoapChannel::instance()->close(SYSTEM_ERROR_COAP_TIMEOUT);
channel.command(MessageChannel::CLOSE);
}
}
Expand Down Expand Up @@ -141,6 +146,7 @@ ProtocolError CoAPMessageStore::receive(Message& msg, Channel& channel, system_t
}
if (msgtype==CoAPType::RESET) {
LOG(WARN, "Received RST message; discarding session");
experimental::CoapChannel::instance()->handleRst(msg);
if (coap_msg) {
coap_msg->notify_delivered_nak();
}
Expand Down
Loading