webrtc

package module
v0.0.0-...-cfb0c9c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 19, 2017 License: BSD-3-Clause Imports: 11 Imported by: 0

README

go-webrtc

Build Status

WebRTC for Golang.

Current Status:

This repository is currently fluctuating a lot, and the exposed interfaces will change. Do not rely on anything in here yet!

  • A PeerConnection can be successfully established between two separate machines using this Go library.
  • It is possible to exchange bytes over a real DTLS/SCTP datachannel. (See the chat demo)
  • Video/Audio support from the Media API is not implemented as it's low priority for us -- but pull requests will be gladly taken!

There is still lots of work to do!

Usage

To immediately see some action, try the chat demo from two machines (or one...)

  • git clone https://github.com/keroserene/go-webrtc
  • cd go-webrtc
  • go run demo/chat/chat.go

Type "start" in one of the Peers, and copy the session descriptions. (This is the "copy-paste" signalling channel). If ICE negotiation succeeds, a really janky chat session should begin.

To write Go code which requires WebRTC functionality:

import "github.com/keroserene/go-webrtc/"

And then you can do things like webrtc.NewPeerConnection(...).

If you've never used WebRTC before, there is already plenty of information online along with javascript examples, but for the Go code here, take a look within demo/* for real usage examples which show how to prepare a PeerConnection and set up the necessary callbacks and signaling.

Also, here are the GoDocs.

Dependencies:
  • GCC 5+
  • TODO:
Package naming

The package name is webrtc, even though the repo name is go-webrtc. (This may be slightly contrary to Go convention, unless we consider the suffix to really begin at the last dash. Reasons:

  • Dashes aren't allowed in package names
  • Including the word "go" in a Go package name seems redundant
  • Just calling this repo webrtc wouldn't make sense either.
  • Also you can rename imported packages to whatever you like.

(e.g. import "foo" "github.com/keroserene/go-webrtc")

Building

Latest tested native webrtc archive: f33698296719f956497d2dbff81b5080864a8804

There are currently two ways to build gowebrtc: the easy way, and the hard way.

The hard way is to build from scratch, which involves Google's depot_tools and chromium stuff, gclient syncing, which takes a couple hours, and possibly many more if you run into problems... along with writing a custom ninja file and concatenating archives correctly and such.

See webrtc.org native-code dev.

The easy way is to use the pre-built archive I've provided in lib/.

Once the archive is ready, cgo takes care of everything, and building is as easy as go build or go install.

TODO(keroserene): More information / provide a real build script to automate the hard way so it becomes the easy way. (See Issue #23)

Documentation

Overview

Package webrtc/data contains the go wrapper for the Peer-to-Peer Data API portion of WebRTC spec.

See: https://w3c.github.io/webrtc-pc/#idl-def-RTCDataChannel

Package webrtc is a golang wrapper on native code WebRTC.

For consistency with the browser-based WebRTCs, the interface here is based loosely on: w3c.github.io/webrtc-pc

The main goal of this project is to present a golang WebRTC package in the most idiomatic and simple-to-use way.

However, to provide a better experience for users of this package, there are differences inherent in the interface written here and the original native code WebRTC - from the golang requirement of Capitalized identifiers for public interfaces, to the replacement of certain callbacks with goroutines.

Note that building the necessary libwebrtc static library is excessively complicated, which is why the necessary platform-specific archives will be provided in lib/. This also mitigates the possibility that future commits on native libwebrtc will break go-webrtc, because the interface with the native code, through the intermediate CGO layer, is relatively fragile.

Due to other external goals of the developers, this package will only be focused on DataChannels. However, extending this package to allow video/audio media streams and related functionality, to be a "complete" WebRTC suite, is entirely possible and will likely happen in the long term. (Issue #7) This will however have implications for the archives that need to be built and linked.

Please share any improvements or concerns as issues or pull requests on github.

Index

Constants

This section is empty.

Variables

View Source
var (
	INFO  *log.Logger
	WARN  *log.Logger
	ERROR *log.Logger
	TRACE *log.Logger
)
View Source
var BundlePolicyString = []string{"Balanced", "MaxBundle", "MaxCompat"}
View Source
var DCMap = NewCGOMap()
View Source
var DataStateString = []string{"Connecting", "Open", "Closing", "Closed"}
View Source
var IceCandidateTypeString = []string{"host", "srflx", "prflx", "relay"}
View Source
var IceConnectionStateString = []string{
	"New", "Checking", "Connected", "Completed",
	"Failed", "Disconnected", "Closed"}
View Source
var IceGatheringStateString = []string{
	"New", "Gathering", "Complete"}
View Source
var IceProtocolString = []string{"udp", "tcp"}
View Source
var IceTcpCandidateTypeString = []string{"active", "passive", "so"}
View Source
var IceTransportPolicyString = []string{"None", "Relay", "NoHost", "All"}
View Source
var PCMap = NewCGOMap()
View Source
var PeerConnectionStateString = []string{
	"New", "Connecting", "Connected", "Disconnected", "Failed"}
View Source
var SdpTypes = []string{"offer", "pranswer", "answer", "rollback"}

TODO: Turn into Enum.

View Source
var SignalingStateString = []string{"Stable",
	"HaveLocalOffer", "HaveLocalPrAnswer",
	"HaveRemoteOffer", "HaveRemotePrAnswer",
	"Closed"}

Functions

func CgoSdpToGoString

func CgoSdpToGoString(sdp C.CGO_sdp) string

func EnumToStringSafe

func EnumToStringSafe(value int, valueStrings []string) string

Return a string value for an integer enum from a mapping array or the integer string if the integer it outside the expected range.

func SetLoggingVerbosity

func SetLoggingVerbosity(level int)

Logging verbosity level, from 0 (nothing) upwards.

Types

type BundlePolicy

type BundlePolicy int
const (
	BundlePolicyBalanced BundlePolicy = iota
	BundlePolicyMaxBundle
	BundlePolicyMaxCompat
)

These "Enum" consts must match order in: peerconnectioninterface.h There doesn't seem to be a way to have a named container for enums in go, and the idiomatic way seems to be just prefixes.

func (BundlePolicy) String

func (p BundlePolicy) String() string

type CGOMap

type CGOMap struct {
	// contains filtered or unexported fields
}

func NewCGOMap

func NewCGOMap() CGOMap

func (*CGOMap) Delete

func (m *CGOMap) Delete(index int)

func (*CGOMap) Get

func (m *CGOMap) Get(index int) interface{}

func (*CGOMap) Set

func (m *CGOMap) Set(p interface{}) int

type Configuration

type Configuration struct {
	IceServers []IceServer
	IceTransportPolicy
	BundlePolicy
	// [ED] RtcpMuxPolicy        RtcpMuxPolicy
	PeerIdentity string // Target peer identity

}

func NewConfiguration

func NewConfiguration(options ...ConfigurationOption) *Configuration

Create a new Configuration with default values according to spec. Accepts any number of |IceServer|s. Returns nil if there's an error.

func (*Configuration) AddIceServer

func (config *Configuration) AddIceServer(params ...string) error

type ConfigurationOption

type ConfigurationOption func(c *Configuration) error

Used in Configuration's variadic functional constructor

func OptionBundlePolicy

func OptionBundlePolicy(policy BundlePolicy) ConfigurationOption

func OptionIceServer

func OptionIceServer(params ...string) ConfigurationOption

func OptionIceTransportPolicy

func OptionIceTransportPolicy(policy IceTransportPolicy) ConfigurationOption

type DataChannel

type DataChannel struct {
	BufferedAmountLowThreshold int
	BinaryType                 string

	// Event Handlers
	OnOpen              func()
	OnClose             func()
	OnMessage           func([]byte) // byte slice.
	OnBufferedAmountLow func()
	// contains filtered or unexported fields
}
DataChannel

OnError - is not implemented because the underlying Send always returns true as specified for SCTP, there is no reasonable exposure of other specific errors from the native code, and OnClose already covers the bases.

func NewDataChannel

func NewDataChannel(o unsafe.Pointer) *DataChannel

Create a Go Channel struct, and prepare internal CGO references / observers. The most reasonable place for this to be created is from PeerConnection, which is not available in the subpackage.

func (*DataChannel) BufferedAmount

func (c *DataChannel) BufferedAmount() int

func (*DataChannel) Close

func (c *DataChannel) Close() error

func (*DataChannel) ID

func (c *DataChannel) ID() int

func (*DataChannel) Label

func (c *DataChannel) Label() string

func (*DataChannel) MaxPacketLifeTime

func (c *DataChannel) MaxPacketLifeTime() uint

func (*DataChannel) MaxRetransmits

func (c *DataChannel) MaxRetransmits() uint

func (*DataChannel) Negotiated

func (c *DataChannel) Negotiated() bool

func (*DataChannel) Ordered

func (c *DataChannel) Ordered() bool

func (*DataChannel) Protocol

func (c *DataChannel) Protocol() string

func (*DataChannel) ReadyState

func (c *DataChannel) ReadyState() DataState

func (*DataChannel) Send

func (c *DataChannel) Send(data []byte)

type DataState

type DataState int
const (
	DataStateConnecting DataState = iota
	DataStateOpen
	DataStateClosing
	DataStateClosed
)

func (DataState) String

func (s DataState) String() string

type IceCandidate

type IceCandidate struct {
	Candidate     string `json:"candidate"`
	SdpMid        string `json:"sdpMid"`
	SdpMLineIndex int    `json:"sdpMLineIndex"`
}

func DeserializeIceCandidate

func DeserializeIceCandidate(msg string) *IceCandidate

Deserialize a received json string into an IceCandidate, if possible.

func (*IceCandidate) Serialize

func (candidate *IceCandidate) Serialize() string

Serialize an IceCandidate into a JSON string.

type IceCandidateType

type IceCandidateType int
const (
	IceCandidateTypeHost IceCandidateType = iota
	IceCandidateTypeSrflx
	IceCandidateTypePrflx
	IceCandidateTypeRelay
)

func (IceCandidateType) String

func (t IceCandidateType) String() string

type IceConnectionState

type IceConnectionState int
const (
	IceConnectionStateNew IceConnectionState = iota
	IceConnectionStateChecking
	IceConnectionStateConnected
	IceConnectionStateCompleted
	IceConnectionStateFailed
	IceConnectionStateDisconnected
	IceConnectionStateClosed
)

func (IceConnectionState) String

func (s IceConnectionState) String() string

type IceCredentialType

type IceCredentialType int

type IceGatheringState

type IceGatheringState int
const (
	IceGatheringStateNew IceGatheringState = iota
	IceGatheringStateGathering
	IceGatheringStateComplete
)

func (IceGatheringState) String

func (s IceGatheringState) String() string

type IceProtocol

type IceProtocol int
const (
	IceProtocolUPD IceProtocol = iota
	IceProtocolTCP
)

func (IceProtocol) String

func (p IceProtocol) String() string

type IceServer

type IceServer struct {
	Urls       []string // The only "required" element.
	Username   string
	Credential string
}

func NewIceServer

func NewIceServer(params ...string) (*IceServer, error)

Create a new IceServer object. Expects anywhere from one to three strings, in this order: - comma-separated list of urls. - username - credential TODO: For the ED version, may need to support CredentialType.

type IceTcpCandidateType

type IceTcpCandidateType int
const (
	IceTcpCandidateTypeActive IceTcpCandidateType = iota
	IceTcpCandidateTypePassive
	IceTcpCandidateTypeSo
)

func (IceTcpCandidateType) String

func (t IceTcpCandidateType) String() string

type IceTransportPolicy

type IceTransportPolicy int
const (
	IceTransportPolicyNone IceTransportPolicy = iota
	IceTransportPolicyRelay

	IceTransportPolicyAll
)

func (IceTransportPolicy) String

func (p IceTransportPolicy) String() string

type Init

type Init struct {
	Ordered           bool
	MaxPacketLifeTime uint
	MaxRetransmits    uint
	Protocol          string
	Negotiated        bool
	ID                uint
}

TODO: Variadic options constructor, probably makes more sense for CreateDataChannel in parent package PeerConnection.

type PeerConnection

type PeerConnection struct {

	// Event handlers
	OnNegotiationNeeded        func()
	OnIceCandidate             func(IceCandidate)
	OnIceCandidateError        func()
	OnIceComplete              func() // Possibly to be removed.
	OnSignalingStateChange     func(SignalingState)
	OnIceConnectionStateChange func(IceConnectionState)
	OnIceGatheringStateChange  func(IceGatheringState)
	OnConnectionStateChange    func(PeerConnectionState)
	OnDataChannel              func(*DataChannel)
	// contains filtered or unexported fields
}
WebRTC PeerConnection

This is the main container of WebRTC functionality - from handling the ICE negotiation to setting up Data Channels.

See: https://w3c.github.io/webrtc-pc/#idl-def-RTCPeerConnection

func NewPeerConnection

func NewPeerConnection(config *Configuration) (*PeerConnection, error)
Construct a WebRTC PeerConnection.

For a successful connection, provide at least one ICE server (stun or turn) in the |Configuration| struct.

func (*PeerConnection) AddIceCandidate

func (pc *PeerConnection) AddIceCandidate(ic IceCandidate) error

func (*PeerConnection) Close

func (pc *PeerConnection) Close() error

func (*PeerConnection) ConnectionState

func (pc *PeerConnection) ConnectionState() PeerConnectionState

readonly connectionState

func (*PeerConnection) CreateAnswer

func (pc *PeerConnection) CreateAnswer() (*SessionDescription, error)

CreateAnswer prepares an SDP "answer" message. This should only happen in response to an offer received and set as the remote description. Once generated, this answer should then be set as the local description and sent back over the signaling channel to the remote peer.

This method is blocking, and should occur within a separate goroutine.

func (*PeerConnection) CreateDataChannel

func (pc *PeerConnection) CreateDataChannel(label string, dict Init) (
	*DataChannel, error)

Create and return a DataChannel.

This only needs to be called by one side, unless "negotiated" is true.

If creating the first DataChannel, this actually triggers the local PeerConnection's .OnNegotiationNeeded callback, which should lead to a user-provided goroutine containing CreateOffer, SetLocalDescription, and the rest of the signalling exchange.

Once the connection succeeds, .OnDataChannel should trigger on the remote peer's |PeerConnection|, while .OnOpen should trigger on the local DataChannel returned by this method. Both DataChannel references should then be open and ready to exchange data.

TODO: Implement the "negotiated" flag?

func (*PeerConnection) CreateOffer

func (pc *PeerConnection) CreateOffer() (*SessionDescription, error)

CreateOffer prepares an SDP "offer" message, which should be set as the local description, then sent to the remote peer over a signalling channel. This should only be called by the peer initiating the connection.

This method is blocking, and should occur within a separate goroutine.

func (*PeerConnection) GetConfiguration

func (pc *PeerConnection) GetConfiguration() Configuration

func (*PeerConnection) IceConnectionState

func (pc *PeerConnection) IceConnectionState() IceConnectionState

readonly iceconnectionState

func (*PeerConnection) IceGatheringState

func (pc *PeerConnection) IceGatheringState() IceGatheringState

readonly icegatheringstatee

func (*PeerConnection) LocalDescription

func (pc *PeerConnection) LocalDescription() (sdp *SessionDescription)

readonly localDescription

func (*PeerConnection) RemoteDescription

func (pc *PeerConnection) RemoteDescription() (sdp *SessionDescription)

readonly remoteDescription

func (*PeerConnection) SetConfiguration

func (pc *PeerConnection) SetConfiguration(config Configuration) error

func (*PeerConnection) SetLocalDescription

func (pc *PeerConnection) SetLocalDescription(sdp *SessionDescription) error

Set a |SessionDescription| as the local description. The description should be generated from the local peer's CreateOffer or CreateAnswer, and not be a description received over the signaling channel.

func (*PeerConnection) SetRemoteDescription

func (pc *PeerConnection) SetRemoteDescription(sdp *SessionDescription) error

Set a |SessionDescription| as the remote description. This description should be one generated by the remote peer's CreateOffer or CreateAnswer, received over the signaling channel, and not a description created locally.

If the local peer is the answerer, this must be called before CreateAnswer.

func (*PeerConnection) SignalingState

func (pc *PeerConnection) SignalingState() SignalingState

readonly signalingState

type PeerConnectionState

type PeerConnectionState int
const (
	PeerConnectionStateNew PeerConnectionState = iota
	PeerConnectionStateConnecting
	PeerConnectionStateConnected
	PeerConnectionStateDisconnected
	PeerConnectionStateFailed
)

func (PeerConnectionState) String

func (s PeerConnectionState) String() string

type RtcpMuxPolicy

type RtcpMuxPolicy int

type SessionDescription

type SessionDescription struct {
	Type string `json:"type"`
	Sdp  string `json:"sdp"`
}
WebRTC SessionDescription

See: https://w3c.github.io/webrtc-pc/#idl-def-RTCSessionDescription

func DeserializeSessionDescription

func DeserializeSessionDescription(msg string) *SessionDescription

Deserialize a received json string into a SessionDescription, if possible.

func NewSessionDescription

func NewSessionDescription(sdpType string, serializedSDP C.CGO_sdpString) *SessionDescription

Construct a SessionDescription object from a valid msg.

func (*SessionDescription) GoStringToCgoSdp

func (desc *SessionDescription) GoStringToCgoSdp() C.CGO_sdp

func (*SessionDescription) Serialize

func (desc *SessionDescription) Serialize() string

Serialize a SessionDescription into a JSON string.

type SignalingState

type SignalingState int
const (
	SignalingStateStable SignalingState = iota
	SignalingStateHaveLocalOffer
	SignalingStateHaveLocalPrAnswer
	SignalingStateHaveRemoteOffer
	SignalingStateHaveRemotePrAnswer
	SignalingStateClosed
)

func (SignalingState) String

func (s SignalingState) String() string

Directories

Path Synopsis
* Basic webrtc demo, two local clients speaking over go, to show the most basic * usage of webrtc in Go.
* Basic webrtc demo, two local clients speaking over go, to show the most basic * usage of webrtc in Go.
chat
* Webrtc chat demo.
* Webrtc chat demo.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL