Files
webrtc/examples/ortc-quic/main.go
Sean DuBois dbde6114a2 Update import paths
Add /v2 to import paths everywhere
2019-04-07 02:17:15 -07:00

171 lines
3.4 KiB
Go

// +build quic
package main
import (
"flag"
"fmt"
"time"
"github.com/pion/quic"
"github.com/pion/webrtc/v2"
"github.com/pion/webrtc/v2/examples/internal/signal"
)
const messageSize = 15
func main() {
isOffer := flag.Bool("offer", false, "Act as the offerer if set")
flag.Parse()
// This example shows off the experimental implementation of webrtc-quic.
// Everything below is the pion-WebRTC (ORTC) API! Thanks for using it ❤️.
// Create an API object
api := webrtc.NewAPI()
// Prepare ICE gathering options
iceOptions := webrtc.ICEGatherOptions{
ICEServers: []webrtc.ICEServer{
{URLs: []string{"stun:stun.l.google.com:19302"}},
},
}
// Create the ICE gatherer
gatherer, err := api.NewICEGatherer(iceOptions)
if err != nil {
panic(err)
}
// Construct the ICE transport
ice := api.NewICETransport(gatherer)
// Construct the Quic transport
qt, err := api.NewQUICTransport(ice, nil)
if err != nil {
panic(err)
}
// Handle incoming streams
qt.OnBidirectionalStream(func(stream *quic.BidirectionalStream) {
fmt.Printf("New stream %d\n", stream.StreamID())
// Handle reading from the stream
go ReadLoop(stream)
// Handle writing to the stream
go WriteLoop(stream)
})
// Gather candidates
err = gatherer.Gather()
if err != nil {
panic(err)
}
iceCandidates, err := gatherer.GetLocalCandidates()
if err != nil {
panic(err)
}
iceParams, err := gatherer.GetLocalParameters()
if err != nil {
panic(err)
}
quicParams, err := qt.GetLocalParameters()
if err != nil {
panic(err)
}
s := Signal{
ICECandidates: iceCandidates,
ICEParameters: iceParams,
QuicParameters: quicParams,
}
// Exchange the information
fmt.Println(signal.Encode(s))
remoteSignal := Signal{}
signal.Decode(signal.MustReadStdin(), &remoteSignal)
iceRole := webrtc.ICERoleControlled
if *isOffer {
iceRole = webrtc.ICERoleControlling
}
err = ice.SetRemoteCandidates(remoteSignal.ICECandidates)
if err != nil {
panic(err)
}
// Start the ICE transport
err = ice.Start(nil, remoteSignal.ICEParameters, &iceRole)
if err != nil {
panic(err)
}
// Start the Quic transport
err = qt.Start(remoteSignal.QuicParameters)
if err != nil {
panic(err)
}
// Construct the stream as the offerer
if *isOffer {
var stream *quic.BidirectionalStream
stream, err = qt.CreateBidirectionalStream()
if err != nil {
panic(err)
}
// Handle reading from the stream
go ReadLoop(stream)
// Handle writing to the stream
go WriteLoop(stream)
}
select {}
}
// Signal is used to exchange signaling info.
// This is not part of the ORTC spec. You are free
// to exchange this information any way you want.
type Signal struct {
ICECandidates []webrtc.ICECandidate `json:"iceCandidates"`
ICEParameters webrtc.ICEParameters `json:"iceParameters"`
QuicParameters webrtc.QUICParameters `json:"quicParameters"`
}
// ReadLoop reads from the stream
func ReadLoop(s *quic.BidirectionalStream) {
for {
buffer := make([]byte, messageSize)
params, err := s.ReadInto(buffer)
if err != nil {
panic(err)
}
fmt.Printf("Message from stream '%d': %s\n", s.StreamID(), string(buffer[:params.Amount]))
}
}
// WriteLoop writes to the stream
func WriteLoop(s *quic.BidirectionalStream) {
for range time.NewTicker(5 * time.Second).C {
message := signal.RandSeq(messageSize)
fmt.Printf("Sending %s \n", message)
data := quic.StreamWriteParameters{
Data: []byte(message),
}
err := s.Write(data)
if err != nil {
panic(err)
}
}
}