snapshot of https://github.com/pion/webrtc.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
REUSE Compliance Check / lint (push) Failing after 0s
Browser E2E / Test (push) Failing after 3s
Test / test (1.24) (push) Failing after 0s
Test / test-i386 (1.25) (push) Failing after 0s
Test / test-i386 (1.24) (push) Failing after 0s
Test / test-windows (1.25) (push) Failing after 0s
Test / test-windows (1.24) (push) Failing after 0s
Test / test (1.25) (push) Failing after 0s
Examples Tests / Test (push) Failing after 3s
Test / test-macos (1.25) (push) Failing after 0s
Test / test-macos (1.24) (push) Failing after 0s
Go mod tidy / tidy (push) Failing after 0s
Test / test-wasm (push) Failing after 0s
CodeQL / analyze (push) Failing after 1s
Fuzz / fuzz (push) Failing after 0s

This commit is contained in:
upstream-mirror
2026-09-15 20:06:07 +05:00
commit 8acb1a3a29
394 changed files with 78746 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
# data-channels-flow-control
This example demonstrates how to use the following property / methods.
* func (d *DataChannel) BufferedAmount() uint64
* func (d *DataChannel) SetBufferedAmountLowThreshold(th uint64)
* func (d *DataChannel) BufferedAmountLowThreshold() uint64
* func (d *DataChannel) OnBufferedAmountLow(f func())
These methods are equivalent to that of JavaScript WebRTC API.
See https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel for more details.
## When do we need it?
Send or SendText methods are called on DataChannel to send data to the connected peer.
The methods return immediately, but it does not mean the data was actually sent onto
the wire. Instead, it is queued in a buffer until it actually gets sent out to the wire.
When you have a large amount of data to send, it is an application's responsibility to
control the buffered amount in order not to indefinitely grow the buffer size to eventually
exhaust the memory.
The rate you wish to send data might be much higher than the rate the data channel can
actually send to the peer over the Internet. The above properties/methods help your
application to pace the amount of data to be pushed into the data channel.
## How to run the example code
The demo code (main.go) implements two endpoints (offerPC and answerPC) in it.
```
signaling messages
+----------------------------------------+
| |
v v
+---------------+ +---------------+
| | data | |
| offerPC |----------------------->| answerPC |
|:PeerConnection| |:PeerConnection|
+---------------+ +---------------+
```
First offerPC and answerPC will exchange signaling message to establish a peer-to-peer
connection, and data channel (label: "data").
Once the data channel is successfully opened, offerPC will start sending a series of
1024-byte packets to answerPC as fast as it can, until you kill the process by Ctrl-c.
Here's how to run the code.
At the root of the example, `pion/webrtc/examples/data-channels-flow-control/`:
```
$ go run main.go
2019/08/31 14:56:41 OnOpen: data-824635025728. Start sending a series of 1024-byte packets as fast as it can
2019/08/31 14:56:41 OnOpen: data-824637171120. Start receiving data
2019/08/31 14:56:42 Throughput: 179.118 Mbps
2019/08/31 14:56:43 Throughput: 203.545 Mbps
2019/08/31 14:56:44 Throughput: 211.516 Mbps
2019/08/31 14:56:45 Throughput: 216.292 Mbps
2019/08/31 14:56:46 Throughput: 217.961 Mbps
2019/08/31 14:56:47 Throughput: 218.342 Mbps
:
```

View File

@@ -0,0 +1,227 @@
// SPDX-FileCopyrightText: 2026 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
// data-channels-flow-control demonstrates how to use the DataChannel congestion control APIs
package main
import (
"encoding/json"
"fmt"
"log"
"os"
"sync/atomic"
"time"
"github.com/pion/webrtc/v4"
)
const (
bufferedAmountLowThreshold uint64 = 512 * 1024 // 512 KB
maxBufferedAmount uint64 = 1024 * 1024 // 1 MB
)
func check(err error) {
if err != nil {
panic(err)
}
}
func setRemoteDescription(pc *webrtc.PeerConnection, sdp []byte) {
var desc webrtc.SessionDescription
err := json.Unmarshal(sdp, &desc)
check(err)
// Apply the desc as the remote description
err = pc.SetRemoteDescription(desc)
check(err)
}
func createOfferer() *webrtc.PeerConnection {
// Prepare the configuration
config := webrtc.Configuration{
ICEServers: []webrtc.ICEServer{},
}
// Create a new PeerConnection
pc, err := webrtc.NewPeerConnection(config)
check(err)
buf := make([]byte, 1024)
ordered := false
maxRetransmits := uint16(0)
options := &webrtc.DataChannelInit{
Ordered: &ordered,
MaxRetransmits: &maxRetransmits,
}
sendMoreCh := make(chan struct{}, 1)
// Create a datachannel with label 'data'
dataChannel, err := pc.CreateDataChannel("data", options)
check(err)
// Register channel opening handling
dataChannel.OnOpen(func() {
log.Printf(
"OnOpen: %s-%d. Start sending a series of 1024-byte packets as fast as it can\n",
dataChannel.Label(), dataChannel.ID(),
)
for {
err2 := dataChannel.Send(buf)
check(err2)
if dataChannel.BufferedAmount() > maxBufferedAmount {
// Wait until the bufferedAmount becomes lower than the threshold
<-sendMoreCh
}
}
})
// Set bufferedAmountLowThreshold so that we can get notified when
// we can send more
dataChannel.SetBufferedAmountLowThreshold(bufferedAmountLowThreshold)
// This callback is made when the current bufferedAmount becomes lower than the threshold
dataChannel.OnBufferedAmountLow(func() {
select {
case sendMoreCh <- struct{}{}:
default:
}
})
return pc
}
func createAnswerer() *webrtc.PeerConnection {
// Prepare the configuration
config := webrtc.Configuration{
ICEServers: []webrtc.ICEServer{},
}
// Create a new PeerConnection
pc, err := webrtc.NewPeerConnection(config)
check(err)
pc.OnDataChannel(func(dataChannel *webrtc.DataChannel) {
var totalBytesReceived uint64
// Register channel opening handling
dataChannel.OnOpen(func() {
log.Printf("OnOpen: %s-%d. Start receiving data", dataChannel.Label(), dataChannel.ID())
since := time.Now()
// Start printing out the observed throughput
ticker := time.NewTicker(1000 * time.Millisecond)
defer ticker.Stop()
for range ticker.C {
bps := float64(atomic.LoadUint64(&totalBytesReceived)*8) / time.Since(since).Seconds()
log.Printf("Throughput: %.03f Mbps", bps/1024/1024)
}
})
// Register the OnMessage to handle incoming messages
dataChannel.OnMessage(func(dcMsg webrtc.DataChannelMessage) {
n := len(dcMsg.Data)
atomic.AddUint64(&totalBytesReceived, uint64(n))
})
})
return pc
}
func main() {
offerPC := createOfferer()
defer func() {
if err := offerPC.Close(); err != nil {
fmt.Printf("cannot close offerPC: %v\n", err)
}
}()
answerPC := createAnswerer()
defer func() {
if err := answerPC.Close(); err != nil {
fmt.Printf("cannot close answerPC: %v\n", err)
}
}()
// Set ICE Candidate handler. As soon as a PeerConnection has gathered a candidate
// send it to the other peer
answerPC.OnICECandidate(func(candidate *webrtc.ICECandidate) {
if candidate != nil {
check(offerPC.AddICECandidate(candidate.ToJSON()))
}
})
// Set ICE Candidate handler. As soon as a PeerConnection has gathered a candidate
// send it to the other peer
offerPC.OnICECandidate(func(candidate *webrtc.ICECandidate) {
if candidate != nil {
check(answerPC.AddICECandidate(candidate.ToJSON()))
}
})
// Set the handler for Peer connection state
// This will notify you when the peer has connected/disconnected
offerPC.OnConnectionStateChange(func(state webrtc.PeerConnectionState) {
fmt.Printf("Peer Connection State has changed: %s (offerer)\n", state.String())
if state == webrtc.PeerConnectionStateFailed {
// Wait until PeerConnection has had no network activity for 30 seconds or another failure.
// It may be reconnected using an ICE Restart.
// Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout.
// Note that the PeerConnection may come back from PeerConnectionStateDisconnected.
fmt.Println("Peer Connection has gone to failed exiting")
os.Exit(0)
}
if state == webrtc.PeerConnectionStateClosed {
// PeerConnection was explicitly closed. This usually happens from a DTLS CloseNotify
fmt.Println("Peer Connection has gone to closed exiting")
os.Exit(0)
}
})
// Set the handler for Peer connection state
// This will notify you when the peer has connected/disconnected
answerPC.OnConnectionStateChange(func(state webrtc.PeerConnectionState) {
fmt.Printf("Peer Connection State has changed: %s (answerer)\n", state.String())
if state == webrtc.PeerConnectionStateFailed {
// Wait until PeerConnection has had no network activity for 30 seconds or another failure.
// It may be reconnected using an ICE Restart.
// Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout.
// Note that the PeerConnection may come back from PeerConnectionStateDisconnected.
fmt.Println("Peer Connection has gone to failed exiting")
os.Exit(0)
}
if state == webrtc.PeerConnectionStateClosed {
// PeerConnection was explicitly closed. This usually happens from a DTLS CloseNotify
fmt.Println("Peer Connection has gone to closed exiting")
os.Exit(0)
}
})
// Now, create an offer
offer, err := offerPC.CreateOffer(nil)
check(err)
check(offerPC.SetLocalDescription(offer))
desc, err := json.Marshal(offer)
check(err)
setRemoteDescription(answerPC, desc)
answer, err := answerPC.CreateAnswer(nil)
check(err)
check(answerPC.SetLocalDescription(answer))
desc2, err := json.Marshal(answer)
check(err)
setRemoteDescription(offerPC, desc2)
// Block forever
select {}
}