-
Notifications
You must be signed in to change notification settings - Fork 3
/
advertisement.go
139 lines (111 loc) · 2.84 KB
/
advertisement.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package api
import (
"errors"
"fmt"
"log"
"strconv"
"strings"
)
const (
DirectionIn = "in"
DirectionOut = "out"
)
// todo: support codec params
type CodecInfo struct {
Codec string
}
func (ci CodecInfo) Match(other CodecInfo) bool {
// Code name match alone
// TODO: revisit this once we have more info on Cap/Adv model
if ci.Codec == other.Codec {
return true
}
return false
}
type Capability struct {
Id uint8
Direction string
Codecs []CodecInfo
}
type AdvertisementInfo struct {
Caps []Capability
}
// Crude parse function. Needs to be revisited once ABNF is defined
func (ad Advertisement) Parse() (AdvertisementInfo, error) {
adLines := strings.Split(string(ad), "\n")
if len(adLines) == 0 {
return AdvertisementInfo{}, errors.New("error parsing advertisement")
}
adInfo := AdvertisementInfo{}
for idx, line := range adLines {
var cap Capability
if len(line) == 0 {
continue
}
parts := strings.Split(line, " ")
if len(parts) < 3 {
// need id, dir and atleast one codec
return adInfo, fmt.Errorf("line [%d] misses minimally required slots", idx)
}
id, err := strconv.Atoi(parts[0])
if err != nil {
return adInfo, err
}
cap.Id = uint8(id)
dir := strings.TrimRight(parts[1], ":")
if dir != DirectionIn && dir != DirectionOut {
return adInfo, fmt.Errorf("line [%d] malformed direction", idx)
}
cap.Direction = dir
// parse codes
var codecs []CodecInfo
for i := 2; i < len(parts); i++ {
codec := strings.TrimRight(parts[i], ";")
codecs = append(codecs, CodecInfo{codec})
}
cap.Codecs = codecs
adInfo.Caps = append(adInfo.Caps, cap)
}
return adInfo, nil
}
//////
// Directive
/////
type Directive string
func (d Directive) Parse() (DirectiveInfo, error) {
dInfo := DirectiveInfo{}
sDirective := string(d)
parts := strings.Split(sDirective, ":")
log.Printf("\tparts [%s]", parts)
if len(parts) < 2 {
// need src to sink, codecinfo
return DirectiveInfo{}, fmt.Errorf("misses minimally required slots")
}
srcDst := strings.Split(parts[0], "to")
src, err := strconv.Atoi(strings.TrimRight(srcDst[0], " "))
if err != nil {
return DirectiveInfo{}, err
}
dst, err := strconv.Atoi(strings.TrimLeft(srcDst[1], " "))
if err != nil {
return DirectiveInfo{}, err
}
dInfo.SourceId = uint8(src)
dInfo.SinkId = uint8(dst)
codec := strings.TrimRight(parts[1], ";")
dInfo.Codec = CodecInfo{codec}
return dInfo, nil
}
type DirectiveInfo struct {
SourceId uint8
SinkId uint8
Codec CodecInfo
}
func (di DirectiveInfo) GenClientDirectives() Directive {
d := strconv.Itoa(int(di.SinkId)) + " to " + strconv.Itoa(int(di.SourceId)) + ":" + di.Codec.Codec + ";"
return Directive(d)
}
func (di DirectiveInfo) GenServerDirectives() Directive {
d := strconv.Itoa(int(di.SourceId)) + " to " + strconv.Itoa(int(di.SinkId)) + ":" + di.Codec.Codec + ";"
return Directive(d)
}