Skip to content

Commit

Permalink
Implement API handler to fetch sessions for call
Browse files Browse the repository at this point in the history
  • Loading branch information
streamer45 committed Jan 8, 2025
1 parent ed6f914 commit 8790b1f
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 0 deletions.
28 changes: 28 additions & 0 deletions service/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,31 @@ func (c *Client) GetSession(callID, sessionID string) (rtc.SessionConfig, int, e

return cfg, resp.StatusCode, nil
}

func (c *Client) GetSessions(callID string) ([]rtc.SessionConfig, int, error) {
reqURL := fmt.Sprintf("%s/calls/%s/sessions", c.cfg.httpURL, callID)

req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
return nil, 0, fmt.Errorf("failed to build request: %w", err)
}
req.SetBasicAuth(c.cfg.ClientID, c.cfg.AuthKey)

resp, err := c.httpClient.Do(req)
if err != nil {
return nil, 0, fmt.Errorf("http request failed: %w", err)
}
defer resp.Body.Close()

var cfgs []rtc.SessionConfig

if resp.StatusCode != http.StatusOK {
return nil, resp.StatusCode, fmt.Errorf("request failed with status %s", resp.Status)
}

if err := json.NewDecoder(resp.Body).Decode(&cfgs); err != nil {
return nil, resp.StatusCode, fmt.Errorf("decoding http response failed: %w", err)
}

return cfgs, resp.StatusCode, nil
}
82 changes: 82 additions & 0 deletions service/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -880,3 +880,85 @@ func TestClientGetSession(t *testing.T) {
require.Equal(t, http.StatusOK, code)
})
}

func TestClientGetSessions(t *testing.T) {
th := SetupTestHelper(t, nil)
defer th.Teardown()

// register client
authKey := "Nl9OZthX5cMJz5a_HmU3kQJ4pHIIlohr"
err := th.srvc.auth.Register("clientA", authKey)
require.NoError(t, err)

t.Run("unauthorized", func(t *testing.T) {
c, err := NewClient(ClientConfig{
URL: th.apiURL,
})
require.NoError(t, err)
require.NotNil(t, c)
defer c.Close()

cfgs, code, err := c.GetSessions("callID")
require.EqualError(t, err, "request failed with status 401 Unauthorized")
require.Empty(t, cfgs)
require.Equal(t, http.StatusUnauthorized, code)
})

t.Run("no call ongoing", func(t *testing.T) {
c, err := NewClient(ClientConfig{
URL: th.apiURL,
ClientID: "clientA",
AuthKey: authKey,
})
require.NoError(t, err)
require.NotNil(t, c)
defer c.Close()

cfgs, code, err := c.GetSessions("callID")
require.EqualError(t, err, "request failed with status 404 Not Found")
require.Empty(t, cfgs)
require.Equal(t, http.StatusNotFound, code)
})

t.Run("call ongoing", func(t *testing.T) {
c, err := NewClient(ClientConfig{
URL: th.apiURL,
ClientID: "clientA",
AuthKey: authKey,
})
require.NoError(t, err)
require.NotNil(t, c)
defer c.Close()

cfgA := rtc.SessionConfig{
GroupID: "clientA",
CallID: "callIDA",
UserID: "userA",
SessionID: "sessionA",
}
err = th.srvc.rtcServer.InitSession(cfgA, nil)
require.NoError(t, err)
defer func() {
err := th.srvc.rtcServer.CloseSession("sessionA")
require.NoError(t, err)
}()

cfgB := rtc.SessionConfig{
GroupID: "clientA",
CallID: "callIDA",
UserID: "userB",
SessionID: "sessionB",
}
err = th.srvc.rtcServer.InitSession(cfgB, nil)
require.NoError(t, err)
defer func() {
err := th.srvc.rtcServer.CloseSession("sessionB")
require.NoError(t, err)
}()

sessionCfgs, code, err := c.GetSessions("callIDA")
require.NoError(t, err)
require.ElementsMatch(t, []rtc.SessionConfig{cfgA, cfgB}, sessionCfgs)
require.Equal(t, http.StatusOK, code)
})
}
25 changes: 25 additions & 0 deletions service/rtc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,28 @@ func (s *Server) GetSessionConfig(groupID, callID, sessionID string) (SessionCon

return session.cfg, nil
}

func (s *Server) GetSessionConfigs(groupID, callID string) ([]SessionConfig, error) {
group := s.getGroup(groupID)
if group == nil {
return nil, fmt.Errorf("group not found")
}

call := group.getCall(callID)
if call == nil {
return nil, fmt.Errorf("call not found")
}

call.mut.RLock()
defer call.mut.RUnlock()
if len(call.sessions) == 0 {
return nil, fmt.Errorf("no sessions found")
}

cfgs := make([]SessionConfig, 0, len(call.sessions))
for _, session := range call.sessions {
cfgs = append(cfgs, session.cfg)
}

return cfgs, nil
}
1 change: 1 addition & 0 deletions service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func New(cfg Config) (*Service, error) {
s.apiServer.RegisterHandleFunc("/login", s.loginClient)
s.apiServer.RegisterHandleFunc("/register", s.registerClient)
s.apiServer.RegisterHandleFunc("/unregister", s.unregisterClient)
s.apiServer.RegisterHandleFunc("/calls/{callID}/sessions", s.handleGetSessions)
s.apiServer.RegisterHandleFunc("/calls/{callID}/sessions/{sessionID}", s.handleGetSession)
s.apiServer.RegisterHandler("/ws", s.wsServer)

Expand Down
34 changes: 34 additions & 0 deletions service/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,37 @@ func (s *Service) handleGetSession(w http.ResponseWriter, req *http.Request) {
s.log.Error("failed to encode data", mlog.Err(err))
}
}

func (s *Service) handleGetSessions(w http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodGet {
http.NotFound(w, req)
return
}

clientID, code, err := s.authHandler(w, req)
if err != nil {
s.log.Error("failed to authenticate", mlog.Err(err), mlog.Int("code", code))
}

if clientID == "" {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}

callID := req.PathValue("callID")
if callID == "" {
http.Error(w, "callID is required", http.StatusBadRequest)
return
}

cfgs, err := s.rtcServer.GetSessionConfigs(clientID, callID)
if err != nil {
http.Error(w, fmt.Sprintf("failed to get session configs: %s", err.Error()), http.StatusNotFound)
return
}

w.Header().Add("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(cfgs); err != nil {
s.log.Error("failed to encode data", mlog.Err(err))
}
}

0 comments on commit 8790b1f

Please sign in to comment.