mirror of
https://github.com/harshabose/client.git
synced 2025-10-30 02:02:04 +08:00
Initial clean commit
This commit is contained in:
130
firebase_answer.go
Normal file
130
firebase_answer.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/firestore"
|
||||
"firebase.google.com/go"
|
||||
"google.golang.org/api/option"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
type AnswerSignal struct {
|
||||
peerConnection *PeerConnection
|
||||
app *firebase.App
|
||||
client *firestore.Client
|
||||
docRef *firestore.DocumentRef
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func CreateFirebaseAnswerSignal(ctx context.Context, peerConnection *PeerConnection) *AnswerSignal {
|
||||
var (
|
||||
configuration option.ClientOption
|
||||
app *firebase.App
|
||||
client *firestore.Client
|
||||
err error
|
||||
)
|
||||
|
||||
if configuration, err = GetFirebaseConfiguration(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if app, err = firebase.NewApp(ctx, nil, configuration); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if client, err = app.Firestore(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &AnswerSignal{
|
||||
app: app,
|
||||
client: client,
|
||||
peerConnection: peerConnection,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
func (signal *AnswerSignal) Connect(category, connectionLabel string) error {
|
||||
signal.docRef = signal.client.Collection(category).Doc(connectionLabel)
|
||||
|
||||
ticker := time.NewTicker(1 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
var data map[string]interface{}
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
snapshot, err := signal.docRef.Get(signal.ctx)
|
||||
if err != nil || snapshot == nil {
|
||||
if status.Code(err) == codes.NotFound {
|
||||
continue loop
|
||||
}
|
||||
}
|
||||
data = snapshot.Data()
|
||||
|
||||
if currentStatus, exists := data[FieldStatus]; !exists || currentStatus != FieldStatusPending {
|
||||
continue loop
|
||||
}
|
||||
|
||||
break loop
|
||||
}
|
||||
}
|
||||
fmt.Println("Found Offer. Creating answer...")
|
||||
|
||||
return signal.answer(data[FieldOffer].(map[string]interface{}))
|
||||
}
|
||||
|
||||
func (signal *AnswerSignal) answer(offer map[string]interface{}) error {
|
||||
sdp, ok := offer[FieldSDP].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid SDP format in offer")
|
||||
}
|
||||
|
||||
if err := signal.peerConnection.peerConnection.SetRemoteDescription(webrtc.SessionDescription{
|
||||
Type: webrtc.SDPTypeOffer,
|
||||
SDP: sdp,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
answer, err := signal.peerConnection.peerConnection.CreateAnswer(nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while creating answer: %w", err)
|
||||
}
|
||||
|
||||
if err := signal.peerConnection.peerConnection.SetLocalDescription(answer); err != nil {
|
||||
return fmt.Errorf("error while setting local sdp: %w", err)
|
||||
}
|
||||
|
||||
timer := time.NewTicker(30 * time.Second)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case <-webrtc.GatheringCompletePromise(signal.peerConnection.peerConnection):
|
||||
fmt.Println("ICE Gathering complete")
|
||||
case <-timer.C:
|
||||
return errors.New("failed to gather ICE candidates within 30 seconds")
|
||||
}
|
||||
|
||||
if _, err = signal.docRef.Set(signal.ctx, map[string]interface{}{
|
||||
FieldAnswer: map[string]interface{}{
|
||||
FieldSDP: signal.peerConnection.peerConnection.LocalDescription().SDP,
|
||||
FieldUpdatedAt: firestore.ServerTimestamp,
|
||||
},
|
||||
FieldStatus: FieldStatusConnected,
|
||||
}, firestore.MergeAll); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (signal *AnswerSignal) Close() error {
|
||||
return signal.client.Close()
|
||||
}
|
||||
Reference in New Issue
Block a user