mirror of
https://github.com/m1k1o/neko-rooms.git
synced 2026-11-02 22:51:34 -06:00
Add mux support. (#58)
* add mux support. * usemux to mux. * lint fix. * dev script mux. * add mux to readme.
This commit is contained in:
@@ -282,6 +282,9 @@ components:
|
||||
storage_enabled:
|
||||
type: boolean
|
||||
example: true
|
||||
uses_mux:
|
||||
type: boolean
|
||||
example: true
|
||||
|
||||
RoomEntry:
|
||||
type: object
|
||||
|
||||
@@ -590,6 +590,12 @@ export interface RoomsConfig {
|
||||
* @memberof RoomsConfig
|
||||
*/
|
||||
'storage_enabled'?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof RoomsConfig
|
||||
*/
|
||||
'uses_mux'?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
:rotate="270"
|
||||
:size="100"
|
||||
:width="15"
|
||||
:value="(stats.connections / settings.max_connections) * 100"
|
||||
:value="usesMux ? 100 : ((stats.connections / settings.max_connections) * 100)"
|
||||
color="blue"
|
||||
>
|
||||
{{ stats.connections }} / {{ settings.max_connections }}
|
||||
{{ stats.connections }} <template v-if="!usesMux">/ {{ settings.max_connections }}</template>
|
||||
</v-progress-circular>
|
||||
</div>
|
||||
</v-col>
|
||||
@@ -99,7 +99,7 @@
|
||||
<span>Invite link for admins</span>
|
||||
</v-tooltip>
|
||||
</td></tr>
|
||||
<tr><th> Max connections </th><td>{{ settings.max_connections }}</td></tr>
|
||||
<tr v-if="!usesMux"><th> Max connections </th><td>{{ settings.max_connections }}</td></tr>
|
||||
<tr><th> Control protection </th><td>{{ settings.control_protection }}</td></tr>
|
||||
<tr><th> Implicit Control </th><td>{{ settings.implicit_control }}</td></tr>
|
||||
</tbody>
|
||||
@@ -274,6 +274,11 @@ export default class RoomInfo extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
get usesMux() {
|
||||
// old rooms might not use mux despite enabled server wide, simple check for that
|
||||
return this.$store.state.roomsConfig.uses_mux && this.settings?.max_connections == 1
|
||||
}
|
||||
|
||||
get allBrowserExtensions() {
|
||||
if (!this.settings?.browser_policy?.type) return {}
|
||||
|
||||
|
||||
@@ -56,7 +56,28 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row align="center">
|
||||
<!-- if uses mux vs. old logic -->
|
||||
<v-row align="center" v-if="usesMux">
|
||||
<v-col class="pt-0">
|
||||
<v-checkbox
|
||||
v-model="data.control_protection"
|
||||
label="Enable control protection"
|
||||
hide-details
|
||||
class="shrink ml-2 mt-0"
|
||||
></v-checkbox>
|
||||
<div style="margin-left: 41px;"><i>Users can gain control only if at least one admin is in the room.</i></div>
|
||||
</v-col>
|
||||
<v-col class="pt-0">
|
||||
<v-checkbox
|
||||
v-model="data.implicit_control"
|
||||
label="Enable implicit control"
|
||||
hide-details
|
||||
class="shrink ml-2 mt-0"
|
||||
></v-checkbox>
|
||||
<div style="margin-left: 41px;"><i>Users do not need to request control prior usage.</i></div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row align="center" v-else>
|
||||
<v-col class="pt-0">
|
||||
<v-text-field
|
||||
label="Max connections"
|
||||
@@ -482,6 +503,10 @@ export default class RoomsCreate extends Vue {
|
||||
return this.$store.state.roomsConfig.storage_enabled
|
||||
}
|
||||
|
||||
get usesMux() {
|
||||
return this.$store.state.roomsConfig.uses_mux
|
||||
}
|
||||
|
||||
get videoCodecs() {
|
||||
return this.$store.state.videoCodecs
|
||||
}
|
||||
@@ -579,7 +604,7 @@ export default class RoomsCreate extends Vue {
|
||||
// eslint-disable-next-line
|
||||
admin_pass: this.data.admin_pass || randomPassword(),
|
||||
// eslint-disable-next-line
|
||||
max_connections: Number(this.data.max_connections),
|
||||
max_connections: Number(this.data.max_connections), // not needed when uses mux
|
||||
// eslint-disable-next-line
|
||||
control_protection: Boolean(this.data.control_protection),
|
||||
// eslint-disable-next-line
|
||||
|
||||
@@ -89,29 +89,34 @@ export default class RoomsList extends Vue {
|
||||
private roomId = ''
|
||||
private roomLoading = [] as Array<string>
|
||||
|
||||
private headers = [
|
||||
{
|
||||
text: 'Deployment',
|
||||
value: 'url',
|
||||
sortable: false,
|
||||
},
|
||||
{ text: 'Name', value: 'name' },
|
||||
{ text: 'Max connections', value: 'max_connections' },
|
||||
{ text: 'Neko image', value: 'neko_image' },
|
||||
{ text: 'Status', value: 'status' },
|
||||
{ text: 'Created', value: 'created' },
|
||||
{
|
||||
text: 'Actions',
|
||||
value: 'actions',
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
text: 'Destroy',
|
||||
value: 'destroy',
|
||||
align: 'end',
|
||||
sortable: false,
|
||||
},
|
||||
]
|
||||
get headers() {
|
||||
return [
|
||||
{
|
||||
text: 'Deployment',
|
||||
value: 'url',
|
||||
sortable: false,
|
||||
},
|
||||
{ text: 'Name', value: 'name' },
|
||||
// when using mux we don't have max connections
|
||||
...(!this.$store.state.roomsConfig.uses_mux ? [
|
||||
{ text: 'Max connections', value: 'max_connections' }
|
||||
] : []),
|
||||
{ text: 'Neko image', value: 'neko_image' },
|
||||
{ text: 'Status', value: 'status' },
|
||||
{ text: 'Created', value: 'created' },
|
||||
{
|
||||
text: 'Actions',
|
||||
value: 'actions',
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
text: 'Destroy',
|
||||
value: 'destroy',
|
||||
align: 'end',
|
||||
sortable: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
get rooms() {
|
||||
return this.$store.state.rooms
|
||||
|
||||
@@ -21,6 +21,7 @@ docker run --rm -it \
|
||||
-v "`realpath ${DATA_PATH}`:/data" \
|
||||
-e "TZ=${TZ}" \
|
||||
-e "NEKO_ROOMS_EPR=${NEKO_ROOMS_EPR}" \
|
||||
-e "NEKO_ROOMS_MUX=true" \
|
||||
-e "NEKO_ROOMS_NAT1TO1=${NEKO_ROOMS_NAT1TO1}" \
|
||||
-e "NEKO_ROOMS_STORAGE_INTERNAL=/data" \
|
||||
-e "NEKO_ROOMS_STORAGE_EXTERNAL=`realpath ${DATA_PATH}`" \
|
||||
|
||||
@@ -21,3 +21,11 @@ NEKO_ROOMS_PATH_PREFIX=/test/
|
||||
```
|
||||
|
||||
Now room will be available at `example.org/test/<room-name>` instead of `example.org/<room-name>`.
|
||||
|
||||
## using mux
|
||||
|
||||
When using mux, there will be allocated two ports per room: TCP and UDP port with the same number.
|
||||
|
||||
```
|
||||
NEKO_ROOMS_MUX=true
|
||||
```
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
)
|
||||
|
||||
type Room struct {
|
||||
Mux bool
|
||||
EprMin uint16
|
||||
EprMax uint16
|
||||
|
||||
@@ -40,6 +41,11 @@ type Room struct {
|
||||
}
|
||||
|
||||
func (Room) Init(cmd *cobra.Command) error {
|
||||
cmd.PersistentFlags().StringSlice("usemux", []string{}, "use mux for connection - needs only one UDP and TCP port per room")
|
||||
if err := viper.BindPFlag("usemux", cmd.PersistentFlags().Lookup("usemux")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().String("epr", "59000-59999", "limits the pool of ephemeral ports that ICE UDP connections can allocate from")
|
||||
if err := viper.BindPFlag("epr", cmd.PersistentFlags().Lookup("epr")); err != nil {
|
||||
return err
|
||||
@@ -147,6 +153,8 @@ func (Room) Init(cmd *cobra.Command) error {
|
||||
}
|
||||
|
||||
func (s *Room) Set() {
|
||||
s.Mux = viper.GetBool("mux")
|
||||
|
||||
min := uint16(59000)
|
||||
max := uint16(59999)
|
||||
epr := viper.GetString("epr")
|
||||
|
||||
+36
-10
@@ -55,6 +55,7 @@ func (manager *RoomManagerCtx) Config() types.RoomsConfig {
|
||||
Connections: manager.config.EprMax - manager.config.EprMin + 1,
|
||||
NekoImages: manager.config.NekoImages,
|
||||
StorageEnabled: manager.config.StorageEnabled,
|
||||
UsesMux: manager.config.Mux,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,27 +116,42 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
|
||||
// Allocate ports
|
||||
//
|
||||
|
||||
epr, err := manager.allocatePorts(settings.MaxConnections)
|
||||
portsNeeded := settings.MaxConnections
|
||||
if manager.config.Mux {
|
||||
portsNeeded = 1
|
||||
}
|
||||
|
||||
epr, err := manager.allocatePorts(portsNeeded)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
portBindings := nat.PortMap{}
|
||||
exposedPorts := nat.PortSet{
|
||||
nat.Port(fmt.Sprintf("%d/tcp", frontendPort)): struct{}{},
|
||||
}
|
||||
|
||||
for port := epr.Min; port <= epr.Max; port++ {
|
||||
portKey := nat.Port(fmt.Sprintf("%d/udp", port))
|
||||
|
||||
portBindings[portKey] = []nat.PortBinding{
|
||||
portBindings[nat.Port(fmt.Sprintf("%d/udp", port))] = []nat.PortBinding{
|
||||
{
|
||||
HostIP: "0.0.0.0",
|
||||
HostPort: fmt.Sprintf("%d", port),
|
||||
},
|
||||
}
|
||||
|
||||
exposedPorts[portKey] = struct{}{}
|
||||
// expose TCP port as well when using mux
|
||||
if manager.config.Mux {
|
||||
portBindings[nat.Port(fmt.Sprintf("%d/tcp", port))] = []nat.PortBinding{
|
||||
{
|
||||
HostIP: "0.0.0.0",
|
||||
HostPort: fmt.Sprintf("%d", port),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exposedPorts := nat.PortSet{
|
||||
nat.Port(fmt.Sprintf("%d/tcp", frontendPort)): struct{}{},
|
||||
}
|
||||
|
||||
for port := range portBindings {
|
||||
exposedPorts[port] = struct{}{}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -229,10 +245,20 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (string, erro
|
||||
|
||||
env := []string{
|
||||
fmt.Sprintf("NEKO_BIND=:%d", frontendPort),
|
||||
fmt.Sprintf("NEKO_EPR=%d-%d", epr.Min, epr.Max),
|
||||
"NEKO_ICELITE=true",
|
||||
}
|
||||
|
||||
if manager.config.Mux {
|
||||
env = append(env,
|
||||
fmt.Sprintf("NEKO_UDPMUX=%d", epr.Min),
|
||||
fmt.Sprintf("NEKO_TCPMUX=%d", epr.Min),
|
||||
)
|
||||
} else {
|
||||
env = append(env,
|
||||
fmt.Sprintf("NEKO_EPR=%d-%d", epr.Min, epr.Max),
|
||||
)
|
||||
}
|
||||
|
||||
// optional nat mapping
|
||||
if len(manager.config.NAT1To1IPs) > 0 {
|
||||
env = append(env, fmt.Sprintf("NEKO_NAT1TO1=%s", strings.Join(manager.config.NAT1To1IPs, ",")))
|
||||
|
||||
@@ -19,6 +19,8 @@ var blacklistedEnvs = []string{
|
||||
// ignore bunch of envs managed by neko-rooms
|
||||
"NEKO_BIND",
|
||||
"NEKO_EPR",
|
||||
"NEKO_UDPMUX",
|
||||
"NEKO_TCPMUX",
|
||||
"NEKO_NAT1TO1",
|
||||
"NEKO_ICELITE",
|
||||
}
|
||||
@@ -27,6 +29,7 @@ type RoomsConfig struct {
|
||||
Connections uint16 `json:"connections"`
|
||||
NekoImages []string `json:"neko_images"`
|
||||
StorageEnabled bool `json:"storage_enabled"`
|
||||
UsesMux bool `json:"uses_mux"`
|
||||
}
|
||||
|
||||
type RoomEntry struct {
|
||||
@@ -35,7 +38,7 @@ type RoomEntry struct {
|
||||
Name string `json:"name"`
|
||||
NekoImage string `json:"neko_image"`
|
||||
IsOutdated bool `json:"is_outdated"`
|
||||
MaxConnections uint16 `json:"max_connections"`
|
||||
MaxConnections uint16 `json:"max_connections"` // ignored when using mux
|
||||
Running bool `json:"running"`
|
||||
Status string `json:"status"`
|
||||
Created time.Time `json:"created"`
|
||||
@@ -66,7 +69,7 @@ type RoomResources struct {
|
||||
type RoomSettings struct {
|
||||
Name string `json:"name"`
|
||||
NekoImage string `json:"neko_image"`
|
||||
MaxConnections uint16 `json:"max_connections"`
|
||||
MaxConnections uint16 `json:"max_connections"` // ignored when using mux
|
||||
|
||||
ControlProtection bool `json:"control_protection"`
|
||||
ImplicitControl bool `json:"implicit_control"`
|
||||
|
||||
Reference in New Issue
Block a user