ionorg / ion-sdk-go

ion sdk for golang
MIT License
55 stars 46 forks source link

abstract GRPC implementation so alternative signalling methods are possible #66

Closed MousyBusiness closed 2 years ago

MousyBusiness commented 2 years ago

The primary motivation around this PR is the conflict of the need for port 443 between SFU and TURN if behind restrictive enterprise firewalls. If on these networks, only TLS over 443 is allowed, then signalling the SFU on 443 and using TURN on 443 cannot co-exist.

A minor refactor to rtc.go allows non-grpc methods of signalling.

The 'Signaller' interface exactly matches the GRPC stream so does not break existing examples or server code.

type Signaller interface {
    Send(request *rtc.Request) error
    Recv() (*rtc.Reply, error)
    CloseSend() error
}

An example of how this can be implemented, in a system I'm building, we use a custom signalling server which clients communicate with, which in turn are propagated to the appropriate SFU server.

The client side implementation is as follows:

func NewSFUSignaller(ctx context.Context, sid string) *signaller {
    s := &signaller{
        sid: sid,
        ch:  make(chan *rtc.Reply, 1),
    }
    s.ctx, s.cancel = context.WithCancel(ctx)
    return s
}

func (s *signaller) Send(request *rtc.Request) error {
    select {
    case <-s.ctx.Done():
        return errors.New("send closed")
    default:
    }

    b, err := proto.Marshal(request)
    if err != nil {
        return err
    }

    if err := s.sendSFUSignal(b); err != nil {
        return err
    }

    return nil
}

func (s *signaller) Recv() (*rtc.Reply, error) {
    select {
    case rep, ok := <-s.ch:
        if ok {
            return rep, nil
        }
        return nil, io.EOF
    case <-s.ctx.Done():
        return nil, errors.New("signaller closed")
    }
}

NOTE: sendSFUSignal is an http POST to signalling server

You can see that the rtc protocol buffers are still used, and the interface is simply implemented.