Add mux support. (#58)

* add mux support.

* usemux to mux.

* lint fix.

* dev script mux.

* add mux to readme.
This commit is contained in:
Miroslav Šedivý
2022-07-31 13:52:41 +02:00
committed by GitHub
parent 3d787ab67f
commit e8b875229b
10 changed files with 130 additions and 40 deletions
+3
View File
@@ -282,6 +282,9 @@ components:
storage_enabled:
type: boolean
example: true
uses_mux:
type: boolean
example: true
RoomEntry:
type: object
+6
View File
@@ -590,6 +590,12 @@ export interface RoomsConfig {
* @memberof RoomsConfig
*/
'storage_enabled'?: boolean;
/**
*
* @type {boolean}
* @memberof RoomsConfig
*/
'uses_mux'?: boolean;
}
/**
+8 -3
View File
@@ -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 {}
+27 -2
View File
@@ -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
+7 -2
View File
@@ -89,14 +89,18 @@ export default class RoomsList extends Vue {
private roomId = ''
private roomLoading = [] as Array<string>
private headers = [
get headers() {
return [
{
text: 'Deployment',
value: 'url',
sortable: false,
},
{ text: 'Name', value: 'name' },
{ text: 'Max connections', value: 'max_connections' },
// 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' },
@@ -112,6 +116,7 @@ export default class RoomsList extends Vue {
sortable: false,
},
]
}
get rooms() {
return this.$store.state.rooms
+1
View File
@@ -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}`" \
+8
View File
@@ -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
```
+8
View File
@@ -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
View File
@@ -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, ",")))
+5 -2
View File
@@ -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"`