Skip to content
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

Implement knocking for streaming within the EU #77

Open
RobusK opened this issue Jun 1, 2020 · 9 comments
Open

Implement knocking for streaming within the EU #77

RobusK opened this issue Jun 1, 2020 · 9 comments

Comments

@RobusK
Copy link

RobusK commented Jun 1, 2020

By default, it is not possible to watch TV with this addon within EU countries other than Germany. On Chrome, the HTTP player on the website performs the following request to unlock access:

POST /api/open-eu-network HTTP/1.1
Host: eunet.waipu.tv
Connection: keep-alive
Content-Length: 0
Authorization: Bearer <censored>
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36
DNT: 1
Accept: */*
Origin: https://play.waipu.tv
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://play.waipu.tv/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

This can be easily reproduced by pinging one of the streaming servers, e.g. e-m1-004-v4.wpstr.tv. The pings will time out until a correct knock request has been sent. Perhaps send a knock if status.wpstr.tv returns a country code other than DE?

@flubshi
Copy link
Owner

flubshi commented Jun 1, 2020

Thanks for creating this issue and providing information about the API call!

Do we have to call /api/open-eu-network on login? Or on playback?
Do we need to call it for the exact streaming server that is providing the actual stream?

@RobusK
Copy link
Author

RobusK commented Jun 1, 2020

The browser sends the request once and the "knock" remains valid for some time, for all streaming servers. From what I can tell, it invalidates after about an hour of inactivity. I'll experiment some more and report my findings.

@flubshi
Copy link
Owner

flubshi commented Jun 1, 2020

Notes for status check:

GET https://status.wpstr.tv/status

EU network:

{
  "isEuMobilityNetwork": true,
  "isClosedNetwork": false,
  "countryCode": "NL",
  "statusText": "This IP Address can't connect to the WAIPU network.",
  "ip": "...",
  "statusCode": 404,
  "internalCode": 404,
  "openViaOverflow": {
    "isOpen": false,
    "openUntilUnixTimestamp": 0
  }
}

Germany:

{
  "isEuMobilityNetwork": false,
  "isClosedNetwork": true,
  "countryCode": "DE",
  "statusText": "This IP has access to the WAIPU network.",
  "ip": "...",
  "statusCode": 200,
  "internalCode": 200,
  "openViaOverflow": {
    "isOpen": false,
    "openUntilUnixTimestamp": 0
  }
}

Maybe isEuMobilityNetwork is a better indicator than the country code. But tbh - not sure what is meant by isClosedNetwork...

For my previous questions:
I think we should call POST https://eunet.wpstr.tv/api/open-eu-network + bearer directly before playback.

Edit:
Might be interesting to see status after api/open-eu-network

@RobusK
Copy link
Author

RobusK commented Jun 1, 2020

The flow seems to be as follows:
https://status.wpstr.tv/status?uh=<censored, some sort of hash>

which initially returns:

{
  "isEuMobilityNetwork": true,
  "isClosedNetwork": false,
  "countryCode": "PL",
  "statusText": "This IP Address can't connect to the WAIPU network.",
  "ip": "<censored>",
  "statusCode": 404,
  "internalCode": 404,
  "openViaOverflow": {
    "isOpen": false,
    "openUntilUnixTimestamp": 0
  }
}

The javascript inspects:

if (i.isClosedNetwork || i.openViaOverflow.isOpen) 
	return {
		app: n // everything is fine, render player
		};
if (i.isEuMobilityNetwork)
   return await t.euMobilityNetworkCheck(e); // send knock request

For the knock request, only the status is being considered, 201 being a success:

case 201:
	n = n.set("closedNetwork", m.EU_UPGRADE);
	break;
case 403:
	n = n.set("closedNetwork", m.EU_UPGRADE_NOT_ALLOWED);
	break;
case 200:
case 500:
default:
	n = n.set("closedNetwork", m.NONE)
}

After that, a status request conveniently gives us information about the validity of the knock:

{
  "isEuMobilityNetwork": true,
  "isClosedNetwork": false,
  "countryCode": "PL",
  "statusText": "This IP has access to the WAIPU network.",
  "ip": "<cencored>",
  "statusCode": 200,
  "internalCode": 200,
  "openViaOverflow": {
    "isOpen": true,
    "openUntilUnixTimestamp": 1591128255
  }
}

@flubshi
Copy link
Owner

flubshi commented Jun 1, 2020

Very helpful information - thanks a lot!

@flubshi
Copy link
Owner

flubshi commented Jun 3, 2020

I implemented eu streaming in plugin.video.waipu.tv first. The pvr plugin will hopefully follow next week.

Maybe you could test if it works for you? Depending on which Kodi version you use:

Kodi 19 - Matrix: v0.8.3-Matrix
Kodi 18 - Leia: Testing version from PR

@RobusK
Copy link
Author

RobusK commented Jun 4, 2020

I tried the Leia version, when trying to enter the addon from Videos, it errors out. Log:

Update: On the second try it lets me in, but trying to play LiveTV crashes kodi. I can't ping the servers either. I haven't tried using the addon before the change, so it might be unrelated to the PR.

2020-06-04 17:55:05.964 T:8792   ERROR: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
                                             - NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
                                            Error Type: <type 'exceptions.AttributeError'>
                                            Error Contents: WaipuAPI instance has no attribute 'decode_token'
                                            Traceback (most recent call last):
                                              File "C:\Users\Robus\AppData\Roaming\Kodi\addons\plugin.video.waipu.tv\main.py", line 10, in <module>
                                                waipu.run()
                                              File "C:\Users\Robus\AppData\Roaming\Kodi\addons\plugin.video.waipu.tv\lib\waipu.py", line 529, in run
                                                plugin.run()
                                              File "C:\Users\Robus\AppData\Roaming\Kodi\addons\script.module.routing\lib\routing.py", line 130, in run
                                                self._dispatch(self.path)
                                              File "C:\Users\Robus\AppData\Roaming\Kodi\addons\script.module.routing\lib\routing.py", line 141, in _dispatch
                                                view_func(**kwargs)
                                              File "C:\Users\Robus\AppData\Roaming\Kodi\addons\plugin.video.waipu.tv\lib\waipu.py", line 507, in index
                                                load_acc_details()
                                              File "C:\Users\Robus\AppData\Roaming\Kodi\addons\plugin.video.waipu.tv\lib\waipu.py", line 53, in load_acc_details
                                                status = w.getStatus()
                                              File "C:\Users\Robus\AppData\Roaming\Kodi\addons\plugin.video.waipu.tv\lib\waipu_api.py", line 170, in getStatus
                                                jwt_json = self.decode_token(self.get_token())
                                            AttributeError: WaipuAPI instance has no attribute 'decode_token'
                                            -->End of Python script error report<--```  

@flubshi
Copy link
Owner

flubshi commented Jun 5, 2020

I am sorry - should be fixed now. This time I have tested 😋

Maybe you could test this test version for Kodi 18 -Leia: plugin.video.waipu.tv - v0.3.4

If this works for you I can start implementing this in pvr.waipu :)

@RobusK
Copy link
Author

RobusK commented Jun 6, 2020

Works! Thank you!
One suggestion: it would be nice if there was a 'refresh' button in the settings to see an updated status. The streaming servers and the status/eunet endpoints are in different ASNs, so it took some head-scratching to figure out why it wasn't working in a multi-homed setup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants