diff --git a/frontend/socketutil.lua b/frontend/socketutil.lua index 4a62985c3..53ddf2419 100644 --- a/frontend/socketutil.lua +++ b/frontend/socketutil.lua @@ -51,7 +51,7 @@ function socketutil:set_timeout(block_timeout, total_timeout) -- Also update the actual LuaSocket & LuaSec constants, because: -- 1. LuaSocket's `open` does a `settimeout` *after* create with this constant - -- 2. KOSync updates it to a stupidly low value + -- 2. Rogue code might be attempting to enforce them http.TIMEOUT = self.block_timeout https.TIMEOUT = self.block_timeout end diff --git a/plugins/kosync.koplugin/KOSyncClient.lua b/plugins/kosync.koplugin/KOSyncClient.lua index 7d67db4c6..ca35e6e00 100644 --- a/plugins/kosync.koplugin/KOSyncClient.lua +++ b/plugins/kosync.koplugin/KOSyncClient.lua @@ -1,5 +1,11 @@ local UIManager = require("ui/uimanager") -local DEBUG = require("dbg") +local logger = require("logger") +local socketutil = require("socketutil") + +-- Push/Pull +local PROGRESS_TIMEOUTS = { 2, 5 } +-- Login/Register +local AUTH_TIMEOUTS = { 5, 10 } local KOSyncClient = { service_spec = nil, @@ -15,22 +21,21 @@ function KOSyncClient:new(o) end function KOSyncClient:init() - require("socket.http").TIMEOUT = 1 local Spore = require("Spore") self.client = Spore.new_from_spec(self.service_spec, { base_url = self.custom_url, }) - package.loaded['Spore.Middleware.GinClient'] = {} - require('Spore.Middleware.GinClient').call = function(_, req) - req.headers['accept'] = "application/vnd.koreader.v1+json" + package.loaded["Spore.Middleware.GinClient"] = {} + require("Spore.Middleware.GinClient").call = function(_, req) + req.headers["accept"] = "application/vnd.koreader.v1+json" end - package.loaded['Spore.Middleware.KOSyncAuth'] = {} - require('Spore.Middleware.KOSyncAuth').call = function(args, req) - req.headers['x-auth-user'] = args.username - req.headers['x-auth-key'] = args.userkey + package.loaded["Spore.Middleware.KOSyncAuth"] = {} + require("Spore.Middleware.KOSyncAuth").call = function(args, req) + req.headers["x-auth-user"] = args.username + req.headers["x-auth-key"] = args.userkey end - package.loaded['Spore.Middleware.AsyncHTTP'] = {} - require('Spore.Middleware.AsyncHTTP').call = function(args, req) + package.loaded["Spore.Middleware.AsyncHTTP"] = {} + require("Spore.Middleware.AsyncHTTP").call = function(args, req) -- disable async http if Turbo looper is missing if not UIManager.looper then return end req:finalize() @@ -41,7 +46,7 @@ function KOSyncClient:init() body = req.env.spore.payload, on_headers = function(headers) for header, value in pairs(req.headers) do - if type(header) == 'string' then + if type(header) == "string" then headers:add(header, value) end end @@ -59,37 +64,41 @@ end function KOSyncClient:register(username, password) self.client:reset_middlewares() - self.client:enable('Format.JSON') + self.client:enable("Format.JSON") self.client:enable("GinClient") + socketutil:set_timeout(AUTH_TIMEOUTS[1], AUTH_TIMEOUTS[2]) local ok, res = pcall(function() return self.client:register({ username = username, password = password, }) end) + socketutil:reset_timeout() if ok then return res.status == 201, res.body else - DEBUG(ok, res) + logger.dbg("KOSyncClient:register failure:", res) return false, res.body end end function KOSyncClient:authorize(username, password) self.client:reset_middlewares() - self.client:enable('Format.JSON') + self.client:enable("Format.JSON") self.client:enable("GinClient") self.client:enable("KOSyncAuth", { username = username, userkey = password, }) + socketutil:set_timeout(AUTH_TIMEOUTS[1], AUTH_TIMEOUTS[2]) local ok, res = pcall(function() return self.client:authorize() end) + socketutil:reset_timeout() if ok then return res.status == 200, res.body else - DEBUG("err:", res) + logger.dbg("KOSyncClient:authorize failure:", res) return false, res.body end end @@ -104,12 +113,14 @@ function KOSyncClient:update_progress( device_id, callback) self.client:reset_middlewares() - self.client:enable('Format.JSON') + self.client:enable("Format.JSON") self.client:enable("GinClient") self.client:enable("KOSyncAuth", { username = username, userkey = password, }) + -- Set *very* tight timeouts to avoid blocking for too long... + socketutil:set_timeout(PROGRESS_TIMEOUTS[1], PROGRESS_TIMEOUTS[2]) local co = coroutine.create(function() local ok, res = pcall(function() return self.client:update_progress({ @@ -123,13 +134,14 @@ function KOSyncClient:update_progress( if ok then callback(res.status == 200, res.body) else - DEBUG("err:", res) + logger.dbg("KOSyncClient:update_progress failure:", res) callback(false, res.body) end end) self.client:enable("AsyncHTTP", {thread = co}) coroutine.resume(co) if UIManager.looper then UIManager:setInputTimeout() end + socketutil:reset_timeout() end function KOSyncClient:get_progress( @@ -138,12 +150,13 @@ function KOSyncClient:get_progress( document, callback) self.client:reset_middlewares() - self.client:enable('Format.JSON') + self.client:enable("Format.JSON") self.client:enable("GinClient") self.client:enable("KOSyncAuth", { username = username, userkey = password, }) + socketutil:set_timeout(PROGRESS_TIMEOUTS[1], PROGRESS_TIMEOUTS[2]) local co = coroutine.create(function() local ok, res = pcall(function() return self.client:get_progress({ @@ -153,13 +166,14 @@ function KOSyncClient:get_progress( if ok then callback(res.status == 200, res.body) else - DEBUG("err:", res) + logger.dbg("KOSyncClient:get_progress failure:", res) callback(false, res.body) end end) self.client:enable("AsyncHTTP", {thread = co}) coroutine.resume(co) if UIManager.looper then UIManager:setInputTimeout() end + socketutil:reset_timeout() end return KOSyncClient