Skip to content

Commit b7b3acb

Browse files
committed
fix: guard against iterating over potential nils
1 parent a182c5c commit b7b3acb

File tree

10 files changed

+40
-40
lines changed

10 files changed

+40
-40
lines changed

drivers/SmartThings/sonos/src/api/event_handlers.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function CapEventHandlers.handle_group_update(device, group_info)
6565
end
6666

6767
function CapEventHandlers.handle_audio_clip_status(device, clips)
68-
for _, clip in ipairs(clips) do
68+
for _, clip in ipairs(clips or {}) do
6969
if clip.status == "ACTIVE" then
7070
log.debug(st_utils.stringify_table(clip, "Playing Audio Clip: ", false))
7171
elseif clip.status == "DONE" then

drivers/SmartThings/sonos/src/api/sonos_connection.lua

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ local _update_subscriptions_helper = function(
5555
command,
5656
reply_tx
5757
)
58-
for _, namespace in ipairs(namespaces) do
58+
for _, namespace in ipairs(namespaces or {}) do
5959
local wss_msg_header = {
6060
namespace = namespace,
6161
command = command,
@@ -406,7 +406,7 @@ function SonosConnection.new(driver, device)
406406
return
407407
end
408408
local group = household.groups[header.groupId] or { playerIds = {} }
409-
for _, player_id in ipairs(group.player_ids) do
409+
for _, player_id in ipairs(group.player_ids or {}) do
410410
local device_for_player = self.driver:device_for_player(header.householdId, player_id)
411411
--- we've seen situations where these messages can be processed while a device
412412
--- is being deleted so we check for the presence of emit event as a proxy for
@@ -430,7 +430,7 @@ function SonosConnection.new(driver, device)
430430
return
431431
end
432432
local group = household.groups[header.groupId] or { playerIds = {} }
433-
for _, player_id in ipairs(group.player_ids) do
433+
for _, player_id in ipairs(group.player_ids or {}) do
434434
local device_for_player = self.driver:device_for_player(header.householdId, player_id)
435435
--- we've seen situations where these messages can be processed while a device
436436
--- is being deleted so we check for the presence of emit event as a proxy for
@@ -453,7 +453,7 @@ function SonosConnection.new(driver, device)
453453
return
454454
end
455455
local group = household.groups[header.groupId] or { playerIds = {} }
456-
for _, player_id in ipairs(group.player_ids) do
456+
for _, player_id in ipairs(group.player_ids or {}) do
457457
local device_for_player = self.driver:device_for_player(header.householdId, player_id)
458458
--- we've seen situations where these messages can be processed while a device
459459
--- is being deleted so we check for the presence of emit event as a proxy for
@@ -469,7 +469,7 @@ function SonosConnection.new(driver, device)
469469

470470
local household = self.driver.sonos:get_household(header.householdId) or { groups = {} }
471471

472-
for group_id, group in pairs(household.groups) do
472+
for group_id, group in pairs(household.groups or {}) do
473473
local coordinator_id =
474474
self.driver.sonos:get_coordinator_for_group(header.householdId, group_id)
475475
local coordinator_player = household.players[coordinator_id]
@@ -510,7 +510,7 @@ function SonosConnection.new(driver, device)
510510
end
511511
self.driver.sonos:update_household_favorites(header.householdId, new_favorites)
512512

513-
for _, player_id in ipairs(group.player_ids) do
513+
for _, player_id in ipairs(group.player_ids or {}) do
514514
local device_for_player =
515515
self.driver:device_for_player(header.householdId, player_id)
516516
--- we've seen situations where these messages can be processed while a device

drivers/SmartThings/sonos/src/api/sonos_ssdp_discovery.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ function SpeakerDiscoveryInfo.new(ssdp_info, discovery_info)
115115
ret.rest_path = rest_path
116116
end
117117

118-
for k, v in pairs(SpeakerDiscoveryInfo) do
118+
for k, v in pairs(SpeakerDiscoveryInfo or {}) do
119119
rawset(ret, k, v)
120120
end
121121

@@ -227,7 +227,7 @@ local function make_persistent_task_impl(
227227
log.warn(string.format("Select error: %s", select_err))
228228
end
229229

230-
for _, receiver in ipairs(recv_ready) do
230+
for _, receiver in ipairs(recv_ready or {}) do
231231
if receiver == interval_timer then
232232
interval_timer:handled()
233233
ssdp_search_handle:multicast_m_search()
@@ -331,7 +331,7 @@ function SonosPersistentSsdpTask:get_all_known()
331331
-- make a shallow copy of the table so it doesn't get clobbered
332332
-- the player info itself is a read-only proxy table as well
333333
local known = {}
334-
for id, info in pairs(self.player_info_by_sonos_ids) do
334+
for id, info in pairs(self.player_info_by_sonos_ids or {}) do
335335
known[id] = info
336336
end
337337
return known
@@ -454,7 +454,7 @@ function sonos_ssdp.spawn_persistent_ssdp_task()
454454
log.debug(
455455
st_utils.stringify_table(waiting_handles, "waiting for unique keys and mac addresses", true)
456456
)
457-
for _, reply_tx in ipairs(waiting_handles) do
457+
for _, reply_tx in ipairs(waiting_handles or {}) do
458458
reply_tx:send(speaker_info)
459459
end
460460

drivers/SmartThings/sonos/src/api/sonos_websocket_router.lua

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ local pending_close = {}
3939

4040
cosock.spawn(function()
4141
while true do
42-
for _, unique_key in ipairs(pending_close) do -- close any sockets pending close before selecting/receiving on them
42+
for _, unique_key in ipairs(pending_close or {}) do -- close any sockets pending close before selecting/receiving on them
4343
local wss = websockets[unique_key]
4444
if wss ~= nil then
4545
log.trace(string.format("Closing websocket for player %s", unique_key))
@@ -60,7 +60,7 @@ cosock.spawn(function()
6060
pending_close = {}
6161

6262
local socks = { control_rx }
63-
for _, wss in pairs(websockets) do
63+
for _, wss in pairs(websockets or {}) do
6464
table.insert(socks, wss)
6565
end
6666
local receivers, _, err = socket.select(socks, nil, 10)
@@ -71,7 +71,7 @@ cosock.spawn(function()
7171
log.error("Error in Websocket Router event loop: " .. err)
7272
end
7373
else
74-
for _, recv in ipairs(receivers) do
74+
for _, recv in ipairs(receivers or {}) do
7575
if recv.link and recv.link.queue and #recv.link.queue == 0 then -- workaround a bug in receiving
7676
log.warn("attempting to receive on empty channel")
7777
goto continue
@@ -93,7 +93,7 @@ cosock.spawn(function()
9393
elseif err == "closed" and recv.id then -- closed websocket
9494
log.trace(string.format("Websocket %s closed", tostring(recv.id)))
9595
local still_open_sockets = {}
96-
for unique_key, wss in pairs(websockets) do
96+
for unique_key, wss in pairs(websockets or {}) do
9797
if wss.id ~= recv.id then
9898
still_open_sockets[unique_key] = wss
9999
end
@@ -207,7 +207,7 @@ local function _make_websocket(url_table, api_key)
207207

208208
local headers = SonosApi.make_headers(api_key)
209209
local config = LustreConfig.default():protocol("v1.api.smartspeaker.audio")
210-
for k, v in pairs(headers) do
210+
for k, v in pairs(headers or {}) do
211211
config = config:header(k, v)
212212
end
213213

@@ -313,7 +313,7 @@ end
313313
function SonosWebSocketRouter.cleanup_unused_sockets(driver)
314314
log.trace("Begin cleanup of unused websockets")
315315
local should_keep = {}
316-
for unique_key, _ in pairs(websockets) do
316+
for unique_key, _ in pairs(websockets or {}) do
317317
local household_id, player_id = unique_key:match("(.*)/(.*)")
318318
local is_joined = driver.sonos:get_device_id_for_player(household_id, player_id) ~= nil
319319
log.debug(string.format("Is Player %s joined? %s", player_id, is_joined))
@@ -322,7 +322,7 @@ function SonosWebSocketRouter.cleanup_unused_sockets(driver)
322322

323323
local known_devices = driver:get_devices()
324324

325-
for _, device in ipairs(known_devices) do
325+
for _, device in ipairs(known_devices or {}) do
326326
local household_id, coordinator_id = driver.sonos:get_coordinator_for_device(device)
327327
local coordinator_unique_key, bad_key_part =
328328
utils.sonos_unique_key(household_id, coordinator_id)
@@ -340,7 +340,7 @@ function SonosWebSocketRouter.cleanup_unused_sockets(driver)
340340
end
341341
end
342342

343-
for unique_key, keep in pairs(should_keep) do
343+
for unique_key, keep in pairs(should_keep or {}) do
344344
if not keep then
345345
SonosWebSocketRouter.close_socket_for_player(unique_key)
346346
end

drivers/SmartThings/sonos/src/cosock/bus.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ end
159159
function __sender_mt:close()
160160
self._bus_inner.closed = true
161161
local existing_links = self._bus_inner.receiver_links
162-
for _, link in pairs(existing_links) do
162+
for _, link in pairs(existing_links or {}) do
163163
if link.waker then
164164
link.waker()
165165
end
@@ -176,7 +176,7 @@ end
176176
function __sender_mt:send(msg)
177177
if not self._bus_inner.closed then
178178
-- wapping in table allows `nil` to be sent as a message
179-
for _, link in pairs(self._bus_inner.receiver_links) do
179+
for _, link in pairs(self._bus_inner.receiver_links or {}) do
180180
table.insert(link.queue, { msg = msg })
181181
if link.waker then
182182
link.waker()

drivers/SmartThings/sonos/src/lunchbox/rest.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ function RestClient:get(path, additional_headers, retry_fn)
331331
)
332332

333333
if additional_headers ~= nil and type(additional_headers) == "table" then
334-
for k, v in pairs(additional_headers) do request = request:add_header(k, v) end
334+
for k, v in pairs(additional_headers or {}) do request = request:add_header(k, v) end
335335
end
336336

337337
return execute_request(self, request, retry_fn)
@@ -345,7 +345,7 @@ function RestClient:post(path, body_string, additional_headers, retry_fn)
345345
)
346346

347347
if additional_headers ~= nil and type(additional_headers) == "table" then
348-
for k, v in pairs(additional_headers) do request = request:add_header(k, v) end
348+
for k, v in pairs(additional_headers or {}) do request = request:add_header(k, v) end
349349
end
350350

351351
request = request:append_body(body_string)
@@ -361,7 +361,7 @@ function RestClient:put(path, body_string, additional_headers, retry_fn)
361361
)
362362

363363
if additional_headers ~= nil and type(additional_headers) == "table" then
364-
for k, v in pairs(additional_headers) do request = request:add_header(k, v) end
364+
for k, v in pairs(additional_headers or {}) do request = request:add_header(k, v) end
365365
end
366366

367367
request = request:append_body(body_string)

drivers/SmartThings/sonos/src/sonos_driver.lua

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ function SonosDriver:oauth_info_event_subscribe()
134134
end
135135

136136
function SonosDriver:update_after_startup_state_received()
137-
for k, v in pairs(self.hub_augmented_driver_data) do
137+
for k, v in pairs(self.hub_augmented_driver_data or {}) do
138138
local decode_success, decoded = pcall(json.decode, v)
139139
if decode_success then
140140
self:handle_augmented_data_change(k, decoded)
@@ -212,7 +212,7 @@ function SonosDriver:handle_startup_state_received()
212212
token_refresher.spawn_token_refresher(self)
213213
end
214214
self.startup_state_received = true
215-
for _, device in pairs(self.devices_waiting_for_startup_state) do
215+
for _, device in pairs(self.devices_waiting_for_startup_state or {}) do
216216
SonosDriverLifecycleHandlers.initialize_device(self, device)
217217
end
218218
self.devices_waiting_for_startup_state = {}
@@ -291,7 +291,7 @@ function SonosDriver:check_auth(info_or_device)
291291
end
292292

293293
local unauthorized = false
294-
for _, api_key in pairs(SonosApi.api_keys) do
294+
for _, api_key in pairs(SonosApi.api_keys or {}) do
295295
local headers = SonosApi.make_headers(api_key, maybe_token and maybe_token.accessToken)
296296
local response, response_err = SonosApi.RestApi.get_groups_info(rest_url, household_id, headers)
297297

@@ -422,13 +422,13 @@ local function make_ssdp_event_handler(
422422
local recv_ready, _, select_err = cosock.socket.select(receivers, nil, nil)
423423

424424
if recv_ready then
425-
for _, receiver in ipairs(recv_ready) do
425+
for _, receiver in ipairs(recv_ready or {}) do
426426
if oauth_token_subscription ~= nil and receiver == oauth_token_subscription then
427427
local token_evt, receive_err = oauth_token_subscription:receive()
428428
if not token_evt then
429429
log.warn(string.format("Error on token event bus receive: %s", receive_err))
430430
else
431-
for _, event in pairs(unauthorized) do
431+
for _, event in pairs(unauthorized or {}) do
432432
-- shouldn't need a nil check on the ssdp_task here since this whole function
433433
-- won't get called unless the task is successfully spawned.
434434
driver.ssdp_task:publish(event)
@@ -696,7 +696,7 @@ function SonosDriver.new_driver_template()
696696
},
697697
}
698698

699-
for k, v in pairs(SonosDriver) do
699+
for k, v in pairs(SonosDriver or {}) do
700700
template[k] = v
701701
end
702702

drivers/SmartThings/sonos/src/sonos_state.lua

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,26 +361,26 @@ function SonosState:update_household_info(id, groups_event, driver)
361361

362362
local groups, players = groups_event.groups, groups_event.players
363363

364-
for _, group in ipairs(groups) do
364+
for _, group in ipairs(groups or {}) do
365365
household.groups[group.id] =
366366
{ id = group.id, coordinator_id = group.coordinatorId, player_ids = group.playerIds }
367-
for _, playerId in ipairs(group.playerIds) do
367+
for _, playerId in ipairs(group.playerIds or {}) do
368368
household.player_to_group[playerId] = group.id
369369
end
370370
end
371371

372372
-- Iterate through the players and track all the devices associated with them
373373
-- for bonded set tracking.
374374
local log_devices_error = false
375-
for _, player in ipairs(players) do
375+
for _, player in ipairs(players or {}) do
376376
-- Prefer devices because deviceIds is deprecated but all we care about is
377377
-- the ID so either way is fine.
378378
if type(player.devices) == "table" then
379-
for _, device in ipairs(player.devices) do
379+
for _, device in ipairs(player.devices or {}) do
380380
update_device_info(driver, player, household, known_bonded_players, device.id)
381381
end
382382
elseif type(player.deviceIds) == "table" then
383-
for _, device_id in ipairs(player.deviceIds) do
383+
for _, device_id in ipairs(player.deviceIds or {}) do
384384
update_device_info(driver, player, household, known_bonded_players, device_id)
385385
end
386386
else

drivers/SmartThings/sonos/src/ssdp.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ end
6464
---@diagnostic disable-next-line: inject-field
6565
function Ssdp.check_headers_contain(headers, keys_to_check)
6666
local missing = {}
67-
for _, header_key in ipairs(keys_to_check) do
67+
for _, header_key in ipairs(keys_to_check or {}) do
6868
if headers:get_one(header_key) == nil then
6969
table.insert(missing, header_key)
7070
end
@@ -197,7 +197,7 @@ end
197197
--- the search end time will be pushed out based on the `mx` parameter, extending the amount of
198198
--- time that `receive_m_search_response` will return results with a timeout.
199199
function _ssdp_mt:multicast_m_search()
200-
for term, _ in pairs(self.search_terms) do
200+
for term, _ in pairs(self.search_terms or {}) do
201201
local multicast_msg = table.concat({
202202
"M-SEARCH * HTTP/1.1",
203203
"HOST: 239.255.255.250:1900",
@@ -284,7 +284,7 @@ function _ssdp_mt:next_msearch_response()
284284
)
285285
end
286286

287-
for _, location in ipairs(location_candidates) do
287+
for _, location in ipairs(location_candidates or {}) do
288288
local location_host_match = location:match("http://([^,/]+):[^/]+/.+%.xml")
289289
if location_host_match ~= nil then
290290
possible_locations[location_host_match] = location

drivers/SmartThings/sonos/src/utils.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ function utils.deep_table_eq(tbl1, tbl2)
319319
if tbl1 == tbl2 then
320320
return true
321321
elseif type(tbl1) == "table" and type(tbl2) == "table" then
322-
for key1, value1 in pairs(tbl1) do
322+
for key1, value1 in pairs(tbl1 or {}) do
323323
local value2 = tbl2[key1]
324324

325325
if value2 == nil then
@@ -337,7 +337,7 @@ function utils.deep_table_eq(tbl1, tbl2)
337337
end
338338

339339
-- check for missing keys in tbl1
340-
for key2, _ in pairs(tbl2) do
340+
for key2, _ in pairs(tbl2 or {}) do
341341
if tbl1[key2] == nil then
342342
return false
343343
end

0 commit comments

Comments
 (0)