Skip to content

Commit 430f66f

Browse files
committed
Add various bugfixes
1 parent ff7bd32 commit 430f66f

File tree

20 files changed

+155
-74
lines changed

20 files changed

+155
-74
lines changed

include/http/HTTPRequestManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ namespace OpenShock::HTTP {
7979

8080
T data;
8181
if (!jsonParser(response.code, json, data)) {
82+
cJSON_Delete(json);
8283
return {RequestResult::ParseFailed, response.code, {}};
8384
}
8485

src/CommandHandler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ static void commandhandler_keepalivetask(void* arg)
8686
if (cmdRef.lastActivityTimestamp + KEEP_ALIVE_INTERVAL < now) {
8787
OS_LOGV(TAG, "Sending keep-alive for shocker %u", cmdRef.shockerId);
8888

89+
ScopedReadLock rfLock__(&s_rfTransmitterMutex);
8990
if (s_rfTransmitter == nullptr) {
9091
OS_LOGW(TAG, "RF Transmitter is not initialized, ignoring keep-alive");
9192
break;
@@ -229,6 +230,7 @@ bool CommandHandler::Init()
229230

230231
bool CommandHandler::Ok()
231232
{
233+
ScopedReadLock lock__(&s_rfTransmitterMutex);
232234
return s_rfTransmitter != nullptr;
233235
}
234236

@@ -278,6 +280,7 @@ bool CommandHandler::SetKeepAliveEnabled(bool enabled)
278280

279281
gpio_num_t CommandHandler::GetRfTxPin()
280282
{
283+
ScopedReadLock lock__(&s_rfTransmitterMutex);
281284
if (s_rfTransmitter != nullptr) {
282285
return s_rfTransmitter->GetTxPin();
283286
}

src/EStopManager.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ static OpenShock::SimpleMutex s_estopMutex = {};
3333
static gpio_num_t s_estopPin = GPIO_NUM_NC;
3434
static TaskHandle_t s_estopTask = nullptr;
3535

36-
static EStopState s_lastPublishedState = EStopState::Idle;
37-
static bool s_estopActive = false;
38-
static int64_t s_estopActivatedAt = 0;
36+
static EStopState s_lastPublishedState = EStopState::Idle;
37+
static volatile bool s_estopActive = false;
38+
static volatile int64_t s_estopActivatedAt = 0;
3939

4040
static volatile bool s_externallyTriggered = false;
4141

src/GatewayClient.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,6 @@ void GatewayClient::_sendBootStatus()
155155

156156
void GatewayClient::_handleEvent(WStype_t type, uint8_t* payload, std::size_t length)
157157
{
158-
(void)payload;
159-
160158
switch (type) {
161159
case WStype_DISCONNECTED:
162160
_setState(GatewayClientState::Disconnected);

src/GatewayConnectionManager.cpp

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ const char* const TAG = "GatewayConnectionManager";
1010
#include "http/JsonAPI.h"
1111
#include "Logging.h"
1212

13+
#include "SimpleMutex.h"
14+
15+
#include <atomic>
1316
#include <unordered_map>
1417

1518
//
@@ -34,25 +37,29 @@ const uint8_t FLAG_LINKED = 1 << 1;
3437

3538
const uint8_t LINK_CODE_LENGTH = 6;
3639

37-
static uint8_t s_flags = 0;
38-
static int64_t s_lastAuthFailure = 0;
39-
static int64_t s_lastConnectionAttempt = 0;
40+
static std::atomic<uint8_t> s_flags = 0;
41+
static std::atomic<int64_t> s_lastAuthFailure = 0;
42+
static std::atomic<int64_t> s_lastConnectionAttempt = 0;
43+
static OpenShock::SimpleMutex s_clientMutex;
4044
static std::unique_ptr<OpenShock::GatewayClient> s_wsClient = nullptr;
4145

4246
static void evh_gotIP(arduino_event_t* event)
4347
{
4448
(void)event;
4549

46-
s_flags |= FLAG_HAS_IP;
50+
s_flags.fetch_or(FLAG_HAS_IP, std::memory_order_relaxed);
4751
OS_LOGD(TAG, "Got IP address");
4852
}
4953

5054
static void evh_wiFiDisconnected(arduino_event_t* event)
5155
{
5256
(void)event;
5357

54-
s_flags = FLAG_NONE;
55-
s_wsClient = nullptr;
58+
s_flags.store(FLAG_NONE, std::memory_order_relaxed);
59+
{
60+
OpenShock::ScopedLock lock__(&s_clientMutex);
61+
s_wsClient = nullptr;
62+
}
5663
OS_LOGD(TAG, "Lost IP address");
5764
}
5865

@@ -79,6 +86,7 @@ bool GatewayConnectionManager::Init()
7986

8087
bool GatewayConnectionManager::IsConnected()
8188
{
89+
ScopedLock lock__(&s_clientMutex);
8290
if (s_wsClient == nullptr) {
8391
return false;
8492
}
@@ -88,15 +96,18 @@ bool GatewayConnectionManager::IsConnected()
8896

8997
bool GatewayConnectionManager::IsLinked()
9098
{
91-
return (s_flags & FLAG_LINKED) != 0;
99+
return (s_flags.load(std::memory_order_relaxed) & FLAG_LINKED) != 0;
92100
}
93101

94102
AccountLinkResultCode GatewayConnectionManager::Link(std::string_view linkCode)
95103
{
96-
if ((s_flags & FLAG_HAS_IP) == 0) {
104+
if ((s_flags.load(std::memory_order_relaxed) & FLAG_HAS_IP) == 0) {
97105
return AccountLinkResultCode::NoInternetConnection;
98106
}
99-
s_wsClient = nullptr;
107+
{
108+
ScopedLock lock__(&s_clientMutex);
109+
s_wsClient = nullptr;
110+
}
100111

101112
OS_LOGD(TAG, "Attempting to link to account using code %.*s", linkCode.length(), linkCode.data());
102113

@@ -136,20 +147,24 @@ AccountLinkResultCode GatewayConnectionManager::Link(std::string_view linkCode)
136147
return AccountLinkResultCode::InternalError;
137148
}
138149

139-
s_flags |= FLAG_LINKED;
150+
s_flags.fetch_or(FLAG_LINKED, std::memory_order_relaxed);
140151
OS_LOGD(TAG, "Successfully linked to account");
141152

142153
return AccountLinkResultCode::Success;
143154
}
144155
void GatewayConnectionManager::UnLink()
145156
{
146-
s_flags &= FLAG_HAS_IP;
147-
s_wsClient = nullptr;
157+
s_flags.fetch_and(static_cast<uint8_t>(~FLAG_LINKED), std::memory_order_relaxed);
158+
{
159+
ScopedLock lock__(&s_clientMutex);
160+
s_wsClient = nullptr;
161+
}
148162
Config::ClearBackendAuthToken();
149163
}
150164

151165
bool GatewayConnectionManager::SendMessageTXT(std::string_view data)
152166
{
167+
ScopedLock lock__(&s_clientMutex);
153168
if (s_wsClient == nullptr) {
154169
return false;
155170
}
@@ -159,6 +174,7 @@ bool GatewayConnectionManager::SendMessageTXT(std::string_view data)
159174

160175
bool GatewayConnectionManager::SendMessageBIN(tcb::span<const uint8_t> data)
161176
{
177+
ScopedLock lock__(&s_clientMutex);
162178
if (s_wsClient == nullptr) {
163179
return false;
164180
}
@@ -169,7 +185,7 @@ bool GatewayConnectionManager::SendMessageBIN(tcb::span<const uint8_t> data)
169185
bool FetchHubInfo(std::string authToken)
170186
{
171187
// TODO: this function is very slow, should be optimized!
172-
if ((s_flags & FLAG_HAS_IP) == 0) {
188+
if ((s_flags.load(std::memory_order_relaxed) & FLAG_HAS_IP) == 0) {
173189
return false;
174190
}
175191

@@ -181,7 +197,7 @@ bool FetchHubInfo(std::string authToken)
181197

182198
if (response.code == 401) {
183199
OS_LOGD(TAG, "Auth token is invalid, waiting 5 minutes before checking again");
184-
s_lastAuthFailure = OpenShock::micros();
200+
s_lastAuthFailure = OpenShock::millis();
185201
return false;
186202
}
187203

@@ -205,7 +221,7 @@ bool FetchHubInfo(std::string authToken)
205221
OS_LOGI(TAG, " [%s] rf=%u model=%u", shocker.id.c_str(), shocker.rfId, shocker.model);
206222
}
207223

208-
s_flags |= FLAG_LINKED;
224+
s_flags.fetch_or(FLAG_LINKED, std::memory_order_relaxed);
209225

210226
return true;
211227
}
@@ -245,7 +261,7 @@ bool StartConnectingToLCG()
245261

246262
if (response.code == 401) {
247263
OS_LOGD(TAG, "Auth token is invalid, waiting 5 minutes before retrying");
248-
s_lastAuthFailure = OpenShock::micros();
264+
s_lastAuthFailure = OpenShock::millis();
249265
return false;
250266
}
251267

@@ -270,9 +286,11 @@ bool StartConnectingToLCG()
270286

271287
void GatewayConnectionManager::Update()
272288
{
289+
ScopedLock lock__(&s_clientMutex);
290+
273291
if (s_wsClient == nullptr) {
274292
// Can't connect to the API without WiFi or an auth token
275-
if ((s_flags & FLAG_HAS_IP) == 0 || !Config::HasBackendAuthToken()) {
293+
if ((s_flags.load(std::memory_order_relaxed) & FLAG_HAS_IP) == 0 || !Config::HasBackendAuthToken()) {
276294
return;
277295
}
278296

@@ -287,7 +305,7 @@ void GatewayConnectionManager::Update()
287305
return;
288306
}
289307

290-
s_flags |= FLAG_LINKED;
308+
s_flags.fetch_or(FLAG_LINKED, std::memory_order_relaxed);
291309
OS_LOGD(TAG, "Successfully verified auth token");
292310

293311
s_wsClient = std::make_unique<GatewayClient>(authToken);

src/ReadWriteMutex.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ bool OpenShock::ReadWriteMutex::lockRead(TickType_t xTicksToWait)
2929

3030
if (++m_readers == 1) {
3131
if (xSemaphoreTake(m_mutex, xTicksToWait) == pdFALSE) {
32+
--m_readers;
3233
xSemaphoreGive(m_readSem);
3334
return false;
3435
}

src/VisualStateManager.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const char* const TAG = "VisualStateManager";
1111
#include "PinPatternManager.h"
1212
#include "RGBPatternManager.h"
1313

14+
#include <atomic>
1415
#include <memory>
1516

1617
#ifndef OPENSHOCK_LED_GPIO
@@ -32,22 +33,22 @@ const uint64_t kWiFiScanningFlag = 1 << 7;
3233
// Bitmask of when the system is running normally
3334
const uint64_t kStatusOKMask = kWebSocketConnectedFlag | kHasIpAddressFlag | kWiFiConnectedFlag;
3435

35-
static uint64_t s_stateFlags = 0;
36+
static std::atomic<uint64_t> s_stateFlags = 0;
3637
static std::shared_ptr<OpenShock::PinPatternManager> s_builtInLedManager;
3738
static std::shared_ptr<OpenShock::RGBPatternManager> s_RGBLedManager;
3839

3940
inline void _setStateFlag(uint64_t flag, bool state)
4041
{
4142
if (state) {
42-
s_stateFlags |= flag;
43+
s_stateFlags.fetch_or(flag, std::memory_order_relaxed);
4344
} else {
44-
s_stateFlags &= ~flag;
45+
s_stateFlags.fetch_and(~flag, std::memory_order_relaxed);
4546
}
4647
}
4748

4849
inline bool _isStateFlagSet(uint64_t flag)
4950
{
50-
return s_stateFlags & flag;
51+
return s_stateFlags.load(std::memory_order_relaxed) & flag;
5152
}
5253

5354
using namespace OpenShock;
@@ -384,7 +385,7 @@ bool VisualStateManager::Init()
384385

385386
err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, _handleEspWiFiEvent, nullptr);
386387
if (err != ESP_OK) {
387-
OS_LOGE(TAG, "Failed to register event handler for IP_EVENT: %s", esp_err_to_name(err));
388+
OS_LOGE(TAG, "Failed to register event handler for WIFI_EVENT: %s", esp_err_to_name(err));
388389
return false;
389390
}
390391

src/WebSocketDeFragger.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ void WebSocketDeFragger::start(uint8_t socketId, WebSocketMessageType type, cons
9191
auto it = m_messages.find(socketId);
9292
if (it != m_messages.end()) {
9393
it->second.data.assign(data, length);
94+
it->second.type = type;
9495
return;
9596
}
9697

src/captiveportal/Manager.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@ const char* const TAG = "CaptivePortal";
1717

1818
#include <esp_timer.h>
1919

20+
#include "SimpleMutex.h"
21+
2022
#include <memory>
2123

2224
using namespace OpenShock;
2325

24-
static bool s_alwaysEnabled = false;
25-
static bool s_forceClosed = false;
26-
static esp_timer_handle_t s_captivePortalUpdateLoopTimer = nullptr;
26+
static volatile bool s_alwaysEnabled = false;
27+
static volatile bool s_forceClosed = false;
28+
static esp_timer_handle_t s_captivePortalUpdateLoopTimer = nullptr;
29+
static SimpleMutex s_instanceMutex;
2730
static std::unique_ptr<CaptivePortal::CaptivePortalInstance> s_instance = nullptr;
2831

2932
static bool captiveportal_start()
@@ -83,6 +86,8 @@ static void captiveportal_updateloop(void*)
8386
bool commandHandlerOk = CommandHandler::Ok();
8487
bool shouldBeRunning = (s_alwaysEnabled || !gatewayConnected || !commandHandlerOk) && !s_forceClosed;
8588

89+
ScopedLock lock__(&s_instanceMutex);
90+
8691
if (s_instance == nullptr) {
8792
if (shouldBeRunning) {
8893
OS_LOGD(TAG, "Starting captive portal");
@@ -166,11 +171,13 @@ bool CaptivePortal::ForceClose(uint32_t timeoutMs)
166171

167172
bool CaptivePortal::IsRunning()
168173
{
174+
ScopedLock lock__(&s_instanceMutex);
169175
return s_instance != nullptr;
170176
}
171177

172178
bool CaptivePortal::SendMessageTXT(uint8_t socketId, std::string_view data)
173179
{
180+
ScopedLock lock__(&s_instanceMutex);
174181
if (s_instance == nullptr) return false;
175182

176183
s_instance->sendMessageTXT(socketId, data);
@@ -179,6 +186,7 @@ bool CaptivePortal::SendMessageTXT(uint8_t socketId, std::string_view data)
179186
}
180187
bool CaptivePortal::SendMessageBIN(uint8_t socketId, tcb::span<const uint8_t> data)
181188
{
189+
ScopedLock lock__(&s_instanceMutex);
182190
if (s_instance == nullptr) return false;
183191

184192
s_instance->sendMessageBIN(socketId, data);
@@ -188,6 +196,7 @@ bool CaptivePortal::SendMessageBIN(uint8_t socketId, tcb::span<const uint8_t> da
188196

189197
bool CaptivePortal::BroadcastMessageTXT(std::string_view data)
190198
{
199+
ScopedLock lock__(&s_instanceMutex);
191200
if (s_instance == nullptr) return false;
192201

193202
s_instance->broadcastMessageTXT(data);
@@ -196,6 +205,7 @@ bool CaptivePortal::BroadcastMessageTXT(std::string_view data)
196205
}
197206
bool CaptivePortal::BroadcastMessageBIN(tcb::span<const uint8_t> data)
198207
{
208+
ScopedLock lock__(&s_instanceMutex);
199209
if (s_instance == nullptr) return false;
200210

201211
s_instance->broadcastMessageBIN(data);

src/captiveportal/RFC8908Handler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ void CaptivePortal::RFC8908Handler::handleRequest(AsyncWebServerRequest* request
8585
cJSON_AddStringToObject(doc, "user-portal-url", portalUrl.c_str());
8686
cJSON_AddStringToObject(doc, "venue-info-url", "https://openshock.org");
8787

88-
AsyncWebServerResponse* response = request->beginResponse(200, "application/captive+json", cJSON_Print(doc));
88+
char* jsonStr = cJSON_Print(doc);
89+
AsyncWebServerResponse* response = request->beginResponse(200, "application/captive+json", jsonStr);
90+
cJSON_free(jsonStr);
8991

9092
response->addHeader("Cache-Control", "private");
9193
request->send(response);

0 commit comments

Comments
 (0)