mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 16:55:37 +02:00
Merge branch 'main' into feat/play
This commit is contained in:
@@ -1,20 +1,29 @@
|
|||||||
FROM docker.io/golang:1.23-alpine AS go-build
|
FROM docker.io/golang:1.24-alpine AS go-build
|
||||||
WORKDIR /builder
|
WORKDIR /builder
|
||||||
COPY packages/relay/ /builder/
|
COPY packages/relay/ /builder/
|
||||||
RUN go build
|
RUN go build
|
||||||
|
|
||||||
FROM docker.io/golang:1.23-alpine
|
FROM docker.io/golang:1.24-alpine
|
||||||
COPY --from=go-build /builder/relay /relay/relay
|
COPY --from=go-build /builder/relay /relay/relay
|
||||||
WORKDIR /relay
|
WORKDIR /relay
|
||||||
|
|
||||||
|
# TODO: Switch running layer to just alpine (doesn't need golang dev stack)
|
||||||
|
|
||||||
# ENV flags
|
# ENV flags
|
||||||
ENV VERBOSE=false
|
ENV VERBOSE=false
|
||||||
|
ENV DEBUG=false
|
||||||
ENV ENDPOINT_PORT=8088
|
ENV ENDPOINT_PORT=8088
|
||||||
ENV WEBRTC_UDP_START=10000
|
ENV WEBRTC_UDP_START=10000
|
||||||
ENV WEBRTC_UDP_END=20000
|
ENV WEBRTC_UDP_END=20000
|
||||||
ENV STUN_SERVER="stun.l.google.com:19302"
|
ENV STUN_SERVER="stun.l.google.com:19302"
|
||||||
|
ENV WEBRTC_UDP_MUX=8088
|
||||||
|
ENV WEBRTC_NAT_IPS=""
|
||||||
|
ENV AUTO_ADD_LOCAL_IP=true
|
||||||
|
ENV TLS_CERT=""
|
||||||
|
ENV TLS_KEY=""
|
||||||
|
|
||||||
EXPOSE $ENDPOINT_PORT
|
EXPOSE $ENDPOINT_PORT
|
||||||
EXPOSE $WEBRTC_UDP_START-$WEBRTC_UDP_END/udp
|
EXPOSE $WEBRTC_UDP_START-$WEBRTC_UDP_END/udp
|
||||||
|
EXPOSE $WEBRTC_UDP_MUX/udp
|
||||||
|
|
||||||
ENTRYPOINT ["/relay/relay"]
|
ENTRYPOINT ["/relay/relay"]
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { database } from "./database";
|
|
||||||
import { email } from "./email";
|
import { email } from "./email";
|
||||||
import { allSecrets } from "./secret";
|
import { allSecrets } from "./secret";
|
||||||
|
import { database } from "./database";
|
||||||
|
|
||||||
export const bus = new sst.aws.Bus("Bus");
|
export const bus = new sst.aws.Bus("Bus");
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,29 @@
|
|||||||
//Created manually from the dashboard and shared with the whole team/org
|
//Created manually from the dashboard and shared with the whole team/org
|
||||||
const dbProject = neon.getProjectOutput({
|
const dbProject = neon.getProjectOutput({
|
||||||
id:"red-mud-17843368"
|
id: "black-sky-26872933"
|
||||||
})
|
})
|
||||||
|
|
||||||
const dbBranchId = $app.stage !== "production" ?
|
const dbBranchId = $app.stage !== "production" ?
|
||||||
new neon.Branch("DatabaseBranch", {
|
new neon.Branch("NeonBranch", {
|
||||||
parentId: dbProject.defaultBranchId,
|
parentId: dbProject.defaultBranchId,
|
||||||
projectId: dbProject.id,
|
projectId: dbProject.id,
|
||||||
name: $app.stage,
|
name: $app.stage,
|
||||||
}).id : dbProject.defaultBranchId
|
}).id : dbProject.defaultBranchId
|
||||||
|
|
||||||
const dbEndpoint = new neon.Endpoint("NestriEndpoint", {
|
const dbEndpoint = new neon.Endpoint("NeonEndpoint", {
|
||||||
projectId: dbProject.id,
|
projectId: dbProject.id,
|
||||||
branchId: dbBranchId
|
branchId: dbBranchId,
|
||||||
|
poolerEnabled: true,
|
||||||
|
type: "read_write",
|
||||||
})
|
})
|
||||||
|
|
||||||
const dbRole = new neon.Role("AdminRole", {
|
const dbRole = new neon.Role("NeonRole", {
|
||||||
name: "admin",
|
name: "admin",
|
||||||
branchId: dbBranchId,
|
branchId: dbBranchId,
|
||||||
projectId: dbProject.id,
|
projectId: dbProject.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
const db = new neon.Database("NestriDatabase", {
|
const db = new neon.Database("NeonDatabase", {
|
||||||
branchId: dbBranchId,
|
branchId: dbBranchId,
|
||||||
projectId: dbProject.id,
|
projectId: dbProject.id,
|
||||||
ownerName: dbRole.name,
|
ownerName: dbRole.name,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// This is the website part where people play and connect
|
// This is the website part where people play and connect
|
||||||
import { auth, api } from "./api";
|
|
||||||
import { domain } from "./dns";
|
import { domain } from "./dns";
|
||||||
|
import { auth, api } from "./api";
|
||||||
|
|
||||||
new sst.aws.StaticSite("Web", {
|
new sst.aws.StaticSite("Web", {
|
||||||
path: "./packages/www",
|
path: "./packages/www",
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
import { Resource } from "sst";
|
import { Resource } from "sst";
|
||||||
import { defineConfig } from "drizzle-kit";
|
import { defineConfig } from "drizzle-kit";
|
||||||
|
|
||||||
|
function addPoolerSuffix(original: string): string {
|
||||||
|
const firstDotIndex = original.indexOf('.');
|
||||||
|
if (firstDotIndex === -1) return original + '-pooler';
|
||||||
|
return original.slice(0, firstDotIndex) + '-pooler' + original.slice(firstDotIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dbHost = addPoolerSuffix(Resource.Database.host)
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
schema: "./src/**/*.sql.ts",
|
schema: "./src/**/*.sql.ts",
|
||||||
out: "./migrations",
|
out: "./migrations",
|
||||||
dialect: "postgresql",
|
dialect: "postgresql",
|
||||||
verbose: true,
|
verbose: true,
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
url: `postgresql://${Resource.Database.user}:${Resource.Database.password}@${Resource.Database.host}/${Resource.Database.name}?sslmode=require`,
|
url: `postgresql://${Resource.Database.user}:${Resource.Database.password}@${dbHost}/${Resource.Database.name}?sslmode=require`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -7,7 +7,15 @@ import { Pool, neonConfig } from "@neondatabase/serverless";
|
|||||||
|
|
||||||
neonConfig.webSocketConstructor = ws;
|
neonConfig.webSocketConstructor = ws;
|
||||||
|
|
||||||
const client = new Pool({ connectionString: `postgres://${Resource.Database.user}:${Resource.Database.password}@${Resource.Database.host}/${Resource.Database.name}?sslmode=require` })
|
function addPoolerSuffix(original: string): string {
|
||||||
|
const firstDotIndex = original.indexOf('.');
|
||||||
|
if (firstDotIndex === -1) return original + '-pooler';
|
||||||
|
return original.slice(0, firstDotIndex) + '-pooler' + original.slice(firstDotIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dbHost = addPoolerSuffix(Resource.Database.host)
|
||||||
|
|
||||||
|
const client = new Pool({ connectionString: `postgres://${Resource.Database.user}:${Resource.Database.password}@${dbHost}/${Resource.Database.name}?sslmode=require` })
|
||||||
|
|
||||||
export const db = neonDrizzle(client, {
|
export const db = neonDrizzle(client, {
|
||||||
logger:
|
logger:
|
||||||
|
|||||||
@@ -64,12 +64,12 @@ const app = issuer({
|
|||||||
PasswordUI({
|
PasswordUI({
|
||||||
sendCode: async (email, code) => {
|
sendCode: async (email, code) => {
|
||||||
console.log("email & code:", email, code)
|
console.log("email & code:", email, code)
|
||||||
await Email.send(
|
// await Email.send(
|
||||||
"auth",
|
// "auth",
|
||||||
email,
|
// email,
|
||||||
`Nestri code: ${code}`,
|
// `Nestri code: ${code}`,
|
||||||
`Your Nestri login code is ${code}`,
|
// `Your Nestri login code is ${code}`,
|
||||||
)
|
// )
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
module relay
|
module relay
|
||||||
|
|
||||||
go 1.23
|
go 1.24
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
|
github.com/pion/ice/v4 v4.0.7
|
||||||
github.com/pion/interceptor v0.1.37
|
github.com/pion/interceptor v0.1.37
|
||||||
github.com/pion/webrtc/v4 v4.0.8
|
github.com/pion/webrtc/v4 v4.0.12
|
||||||
google.golang.org/protobuf v1.36.4
|
google.golang.org/protobuf v1.36.5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/pion/datachannel v1.5.10 // indirect
|
github.com/pion/datachannel v1.5.10 // indirect
|
||||||
github.com/pion/dtls/v3 v3.0.4 // indirect
|
github.com/pion/dtls/v3 v3.0.4 // indirect
|
||||||
github.com/pion/ice/v4 v4.0.5 // indirect
|
|
||||||
github.com/pion/logging v0.2.3 // indirect
|
github.com/pion/logging v0.2.3 // indirect
|
||||||
github.com/pion/mdns/v2 v2.0.7 // indirect
|
github.com/pion/mdns/v2 v2.0.7 // indirect
|
||||||
github.com/pion/randutil v0.1.0 // indirect
|
github.com/pion/randutil v0.1.0 // indirect
|
||||||
github.com/pion/rtcp v1.2.15 // indirect
|
github.com/pion/rtcp v1.2.15 // indirect
|
||||||
github.com/pion/rtp v1.8.11 // indirect
|
github.com/pion/rtp v1.8.12 // indirect
|
||||||
github.com/pion/sctp v1.8.35 // indirect
|
github.com/pion/sctp v1.8.36 // indirect
|
||||||
github.com/pion/sdp/v3 v3.0.10 // indirect
|
github.com/pion/sdp/v3 v3.0.10 // indirect
|
||||||
github.com/pion/srtp/v3 v3.0.4 // indirect
|
github.com/pion/srtp/v3 v3.0.4 // indirect
|
||||||
github.com/pion/stun/v3 v3.0.0 // indirect
|
github.com/pion/stun/v3 v3.0.0 // indirect
|
||||||
github.com/pion/transport/v3 v3.0.7 // indirect
|
github.com/pion/transport/v3 v3.0.7 // indirect
|
||||||
github.com/pion/turn/v4 v4.0.0 // indirect
|
github.com/pion/turn/v4 v4.0.0 // indirect
|
||||||
github.com/wlynxg/anet v0.0.5 // indirect
|
github.com/wlynxg/anet v0.0.5 // indirect
|
||||||
golang.org/x/crypto v0.32.0 // indirect
|
golang.org/x/crypto v0.35.0 // indirect
|
||||||
golang.org/x/net v0.34.0 // indirect
|
golang.org/x/net v0.35.0 // indirect
|
||||||
golang.org/x/sys v0.29.0 // indirect
|
golang.org/x/sys v0.30.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk
|
|||||||
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
|
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
|
||||||
github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
|
github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
|
||||||
github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
|
github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
|
||||||
github.com/pion/ice/v4 v4.0.5 h1:6awVfa1jg9YsI9/Lep4TG/o3kwS1Oayr5b8xz50ibJ8=
|
github.com/pion/ice/v4 v4.0.7 h1:mnwuT3n3RE/9va41/9QJqN5+Bhc0H/x/ZyiVlWMw35M=
|
||||||
github.com/pion/ice/v4 v4.0.5/go.mod h1:JJaoEIxUIlGDA9gaRZbwXYqI3j6VG/QchpjX+QmwN6A=
|
github.com/pion/ice/v4 v4.0.7/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
|
||||||
github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
|
github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
|
||||||
github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
|
github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
|
||||||
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
|
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
|
||||||
@@ -22,10 +22,10 @@ github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
|||||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||||
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
||||||
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
||||||
github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk=
|
github.com/pion/rtp v1.8.12 h1:nsKs8Wi0jQyBFHU3qmn/OvtZrhktVfJY0vRxwACsL5U=
|
||||||
github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
|
github.com/pion/rtp v1.8.12/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
|
||||||
github.com/pion/sctp v1.8.35 h1:qwtKvNK1Wc5tHMIYgTDJhfZk7vATGVHhXbUDfHbYwzA=
|
github.com/pion/sctp v1.8.36 h1:owNudmnz1xmhfYje5L/FCav3V9wpPRePHle3Zi+P+M0=
|
||||||
github.com/pion/sctp v1.8.35/go.mod h1:EcXP8zCYVTRy3W9xtOF7wJm1L1aXfKRQzaM33SjQlzg=
|
github.com/pion/sctp v1.8.36/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
|
||||||
github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
|
github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA=
|
||||||
github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
||||||
github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
|
github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
|
||||||
@@ -36,23 +36,23 @@ github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1
|
|||||||
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
|
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
|
||||||
github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
|
github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
|
||||||
github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
|
github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
|
||||||
github.com/pion/webrtc/v4 v4.0.8 h1:T1ZmnT9qxIJIt4d8XoiMOBrTClGHDDXNg9e/fh018Qc=
|
github.com/pion/webrtc/v4 v4.0.12 h1:/omInB15DdJDlA3WoAQAAhIQQvFCWNHdJ2t5e2+ozx4=
|
||||||
github.com/pion/webrtc/v4 v4.0.8/go.mod h1:HHBeUVBAC+j4ZFnYhovEFStF02Arb1EyD4G7e7HBTJw=
|
github.com/pion/webrtc/v4 v4.0.12/go.mod h1:sMOtH6DSNVu6tfndczTMvJkKnyFVVeq+/G3dval418g=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||||
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||||
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package relay
|
package relay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/pion/ice/v4"
|
||||||
"github.com/pion/interceptor"
|
"github.com/pion/interceptor"
|
||||||
"github.com/pion/webrtc/v4"
|
"github.com/pion/webrtc/v4"
|
||||||
"log"
|
"log"
|
||||||
@@ -38,7 +39,7 @@ func InitWebRTCAPI() error {
|
|||||||
PayloadType: 49,
|
PayloadType: 49,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
if err := mediaEngine.RegisterCodec(codec, webrtc.RTPCodecTypeVideo); err != nil {
|
if err = mediaEngine.RegisterCodec(codec, webrtc.RTPCodecTypeVideo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,12 +59,28 @@ func InitWebRTCAPI() error {
|
|||||||
// New in v4, reduces CPU usage and latency when enabled
|
// New in v4, reduces CPU usage and latency when enabled
|
||||||
settingEngine.EnableSCTPZeroChecksum(true)
|
settingEngine.EnableSCTPZeroChecksum(true)
|
||||||
|
|
||||||
// Set the UDP port range used by WebRTC
|
nat11IPs := GetFlags().NAT11IPs
|
||||||
err = settingEngine.SetEphemeralUDPPortRange(uint16(flags.WebRTCUDPStart), uint16(flags.WebRTCUDPEnd))
|
if len(nat11IPs) > 0 {
|
||||||
if err != nil {
|
settingEngine.SetNAT1To1IPs(nat11IPs, webrtc.ICECandidateTypeHost)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
muxPort := GetFlags().UDPMuxPort
|
||||||
|
if muxPort > 0 {
|
||||||
|
mux, err := ice.NewMultiUDPMuxFromPort(muxPort)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
settingEngine.SetICEUDPMux(mux)
|
||||||
|
} else {
|
||||||
|
// Set the UDP port range used by WebRTC
|
||||||
|
err = settingEngine.SetEphemeralUDPPortRange(uint16(flags.WebRTCUDPStart), uint16(flags.WebRTCUDPEnd))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settingEngine.SetIncludeLoopbackCandidate(true) // Just in case
|
||||||
|
|
||||||
// Create a new API object with our customized settings
|
// Create a new API object with our customized settings
|
||||||
globalWebRTCAPI = webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine), webrtc.WithSettingEngine(settingEngine), webrtc.WithInterceptorRegistry(interceptorRegistry))
|
globalWebRTCAPI = webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine), webrtc.WithSettingEngine(settingEngine), webrtc.WithInterceptorRegistry(interceptorRegistry))
|
||||||
|
|
||||||
@@ -88,7 +105,7 @@ func CreatePeerConnection(onClose func()) (*webrtc.PeerConnection, error) {
|
|||||||
if connectionState == webrtc.PeerConnectionStateFailed ||
|
if connectionState == webrtc.PeerConnectionStateFailed ||
|
||||||
connectionState == webrtc.PeerConnectionStateDisconnected ||
|
connectionState == webrtc.PeerConnectionStateDisconnected ||
|
||||||
connectionState == webrtc.PeerConnectionStateClosed {
|
connectionState == webrtc.PeerConnectionStateClosed {
|
||||||
err := pc.Close()
|
err = pc.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error closing PeerConnection: %s\n", err.Error())
|
log.Printf("Error closing PeerConnection: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func participantHandler(participant *Participant, room *Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Data channel settings
|
// Data channel settings
|
||||||
settingOrdered := false
|
settingOrdered := true
|
||||||
settingMaxRetransmits := uint16(0)
|
settingMaxRetransmits := uint16(0)
|
||||||
dc, err := participant.PeerConnection.CreateDataChannel("data", &webrtc.DataChannelInit{
|
dc, err := participant.PeerConnection.CreateDataChannel("data", &webrtc.DataChannelInit{
|
||||||
Ordered: &settingOrdered,
|
Ordered: &settingOrdered,
|
||||||
@@ -75,13 +75,10 @@ func participantHandler(participant *Participant, room *Room) {
|
|||||||
log.Printf("Failed to marshal input message for participant: '%s' in room: '%s' - reason: %s\n", participant.ID, room.Name, err)
|
log.Printf("Failed to marshal input message for participant: '%s' in room: '%s' - reason: %s\n", participant.ID, room.Name, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = room.DataChannel.SendBinary(data); err != nil {
|
}
|
||||||
log.Printf("Failed to send input message to room: '%s' - reason: %s\n", room.Name, err)
|
|
||||||
}
|
if err = room.DataChannel.SendBinary(data); err != nil {
|
||||||
} else {
|
log.Printf("Failed to send input message to room: '%s' - reason: %s\n", room.Name, err)
|
||||||
if err = room.DataChannel.SendBinary(data); err != nil {
|
|
||||||
log.Printf("Failed to send input message to room: '%s' - reason: %s\n", room.Name, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,22 +2,28 @@ package relay
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"github.com/pion/webrtc/v4"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"github.com/pion/webrtc/v4"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var globalFlags *Flags
|
var globalFlags *Flags
|
||||||
|
|
||||||
type Flags struct {
|
type Flags struct {
|
||||||
Verbose bool
|
Verbose bool // Verbose mode - log more information to console
|
||||||
Debug bool
|
Debug bool // Debug mode - log deeper debug information to console
|
||||||
EndpointPort int
|
EndpointPort int // Port for HTTP/S and WS/S endpoint (TCP)
|
||||||
WebRTCUDPStart int
|
WebRTCUDPStart int // WebRTC UDP port range start - ignored if UDPMuxPort is set
|
||||||
WebRTCUDPEnd int
|
WebRTCUDPEnd int // WebRTC UDP port range end - ignored if UDPMuxPort is set
|
||||||
STUNServer string
|
STUNServer string // WebRTC STUN server
|
||||||
|
UDPMuxPort int // WebRTC UDP mux port - if set, overrides UDP port range
|
||||||
|
AutoAddLocalIP bool // Automatically add local IP to NAT 1 to 1 IPs
|
||||||
|
NAT11IPs []string // WebRTC NAT 1 to 1 IP(s) - allows specifying host IP(s) if behind NAT
|
||||||
|
TLSCert string // Path to TLS certificate
|
||||||
|
TLSKey string // Path to TLS key
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flags *Flags) DebugLog() {
|
func (flags *Flags) DebugLog() {
|
||||||
@@ -28,6 +34,13 @@ func (flags *Flags) DebugLog() {
|
|||||||
log.Println("> WebRTC UDP Range Start: ", flags.WebRTCUDPStart)
|
log.Println("> WebRTC UDP Range Start: ", flags.WebRTCUDPStart)
|
||||||
log.Println("> WebRTC UDP Range End: ", flags.WebRTCUDPEnd)
|
log.Println("> WebRTC UDP Range End: ", flags.WebRTCUDPEnd)
|
||||||
log.Println("> WebRTC STUN Server: ", flags.STUNServer)
|
log.Println("> WebRTC STUN Server: ", flags.STUNServer)
|
||||||
|
log.Println("> WebRTC UDP Mux Port: ", flags.UDPMuxPort)
|
||||||
|
log.Println("> Auto Add Local IP: ", flags.AutoAddLocalIP)
|
||||||
|
for i, ip := range flags.NAT11IPs {
|
||||||
|
log.Printf("> WebRTC NAT 1 to 1 IP (%d): %s\n", i, ip)
|
||||||
|
}
|
||||||
|
log.Println("> Path to TLS Cert: ", flags.TLSCert)
|
||||||
|
log.Println("> Path to TLS Key: ", flags.TLSKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEnvAsInt(name string, defaultVal int) int {
|
func getEnvAsInt(name string, defaultVal int) int {
|
||||||
@@ -66,6 +79,13 @@ func InitFlags() {
|
|||||||
flag.IntVar(&globalFlags.WebRTCUDPStart, "webrtcUDPStart", getEnvAsInt("WEBRTC_UDP_START", 10000), "WebRTC UDP port range start")
|
flag.IntVar(&globalFlags.WebRTCUDPStart, "webrtcUDPStart", getEnvAsInt("WEBRTC_UDP_START", 10000), "WebRTC UDP port range start")
|
||||||
flag.IntVar(&globalFlags.WebRTCUDPEnd, "webrtcUDPEnd", getEnvAsInt("WEBRTC_UDP_END", 20000), "WebRTC UDP port range end")
|
flag.IntVar(&globalFlags.WebRTCUDPEnd, "webrtcUDPEnd", getEnvAsInt("WEBRTC_UDP_END", 20000), "WebRTC UDP port range end")
|
||||||
flag.StringVar(&globalFlags.STUNServer, "stunServer", getEnvAsString("STUN_SERVER", "stun.l.google.com:19302"), "WebRTC STUN server")
|
flag.StringVar(&globalFlags.STUNServer, "stunServer", getEnvAsString("STUN_SERVER", "stun.l.google.com:19302"), "WebRTC STUN server")
|
||||||
|
flag.IntVar(&globalFlags.UDPMuxPort, "webrtcUDPMux", getEnvAsInt("WEBRTC_UDP_MUX", 8088), "WebRTC UDP mux port")
|
||||||
|
flag.BoolVar(&globalFlags.AutoAddLocalIP, "autoAddLocalIP", getEnvAsBool("AUTO_ADD_LOCAL_IP", true), "Automatically add local IP to NAT 1 to 1 IPs")
|
||||||
|
// String with comma separated IPs
|
||||||
|
nat11IPs := ""
|
||||||
|
flag.StringVar(&nat11IPs, "webrtcNAT11IPs", getEnvAsString("WEBRTC_NAT_IPS", ""), "WebRTC NAT 1 to 1 IP(s)")
|
||||||
|
flag.StringVar(&globalFlags.TLSCert, "tlsCert", getEnvAsString("TLS_CERT", ""), "Path to TLS certificate")
|
||||||
|
flag.StringVar(&globalFlags.TLSKey, "tlsKey", getEnvAsString("TLS_KEY", ""), "Path to TLS key")
|
||||||
// Parse flags
|
// Parse flags
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@@ -75,8 +95,44 @@ func InitFlags() {
|
|||||||
URLs: []string{"stun:" + globalFlags.STUNServer},
|
URLs: []string{"stun:" + globalFlags.STUNServer},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize NAT 1 to 1 IPs
|
||||||
|
globalFlags.NAT11IPs = []string{}
|
||||||
|
|
||||||
|
// Get local IP
|
||||||
|
if globalFlags.AutoAddLocalIP {
|
||||||
|
globalFlags.NAT11IPs = append(globalFlags.NAT11IPs, getLocalIP())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse NAT 1 to 1 IPs from string
|
||||||
|
if len(nat11IPs) > 0 {
|
||||||
|
split := strings.Split(nat11IPs, ",")
|
||||||
|
if len(split) > 0 {
|
||||||
|
for _, ip := range split {
|
||||||
|
globalFlags.NAT11IPs = append(globalFlags.NAT11IPs, ip)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
globalFlags.NAT11IPs = append(globalFlags.NAT11IPs, nat11IPs)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFlags() *Flags {
|
func GetFlags() *Flags {
|
||||||
return globalFlags
|
return globalFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getLocalIP returns local IP, be it either IPv4 or IPv6, skips loopback addresses
|
||||||
|
func getLocalIP() string {
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
for _, address := range addrs {
|
||||||
|
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||||
|
if ipnet.IP.To4() != nil || ipnet.IP != nil {
|
||||||
|
return ipnet.IP.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package relay
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -10,7 +11,7 @@ import (
|
|||||||
|
|
||||||
var httpMux *http.ServeMux
|
var httpMux *http.ServeMux
|
||||||
|
|
||||||
func InitHTTPEndpoint() {
|
func InitHTTPEndpoint() error {
|
||||||
// Create HTTP mux which serves our WS endpoint
|
// Create HTTP mux which serves our WS endpoint
|
||||||
httpMux = http.NewServeMux()
|
httpMux = http.NewServeMux()
|
||||||
|
|
||||||
@@ -20,15 +21,30 @@ func InitHTTPEndpoint() {
|
|||||||
|
|
||||||
// Get our serving port
|
// Get our serving port
|
||||||
port := GetFlags().EndpointPort
|
port := GetFlags().EndpointPort
|
||||||
|
tlsCert := GetFlags().TLSCert
|
||||||
|
tlsKey := GetFlags().TLSKey
|
||||||
|
|
||||||
// Log and start the endpoint server
|
// Log and start the endpoint server
|
||||||
log.Println("Starting HTTP endpoint server on :", strconv.Itoa(port))
|
if len(tlsCert) <= 0 && len(tlsKey) <= 0 {
|
||||||
go func() {
|
log.Println("Starting HTTP endpoint server on :", strconv.Itoa(port))
|
||||||
log.Fatal((&http.Server{
|
go func() {
|
||||||
Handler: httpMux,
|
log.Fatal((&http.Server{
|
||||||
Addr: ":" + strconv.Itoa(port),
|
Handler: httpMux,
|
||||||
}).ListenAndServe())
|
Addr: ":" + strconv.Itoa(port),
|
||||||
}()
|
}).ListenAndServe())
|
||||||
|
}()
|
||||||
|
} else if len(tlsCert) > 0 && len(tlsKey) > 0 {
|
||||||
|
log.Println("Starting HTTPS endpoint server on :", strconv.Itoa(port))
|
||||||
|
go func() {
|
||||||
|
log.Fatal((&http.Server{
|
||||||
|
Handler: httpMux,
|
||||||
|
Addr: ":" + strconv.Itoa(port),
|
||||||
|
}).ListenAndServeTLS(tlsCert, tlsKey))
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
return errors.New("no TLS certificate or TLS key provided")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// logHTTPError logs (if verbose) and sends an error code to requester
|
// logHTTPError logs (if verbose) and sends an error code to requester
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Container, FullScreen } from "@nestri/www/ui/layout";
|
|
||||||
import { Text } from "@nestri/www/ui/text";
|
import { Text } from "@nestri/www/ui/text";
|
||||||
|
import { Container, FullScreen } from "@nestri/www/ui/layout";
|
||||||
|
|
||||||
export function TeamCreate() {
|
export function TeamCreate() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user