44package main
55
66import (
7+ "bytes"
78 "context"
89 "encoding/json"
910 "fmt"
11+ "io"
1012 "math/rand"
13+ "net/http"
1114 "os"
1215 "strconv"
1316 "strings"
@@ -97,6 +100,28 @@ func (v *SRSServer) Format(f fmt.State, c rune) {
97100 }
98101}
99102
103+ func (v * SRSServer ) ApiRequest (ctx context.Context , r * http.Request , body []byte ) ([]byte , error ) {
104+ url := "http://" + v .IP + ":" + v .API [0 ] + r .URL .Path
105+ if r .URL .RawQuery != "" {
106+ url += "?" + r .URL .RawQuery
107+ }
108+
109+ if req , err := http .NewRequestWithContext (ctx , r .Method , url , bytes .NewReader (body )); err != nil {
110+ return nil , errors .Wrapf (err , "create request to %v" , url )
111+ } else if res , err := http .DefaultClient .Do (req ); err != nil {
112+ return nil , errors .Wrapf (err , "send request to %v" , url )
113+ } else {
114+ defer res .Body .Close ()
115+ if ret , err := io .ReadAll (res .Body ); err != nil {
116+ return nil , errors .Wrapf (err , "read http respose error" )
117+ } else if ! isHttpStatusOK (res .StatusCode ) {
118+ return ret , errors .Errorf ("http response status code %v" , res .StatusCode )
119+ } else {
120+ return ret , nil
121+ }
122+ }
123+ }
124+
100125func NewSRSServer (opts ... func (* SRSServer )) * SRSServer {
101126 v := & SRSServer {}
102127 for _ , opt := range opts {
@@ -158,13 +183,16 @@ type SRSLoadBalancer interface {
158183 StoreWebRTC (ctx context.Context , streamURL string , value * RTCConnection ) error
159184 // Load the WebRTC streaming by ufrag, the ICE username.
160185 LoadWebRTCByUfrag (ctx context.Context , ufrag string ) (* RTCConnection , error )
186+ // proxy http api to srs
187+ ProxyHTTPAPI (ctx context.Context , w http.ResponseWriter , r * http.Request ) error
161188}
162189
163190// srsLoadBalancer is the global SRS load balancer.
164191var srsLoadBalancer SRSLoadBalancer
165192
166193// srsMemoryLoadBalancer stores state in memory.
167194type srsMemoryLoadBalancer struct {
195+ * SrsApiProxy
168196 // All available SRS servers, key is server ID.
169197 servers sync.Map [string , * SRSServer ]
170198 // The picked server to servce client by specified stream URL, key is stream url.
@@ -287,7 +315,17 @@ func (v *srsMemoryLoadBalancer) LoadWebRTCByUfrag(ctx context.Context, ufrag str
287315 }
288316}
289317
318+ func (v * srsMemoryLoadBalancer ) ProxyHTTPAPI (ctx context.Context , w http.ResponseWriter , r * http.Request ) error {
319+ services := make ([]* SRSServer , v .servers .Size ())
320+ v .servers .Range (func (_ string , value * SRSServer ) bool {
321+ services = append (services , value )
322+ return true
323+ })
324+ return v .proxySrsAPI (ctx , services , w , r )
325+ }
326+
290327type srsRedisLoadBalancer struct {
328+ * SrsApiProxy
291329 // The redis client sdk.
292330 rdb * redis.Client
293331}
@@ -528,6 +566,40 @@ func (v *srsRedisLoadBalancer) LoadWebRTCByUfrag(ctx context.Context, ufrag stri
528566 return & actual , nil
529567}
530568
569+ func (v * srsRedisLoadBalancer ) ProxyHTTPAPI (ctx context.Context , w http.ResponseWriter , r * http.Request ) error {
570+ defer r .Body .Close ()
571+ // Query all servers from redis, in json string.
572+ var serverKeys []string
573+ if b , err := v .rdb .Get (ctx , v .redisKeyServers ()).Bytes (); err == nil {
574+ if err := json .Unmarshal (b , & serverKeys ); err != nil {
575+ return errors .Wrapf (err , "unmarshal key=%v servers %v" , v .redisKeyServers (), string (b ))
576+ }
577+ }
578+
579+ // No server found, failed.
580+ if len (serverKeys ) == 0 {
581+ err := errors .New ("servers empty" )
582+ apiError (ctx , w , r , err , http .StatusInternalServerError )
583+ return err
584+ }
585+
586+ // TODO get all SRSServer
587+ var srsServers []* SRSServer
588+
589+ for _ , key := range serverKeys {
590+ var server SRSServer
591+ if b , err := v .rdb .Get (ctx , key ).Bytes (); err == nil {
592+ if err := json .Unmarshal (b , & server ); err != nil {
593+ return errors .Wrapf (err , "unmarshal servers %v, %v" , key , string (b ))
594+ }
595+ srsServers = append (srsServers , & server )
596+ logger .Df (ctx , "srsServer: %v" , server )
597+ }
598+ }
599+
600+ return v .proxySrsAPI (ctx , srsServers , w , r )
601+ }
602+
531603func (v * srsRedisLoadBalancer ) redisKeyUfrag (ufrag string ) string {
532604 return fmt .Sprintf ("srs-proxy-ufrag:%v" , ufrag )
533605}
@@ -549,5 +621,5 @@ func (v *srsRedisLoadBalancer) redisKeyServer(serverID string) string {
549621}
550622
551623func (v * srsRedisLoadBalancer ) redisKeyServers () string {
552- return fmt . Sprintf ( "srs-proxy-all-servers" )
624+ return "srs-proxy-all-servers"
553625}
0 commit comments