Skip to content

Commit

Permalink
Add NAT1To1IP and UseExternalIP to config
Browse files Browse the repository at this point in the history
Gives user more control over what IP appears in Offer/Answer
  • Loading branch information
Sean-Der committed Dec 3, 2023
1 parent 3fff27b commit 38500e6
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 19 deletions.
8 changes: 8 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package config

import (
"fmt"
"os"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -49,6 +50,9 @@ type Config struct {
RTPPort rtcconfig.PortRange `yaml:"rtp_port"`
Logging logger.Config `yaml:"logging"`

UseExternalIP bool `yaml:"use_external_ip"`
NAT1To1IP string `yaml:"nat_1_to_1_ip"`

// internal
ServiceName string `yaml:"-"`
NodeID string // Do not provide, will be overwritten
Expand Down Expand Up @@ -91,6 +95,10 @@ func (conf *Config) Init() error {
return err
}

if conf.UseExternalIP && conf.NAT1To1IP != "" {
return fmt.Errorf("use_external_ip and nat_1_to_1_ip can not both be set")
}

return nil
}

Expand Down
21 changes: 16 additions & 5 deletions pkg/sip/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ import (
type Client struct {
conf *config.Config

sipCli *sipgo.Client
publicIp string
sipCli *sipgo.Client
signalingIp string

cmu sync.RWMutex
activeCalls map[string]*outboundCall
Expand All @@ -40,13 +40,25 @@ type Client struct {
func NewClient(conf *config.Config) *Client {
c := &Client{
conf: conf,
publicIp: getPublicIP(),
activeCalls: make(map[string]*outboundCall),
}
return c
}

func (c *Client) Start(agent *sipgo.UserAgent) error {
var err error
if c.conf.UseExternalIP {
if c.signalingIp, err = getPublicIP(); err != nil {
return err
}
} else if c.conf.NAT1To1IP != "" {
c.signalingIp = c.conf.NAT1To1IP
} else {
if c.signalingIp, err = getLocalIP(); err != nil {
return err
}
}

if agent == nil {
ua, err := sipgo.NewUA(
sipgo.WithUserAgent(UserAgent),
Expand All @@ -56,8 +68,7 @@ func (c *Client) Start(agent *sipgo.UserAgent) error {
}
agent = ua
}
var err error
c.sipCli, err = sipgo.NewClient(agent, sipgo.WithClientHostname(c.publicIp))
c.sipCli, err = sipgo.NewClient(agent, sipgo.WithClientHostname(c.signalingIp))
if err != nil {
return err
}
Expand Down
43 changes: 37 additions & 6 deletions pkg/sip/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,63 @@ package sip

import (
"encoding/json"
"fmt"
"io"
"net"
"net/http"
)

func getPublicIP() string {
func getPublicIP() (string, error) {
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
panic(err)
return "", err
}
defer req.Body.Close()

body, err := io.ReadAll(req.Body)
if err != nil {
panic(err)
return "", err
}

ip := struct {
Query string
}{}
if err = json.Unmarshal(body, &ip); err != nil {
panic(err)
return "", err
}

if ip.Query == "" {
panic("Query entry was not populated")
return "", fmt.Errorf("Query entry was not populated")
}

return ip.Query
return ip.Query, nil
}

func getLocalIP() (string, error) {
ifaces, err := net.Interfaces()
if err != nil {
return "", err
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
continue
}

for _, a := range addrs {
switch v := a.(type) {
case *net.IPAddr:
if !v.IP.IsLoopback() && v.IP.To4() != nil {
return v.IP.String(), nil
}
case *net.IPNet:
if !v.IP.IsLoopback() && v.IP.To4() != nil {
return v.IP.String(), nil
}
}

}
}

return "", fmt.Errorf("No local interface found")
}
4 changes: 2 additions & 2 deletions pkg/sip/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (c *inboundCall) handleInvite(req *sip.Request, tx sip.ServerTransaction) {
c.s.cmu.Unlock()

res := sip.NewResponseFromRequest(req, 200, "OK", answerData)
res.AppendHeader(&sip.ContactHeader{Address: sip.Uri{Host: c.s.publicIp, Port: c.s.conf.SIPPort}})
res.AppendHeader(&sip.ContactHeader{Address: sip.Uri{Host: c.s.signalingIp, Port: c.s.conf.SIPPort}})
res.AppendHeader(&contentTypeHeaderSDP)
if err = tx.Respond(res); err != nil {
log.Println(err)
Expand Down Expand Up @@ -202,7 +202,7 @@ func (c *inboundCall) runMediaConn(offerData []byte) (answerData []byte, _ error
s := rtp.NewMediaStreamOut[ulaw.Sample](conn, rtpPacketDur)
c.lkRoom.SetOutput(ulaw.Decode(s))

return sdpGenerateAnswer(offer, c.s.publicIp, conn.LocalAddr().Port)
return sdpGenerateAnswer(offer, c.s.signalingIp, conn.LocalAddr().Port)
}

func (c *inboundCall) pinPrompt() {
Expand Down
4 changes: 2 additions & 2 deletions pkg/sip/outbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ func (c *outboundCall) stopSIP() {
}

func (c *outboundCall) sipSignal(conf sipOutboundConfig) error {
offer, err := sdpGenerateOffer(c.c.publicIp, c.rtpConn.LocalAddr().Port)
offer, err := sdpGenerateOffer(c.c.signalingIp, c.rtpConn.LocalAddr().Port)
if err != nil {
return err
}
Expand All @@ -271,7 +271,7 @@ func (c *outboundCall) sipAttemptInvite(offer []byte, conf sipOutboundConfig, au
req.SetDestination("") // FIXME: what should be here
req.SetBody(offer)
req.AppendHeader(sip.NewHeader("Content-Type", "application/sdp"))
req.AppendHeader(sip.NewHeader("Contact", fmt.Sprintf("<sip:livekit@%s:5060>", c.c.publicIp)))
req.AppendHeader(sip.NewHeader("Contact", fmt.Sprintf("<sip:livekit@%s:5060>", c.c.signalingIp)))
req.AppendHeader(sip.NewHeader("Allow", "INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE"))

if authHeader != "" {
Expand Down
20 changes: 16 additions & 4 deletions pkg/sip/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ type (
AuthHandlerFunc func(from, to, srcAddress string) (username, password string, err error)
DispatchRuleHandlerFunc func(callingNumber, calledNumber, srcAddress string, pin string, noPin bool) (joinRoom, identity string, requestPin, rejectInvite bool)
Server struct {
sipSrv *sipgo.Server
publicIp string
sipSrv *sipgo.Server
signalingIp string

inProgressInvites []*inProgressInvite

Expand All @@ -65,7 +65,6 @@ type (
func NewServer(conf *config.Config) *Server {
s := &Server{
conf: conf,
publicIp: getPublicIP(),
activeCalls: make(map[string]*inboundCall),
inProgressInvites: []*inProgressInvite{},
}
Expand Down Expand Up @@ -110,6 +109,19 @@ func logOnError(err error) {
}

func (s *Server) Start(agent *sipgo.UserAgent) error {
var err error
if s.conf.UseExternalIP {
if s.signalingIp, err = getPublicIP(); err != nil {
return err
}
} else if s.conf.NAT1To1IP != "" {
s.signalingIp = s.conf.NAT1To1IP
} else {
if s.signalingIp, err = getLocalIP(); err != nil {
return err
}
}

if agent == nil {
ua, err := sipgo.NewUA(
sipgo.WithUserAgent(UserAgent),
Expand All @@ -119,7 +131,7 @@ func (s *Server) Start(agent *sipgo.UserAgent) error {
}
agent = ua
}
var err error

s.sipSrv, err = sipgo.NewServer(agent)
if err != nil {
return err
Expand Down

0 comments on commit 38500e6

Please sign in to comment.