enen92/screensaver.kaster

Bad image URLs cause excessive hits on Google servers

Closed this issue · 7 comments

After setting up a caching DNS server I was surprised to see in the logs I was getting hundreds of thousands of hits per day on google image servers, as well as issues with not being able to wake Kodi up when Kaster was running on occasion.

I was also seeing Kodi crash logs with entries like these:-

2020-12-03 02:11:10.523 T:2041557200 ERROR: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <class 'requests.exceptions.ConnectionError'>
Error Contents: HTTPSConnectionPool(host='lh3.googleusercontent.com', port=443): Max retries exceeded with url: /-zabx6mtDOEg/UtrJztwa_YI/AAAAAAAAX3M/Z7BuWJ7hkzQ/s1920-w1920-h1080-c/Mysore%2BPalace.jpg (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x8d8de6b0>: Failed to establish a new connection: [Errno 110] Connection timed out',))
Traceback (most recent call last):
File "/home/pi/.kodi/addons/screensaver.kaster/resources/lib/screensaver.py", line 66, in onInit
req = requests.head(url=self.images[rand_index]["url"])
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/api.py", line 101, in head
return request('head', url, **kwargs)
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/api.py", line 60, in request
return session.request(method=method, url=url, **kwargs)
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/sessions.py", line 533, in request
resp = self.send(prep, **send_kwargs)
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/sessions.py", line 646, in send
r = adapter.send(request, **kwargs)
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/adapters.py", line 516, in send
raise ConnectionError(e, request=request)
ConnectionError: HTTPSConnectionPool(host='lh3.googleusercontent.com', port=443): Max retries exceeded with url: /-zabx6mtDOEg/UtrJztwa_YI/AAAAAAAAX3M/Z7BuWJ7hkzQ/s1920-w1920-h1080-c/Mysore%2BPalace.jpg (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x8d8de6b0>: Failed to establish a new connection: [Errno 110] Connection timed out',))
-->End of Python script error report<--

2020-12-10 00:41:14.044 T:2097148112 ERROR: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <class 'requests.exceptions.ConnectionError'>
Error Contents: HTTPSConnectionPool(host='lh3.googleusercontent.com', port=443): Max retries exceeded with url: /mbbapEbFH7QmPoDJv1k6XkJZsshrYb-N7YeyvRthEKkbZlMAuh49Zw=s1280-w1280-h720-p-k-no-nd-mv (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0xa4f7a030>: Failed to establish a new connection: [Errno 110] Connection timed out',))
Traceback (most recent call last):
File "/home/pi/.kodi/addons/screensaver.kaster/resources/lib/screensaver.py", line 66, in onInit
req = requests.head(url=self.images[rand_index]["url"])
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/api.py", line 101, in head
return request('head', url, **kwargs)
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/api.py", line 60, in request
return session.request(method=method, url=url, **kwargs)
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/sessions.py", line 533, in request
resp = self.send(prep, **send_kwargs)
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/sessions.py", line 646, in send
r = adapter.send(request, **kwargs)
File "/home/pi/.kodi/addons/script.module.requests/lib/requests/adapters.py", line 516, in send
raise ConnectionError(e, request=request)
ConnectionError: HTTPSConnectionPool(host='lh3.googleusercontent.com', port=443): Max retries exceeded with url: /mbbapEbFH7QmPoDJv1k6XkJZsshrYb-N7YeyvRthEKkbZlMAuh49Zw=s1280-w1280-h720-p-k-no-nd-mv (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0xa4f7a030>: Failed to establish a new connection: [Errno 110] Connection timed out',))
-->End of Python script error report<--

The two URLs shown in this log
https://lh3.googleusercontent.com/-zabx6mtDOEg/UtrJztwa_YI/AAAAAAAAX3M/Z7BuWJ7hkzQ/s1920-w1920-h1080-c/Mysore+Palace.jpg
https://lh3.googleusercontent.com/mbbapEbFH7QmPoDJv1k6XkJZsshrYb-N7YeyvRthEKkbZlMAuh49Zw=s1280-w1280-h720-p-k-no-nd-mv

are listed in the chromecast.json file, but are not present on the Google servers and return a 404 error. The second one appears to be malformed since it does not end in .jpg.

As a workaround I have removed those URLs from chromecast.json, and to prevent future problems with 404 errors causing DNS storms have edited screensaver.py to force a delay after any result other than 200

            # if it is a google image....
            if "private" not in self.images[rand_index]:
                req = requests.head(url=self.images[rand_index]["url"])
                if req.status_code != 200:
                    # sleep for a bit to avoid 429 (too many requests)
                    #if req.status_code == 429:
                    #    self.exit_monitor.waitForAbort(5)
                    self.exit_monitor.waitForAbort(5)
                    continue

Looking deeper into this I notice that an awful lot of the URLs in chromecast.json are invalid. In fact only 455 out of 785 are valid.

I have made a little script to extract the valid URLs. A revised chromecast.json is attached
chromecast_json.zip

I have scraped the Chromecast gallery page curated by Alex Meub at https://chromecastbg.alexmeub.com/ and produced a new chromecast.json file containing 851 chromecast screensavers. This file includes the existing screensavers plus a whole lot of newer ones. All the images are stored on Google servers so none of Alex's bandwidth is used.
All the images currently download OK.

The attached zip file has two versions, 'Better' at 1920x1200 resolution, and 'Best' at 2560x1440 resolution.
new_chromecast_json.zip

Thanks for the contribution @delboy711
I'll submit a new update to the repo

I'm on version 1.3.5 and seem to be having the same problems. Sometimes Kodi doesn't respond to remote control input when Kaster is active. And below is the activity of one of my PiHoles with the black bar being Vero activity. It seems odd in that the Vero is on permanently overnight but the DNS activity was normal until just after 7am and then it goes crazy. It seems to be the same every time it goes crazy. It's definitely Kaster causing it.
Kaster

I have also seen another instance of a DNS storm with 1.3.5.
To try to fix it I edited the file ~/.kodi/addons/screensaver.kaster/resources/lib/screensaver.py

On line 70. Add a timeout to the image fetch
req = requests.head(url=self.images[rand_index]["url"], timeout=2)

Comment out line 73 to sleep after any fetch failure instead of just error 429
#if req.status_code == 429:

Reduce indentation of lines 74 and 75 to the comment lines above
(Sorry I have never worked out how to paste code in github without losing all the indentation)

I made this change about 2 weeks ago and have not had a DNS storm since, but was waiting to confirm it was actually fixed before reporting it.

Thanks for that. I've made those changes and will give it a try.

It seems to have worked for me thanks. It definitely would have done it within 24 hours previously.