Skip to content
This repository has been archived by the owner on Jul 12, 2023. It is now read-only.

Commit

Permalink
WebRTConn Raw Socket Support
Browse files Browse the repository at this point in the history
- Use `DataChannelConfig` to specify a raw socket to be used for the Peer Connection.
  • Loading branch information
gaukas committed Sep 22, 2021
1 parent ef6383a commit 32d58fd
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 2 deletions.
2 changes: 1 addition & 1 deletion WebRTConnProcedural.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (c *WebRTConn) Init(dcconfig *DataChannelConfig, pionSettingEngine webrtc.S

// defer c.lock.Unlock()
// c.lock.Lock()
err := c.dataChannel.Initialize()
err := c.dataChannel.Initialize() // After this line, no change made to pionSettingEngine or pionConfiguration will be effective.
if err != nil {
return err
}
Expand Down
12 changes: 12 additions & 0 deletions datachannel.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ func DeclareDatachannel(dcconfig *DataChannelConfig, pionSettingEngine webrtc.Se
// WebRTCPeerConnection: nil,
// WebRTCDataChannel: nil,
}

if dcconfig.SelfSDPType == "answer" {
if dcconfig.AnswererType == "active" {
dataChannel.SetDTLSActive()
} else if dcconfig.AnswererType == "passive" {
dataChannel.SetDTLSPassive()
}
}

if dcconfig.RawSocket != nil {
dataChannel.UseRawSocket(dcconfig.RawSocket)
}
return &dataChannel
}

Expand Down
10 changes: 9 additions & 1 deletion datachannelconfig.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package transportc

import "github.com/pion/webrtc/v3"
import (
"net"

"github.com/pion/webrtc/v3"
)

const (
DataChannelBufferSizeDefault uint64 = 1024 * 1024 // Default Buffer Size: 1MB
Expand All @@ -17,6 +21,10 @@ type DataChannelConfig struct {
IPAddr []string
CandidateType webrtc.ICECandidateType
Port uint16
AnswererType string // "active", "passive". Only valid when SelfSDPType == "answer"

// Enhanced Features Under Test, just wrapper
RawSocket *net.UDPConn
}

func (dcc DataChannelConfig) PeerSDPType() string {
Expand Down
32 changes: 32 additions & 0 deletions examples/ping-pong-rawsocket/internal/strtool/strtool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package strtool

import (
"bufio"
"fmt"
"io"
"os"
"strings"
)

func MustReadStdin() string {
r := bufio.NewReader(os.Stdin)

var in string
for {
var err error
in, err = r.ReadString('\n')
if err != io.EOF {
if err != nil {
panic(err)
}
}
in = strings.TrimSpace(in)
if len(in) > 0 {
break
}
}

fmt.Println("")

return in
}
98 changes: 98 additions & 0 deletions examples/ping-pong-rawsocket/ping/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package main

import (
"fmt"
"log"
"os"
"strconv"

"github.com/Gaukas/transportc"
"github.com/Gaukas/transportc/examples/ping-pong-rawsocket/internal/strtool"
"github.com/pion/webrtc/v3"
)

// ping, a client actively establish the server and

func main() {
logger := log.Logger{}
logger.SetPrefix("[Logger] ")
logger.SetOutput(os.Stdout)

logger.Println("Dialing to get a WebRTConn struct...")
conn, _ := transportc.Dial("udp", "0.0.0.0")

newDCConfig := transportc.DataChannelConfig{
Label: "Ping-DataChannel",
SelfSDPType: "offer",
SendBufferSize: transportc.DataChannelBufferSizeDefault,
}
newSettingEngine := webrtc.SettingEngine{}
newConfiguration := webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{
URLs: []string{"stun:stun.l.google.com:19302"},
},
},
}

logger.Println("Initializing WebRTConn instance...")
err := conn.Init(&newDCConfig, newSettingEngine, newConfiguration)
if err != nil {
logger.Panic(err) // Init must not fail. There's no recoverability in a WebRTConn failed to call Init()
}

// Offerer: Show local SDP
logger.Println("Acquiring local SDP (offer)...")
localSdp, err := conn.LocalSDPJsonString()
if err != nil {
logger.Panic(err) // If no valid local SDP, you can't establish WebRTC peer connection, and therefore, no datachannel.
}
logger.Printf("Offer generated as below:\n%s\n", localSdp)

// Offerer: Wait for remote SDP
logger.Println("Ready for Answer...")
remoteSdp := strtool.MustReadStdin()

conn.SetRemoteSDPJsonString(remoteSdp)

// Block until conn is good to go
if (conn.Status() & transportc.WebRTConnReady) == 0 {
logger.Println("Waiting for peer...")
for (conn.Status() & transportc.WebRTConnReady) == 0 {
}
}
logger.Println("DataChannel established.")

lastidx := 0
for lastidx < 100 {
b := []byte(fmt.Sprintf("%d", lastidx))
conn.Write(b)
// logger.Printf("Ping: %s of size %d\n", string(b), len(b))
recv := make([]byte, 10)

// Block until receive
for {
n, _ := conn.Read(recv)
if n > 0 {
clean := []byte{}
for _, b := range recv {
if b != 0 {
clean = append(clean, b)
}
}
recv = clean
break
}
}
logger.Printf("Ping: %s of size %d, Pong: %s of size %d\n", string(b), len(b), string(recv), len(recv))
idx64, err := strconv.ParseInt(fmt.Sprintf("%s", string(recv)), 10, 64)
if err != nil {
panic(err)
}
// logger.Printf("Pong cast to: %d\n", idx64)
lastidx = int(idx64) + 1
}
logger.Println("Closing WebRTConn...")
conn.Write([]byte("BYE"))
conn.Close()
}
98 changes: 98 additions & 0 deletions examples/ping-pong-rawsocket/pong/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package main

import (
"log"
"net"
"os"

"github.com/Gaukas/transportc"
"github.com/Gaukas/transportc/examples/ping-pong-rawsocket/internal/strtool"
"github.com/pion/webrtc/v3"
)

// ping, a client actively establish the server and

func main() {
logger := log.Logger{}
logger.SetPrefix("[Logger] ")
logger.SetOutput(os.Stdout)

logger.Println("Dialing to get a WebRTConn struct...")
conn, _ := transportc.Dial("udp", "0.0.0.0")

udpListener, err := net.ListenUDP("udp", &net.UDPAddr{
IP: net.IP{0, 0, 0, 0},
Port: 8563,
})

newDCConfig := transportc.DataChannelConfig{
Label: "Ping-DataChannel",
SelfSDPType: "answer",
SendBufferSize: transportc.DataChannelBufferSizeDefault,
RawSocket: udpListener,
}

newSettingEngine := webrtc.SettingEngine{}
newConfiguration := webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{
URLs: []string{"stun:stun.l.google.com:19302"},
},
},
}

logger.Println("Initializing WebRTConn instance...")
err = conn.Init(&newDCConfig, newSettingEngine, newConfiguration)
if err != nil {
logger.Panic(err) // Init must not fail. There's no recoverability in a WebRTConn failed to call Init()
}

// Answerer: Wait for remote SDP
logger.Println("Ready for Offer...")
remoteSdp := strtool.MustReadStdin()
conn.SetRemoteSDPJsonString(remoteSdp)

// Offerer: Show local SDP
logger.Println("Acquiring local SDP (answer)...")
localSdp, err := conn.LocalSDPJsonString()
if err != nil {
logger.Panic(err) // If no valid local SDP, you can't establish WebRTC peer connection, and therefore, no datachannel.
}
logger.Printf("Answer generated as below:\n%s\n", localSdp)

// Block until conn is good to go
if (conn.Status() & transportc.WebRTConnReady) == 0 {
logger.Println("Waiting for peer...")
for (conn.Status() & transportc.WebRTConnReady) == 0 {
}
}
logger.Println("DataChannel established.")
for {
recv := make([]byte, 10)
// Block until receive
for {
n, _ := conn.Read(recv)
if n > 0 {
// Copy recv into a "clean" array includes no \x00
clean := []byte{}
for _, b := range recv {
if b != 0 {
clean = append(clean, b)
}
}
recv = clean
// logger.Printf("Ping: %s of size %d", string(recv), len(recv))
break
}
}

if string(recv) == "BYE" {
logger.Println("Ping: BYE")
break
} else {
// logger.Printf("Pong: %s of size %d", string(recv), len(recv))
conn.Write(recv)
}
}
conn.Close()
}

0 comments on commit 32d58fd

Please sign in to comment.