mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-23 03:33:35 +00:00
Renew the handshake session 20 minutes before we think it will expire (#697)
* Renew the KLAP handshake session 20 minutes before we think it will expire Currently we assumed the clocks were perfectly aligned and the handshake session lasted 20 hours. We now add a 20 minute buffer * use timeout cookie when available
This commit is contained in:
parent
24c645746e
commit
bab40d43e6
@ -36,6 +36,10 @@ from .protocol import DEFAULT_CREDENTIALS, BaseTransport, get_default_credential
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
ONE_DAY_SECONDS = 86400
|
||||||
|
SESSION_EXPIRE_BUFFER_SECONDS = 60 * 20
|
||||||
|
|
||||||
|
|
||||||
def _sha1(payload: bytes) -> str:
|
def _sha1(payload: bytes) -> str:
|
||||||
sha1_algo = hashlib.sha1() # noqa: S324
|
sha1_algo = hashlib.sha1() # noqa: S324
|
||||||
sha1_algo.update(payload)
|
sha1_algo.update(payload)
|
||||||
@ -59,6 +63,7 @@ class AesTransport(BaseTransport):
|
|||||||
|
|
||||||
DEFAULT_PORT: int = 80
|
DEFAULT_PORT: int = 80
|
||||||
SESSION_COOKIE_NAME = "TP_SESSIONID"
|
SESSION_COOKIE_NAME = "TP_SESSIONID"
|
||||||
|
TIMEOUT_COOKIE_NAME = "TIMEOUT"
|
||||||
COMMON_HEADERS = {
|
COMMON_HEADERS = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"requestByApp": "true",
|
"requestByApp": "true",
|
||||||
@ -254,7 +259,9 @@ class AesTransport(BaseTransport):
|
|||||||
**self.COMMON_HEADERS,
|
**self.COMMON_HEADERS,
|
||||||
self.CONTENT_LENGTH: str(self.KEY_PAIR_CONTENT_LENGTH),
|
self.CONTENT_LENGTH: str(self.KEY_PAIR_CONTENT_LENGTH),
|
||||||
}
|
}
|
||||||
status_code, resp_dict = await self._http_client.post(
|
http_client = self._http_client
|
||||||
|
|
||||||
|
status_code, resp_dict = await http_client.post(
|
||||||
url,
|
url,
|
||||||
json=self._generate_key_pair_payload(),
|
json=self._generate_key_pair_payload(),
|
||||||
headers=headers,
|
headers=headers,
|
||||||
@ -277,17 +284,21 @@ class AesTransport(BaseTransport):
|
|||||||
handshake_key = resp_dict["result"]["key"]
|
handshake_key = resp_dict["result"]["key"]
|
||||||
|
|
||||||
if (
|
if (
|
||||||
cookie := self._http_client.get_cookie( # type: ignore
|
cookie := http_client.get_cookie( # type: ignore
|
||||||
self.SESSION_COOKIE_NAME
|
self.SESSION_COOKIE_NAME
|
||||||
)
|
)
|
||||||
) or (
|
) or (
|
||||||
cookie := self._http_client.get_cookie( # type: ignore
|
cookie := http_client.get_cookie("SESSIONID") # type: ignore
|
||||||
"SESSIONID"
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
self._session_cookie = {self.SESSION_COOKIE_NAME: cookie}
|
self._session_cookie = {self.SESSION_COOKIE_NAME: cookie}
|
||||||
|
|
||||||
self._session_expire_at = time.time() + 86400
|
timeout = int(
|
||||||
|
http_client.get_cookie(self.TIMEOUT_COOKIE_NAME) or ONE_DAY_SECONDS
|
||||||
|
)
|
||||||
|
# There is a 24 hour timeout on the session cookie
|
||||||
|
# but the clock on the device is not always accurate
|
||||||
|
# so we set the expiry to 24 hours from now minus a buffer
|
||||||
|
self._session_expire_at = time.time() + timeout - SESSION_EXPIRE_BUFFER_SECONDS
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
assert self._key_pair is not None
|
assert self._key_pair is not None
|
||||||
self._encryption_session = AesEncyptionSession.create_from_keypair(
|
self._encryption_session = AesEncyptionSession.create_from_keypair(
|
||||||
|
@ -63,6 +63,10 @@ from .protocol import DEFAULT_CREDENTIALS, BaseTransport, get_default_credential
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
ONE_DAY_SECONDS = 86400
|
||||||
|
SESSION_EXPIRE_BUFFER_SECONDS = 60 * 20
|
||||||
|
|
||||||
|
|
||||||
def _sha256(payload: bytes) -> bytes:
|
def _sha256(payload: bytes) -> bytes:
|
||||||
digest = hashes.Hash(hashes.SHA256()) # noqa: S303
|
digest = hashes.Hash(hashes.SHA256()) # noqa: S303
|
||||||
digest.update(payload)
|
digest.update(payload)
|
||||||
@ -86,6 +90,7 @@ class KlapTransport(BaseTransport):
|
|||||||
DEFAULT_PORT: int = 80
|
DEFAULT_PORT: int = 80
|
||||||
DISCOVERY_QUERY = {"system": {"get_sysinfo": None}}
|
DISCOVERY_QUERY = {"system": {"get_sysinfo": None}}
|
||||||
SESSION_COOKIE_NAME = "TP_SESSIONID"
|
SESSION_COOKIE_NAME = "TP_SESSIONID"
|
||||||
|
TIMEOUT_COOKIE_NAME = "TIMEOUT"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -271,14 +276,18 @@ class KlapTransport(BaseTransport):
|
|||||||
self._session_cookie = None
|
self._session_cookie = None
|
||||||
|
|
||||||
local_seed, remote_seed, auth_hash = await self.perform_handshake1()
|
local_seed, remote_seed, auth_hash = await self.perform_handshake1()
|
||||||
if cookie := self._http_client.get_cookie( # type: ignore
|
http_client = self._http_client
|
||||||
self.SESSION_COOKIE_NAME
|
if cookie := http_client.get_cookie(self.SESSION_COOKIE_NAME): # type: ignore
|
||||||
):
|
|
||||||
self._session_cookie = {self.SESSION_COOKIE_NAME: cookie}
|
self._session_cookie = {self.SESSION_COOKIE_NAME: cookie}
|
||||||
# The device returns a TIMEOUT cookie on handshake1 which
|
# The device returns a TIMEOUT cookie on handshake1 which
|
||||||
# it doesn't like to get back so we store the one we want
|
# it doesn't like to get back so we store the one we want
|
||||||
|
timeout = int(
|
||||||
self._session_expire_at = time.time() + 86400
|
http_client.get_cookie(self.TIMEOUT_COOKIE_NAME) or ONE_DAY_SECONDS
|
||||||
|
)
|
||||||
|
# There is a 24 hour timeout on the session cookie
|
||||||
|
# but the clock on the device is not always accurate
|
||||||
|
# so we set the expiry to 24 hours from now minus a buffer
|
||||||
|
self._session_expire_at = time.time() + timeout - SESSION_EXPIRE_BUFFER_SECONDS
|
||||||
self._encryption_session = await self.perform_handshake2(
|
self._encryption_session = await self.perform_handshake2(
|
||||||
local_seed, remote_seed, auth_hash
|
local_seed, remote_seed, auth_hash
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user