| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
- // SPDX-License-Identifier: MIT
- // Package main implements a simple example demonstrating a Pion-to-Pion ICE connection
- package main
- import (
- "bufio"
- "context"
- "flag"
- "fmt"
- "net/http"
- "net/url"
- "os"
- "time"
- "github.com/pion/ice/v2"
- "github.com/pion/randutil"
- )
- //nolint:gochecknoglobals
- var (
- isControlling bool
- iceAgent *ice.Agent
- remoteAuthChannel chan string
- localHTTPPort, remoteHTTPPort int
- )
- // HTTP Listener to get ICE Credentials from remote Peer
- func remoteAuth(_ http.ResponseWriter, r *http.Request) {
- if err := r.ParseForm(); err != nil {
- panic(err)
- }
- remoteAuthChannel <- r.PostForm["ufrag"][0]
- remoteAuthChannel <- r.PostForm["pwd"][0]
- }
- // HTTP Listener to get ICE Candidate from remote Peer
- func remoteCandidate(_ http.ResponseWriter, r *http.Request) {
- if err := r.ParseForm(); err != nil {
- panic(err)
- }
- c, err := ice.UnmarshalCandidate(r.PostForm["candidate"][0])
- if err != nil {
- panic(err)
- }
- if err := iceAgent.AddRemoteCandidate(c); err != nil { //nolint:contextcheck
- panic(err)
- }
- }
- func main() { //nolint
- var (
- err error
- conn *ice.Conn
- )
- remoteAuthChannel = make(chan string, 3)
- flag.BoolVar(&isControlling, "controlling", false, "is ICE Agent controlling")
- flag.Parse()
- if isControlling {
- localHTTPPort = 9000
- remoteHTTPPort = 9001
- } else {
- localHTTPPort = 9001
- remoteHTTPPort = 9000
- }
- http.HandleFunc("/remoteAuth", remoteAuth)
- http.HandleFunc("/remoteCandidate", remoteCandidate)
- go func() {
- if err = http.ListenAndServe(fmt.Sprintf(":%d", localHTTPPort), nil); err != nil { //nolint:gosec
- panic(err)
- }
- }()
- if isControlling {
- fmt.Println("Local Agent is controlling")
- } else {
- fmt.Println("Local Agent is controlled")
- }
- fmt.Print("Press 'Enter' when both processes have started")
- if _, err = bufio.NewReader(os.Stdin).ReadBytes('\n'); err != nil {
- panic(err)
- }
- iceAgent, err = ice.NewAgent(&ice.AgentConfig{
- NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4},
- })
- if err != nil {
- panic(err)
- }
- // When we have gathered a new ICE Candidate send it to the remote peer
- if err = iceAgent.OnCandidate(func(c ice.Candidate) {
- if c == nil {
- return
- }
- _, err = http.PostForm(fmt.Sprintf("http://localhost:%d/remoteCandidate", remoteHTTPPort), //nolint
- url.Values{
- "candidate": {c.Marshal()},
- })
- if err != nil {
- panic(err)
- }
- }); err != nil {
- panic(err)
- }
- // When ICE Connection state has change print to stdout
- if err = iceAgent.OnConnectionStateChange(func(c ice.ConnectionState) {
- fmt.Printf("ICE Connection State has changed: %s\n", c.String())
- }); err != nil {
- panic(err)
- }
- // Get the local auth details and send to remote peer
- localUfrag, localPwd, err := iceAgent.GetLocalUserCredentials()
- if err != nil {
- panic(err)
- }
- _, err = http.PostForm(fmt.Sprintf("http://localhost:%d/remoteAuth", remoteHTTPPort), //nolint
- url.Values{
- "ufrag": {localUfrag},
- "pwd": {localPwd},
- })
- if err != nil {
- panic(err)
- }
- remoteUfrag := <-remoteAuthChannel
- remotePwd := <-remoteAuthChannel
- if err = iceAgent.GatherCandidates(); err != nil {
- panic(err)
- }
- // Start the ICE Agent. One side must be controlled, and the other must be controlling
- if isControlling {
- conn, err = iceAgent.Dial(context.TODO(), remoteUfrag, remotePwd)
- } else {
- conn, err = iceAgent.Accept(context.TODO(), remoteUfrag, remotePwd)
- }
- if err != nil {
- panic(err)
- }
- // Send messages in a loop to the remote peer
- go func() {
- for {
- time.Sleep(time.Second * 3)
- val, err := randutil.GenerateCryptoRandomString(15, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
- if err != nil {
- panic(err)
- }
- if _, err = conn.Write([]byte(val)); err != nil {
- panic(err)
- }
- fmt.Printf("Sent: '%s'\n", val)
- }
- }()
- // Receive messages in a loop from the remote peer
- buf := make([]byte, 1500)
- for {
- n, err := conn.Read(buf)
- if err != nil {
- panic(err)
- }
- fmt.Printf("Received: '%s'\n", string(buf[:n]))
- }
- }
|