2020-10-23 03:54:50 +13:00
package config
import (
2021-03-11 01:15:18 +13:00
"fmt"
2020-10-23 03:54:50 +13:00
"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
2021-03-18 03:47:49 +13:00
"demodesk/neko/internal/types"
2021-03-19 01:38:32 +13:00
"demodesk/neko/internal/utils"
2020-10-23 03:54:50 +13:00
)
2021-09-03 07:37:24 +12:00
// default port range - min
const defEprMin = 59000
// default port range - max
const defEprMax = 59100
// 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
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
}
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
}
2021-03-17 03:24:58 +13:00
cmd . PersistentFlags ( ) . String ( "webrtc.epr" , fmt . Sprintf ( "%d-%d" , defEprMin , defEprMax ) , "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 {
2021-02-03 09:12:11 +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
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
}
}
2021-03-11 01:15:18 +13:00
min := uint16 ( defEprMin )
max := uint16 ( defEprMax )
2021-03-17 03:24:58 +13:00
epr := viper . GetString ( "webrtc.epr" )
2020-10-23 03:54:50 +13:00
ports := strings . SplitN ( epr , "-" , - 1 )
if len ( ports ) > 1 {
start , err := strconv . ParseUint ( ports [ 0 ] , 10 , 16 )
if err == nil {
min = uint16 ( start )
}
end , err := strconv . ParseUint ( ports [ 1 ] , 10 , 16 )
if err == nil {
max = uint16 ( end )
}
}
if min > max {
s . EphemeralMin = max
s . EphemeralMax = min
} else {
s . EphemeralMin = min
s . EphemeralMax = max
}
}