Skip to content

Renew the handshake session 20 minutes before we think it will expire #697

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

Merged
merged 12 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 17 additions & 6 deletions kasa/aestransport.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
_LOGGER = logging.getLogger(__name__)


ONE_DAY_SECONDS = 86400
SESSION_EXPIRE_BUFFER_SECONDS = 60 * 20


def _sha1(payload: bytes) -> str:
sha1_algo = hashlib.sha1() # noqa: S324
sha1_algo.update(payload)
Expand All @@ -59,6 +63,7 @@ class AesTransport(BaseTransport):

DEFAULT_PORT: int = 80
SESSION_COOKIE_NAME = "TP_SESSIONID"
TIMEOUT_COOKIE_NAME = "TIMEOUT"
COMMON_HEADERS = {
"Content-Type": "application/json",
"requestByApp": "true",
Expand Down Expand Up @@ -254,7 +259,9 @@ async def perform_handshake(self) -> None:
**self.COMMON_HEADERS,
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,
json=self._generate_key_pair_payload(),
headers=headers,
Expand All @@ -277,17 +284,21 @@ async def perform_handshake(self) -> None:
handshake_key = resp_dict["result"]["key"]

if (
cookie := self._http_client.get_cookie( # type: ignore
cookie := http_client.get_cookie( # type: ignore
self.SESSION_COOKIE_NAME
)
) or (
cookie := self._http_client.get_cookie( # type: ignore
"SESSIONID"
)
cookie := http_client.get_cookie("SESSIONID") # type: ignore
):
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:
assert self._key_pair is not None
self._encryption_session = AesEncyptionSession.create_from_keypair(
Expand Down
19 changes: 14 additions & 5 deletions kasa/klaptransport.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
_LOGGER = logging.getLogger(__name__)


ONE_DAY_SECONDS = 86400
SESSION_EXPIRE_BUFFER_SECONDS = 60 * 20


def _sha256(payload: bytes) -> bytes:
digest = hashes.Hash(hashes.SHA256()) # noqa: S303
digest.update(payload)
Expand All @@ -86,6 +90,7 @@ class KlapTransport(BaseTransport):
DEFAULT_PORT: int = 80
DISCOVERY_QUERY = {"system": {"get_sysinfo": None}}
SESSION_COOKIE_NAME = "TP_SESSIONID"
TIMEOUT_COOKIE_NAME = "TIMEOUT"

def __init__(
self,
Expand Down Expand Up @@ -271,14 +276,18 @@ async def perform_handshake(self) -> Any:
self._session_cookie = None

local_seed, remote_seed, auth_hash = await self.perform_handshake1()
if cookie := self._http_client.get_cookie( # type: ignore
self.SESSION_COOKIE_NAME
):
http_client = self._http_client
if cookie := http_client.get_cookie(self.SESSION_COOKIE_NAME): # type: ignore
self._session_cookie = {self.SESSION_COOKIE_NAME: cookie}
# The device returns a TIMEOUT cookie on handshake1 which
# it doesn't like to get back so we store the one we want

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
self._encryption_session = await self.perform_handshake2(
local_seed, remote_seed, auth_hash
)
Expand Down