/
exchange.go
105 lines (87 loc) · 2.66 KB
/
exchange.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package exchange
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/pion/webrtc/v2"
)
type createSessionRequest struct {
SessionDescription *webrtc.SessionDescription `json:"session_description"`
SessionID string `json:"session_id"`
}
type sessionResponse struct {
SessionDescription *webrtc.SessionDescription `json:"session_description"`
}
func CreateSession(ctx context.Context, offer *webrtc.SessionDescription, sessionID string) error {
req := createSessionRequest{
SessionID: sessionID,
SessionDescription: offer,
}
buf := new(bytes.Buffer)
err := json.NewEncoder(buf).Encode(req)
if err != nil {
return fmt.Errorf("failed to encode: %s", err)
}
resp, err := http.Post(fmt.Sprintf("https://webrtc-sdp-exchanger.appspot.com/sessions/%s", sessionID), "application/json; charset=utf-8", buf)
if err != nil {
return fmt.Errorf("http post: %s", err)
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("invalid status: %s", resp.Status)
}
return nil
}
func GetSessionAnswer(ctx context.Context, sessionID string) (*webrtc.SessionDescription, error) {
return getSessionWithRetry(ctx, sessionID, webrtc.SDPTypeAnswer)
}
func GetSessionOffer(ctx context.Context, sessionID string) (*webrtc.SessionDescription, error) {
return getSessionWithRetry(ctx, sessionID, webrtc.SDPTypeOffer)
}
func getSessionWithRetry(ctx context.Context, sessionID string, sdpType webrtc.SDPType) (*webrtc.SessionDescription, error) {
for {
res, err := getSession(ctx, sessionID, sdpType)
if err != nil {
return nil, err
}
// retry
if res == nil {
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-time.After(3 * time.Second):
}
}
return res, nil
}
}
func getSession(ctx context.Context, sessionID string, sdpType webrtc.SDPType) (*webrtc.SessionDescription, error) {
req, err := http.NewRequest("GET", fmt.Sprintf("https://webrtc-sdp-exchanger.appspot.com/sessions/%s/%s", sessionID, sdpType.String()), nil)
if err != nil {
return nil, err
}
req.WithContext(ctx)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("http get: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
if resp.StatusCode != http.StatusNotFound {
b, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("invalid status %s: %s", resp.Status, string(b))
}
return nil, nil
}
res := sessionResponse{}
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
return nil, nil
}
if res.SessionDescription == nil {
return nil, fmt.Errorf("not found: session_description")
}
return res.SessionDescription, nil
}