2020-10-23 03:54:50 +13:00
package config
import (
"strconv"
"strings"
2021-03-11 01:15:18 +13:00
"github.com/rs/zerolog/log"
2020-10-23 03:54:50 +13:00
"github.com/spf13/cobra"
"github.com/spf13/viper"
2021-02-02 11:50:18 +13:00
2022-07-14 10:58:22 +12:00
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/utils"
2020-10-23 03:54:50 +13:00
)
2021-09-03 07:37:24 +12:00
// default stun server
const defStunSrv = "stun:stun.l.google.com:19302"
2020-10-23 03:54:50 +13:00
type WebRTC struct {
ICELite bool
2021-02-03 09:12:11 +13:00
ICETrickle bool
2021-03-18 03:47:49 +13:00
ICEServers [ ] types . ICEServer
2020-10-23 03:54:50 +13:00
EphemeralMin uint16
EphemeralMax uint16
2022-02-10 09:45:03 +13:00
TCPMux int
UDPMux int
2021-03-11 01:15:18 +13:00
NAT1To1IPs [ ] string
IpRetrievalUrl string
2020-10-23 03:54:50 +13:00
}
func ( WebRTC ) Init ( cmd * cobra . Command ) error {
2021-03-17 03:24:58 +13:00
cmd . PersistentFlags ( ) . Bool ( "webrtc.icelite" , false , "configures whether or not the ICE agent should be a lite agent" )
if err := viper . BindPFlag ( "webrtc.icelite" , cmd . PersistentFlags ( ) . Lookup ( "webrtc.icelite" ) ) ; err != nil {
2020-10-23 03:54:50 +13:00
return err
}
2021-03-17 03:24:58 +13:00
cmd . PersistentFlags ( ) . Bool ( "webrtc.icetrickle" , true , "configures whether cadidates should be sent asynchronously using Trickle ICE" )
if err := viper . BindPFlag ( "webrtc.icetrickle" , cmd . PersistentFlags ( ) . Lookup ( "webrtc.icetrickle" ) ) ; err != nil {
2020-10-23 03:54:50 +13:00
return err
}
2021-03-18 03:47:49 +13:00
cmd . PersistentFlags ( ) . String ( "webrtc.iceservers" , "[]" , "STUN and TURN servers in JSON format with `urls`, `username`, `password` keys" )
if err := viper . BindPFlag ( "webrtc.iceservers" , cmd . PersistentFlags ( ) . Lookup ( "webrtc.iceservers" ) ) ; err != nil {
2020-10-23 03:54:50 +13:00
return err
}
2022-02-10 09:45:03 +13:00
cmd . PersistentFlags ( ) . String ( "webrtc.epr" , "" , "limits the pool of ephemeral ports that ICE UDP connections can allocate from" )
if err := viper . BindPFlag ( "webrtc.epr" , cmd . PersistentFlags ( ) . Lookup ( "webrtc.epr" ) ) ; err != nil {
return err
}
cmd . PersistentFlags ( ) . Int ( "webrtc.tcpmux" , 0 , "single TCP mux port for all peers" )
if err := viper . BindPFlag ( "webrtc.tcpmux" , cmd . PersistentFlags ( ) . Lookup ( "webrtc.tcpmux" ) ) ; err != nil {
return err
}
cmd . PersistentFlags ( ) . Int ( "webrtc.udpmux" , 0 , "single UDP mux port for all peers, replaces EPR" )
if err := viper . BindPFlag ( "webrtc.udpmux" , cmd . PersistentFlags ( ) . Lookup ( "webrtc.udpmux" ) ) ; err != nil {
return err
}
2021-03-17 03:24:58 +13:00
cmd . PersistentFlags ( ) . StringSlice ( "webrtc.nat1to1" , [ ] string { } , "sets a list of external IP addresses of 1:1 (D)NAT and a candidate type for which the external IP address is used" )
if err := viper . BindPFlag ( "webrtc.nat1to1" , cmd . PersistentFlags ( ) . Lookup ( "webrtc.nat1to1" ) ) ; err != nil {
2020-10-23 03:54:50 +13:00
return err
}
2021-03-17 03:24:58 +13:00
cmd . PersistentFlags ( ) . String ( "webrtc.ip_retrieval_url" , "https://checkip.amazonaws.com" , "URL address used for retrieval of the external IP address" )
if err := viper . BindPFlag ( "webrtc.ip_retrieval_url" , cmd . PersistentFlags ( ) . Lookup ( "webrtc.ip_retrieval_url" ) ) ; err != nil {
2021-03-11 01:15:18 +13:00
return err
}
2020-10-23 03:54:50 +13:00
return nil
}
func ( s * WebRTC ) Set ( ) {
2021-03-17 03:24:58 +13:00
s . ICELite = viper . GetBool ( "webrtc.icelite" )
s . ICETrickle = viper . GetBool ( "webrtc.icetrickle" )
2021-03-18 03:47:49 +13:00
if err := viper . UnmarshalKey ( "webrtc.iceservers" , & s . ICEServers , viper . DecodeHook (
utils . JsonStringAutoDecode ( s . ICEServers ) ,
) ) ; err != nil {
log . Warn ( ) . Err ( err ) . Msgf ( "unable to parse ICE servers" )
}
if len ( s . ICEServers ) == 0 {
s . ICEServers = append ( s . ICEServers , types . ICEServer {
2021-09-03 07:37:24 +12:00
URLs : [ ] string { defStunSrv } ,
2021-03-18 03:47:49 +13:00
} )
}
2020-10-23 03:54:50 +13:00
2022-02-10 09:45:03 +13:00
s . TCPMux = viper . GetInt ( "webrtc.tcpmux" )
s . UDPMux = viper . GetInt ( "webrtc.udpmux" )
epr := viper . GetString ( "webrtc.epr" )
if epr != "" {
ports := strings . SplitN ( epr , "-" , - 1 )
if len ( ports ) > 1 {
min , err := strconv . ParseUint ( ports [ 0 ] , 10 , 16 )
if err != nil {
log . Panic ( ) . Err ( err ) . Msgf ( "unable to parse ephemeral min port" )
}
max , err := strconv . ParseUint ( ports [ 1 ] , 10 , 16 )
if err != nil {
log . Panic ( ) . Err ( err ) . Msgf ( "unable to parse ephemeral max port" )
}
s . EphemeralMin = uint16 ( min )
s . EphemeralMax = uint16 ( max )
}
if s . EphemeralMin > s . EphemeralMax {
log . Panic ( ) . Msgf ( "ephemeral min port cannot be bigger than max" )
}
}
if epr == "" && s . TCPMux == 0 && s . UDPMux == 0 {
// using default epr range
s . EphemeralMin = 59000
s . EphemeralMax = 59100
log . Warn ( ) .
Uint16 ( "min" , s . EphemeralMin ) .
Uint16 ( "max" , s . EphemeralMax ) .
Msgf ( "no TCP, UDP mux or epr specified, using default epr range" )
}
2021-03-17 03:24:58 +13:00
s . NAT1To1IPs = viper . GetStringSlice ( "webrtc.nat1to1" )
s . IpRetrievalUrl = viper . GetString ( "webrtc.ip_retrieval_url" )
2021-03-11 01:15:18 +13:00
if s . IpRetrievalUrl != "" && len ( s . NAT1To1IPs ) == 0 {
ip , err := utils . HttpRequestGET ( s . IpRetrievalUrl )
2020-10-23 03:54:50 +13:00
if err == nil {
s . NAT1To1IPs = append ( s . NAT1To1IPs , ip )
2021-03-11 01:15:18 +13:00
} else {
log . Warn ( ) . Err ( err ) . Msgf ( "IP retrieval failed" )
2020-10-23 03:54:50 +13:00
}
}
}