-
-
Notifications
You must be signed in to change notification settings - Fork 235
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sfu): add data channel middlewares (#388)
* feat(sfu): Add datachannel middlewares * feat(sfu): Add datachannel fanout middleware * fix grpc web sfu initialization * Add keepalive datachannel middleware * Simplify middleware api * Fix tests * Fix tests and linter issues * Add readme and forward args to callback
- Loading branch information
Showing
15 changed files
with
296 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Datachannels middlewares | ||
|
||
`ion-sfu` supports datachannels middlewares similar to the `net/http` standard library handlers. | ||
|
||
## API | ||
|
||
### Middleware | ||
|
||
To create a datachannel middleware, just follow below pattern: | ||
|
||
```go | ||
func SubscriberAPI(next sfu.MessageProcessor) sfu.MessageProcessor { | ||
return sfu.ProcessFunc(func(ctx context.Context, args sfu.ProcessArgs) { | ||
next.Process(ctx,args) | ||
} | ||
} | ||
``` | ||
|
||
### Init middlewares | ||
|
||
To initialize the middlewares you need to declare them after sfu initialization: | ||
```go | ||
s := sfu.NewSFU(conf) | ||
dc := s.NewDatachannel(sfu.APIChannelLabel) | ||
dc.Use(datachannel.KeepAlive(5*time.Second), datachannel.SubscriberAPI) | ||
// This callback is optional | ||
dc.OnMessage(func(ctx context.Context, msg webrtc.DataChannelMessage, in *webrtc.DataChannel, out []*webrtc.DataChannel) { | ||
}) | ||
``` | ||
The datachannels will be negotiated on peer join in the `Subscriber` peer connection. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package datachannel | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"time" | ||
|
||
"github.com/pion/ion-sfu/pkg/sfu" | ||
) | ||
|
||
func KeepAlive(timeout time.Duration) func(next sfu.MessageProcessor) sfu.MessageProcessor { | ||
var timer *time.Timer | ||
return func(next sfu.MessageProcessor) sfu.MessageProcessor { | ||
return sfu.ProcessFunc(func(ctx context.Context, args sfu.ProcessArgs) { | ||
if timer == nil { | ||
timer = time.AfterFunc(timeout, func() { | ||
_ = args.Peer.Close() | ||
}) | ||
} | ||
if args.Message.IsString && bytes.Equal(args.Message.Data, []byte("ping")) { | ||
if !timer.Stop() { | ||
<-timer.C | ||
} | ||
timer.Reset(timeout) | ||
_ = args.DataChannel.SendText("pong") | ||
return | ||
} | ||
next.Process(ctx, args) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package sfu | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/pion/webrtc/v3" | ||
) | ||
|
||
type ( | ||
// Datachannel is a wrapper to define middlewares executed on defined label. | ||
// The datachannels created will be negotiated on join to all peers that joins | ||
// the SFU. | ||
Datachannel struct { | ||
label string | ||
middlewares []func(MessageProcessor) MessageProcessor | ||
onMessage func(ctx context.Context, args ProcessArgs, out []*webrtc.DataChannel) | ||
} | ||
|
||
ProcessArgs struct { | ||
Peer *Peer | ||
Message webrtc.DataChannelMessage | ||
DataChannel *webrtc.DataChannel | ||
} | ||
|
||
Middlewares []func(MessageProcessor) MessageProcessor | ||
|
||
MessageProcessor interface { | ||
Process(ctx context.Context, args ProcessArgs) | ||
} | ||
|
||
ProcessFunc func(ctx context.Context, args ProcessArgs) | ||
|
||
chainHandler struct { | ||
middlewares Middlewares | ||
Last MessageProcessor | ||
current MessageProcessor | ||
} | ||
) | ||
|
||
// Use adds the middlewares to the current Datachannel. | ||
// The middlewares are going to be executed before the OnMessage event fires. | ||
func (dc *Datachannel) Use(middlewares ...func(MessageProcessor) MessageProcessor) { | ||
dc.middlewares = append(dc.middlewares, middlewares...) | ||
} | ||
|
||
// OnMessage sets the message callback for the datachannel, the event is fired | ||
// after all the middlewares have processed the message. | ||
func (dc *Datachannel) OnMessage(fn func(ctx context.Context, args ProcessArgs, out []*webrtc.DataChannel)) { | ||
dc.onMessage = fn | ||
} | ||
|
||
func (p ProcessFunc) Process(ctx context.Context, args ProcessArgs) { | ||
p(ctx, args) | ||
} | ||
|
||
func (mws Middlewares) Process(h MessageProcessor) MessageProcessor { | ||
return &chainHandler{mws, h, chain(mws, h)} | ||
} | ||
|
||
func (mws Middlewares) ProcessFunc(h MessageProcessor) MessageProcessor { | ||
return &chainHandler{mws, h, chain(mws, h)} | ||
} | ||
|
||
func newDCChain(m []func(p MessageProcessor) MessageProcessor) Middlewares { | ||
return Middlewares(m) | ||
} | ||
|
||
func (c *chainHandler) Process(ctx context.Context, args ProcessArgs) { | ||
c.current.Process(ctx, args) | ||
} | ||
|
||
func chain(mws []func(processor MessageProcessor) MessageProcessor, last MessageProcessor) MessageProcessor { | ||
if len(mws) == 0 { | ||
return last | ||
} | ||
h := mws[len(mws)-1](last) | ||
for i := len(mws) - 2; i >= 0; i-- { | ||
h = mws[i](h) | ||
} | ||
return h | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.