From 4dcd1e176f5684fae54d619820e7fca00b5ef120 Mon Sep 17 00:00:00 2001
From: Timo <16718859+toger5@users.noreply.github.com>
Date: Mon, 12 Jun 2023 15:35:54 +0200
Subject: [PATCH 1/3] respect mute state set in lobby for call (#1102)

Signed-off-by: Timo K <toger5@hotmail.de>
---
 src/room/GroupCallView.tsx |  4 ++++
 src/room/InCallView.tsx    | 12 ++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx
index 9e8a389..098cbde 100644
--- a/src/room/GroupCallView.tsx
+++ b/src/room/GroupCallView.tsx
@@ -183,6 +183,10 @@ export function GroupCallView({
         matrixInfo={matrixInfo}
         mediaDevices={lkState.mediaDevices}
         livekitRoom={lkState.room}
+        userChoices={{
+          videoMuted: lkState.localMedia.video.muted,
+          audioMuted: lkState.localMedia.audio.muted,
+        }}
       />
     );
   } else if (left) {
diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx
index 6382cb8..c1414e2 100644
--- a/src/room/InCallView.tsx
+++ b/src/room/InCallView.tsx
@@ -81,6 +81,11 @@ const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
 // For now we can disable screensharing in Safari.
 const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
 
+interface LocalUserChoices {
+  videoMuted: boolean;
+  audioMuted: boolean;
+}
+
 interface Props {
   client: MatrixClient;
   groupCall: GroupCall;
@@ -92,6 +97,8 @@ interface Props {
   matrixInfo: MatrixInfo;
   mediaDevices: MediaDevicesState;
   livekitRoom: Room;
+
+  userChoices: LocalUserChoices;
 }
 
 export function InCallView({
@@ -104,6 +111,7 @@ export function InCallView({
   matrixInfo,
   mediaDevices,
   livekitRoom,
+  userChoices,
 }: Props) {
   const { t } = useTranslation();
   usePreventScroll();
@@ -143,8 +151,8 @@ export function InCallView({
     token,
     serverUrl: Config.get().livekit.server_url,
     room: livekitRoom,
-    audio: true,
-    video: true,
+    audio: !userChoices.audioMuted,
+    video: !userChoices.videoMuted,
     onConnected: () => {
       console.log("connected to LiveKit room");
     },

From 0192ed70eab0ec89e22d1f26abce924a72dd08f6 Mon Sep 17 00:00:00 2001
From: Enrico Schwendig <enricos@element.io>
Date: Mon, 12 Jun 2023 15:52:27 +0200
Subject: [PATCH 2/3] Local develop setup with docker (#1103)

* Add local live kit backend run setup
---
 .env.example               |  3 ++
 README.md                  | 31 ++++++++++++
 backend-docker-compose.yml | 47 ++++++++++++++++++
 backend/auth/Dockerfile    | 15 ++++++
 backend/auth/go.mod        | 20 ++++++++
 backend/auth/go.sum        | 94 ++++++++++++++++++++++++++++++++++++
 backend/auth/server.go     | 98 ++++++++++++++++++++++++++++++++++++++
 backend/livekit.yaml       | 26 ++++++++++
 backend/redis.conf         |  5 ++
 package.json               |  3 +-
 10 files changed, 341 insertions(+), 1 deletion(-)
 create mode 100644 backend-docker-compose.yml
 create mode 100644 backend/auth/Dockerfile
 create mode 100644 backend/auth/go.mod
 create mode 100644 backend/auth/go.sum
 create mode 100644 backend/auth/server.go
 create mode 100644 backend/livekit.yaml
 create mode 100644 backend/redis.conf

diff --git a/.env.example b/.env.example
index 596de72..f03e882 100644
--- a/.env.example
+++ b/.env.example
@@ -3,6 +3,9 @@
 # Environment files are documented here:
 # https://vitejs.dev/guide/env-and-mode.html#env-files
 ####
+# Develop backend settings:
+LIVEKIT_KEY="devkey"
+LIVEKIT_SECRET="secret"
 
 # Used for determining the homeserver to use for short urls etc.
 # VITE_FALLBACK_STUN_ALLOWED=false
diff --git a/README.md b/README.md
index cd4b65d..c137b21 100644
--- a/README.md
+++ b/README.md
@@ -74,6 +74,37 @@ You're now ready to launch the development server:
 yarn dev
 ```
 
+### Local Backend
+
+#### JWT keys
+
+Add in you `.env` in root dir with:
+
+```yaml
+# Develop backend settings:
+LIVEKIT_KEY="devkey"
+LIVEKIT_SECRET="secret"
+```
+
+#### Add SFU parameter in your local config `./public/config.yml`
+
+```yaml
+"livekit": {
+    "server_url": "ws://localhost:7880",
+    "jwt_service_url": "http:/localhost:8881"
+  },
+```
+
+#### Run Backend
+
+```
+yarn backend
+```
+
+##### Services
+
+JWT Service: http://localhost:8881/token?name=Name&identity=1234&roomName=room
+
 ## Configuration
 
 There are currently two different config files. `.env` holds variables that are used at build time, while `public/config.json` holds variables that are used at runtime. Documentation and default values for `public/config.json` can be found in [ConfigOptions.ts](src/config/ConfigOptions.ts).
diff --git a/backend-docker-compose.yml b/backend-docker-compose.yml
new file mode 100644
index 0000000..d575cf1
--- /dev/null
+++ b/backend-docker-compose.yml
@@ -0,0 +1,47 @@
+# LiveKit requires host networking, which is only available on Linux
+# This compose will not function correctly on Mac or Windows
+version: "3.9"
+
+networks:
+  lkbackend:
+
+services:
+  auth-service:
+    build:
+      context: ./backend/auth
+    container_name: auth-server
+    hostname: auth-server
+    ports:
+      - 8881:8080
+    environment:
+      - LIVEKIT_KEY=${LIVEKIT_KEY}
+      - LIVEKIT_SECRET=${LIVEKIT_SECRET}
+    deploy:
+      restart_policy:
+        condition: on-failure
+    networks:
+      - lkbackend
+
+  livekit:
+    image: livekit/livekit-server:latest
+    command: --dev --config /etc/livekit.yaml
+    restart: unless-stopped
+    ports:
+      - "7880:7880"
+      - "7881:7881"
+      - "7882:7882"
+      - "50100-50200:50100-50200"
+    volumes:
+      - ./backend/livekit.yaml:/etc/livekit.yaml
+    networks:
+      - lkbackend
+
+  redis:
+    image: redis:6-alpine
+    command: redis-server /etc/redis.conf
+    ports:
+      - 6379:6379
+    volumes:
+      - ./backend/redis.conf:/etc/redis.conf
+    networks:
+      - lkbackend
diff --git a/backend/auth/Dockerfile b/backend/auth/Dockerfile
new file mode 100644
index 0000000..c7bbd95
--- /dev/null
+++ b/backend/auth/Dockerfile
@@ -0,0 +1,15 @@
+FROM golang:1.20-alpine
+
+WORKDIR /app
+
+COPY go.mod ./
+COPY go.sum ./
+RUN go mod download
+
+COPY *.go ./
+
+RUN go build -o /auth-server
+
+EXPOSE 8080
+
+CMD [ "/auth-server" ]
diff --git a/backend/auth/go.mod b/backend/auth/go.mod
new file mode 100644
index 0000000..75d1a53
--- /dev/null
+++ b/backend/auth/go.mod
@@ -0,0 +1,20 @@
+module vector-auth-server
+
+go 1.20
+
+require github.com/livekit/protocol v1.5.7
+
+require (
+	github.com/go-jose/go-jose/v3 v3.0.0 // indirect
+	github.com/golang/protobuf v1.5.3 // indirect
+	github.com/twitchtv/twirp v8.1.3+incompatible // indirect
+	golang.org/x/crypto v0.9.0 // indirect
+	golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect
+	golang.org/x/net v0.10.0 // indirect
+	golang.org/x/sys v0.8.0 // indirect
+	golang.org/x/text v0.9.0 // indirect
+	google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd // indirect
+	google.golang.org/grpc v1.55.0 // indirect
+	google.golang.org/protobuf v1.30.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/backend/auth/go.sum b/backend/auth/go.sum
new file mode 100644
index 0000000..e841974
--- /dev/null
+++ b/backend/auth/go.sum
@@ -0,0 +1,94 @@
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/eapache/channels v1.1.0 h1:F1taHcn7/F0i8DYqKXJnyhJcVpp2kgFcNePxXtnyu4k=
+github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
+github.com/frostbyte73/core v0.0.9 h1:AmE9GjgGpPsWk9ZkmY3HsYUs2hf2tZt+/W6r49URBQI=
+github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0=
+github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
+github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
+github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw=
+github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c=
+github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1 h1:jm09419p0lqTkDaKb5iXdynYrzB84ErPPO4LbRASk58=
+github.com/livekit/protocol v1.5.7 h1:jZeFQEmLuIhFblXDGPRCBbfjVJHb+YU7AsO+SMoXF70=
+github.com/livekit/protocol v1.5.7/go.mod h1:ZaOnsvP+JS4s7vI1UO+JVdBagvvLp/lBXDAl2hkDS0I=
+github.com/livekit/psrpc v0.3.0 h1:giBZsfM3CWA0oIYXofsMITbVQtyW7u/ES9sQmVspHPM=
+github.com/mackerelio/go-osstat v0.2.4 h1:qxGbdPkFo65PXOb/F/nhDKpF2nGmGaCFDLXoZjJTtUs=
+github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
+github.com/nats-io/nats.go v1.25.0 h1:t5/wCPGciR7X3Mu8QOi4jiJaXaWM8qtkLu4lzGZvYHE=
+github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA=
+github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
+github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
+github.com/pion/dtls/v2 v2.2.6 h1:yXMxKr0Skd+Ub6A8UqXTRLSywskx93ooMRHsQUtd+Z4=
+github.com/pion/ice/v2 v2.3.4 h1:tjYjTLpWyZzUjpDnzk6T1y3oQyhyY2DiM2t095iDhyQ=
+github.com/pion/interceptor v0.1.16 h1:0GDZrfNO+BmVNWymS31fMlVtPO2IJVBzy2Qq5XCYMIg=
+github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
+github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U=
+github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
+github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc=
+github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA=
+github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw=
+github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
+github.com/pion/srtp/v2 v2.0.14 h1:Glt0MqEvINrDxL+aanmK4DiFjvs+uN2iYc6XD/iKpoY=
+github.com/pion/stun v0.5.2 h1:J/8glQnDV91dfk2+ZnGN0o9bUJgABhTNljwfQWByoXE=
+github.com/pion/transport/v2 v2.2.0 h1:u5lFqFHkXLMXMzai8tixZDfVjb8eOjH35yCunhPeb1c=
+github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI=
+github.com/pion/udp/v2 v2.0.1 h1:xP0z6WNux1zWEjhC7onRA3EwwSliXqu1ElUZAQhUP54=
+github.com/pion/webrtc/v3 v3.2.4 h1:gWSx4dqQb77051qBT9ipDrOyP6/sGYcAQP3UPjM8pU8=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
+github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
+github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
+github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
+github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvktgc=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
+github.com/twitchtv/twirp v8.1.3+incompatible h1:+F4TdErPgSUbMZMwp13Q/KgDVuI7HJXP61mNV3/7iuU=
+github.com/twitchtv/twirp v8.1.3+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
+go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
+golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
+golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU=
+golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd h1:sLpv7bNL1AsX3fdnWh9WVh7ejIzXdOc1RRHGeAmeStU=
+google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
+google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
+google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
+google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/backend/auth/server.go b/backend/auth/server.go
new file mode 100644
index 0000000..b3721e2
--- /dev/null
+++ b/backend/auth/server.go
@@ -0,0 +1,98 @@
+package main
+
+import (
+	"encoding/json"
+	"log"
+	"net/http"
+	"os"
+
+	"time"
+
+	"github.com/livekit/protocol/auth"
+)
+
+type Handler struct {
+	key, secret string
+}
+
+func (h *Handler) handle(w http.ResponseWriter, r *http.Request) {
+	log.Printf("Request from %s", r.RemoteAddr)
+
+	// Set the CORS headers
+	w.Header().Set("Access-Control-Allow-Origin", "*")
+	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
+	w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
+
+	// Handle preflight request (CORS)
+	if r.Method == "OPTIONS" {
+		w.WriteHeader(http.StatusOK)
+		return
+	}
+
+	roomName := r.URL.Query().Get("roomName")
+	name := r.URL.Query().Get("name")
+	identity := r.URL.Query().Get("identity")
+
+	log.Printf("roomName: %s, name: %s, identity: %s", roomName, name, identity)
+
+	if roomName == "" || name == "" || identity == "" {
+		w.WriteHeader(http.StatusBadRequest)
+		return
+	}
+
+	token, err := getJoinToken(h.key, h.secret, roomName, identity, name)
+	if err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	res := Response{token}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(res)
+}
+
+func main() {
+	key := os.Getenv("LIVEKIT_KEY")
+	secret := os.Getenv("LIVEKIT_SECRET")
+
+	// Check if the key and secret are empty.
+	if key == "" || secret == "" {
+		log.Fatal("LIVEKIT_KEY and LIVEKIT_SECRET environment variables must be set")
+	}
+
+	log.Printf("LIVEKIT_KEY: %s and LIVEKIT_SECRET %s", key, secret)
+
+	handler := &Handler{
+		key:    key,
+		secret: secret,
+	}
+
+	http.HandleFunc("/token", handler.handle)
+	log.Fatal(http.ListenAndServe(":8080", nil))
+}
+
+type Response struct {
+	Token string `json:"accessToken"`
+}
+
+func getJoinToken(apiKey, apiSecret, room, identity, name string) (string, error) {
+	at := auth.NewAccessToken(apiKey, apiSecret)
+
+	canPublish := true
+	canSubscribe := true
+	grant := &auth.VideoGrant{
+		RoomJoin:     true,
+		RoomCreate:   true,
+		CanPublish:   &canPublish,
+		CanSubscribe: &canSubscribe,
+		Room:         room,
+	}
+
+	at.AddGrant(grant).
+		SetIdentity(identity).
+		SetValidFor(time.Hour).
+		SetName(name)
+
+	return at.ToJWT()
+}
diff --git a/backend/livekit.yaml b/backend/livekit.yaml
new file mode 100644
index 0000000..da24c76
--- /dev/null
+++ b/backend/livekit.yaml
@@ -0,0 +1,26 @@
+port: 7880
+environment: dev
+bind_addresses:
+  - "0.0.0.0"
+rtc:
+  tcp_port: 7881
+  port_range_start: 50100
+  port_range_end: 50200
+  use_external_ip: false
+#redis:
+#    address: redis:6379
+#    username: ""
+#    password: ""
+#    db: 0
+turn:
+  enabled: false
+  domain: localhost
+  cert_file: ""
+  key_file: ""
+  tls_port: 5349
+  udp_port: 443
+  external_tls: true
+keys:
+  devkey: secret
+signal_relay:
+  enabled: true
diff --git a/backend/redis.conf b/backend/redis.conf
new file mode 100644
index 0000000..32a39f7
--- /dev/null
+++ b/backend/redis.conf
@@ -0,0 +1,5 @@
+bind 0.0.0.0
+protected-mode yes
+port 6379
+timeout 0
+tcp-keepalive 300
diff --git a/package.json b/package.json
index 6f616f4..7d93035 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
     "lint:types": "tsc",
     "i18n": "node_modules/i18next-parser/bin/cli.js",
     "i18n:check": "node_modules/i18next-parser/bin/cli.js --fail-on-warnings --fail-on-update",
-    "test": "jest"
+    "test": "jest",
+    "backend": "docker-compose -f backend-docker-compose.yml up"
   },
   "dependencies": {
     "@juggle/resize-observer": "^3.3.1",

From 8f356e396cb7aee7d9a98150ce5fb8b3e5fd46c2 Mon Sep 17 00:00:00 2001
From: fkwp <github-fkwp@w4ve.de>
Date: Mon, 12 Jun 2023 16:09:29 +0200
Subject: [PATCH 3/3] change livekit SFU for PR builds

---
 config/element_io_preview.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/element_io_preview.json b/config/element_io_preview.json
index 30065ab..abda235 100644
--- a/config/element_io_preview.json
+++ b/config/element_io_preview.json
@@ -6,7 +6,7 @@
     }
   },
   "livekit": {
-    "server_url": "wss://ec-test-t5xo1uoy.livekit.cloud",
+    "server_url": "wss://voip-sip-poc.element.io/lk/sfu",
     "jwt_service_url": "https://voip-sip-poc.element.io/lk/jwt_service"
   },
   "posthog": {