Get TURN config from shittyserver instead of hard-coding

This commit is contained in:
Marks Polakovs 2020-04-24 11:27:08 +02:00
parent 90c082ab2c
commit 327f25f901
4 changed files with 100 additions and 61 deletions

View file

@ -29,14 +29,18 @@ parso==0.6.2
pluggy==0.13.1
pycparser==2.20
pyee==7.0.1
PyJWT==1.7.1
pylibsrtp==0.6.6
pyls==0.1.6
pyls-mypy==0.1.8
python-dateutil==2.8.1
python-jsonrpc-server==0.3.4
python-language-server==0.31.9
pytz==2019.3
raygun4py==4.3.0
requests==2.23.0
six==1.14.0
twilio==6.38.1
typed-ast==1.4.1
typing-extensions==3.7.4.2
ujson==1.35

View file

@ -2,10 +2,18 @@
key = CHANGEME
enable = False
[twilio]
account_sid = CHANGEME
auth_token = CHANGEME
[time]
local_timezone = Europe/London
[shittyserver]
notify_url = https://example.com
websocket_port = 8079
telnet_port = 8078
turn_provider = twilio
[stateserver]
myradio_key = CHANGEME

View file

@ -7,7 +7,7 @@ import sys
import uuid
from datetime import datetime, timezone
from types import TracebackType
from typing import Optional, Any, Type, Dict
from typing import Optional, Any, Type, Dict, List
import aiohttp
import av # type: ignore
@ -21,18 +21,17 @@ config = configparser.RawConfigParser()
config.read("serverconfig.ini")
if config.get("raygun", "enable") == "True":
def handle_exception(
exc_type: Type[BaseException],
exc_value: BaseException,
exc_traceback: TracebackType,
exc_type: Type[BaseException],
exc_value: BaseException,
exc_traceback: TracebackType,
) -> None:
sys.__excepthook__(exc_type, exc_value, exc_traceback)
cl = raygunprovider.RaygunSender(config.get("raygun", "key"))
cl.send_exception(exc_info=(exc_type, exc_value, exc_traceback))
sys.excepthook = handle_exception
sys.excepthook = handle_exception
file_contents_ex = re.compile(r"^ws=\d$")
@ -54,6 +53,42 @@ def write_ob_status(status: bool) -> None:
fd.truncate()
TurnCredentials = List[Dict[str, Any]]
def get_turn_credentials() -> TurnCredentials:
provider = config.get("shittyserver", "turn_provider")
if provider == "twilio":
from twilio.rest import Client # type: ignore
client = Client(config.get("twilio", "account_sid"), config.get("twilio", "auth_token"))
token = client.tokens.create()
# Twilio's typedef is wrong, reee
# noinspection PyTypeChecker
return token.ice_servers # type: ignore
elif provider == "hardcoded":
return [
{
"urls": ["stun:eu-turn4.xirsys.com"],
},
{
"username":
"h42bRBHL2GtRTiQRoXN8GCG-PFYMl4Acel6EQ9xINBWdTpoZyBEGyCcJBCtT3iINAAAAAF5_NJptYXJrc3BvbGFrb3Zz",
"credential": "17e834fa-70e7-11ea-a66c-faa4ea02ad5c",
"urls": [
"turn:eu-turn4.xirsys.com:80?transport=udp",
"turn:eu-turn4.xirsys.com:3478?transport=udp",
"turn:eu-turn4.xirsys.com:80?transport=tcp",
"turn:eu-turn4.xirsys.com:3478?transport=tcp",
"turns:eu-turn4.xirsys.com:443?transport=tcp",
"turns:eu-turn4.xirsys.com:5349?transport=tcp",
],
},
]
else:
raise Exception("unknown provider " + provider)
@Jack.set_error_function # type: ignore
def error(msg: str) -> None:
print("Error:", msg)
@ -177,8 +212,8 @@ class Session(object):
await self.pc.close()
if (
self.websocket is not None
and self.websocket.state == websockets.protocol.State.OPEN
self.websocket is not None
and self.websocket.state == websockets.protocol.State.OPEN
):
try:
await self.websocket.send(json.dumps({"kind": "DIED"}))
@ -311,9 +346,11 @@ class Session(object):
self.websocket = websocket
self.connection_state = "HELLO"
print(self.connection_id, "Connected")
ice_config = get_turn_credentials()
print(self.connection_id, "Obtained ICE")
# TODO Raygun user ID
await websocket.send(
json.dumps({"kind": "HELLO", "connectionId": self.connection_id})
json.dumps({"kind": "HELLO", "connectionId": self.connection_id, "iceServers": ice_config})
)
try:
@ -353,7 +390,7 @@ print("Shittyserver WS starting on port {}.".format(config.get("shittyserver", "
async def telnet_server(
reader: asyncio.StreamReader, writer: asyncio.StreamWriter
reader: asyncio.StreamReader, writer: asyncio.StreamWriter
) -> None:
global active_sessions, live_session
while True:
@ -374,15 +411,15 @@ async def telnet_server(
result[sid] = sess.to_dict()
writer.write(
(
json.dumps(
{
"live": live_session.to_dict()
if live_session is not None
else None,
"active": result,
}
)
+ "\r\n"
json.dumps(
{
"live": live_session.to_dict()
if live_session is not None
else None,
"active": result,
}
)
+ "\r\n"
).encode("utf-8")
)

View file

@ -29,46 +29,6 @@ export class WebRTCStreamer extends Streamer {
async start(): Promise<void> {
console.log("RTCStreamer start");
this.pc = new RTCPeerConnection({
iceServers: [
{
urls: [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:19302",
"stun:stun2.l.google.com:19302",
"stun:stun3.l.google.com:19302",
"stun:stun4.l.google.com:19302",
],
},
{
urls: ["stun:eu-turn4.xirsys.com"],
},
{
username:
"h42bRBHL2GtRTiQRoXN8GCG-PFYMl4Acel6EQ9xINBWdTpoZyBEGyCcJBCtT3iINAAAAAF5_NJptYXJrc3BvbGFrb3Zz",
credential: "17e834fa-70e7-11ea-a66c-faa4ea02ad5c",
urls: [
"turn:eu-turn4.xirsys.com:80?transport=udp",
"turn:eu-turn4.xirsys.com:3478?transport=udp",
"turn:eu-turn4.xirsys.com:80?transport=tcp",
"turn:eu-turn4.xirsys.com:3478?transport=tcp",
"turns:eu-turn4.xirsys.com:443?transport=tcp",
"turns:eu-turn4.xirsys.com:5349?transport=tcp",
],
},
],
});
this.pc.oniceconnectionstatechange = (e) => {
if (!this.pc) {
throw new Error(
"Received ICEConnectionStateChange but PC was null?????"
);
}
console.log("ICE Connection state change: " + this.pc.iceConnectionState);
this.onStateChange(this.mapStateToConnectionState());
};
this.stream.getAudioTracks().forEach((track) => this.pc!.addTrack(track));
this.addConnectionStateListener((state) => {
if (state === "CONNECTED") {
this.newsInterval = later.setInterval(
@ -83,7 +43,6 @@ export class WebRTCStreamer extends Streamer {
}
});
console.log("PC created");
this.ws = new WebSocket(process.env.REACT_APP_WS_URL!);
this.ws.onopen = (e) => {
console.log("WS open");
@ -156,6 +115,9 @@ export class WebRTCStreamer extends Streamer {
if (this.state !== "HELLO") {
this.ws!.close();
}
this.createPeerConnection(data.iceServers);
if (!this.pc) {
throw new Error(
"Tried to do websocket fuckery with a null PeerConnection!"
@ -225,6 +187,34 @@ export class WebRTCStreamer extends Streamer {
}
}
createPeerConnection(iceServers: RTCIceServer[]) {
this.pc = new RTCPeerConnection({
iceServers: [
{
urls: [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:19302",
"stun:stun2.l.google.com:19302",
"stun:stun3.l.google.com:19302",
"stun:stun4.l.google.com:19302",
],
},
...iceServers,
],
});
this.pc.oniceconnectionstatechange = (e) => {
if (!this.pc) {
throw new Error(
"Received ICEConnectionStateChange but PC was null?????"
);
}
console.log("ICE Connection state change: " + this.pc.iceConnectionState);
this.onStateChange(this.mapStateToConnectionState());
};
this.stream.getAudioTracks().forEach((track) => this.pc!.addTrack(track));
console.log("PC created");
}
async getStatistics() {
if (this.pc) {
return await this.pc.getStats();