Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 5095792

Browse files
committed
perf: Reduce RTC connection times
1 parent 08ef03e commit 5095792

File tree

3 files changed

+49
-9
lines changed

3 files changed

+49
-9
lines changed

wsnet/dial.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,16 @@ func (d *Dialer) negotiate() (err error) {
113113

114114
go func() {
115115
defer close(errCh)
116-
err := waitForDataChannelOpen(context.Background(), d.ctrl)
116+
err := waitForConnectionOpen(context.Background(), d.rtc)
117117
if err != nil {
118118
_ = d.conn.Close()
119119
errCh <- err
120120
return
121121
}
122-
d.ctrlrw, err = d.ctrl.Detach()
123-
if err != nil {
124-
errCh <- err
125-
}
126-
_ = d.conn.Close()
122+
go func() {
123+
// Closing this connection took 30ms+.
124+
_ = d.conn.Close()
125+
}()
127126
}()
128127

129128
for {
@@ -179,7 +178,20 @@ func (d *Dialer) Close() error {
179178

180179
// Ping sends a ping through the control channel.
181180
func (d *Dialer) Ping(ctx context.Context) error {
182-
_, err := d.ctrlrw.Write([]byte{'a'})
181+
// Since we control the client and server we could open this
182+
// data channel with `Negotiated` true to reduce traffic being
183+
// sent when the RTC connection is opened.
184+
err := waitForDataChannelOpen(context.Background(), d.ctrl)
185+
if err != nil {
186+
return err
187+
}
188+
if d.ctrlrw == nil {
189+
d.ctrlrw, err = d.ctrl.Detach()
190+
if err != nil {
191+
return err
192+
}
193+
}
194+
_, err = d.ctrlrw.Write([]byte{'a'})
183195
if err != nil {
184196
return fmt.Errorf("write: %w", err)
185197
}

wsnet/listen.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func (l *listener) dial(ctx context.Context) (<-chan error, error) {
9898
// Negotiates the handshake protocol over the connection provided.
9999
// This functions control-flow is important to readability,
100100
// so the cognitive overload linter has been disabled.
101-
// nolint:gocognit
101+
// nolint:gocognit,nestif
102102
func (l *listener) negotiate(conn net.Conn) {
103103
var (
104104
err error
@@ -167,11 +167,17 @@ func (l *listener) negotiate(conn net.Conn) {
167167
closeError(err)
168168
return
169169
}
170+
rtc.OnConnectionStateChange(func(pcs webrtc.PeerConnectionState) {
171+
if pcs == webrtc.PeerConnectionStateConnecting {
172+
return
173+
}
174+
_ = conn.Close()
175+
})
176+
flushCandidates := proxyICECandidates(rtc, conn)
170177
l.connClosersMut.Lock()
171178
l.connClosers = append(l.connClosers, rtc)
172179
l.connClosersMut.Unlock()
173180
rtc.OnDataChannel(l.handle)
174-
flushCandidates := proxyICECandidates(rtc, conn)
175181
err = rtc.SetRemoteDescription(*msg.Offer)
176182
if err != nil {
177183
closeError(fmt.Errorf("apply offer: %w", err))

wsnet/rtc.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ func dialICEURL(server webrtc.ICEServer, rawURL string, options *DialICEOptions)
155155
// Generalizes creating a new peer connection with consistent options.
156156
func newPeerConnection(servers []webrtc.ICEServer) (*webrtc.PeerConnection, error) {
157157
se := webrtc.SettingEngine{}
158+
se.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeUDP4})
159+
se.SetSrflxAcceptanceMinWait(0)
158160
se.DetachDataChannels()
159161
se.SetICETimeouts(time.Second*5, time.Second*5, time.Second*2)
160162

@@ -165,6 +167,7 @@ func newPeerConnection(servers []webrtc.ICEServer) (*webrtc.PeerConnection, erro
165167
if server.Credential != nil && len(server.URLs) == 1 {
166168
url, err := ice.ParseURL(server.URLs[0])
167169
if err == nil && url.Proto == ice.ProtoTypeTCP {
170+
se.SetNetworkTypes([]webrtc.NetworkType{webrtc.NetworkTypeTCP4, webrtc.NetworkTypeTCP6})
168171
se.SetRelayAcceptanceMinWait(0)
169172
}
170173
}
@@ -213,6 +216,25 @@ func proxyICECandidates(conn *webrtc.PeerConnection, w io.Writer) func() {
213216
}
214217
}
215218

219+
// Waits for a PeerConnection to hit the open state.
220+
func waitForConnectionOpen(ctx context.Context, conn *webrtc.PeerConnection) error {
221+
if conn.ConnectionState() == webrtc.PeerConnectionStateConnected {
222+
return nil
223+
}
224+
ctx, cancelFunc := context.WithTimeout(ctx, time.Second*15)
225+
defer cancelFunc()
226+
conn.OnConnectionStateChange(func(pcs webrtc.PeerConnectionState) {
227+
if pcs == webrtc.PeerConnectionStateConnected {
228+
cancelFunc()
229+
}
230+
})
231+
<-ctx.Done()
232+
if ctx.Err() == context.DeadlineExceeded {
233+
return ctx.Err()
234+
}
235+
return nil
236+
}
237+
216238
// Waits for a DataChannel to hit the open state.
217239
func waitForDataChannelOpen(ctx context.Context, channel *webrtc.DataChannel) error {
218240
if channel.ReadyState() == webrtc.DataChannelStateOpen {

0 commit comments

Comments
 (0)