Skip to content

Commit

Permalink
Merge 6b8cb93 into a72d199
Browse files Browse the repository at this point in the history
  • Loading branch information
backkem committed Jan 4, 2019
2 parents a72d199 + 6b8cb93 commit cdcdf1e
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 83 deletions.
74 changes: 5 additions & 69 deletions internal/network/manager.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
package network

import (
"crypto"
"crypto/x509"
"fmt"
"strings"
"sync"

"github.com/pions/datachannel"
"github.com/pions/dtls/pkg/dtls"
"github.com/pions/sctp"
"github.com/pions/webrtc/internal/mux"
"github.com/pions/webrtc/internal/srtp"
"github.com/pions/webrtc/pkg/ice"
)

const (
srtpMasterKeyLen = 16
srtpMasterKeySaltLen = 14
receiveMTU = 8192
)

// Manager contains all network state (DTLS, SRTP) that is shared between ports
// It is also used to perform operations that involve multiple ports
type Manager struct {
iceConn *ice.Conn
isOffer bool

SrtpSession *srtp.SessionSRTP
SrtcpSession *srtp.SessionSRTCP

mux *mux.Mux

dtlsEndpoint *mux.Endpoint
srtpEndpoint *mux.Endpoint
srtcpEndpoint *mux.Endpoint

Expand All @@ -51,24 +44,14 @@ func NewManager() *Manager {
}

// Start starts the network manager
func (m *Manager) Start(iceConn *ice.Conn, isOffer bool,
dtlsCert *x509.Certificate, dtlsPrivKey crypto.PrivateKey, fingerprint, fingerprintHash string) error {
// m := &Manager{
// iceConn: iceConn,
// bufferTransportGenerator: btg,
// }

m.iceConn = iceConn
func (m *Manager) Start(mx *mux.Mux, dtlsConn *dtls.Conn, isOffer bool) error {
m.isOffer = isOffer

m.mux = mux.NewMux(m.iceConn, receiveMTU)
m.dtlsEndpoint = m.mux.NewEndpoint(mux.MatchDTLS)
m.mux = mx
m.srtpEndpoint = m.mux.NewEndpoint(mux.MatchSRTP)
m.srtcpEndpoint = m.mux.NewEndpoint(mux.MatchSRTCP)

if err := m.startDTLS(isOffer, dtlsCert, dtlsPrivKey, fingerprint, fingerprintHash); err != nil {
return err
}
m.dtlsConn = dtlsConn

return m.startSRTP(isOffer)
}
Expand Down Expand Up @@ -124,47 +107,6 @@ func (m *Manager) startSRTP(isOffer bool) error {
return err
}

func (m *Manager) startDTLS(isOffer bool, dtlsCert *x509.Certificate, dtlsPrivKey crypto.PrivateKey, fingerprint, fingerprintHash string) error {
dtlsCofig := &dtls.Config{Certificate: dtlsCert, PrivateKey: dtlsPrivKey}
if isOffer {
// Assumes we offer to be passive and this is accepted.
dtlsConn, err := dtls.Server(m.dtlsEndpoint, dtlsCofig)
if err != nil {
return err
}
m.dtlsConn = dtlsConn
} else {
// Assumes the peer offered to be passive and we accepted.
dtlsConn, err := dtls.Client(m.dtlsEndpoint, dtlsCofig)
if err != nil {
return err
}
m.dtlsConn = dtlsConn
}

// Check the fingerprint if a certificate was exchanged
cert := m.dtlsConn.RemoteCertificate()
if cert != nil {
hashAlgo, err := dtls.HashAlgorithmString(fingerprintHash)
if err != nil {
return err
}

fp := ""
fp, err = dtls.Fingerprint(cert, hashAlgo)
if err != nil {
return err
}

if strings.ToUpper(fp) != fingerprint {
return fmt.Errorf("invalid fingerprint: %s <> %s", fp, fingerprint)
}
} else {
fmt.Println("Warning: Certificate not checked")
}
return nil
}

// StartSCTP starts the SCTP association
func (m *Manager) StartSCTP(isOffer bool) error {
if isOffer {
Expand Down Expand Up @@ -210,7 +152,7 @@ func (m *Manager) Close() error {
// continue the chain the Mux has to be closed.

// Close SCTP. This should close the data channels, SCTP, and DTLS
var errSCTP, errMux, errSRTP, errSRTCP error
var errSCTP, errSRTP, errSRTCP error

m.sctpAssociationMutex.RLock()
if m.sctpAssociation != nil {
Expand All @@ -221,17 +163,11 @@ func (m *Manager) Close() error {
errSRTP = m.SrtpSession.Close()
errSRTCP = m.SrtcpSession.Close()

// Close the Mux. This should close the Mux and ICE.
if m.mux != nil {
errMux = m.mux.Close()
}

// TODO: better way to combine/handle errors?
if errSCTP != nil ||
errMux != nil ||
errSRTP != nil ||
errSRTCP != nil {
return fmt.Errorf("Failed to close: %v, %v, %v, %v", errSCTP, errMux, errSRTP, errSRTCP)
return fmt.Errorf("Failed to close: %v, %v, %v", errSCTP, errSRTP, errSRTCP)
}

return nil
Expand Down
2 changes: 0 additions & 2 deletions rtcdatachannel.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"github.com/pkg/errors"
)

const receiveMTU = 8192

// RTCDataChannel represents a WebRTC DataChannel
// The RTCDataChannel interface represents a network channel
// which can be used for bidirectional peer-to-peer transfers of arbitrary data
Expand Down
8 changes: 5 additions & 3 deletions rtcdtlstransport.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/pions/dtls/pkg/dtls"
"github.com/pions/webrtc/internal/mux"
"github.com/pions/webrtc/pkg/rtcerr"
)

Expand Down Expand Up @@ -85,8 +86,8 @@ func (t *RTCDtlsTransport) Start(remoteParameters RTCDtlsParameters) error {
return err
}

// TODO: Mux
dtlsEndpoint := t.iceTransport.conn
mx := t.iceTransport.mux
dtlsEndpoint := mx.NewEndpoint(mux.MatchDTLS)

// TODO: handle multiple certs
cert := t.certificates[0]
Expand Down Expand Up @@ -156,7 +157,8 @@ func (t *RTCDtlsTransport) validateFingerPrint(remoteParameters RTCDtlsParameter

func (t *RTCDtlsTransport) ensureICEConn() error {
if t.iceTransport == nil ||
t.iceTransport.conn == nil {
t.iceTransport.conn == nil ||
t.iceTransport.mux == nil {
return errors.New("ICE connection not started")
}

Expand Down
10 changes: 10 additions & 0 deletions rtcicetransport.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"sync"

"github.com/pions/webrtc/internal/mux"
"github.com/pions/webrtc/pkg/ice"
)

Expand All @@ -22,6 +23,7 @@ type RTCIceTransport struct {

gatherer *RTCIceGatherer
conn *ice.Conn
mux *mux.Mux
}

// func (t *RTCIceTransport) GetLocalCandidates() []RTCIceCandidate {
Expand Down Expand Up @@ -101,9 +103,17 @@ func (t *RTCIceTransport) Start(gatherer *RTCIceGatherer, params RTCIceParameter
return errors.New("Unknown ICE Role")
}

t.mux = mux.NewMux(t.conn, receiveMTU)

return nil
}

// Stop irreversibly stops the RTCIceTransport.
func (t *RTCIceTransport) Stop() error {
// Close the Mux. This closes the Mux and the underlying ICE conn.
return t.mux.Close()
}

// OnConnectionStateChange sets a handler that is fired when the ICE
// connection state changes.
func (t *RTCIceTransport) OnConnectionStateChange(f func(RTCIceTransportState)) {
Expand Down
69 changes: 60 additions & 9 deletions rtcpeerconnection.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ var pcLog = logging.NewScopedLogger("pc")
// comparisons when no value was defined.
const Unknown = iota

const receiveMTU = 8192

// RTCPeerConnection represents a WebRTC connection that establishes a
// peer-to-peer communications with another RTCPeerConnection instance in a
// browser, or to another endpoint implementing the required protocols.
Expand Down Expand Up @@ -113,8 +115,9 @@ type RTCPeerConnection struct {
// Deprecated: Internal mechanism which will be removed.
networkManager *network.Manager

iceGatherer *RTCIceGatherer
iceTransport *RTCIceTransport
iceGatherer *RTCIceGatherer
iceTransport *RTCIceTransport
dtlsTransport *RTCDtlsTransport
}

// New creates a new RTCPeerConfiguration with the provided configuration
Expand Down Expand Up @@ -496,7 +499,7 @@ func (pc *RTCPeerConnection) gather() error {
return pc.iceGatherer.Gather()
}

func (pc *RTCPeerConnection) createIceTransport() *RTCIceTransport {
func (pc *RTCPeerConnection) createICETransport() *RTCIceTransport {
t := NewRTCIceTransport(pc.iceGatherer)

t.OnConnectionStateChange(func(state RTCIceTransportState) {
Expand All @@ -509,6 +512,11 @@ func (pc *RTCPeerConnection) createIceTransport() *RTCIceTransport {
return t
}

func (pc *RTCPeerConnection) createDTLSTransport() (*RTCDtlsTransport, error) {
dtlsTransport, err := NewRTCDtlsTransport(pc.iceTransport, pc.configuration.Certificates)
return dtlsTransport, err
}

// CreateAnswer starts the RTCPeerConnection and generates the localDescription
func (pc *RTCPeerConnection) CreateAnswer(options *RTCAnswerOptions) (RTCSessionDescription, error) {
useIdentity := pc.idpLoginURL != nil
Expand Down Expand Up @@ -750,7 +758,7 @@ func (pc *RTCPeerConnection) SetRemoteDescription(desc RTCSessionDescription) er
}

// Create the ice transport
iceTransport := pc.createIceTransport()
iceTransport := pc.createICETransport()
pc.iceTransport = iceTransport

for _, m := range pc.RemoteDescription().parsed.MediaDescriptions {
Expand All @@ -777,6 +785,13 @@ func (pc *RTCPeerConnection) SetRemoteDescription(desc RTCSessionDescription) er
}
}

// Create the DTLS transport
dtlsTransport, err := pc.createDTLSTransport()
if err != nil {
return err
}
pc.dtlsTransport = dtlsTransport

fingerprint, ok := desc.parsed.Attribute("fingerprint")
if !ok {
fingerprint, ok = desc.parsed.MediaDescriptions[0].Attribute("fingerprint")
Expand Down Expand Up @@ -816,9 +831,17 @@ func (pc *RTCPeerConnection) SetRemoteDescription(desc RTCSessionDescription) er
pcLog.Warnf("Failed to start manager: %s", err)
}

cert := pc.configuration.Certificates[0] // TODO: handle multiple certs
err = pc.networkManager.Start(pc.iceTransport.conn, weOffer,
cert.x509Cert, cert.privateKey, fingerprint, fingerprintHash)
// Start the dtls transport
err = pc.dtlsTransport.Start(RTCDtlsParameters{
Role: RTCDtlsRoleAuto,
Fingerprints: []RTCDtlsFingerprint{{Algorithm: fingerprintHash, Value: fingerprint}},
})
if err != nil {
// TODO: Handle error
pcLog.Warnf("Failed to start manager: %s", err)
}

err = pc.networkManager.Start(pc.iceTransport.mux, pc.dtlsTransport.conn, weOffer)
if err != nil {
// TODO: Handle error
pcLog.Warnf("Failed to start manager: %s", err)
Expand Down Expand Up @@ -1315,13 +1338,41 @@ func (pc *RTCPeerConnection) Close() error {
// https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #12)
pc.ConnectionState = RTCPeerConnectionStateClosed

// Try closing everything and collect the errors
var closeErrs []error

if pc.networkManager != nil {
if err := pc.networkManager.Close(); err != nil {
return err
closeErrs = append(closeErrs, err)
}
}

return nil
if pc.iceTransport != nil {
if err := pc.iceTransport.Stop(); err != nil {
closeErrs = append(closeErrs, err)
}
}

// TODO: Figure out stopping ICE transport & Gatherer independently.
// pc.iceGatherer()

return flattenErrs(closeErrs)
}

func flattenErrs(errs []error) error {
var errstrings []string

for _, err := range errs {
if err != nil {
errstrings = append(errstrings, err.Error())
}
}

if len(errstrings) == 0 {
return nil
}

return fmt.Errorf(strings.Join(errstrings, "\n"))
}

/* Everything below is private */
Expand Down

0 comments on commit cdcdf1e

Please sign in to comment.