Skip to content

Commit

Permalink
Picking the highest priority nominated candidate
Browse files Browse the repository at this point in the history
  • Loading branch information
daonb committed Jun 4, 2024
1 parent a9afafc commit 5cd69a4
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 64 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ and the release workflow reads it to set github's release notes.

### Added

- the status command show the chosen ICE candidate pairs for connected peers
- the status command shows the chosen ICE candidate pairs for connected peers

## [1.4.0] 2024-4-14

Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ require (
git.rootprojects.org/root/go-gitver/v2 v2.0.2
github.com/coreos/go-semver v0.3.1
github.com/creack/pty v1.1.20
github.com/dchest/uniuri v1.2.0
github.com/fatih/color v1.17.0
github.com/google/uuid v1.3.1
github.com/gorilla/websocket v1.4.2
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
Expand All @@ -29,8 +31,6 @@ require (
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dchest/uniuri v1.2.0 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/kr/pretty v0.3.1 // indirect
Expand Down
60 changes: 60 additions & 0 deletions peers/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strconv"
"strings"
"sync"
"text/tabwriter"
"time"
"unicode"

Expand Down Expand Up @@ -76,6 +77,24 @@ type Peer struct {
Conf *Conf
}

// CandidatePairStats is a struct that holds the values of a ICE candidate pair
type CandidatePairStats struct {
FP string `json:"fp"`
LocalAddr string `json:"local_addr"` // IP:Port
LocalProtocol string `json:"local_proto"`
LocalType string `json:"local_type"`
RemoteAddr string `json:"remote_addr"`
RemoteProtocol string `json:"remote_proto"`
RemoteType string `json:"remote_type"`
}

// CandidatePairStats.Write writes the candidate pair to a tabwriter
func (p *CandidatePairStats) Write(w *tabwriter.Writer) {
fp := fmt.Sprintf("%s\uf141", string([]rune(p.FP)[:6]))
fmt.Fprintln(w, strings.Join([]string{fp, p.LocalAddr, p.LocalProtocol,
p.LocalType, "->", p.RemoteAddr, p.RemoteProtocol, p.RemoteType}, "\t"))
}

// NewPeer funcions starts listening to incoming peer connection from a remote
func NewPeer(fp string, conf *Conf) (*Peer, error) {
webrtcAPIM.Lock()
Expand Down Expand Up @@ -477,6 +496,47 @@ func (peer *Peer) Broadcast(typ string, args interface{}) error {
}
return nil
}
func (peer *Peer) GetCandidatePair(ret *CandidatePairStats) error {
ret.FP = peer.FP
if peer.PC == nil {
return fmt.Errorf("peer has no peer connection")
}
stats := peer.PC.GetStats()
var localP int32
var remoteP int32
for _, report := range stats {
pairStats, ok := report.(webrtc.ICECandidatePairStats)
if !ok || pairStats.Type != webrtc.StatsTypeCandidatePair {
continue
}
// Check if it is selected
if !pairStats.Nominated {
continue
}
local, ok := stats[pairStats.LocalCandidateID].(webrtc.ICECandidateStats)
if !ok {
return fmt.Errorf("failed to get local candidate")
}
remote, ok := stats[pairStats.RemoteCandidateID].(webrtc.ICECandidateStats)
if !ok {
return fmt.Errorf("failed to get remote candidate")
}
if local.Priority > localP {
localP = local.Priority
ret.LocalAddr = fmt.Sprintf("%s:%d", local.IP, local.Port)
ret.LocalProtocol = local.Protocol
ret.LocalType = local.CandidateType.String()
}
if remote.Priority > remoteP {
remoteP = remote.Priority
ret.RemoteAddr = fmt.Sprintf("%s:%d", remote.IP, remote.Port)
ret.RemoteProtocol = remote.Protocol
ret.RemoteType = remote.CandidateType.String()
}
}
return nil
}

func (peer *Peer) Close() {
peer.Lock()
defer peer.Unlock()
Expand Down
64 changes: 12 additions & 52 deletions sock.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"runtime"
"strings"
"sync"
"text/tabwriter"
"time"

"github.com/dchest/uniuri"
Expand Down Expand Up @@ -42,18 +41,11 @@ type LiveOffer struct {
p *peers.Peer
id string
}
type CandidatePairValues struct {
FP string `json:"fp"`
LocalAddr string `json:"local_addr"` // IP:Port
LocalProtocol string `json:"local_proto"`
LocalType string `json:"local_type"`
RemoteAddr string `json:"remote_addr"`
RemoteProtocol string `json:"remote_proto"`
RemoteType string `json:"remote_type"`
}

// StatusMessage is a struct that holds the response to the status request
type StatusMessage struct {
Version string `json:"version"`
Peers []CandidatePairValues `json:"peers,omitempty"`
Version string `json:"version"`
Peers []peers.CandidatePairStats `json:"peers,omitempty"`
}

const socketFileName = "webexec.sock"
Expand Down Expand Up @@ -207,48 +199,22 @@ func StartSocketServer(lc fx.Lifecycle, s *sockServer, params SocketStartParams)
return &server, nil
}

// handleStatus now uses getPeerStat to extract peer stats.
func (s *sockServer) handleStatus(w http.ResponseWriter, r *http.Request) {
Logger.Info("Got status request")
if r.Method != "GET" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}

ret := StatusMessage{Version: version}
for _, peer := range peers.Peers {
if peer.PC == nil {
continue
}
stats := peer.PC.GetStats()
for _, report := range stats {
pairStats, ok := report.(webrtc.ICECandidatePairStats)
if !ok || pairStats.Type != webrtc.StatsTypeCandidatePair {
continue
}
// check if it is selected
if pairStats.State != webrtc.StatsICECandidatePairStateSucceeded {
continue
}
local, ok := stats[pairStats.LocalCandidateID].(webrtc.ICECandidateStats)
if !ok {
http.Error(w, "Failed to get local candidate", http.StatusInternalServerError)
return
}
remote, ok := stats[pairStats.RemoteCandidateID].(webrtc.ICECandidateStats)
if !ok {
http.Error(w, "Failed to get remote candidate", http.StatusInternalServerError)
return
}
ret.Peers = append(ret.Peers, CandidatePairValues{
FP: peer.FP,
LocalAddr: fmt.Sprintf("%s:%d", local.IP, local.Port),
LocalProtocol: local.Protocol,
LocalType: local.CandidateType.String(),
RemoteAddr: fmt.Sprintf("%s:%d", remote.IP, remote.Port),
RemoteProtocol: remote.Protocol,
RemoteType: remote.CandidateType.String(),
})
break
var cp peers.CandidatePairStats
err := peer.GetCandidatePair(&cp)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
ret.Peers = append(ret.Peers, cp)
}
b, err := json.Marshal(ret)
if err != nil {
Expand Down Expand Up @@ -450,9 +416,3 @@ func writeClipboard(data []byte, mimeType string) error {
}
return cmd.Wait()
}

func (p *CandidatePairValues) Write(w *tabwriter.Writer) {
fp := fmt.Sprintf("%s\uf141", string([]rune(p.FP)[:6]))
fmt.Fprintln(w, strings.Join([]string{fp, p.LocalAddr, p.LocalProtocol,
p.LocalType, "->", p.RemoteAddr, p.RemoteProtocol, p.RemoteType}, "\t"))
}
17 changes: 8 additions & 9 deletions webexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,14 @@ func statusCMD(c *cli.Context) error {
label := color.New().PrintfFunc()
value := color.New(color.FgGreen).PrintfFunc()
header := color.New(color.FgYellow).FprintfFunc()
fp := getFP()
if fp == "" {
fmt.Println("Unitialized, please run `webexec init`")
} else {
label("FP")
fmt.Printf(": ")
value("%s\n", fp)
}
pid, err := getAgentPid()
if err != nil {
return err
Expand All @@ -550,15 +558,6 @@ func statusCMD(c *cli.Context) error {
fmt.Printf(": ")
value("%d\n", pid)
}
// TODO: Get the the fingerprints of connected peers from the agent using the status socket
fp := getFP()
if fp == "" {
fmt.Println("Unitialized, please run `webexec init`")
} else {
label("FP")
fmt.Printf(": ")
value("%s\n", fp)
}
httpc := newSocketClient()
if httpc == nil {
return nil
Expand Down

0 comments on commit 5cd69a4

Please sign in to comment.