Move signaling api types to api package.

This commit is contained in:
Joachim Bauch 2025-12-11 16:34:03 +01:00
commit 179498f28b
No known key found for this signature in database
GPG key ID: 77C1D22D53E15F02
54 changed files with 1498 additions and 1424 deletions

View file

@ -46,6 +46,10 @@ component_management:
name: metrics
paths:
- metrics/**
- component_id: module_mock
name: mock
paths:
- mock/**
- component_id: module_nats
name: nats
paths:

View file

@ -19,7 +19,7 @@ PROTO_FILES := $(filter-out $(GRPC_PROTO_FILES),$(basename $(wildcard *.proto)))
PROTO_GO_FILES := $(addsuffix .pb.go,$(PROTO_FILES))
GRPC_PROTO_GO_FILES := $(addsuffix .pb.go,$(GRPC_PROTO_FILES)) $(addsuffix _grpc.pb.go,$(GRPC_PROTO_FILES))
TEST_GO_FILES := $(wildcard *_test.go))
EASYJSON_FILES := $(filter-out $(TEST_GO_FILES),$(wildcard api*.go talk/ocs.go))
EASYJSON_FILES := $(filter-out $(TEST_GO_FILES),$(wildcard api*.go api/signaling.go talk/ocs.go))
EASYJSON_GO_FILES := $(patsubst %.go,%_easyjson.go,$(EASYJSON_FILES))
COMMON_GO_FILES := $(filter-out continentmap.go $(PROTO_GO_FILES) $(GRPC_PROTO_GO_FILES) $(EASYJSON_GO_FILES) $(TEST_GO_FILES),$(wildcard *.go))
CLIENT_TEST_GO_FILES := $(wildcard client/*_test.go))

View file

@ -19,7 +19,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package signaling
package api
import (
"encoding/json"
@ -36,7 +36,6 @@ import (
"github.com/pion/ice/v4"
"github.com/pion/sdp/v3"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/container"
"github.com/strukturag/nextcloud-spreed-signaling/internal"
)
@ -53,6 +52,9 @@ const (
)
var (
// InvalidHelloVersion is returned if the version in the "hello" message is not supported.
InvalidHelloVersion = NewError("invalid_hello_version", "The hello version is not supported.")
ErrNoSdp = NewError("no_sdp", "Payload does not contain a SDP.") // +checklocksignore: Global readonly variable.
ErrInvalidSdp = NewError("invalid_sdp", "Payload does not contain a valid SDP.")
@ -68,6 +70,10 @@ type PublicSessionId string
type RoomSessionId string
const (
FederatedRoomSessionIdPrefix = "federated|"
)
func (s RoomSessionId) IsFederated() bool {
return strings.HasPrefix(string(s), FederatedRoomSessionIdPrefix)
}
@ -205,7 +211,11 @@ type ServerMessage struct {
Dialout *DialoutInternalClientMessage `json:"dialout,omitempty"`
}
func (r *ServerMessage) CloseAfterSend(session Session) bool {
type RoomAware interface {
IsInRoom(id string) bool
}
func (r *ServerMessage) CloseAfterSend(session RoomAware) bool {
if r.Type == "bye" {
return true
}
@ -214,10 +224,8 @@ func (r *ServerMessage) CloseAfterSend(session Session) bool {
if evt := r.Event; evt != nil && evt.Target == "roomlist" && evt.Type == "disinvite" {
// Only close session / connection if the disinvite was for the room
// the session is currently in.
if session != nil && evt.Disinvite != nil {
if room := session.GetRoom(); room != nil && evt.Disinvite.RoomId == room.Id() {
return true
}
if session != nil && evt.Disinvite != nil && session.IsInRoom(evt.Disinvite.RoomId) {
return true
}
}
}
@ -357,8 +365,8 @@ type ClientTypeInternalAuthParams struct {
Random string `json:"random"`
Token string `json:"token"`
Backend string `json:"backend"`
parsedBackend *url.URL
Backend string `json:"backend"`
ParsedBackend *url.URL `json:"-"`
}
func (p *ClientTypeInternalAuthParams) CheckValid() error {
@ -377,7 +385,7 @@ func (p *ClientTypeInternalAuthParams) CheckValid() error {
p.Backend = u.String()
}
p.parsedBackend = u
p.ParsedBackend = u
}
return nil
}
@ -437,12 +445,12 @@ type HelloClientMessageAuth struct {
Params json.RawMessage `json:"params"`
Url string `json:"url"`
parsedUrl *url.URL
Url string `json:"url"`
ParsedUrl *url.URL `json:"-"`
internalParams ClientTypeInternalAuthParams
helloV2Params HelloV2AuthParams
federationParams FederationAuthParams
InternalParams ClientTypeInternalAuthParams `json:"-"`
HelloV2Params HelloV2AuthParams `json:"-"`
FederationParams FederationAuthParams `json:"-"`
}
// Type "hello"
@ -492,7 +500,7 @@ func (m *HelloClientMessage) CheckValid() error {
m.Auth.Url = u.String()
}
m.Auth.parsedUrl = u
m.Auth.ParsedUrl = u
}
switch m.Version {
@ -501,23 +509,23 @@ func (m *HelloClientMessage) CheckValid() error {
case HelloVersionV2:
switch m.Auth.Type {
case HelloClientTypeClient:
if err := json.Unmarshal(m.Auth.Params, &m.Auth.helloV2Params); err != nil {
if err := json.Unmarshal(m.Auth.Params, &m.Auth.HelloV2Params); err != nil {
return err
} else if err := m.Auth.helloV2Params.CheckValid(); err != nil {
} else if err := m.Auth.HelloV2Params.CheckValid(); err != nil {
return err
}
case HelloClientTypeFederation:
if err := json.Unmarshal(m.Auth.Params, &m.Auth.federationParams); err != nil {
if err := json.Unmarshal(m.Auth.Params, &m.Auth.FederationParams); err != nil {
return err
} else if err := m.Auth.federationParams.CheckValid(); err != nil {
} else if err := m.Auth.FederationParams.CheckValid(); err != nil {
return err
}
}
}
case HelloClientTypeInternal:
if err := json.Unmarshal(m.Auth.Params, &m.Auth.internalParams); err != nil {
if err := json.Unmarshal(m.Auth.Params, &m.Auth.InternalParams); err != nil {
return err
} else if err := m.Auth.internalParams.CheckValid(); err != nil {
} else if err := m.Auth.InternalParams.CheckValid(); err != nil {
return err
}
default:
@ -654,11 +662,11 @@ func (m *RoomClientMessage) CheckValid() error {
}
type RoomFederationMessage struct {
SignalingUrl string `json:"signaling"`
parsedSignalingUrl *url.URL
SignalingUrl string `json:"signaling"`
ParsedSignalingUrl *url.URL `json:"-"`
NextcloudUrl string `json:"url"`
parsedNextcloudUrl *url.URL
NextcloudUrl string `json:"url"`
ParsedNextcloudUrl *url.URL `json:"-"`
RoomId string `json:"roomid,omitempty"`
Token string `json:"token"`
@ -675,14 +683,14 @@ func (m *RoomFederationMessage) CheckValid() error {
if u, err := url.Parse(m.SignalingUrl); err != nil {
return fmt.Errorf("invalid signaling url: %w", err)
} else {
m.parsedSignalingUrl = u
m.ParsedSignalingUrl = u
}
if m.NextcloudUrl == "" {
return errors.New("nextcloud url missing")
} else if u, err := url.Parse(m.NextcloudUrl); err != nil {
return fmt.Errorf("invalid nextcloud url: %w", err)
} else {
m.parsedNextcloudUrl = u
m.ParsedNextcloudUrl = u
}
if m.Token == "" {
return errors.New("token missing")
@ -698,8 +706,8 @@ type RoomServerMessage struct {
}
type RoomBandwidth struct {
MaxStreamBitrate api.Bandwidth `json:"maxstreambitrate"`
MaxScreenBitrate api.Bandwidth `json:"maxscreenbitrate"`
MaxStreamBitrate Bandwidth `json:"maxstreambitrate"`
MaxScreenBitrate Bandwidth `json:"maxscreenbitrate"`
}
type RoomErrorDetails struct {
@ -732,21 +740,21 @@ type MessageClientMessageData struct {
json.Marshaler
json.Unmarshaler
Type string `json:"type"`
Sid string `json:"sid"`
RoomType string `json:"roomType"`
Payload api.StringMap `json:"payload"`
Type string `json:"type"`
Sid string `json:"sid"`
RoomType string `json:"roomType"`
Payload StringMap `json:"payload"`
// Only supported if Type == "offer"
Bitrate api.Bandwidth `json:"bitrate,omitempty"`
AudioCodec string `json:"audiocodec,omitempty"`
VideoCodec string `json:"videocodec,omitempty"`
VP9Profile string `json:"vp9profile,omitempty"`
H264Profile string `json:"h264profile,omitempty"`
Bitrate Bandwidth `json:"bitrate,omitempty"`
AudioCodec string `json:"audiocodec,omitempty"`
VideoCodec string `json:"videocodec,omitempty"`
VP9Profile string `json:"vp9profile,omitempty"`
H264Profile string `json:"h264profile,omitempty"`
offerSdp *sdp.SessionDescription // Only set if Type == "offer"
answerSdp *sdp.SessionDescription // Only set if Type == "answer"
candidate ice.Candidate // Only set if Type == "candidate"
OfferSdp *sdp.SessionDescription `json:"-"` // Only set if Type == "offer"
AnswerSdp *sdp.SessionDescription `json:"-"` // Only set if Type == "answer"
Candidate ice.Candidate `json:"-"` // Only set if Type == "candidate"
}
func (m *MessageClientMessageData) String() string {
@ -757,10 +765,10 @@ func (m *MessageClientMessageData) String() string {
return string(data)
}
func parseSDP(s string) (*sdp.SessionDescription, error) {
func ParseSDP(s string) (*sdp.SessionDescription, error) {
var sdp sdp.SessionDescription
if err := sdp.UnmarshalString(s); err != nil {
return nil, NewErrorDetail("invalid_sdp", "Error parsing SDP from payload.", api.StringMap{
return nil, NewErrorDetail("invalid_sdp", "Error parsing SDP from payload.", StringMap{
"error": err.Error(),
})
}
@ -772,7 +780,7 @@ func parseSDP(s string) (*sdp.SessionDescription, error) {
}
if _, err := ice.UnmarshalCandidate(a.Value); err != nil {
return nil, NewErrorDetail("invalid_sdp", "Error parsing candidate from media description.", api.StringMap{
return nil, NewErrorDetail("invalid_sdp", "Error parsing candidate from media description.", StringMap{
"media": m.MediaName.Media,
"idx": idx,
"error": err.Error(),
@ -788,52 +796,66 @@ var (
emptyCandidate = &ice.CandidateHost{}
)
// TODO: Use shared method from "mcu_common.go".
func isValidStreamType(s string) bool {
switch s {
case "audio":
fallthrough
case "video":
fallthrough
case "screen":
return true
default:
return false
}
}
func (m *MessageClientMessageData) CheckValid() error {
if m.RoomType != "" && !IsValidStreamType(m.RoomType) {
if m.RoomType != "" && !isValidStreamType(m.RoomType) {
return fmt.Errorf("invalid room type: %s", m.RoomType)
}
switch m.Type {
case "offer", "answer":
sdpText, ok := api.GetStringMapEntry[string](m.Payload, "sdp")
sdpText, ok := GetStringMapEntry[string](m.Payload, "sdp")
if !ok {
return ErrInvalidSdp
}
sdp, err := parseSDP(sdpText)
sdp, err := ParseSDP(sdpText)
if err != nil {
return err
}
switch m.Type {
case "offer":
m.offerSdp = sdp
m.OfferSdp = sdp
case "answer":
m.answerSdp = sdp
m.AnswerSdp = sdp
}
case "candidate":
candValue, found := m.Payload["candidate"]
if !found {
return ErrNoCandidate
}
candItem, ok := api.ConvertStringMap(candValue)
candItem, ok := ConvertStringMap(candValue)
if !ok {
return ErrInvalidCandidate
}
candText, ok := api.GetStringMapEntry[string](candItem, "candidate")
candText, ok := GetStringMapEntry[string](candItem, "candidate")
if !ok {
return ErrInvalidCandidate
}
if candText == "" {
m.candidate = emptyCandidate
m.Candidate = emptyCandidate
} else {
cand, err := ice.UnmarshalCandidate(candText)
if err != nil {
return NewErrorDetail("invalid_candidate", "Error parsing candidate from payload.", api.StringMap{
return NewErrorDetail("invalid_candidate", "Error parsing candidate from payload.", StringMap{
"error": err.Error(),
})
}
m.candidate = cand
m.Candidate = cand
}
}
return nil
@ -1113,11 +1135,18 @@ func (m *InternalClientMessage) CheckValid() error {
return nil
}
type InternalServerDialoutRequestContents struct {
// E.164 number to dial (e.g. "+1234567890")
Number string `json:"number"`
Options json.RawMessage `json:"options,omitempty"`
}
type InternalServerDialoutRequest struct {
RoomId string `json:"roomid"`
Backend string `json:"backend"`
Request *BackendRoomDialoutRequest `json:"request"`
Request *InternalServerDialoutRequestContents `json:"request"`
}
type InternalServerMessage struct {
@ -1133,8 +1162,8 @@ type RoomEventServerMessage struct {
Properties json.RawMessage `json:"properties,omitempty"`
// TODO(jojo): Change "InCall" to "int" when #914 has landed in NC Talk.
InCall json.RawMessage `json:"incall,omitempty"`
Changed []api.StringMap `json:"changed,omitempty"`
Users []api.StringMap `json:"users,omitempty"`
Changed []StringMap `json:"changed,omitempty"`
Users []StringMap `json:"users,omitempty"`
All bool `json:"all,omitempty"`
}
@ -1158,7 +1187,7 @@ type RoomDisinviteEventServerMessage struct {
Reason string `json:"reason"`
}
type ChatComment api.StringMap
type ChatComment StringMap
type RoomEventMessageDataChat struct {
// Refresh will be included if the client does not support the "chat-relay" feature.
@ -1260,7 +1289,7 @@ type AnswerOfferMessage struct {
From PublicSessionId `json:"from"`
Type string `json:"type"`
RoomType string `json:"roomType"`
Payload api.StringMap `json:"payload"`
Payload StringMap `json:"payload"`
Sid string `json:"sid,omitempty"`
}
@ -1292,8 +1321,8 @@ func (m *TransientDataClientMessage) CheckValid() error {
type TransientDataServerMessage struct {
Type string `json:"type"`
Key string `json:"key,omitempty"`
OldValue any `json:"oldvalue,omitempty"`
Value any `json:"value,omitempty"`
Data api.StringMap `json:"data,omitempty"`
Key string `json:"key,omitempty"`
OldValue any `json:"oldvalue,omitempty"`
Value any `json:"value,omitempty"`
Data StringMap `json:"data,omitempty"`
}

View file

@ -19,7 +19,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package signaling
package api
import (
"encoding/json"
@ -33,6 +33,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/strukturag/nextcloud-spreed-signaling/container"
"github.com/strukturag/nextcloud-spreed-signaling/mock"
)
type testCheckValid interface {
@ -509,10 +510,10 @@ func TestFilterSDPCandidates(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
s, err := parseSDP(MockSdpOfferAudioOnly)
s, err := ParseSDP(mock.MockSdpOfferAudioOnly)
require.NoError(err)
if encoded, err := s.Marshal(); assert.NoError(err) {
assert.Equal(MockSdpOfferAudioOnly, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
assert.Equal(mock.MockSdpOfferAudioOnly, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
}
expectedBefore := map[string]int{
@ -549,8 +550,8 @@ func TestFilterSDPCandidates(t *testing.T) {
}
if encoded, err := s.Marshal(); assert.NoError(err) {
assert.NotEqual(MockSdpOfferAudioOnly, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
assert.Equal(MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
assert.NotEqual(mock.MockSdpOfferAudioOnly, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
assert.Equal(mock.MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
}
}
@ -559,10 +560,10 @@ func TestNoFilterSDPCandidates(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
s, err := parseSDP(MockSdpOfferAudioOnlyNoFilter)
s, err := ParseSDP(mock.MockSdpOfferAudioOnlyNoFilter)
require.NoError(err)
if encoded, err := s.Marshal(); assert.NoError(err) {
assert.Equal(MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
assert.Equal(mock.MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
}
expectedBefore := map[string]int{
@ -599,6 +600,6 @@ func TestNoFilterSDPCandidates(t *testing.T) {
}
if encoded, err := s.Marshal(); assert.NoError(err) {
assert.Equal(MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
assert.Equal(mock.MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
}
}

View file

@ -25,6 +25,8 @@ import (
"encoding/json"
"fmt"
"time"
"github.com/strukturag/nextcloud-spreed-signaling/api"
)
type AsyncMessage struct {
@ -32,7 +34,7 @@ type AsyncMessage struct {
Type string `json:"type"`
Message *ServerMessage `json:"message,omitempty"`
Message *api.ServerMessage `json:"message,omitempty"`
Room *BackendServerRoomRequest `json:"room,omitempty"`
@ -56,12 +58,12 @@ func (m *AsyncMessage) String() string {
type AsyncRoomMessage struct {
Type string `json:"type"`
SessionId PublicSessionId `json:"sessionid,omitempty"`
ClientType ClientType `json:"clienttype,omitempty"`
SessionId api.PublicSessionId `json:"sessionid,omitempty"`
ClientType api.ClientType `json:"clienttype,omitempty"`
}
type SendOfferMessage struct {
MessageId string `json:"messageid,omitempty"`
SessionId PublicSessionId `json:"sessionid"`
Data *MessageClientMessageData `json:"data"`
MessageId string `json:"messageid,omitempty"`
SessionId api.PublicSessionId `json:"sessionid"`
Data *api.MessageClientMessageData `json:"data"`
}

View file

@ -127,8 +127,8 @@ type BackendRoomInviteRequest struct {
}
type BackendRoomDisinviteRequest struct {
UserIds []string `json:"userids,omitempty"`
SessionIds []RoomSessionId `json:"sessionids,omitempty"`
UserIds []string `json:"userids,omitempty"`
SessionIds []api.RoomSessionId `json:"sessionids,omitempty"`
// TODO(jojo): We should get rid of "AllUserIds" and find a better way to
// notify existing users the room has changed and they need to update it.
AllUserIds []string `json:"alluserids,omitempty"`
@ -161,11 +161,11 @@ type BackendRoomMessageRequest struct {
Data json.RawMessage `json:"data,omitempty"`
}
type BackendRoomSwitchToSessionsList []RoomSessionId
type BackendRoomSwitchToSessionsMap map[RoomSessionId]json.RawMessage
type BackendRoomSwitchToSessionsList []api.RoomSessionId
type BackendRoomSwitchToSessionsMap map[api.RoomSessionId]json.RawMessage
type BackendRoomSwitchToPublicSessionsList []PublicSessionId
type BackendRoomSwitchToPublicSessionsMap map[PublicSessionId]json.RawMessage
type BackendRoomSwitchToPublicSessionsList []api.PublicSessionId
type BackendRoomSwitchToPublicSessionsMap map[api.PublicSessionId]json.RawMessage
type BackendRoomSwitchToMessageRequest struct {
// Target room id
@ -198,13 +198,13 @@ func isValidNumber(s string) bool {
return checkE164Number.MatchString(s)
}
func (r *BackendRoomDialoutRequest) ValidateNumber() *Error {
func (r *BackendRoomDialoutRequest) ValidateNumber() *api.Error {
if r.Number == "" {
return NewError("number_missing", "No number provided")
return api.NewError("number_missing", "No number provided")
}
if !isValidNumber(r.Number) {
return NewError("invalid_number", "Expected E.164 number.")
return api.NewError("invalid_number", "Expected E.164 number.")
}
return nil
@ -246,7 +246,7 @@ type BackendRoomDialoutError struct {
type BackendRoomDialoutResponse struct {
CallId string `json:"callid,omitempty"`
Error *Error `json:"error,omitempty"`
Error *api.Error `json:"error,omitempty"`
}
// Requests from the signaling server to the Nextcloud backend.
@ -287,7 +287,7 @@ type BackendClientResponse struct {
Type string `json:"type"`
Error *Error `json:"error,omitempty"`
Error *api.Error `json:"error,omitempty"`
Auth *BackendClientAuthResponse `json:"auth,omitempty"`
@ -305,11 +305,11 @@ type BackendClientAuthResponse struct {
}
type BackendClientRoomRequest struct {
Version string `json:"version"`
RoomId string `json:"roomid"`
Action string `json:"action,omitempty"`
UserId string `json:"userid"`
SessionId RoomSessionId `json:"sessionid"`
Version string `json:"version"`
RoomId string `json:"roomid"`
Action string `json:"action,omitempty"`
UserId string `json:"userid"`
SessionId api.RoomSessionId `json:"sessionid"`
// For Nextcloud Talk with SIP support and for federated sessions.
ActorId string `json:"actorid,omitempty"`
@ -318,7 +318,7 @@ type BackendClientRoomRequest struct {
}
func (r *BackendClientRoomRequest) UpdateFromSession(s Session) {
if s.ClientType() == HelloClientTypeFederation {
if s.ClientType() == api.HelloClientTypeFederation {
// Need to send additional data for requests of federated users.
if u, err := s.ParsedUserData(); err == nil && len(u) > 0 {
if actorType, found := api.GetStringMapEntry[string](u, "actorType"); found {
@ -331,7 +331,7 @@ func (r *BackendClientRoomRequest) UpdateFromSession(s Session) {
}
}
func NewBackendClientRoomRequest(roomid string, userid string, sessionid RoomSessionId) *BackendClientRequest {
func NewBackendClientRoomRequest(roomid string, userid string, sessionid api.RoomSessionId) *BackendClientRequest {
return &BackendClientRequest{
Type: "room",
Room: &BackendClientRoomRequest{
@ -361,8 +361,8 @@ type RoomSessionData struct {
}
type BackendPingEntry struct {
UserId string `json:"userid,omitempty"`
SessionId RoomSessionId `json:"sessionid"`
UserId string `json:"userid,omitempty"`
SessionId api.RoomSessionId `json:"sessionid"`
}
type BackendClientPingRequest struct {
@ -388,12 +388,12 @@ type BackendClientRingResponse struct {
}
type BackendClientSessionRequest struct {
Version string `json:"version"`
RoomId string `json:"roomid"`
Action string `json:"action"`
SessionId PublicSessionId `json:"sessionid"`
UserId string `json:"userid,omitempty"`
User json.RawMessage `json:"user,omitempty"`
Version string `json:"version"`
RoomId string `json:"roomid"`
Action string `json:"action"`
SessionId api.PublicSessionId `json:"sessionid"`
UserId string `json:"userid,omitempty"`
User json.RawMessage `json:"user,omitempty"`
}
type BackendClientSessionResponse struct {
@ -401,7 +401,7 @@ type BackendClientSessionResponse struct {
RoomId string `json:"roomid"`
}
func NewBackendClientSessionRequest(roomid string, action string, sessionid PublicSessionId, msg *AddSessionInternalClientMessage) *BackendClientRequest {
func NewBackendClientSessionRequest(roomid string, action string, sessionid api.PublicSessionId, msg *api.AddSessionInternalClientMessage) *BackendClientRequest {
request := &BackendClientRequest{
Type: "session",
Session: &BackendClientSessionRequest{
@ -548,12 +548,12 @@ type BackendServerInfoSfu struct {
}
type BackendServerInfoDialout struct {
SessionId PublicSessionId `json:"sessionid"`
Connected bool `json:"connected"`
Address string `json:"address,omitempty"`
UserAgent string `json:"useragent,omitempty"`
Version string `json:"version,omitempty"`
Features []string `json:"features,omitempty"`
SessionId api.PublicSessionId `json:"sessionid"`
Connected bool `json:"connected"`
Address string `json:"address,omitempty"`
UserAgent string `json:"useragent,omitempty"`
Version string `json:"version,omitempty"`
Features []string `json:"features,omitempty"`
}
type BackendServerInfoNats struct {

View file

@ -93,7 +93,7 @@ func (m *ProxyClientMessage) CheckValid() error {
return nil
}
func (m *ProxyClientMessage) NewErrorServerMessage(e *Error) *ProxyServerMessage {
func (m *ProxyClientMessage) NewErrorServerMessage(e *api.Error) *ProxyServerMessage {
return &ProxyServerMessage{
Id: m.Id,
Type: "error",
@ -102,7 +102,7 @@ func (m *ProxyClientMessage) NewErrorServerMessage(e *Error) *ProxyServerMessage
}
func (m *ProxyClientMessage) NewWrappedErrorServerMessage(e error) *ProxyServerMessage {
return m.NewErrorServerMessage(NewError("internal_error", e.Error()))
return m.NewErrorServerMessage(api.NewError("internal_error", e.Error()))
}
// ProxyServerMessage is a message that is sent from the server to a client.
@ -114,7 +114,7 @@ type ProxyServerMessage struct {
Type string `json:"type"`
Error *Error `json:"error,omitempty"`
Error *api.Error `json:"error,omitempty"`
Hello *HelloProxyServerMessage `json:"hello,omitempty"`
@ -135,7 +135,7 @@ func (r *ProxyServerMessage) String() string {
return string(data)
}
func (r *ProxyServerMessage) CloseAfterSend(session Session) bool {
func (r *ProxyServerMessage) CloseAfterSend(session api.RoomAware) bool {
switch r.Type {
case "bye":
return true
@ -153,7 +153,7 @@ type TokenClaims struct {
type HelloProxyClientMessage struct {
Version string `json:"version"`
ResumeId PublicSessionId `json:"resumeid"`
ResumeId api.PublicSessionId `json:"resumeid"`
Features []string `json:"features,omitempty"`
@ -162,7 +162,7 @@ type HelloProxyClientMessage struct {
}
func (m *HelloProxyClientMessage) CheckValid() error {
if m.Version != HelloVersionV1 {
if m.Version != api.HelloVersionV1 {
return fmt.Errorf("unsupported hello version: %s", m.Version)
}
if m.ResumeId == "" {
@ -176,8 +176,8 @@ func (m *HelloProxyClientMessage) CheckValid() error {
type HelloProxyServerMessage struct {
Version string `json:"version"`
SessionId PublicSessionId `json:"sessionid"`
Server *WelcomeServerMessage `json:"server,omitempty"`
SessionId api.PublicSessionId `json:"sessionid"`
Server *api.WelcomeServerMessage `json:"server,omitempty"`
}
// Type "bye"
@ -209,10 +209,10 @@ type NewPublisherSettings struct {
type CommandProxyClientMessage struct {
Type string `json:"type"`
Sid string `json:"sid,omitempty"`
StreamType StreamType `json:"streamType,omitempty"`
PublisherId PublicSessionId `json:"publisherId,omitempty"`
ClientId string `json:"clientId,omitempty"`
Sid string `json:"sid,omitempty"`
StreamType StreamType `json:"streamType,omitempty"`
PublisherId api.PublicSessionId `json:"publisherId,omitempty"`
ClientId string `json:"clientId,omitempty"`
// Deprecated: use PublisherSettings instead.
Bitrate api.Bandwidth `json:"bitrate,omitempty"`

View file

@ -25,6 +25,7 @@ import (
"context"
"errors"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/nats"
)
@ -55,13 +56,13 @@ type AsyncEvents interface {
RegisterUserListener(userId string, backend *Backend, listener AsyncEventListener) error
UnregisterUserListener(userId string, backend *Backend, listener AsyncEventListener) error
RegisterSessionListener(sessionId PublicSessionId, backend *Backend, listener AsyncEventListener) error
UnregisterSessionListener(sessionId PublicSessionId, backend *Backend, listener AsyncEventListener) error
RegisterSessionListener(sessionId api.PublicSessionId, backend *Backend, listener AsyncEventListener) error
UnregisterSessionListener(sessionId api.PublicSessionId, backend *Backend, listener AsyncEventListener) error
PublishBackendRoomMessage(roomId string, backend *Backend, message *AsyncMessage) error
PublishRoomMessage(roomId string, backend *Backend, message *AsyncMessage) error
PublishUserMessage(userId string, backend *Backend, message *AsyncMessage) error
PublishSessionMessage(sessionId PublicSessionId, backend *Backend, message *AsyncMessage) error
PublishSessionMessage(sessionId api.PublicSessionId, backend *Backend, message *AsyncMessage) error
}
func NewAsyncEvents(ctx context.Context, url string) (AsyncEvents, error) {

View file

@ -27,6 +27,7 @@ import (
"sync"
"time"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/nats"
)
@ -55,7 +56,7 @@ func GetSubjectForUserId(userId string, backend *Backend) string {
return nats.GetEncodedSubject("user", userId+"|"+backend.Id())
}
func GetSubjectForSessionId(sessionId PublicSessionId, backend *Backend) string {
func GetSubjectForSessionId(sessionId api.PublicSessionId, backend *Backend) string {
return string("session." + sessionId)
}
@ -242,7 +243,7 @@ func (e *asyncEventsNats) UnregisterUserListener(roomId string, backend *Backend
return e.unregisterListener(key, e.userSubscriptions, listener)
}
func (e *asyncEventsNats) RegisterSessionListener(sessionId PublicSessionId, backend *Backend, listener AsyncEventListener) error {
func (e *asyncEventsNats) RegisterSessionListener(sessionId api.PublicSessionId, backend *Backend, listener AsyncEventListener) error {
key := GetSubjectForSessionId(sessionId, backend)
e.mu.Lock()
@ -251,7 +252,7 @@ func (e *asyncEventsNats) RegisterSessionListener(sessionId PublicSessionId, bac
return e.registerListener(key, e.sessionSubscriptions, listener)
}
func (e *asyncEventsNats) UnregisterSessionListener(sessionId PublicSessionId, backend *Backend, listener AsyncEventListener) error {
func (e *asyncEventsNats) UnregisterSessionListener(sessionId api.PublicSessionId, backend *Backend, listener AsyncEventListener) error {
key := GetSubjectForSessionId(sessionId, backend)
e.mu.Lock()
@ -280,7 +281,7 @@ func (e *asyncEventsNats) PublishUserMessage(userId string, backend *Backend, me
return e.publish(subject, message)
}
func (e *asyncEventsNats) PublishSessionMessage(sessionId PublicSessionId, backend *Backend, message *AsyncMessage) error {
func (e *asyncEventsNats) PublishSessionMessage(sessionId api.PublicSessionId, backend *Backend, message *AsyncMessage) error {
subject := GetSubjectForSessionId(sessionId, backend)
return e.publish(subject, message)
}

View file

@ -44,7 +44,7 @@ const (
)
var (
SessionLimitExceeded = NewError("session_limit_exceeded", "Too many sessions connected for this backend.")
SessionLimitExceeded = api.NewError("session_limit_exceeded", "Too many sessions connected for this backend.")
)
type Backend struct {
@ -60,7 +60,7 @@ type Backend struct {
sessionLimit uint64
sessionsLock sync.Mutex
// +checklocks:sessionsLock
sessions map[PublicSessionId]bool
sessions map[api.PublicSessionId]bool
counted bool
}
@ -134,7 +134,7 @@ func (b *Backend) Len() int {
}
func (b *Backend) AddSession(session Session) error {
if session.ClientType() == HelloClientTypeInternal || session.ClientType() == HelloClientTypeVirtual {
if session.ClientType() == api.HelloClientTypeInternal || session.ClientType() == api.HelloClientTypeVirtual {
// Internal and virtual sessions are not counting to the limit.
return nil
}
@ -147,7 +147,7 @@ func (b *Backend) AddSession(session Session) error {
b.sessionsLock.Lock()
defer b.sessionsLock.Unlock()
if b.sessions == nil {
b.sessions = make(map[PublicSessionId]bool)
b.sessions = make(map[api.PublicSessionId]bool)
} else if uint64(len(b.sessions)) >= b.sessionLimit {
statsBackendLimitExceededTotal.WithLabelValues(b.id).Inc()
return SessionLimitExceeded

View file

@ -61,7 +61,7 @@ const (
randomUsernameLength = 32
sessionIdNotInMeeting = RoomSessionId("0")
sessionIdNotInMeeting = api.RoomSessionId("0")
startDialoutTimeout = 45 * time.Second
)
@ -329,12 +329,12 @@ func (b *BackendServer) parseRequestBody(f func(context.Context, http.ResponseWr
func (b *BackendServer) sendRoomInvite(roomid string, backend *Backend, userids []string, properties json.RawMessage) {
msg := &AsyncMessage{
Type: "message",
Message: &ServerMessage{
Message: &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "roomlist",
Type: "invite",
Invite: &RoomEventServerMessage{
Invite: &api.RoomEventServerMessage{
RoomId: roomid,
Properties: properties,
},
@ -348,16 +348,16 @@ func (b *BackendServer) sendRoomInvite(roomid string, backend *Backend, userids
}
}
func (b *BackendServer) sendRoomDisinvite(roomid string, backend *Backend, reason string, userids []string, sessionids []RoomSessionId) {
func (b *BackendServer) sendRoomDisinvite(roomid string, backend *Backend, reason string, userids []string, sessionids []api.RoomSessionId) {
msg := &AsyncMessage{
Type: "message",
Message: &ServerMessage{
Message: &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "roomlist",
Type: "disinvite",
Disinvite: &RoomDisinviteEventServerMessage{
RoomEventServerMessage: RoomEventServerMessage{
Disinvite: &api.RoomDisinviteEventServerMessage{
RoomEventServerMessage: api.RoomEventServerMessage{
RoomId: roomid,
},
Reason: reason,
@ -383,7 +383,7 @@ func (b *BackendServer) sendRoomDisinvite(roomid string, backend *Backend, reaso
}
wg.Add(1)
go func(sessionid RoomSessionId) {
go func(sessionid api.RoomSessionId) {
defer wg.Done()
if sid, err := b.lookupByRoomSessionId(ctx, sessionid, nil); err != nil {
b.logger.Printf("Could not lookup by room session %s: %s", sessionid, err)
@ -400,12 +400,12 @@ func (b *BackendServer) sendRoomDisinvite(roomid string, backend *Backend, reaso
func (b *BackendServer) sendRoomUpdate(roomid string, backend *Backend, notified_userids []string, all_userids []string, properties json.RawMessage) {
msg := &AsyncMessage{
Type: "message",
Message: &ServerMessage{
Message: &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "roomlist",
Type: "update",
Update: &RoomEventServerMessage{
Update: &api.RoomEventServerMessage{
RoomId: roomid,
Properties: properties,
},
@ -428,7 +428,7 @@ func (b *BackendServer) sendRoomUpdate(roomid string, backend *Backend, notified
}
}
func (b *BackendServer) lookupByRoomSessionId(ctx context.Context, roomSessionId RoomSessionId, cache *container.ConcurrentMap[RoomSessionId, PublicSessionId]) (PublicSessionId, error) {
func (b *BackendServer) lookupByRoomSessionId(ctx context.Context, roomSessionId api.RoomSessionId, cache *container.ConcurrentMap[api.RoomSessionId, api.PublicSessionId]) (api.PublicSessionId, error) {
if roomSessionId == sessionIdNotInMeeting {
b.logger.Printf("Trying to lookup empty room session id: %s", roomSessionId)
return "", nil
@ -453,14 +453,14 @@ func (b *BackendServer) lookupByRoomSessionId(ctx context.Context, roomSessionId
return sid, nil
}
func (b *BackendServer) fixupUserSessions(ctx context.Context, cache *container.ConcurrentMap[RoomSessionId, PublicSessionId], users []api.StringMap) []api.StringMap {
func (b *BackendServer) fixupUserSessions(ctx context.Context, cache *container.ConcurrentMap[api.RoomSessionId, api.PublicSessionId], users []api.StringMap) []api.StringMap {
if len(users) == 0 {
return users
}
var wg sync.WaitGroup
for _, user := range users {
roomSessionId, found := api.GetStringMapString[RoomSessionId](user, "sessionId")
roomSessionId, found := api.GetStringMapString[api.RoomSessionId](user, "sessionId")
if !found {
b.logger.Printf("User %+v has invalid room session id, ignoring", user)
delete(user, "sessionId")
@ -474,7 +474,7 @@ func (b *BackendServer) fixupUserSessions(ctx context.Context, cache *container.
}
wg.Add(1)
go func(roomSessionId RoomSessionId, u api.StringMap) {
go func(roomSessionId api.RoomSessionId, u api.StringMap) {
defer wg.Done()
if sessionId, err := b.lookupByRoomSessionId(ctx, roomSessionId, cache); err != nil {
b.logger.Printf("Could not lookup by room session %s: %s", roomSessionId, err)
@ -505,7 +505,7 @@ func (b *BackendServer) sendRoomIncall(roomid string, backend *Backend, request
ctx := log.NewLoggerContext(context.Background(), b.logger)
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
var cache container.ConcurrentMap[RoomSessionId, PublicSessionId]
var cache container.ConcurrentMap[api.RoomSessionId, api.PublicSessionId]
// Convert (Nextcloud) session ids to signaling session ids.
request.InCall.Users = b.fixupUserSessions(ctx, &cache, request.InCall.Users)
// Entries in "Changed" are most likely already fetched through the "Users" list.
@ -529,7 +529,7 @@ func (b *BackendServer) sendRoomParticipantsUpdate(ctx context.Context, roomid s
// Convert (Nextcloud) session ids to signaling session ids.
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
var cache container.ConcurrentMap[RoomSessionId, PublicSessionId]
var cache container.ConcurrentMap[api.RoomSessionId, api.PublicSessionId]
request.Participants.Users = b.fixupUserSessions(ctx, &cache, request.Participants.Users)
request.Participants.Changed = b.fixupUserSessions(ctx, &cache, request.Participants.Changed)
@ -545,7 +545,7 @@ loop:
continue
}
sessionId, found := api.GetStringMapString[PublicSessionId](user, "sessionId")
sessionId, found := api.GetStringMapString[api.PublicSessionId](user, "sessionId")
if !found {
b.logger.Printf("User entry has no session id: %+v", user)
continue
@ -567,7 +567,7 @@ loop:
}
wg.Add(1)
go func(sessionId PublicSessionId, permissions []Permission) {
go func(sessionId api.PublicSessionId, permissions []Permission) {
defer wg.Done()
message := &AsyncMessage{
Type: "permissions",
@ -623,7 +623,7 @@ func (b *BackendServer) sendRoomSwitchTo(ctx context.Context, roomid string, bac
}
wg.Add(1)
go func(roomSessionId RoomSessionId) {
go func(roomSessionId api.RoomSessionId) {
defer wg.Done()
if sessionId, err := b.lookupByRoomSessionId(ctx, roomSessionId, nil); err != nil {
b.logger.Printf("Could not lookup by room session %s: %s", roomSessionId, err)
@ -661,7 +661,7 @@ func (b *BackendServer) sendRoomSwitchTo(ctx context.Context, roomid string, bac
}
wg.Add(1)
go func(roomSessionId RoomSessionId, details json.RawMessage) {
go func(roomSessionId api.RoomSessionId, details json.RawMessage) {
defer wg.Done()
if sessionId, err := b.lookupByRoomSessionId(ctx, roomSessionId, nil); err != nil {
b.logger.Printf("Could not lookup by room session %s: %s", roomSessionId, err)
@ -707,7 +707,7 @@ func (r *DialoutErrorResponse) Status() int {
return r.status
}
func returnDialoutError(status int, err *Error) (any, error) {
func returnDialoutError(status int, err *api.Error) (any, error) {
response := &DialoutErrorResponse{
BackendServerRoomResponse: BackendServerRoomResponse{
Type: "dialout",
@ -741,15 +741,18 @@ func (b *BackendServer) startDialoutInSession(ctx context.Context, session *Clie
}
}
id := newRandomString(32)
msg := &ServerMessage{
msg := &api.ServerMessage{
Id: id,
Type: "internal",
Internal: &InternalServerMessage{
Internal: &api.InternalServerMessage{
Type: "dialout",
Dialout: &InternalServerDialoutRequest{
Dialout: &api.InternalServerDialoutRequest{
RoomId: roomid,
Backend: url,
Request: request.Dialout,
Request: &api.InternalServerDialoutRequestContents{
Number: request.Dialout.Number,
Options: request.Dialout.Options,
},
},
},
}
@ -757,9 +760,9 @@ func (b *BackendServer) startDialoutInSession(ctx context.Context, session *Clie
subCtx, cancel := context.WithTimeout(ctx, startDialoutTimeout)
defer cancel()
var response atomic.Pointer[DialoutInternalClientMessage]
var response atomic.Pointer[api.DialoutInternalClientMessage]
session.HandleResponse(id, func(message *ClientMessage) bool {
session.HandleResponse(id, func(message *api.ClientMessage) bool {
response.Store(message.Internal.Dialout)
cancel()
// Don't send error to other sessions in the room.
@ -768,13 +771,13 @@ func (b *BackendServer) startDialoutInSession(ctx context.Context, session *Clie
defer session.ClearResponseHandler(id)
if !session.SendMessage(msg) {
return nil, NewError("error_notify", "Could not notify about new dialout.")
return nil, api.NewError("error_notify", "Could not notify about new dialout.")
}
<-subCtx.Done()
if err := subCtx.Err(); err != nil {
if errors.Is(err, context.DeadlineExceeded) {
return nil, NewError("timeout", "Timeout while waiting for dialout to start.")
return nil, api.NewError("timeout", "Timeout while waiting for dialout to start.")
} else if errors.Is(err, context.Canceled) && errors.Is(ctx.Err(), context.Canceled) {
// Upstream request was cancelled.
return nil, err
@ -783,15 +786,15 @@ func (b *BackendServer) startDialoutInSession(ctx context.Context, session *Clie
dialout := response.Load()
if dialout == nil {
return nil, NewError("error_notify", "No dialout response received.")
return nil, api.NewError("error_notify", "No dialout response received.")
}
switch dialout.Type {
case "error":
return nil, dialout.Error
case "status":
if dialout.Status.Status != DialoutStatusAccepted {
return nil, NewError("unsupported_status", fmt.Sprintf("Unsupported dialout status received: %+v", dialout))
if dialout.Status.Status != api.DialoutStatusAccepted {
return nil, api.NewError("unsupported_status", fmt.Sprintf("Unsupported dialout status received: %+v", dialout))
}
return &BackendServerRoomResponse{
@ -801,7 +804,7 @@ func (b *BackendServer) startDialoutInSession(ctx context.Context, session *Clie
},
}, nil
default:
return nil, NewError("unsupported_type", fmt.Sprintf("Unsupported dialout type received: %+v", dialout))
return nil, api.NewError("unsupported_type", fmt.Sprintf("Unsupported dialout type received: %+v", dialout))
}
}
@ -811,10 +814,10 @@ func (b *BackendServer) startDialout(ctx context.Context, roomid string, backend
}
if !isNumeric(roomid) {
return returnDialoutError(http.StatusBadRequest, NewError("invalid_roomid", "The room id must be numeric."))
return returnDialoutError(http.StatusBadRequest, api.NewError("invalid_roomid", "The room id must be numeric."))
}
var sessionError *Error
var sessionError *api.Error
sessions := b.hub.GetDialoutSessions(roomid, backend)
for _, session := range sessions {
if ctx.Err() != nil {
@ -825,7 +828,7 @@ func (b *BackendServer) startDialout(ctx context.Context, roomid string, backend
response, err := b.startDialoutInSession(ctx, session, roomid, backend, backendUrl, request)
if err != nil {
b.logger.Printf("Error starting dialout request %+v in session %s: %+v", request.Dialout, session.PublicId(), err)
var e *Error
var e *api.Error
if sessionError == nil && errors.As(err, &e) {
sessionError = e
}
@ -839,7 +842,7 @@ func (b *BackendServer) startDialout(ctx context.Context, roomid string, backend
return returnDialoutError(http.StatusBadGateway, sessionError)
}
return returnDialoutError(http.StatusNotFound, NewError("no_client_available", "No available client found to trigger dialout."))
return returnDialoutError(http.StatusNotFound, api.NewError("no_client_available", "No available client found to trigger dialout."))
}
func (b *BackendServer) roomHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, body []byte) {
@ -914,7 +917,7 @@ func (b *BackendServer) roomHandler(ctx context.Context, w http.ResponseWriter,
b.sendRoomInvite(roomid, backend, request.Invite.UserIds, request.Invite.Properties)
b.sendRoomUpdate(roomid, backend, request.Invite.UserIds, request.Invite.AllUserIds, request.Invite.Properties)
case "disinvite":
b.sendRoomDisinvite(roomid, backend, DisinviteReasonDisinvited, request.Disinvite.UserIds, request.Disinvite.SessionIds)
b.sendRoomDisinvite(roomid, backend, api.DisinviteReasonDisinvited, request.Disinvite.UserIds, request.Disinvite.SessionIds)
b.sendRoomUpdate(roomid, backend, request.Disinvite.UserIds, request.Disinvite.AllUserIds, request.Disinvite.Properties)
case "update":
message := &AsyncMessage{
@ -929,7 +932,7 @@ func (b *BackendServer) roomHandler(ctx context.Context, w http.ResponseWriter,
Room: &request,
}
err = b.events.PublishBackendRoomMessage(roomid, backend, message)
b.sendRoomDisinvite(roomid, backend, DisinviteReasonDeleted, request.Delete.UserIds, nil)
b.sendRoomDisinvite(roomid, backend, api.DisinviteReasonDeleted, request.Delete.UserIds, nil)
case "incall":
err = b.sendRoomIncall(roomid, backend, &request)
case "participants":

View file

@ -242,7 +242,7 @@ func performBackendRequest(requestUrl string, body []byte) (*http.Response, erro
return client.Do(request)
}
func expectRoomlistEvent(t *testing.T, ch AsyncChannel, msgType string) (*EventServerMessage, bool) {
func expectRoomlistEvent(t *testing.T, ch AsyncChannel, msgType string) (*api.EventServerMessage, bool) {
assert := assert.New(t)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
@ -515,8 +515,8 @@ func RunTestBackendServer_RoomDisinvite(ctx context.Context, t *testing.T) {
UserIds: []string{
testDefaultUserId,
},
SessionIds: []RoomSessionId{
RoomSessionId(fmt.Sprintf("%s-%s"+roomId, hello.Hello.SessionId)),
SessionIds: []api.RoomSessionId{
api.RoomSessionId(fmt.Sprintf("%s-%s"+roomId, hello.Hello.SessionId)),
},
AllUserIds: []string{},
Properties: roomProperties,
@ -575,8 +575,8 @@ func TestBackendServer_RoomDisinviteDifferentRooms(t *testing.T) {
UserIds: []string{
testDefaultUserId,
},
SessionIds: []RoomSessionId{
RoomSessionId(fmt.Sprintf("%s-%s"+roomId1, hello1.Hello.SessionId)),
SessionIds: []api.RoomSessionId{
api.RoomSessionId(fmt.Sprintf("%s-%s"+roomId1, hello1.Hello.SessionId)),
},
AllUserIds: []string{},
},
@ -1517,15 +1517,15 @@ func TestBackendServer_DialoutAccepted(t *testing.T) {
assert.Equal(roomId, msg.Internal.Dialout.RoomId)
assert.Equal(server.URL+"/", msg.Internal.Dialout.Backend)
response := &ClientMessage{
response := &api.ClientMessage{
Id: msg.Id,
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "dialout",
Dialout: &DialoutInternalClientMessage{
Dialout: &api.DialoutInternalClientMessage{
Type: "status",
RoomId: msg.Internal.Dialout.RoomId,
Status: &DialoutStatusInternalClientMessage{
Status: &api.DialoutStatusInternalClientMessage{
Status: "accepted",
CallId: callId,
},
@ -1604,15 +1604,15 @@ func TestBackendServer_DialoutAcceptedCompat(t *testing.T) {
assert.Equal(roomId, msg.Internal.Dialout.RoomId)
assert.Equal(server.URL+"/", msg.Internal.Dialout.Backend)
response := &ClientMessage{
response := &api.ClientMessage{
Id: msg.Id,
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "dialout",
Dialout: &DialoutInternalClientMessage{
Dialout: &api.DialoutInternalClientMessage{
Type: "status",
RoomId: msg.Internal.Dialout.RoomId,
Status: &DialoutStatusInternalClientMessage{
Status: &api.DialoutStatusInternalClientMessage{
Status: "accepted",
CallId: callId,
},
@ -1692,14 +1692,14 @@ func TestBackendServer_DialoutRejected(t *testing.T) {
assert.Equal(roomId, msg.Internal.Dialout.RoomId)
assert.Equal(server.URL+"/", msg.Internal.Dialout.Backend)
response := &ClientMessage{
response := &api.ClientMessage{
Id: msg.Id,
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "dialout",
Dialout: &DialoutInternalClientMessage{
Dialout: &api.DialoutInternalClientMessage{
Type: "error",
Error: NewError(errorCode, errorMessage),
Error: api.NewError(errorCode, errorMessage),
},
},
}
@ -1783,31 +1783,31 @@ func TestBackendServer_DialoutFirstFailed(t *testing.T) {
assert.Equal(roomId, msg.Internal.Dialout.RoomId)
assert.Equal(server.URL+"/", msg.Internal.Dialout.Backend)
var dialout *DialoutInternalClientMessage
var dialout *api.DialoutInternalClientMessage
// The first session should return an error to make sure the second is retried afterwards.
if returnedError.CompareAndSwap(false, true) {
errorCode := "error-code"
errorMessage := "rejected call"
dialout = &DialoutInternalClientMessage{
dialout = &api.DialoutInternalClientMessage{
Type: "error",
Error: NewError(errorCode, errorMessage),
Error: api.NewError(errorCode, errorMessage),
}
} else {
dialout = &DialoutInternalClientMessage{
dialout = &api.DialoutInternalClientMessage{
Type: "status",
RoomId: msg.Internal.Dialout.RoomId,
Status: &DialoutStatusInternalClientMessage{
Status: &api.DialoutStatusInternalClientMessage{
Status: "accepted",
CallId: callId,
},
}
}
response := &ClientMessage{
response := &api.ClientMessage{
Id: msg.Id,
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "dialout",
Dialout: dialout,
},

View file

@ -37,6 +37,7 @@ import (
"github.com/gorilla/websocket"
"github.com/mailru/easyjson"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/internal"
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/pool"
@ -84,7 +85,7 @@ func IsValidCountry(country string) bool {
}
var (
InvalidFormat = NewError("invalid_format", "Invalid data format.")
InvalidFormat = api.NewError("invalid_format", "Invalid data format.")
bufferPool pool.BufferPool
)
@ -92,7 +93,7 @@ var (
type WritableClientMessage interface {
json.Marshaler
CloseAfterSend(session Session) bool
CloseAfterSend(session api.RoomAware) bool
}
type HandlerClient interface {
@ -106,9 +107,9 @@ type HandlerClient interface {
GetSession() Session
SetSession(session Session)
SendError(e *Error) bool
SendByeResponse(message *ClientMessage) bool
SendByeResponseWithReason(message *ClientMessage, reason string) bool
SendError(e *api.Error) bool
SendByeResponse(message *api.ClientMessage) bool
SendByeResponseWithReason(message *api.ClientMessage, reason string) bool
SendMessage(message WritableClientMessage) bool
Close()
@ -139,7 +140,7 @@ type Client struct {
handler ClientHandler
session atomic.Pointer[Session]
sessionId atomic.Pointer[PublicSessionId]
sessionId atomic.Pointer[api.PublicSessionId]
mu sync.Mutex
@ -219,11 +220,11 @@ func (c *Client) SetSession(session Session) {
}
}
func (c *Client) SetSessionId(sessionId PublicSessionId) {
func (c *Client) SetSessionId(sessionId api.PublicSessionId) {
c.sessionId.Store(&sessionId)
}
func (c *Client) GetSessionId() PublicSessionId {
func (c *Client) GetSessionId() api.PublicSessionId {
sessionId := c.sessionId.Load()
if sessionId == nil {
session := c.GetSession()
@ -293,20 +294,20 @@ func (c *Client) doClose() {
}
}
func (c *Client) SendError(e *Error) bool {
message := &ServerMessage{
func (c *Client) SendError(e *api.Error) bool {
message := &api.ServerMessage{
Type: "error",
Error: e,
}
return c.SendMessage(message)
}
func (c *Client) SendByeResponse(message *ClientMessage) bool {
func (c *Client) SendByeResponse(message *api.ClientMessage) bool {
return c.SendByeResponseWithReason(message, "")
}
func (c *Client) SendByeResponseWithReason(message *ClientMessage, reason string) bool {
response := &ServerMessage{
func (c *Client) SendByeResponseWithReason(message *api.ClientMessage, reason string) bool {
response := &api.ServerMessage{
Type: "bye",
}
if message != nil {
@ -314,7 +315,7 @@ func (c *Client) SendByeResponseWithReason(message *ClientMessage, reason string
}
if reason != "" {
if response.Bye == nil {
response.Bye = &ByeServerMessage{}
response.Bye = &api.ByeServerMessage{}
}
response.Bye.Reason = reason
}
@ -497,9 +498,9 @@ close:
}
func (c *Client) writeError(e error) bool { // nolint
message := &ServerMessage{
message := &api.ServerMessage{
Type: "error",
Error: NewError("internal_error", e.Error()),
Error: api.NewError("internal_error", e.Error()),
}
c.mu.Lock()
defer c.mu.Unlock()

View file

@ -48,6 +48,7 @@ import (
"github.com/mailru/easyjson/jwriter"
signaling "github.com/strukturag/nextcloud-spreed-signaling"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/internal"
"github.com/strukturag/nextcloud-spreed-signaling/talk"
)
@ -138,9 +139,9 @@ type SignalingClient struct {
lock sync.Mutex
// +checklocks:lock
privateSessionId signaling.PrivateSessionId
privateSessionId api.PrivateSessionId
// +checklocks:lock
publicSessionId signaling.PublicSessionId
publicSessionId api.PublicSessionId
// +checklocks:lock
userId string
}
@ -183,9 +184,9 @@ func (c *SignalingClient) Close() {
c.lock.Lock()
c.publicSessionId = ""
c.privateSessionId = ""
c.writeInternal(&signaling.ClientMessage{
c.writeInternal(&api.ClientMessage{
Type: "bye",
Bye: &signaling.ByeClientMessage{},
Bye: &api.ByeClientMessage{},
})
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) // nolint
@ -194,7 +195,7 @@ func (c *SignalingClient) Close() {
c.lock.Unlock()
}
func (c *SignalingClient) Send(message *signaling.ClientMessage) {
func (c *SignalingClient) Send(message *api.ClientMessage) {
c.lock.Lock()
if c.conn == nil {
c.lock.Unlock()
@ -209,7 +210,7 @@ func (c *SignalingClient) Send(message *signaling.ClientMessage) {
c.lock.Unlock()
}
func (c *SignalingClient) processMessage(message *signaling.ServerMessage) {
func (c *SignalingClient) processMessage(message *api.ServerMessage) {
c.stats.numRecvMessages.Add(1)
switch message.Type {
case "welcome":
@ -229,7 +230,7 @@ func (c *SignalingClient) processMessage(message *signaling.ServerMessage) {
}
}
func (c *SignalingClient) processHelloMessage(message *signaling.ServerMessage) {
func (c *SignalingClient) processHelloMessage(message *api.ServerMessage) {
c.lock.Lock()
defer c.lock.Unlock()
c.privateSessionId = message.Hello.ResumeId
@ -239,13 +240,13 @@ func (c *SignalingClient) processHelloMessage(message *signaling.ServerMessage)
c.readyWg.Done()
}
func (c *SignalingClient) PublicSessionId() signaling.PublicSessionId {
func (c *SignalingClient) PublicSessionId() api.PublicSessionId {
c.lock.Lock()
defer c.lock.Unlock()
return c.publicSessionId
}
func (c *SignalingClient) processMessageMessage(message *signaling.ServerMessage) {
func (c *SignalingClient) processMessageMessage(message *api.ServerMessage) {
var msg MessagePayload
if err := msg.UnmarshalJSON(message.Message.Data); err != nil {
log.Println("Error in unmarshal", err)
@ -304,7 +305,7 @@ func (c *SignalingClient) readPump() {
c.stats.numRecvBytes.Add(uint64(decodeBuffer.Len()))
var message signaling.ServerMessage
var message api.ServerMessage
if err := message.UnmarshalJSON(decodeBuffer.Bytes()); err != nil {
log.Printf("Error: %v", err)
break
@ -314,7 +315,7 @@ func (c *SignalingClient) readPump() {
}
}
func (c *SignalingClient) writeInternal(message *signaling.ClientMessage) bool {
func (c *SignalingClient) writeInternal(message *api.ClientMessage) bool {
var closeData []byte
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
@ -383,7 +384,7 @@ func (c *SignalingClient) writePump() {
}
func (c *SignalingClient) SendMessages(clients []*SignalingClient) {
sessionIds := make(map[*SignalingClient]signaling.PublicSessionId)
sessionIds := make(map[*SignalingClient]api.PublicSessionId)
for _, c := range clients {
sessionIds[c] = c.PublicSessionId()
}
@ -402,10 +403,10 @@ func (c *SignalingClient) SendMessages(clients []*SignalingClient) {
Now: now,
}
data, _ := msgdata.MarshalJSON()
msg := &signaling.ClientMessage{
msg := &api.ClientMessage{
Type: "message",
Message: &signaling.MessageClientMessage{
Recipient: signaling.MessageClientMessageRecipient{
Message: &api.MessageClientMessage{
Recipient: api.MessageClientMessageRecipient{
Type: "session",
SessionId: sessionIds[recipient],
},
@ -599,11 +600,11 @@ func main() {
defer client.Close()
readyWg.Add(1)
request := &signaling.ClientMessage{
request := &api.ClientMessage{
Type: "hello",
Hello: &signaling.HelloClientMessage{
Version: signaling.HelloVersionV1,
Auth: &signaling.HelloClientMessageAuth{
Hello: &api.HelloClientMessage{
Version: api.HelloVersionV1,
Auth: &api.HelloClientMessageAuth{
Url: backendUrl,
Params: json.RawMessage("{}"),
},

View file

@ -50,24 +50,20 @@ var (
PathToOcsSignalingBackend = "ocs/v2.php/apps/spreed/api/v1/signaling/backend"
)
const (
FederatedRoomSessionIdPrefix = "federated|"
)
// ResponseHandlerFunc will return "true" has been fully processed.
type ResponseHandlerFunc func(message *ClientMessage) bool
type ResponseHandlerFunc func(message *api.ClientMessage) bool
type ClientSession struct {
logger log.Logger
hub *Hub
events AsyncEvents
privateId PrivateSessionId
publicId PublicSessionId
privateId api.PrivateSessionId
publicId api.PublicSessionId
data *SessionIdData
ctx context.Context
closeFunc context.CancelFunc
clientType ClientType
clientType api.ClientType
features []string
userId string
userData json.RawMessage
@ -95,7 +91,7 @@ type ClientSession struct {
roomSessionIdLock sync.RWMutex
// +checklocks:roomSessionIdLock
roomSessionId RoomSessionId
roomSessionId api.RoomSessionId
publisherWaiters async.ChannelWaiters // +checklocksignore
@ -105,7 +101,7 @@ type ClientSession struct {
subscribers map[StreamId]McuSubscriber
// +checklocks:mu
pendingClientMessages []*ServerMessage
pendingClientMessages []*api.ServerMessage
// +checklocks:mu
hasPendingChat bool
// +checklocks:mu
@ -116,14 +112,14 @@ type ClientSession struct {
seenJoinedLock sync.Mutex
// +checklocks:seenJoinedLock
seenJoinedEvents map[PublicSessionId]bool
seenJoinedEvents map[api.PublicSessionId]bool
responseHandlersLock sync.Mutex
// +checklocks:responseHandlersLock
responseHandlers map[string]ResponseHandlerFunc
}
func NewClientSession(hub *Hub, privateId PrivateSessionId, publicId PublicSessionId, data *SessionIdData, backend *Backend, hello *HelloClientMessage, auth *BackendClientAuthResponse) (*ClientSession, error) {
func NewClientSession(hub *Hub, privateId api.PrivateSessionId, publicId api.PublicSessionId, data *SessionIdData, backend *Backend, hello *api.HelloClientMessage, auth *BackendClientAuthResponse) (*ClientSession, error) {
ctx := log.NewLoggerContext(context.Background(), hub.logger)
ctx, closeFunc := context.WithCancel(ctx)
s := &ClientSession{
@ -145,15 +141,15 @@ func NewClientSession(hub *Hub, privateId PrivateSessionId, publicId PublicSessi
backend: backend,
asyncCh: make(AsyncChannel, DefaultAsyncChannelSize),
}
if s.clientType == HelloClientTypeInternal {
s.backendUrl = hello.Auth.internalParams.Backend
s.parsedBackendUrl = hello.Auth.internalParams.parsedBackend
if !s.HasFeature(ClientFeatureInternalInCall) {
if s.clientType == api.HelloClientTypeInternal {
s.backendUrl = hello.Auth.InternalParams.Backend
s.parsedBackendUrl = hello.Auth.InternalParams.ParsedBackend
if !s.HasFeature(api.ClientFeatureInternalInCall) {
s.SetInCall(FlagInCall | FlagWithAudio)
}
} else {
s.backendUrl = hello.Auth.Url
s.parsedBackendUrl = hello.Auth.parsedUrl
s.parsedBackendUrl = hello.Auth.ParsedUrl
}
if err := s.SubscribeEvents(); err != nil {
@ -167,15 +163,15 @@ func (s *ClientSession) Context() context.Context {
return s.ctx
}
func (s *ClientSession) PrivateId() PrivateSessionId {
func (s *ClientSession) PrivateId() api.PrivateSessionId {
return s.privateId
}
func (s *ClientSession) PublicId() PublicSessionId {
func (s *ClientSession) PublicId() api.PublicSessionId {
return s.publicId
}
func (s *ClientSession) RoomSessionId() RoomSessionId {
func (s *ClientSession) RoomSessionId() api.RoomSessionId {
s.roomSessionIdLock.RLock()
defer s.roomSessionIdLock.RUnlock()
return s.roomSessionId
@ -185,7 +181,7 @@ func (s *ClientSession) Data() *SessionIdData {
return s.data
}
func (s *ClientSession) ClientType() ClientType {
func (s *ClientSession) ClientType() api.ClientType {
return s.clientType
}
@ -345,6 +341,11 @@ func (s *ClientSession) onRoomSet(hasRoom bool) {
s.seenJoinedEvents = nil
}
func (s *ClientSession) IsInRoom(id string) bool {
room := s.GetRoom()
return room != nil && room.Id() == id
}
func (s *ClientSession) GetFederationClient() *FederationClient {
return s.federation.Load()
}
@ -460,7 +461,7 @@ func (s *ClientSession) SubscribeEvents() error {
return s.events.RegisterSessionListener(s.publicId, s.backend, s)
}
func (s *ClientSession) UpdateRoomSessionId(roomSessionId RoomSessionId) error {
func (s *ClientSession) UpdateRoomSessionId(roomSessionId api.RoomSessionId) error {
s.roomSessionIdLock.Lock()
defer s.roomSessionIdLock.Unlock()
@ -494,7 +495,7 @@ func (s *ClientSession) UpdateRoomSessionId(roomSessionId RoomSessionId) error {
return nil
}
func (s *ClientSession) SubscribeRoomEvents(roomid string, roomSessionId RoomSessionId) error {
func (s *ClientSession) SubscribeRoomEvents(roomid string, roomSessionId api.RoomSessionId) error {
s.roomSessionIdLock.Lock()
defer s.roomSessionIdLock.Unlock()
@ -530,7 +531,7 @@ func (s *ClientSession) LeaveRoom(notify bool) *Room {
return s.LeaveRoomWithMessage(notify, nil)
}
func (s *ClientSession) LeaveRoomWithMessage(notify bool, message *ClientMessage) *Room {
func (s *ClientSession) LeaveRoomWithMessage(notify bool, message *api.ClientMessage) *Room {
if prev := s.federation.Swap(nil); prev != nil {
// Session was connected to a federation room.
if err := prev.Leave(message); err != nil {
@ -580,7 +581,7 @@ func (s *ClientSession) doUnsubscribeRoomEvents(notify bool) {
defer s.roomSessionIdLock.Unlock()
if notify && room != nil && s.roomSessionId != "" && !s.roomSessionId.IsFederated() {
// Notify
go func(sid RoomSessionId) {
go func(sid api.RoomSessionId) {
ctx := log.NewLoggerContext(context.Background(), s.logger)
request := NewBackendClientRoomRequest(room.Id(), s.userId, sid)
request.Room.UpdateFromSession(s)
@ -652,8 +653,8 @@ func (s *ClientSession) SetClient(client HandlerClient) HandlerClient {
}
// +checklocks:s.mu
func (s *ClientSession) sendOffer(client McuClient, sender PublicSessionId, streamType StreamType, offer api.StringMap) {
offer_message := &AnswerOfferMessage{
func (s *ClientSession) sendOffer(client McuClient, sender api.PublicSessionId, streamType StreamType, offer api.StringMap) {
offer_message := &api.AnswerOfferMessage{
To: s.PublicId(),
From: sender,
Type: "offer",
@ -666,10 +667,10 @@ func (s *ClientSession) sendOffer(client McuClient, sender PublicSessionId, stre
s.logger.Println("Could not serialize offer", offer_message, err)
return
}
response_message := &ServerMessage{
response_message := &api.ServerMessage{
Type: "message",
Message: &MessageServerMessage{
Sender: &MessageServerMessageSender{
Message: &api.MessageServerMessage{
Sender: &api.MessageServerMessageSender{
Type: "session",
SessionId: sender,
},
@ -681,8 +682,8 @@ func (s *ClientSession) sendOffer(client McuClient, sender PublicSessionId, stre
}
// +checklocks:s.mu
func (s *ClientSession) sendCandidate(client McuClient, sender PublicSessionId, streamType StreamType, candidate any) {
candidate_message := &AnswerOfferMessage{
func (s *ClientSession) sendCandidate(client McuClient, sender api.PublicSessionId, streamType StreamType, candidate any) {
candidate_message := &api.AnswerOfferMessage{
To: s.PublicId(),
From: sender,
Type: "candidate",
@ -697,10 +698,10 @@ func (s *ClientSession) sendCandidate(client McuClient, sender PublicSessionId,
s.logger.Println("Could not serialize candidate", candidate_message, err)
return
}
response_message := &ServerMessage{
response_message := &api.ServerMessage{
Type: "message",
Message: &MessageServerMessage{
Sender: &MessageServerMessageSender{
Message: &api.MessageServerMessage{
Sender: &api.MessageServerMessageSender{
Type: "session",
SessionId: sender,
},
@ -712,7 +713,7 @@ func (s *ClientSession) sendCandidate(client McuClient, sender PublicSessionId,
}
// +checklocks:s.mu
func (s *ClientSession) sendMessageUnlocked(message *ServerMessage) bool {
func (s *ClientSession) sendMessageUnlocked(message *api.ServerMessage) bool {
if c := s.getClientUnlocked(); c != nil {
if c.SendMessage(message) {
return true
@ -723,15 +724,15 @@ func (s *ClientSession) sendMessageUnlocked(message *ServerMessage) bool {
return true
}
func (s *ClientSession) SendError(e *Error) bool {
message := &ServerMessage{
func (s *ClientSession) SendError(e *api.Error) bool {
message := &api.ServerMessage{
Type: "error",
Error: e,
}
return s.SendMessage(message)
}
func (s *ClientSession) SendMessage(message *ServerMessage) bool {
func (s *ClientSession) SendMessage(message *api.ServerMessage) bool {
message = s.filterMessage(message)
if message == nil {
return true
@ -743,7 +744,7 @@ func (s *ClientSession) SendMessage(message *ServerMessage) bool {
return s.sendMessageUnlocked(message)
}
func (s *ClientSession) SendMessages(messages []*ServerMessage) bool {
func (s *ClientSession) SendMessages(messages []*api.ServerMessage) bool {
s.mu.Lock()
defer s.mu.Unlock()
@ -837,7 +838,7 @@ func (e *PermissionError) Error() string {
func (s *ClientSession) isSdpAllowedToSendLocked(sdp *sdp.SessionDescription) (MediaType, error) {
if sdp == nil {
// Should have already been checked when data was validated.
return 0, ErrNoSdp
return 0, api.ErrNoSdp
}
var mediaTypes MediaType
@ -862,7 +863,7 @@ func (s *ClientSession) isSdpAllowedToSendLocked(sdp *sdp.SessionDescription) (M
return mediaTypes, nil
}
func (s *ClientSession) IsAllowedToSend(data *MessageClientMessageData) error {
func (s *ClientSession) IsAllowedToSend(data *api.MessageClientMessageData) error {
s.mu.Lock()
defer s.mu.Unlock()
@ -877,7 +878,7 @@ func (s *ClientSession) IsAllowedToSend(data *MessageClientMessageData) error {
return nil
case data != nil && data.Type == "offer":
// Check what user is trying to publish and check permissions accordingly.
if _, err := s.isSdpAllowedToSendLocked(data.offerSdp); err != nil {
if _, err := s.isSdpAllowedToSendLocked(data.OfferSdp); err != nil {
return err
}
@ -892,7 +893,7 @@ func (s *ClientSession) IsAllowedToSend(data *MessageClientMessageData) error {
}
}
func (s *ClientSession) CheckOfferType(streamType StreamType, data *MessageClientMessageData) (MediaType, error) {
func (s *ClientSession) CheckOfferType(streamType StreamType, data *api.MessageClientMessageData) (MediaType, error) {
s.mu.Lock()
defer s.mu.Unlock()
@ -900,7 +901,7 @@ func (s *ClientSession) CheckOfferType(streamType StreamType, data *MessageClien
}
// +checklocks:s.mu
func (s *ClientSession) checkOfferTypeLocked(streamType StreamType, data *MessageClientMessageData) (MediaType, error) {
func (s *ClientSession) checkOfferTypeLocked(streamType StreamType, data *api.MessageClientMessageData) (MediaType, error) {
if streamType == StreamTypeScreen {
if !s.hasPermissionLocked(PERMISSION_MAY_PUBLISH_SCREEN) {
return 0, &PermissionError{PERMISSION_MAY_PUBLISH_SCREEN}
@ -908,7 +909,7 @@ func (s *ClientSession) checkOfferTypeLocked(streamType StreamType, data *Messag
return MediaTypeScreen, nil
} else if data != nil && data.Type == "offer" {
mediaTypes, err := s.isSdpAllowedToSendLocked(data.offerSdp)
mediaTypes, err := s.isSdpAllowedToSendLocked(data.OfferSdp)
if err != nil {
return 0, err
}
@ -919,7 +920,7 @@ func (s *ClientSession) checkOfferTypeLocked(streamType StreamType, data *Messag
return 0, nil
}
func (s *ClientSession) GetOrCreatePublisher(ctx context.Context, mcu Mcu, streamType StreamType, data *MessageClientMessageData) (McuPublisher, error) {
func (s *ClientSession) GetOrCreatePublisher(ctx context.Context, mcu Mcu, streamType StreamType, data *api.MessageClientMessageData) (McuPublisher, error) {
s.mu.Lock()
defer s.mu.Unlock()
@ -1026,7 +1027,7 @@ func (s *ClientSession) GetOrWaitForPublisher(ctx context.Context, streamType St
}
}
func (s *ClientSession) GetOrCreateSubscriber(ctx context.Context, mcu Mcu, id PublicSessionId, streamType StreamType) (McuSubscriber, error) {
func (s *ClientSession) GetOrCreateSubscriber(ctx context.Context, mcu Mcu, id api.PublicSessionId, streamType StreamType) (McuSubscriber, error) {
s.mu.Lock()
defer s.mu.Unlock()
@ -1061,7 +1062,7 @@ func (s *ClientSession) GetOrCreateSubscriber(ctx context.Context, mcu Mcu, id P
return subscriber, nil
}
func (s *ClientSession) GetSubscriber(id PublicSessionId, streamType StreamType) McuSubscriber {
func (s *ClientSession) GetSubscriber(id api.PublicSessionId, streamType StreamType) McuSubscriber {
s.mu.Lock()
defer s.mu.Unlock()
@ -1128,10 +1129,10 @@ func (s *ClientSession) processAsyncMessage(message *AsyncMessage) {
s.logger.Printf("Could not create MCU subscriber for session %s to process sendoffer in %s: %s", message.SendOffer.SessionId, s.PublicId(), err)
if err := s.events.PublishSessionMessage(message.SendOffer.SessionId, s.backend, &AsyncMessage{
Type: "message",
Message: &ServerMessage{
Message: &api.ServerMessage{
Id: message.SendOffer.MessageId,
Type: "error",
Error: NewError("client_not_found", "No MCU client found to send message to."),
Error: api.NewError("client_not_found", "No MCU client found to send message to."),
},
}); err != nil {
s.logger.Printf("Error sending sendoffer error response to %s: %s", message.SendOffer.SessionId, err)
@ -1141,10 +1142,10 @@ func (s *ClientSession) processAsyncMessage(message *AsyncMessage) {
s.logger.Printf("No MCU subscriber found for session %s to process sendoffer in %s", message.SendOffer.SessionId, s.PublicId())
if err := s.events.PublishSessionMessage(message.SendOffer.SessionId, s.backend, &AsyncMessage{
Type: "message",
Message: &ServerMessage{
Message: &api.ServerMessage{
Id: message.SendOffer.MessageId,
Type: "error",
Error: NewError("client_not_found", "No MCU client found to send message to."),
Error: api.NewError("client_not_found", "No MCU client found to send message to."),
},
}); err != nil {
s.logger.Printf("Error sending sendoffer error response to %s: %s", message.SendOffer.SessionId, err)
@ -1157,10 +1158,10 @@ func (s *ClientSession) processAsyncMessage(message *AsyncMessage) {
s.logger.Printf("Could not send MCU message %+v for session %s to %s: %s", message.SendOffer.Data, message.SendOffer.SessionId, s.PublicId(), err)
if err := s.events.PublishSessionMessage(message.SendOffer.SessionId, s.backend, &AsyncMessage{
Type: "message",
Message: &ServerMessage{
Message: &api.ServerMessage{
Id: message.SendOffer.MessageId,
Type: "error",
Error: NewError("processing_failed", "Processing of the message failed, please check server logs."),
Error: api.NewError("processing_failed", "Processing of the message failed, please check server logs."),
},
}); err != nil {
s.logger.Printf("Error sending sendoffer error response to %s: %s", message.SendOffer.SessionId, err)
@ -1171,8 +1172,8 @@ func (s *ClientSession) processAsyncMessage(message *AsyncMessage) {
return
}
s.hub.sendMcuMessageResponse(s, mc, &MessageClientMessage{
Recipient: MessageClientMessageRecipient{
s.hub.sendMcuMessageResponse(s, mc, &api.MessageClientMessage{
Recipient: api.MessageClientMessageRecipient{
SessionId: message.SendOffer.SessionId,
},
}, message.SendOffer.Data, response)
@ -1190,7 +1191,7 @@ func (s *ClientSession) processAsyncMessage(message *AsyncMessage) {
}
// +checklocks:s.mu
func (s *ClientSession) storePendingMessage(message *ServerMessage) {
func (s *ClientSession) storePendingMessage(message *api.ServerMessage) {
if message.IsChatRefresh() {
if s.hasPendingChat {
// Only send a single "chat-refresh" message on resume.
@ -1208,8 +1209,8 @@ func (s *ClientSession) storePendingMessage(message *ServerMessage) {
}
}
func filterDisplayNames(events []EventServerMessageSessionEntry) []EventServerMessageSessionEntry {
result := make([]EventServerMessageSessionEntry, 0, len(events))
func filterDisplayNames(events []api.EventServerMessageSessionEntry) []api.EventServerMessageSessionEntry {
result := make([]api.EventServerMessageSessionEntry, 0, len(events))
for _, event := range events {
if len(event.User) == 0 {
result = append(result, event)
@ -1249,14 +1250,14 @@ func filterDisplayNames(events []EventServerMessageSessionEntry) []EventServerMe
return result
}
func (s *ClientSession) filterDuplicateJoin(entries []EventServerMessageSessionEntry) []EventServerMessageSessionEntry {
func (s *ClientSession) filterDuplicateJoin(entries []api.EventServerMessageSessionEntry) []api.EventServerMessageSessionEntry {
s.seenJoinedLock.Lock()
defer s.seenJoinedLock.Unlock()
// Due to the asynchronous events, a session might received a "Joined" event
// for the same (other) session twice, so filter these out on a per-session
// level.
result := make([]EventServerMessageSessionEntry, 0, len(entries))
result := make([]api.EventServerMessageSessionEntry, 0, len(entries))
for _, e := range entries {
if s.seenJoinedEvents[e.SessionId] {
s.logger.Printf("Session %s got duplicate joined event for %s, ignoring", s.publicId, e.SessionId)
@ -1264,7 +1265,7 @@ func (s *ClientSession) filterDuplicateJoin(entries []EventServerMessageSessionE
}
if s.seenJoinedEvents == nil {
s.seenJoinedEvents = make(map[PublicSessionId]bool)
s.seenJoinedEvents = make(map[api.PublicSessionId]bool)
}
s.seenJoinedEvents[e.SessionId] = true
result = append(result, e)
@ -1272,7 +1273,7 @@ func (s *ClientSession) filterDuplicateJoin(entries []EventServerMessageSessionE
return result
}
func (s *ClientSession) filterMessage(message *ServerMessage) *ServerMessage {
func (s *ClientSession) filterMessage(message *api.ServerMessage) *api.ServerMessage {
switch message.Type {
case "event":
switch message.Event.Target {
@ -1304,10 +1305,10 @@ func (s *ClientSession) filterMessage(message *ServerMessage) *ServerMessage {
if len(join) != len(message.Event.Join) {
// Create unique copy of message for only this client.
copied = true
message = &ServerMessage{
message = &api.ServerMessage{
Id: message.Id,
Type: message.Type,
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Type: message.Event.Type,
Target: message.Event.Target,
Join: join,
@ -1319,10 +1320,10 @@ func (s *ClientSession) filterMessage(message *ServerMessage) *ServerMessage {
if copied {
message.Event.Join = filterDisplayNames(message.Event.Join)
} else {
message = &ServerMessage{
message = &api.ServerMessage{
Id: message.Id,
Type: message.Type,
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Type: message.Event.Type,
Target: message.Event.Target,
Join: filterDisplayNames(message.Event.Join),
@ -1351,7 +1352,7 @@ func (s *ClientSession) filterMessage(message *ServerMessage) *ServerMessage {
update := false
if data.Chat.Refresh && len(data.Chat.Comment) > 0 {
// New-style chat event, check what the client supports.
if s.HasFeature(ClientFeatureChatRelay) {
if s.HasFeature(api.ClientFeatureChatRelay) {
data.Chat.Refresh = false
} else {
data.Chat.Comment = nil
@ -1360,7 +1361,7 @@ func (s *ClientSession) filterMessage(message *ServerMessage) *ServerMessage {
}
if len(data.Chat.Comment) > 0 && s.HasPermission(PERMISSION_HIDE_DISPLAYNAMES) {
var comment ChatComment
var comment api.ChatComment
if err := json.Unmarshal(data.Chat.Comment, &comment); err != nil {
return message
}
@ -1378,13 +1379,13 @@ func (s *ClientSession) filterMessage(message *ServerMessage) *ServerMessage {
if update {
if encoded, err := json.Marshal(data); err == nil {
// Create unique copy of message for only this client.
message = &ServerMessage{
message = &api.ServerMessage{
Id: message.Id,
Type: message.Type,
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Type: message.Event.Type,
Target: message.Event.Target,
Message: &RoomEventMessage{
Message: &api.RoomEventMessage{
RoomId: message.Event.Message.RoomId,
Data: encoded,
},
@ -1397,7 +1398,7 @@ func (s *ClientSession) filterMessage(message *ServerMessage) *ServerMessage {
}
case "message":
if message.Message != nil && len(message.Message.Data) > 0 && s.HasPermission(PERMISSION_HIDE_DISPLAYNAMES) {
var data MessageServerMessageData
var data api.MessageServerMessageData
if err := json.Unmarshal(message.Message.Data, &data); err != nil {
return message
}
@ -1411,7 +1412,7 @@ func (s *ClientSession) filterMessage(message *ServerMessage) *ServerMessage {
return message
}
func (s *ClientSession) filterAsyncMessage(msg *AsyncMessage) *ServerMessage {
func (s *ClientSession) filterAsyncMessage(msg *AsyncMessage) *api.ServerMessage {
switch msg.Type {
case "message":
if msg.Message == nil {
@ -1427,7 +1428,7 @@ func (s *ClientSession) filterAsyncMessage(msg *AsyncMessage) *ServerMessage {
// Don't send message back to sender (can happen if sent to user or room)
return nil
}
if sender.Type == RecipientTypeCall {
if sender.Type == api.RecipientTypeCall {
if room := s.GetRoom(); room == nil || !room.IsSessionInCall(s) {
// Session is not in call, so discard.
return nil
@ -1442,7 +1443,7 @@ func (s *ClientSession) filterAsyncMessage(msg *AsyncMessage) *ServerMessage {
// Don't send message back to sender (can happen if sent to user or room)
return nil
}
if sender.Type == RecipientTypeCall {
if sender.Type == api.RecipientTypeCall {
if room := s.GetRoom(); room == nil || !room.IsSessionInCall(s) {
// Session is not in call, so discard.
return nil
@ -1541,7 +1542,7 @@ func (s *ClientSession) ClearResponseHandler(id string) {
delete(s.responseHandlers, id)
}
func (s *ClientSession) ProcessResponse(message *ClientMessage) bool {
func (s *ClientSession) ProcessResponse(message *api.ClientMessage) bool {
id := message.Id
if id == "" {
return false

View file

@ -33,6 +33,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/mock"
)
func TestBandwidth_Client(t *testing.T) {
@ -63,20 +64,20 @@ func TestBandwidth_Client(t *testing.T) {
// Client may not send an offer with audio and video.
bitrate := api.BandwidthFromBits(10000)
require.NoError(client.SendMessage(MessageClientMessageRecipient{
require.NoError(client.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: "video",
Bitrate: bitrate,
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
require.True(client.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo))
require.True(client.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo))
pub := mcu.GetPublisher(hello.Hello.SessionId)
require.NotNil(pub)
@ -122,7 +123,7 @@ func TestBandwidth_Backend(t *testing.T) {
params := TestBackendClientAuthParams{
UserId: testDefaultUserId,
}
require.NoError(client.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params))
require.NoError(client.SendHelloParams(server.URL+"/one", api.HelloVersionV1, "client", nil, params))
hello := MustSucceed1(t, client.RunUntilHello, ctx)
@ -136,20 +137,20 @@ func TestBandwidth_Backend(t *testing.T) {
// Client may not send an offer with audio and video.
bitrate := api.BandwidthFromBits(10000)
require.NoError(client.SendMessage(MessageClientMessageRecipient{
require.NoError(client.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: string(streamType),
Bitrate: bitrate,
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
require.True(client.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo))
require.True(client.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo))
pub := mcu.GetPublisher(hello.Hello.SessionId)
require.NotNil(pub, "Could not find publisher")
@ -179,7 +180,7 @@ func TestFeatureChatRelay(t *testing.T) {
defer client.CloseWithBye()
var features []string
if feature {
features = append(features, ClientFeatureChatRelay)
features = append(features, api.ClientFeatureChatRelay)
}
require.NoError(client.SendHelloClientWithFeatures(testDefaultUserId, features))
@ -263,11 +264,11 @@ func TestFeatureChatRelayFederation(t *testing.T) {
hub1, hub2, server1, server2 := CreateClusteredHubsForTest(t)
localFeatures := []string{
ClientFeatureChatRelay,
api.ClientFeatureChatRelay,
}
var federatedFeatures []string
if feature {
federatedFeatures = append(federatedFeatures, ClientFeatureChatRelay)
federatedFeatures = append(federatedFeatures, api.ClientFeatureChatRelay)
}
client1 := NewTestClient(t, server1, hub1)
@ -300,13 +301,13 @@ func TestFeatureChatRelayFederation(t *testing.T) {
token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -323,7 +324,7 @@ func TestFeatureChatRelayFederation(t *testing.T) {
}
// The client1 will see the remote session id for client2.
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]
@ -551,7 +552,7 @@ func TestPermissionHideDisplayNames(t *testing.T) {
client.RunUntilJoined(ctx, hello2.Hello)
client2.RunUntilJoined(ctx, hello.Hello, hello2.Hello)
recipient1 := MessageClientMessageRecipient{
recipient1 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}

View file

@ -48,7 +48,7 @@ const (
)
var (
ErrFederationNotSupported = NewError("federation_unsupported", "The target server does not support federation.")
ErrFederationNotSupported = api.NewError("federation_unsupported", "The target server does not support federation.")
federationWriteBufferPool = &sync.Pool{}
)
@ -81,12 +81,12 @@ type FederationClient struct {
logger log.Logger
hub *Hub
session *ClientSession
message atomic.Pointer[ClientMessage]
message atomic.Pointer[api.ClientMessage]
roomId atomic.Value
remoteRoomId atomic.Value
changeRoomId atomic.Bool
federation atomic.Pointer[RoomFederationMessage]
federation atomic.Pointer[api.RoomFederationMessage]
mu sync.Mutex
dialer *websocket.Dialer
@ -104,18 +104,18 @@ type FederationClient struct {
// +checklocks:helloMu
helloMsgId string
// +checklocks:helloMu
helloAuth *FederationAuthParams
helloAuth *api.FederationAuthParams
// +checklocks:helloMu
resumeId PrivateSessionId
hello atomic.Pointer[HelloServerMessage]
resumeId api.PrivateSessionId
hello atomic.Pointer[api.HelloServerMessage]
// +checklocks:helloMu
pendingMessages []*ClientMessage
pendingMessages []*api.ClientMessage
closeOnLeave atomic.Bool
}
func NewFederationClient(ctx context.Context, hub *Hub, session *ClientSession, message *ClientMessage) (*FederationClient, error) {
func NewFederationClient(ctx context.Context, hub *Hub, session *ClientSession, message *api.ClientMessage) (*FederationClient, error) {
if message.Type != "room" || message.Room == nil || message.Room.Federation == nil {
return nil, fmt.Errorf("expected federation room message, got %+v", message)
}
@ -130,7 +130,7 @@ func NewFederationClient(ctx context.Context, hub *Hub, session *ClientSession,
}
room := message.Room
u := *room.Federation.parsedSignalingUrl
u := *room.Federation.ParsedSignalingUrl
switch u.Scheme {
case "http":
u.Scheme = "ws"
@ -187,7 +187,7 @@ func (c *FederationClient) LocalAddr() net.Addr {
}
func (c *FederationClient) URL() string {
return c.federation.Load().parsedSignalingUrl.String()
return c.federation.Load().ParsedSignalingUrl.String()
}
func (c *FederationClient) RoomId() string {
@ -198,7 +198,7 @@ func (c *FederationClient) RemoteRoomId() string {
return c.remoteRoomId.Load().(string)
}
func (c *FederationClient) CanReuse(federation *RoomFederationMessage) bool {
func (c *FederationClient) CanReuse(federation *api.RoomFederationMessage) bool {
fed := c.federation.Load()
return fed.NextcloudUrl == federation.NextcloudUrl &&
fed.SignalingUrl == federation.SignalingUrl
@ -215,7 +215,7 @@ func (c *FederationClient) connect(ctx context.Context) error {
supportsFederation := false
for _, f := range features {
f = strings.TrimSpace(f)
if f == ServerFeatureFederation {
if f == api.ServerFeatureFederation {
supportsFederation = true
break
}
@ -250,7 +250,7 @@ func (c *FederationClient) connect(ctx context.Context) error {
return nil
}
func (c *FederationClient) ChangeRoom(message *ClientMessage) error {
func (c *FederationClient) ChangeRoom(message *api.ClientMessage) error {
if message.Room == nil || message.Room.Federation == nil {
return fmt.Errorf("expected federation room message, got %+v", message)
} else if !c.CanReuse(message.Room.Federation) {
@ -261,14 +261,14 @@ func (c *FederationClient) ChangeRoom(message *ClientMessage) error {
return c.joinRoom()
}
func (c *FederationClient) Leave(message *ClientMessage) error {
func (c *FederationClient) Leave(message *api.ClientMessage) error {
c.mu.Lock()
defer c.mu.Unlock()
if message == nil {
message = &ClientMessage{
message = &api.ClientMessage{
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: "",
},
}
@ -302,7 +302,7 @@ func (c *FederationClient) closeConnection(withBye bool) {
}
if withBye {
if err := c.sendMessageLocked(&ClientMessage{
if err := c.sendMessageLocked(&api.ClientMessage{
Type: "bye",
}); err != nil && !isClosedError(err) {
c.logger.Printf("Error sending bye on federation connection to %s: %s", c.URL(), err)
@ -339,9 +339,9 @@ func (c *FederationClient) scheduleReconnect() {
func (c *FederationClient) scheduleReconnectLocked() {
c.reconnecting.Store(true)
if c.hello.Swap(nil) != nil {
c.session.SendMessage(&ServerMessage{
c.session.SendMessage(&api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "federation_interrupted",
},
@ -404,7 +404,7 @@ func (c *FederationClient) readPump(conn *websocket.Conn) {
continue
}
var msg ServerMessage
var msg api.ServerMessage
if err := json.Unmarshal(data, &msg); err != nil {
c.logger.Printf("Error unmarshalling %s from %s: %s", string(data), c.URL(), err)
continue
@ -456,9 +456,9 @@ func (c *FederationClient) writePump() {
func (c *FederationClient) closeWithError(err error) {
c.Close()
var e *Error
var e *api.Error
if !errors.As(err, &e) {
e = NewError("federation_error", err.Error())
e = api.NewError("federation_error", err.Error())
}
var id string
@ -466,14 +466,14 @@ func (c *FederationClient) closeWithError(err error) {
id = message.Id
}
c.session.SendMessage(&ServerMessage{
c.session.SendMessage(&api.ServerMessage{
Id: id,
Type: "error",
Error: e,
})
}
func (c *FederationClient) sendHello(auth *FederationAuthParams) error {
func (c *FederationClient) sendHello(auth *api.FederationAuthParams) error {
c.helloMu.Lock()
defer c.helloMu.Unlock()
@ -481,7 +481,7 @@ func (c *FederationClient) sendHello(auth *FederationAuthParams) error {
}
// +checklocks:c.helloMu
func (c *FederationClient) sendHelloLocked(auth *FederationAuthParams) error {
func (c *FederationClient) sendHelloLocked(auth *api.FederationAuthParams) error {
c.helloMsgId = newRandomString(8)
authData, err := json.Marshal(auth)
@ -490,19 +490,19 @@ func (c *FederationClient) sendHelloLocked(auth *FederationAuthParams) error {
}
c.helloAuth = auth
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: c.helloMsgId,
Type: "hello",
Hello: &HelloClientMessage{
Version: HelloVersionV2,
Hello: &api.HelloClientMessage{
Version: api.HelloVersionV2,
Features: c.session.GetFeatures(),
},
}
if resumeId := c.resumeId; resumeId != "" {
msg.Hello.ResumeId = resumeId
} else {
msg.Hello.Auth = &HelloClientMessageAuth{
Type: HelloClientTypeFederation,
msg.Hello.Auth = &api.HelloClientMessageAuth{
Type: api.HelloClientTypeFederation,
Url: c.federation.Load().NextcloudUrl,
Params: authData,
}
@ -510,13 +510,13 @@ func (c *FederationClient) sendHelloLocked(auth *FederationAuthParams) error {
return c.SendMessage(msg)
}
func (c *FederationClient) processWelcome(msg *ServerMessage) {
if !msg.Welcome.HasFeature(ServerFeatureFederation) {
func (c *FederationClient) processWelcome(msg *api.ServerMessage) {
if !msg.Welcome.HasFeature(api.ServerFeatureFederation) {
c.closeWithError(ErrFederationNotSupported)
return
}
federationParams := &FederationAuthParams{
federationParams := &api.FederationAuthParams{
Token: c.federation.Load().Token,
}
if err := c.sendHello(federationParams); err != nil {
@ -525,7 +525,7 @@ func (c *FederationClient) processWelcome(msg *ServerMessage) {
}
}
func (c *FederationClient) processHello(msg *ServerMessage) {
func (c *FederationClient) processHello(msg *api.ServerMessage) {
c.resetReconnect()
c.helloMu.Lock()
@ -567,9 +567,9 @@ func (c *FederationClient) processHello(msg *ServerMessage) {
if c.resumeId == "" {
c.resumeId = msg.Hello.ResumeId
if c.reconnecting.Load() {
c.session.SendMessage(&ServerMessage{
c.session.SendMessage(&api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "federation_resumed",
Resumed: internal.MakePtr(false),
@ -584,9 +584,9 @@ func (c *FederationClient) processHello(msg *ServerMessage) {
c.closeWithError(err)
}
} else {
c.session.SendMessage(&ServerMessage{
c.session.SendMessage(&api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "federation_resumed",
Resumed: internal.MakePtr(true),
@ -627,10 +627,10 @@ func (c *FederationClient) joinRoom() error {
remoteRoomId = room.RoomId
}
return c.SendMessage(&ClientMessage{
return c.SendMessage(&api.ClientMessage{
Id: message.Id,
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: remoteRoomId,
SessionId: room.SessionId,
},
@ -641,15 +641,15 @@ func (c *FederationClient) updateActor(u api.StringMap, actorIdKey, actorTypeKey
if actorType, found := api.GetStringMapEntry[string](u, actorTypeKey); found {
if actorId, found := api.GetStringMapEntry[string](u, actorIdKey); found {
switch actorType {
case ActorTypeFederatedUsers:
case api.ActorTypeFederatedUsers:
if strings.HasSuffix(actorId, localCloudUrl) {
u[actorIdKey] = actorId[:len(actorId)-len(localCloudUrl)]
u[actorTypeKey] = ActorTypeUsers
u[actorTypeKey] = api.ActorTypeUsers
changed = true
}
case ActorTypeUsers:
case api.ActorTypeUsers:
u[actorIdKey] = actorId + remoteCloudUrl
u[actorTypeKey] = ActorTypeFederatedUsers
u[actorTypeKey] = api.ActorTypeFederatedUsers
changed = true
}
}
@ -713,7 +713,7 @@ func (c *FederationClient) updateComment(comment api.StringMap, localCloudUrl st
return changed
}
func (c *FederationClient) updateEventUsers(users []api.StringMap, localSessionId PublicSessionId, remoteSessionId PublicSessionId) {
func (c *FederationClient) updateEventUsers(users []api.StringMap, localSessionId api.PublicSessionId, remoteSessionId api.PublicSessionId) {
localCloudUrl := "@" + getCloudUrl(c.session.BackendUrl())
remoteCloudUrl := "@" + getCloudUrl(c.federation.Load().NextcloudUrl)
checkSessionId := true
@ -722,10 +722,10 @@ func (c *FederationClient) updateEventUsers(users []api.StringMap, localSessionI
if checkSessionId {
key := "sessionId"
sid, found := api.GetStringMapString[PublicSessionId](u, key)
sid, found := api.GetStringMapString[api.PublicSessionId](u, key)
if !found {
key := "sessionid"
sid, found = api.GetStringMapString[PublicSessionId](u, key)
sid, found = api.GetStringMapString[api.PublicSessionId](u, key)
}
if found && sid == remoteSessionId {
u[key] = localSessionId
@ -735,21 +735,21 @@ func (c *FederationClient) updateEventUsers(users []api.StringMap, localSessionI
}
}
func (c *FederationClient) updateSessionRecipient(recipient *MessageClientMessageRecipient, localSessionId PublicSessionId, remoteSessionId PublicSessionId) {
if recipient != nil && recipient.Type == RecipientTypeSession && remoteSessionId != "" && recipient.SessionId == remoteSessionId {
func (c *FederationClient) updateSessionRecipient(recipient *api.MessageClientMessageRecipient, localSessionId api.PublicSessionId, remoteSessionId api.PublicSessionId) {
if recipient != nil && recipient.Type == api.RecipientTypeSession && remoteSessionId != "" && recipient.SessionId == remoteSessionId {
recipient.SessionId = localSessionId
}
}
func (c *FederationClient) updateSessionSender(sender *MessageServerMessageSender, localSessionId PublicSessionId, remoteSessionId PublicSessionId) {
if sender != nil && sender.Type == RecipientTypeSession && remoteSessionId != "" && sender.SessionId == remoteSessionId {
func (c *FederationClient) updateSessionSender(sender *api.MessageServerMessageSender, localSessionId api.PublicSessionId, remoteSessionId api.PublicSessionId) {
if sender != nil && sender.Type == api.RecipientTypeSession && remoteSessionId != "" && sender.SessionId == remoteSessionId {
sender.SessionId = localSessionId
}
}
func (c *FederationClient) processMessage(msg *ServerMessage) {
func (c *FederationClient) processMessage(msg *api.ServerMessage) {
localSessionId := c.session.PublicId()
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if hello := c.hello.Load(); hello != nil {
remoteSessionId = hello.SessionId
}
@ -767,7 +767,7 @@ func (c *FederationClient) processMessage(msg *ServerMessage) {
var data api.StringMap
if err := json.Unmarshal(msg.Control.Data, &data); err == nil {
if action, found := data["action"]; found && action == "forceMute" {
if peerId, found := api.GetStringMapString[PublicSessionId](data, "peerId"); found && peerId == remoteSessionId {
if peerId, found := api.GetStringMapString[api.PublicSessionId](data, "peerId"); found && peerId == remoteSessionId {
data["peerId"] = localSessionId
if d, err := json.Marshal(data); err == nil {
msg.Control.Data = d
@ -874,7 +874,7 @@ func (c *FederationClient) processMessage(msg *ServerMessage) {
case "error":
if c.changeRoomId.Load() && msg.Error.Code == "already_joined" {
if len(msg.Error.Details) > 0 {
var details RoomErrorDetails
var details api.RoomErrorDetails
if err := json.Unmarshal(msg.Error.Details, &details); err == nil && details.Room != nil {
if details.Room.RoomId == remoteRoomId {
details.Room.RoomId = roomId
@ -916,7 +916,7 @@ func (c *FederationClient) processMessage(msg *ServerMessage) {
c.updateSessionRecipient(msg.Message.Recipient, localSessionId, remoteSessionId)
c.updateSessionSender(msg.Message.Sender, localSessionId, remoteSessionId)
if remoteSessionId != "" && len(msg.Message.Data) > 0 {
var ao AnswerOfferMessage
var ao api.AnswerOfferMessage
if json.Unmarshal(msg.Message.Data, &ao) == nil && (ao.Type == "offer" || ao.Type == "answer") {
changed := false
if ao.From == remoteSessionId {
@ -947,7 +947,7 @@ func (c *FederationClient) processMessage(msg *ServerMessage) {
}
}
func (c *FederationClient) ProxyMessage(message *ClientMessage) error {
func (c *FederationClient) ProxyMessage(message *api.ClientMessage) error {
switch message.Type {
case "message":
if hello := c.hello.Load(); hello != nil {
@ -964,14 +964,14 @@ func (c *FederationClient) ProxyMessage(message *ClientMessage) error {
return c.SendMessage(message)
}
func (c *FederationClient) SendMessage(message *ClientMessage) error {
func (c *FederationClient) SendMessage(message *api.ClientMessage) error {
c.mu.Lock()
defer c.mu.Unlock()
return c.sendMessageLocked(message)
}
func (c *FederationClient) deferMessage(message *ClientMessage) {
func (c *FederationClient) deferMessage(message *api.ClientMessage) {
c.helloMu.Lock()
defer c.helloMu.Unlock()
if c.resumeId == "" {
@ -985,7 +985,7 @@ func (c *FederationClient) deferMessage(message *ClientMessage) {
}
// +checklocks:c.mu
func (c *FederationClient) sendMessageLocked(message *ClientMessage) error {
func (c *FederationClient) sendMessageLocked(message *api.ClientMessage) error {
if c.conn == nil {
if message.Type != "room" {
// Join requests will be automatically sent after the hello response has

View file

@ -33,6 +33,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/mock"
)
func Test_FederationInvalidToken(t *testing.T) {
@ -51,13 +52,13 @@ func Test_FederationInvalidToken(t *testing.T) {
MustSucceed1(t, client.RunUntilHello, ctx)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: "test-room",
SessionId: "room-session-id",
Federation: &RoomFederationMessage{
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
Token: "invalid-token",
@ -115,13 +116,13 @@ func Test_Federation(t *testing.T) {
token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -138,7 +139,7 @@ func Test_Federation(t *testing.T) {
}
// The client1 will see the remote session id for client2.
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]
@ -174,7 +175,7 @@ func Test_Federation(t *testing.T) {
assert.Equal("1.0", ping.Version)
assert.Len(ping.Entries, 2)
// The order of entries is not defined
if ping.Entries[0].SessionId == RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)) {
if ping.Entries[0].SessionId == api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)) {
assert.Equal(hello2.Hello.UserId, ping.Entries[0].UserId)
assert.EqualValues(fmt.Sprintf("%s-%s", roomId, hello1.Hello.SessionId), ping.Entries[1].SessionId)
@ -217,7 +218,7 @@ func Test_Federation(t *testing.T) {
assert.Equal(roomId, room.Room.RoomId)
}
client1.RunUntilJoined(ctx, hello1.Hello, &HelloServerMessage{
client1.RunUntilJoined(ctx, hello1.Hello, &api.HelloServerMessage{
SessionId: remoteSessionId,
UserId: hello2.Hello.UserId,
})
@ -228,7 +229,7 @@ func Test_Federation(t *testing.T) {
assert.Empty(room.Room.RoomId)
}
client1.RunUntilLeft(ctx, &HelloServerMessage{
client1.RunUntilLeft(ctx, &api.HelloServerMessage{
SessionId: remoteSessionId,
UserId: hello2.Hello.UserId,
})
@ -262,7 +263,7 @@ func Test_Federation(t *testing.T) {
// Test sending messages between sessions.
data1 := "from-1-to-2"
data2 := "from-2-to-1"
if assert.NoError(client1.SendMessage(MessageClientMessageRecipient{
if assert.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: remoteSessionId,
}, data1)) {
@ -272,7 +273,7 @@ func Test_Federation(t *testing.T) {
}
}
if assert.NoError(client1.SendControl(MessageClientMessageRecipient{
if assert.NoError(client1.SendControl(api.MessageClientMessageRecipient{
Type: "session",
SessionId: remoteSessionId,
}, data1)) {
@ -282,12 +283,12 @@ func Test_Federation(t *testing.T) {
}
}
if assert.NoError(client2.SendMessage(MessageClientMessageRecipient{
if assert.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, data2)) {
var payload string
if checkReceiveClientMessage(ctx, t, client1, "session", &HelloServerMessage{
if checkReceiveClientMessage(ctx, t, client1, "session", &api.HelloServerMessage{
SessionId: remoteSessionId,
UserId: testDefaultUserId + "2",
}, &payload) {
@ -295,12 +296,12 @@ func Test_Federation(t *testing.T) {
}
}
if assert.NoError(client2.SendControl(MessageClientMessageRecipient{
if assert.NoError(client2.SendControl(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, data2)) {
var payload string
if checkReceiveClientControl(ctx, t, client1, "session", &HelloServerMessage{
if checkReceiveClientControl(ctx, t, client1, "session", &api.HelloServerMessage{
SessionId: remoteSessionId,
UserId: testDefaultUserId + "2",
}, &payload) {
@ -313,7 +314,7 @@ func Test_Federation(t *testing.T) {
"action": "forceMute",
"peerId": remoteSessionId,
}
if assert.NoError(client1.SendControl(MessageClientMessageRecipient{
if assert.NoError(client1.SendControl(api.MessageClientMessageRecipient{
Type: "session",
SessionId: remoteSessionId,
}, forceMute)) {
@ -327,7 +328,7 @@ func Test_Federation(t *testing.T) {
data3 := "from-2-to-2"
// Clients can't send to their own (local) session id.
if assert.NoError(client2.SendMessage(MessageClientMessageRecipient{
if assert.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}, data3)) {
@ -338,7 +339,7 @@ func Test_Federation(t *testing.T) {
}
// Clients can't send to their own (remote) session id.
if assert.NoError(client2.SendMessage(MessageClientMessageRecipient{
if assert.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: remoteSessionId,
}, data3)) {
@ -358,7 +359,7 @@ func Test_Federation(t *testing.T) {
},
}
room.PublishUsersInCallChanged(users, users)
var event *EventServerMessage
var event *api.EventServerMessage
// For the local user, it's a federated user on server 2 that joined.
if checkReceiveClientEvent(ctx, t, client1, "update", &event) {
assert.EqualValues(remoteSessionId, event.Update.Users[0]["sessionId"])
@ -414,7 +415,7 @@ func Test_Federation(t *testing.T) {
client1.RunUntilJoined(ctx, hello3.Hello)
client2.RunUntilJoined(ctx, hello3.Hello)
client3.RunUntilJoined(ctx, hello1.Hello, &HelloServerMessage{
client3.RunUntilJoined(ctx, hello1.Hello, &api.HelloServerMessage{
SessionId: remoteSessionId,
UserId: hello2.Hello.UserId,
}, hello3.Hello)
@ -435,13 +436,13 @@ func Test_Federation(t *testing.T) {
token, err = client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"4", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg = &ClientMessage{
msg = &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello4.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello4.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -458,7 +459,7 @@ func Test_Federation(t *testing.T) {
}
// The client1 will see the remote session id for client4.
var remoteSessionId4 PublicSessionId
var remoteSessionId4 api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]
@ -469,17 +470,17 @@ func Test_Federation(t *testing.T) {
assert.Equal(features2, evt.Features)
}
client2.RunUntilJoined(ctx, &HelloServerMessage{
client2.RunUntilJoined(ctx, &api.HelloServerMessage{
SessionId: remoteSessionId4,
UserId: hello4.Hello.UserId,
})
client3.RunUntilJoined(ctx, &HelloServerMessage{
client3.RunUntilJoined(ctx, &api.HelloServerMessage{
SessionId: remoteSessionId4,
UserId: hello4.Hello.UserId,
})
client4.RunUntilJoined(ctx, hello1.Hello, &HelloServerMessage{
client4.RunUntilJoined(ctx, hello1.Hello, &api.HelloServerMessage{
SessionId: remoteSessionId,
UserId: hello2.Hello.UserId,
}, hello3.Hello, hello4.Hello)
@ -526,13 +527,13 @@ func Test_FederationJoinRoomTwice(t *testing.T) {
token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -549,7 +550,7 @@ func Test_FederationJoinRoomTwice(t *testing.T) {
}
// The client1 will see the remote session id for client2.
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]
@ -562,13 +563,13 @@ func Test_FederationJoinRoomTwice(t *testing.T) {
// The client2 will see its own session id, not the one from the remote server.
client2.RunUntilJoined(ctx, hello1.Hello, hello2.Hello)
msg2 := &ClientMessage{
msg2 := &api.ClientMessage{
Id: "join-room-fed-2",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -584,7 +585,7 @@ func Test_FederationJoinRoomTwice(t *testing.T) {
assert.Equal("already_joined", message.Error.Code)
}
if assert.NotNil(message.Error.Details) {
var roomMsg RoomErrorDetails
var roomMsg api.RoomErrorDetails
if assert.NoError(json.Unmarshal(message.Error.Details, &roomMsg)) {
if assert.NotNil(roomMsg.Room) {
assert.Equal(federatedRoomId, roomMsg.Room.RoomId)
@ -632,13 +633,13 @@ func Test_FederationChangeRoom(t *testing.T) {
token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -660,7 +661,7 @@ func Test_FederationChangeRoom(t *testing.T) {
localAddr := fed.LocalAddr()
// The client1 will see the remote session id for client2.
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]
@ -675,13 +676,13 @@ func Test_FederationChangeRoom(t *testing.T) {
roomId2 := roomId + "-2"
federatedRoomId2 := roomId2 + "@federated"
msg2 := &ClientMessage{
msg2 := &api.ClientMessage{
Id: "join-room-fed-2",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId2,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId2, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId2, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId2,
@ -752,13 +753,13 @@ func Test_FederationMedia(t *testing.T) {
token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -775,7 +776,7 @@ func Test_FederationMedia(t *testing.T) {
}
// The client1 will see the remote session id for client2.
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]
@ -788,19 +789,19 @@ func Test_FederationMedia(t *testing.T) {
// The client2 will see its own session id, not the one from the remote server.
client2.RunUntilJoined(ctx, hello1.Hello, hello2.Hello)
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "12345",
RoomType: "screen",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
client2.RunUntilAnswerFromSender(ctx, MockSdpAnswerAudioAndVideo, &MessageServerMessageSender{
client2.RunUntilAnswerFromSender(ctx, mock.MockSdpAnswerAudioAndVideo, &api.MessageServerMessageSender{
Type: "session",
SessionId: hello2.Hello.SessionId,
UserId: hello2.Hello.UserId,
@ -844,13 +845,13 @@ func Test_FederationResume(t *testing.T) {
token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -867,7 +868,7 @@ func Test_FederationResume(t *testing.T) {
}
// The client1 will see the remote session id for client2.
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]
@ -887,7 +888,7 @@ func Test_FederationResume(t *testing.T) {
err = fed2.conn.Close()
data2 := "from-2-to-1"
assert.NoError(client2.SendMessage(MessageClientMessageRecipient{
assert.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, data2))
@ -912,7 +913,7 @@ func Test_FederationResume(t *testing.T) {
defer cancel1()
var payload string
if checkReceiveClientMessage(ctx, t, client1, "session", &HelloServerMessage{
if checkReceiveClientMessage(ctx, t, client1, "session", &api.HelloServerMessage{
SessionId: remoteSessionId,
UserId: testDefaultUserId + "2",
}, &payload) {
@ -964,13 +965,13 @@ func Test_FederationResumeNewSession(t *testing.T) {
token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -987,7 +988,7 @@ func Test_FederationResumeNewSession(t *testing.T) {
}
// The client1 will see the remote session id for client2.
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]
@ -1024,7 +1025,7 @@ func Test_FederationResumeNewSession(t *testing.T) {
// Client1 will get a "leave" for the expired session and a "join" with the
// new remote session id.
client1.RunUntilLeft(ctx, &HelloServerMessage{
client1.RunUntilLeft(ctx, &api.HelloServerMessage{
SessionId: remoteSessionId,
UserId: hello2.Hello.UserId,
})
@ -1087,13 +1088,13 @@ func Test_FederationTransientData(t *testing.T) {
token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata)
require.NoError(err)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "join-room-fed",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: federatedRoomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &RoomFederationMessage{
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", federatedRoomId, hello2.Hello.SessionId)),
Federation: &api.RoomFederationMessage{
SignalingUrl: server1.URL,
NextcloudUrl: server1.URL,
RoomId: roomId,
@ -1110,7 +1111,7 @@ func Test_FederationTransientData(t *testing.T) {
}
// The client1 will see the remote session id for client2.
var remoteSessionId PublicSessionId
var remoteSessionId api.PublicSessionId
if message, ok := client1.RunUntilMessage(ctx); ok {
client1.checkSingleMessageJoined(message)
evt := message.Event.Join[0]

View file

@ -43,6 +43,7 @@ import (
"google.golang.org/grpc/resolver"
status "google.golang.org/grpc/status"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/async"
"github.com/strukturag/nextcloud-spreed-signaling/internal"
"github.com/strukturag/nextcloud-spreed-signaling/log"
@ -202,7 +203,7 @@ func (c *GrpcClient) GetServerId(ctx context.Context) (string, string, error) {
return response.GetServerId(), response.GetVersion(), nil
}
func (c *GrpcClient) LookupResumeId(ctx context.Context, resumeId PrivateSessionId) (*LookupResumeIdReply, error) {
func (c *GrpcClient) LookupResumeId(ctx context.Context, resumeId api.PrivateSessionId) (*LookupResumeIdReply, error) {
statsGrpcClientCalls.WithLabelValues("LookupResumeId").Inc()
// TODO: Remove debug logging
c.logger.Printf("Lookup resume id %s on %s", resumeId, c.Target())
@ -222,7 +223,7 @@ func (c *GrpcClient) LookupResumeId(ctx context.Context, resumeId PrivateSession
return response, nil
}
func (c *GrpcClient) LookupSessionId(ctx context.Context, roomSessionId RoomSessionId, disconnectReason string) (PublicSessionId, error) {
func (c *GrpcClient) LookupSessionId(ctx context.Context, roomSessionId api.RoomSessionId, disconnectReason string) (api.PublicSessionId, error) {
statsGrpcClientCalls.WithLabelValues("LookupSessionId").Inc()
// TODO: Remove debug logging
c.logger.Printf("Lookup room session %s on %s", roomSessionId, c.Target())
@ -241,10 +242,10 @@ func (c *GrpcClient) LookupSessionId(ctx context.Context, roomSessionId RoomSess
return "", ErrNoSuchRoomSession
}
return PublicSessionId(sessionId), nil
return api.PublicSessionId(sessionId), nil
}
func (c *GrpcClient) IsSessionInCall(ctx context.Context, sessionId PublicSessionId, room *Room, backendUrl string) (bool, error) {
func (c *GrpcClient) IsSessionInCall(ctx context.Context, sessionId api.PublicSessionId, room *Room, backendUrl string) (bool, error) {
statsGrpcClientCalls.WithLabelValues("IsSessionInCall").Inc()
// TODO: Remove debug logging
c.logger.Printf("Check if session %s is in call %s on %s", sessionId, room.Id(), c.Target())
@ -262,7 +263,7 @@ func (c *GrpcClient) IsSessionInCall(ctx context.Context, sessionId PublicSessio
return response.GetInCall(), nil
}
func (c *GrpcClient) GetInternalSessions(ctx context.Context, roomId string, backendUrls []string) (internal map[PublicSessionId]*InternalSessionData, virtual map[PublicSessionId]*VirtualSessionData, err error) {
func (c *GrpcClient) GetInternalSessions(ctx context.Context, roomId string, backendUrls []string) (internal map[api.PublicSessionId]*InternalSessionData, virtual map[api.PublicSessionId]*VirtualSessionData, err error) {
statsGrpcClientCalls.WithLabelValues("GetInternalSessions").Inc()
// TODO: Remove debug logging
c.logger.Printf("Get internal sessions for %s on %s", roomId, c.Target())
@ -282,22 +283,22 @@ func (c *GrpcClient) GetInternalSessions(ctx context.Context, roomId string, bac
}
if len(response.InternalSessions) > 0 {
internal = make(map[PublicSessionId]*InternalSessionData, len(response.InternalSessions))
internal = make(map[api.PublicSessionId]*InternalSessionData, len(response.InternalSessions))
for _, s := range response.InternalSessions {
internal[PublicSessionId(s.SessionId)] = s
internal[api.PublicSessionId(s.SessionId)] = s
}
}
if len(response.VirtualSessions) > 0 {
virtual = make(map[PublicSessionId]*VirtualSessionData, len(response.VirtualSessions))
virtual = make(map[api.PublicSessionId]*VirtualSessionData, len(response.VirtualSessions))
for _, s := range response.VirtualSessions {
virtual[PublicSessionId(s.SessionId)] = s
virtual[api.PublicSessionId(s.SessionId)] = s
}
}
return
}
func (c *GrpcClient) GetPublisherId(ctx context.Context, sessionId PublicSessionId, streamType StreamType) (PublicSessionId, string, net.IP, string, string, error) {
func (c *GrpcClient) GetPublisherId(ctx context.Context, sessionId api.PublicSessionId, streamType StreamType) (api.PublicSessionId, string, net.IP, string, string, error) {
statsGrpcClientCalls.WithLabelValues("GetPublisherId").Inc()
// TODO: Remove debug logging
c.logger.Printf("Get %s publisher id %s on %s", streamType, sessionId, c.Target())
@ -311,7 +312,7 @@ func (c *GrpcClient) GetPublisherId(ctx context.Context, sessionId PublicSession
return "", "", nil, "", "", err
}
return PublicSessionId(response.GetPublisherId()), response.GetProxyUrl(), net.ParseIP(response.GetIp()), response.GetConnectToken(), response.GetPublisherToken(), nil
return api.PublicSessionId(response.GetPublisherId()), response.GetProxyUrl(), net.ParseIP(response.GetIp()), response.GetConnectToken(), response.GetPublisherToken(), nil
}
func (c *GrpcClient) GetSessionCount(ctx context.Context, url string) (uint32, error) {
@ -375,7 +376,7 @@ type ProxySessionReceiver interface {
type SessionProxy struct {
logger log.Logger
sessionId PublicSessionId
sessionId api.PublicSessionId
receiver ProxySessionReceiver
sendMu sync.Mutex
@ -421,7 +422,7 @@ func (p *SessionProxy) Close() error {
return p.client.CloseSend()
}
func (c *GrpcClient) ProxySession(ctx context.Context, sessionId PublicSessionId, receiver ProxySessionReceiver) (*SessionProxy, error) {
func (c *GrpcClient) ProxySession(ctx context.Context, sessionId api.PublicSessionId, receiver ProxySessionReceiver) (*SessionProxy, error) {
statsGrpcClientCalls.WithLabelValues("ProxySession").Inc()
md := metadata.Pairs(
"sessionId", string(sessionId),

View file

@ -33,6 +33,7 @@ import (
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
)
@ -159,20 +160,20 @@ func (c *remoteGrpcClient) SetSession(session Session) {
}
}
func (c *remoteGrpcClient) SendError(e *Error) bool {
message := &ServerMessage{
func (c *remoteGrpcClient) SendError(e *api.Error) bool {
message := &api.ServerMessage{
Type: "error",
Error: e,
}
return c.SendMessage(message)
}
func (c *remoteGrpcClient) SendByeResponse(message *ClientMessage) bool {
func (c *remoteGrpcClient) SendByeResponse(message *api.ClientMessage) bool {
return c.SendByeResponseWithReason(message, "")
}
func (c *remoteGrpcClient) SendByeResponseWithReason(message *ClientMessage, reason string) bool {
response := &ServerMessage{
func (c *remoteGrpcClient) SendByeResponseWithReason(message *api.ClientMessage, reason string) bool {
response := &api.ServerMessage{
Type: "bye",
}
if message != nil {
@ -180,7 +181,7 @@ func (c *remoteGrpcClient) SendByeResponseWithReason(message *ClientMessage, rea
}
if reason != "" {
if response.Bye == nil {
response.Bye = &ByeServerMessage{}
response.Bye = &api.ByeServerMessage{}
}
response.Bye.Reason = reason
}

View file

@ -38,6 +38,7 @@ import (
"google.golang.org/grpc/credentials"
status "google.golang.org/grpc/status"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
)
@ -60,9 +61,9 @@ func init() {
}
type GrpcServerHub interface {
GetSessionByResumeId(resumeId PrivateSessionId) Session
GetSessionByPublicId(sessionId PublicSessionId) Session
GetSessionIdByRoomSessionId(roomSessionId RoomSessionId) (PublicSessionId, error)
GetSessionByResumeId(resumeId api.PrivateSessionId) Session
GetSessionByPublicId(sessionId api.PublicSessionId) Session
GetSessionIdByRoomSessionId(roomSessionId api.RoomSessionId) (api.PublicSessionId, error)
GetRoomForBackend(roomId string, backend *Backend) *Room
GetBackend(u *url.URL) *Backend
@ -136,7 +137,7 @@ func (s *GrpcServer) LookupResumeId(ctx context.Context, request *LookupResumeId
statsGrpcServerCalls.WithLabelValues("LookupResumeId").Inc()
// TODO: Remove debug logging
s.logger.Printf("Lookup session for resume id %s", request.ResumeId)
session := s.hub.GetSessionByResumeId(PrivateSessionId(request.ResumeId))
session := s.hub.GetSessionByResumeId(api.PrivateSessionId(request.ResumeId))
if session == nil {
return nil, status.Error(codes.NotFound, "no such room session id")
}
@ -150,7 +151,7 @@ func (s *GrpcServer) LookupSessionId(ctx context.Context, request *LookupSession
statsGrpcServerCalls.WithLabelValues("LookupSessionId").Inc()
// TODO: Remove debug logging
s.logger.Printf("Lookup session id for room session id %s", request.RoomSessionId)
sid, err := s.hub.GetSessionIdByRoomSessionId(RoomSessionId(request.RoomSessionId))
sid, err := s.hub.GetSessionIdByRoomSessionId(api.RoomSessionId(request.RoomSessionId))
if errors.Is(err, ErrNoSuchRoomSession) {
return nil, status.Error(codes.NotFound, "no such room session id")
} else if err != nil {
@ -158,7 +159,7 @@ func (s *GrpcServer) LookupSessionId(ctx context.Context, request *LookupSession
}
if sid != "" && request.DisconnectReason != "" {
if session := s.hub.GetSessionByPublicId(PublicSessionId(sid)); session != nil {
if session := s.hub.GetSessionByPublicId(api.PublicSessionId(sid)); session != nil {
s.logger.Printf("Closing session %s because same room session %s connected", session.PublicId(), request.RoomSessionId)
session.LeaveRoom(false)
switch sess := session.(type) {
@ -179,7 +180,7 @@ func (s *GrpcServer) IsSessionInCall(ctx context.Context, request *IsSessionInCa
statsGrpcServerCalls.WithLabelValues("IsSessionInCall").Inc()
// TODO: Remove debug logging
s.logger.Printf("Check if session %s is in call %s on %s", request.SessionId, request.RoomId, request.BackendUrl)
session := s.hub.GetSessionByPublicId(PublicSessionId(request.SessionId))
session := s.hub.GetSessionByPublicId(api.PublicSessionId(request.SessionId))
if session == nil {
return nil, status.Error(codes.NotFound, "no such session id")
}
@ -187,7 +188,7 @@ func (s *GrpcServer) IsSessionInCall(ctx context.Context, request *IsSessionInCa
result := &IsSessionInCallReply{}
room := session.GetRoom()
if room == nil || room.Id() != request.GetRoomId() || !room.Backend().HasUrl(request.GetBackendUrl()) ||
(session.ClientType() != HelloClientTypeInternal && !room.IsSessionInCall(session)) {
(session.ClientType() != api.HelloClientTypeInternal && !room.IsSessionInCall(session)) {
// Recipient is not in a room, a different room or not in the call.
result.InCall = false
} else {
@ -265,7 +266,7 @@ func (s *GrpcServer) GetPublisherId(ctx context.Context, request *GetPublisherId
statsGrpcServerCalls.WithLabelValues("GetPublisherId").Inc()
// TODO: Remove debug logging
s.logger.Printf("Get %s publisher id for session %s", request.StreamType, request.SessionId)
session := s.hub.GetSessionByPublicId(PublicSessionId(request.SessionId))
session := s.hub.GetSessionByPublicId(api.PublicSessionId(request.SessionId))
if session == nil {
return nil, status.Error(codes.NotFound, "no such session")
}

362
hub.go

File diff suppressed because it is too large Load diff

View file

@ -57,6 +57,7 @@ import (
"github.com/strukturag/nextcloud-spreed-signaling/container"
"github.com/strukturag/nextcloud-spreed-signaling/internal"
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/mock"
"github.com/strukturag/nextcloud-spreed-signaling/nats"
"github.com/strukturag/nextcloud-spreed-signaling/talk"
"github.com/strukturag/nextcloud-spreed-signaling/test"
@ -444,7 +445,7 @@ func processRoomRequest(t *testing.T, w http.ResponseWriter, r *http.Request, re
case "test-invalid-room":
response := &BackendClientResponse{
Type: "error",
Error: &Error{
Error: &api.Error{
Code: "no_such_room",
Message: "The user is not invited to this room.",
},
@ -455,7 +456,7 @@ func processRoomRequest(t *testing.T, w http.ResponseWriter, r *http.Request, re
if strings.Contains(t.Name(), "Federation") {
// Check additional fields present for federated sessions.
if strings.Contains(string(request.Room.SessionId), "@federated") {
assert.Equal(ActorTypeFederatedUsers, request.Room.ActorType)
assert.Equal(api.ActorTypeFederatedUsers, request.Room.ActorType)
assert.NotEmpty(request.Room.ActorId)
} else {
assert.Empty(request.Room.ActorType)
@ -1301,7 +1302,7 @@ func TestClientHelloSessionLimit(t *testing.T) {
params1 := TestBackendClientAuthParams{
UserId: testDefaultUserId,
}
require.NoError(client.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", nil, params1))
require.NoError(client.SendHelloParams(server1.URL+"/one", api.HelloVersionV1, "client", nil, params1))
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
@ -1318,12 +1319,12 @@ func TestClientHelloSessionLimit(t *testing.T) {
params2 := TestBackendClientAuthParams{
UserId: testDefaultUserId + "2",
}
require.NoError(client2.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", nil, params2))
require.NoError(client2.SendHelloParams(server1.URL+"/one", api.HelloVersionV1, "client", nil, params2))
client2.RunUntilError(ctx, "session_limit_exceeded") //nolint
// The client can connect to a different backend.
require.NoError(client2.SendHelloParams(server1.URL+"/two", HelloVersionV1, "client", nil, params2))
require.NoError(client2.SendHelloParams(server1.URL+"/two", api.HelloVersionV1, "client", nil, params2))
if hello, ok := client2.RunUntilHello(ctx); ok {
assert.Equal(testDefaultUserId+"2", hello.Hello.UserId, "%+v", hello.Hello)
@ -1340,7 +1341,7 @@ func TestClientHelloSessionLimit(t *testing.T) {
params3 := TestBackendClientAuthParams{
UserId: testDefaultUserId + "3",
}
require.NoError(client3.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", nil, params3))
require.NoError(client3.SendHelloParams(server1.URL+"/one", api.HelloVersionV1, "client", nil, params3))
if hello, ok := client3.RunUntilHello(ctx); ok {
assert.Equal(testDefaultUserId+"3", hello.Hello.UserId, "%+v", hello.Hello)
@ -1357,7 +1358,7 @@ func TestSessionIdsUnordered(t *testing.T) {
hub, _, _, server := CreateHubForTest(t)
var mu sync.Mutex
var publicSessionIds []PublicSessionId
var publicSessionIds []api.PublicSessionId
var wg sync.WaitGroup
for range 20 {
wg.Add(1)
@ -1397,7 +1398,7 @@ func TestSessionIdsUnordered(t *testing.T) {
larger := 0
smaller := 0
var prevSid PublicSessionId
var prevSid api.PublicSessionId
for i, sid := range publicSessionIds {
if i > 0 {
if sid > prevSid {
@ -1642,7 +1643,7 @@ func TestClientHelloResumePublicId(t *testing.T) {
client2, hello2 := NewTestClientWithHello(ctx, t, server, hub, testDefaultUserId+"2")
require.NotEqual(hello1.Hello.SessionId, hello2.Hello.SessionId)
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
@ -1651,7 +1652,7 @@ func TestClientHelloResumePublicId(t *testing.T) {
client1.SendMessage(recipient2, data) // nolint
var payload string
var sender *MessageServerMessageSender
var sender *api.MessageServerMessageSender
if checkReceiveClientMessageWithSender(ctx, t, client2, "session", hello1.Hello, &payload, &sender) {
assert.Equal(data, payload)
}
@ -1663,7 +1664,7 @@ func TestClientHelloResumePublicId(t *testing.T) {
defer client1.CloseWithBye()
// Can't resume a session with the id received from messages of a client.
require.NoError(client1.SendHelloResume(PrivateSessionId(sender.SessionId)))
require.NoError(client1.SendHelloResume(api.PrivateSessionId(sender.SessionId)))
client1.RunUntilError(ctx, "no_such_session") // nolint
// Expire old sessions
@ -1937,7 +1938,7 @@ func TestClientHelloClient_V3Api(t *testing.T) {
}
// The "/api/v1/signaling/" URL will be changed to use "v3" as the "signaling-v3"
// feature is returned by the capabilities endpoint.
require.NoError(client.SendHelloParams(server.URL, HelloVersionV1, "client", nil, params))
require.NoError(client.SendHelloParams(server.URL, api.HelloVersionV1, "client", nil, params))
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
@ -2010,11 +2011,11 @@ func TestClientMessageToSessionId(t *testing.T) {
waitForAsyncEventsFlushed(ctx, t, hub1.events)
waitForAsyncEventsFlushed(ctx, t, hub2.events)
recipient1 := MessageClientMessageRecipient{
recipient1 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
@ -2071,11 +2072,11 @@ func TestClientControlToSessionId(t *testing.T) {
waitForAsyncEventsFlushed(ctx, t, hub1.events)
waitForAsyncEventsFlushed(ctx, t, hub2.events)
recipient1 := MessageClientMessageRecipient{
recipient1 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
@ -2126,11 +2127,11 @@ func TestClientControlMissingPermissions(t *testing.T) {
PERMISSION_MAY_CONTROL,
})
recipient1 := MessageClientMessageRecipient{
recipient1 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
@ -2165,11 +2166,11 @@ func TestClientMessageToUserId(t *testing.T) {
require.NotEqual(hello1.Hello.SessionId, hello2.Hello.SessionId)
require.NotEqual(hello1.Hello.UserId, hello2.Hello.UserId)
recipient1 := MessageClientMessageRecipient{
recipient1 := api.MessageClientMessageRecipient{
Type: "user",
UserId: hello1.Hello.UserId,
}
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "user",
UserId: hello2.Hello.UserId,
}
@ -2203,11 +2204,11 @@ func TestClientControlToUserId(t *testing.T) {
require.NotEqual(hello1.Hello.SessionId, hello2.Hello.SessionId)
require.NotEqual(hello1.Hello.UserId, hello2.Hello.UserId)
recipient1 := MessageClientMessageRecipient{
recipient1 := api.MessageClientMessageRecipient{
Type: "user",
UserId: hello1.Hello.UserId,
}
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "user",
UserId: hello2.Hello.UserId,
}
@ -2248,7 +2249,7 @@ func TestClientMessageToUserIdMultipleSessions(t *testing.T) {
require.NotEqual(hello1.Hello.UserId, hello2b.Hello.UserId)
require.Equal(hello2a.Hello.UserId, hello2b.Hello.UserId)
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "user",
UserId: hello2a.Hello.UserId,
}
@ -2308,7 +2309,7 @@ func TestClientMessageToRoom(t *testing.T) {
WaitForUsersJoined(ctx, t, client1, hello1, client2, hello2)
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "room",
}
@ -2371,7 +2372,7 @@ func TestClientControlToRoom(t *testing.T) {
WaitForUsersJoined(ctx, t, client1, hello1, client2, hello2)
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "room",
}
@ -2447,7 +2448,7 @@ func TestClientMessageToCall(t *testing.T) {
checkReceiveClientEvent(ctx, t, client1, "update", nil)
checkReceiveClientEvent(ctx, t, client2, "update", nil)
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "call",
}
@ -2552,7 +2553,7 @@ func TestClientControlToCall(t *testing.T) {
checkReceiveClientEvent(ctx, t, client1, "update", nil)
checkReceiveClientEvent(ctx, t, client2, "update", nil)
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "call",
}
@ -2743,12 +2744,12 @@ func TestJoinInvalidRoom(t *testing.T) {
// Join room by id.
roomId := "test-invalid-room"
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "ABCD",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: roomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId)),
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId)),
},
}
require.NoError(client.WriteJSON(msg))
@ -2781,12 +2782,12 @@ func TestJoinRoomTwice(t *testing.T) {
// We will receive a "joined" event.
client.RunUntilJoined(ctx, hello.Hello)
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "ABCD",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: roomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s-2", roomId, client.publicId)),
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s-2", roomId, client.publicId)),
},
}
require.NoError(client.WriteJSON(msg))
@ -2796,7 +2797,7 @@ func TestJoinRoomTwice(t *testing.T) {
if checkMessageType(t, message, "error") {
assert.Equal("already_joined", message.Error.Code)
if assert.NotEmpty(message.Error.Details) {
var roomDetails RoomErrorDetails
var roomDetails api.RoomErrorDetails
if err := json.Unmarshal(message.Error.Details, &roomDetails); assert.NoError(err) {
if assert.NotNil(roomDetails.Room, "%+v", message) {
assert.Equal(roomId, roomDetails.Room.RoomId)
@ -3043,12 +3044,12 @@ func TestJoinRoomSwitchClient(t *testing.T) {
// Join room by id.
roomId := "test-room-slow"
msg := &ClientMessage{
msg := &api.ClientMessage{
Id: "ABCD",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: roomId,
SessionId: RoomSessionId(fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId)),
SessionId: api.RoomSessionId(fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId)),
},
}
require.NoError(client.WriteJSON(msg))
@ -3325,7 +3326,7 @@ func TestClientMessageToSessionIdWhileDisconnected(t *testing.T) {
client2.Close()
assert.NoError(client2.WaitForClientRemoved(ctx))
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
@ -3473,7 +3474,7 @@ func TestRoomParticipantsListUpdateWhileDisconnected(t *testing.T) {
// Give asynchronous events some time to be processed.
time.Sleep(100 * time.Millisecond)
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
@ -3540,7 +3541,7 @@ func RunTestClientTakeoverRoomSession(t *testing.T) {
// Join room by id.
roomId := "test-room-takeover-room-session"
roomSessionid := RoomSessionId("room-session-id")
roomSessionid := api.RoomSessionId("room-session-id")
roomMsg := MustSucceed3(t, client1.JoinRoomWithRoomSession, ctx, roomId, roomSessionid)
require.Equal(roomId, roomMsg.Room.RoomId)
@ -3635,10 +3636,10 @@ func TestClientSendOfferPermissions(t *testing.T) {
session2.SetPermissions([]Permission{})
// Client 2 may not send an offer (he doesn't have the necessary permissions).
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "sendoffer",
Sid: "12345",
RoomType: "screen",
@ -3647,25 +3648,25 @@ func TestClientSendOfferPermissions(t *testing.T) {
msg := MustSucceed1(t, client2.RunUntilMessage, ctx)
require.True(checkMessageError(t, msg, "not_allowed"))
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "12345",
RoomType: "screen",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo)
client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo)
// Client 1 may send an offer.
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "sendoffer",
Sid: "54321",
RoomType: "screen",
@ -3678,7 +3679,7 @@ func TestClientSendOfferPermissions(t *testing.T) {
client1.RunUntilErrorIs(ctx2, ErrNoMessageReceived, context.DeadlineExceeded)
// ...but the other peer will get an offer.
client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo)
}
func TestClientSendOfferPermissionsAudioOnly(t *testing.T) {
@ -3711,15 +3712,15 @@ func TestClientSendOfferPermissionsAudioOnly(t *testing.T) {
session.SetPermissions([]Permission{PERMISSION_MAY_PUBLISH_AUDIO})
// Client may not send an offer with audio and video.
require.NoError(client.SendMessage(MessageClientMessageRecipient{
require.NoError(client.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
@ -3727,19 +3728,19 @@ func TestClientSendOfferPermissionsAudioOnly(t *testing.T) {
require.True(checkMessageError(t, msg, "not_allowed"))
// Client may send an offer (audio only).
require.NoError(client.SendMessage(MessageClientMessageRecipient{
require.NoError(client.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioOnly,
"sdp": mock.MockSdpOfferAudioOnly,
},
}))
client.RunUntilAnswer(ctx, MockSdpAnswerAudioOnly)
client.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioOnly)
}
func TestClientSendOfferPermissionsAudioVideo(t *testing.T) {
@ -3772,19 +3773,19 @@ func TestClientSendOfferPermissionsAudioVideo(t *testing.T) {
// Client is allowed to send audio and video.
session.SetPermissions([]Permission{PERMISSION_MAY_PUBLISH_AUDIO, PERMISSION_MAY_PUBLISH_VIDEO})
require.NoError(client.SendMessage(MessageClientMessageRecipient{
require.NoError(client.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
require.True(client.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo))
require.True(client.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo))
// Client is no longer allowed to send video, this will stop the publisher.
msg := &BackendServerRoomRequest{
@ -3869,19 +3870,19 @@ func TestClientSendOfferPermissionsAudioVideoMedia(t *testing.T) {
session.SetPermissions([]Permission{PERMISSION_MAY_PUBLISH_MEDIA})
// Client may send an offer (audio and video).
require.NoError(client.SendMessage(MessageClientMessageRecipient{
require.NoError(client.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
require.True(client.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo))
require.True(client.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo))
// Client is no longer allowed to send video, this will stop the publisher.
msg := &BackendServerRoomRequest{
@ -3977,25 +3978,25 @@ func TestClientRequestOfferNotInRoom(t *testing.T) {
// We will receive a "joined" event.
client1.RunUntilJoined(ctx, hello1.Hello)
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: "screen",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
require.True(client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo))
require.True(client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo))
// Client 2 may not request an offer (he is not in the room yet).
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
Sid: "12345",
RoomType: "screen",
@ -4012,10 +4013,10 @@ func TestClientRequestOfferNotInRoom(t *testing.T) {
require.True(client2.RunUntilJoined(ctx, hello1.Hello, hello2.Hello))
// Client 2 may not request an offer (he is not in the call yet).
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
Sid: "12345",
RoomType: "screen",
@ -4038,10 +4039,10 @@ func TestClientRequestOfferNotInRoom(t *testing.T) {
checkReceiveClientEvent(ctx, t, client2, "update", nil)
// Client 2 may not request an offer (recipient is not in the call yet).
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
Sid: "12345",
RoomType: "screen",
@ -4064,26 +4065,26 @@ func TestClientRequestOfferNotInRoom(t *testing.T) {
checkReceiveClientEvent(ctx, t, client2, "update", nil)
// Client 2 may request an offer now (both are in the same room and call).
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
Sid: "12345",
RoomType: "screen",
}))
require.True(client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo))
require.True(client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo))
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "answer",
Sid: "12345",
RoomType: "screen",
Payload: api.StringMap{
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}))
@ -4111,7 +4112,7 @@ func TestNoSendBetweenSessionsOnDifferentBackends(t *testing.T) {
params1 := TestBackendClientAuthParams{
UserId: "user1",
}
require.NoError(client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params1))
require.NoError(client1.SendHelloParams(server.URL+"/one", api.HelloVersionV1, "client", nil, params1))
hello1 := MustSucceed1(t, client1.RunUntilHello, ctx)
client2 := NewTestClient(t, server, hub)
@ -4120,14 +4121,14 @@ func TestNoSendBetweenSessionsOnDifferentBackends(t *testing.T) {
params2 := TestBackendClientAuthParams{
UserId: "user2",
}
require.NoError(client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", nil, params2))
require.NoError(client2.SendHelloParams(server.URL+"/two", api.HelloVersionV1, "client", nil, params2))
hello2 := MustSucceed1(t, client2.RunUntilHello, ctx)
recipient1 := MessageClientMessageRecipient{
recipient1 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
@ -4163,7 +4164,7 @@ func TestSendBetweenDifferentUrls(t *testing.T) {
params1 := TestBackendClientAuthParams{
UserId: "user1",
}
require.NoError(client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params1))
require.NoError(client1.SendHelloParams(server.URL+"/one", api.HelloVersionV1, "client", nil, params1))
hello1 := MustSucceed1(t, client1.RunUntilHello, ctx)
client2 := NewTestClient(t, server, hub)
@ -4172,14 +4173,14 @@ func TestSendBetweenDifferentUrls(t *testing.T) {
params2 := TestBackendClientAuthParams{
UserId: "user2",
}
require.NoError(client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", nil, params2))
require.NoError(client2.SendHelloParams(server.URL+"/two", api.HelloVersionV1, "client", nil, params2))
hello2 := MustSucceed1(t, client2.RunUntilHello, ctx)
recipient1 := MessageClientMessageRecipient{
recipient1 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}
recipient2 := MessageClientMessageRecipient{
recipient2 := api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
@ -4213,7 +4214,7 @@ func TestNoSameRoomOnDifferentBackends(t *testing.T) {
params1 := TestBackendClientAuthParams{
UserId: "user1",
}
require.NoError(client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params1))
require.NoError(client1.SendHelloParams(server.URL+"/one", api.HelloVersionV1, "client", nil, params1))
hello1 := MustSucceed1(t, client1.RunUntilHello, ctx)
client2 := NewTestClient(t, server, hub)
@ -4222,7 +4223,7 @@ func TestNoSameRoomOnDifferentBackends(t *testing.T) {
params2 := TestBackendClientAuthParams{
UserId: "user2",
}
require.NoError(client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", nil, params2))
require.NoError(client2.SendHelloParams(server.URL+"/two", api.HelloVersionV1, "client", nil, params2))
hello2 := MustSucceed1(t, client2.RunUntilHello, ctx)
// Join room by id.
@ -4251,7 +4252,7 @@ func TestNoSameRoomOnDifferentBackends(t *testing.T) {
assert.False(rooms[0].IsEqual(rooms[1]), "Rooms should be different: %+v", rooms)
}
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "room",
}
@ -4286,7 +4287,7 @@ func TestSameRoomOnDifferentUrls(t *testing.T) {
params1 := TestBackendClientAuthParams{
UserId: "user1",
}
require.NoError(client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params1))
require.NoError(client1.SendHelloParams(server.URL+"/one", api.HelloVersionV1, "client", nil, params1))
hello1 := MustSucceed1(t, client1.RunUntilHello, ctx)
client2 := NewTestClient(t, server, hub)
@ -4295,7 +4296,7 @@ func TestSameRoomOnDifferentUrls(t *testing.T) {
params2 := TestBackendClientAuthParams{
UserId: "user2",
}
require.NoError(client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", nil, params2))
require.NoError(client2.SendHelloParams(server.URL+"/two", api.HelloVersionV1, "client", nil, params2))
hello2 := MustSucceed1(t, client2.RunUntilHello, ctx)
// Join room by id.
@ -4318,7 +4319,7 @@ func TestSameRoomOnDifferentUrls(t *testing.T) {
assert.Len(rooms, 1)
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "room",
}
@ -4381,24 +4382,24 @@ func TestClientSendOffer(t *testing.T) {
WaitForUsersJoined(ctx, t, client1, hello1, client2, hello2)
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "12345",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
require.True(client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo))
require.True(client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo))
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "sendoffer",
RoomType: "video",
}))
@ -4410,7 +4411,7 @@ func TestClientSendOffer(t *testing.T) {
client1.RunUntilErrorIs(ctx2, ErrNoMessageReceived, context.DeadlineExceeded)
// ...but the other peer will get an offer.
client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo)
})
}
}
@ -4441,19 +4442,19 @@ func TestClientUnshareScreen(t *testing.T) {
session := hub.GetSessionByPublicId(hello.Hello.SessionId).(*ClientSession)
require.NotNil(session, "Session %s does not exist", hello.Hello.SessionId)
require.NoError(client.SendMessage(MessageClientMessageRecipient{
require.NoError(client.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: "screen",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioOnly,
"sdp": mock.MockSdpOfferAudioOnly,
},
}))
client.RunUntilAnswer(ctx, MockSdpAnswerAudioOnly)
client.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioOnly)
publisher := mcu.GetPublisher(hello.Hello.SessionId)
require.NotNil(publisher, "No publisher for %s found", hello.Hello.SessionId)
@ -4465,10 +4466,10 @@ func TestClientUnshareScreen(t *testing.T) {
cleanupScreenPublisherDelay = old
}()
require.NoError(client.SendMessage(MessageClientMessageRecipient{
require.NoError(client.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "unshareScreen",
Sid: "54321",
RoomType: "screen",
@ -4550,7 +4551,7 @@ func TestVirtualClientSessions(t *testing.T) {
calledCtx, calledCancel := context.WithTimeout(ctx, time.Second)
virtualSessionId := PublicSessionId("virtual-session-id")
virtualSessionId := api.PublicSessionId("virtual-session-id")
virtualUserId := "virtual-user-id"
generatedSessionId := GetVirtualSessionId(session2, virtualSessionId)
@ -4562,8 +4563,8 @@ func TestVirtualClientSessions(t *testing.T) {
assert.Equal(virtualUserId, request.UserId, "%+v", request)
})
require.NoError(client2.SendInternalAddSession(&AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
require.NoError(client2.SendInternalAddSession(&api.AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: virtualSessionId,
RoomId: roomId,
},
@ -4636,8 +4637,8 @@ func TestVirtualClientSessions(t *testing.T) {
}
updatedFlags := uint32(0)
require.NoError(client2.SendInternalUpdateSession(&UpdateSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
require.NoError(client2.SendInternalUpdateSession(&api.UpdateSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: virtualSessionId,
RoomId: roomId,
},
@ -4672,7 +4673,7 @@ func TestVirtualClientSessions(t *testing.T) {
})
// Messages to virtual sessions are sent to the associated client session.
virtualRecipient := MessageClientMessageRecipient{
virtualRecipient := api.MessageClientMessageRecipient{
Type: "session",
SessionId: virtualSession.PublicId(),
}
@ -4681,8 +4682,8 @@ func TestVirtualClientSessions(t *testing.T) {
client1.SendMessage(virtualRecipient, data) // nolint
var payload string
var sender *MessageServerMessageSender
var recipient *MessageClientMessageRecipient
var sender *api.MessageServerMessageSender
var recipient *api.MessageClientMessageRecipient
if checkReceiveClientMessageWithSenderAndRecipient(ctx, t, client2, "session", hello1.Hello, &payload, &sender, &recipient) {
assert.Equal(virtualSessionId, recipient.SessionId, "%+v", recipient)
assert.Equal(data, payload)
@ -4696,8 +4697,8 @@ func TestVirtualClientSessions(t *testing.T) {
assert.Equal(data, payload)
}
require.NoError(client2.SendInternalRemoveSession(&RemoveSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
require.NoError(client2.SendInternalRemoveSession(&api.RemoveSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: virtualSessionId,
RoomId: roomId,
},
@ -4792,7 +4793,7 @@ func TestDuplicateVirtualSessions(t *testing.T) {
calledCtx, calledCancel := context.WithTimeout(ctx, time.Second)
virtualSessionId := PublicSessionId("virtual-session-id")
virtualSessionId := api.PublicSessionId("virtual-session-id")
virtualUserId := "virtual-user-id"
generatedSessionId := GetVirtualSessionId(session2, virtualSessionId)
@ -4804,8 +4805,8 @@ func TestDuplicateVirtualSessions(t *testing.T) {
assert.Equal(virtualUserId, request.UserId, "%+v", request)
})
require.NoError(client2.SendInternalAddSession(&AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
require.NoError(client2.SendInternalAddSession(&api.AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: virtualSessionId,
RoomId: roomId,
},
@ -5020,12 +5021,12 @@ func DoTestSwitchToOne(t *testing.T, details api.StringMap) {
client1, hello1 := NewTestClientWithHello(ctx, t, server1, hub1, testDefaultUserId+"1")
client2, hello2 := NewTestClientWithHello(ctx, t, server2, hub2, testDefaultUserId+"2")
roomSessionId1 := RoomSessionId("roomsession1")
roomSessionId1 := api.RoomSessionId("roomsession1")
roomId1 := "test-room"
roomMsg := MustSucceed3(t, client1.JoinRoomWithRoomSession, ctx, roomId1, roomSessionId1)
require.Equal(roomId1, roomMsg.Room.RoomId)
roomSessionId2 := RoomSessionId("roomsession2")
roomSessionId2 := api.RoomSessionId("roomsession2")
roomMsg = MustSucceed3(t, client2.JoinRoomWithRoomSession, ctx, roomId1, roomSessionId2)
require.Equal(roomId1, roomMsg.Room.RoomId)
@ -5035,12 +5036,12 @@ func DoTestSwitchToOne(t *testing.T, details api.StringMap) {
var sessions json.RawMessage
var err error
if details != nil {
sessions, err = json.Marshal(map[RoomSessionId]any{
sessions, err = json.Marshal(map[api.RoomSessionId]any{
roomSessionId1: details,
})
require.NoError(err)
} else {
sessions, err = json.Marshal([]RoomSessionId{
sessions, err = json.Marshal([]api.RoomSessionId{
roomSessionId1,
})
require.NoError(err)
@ -5120,12 +5121,12 @@ func DoTestSwitchToMultiple(t *testing.T, details1 api.StringMap, details2 api.S
client2, hello2 := NewTestClientWithHello(ctx, t, server2, hub2, testDefaultUserId+"2")
defer client2.CloseWithBye()
roomSessionId1 := RoomSessionId("roomsession1")
roomSessionId1 := api.RoomSessionId("roomsession1")
roomId1 := "test-room"
roomMsg := MustSucceed3(t, client1.JoinRoomWithRoomSession, ctx, roomId1, roomSessionId1)
require.Equal(roomId1, roomMsg.Room.RoomId)
roomSessionId2 := RoomSessionId("roomsession2")
roomSessionId2 := api.RoomSessionId("roomsession2")
roomMsg = MustSucceed3(t, client2.JoinRoomWithRoomSession, ctx, roomId1, roomSessionId2)
require.Equal(roomId1, roomMsg.Room.RoomId)
@ -5135,13 +5136,13 @@ func DoTestSwitchToMultiple(t *testing.T, details1 api.StringMap, details2 api.S
var sessions json.RawMessage
var err error
if details1 != nil || details2 != nil {
sessions, err = json.Marshal(map[RoomSessionId]any{
sessions, err = json.Marshal(map[api.RoomSessionId]any{
roomSessionId1: details1,
roomSessionId2: details2,
})
require.NoError(err)
} else {
sessions, err = json.Marshal([]RoomSessionId{
sessions, err = json.Marshal([]api.RoomSessionId{
roomSessionId1,
roomSessionId2,
})
@ -5271,15 +5272,15 @@ func TestDialoutStatus(t *testing.T) {
assert.Equal(roomId, msg.Internal.Dialout.RoomId)
response := &ClientMessage{
response := &api.ClientMessage{
Id: msg.Id,
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "dialout",
Dialout: &DialoutInternalClientMessage{
Dialout: &api.DialoutInternalClientMessage{
Type: "status",
RoomId: msg.Internal.Dialout.RoomId,
Status: &DialoutStatusInternalClientMessage{
Status: &api.DialoutStatusInternalClientMessage{
Status: "accepted",
CallId: callId,
},
@ -5326,10 +5327,10 @@ func TestDialoutStatus(t *testing.T) {
}, nil)
}
require.NoError(internalClient.SendInternalDialout(&DialoutInternalClientMessage{
require.NoError(internalClient.SendInternalDialout(&api.DialoutInternalClientMessage{
RoomId: roomId,
Type: "status",
Status: &DialoutStatusInternalClientMessage{
Status: &api.DialoutStatusInternalClientMessage{
CallId: callId,
Status: "ringing",
},
@ -5352,10 +5353,10 @@ func TestDialoutStatus(t *testing.T) {
removeCallStatusTTL = 500 * time.Millisecond
clearedCause := "cleared-call"
require.NoError(internalClient.SendInternalDialout(&DialoutInternalClientMessage{
require.NoError(internalClient.SendInternalDialout(&api.DialoutInternalClientMessage{
RoomId: roomId,
Type: "status",
Status: &DialoutStatusInternalClientMessage{
Status: &api.DialoutStatusInternalClientMessage{
CallId: callId,
Status: "cleared",
Cause: clearedCause,

View file

@ -56,7 +56,7 @@ const (
)
type McuListener interface {
PublicId() PublicSessionId
PublicId() api.PublicSessionId
OnUpdateOffer(client McuClient, offer api.StringMap)
@ -137,8 +137,8 @@ type Mcu interface {
GetServerInfoSfu() *BackendServerInfoSfu
GetBandwidthLimits() (api.Bandwidth, api.Bandwidth)
NewPublisher(ctx context.Context, listener McuListener, id PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator) (McuPublisher, error)
NewSubscriber(ctx context.Context, listener McuListener, publisher PublicSessionId, streamType StreamType, initiator McuInitiator) (McuSubscriber, error)
NewPublisher(ctx context.Context, listener McuListener, id api.PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator) (McuPublisher, error)
NewSubscriber(ctx context.Context, listener McuListener, publisher api.PublicSessionId, streamType StreamType, initiator McuInitiator) (McuSubscriber, error)
}
// PublisherStream contains the available properties when creating a
@ -171,7 +171,7 @@ type PublisherStream struct {
}
type RemotePublisherController interface {
PublisherId() PublicSessionId
PublisherId() api.PublicSessionId
StartPublishing(ctx context.Context, publisher McuRemotePublisherProperties) error
StopPublishing(ctx context.Context, publisher McuRemotePublisherProperties) error
@ -220,7 +220,7 @@ type McuClient interface {
Close(ctx context.Context)
SendMessage(ctx context.Context, message *MessageClientMessage, data *MessageClientMessageData, callback func(error, api.StringMap))
SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap))
}
type McuClientWithBandwidth interface {
@ -232,7 +232,7 @@ type McuClientWithBandwidth interface {
type McuPublisher interface {
McuClient
PublisherId() PublicSessionId
PublisherId() api.PublicSessionId
HasMedia(MediaType) bool
SetMedia(MediaType)
@ -247,14 +247,14 @@ type McuPublisherWithStreams interface {
type McuRemoteAwarePublisher interface {
McuPublisher
PublishRemote(ctx context.Context, remoteId PublicSessionId, hostname string, port int, rtcpPort int) error
UnpublishRemote(ctx context.Context, remoteId PublicSessionId, hostname string, port int, rtcpPort int) error
PublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error
UnpublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error
}
type McuSubscriber interface {
McuClient
Publisher() PublicSessionId
Publisher() api.PublicSessionId
}
type McuRemotePublisherProperties interface {

View file

@ -33,10 +33,10 @@ func TestCommonMcuStats(t *testing.T) {
}
type MockMcuListener struct {
publicId PublicSessionId
publicId api.PublicSessionId
}
func (m *MockMcuListener) PublicId() PublicSessionId {
func (m *MockMcuListener) PublicId() api.PublicSessionId {
return m.publicId
}

View file

@ -66,7 +66,7 @@ var (
type StreamId string
func getStreamId(publisherId PublicSessionId, streamType StreamType) StreamId {
func getStreamId(publisherId api.PublicSessionId, streamType StreamType) StreamId {
return StreamId(fmt.Sprintf("%s|%s", publisherId, streamType))
}
@ -680,7 +680,7 @@ func (m *mcuJanus) sendKeepalive(ctx context.Context) {
}
}
func (m *mcuJanus) SubscriberConnected(id string, publisher PublicSessionId, streamType StreamType) {
func (m *mcuJanus) SubscriberConnected(id string, publisher api.PublicSessionId, streamType StreamType) {
m.mu.Lock()
defer m.mu.Unlock()
@ -689,7 +689,7 @@ func (m *mcuJanus) SubscriberConnected(id string, publisher PublicSessionId, str
}
}
func (m *mcuJanus) SubscriberDisconnected(id string, publisher PublicSessionId, streamType StreamType) {
func (m *mcuJanus) SubscriberDisconnected(id string, publisher api.PublicSessionId, streamType StreamType) {
m.mu.Lock()
defer m.mu.Unlock()
@ -698,7 +698,7 @@ func (m *mcuJanus) SubscriberDisconnected(id string, publisher PublicSessionId,
}
}
func (m *mcuJanus) createPublisherRoom(ctx context.Context, handle *JanusHandle, id PublicSessionId, streamType StreamType, settings NewPublisherSettings) (uint64, api.Bandwidth, error) {
func (m *mcuJanus) createPublisherRoom(ctx context.Context, handle *JanusHandle, id api.PublicSessionId, streamType StreamType, settings NewPublisherSettings) (uint64, api.Bandwidth, error) {
create_msg := api.StringMap{
"request": "create",
"description": getStreamId(id, streamType),
@ -753,7 +753,7 @@ func (m *mcuJanus) createPublisherRoom(ctx context.Context, handle *JanusHandle,
return roomId, bitrate, nil
}
func (m *mcuJanus) getOrCreatePublisherHandle(ctx context.Context, id PublicSessionId, streamType StreamType, settings NewPublisherSettings) (*JanusHandle, uint64, uint64, api.Bandwidth, error) {
func (m *mcuJanus) getOrCreatePublisherHandle(ctx context.Context, id api.PublicSessionId, streamType StreamType, settings NewPublisherSettings) (*JanusHandle, uint64, uint64, api.Bandwidth, error) {
session := m.session
if session == nil {
return nil, 0, 0, 0, ErrNotConnected
@ -791,7 +791,7 @@ func (m *mcuJanus) getOrCreatePublisherHandle(ctx context.Context, id PublicSess
return handle, response.Session, roomId, bitrate, nil
}
func (m *mcuJanus) NewPublisher(ctx context.Context, listener McuListener, id PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator) (McuPublisher, error) {
func (m *mcuJanus) NewPublisher(ctx context.Context, listener McuListener, id api.PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator) (McuPublisher, error) {
if _, found := streamTypeUserIds[streamType]; !found {
return nil, fmt.Errorf("unsupported stream type %s", streamType)
}
@ -842,7 +842,7 @@ func (m *mcuJanus) NewPublisher(ctx context.Context, listener McuListener, id Pu
return client, nil
}
func (m *mcuJanus) getPublisher(ctx context.Context, publisher PublicSessionId, streamType StreamType) (*mcuJanusPublisher, error) {
func (m *mcuJanus) getPublisher(ctx context.Context, publisher api.PublicSessionId, streamType StreamType) (*mcuJanusPublisher, error) {
// Do the direct check immediately as this should be the normal case.
key := getStreamId(publisher, streamType)
m.mu.Lock()
@ -869,7 +869,7 @@ func (m *mcuJanus) getPublisher(ctx context.Context, publisher PublicSessionId,
}
}
func (m *mcuJanus) getOrCreateSubscriberHandle(ctx context.Context, publisher PublicSessionId, streamType StreamType) (*JanusHandle, *mcuJanusPublisher, error) {
func (m *mcuJanus) getOrCreateSubscriberHandle(ctx context.Context, publisher api.PublicSessionId, streamType StreamType) (*JanusHandle, *mcuJanusPublisher, error) {
var pub *mcuJanusPublisher
var err error
if pub, err = m.getPublisher(ctx, publisher, streamType); err != nil {
@ -890,7 +890,7 @@ func (m *mcuJanus) getOrCreateSubscriberHandle(ctx context.Context, publisher Pu
return handle, pub, nil
}
func (m *mcuJanus) NewSubscriber(ctx context.Context, listener McuListener, publisher PublicSessionId, streamType StreamType, initiator McuInitiator) (McuSubscriber, error) {
func (m *mcuJanus) NewSubscriber(ctx context.Context, listener McuListener, publisher api.PublicSessionId, streamType StreamType, initiator McuInitiator) (McuSubscriber, error) {
if _, found := streamTypeUserIds[streamType]; !found {
return nil, fmt.Errorf("unsupported stream type %s", streamType)
}

View file

@ -86,7 +86,7 @@ func (c *mcuJanusClient) MaxBitrate() api.Bandwidth {
func (c *mcuJanusClient) Close(ctx context.Context) {
}
func (c *mcuJanusClient) SendMessage(ctx context.Context, message *MessageClientMessage, data *MessageClientMessageData, callback func(error, api.StringMap)) {
func (c *mcuJanusClient) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
}
func (c *mcuJanusClient) UpdateBandwidth(media string, sent api.Bandwidth, received api.Bandwidth) {

View file

@ -49,7 +49,7 @@ const (
type mcuJanusPublisher struct {
mcuJanusClient
id PublicSessionId
id api.PublicSessionId
settings NewPublisherSettings
stats publisherStatsCounter
sdpFlags Flags
@ -58,7 +58,7 @@ type mcuJanusPublisher struct {
answerSdp atomic.Pointer[sdp.SessionDescription]
}
func (p *mcuJanusPublisher) PublisherId() PublicSessionId {
func (p *mcuJanusPublisher) PublisherId() api.PublicSessionId {
return p.id
}
@ -173,21 +173,21 @@ func (p *mcuJanusPublisher) Close(ctx context.Context) {
p.mcuJanusClient.Close(ctx)
}
func (p *mcuJanusPublisher) SendMessage(ctx context.Context, message *MessageClientMessage, data *MessageClientMessageData, callback func(error, api.StringMap)) {
func (p *mcuJanusPublisher) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
statsMcuMessagesTotal.WithLabelValues(data.Type).Inc()
jsep_msg := data.Payload
switch data.Type {
case "offer":
p.deferred <- func() {
if data.offerSdp == nil {
if data.OfferSdp == nil {
// Should have been checked before.
go callback(errors.New("no sdp found in offer"), nil)
return
}
if FilterSDPCandidates(data.offerSdp, p.mcu.settings.allowedCandidates.Load(), p.mcu.settings.blockedCandidates.Load()) {
if api.FilterSDPCandidates(data.OfferSdp, p.mcu.settings.allowedCandidates.Load(), p.mcu.settings.blockedCandidates.Load()) {
// Update request with filtered SDP.
marshalled, err := data.offerSdp.Marshal()
marshalled, err := data.OfferSdp.Marshal()
if err != nil {
go callback(fmt.Errorf("could not marshal filtered offer: %w", err), nil)
return
@ -196,7 +196,7 @@ func (p *mcuJanusPublisher) SendMessage(ctx context.Context, message *MessageCli
jsep_msg["sdp"] = string(marshalled)
}
p.offerSdp.Store(data.offerSdp)
p.offerSdp.Store(data.OfferSdp)
p.sdpFlags.Add(sdpHasOffer)
if p.sdpFlags.Get() == sdpHasAnswer|sdpHasOffer {
p.sdpReady.Close()
@ -216,7 +216,7 @@ func (p *mcuJanusPublisher) SendMessage(ctx context.Context, message *MessageCli
sdpString, found := api.GetStringMapEntry[string](jsep, "sdp")
if !found {
p.logger.Printf("No/invalid sdp found in answer %+v", jsep)
} else if answerSdp, err := parseSDP(sdpString); err != nil {
} else if answerSdp, err := api.ParseSDP(sdpString); err != nil {
p.logger.Printf("Error parsing answer sdp %+v: %s", sdpString, err)
p.answerSdp.Store(nil)
p.sdpFlags.Remove(sdpHasAnswer)
@ -233,8 +233,8 @@ func (p *mcuJanusPublisher) SendMessage(ctx context.Context, message *MessageCli
})
}
case "candidate":
if FilterCandidate(data.candidate, p.mcu.settings.allowedCandidates.Load(), p.mcu.settings.blockedCandidates.Load()) {
go callback(ErrCandidateFiltered, nil)
if api.FilterCandidate(data.Candidate, p.mcu.settings.allowedCandidates.Load(), p.mcu.settings.blockedCandidates.Load()) {
go callback(api.ErrCandidateFiltered, nil)
return
}
@ -399,11 +399,11 @@ func (p *mcuJanusPublisher) GetStreams(ctx context.Context) ([]PublisherStream,
return streams, nil
}
func getPublisherRemoteId(id PublicSessionId, remoteId PublicSessionId, hostname string, port int, rtcpPort int) string {
func getPublisherRemoteId(id api.PublicSessionId, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) string {
return fmt.Sprintf("%s-%s@%s:%d:%d", id, remoteId, hostname, port, rtcpPort)
}
func (p *mcuJanusPublisher) PublishRemote(ctx context.Context, remoteId PublicSessionId, hostname string, port int, rtcpPort int) error {
func (p *mcuJanusPublisher) PublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error {
handle := p.handle.Load()
if handle == nil {
return ErrNotConnected
@ -445,7 +445,7 @@ func (p *mcuJanusPublisher) PublishRemote(ctx context.Context, remoteId PublicSe
return nil
}
func (p *mcuJanusPublisher) UnpublishRemote(ctx context.Context, remoteId PublicSessionId, hostname string, port int, rtcpPort int) error {
func (p *mcuJanusPublisher) UnpublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error {
handle := p.handle.Load()
if handle == nil {
return ErrNotConnected

View file

@ -110,7 +110,7 @@ func TestJanusPublisherRemote(t *testing.T) {
var remotePublishId atomic.Value
remoteId := PublicSessionId("the-remote-id")
remoteId := api.PublicSessionId("the-remote-id")
hostname := "remote.server"
port := 12345
rtcpPort := 23456
@ -155,7 +155,7 @@ func TestJanusPublisherRemote(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
pubId := PublicSessionId("publisher-id")
pubId := api.PublicSessionId("publisher-id")
listener1 := &TestMcuListener{
id: pubId,
}

View file

@ -34,10 +34,10 @@ import (
type mcuJanusSubscriber struct {
mcuJanusClient
publisher PublicSessionId
publisher api.PublicSessionId
}
func (p *mcuJanusSubscriber) Publisher() PublicSessionId {
func (p *mcuJanusSubscriber) Publisher() api.PublicSessionId {
return p.publisher
}
@ -290,7 +290,7 @@ func (p *mcuJanusSubscriber) update(ctx context.Context, stream *streamSelection
callback(nil, configure_response.Jsep)
}
func (p *mcuJanusSubscriber) SendMessage(ctx context.Context, message *MessageClientMessage, data *MessageClientMessageData, callback func(error, api.StringMap)) {
func (p *mcuJanusSubscriber) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
statsMcuMessagesTotal.WithLabelValues(data.Type).Inc()
jsep_msg := data.Payload
switch data.Type {
@ -315,9 +315,9 @@ func (p *mcuJanusSubscriber) SendMessage(ctx context.Context, message *MessageCl
}
case "answer":
p.deferred <- func() {
if FilterSDPCandidates(data.answerSdp, p.mcu.settings.allowedCandidates.Load(), p.mcu.settings.blockedCandidates.Load()) {
if api.FilterSDPCandidates(data.AnswerSdp, p.mcu.settings.allowedCandidates.Load(), p.mcu.settings.blockedCandidates.Load()) {
// Update request with filtered SDP.
marshalled, err := data.answerSdp.Marshal()
marshalled, err := data.AnswerSdp.Marshal()
if err != nil {
go callback(fmt.Errorf("could not marshal filtered answer: %w", err), nil)
return
@ -336,8 +336,8 @@ func (p *mcuJanusSubscriber) SendMessage(ctx context.Context, message *MessageCl
}
}
case "candidate":
if FilterCandidate(data.candidate, p.mcu.settings.allowedCandidates.Load(), p.mcu.settings.blockedCandidates.Load()) {
go callback(ErrCandidateFiltered, nil)
if api.FilterCandidate(data.Candidate, p.mcu.settings.allowedCandidates.Load(), p.mcu.settings.blockedCandidates.Load()) {
go callback(api.ErrCandidateFiltered, nil)
return
}

View file

@ -38,6 +38,7 @@ import (
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/mock"
)
func TestMcuJanusStats(t *testing.T) {
@ -329,7 +330,7 @@ func (g *TestJanusGateway) processMessage(session *JanusSession, handle *TestJan
},
Jsep: map[string]any{
"type": "offer",
"sdp": MockSdpOfferAudioOnly,
"sdp": mock.MockSdpOfferAudioOnly,
},
})
}
@ -612,10 +613,10 @@ func newMcuJanusForTesting(t *testing.T) (*mcuJanus, *TestJanusGateway) {
}
type TestMcuListener struct {
id PublicSessionId
id api.PublicSessionId
}
func (t *TestMcuListener) PublicId() PublicSessionId {
func (t *TestMcuListener) PublicId() api.PublicSessionId {
return t.id
}
@ -644,10 +645,10 @@ func (t *TestMcuListener) SubscriberClosed(subscriber McuSubscriber) {
}
type TestMcuController struct {
id PublicSessionId
id api.PublicSessionId
}
func (c *TestMcuController) PublisherId() PublicSessionId {
func (c *TestMcuController) PublisherId() api.PublicSessionId {
return c.id
}
@ -695,14 +696,14 @@ func Test_JanusPublisherFilterOffer(t *testing.T) {
if sdpValue, found := jsep["sdp"]; assert.True(found) {
sdpText, ok := sdpValue.(string)
if assert.True(ok) {
assert.Equal(MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(sdpText, "\r\n", "\n"))
assert.Equal(mock.MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(sdpText, "\r\n", "\n"))
}
}
}
return &janus.EventMsg{
Jsep: api.StringMap{
"sdp": MockSdpAnswerAudioOnly,
"sdp": mock.MockSdpAnswerAudioOnly,
},
}, nil
},
@ -715,7 +716,7 @@ func Test_JanusPublisherFilterOffer(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
pubId := PublicSessionId("publisher-id")
pubId := api.PublicSessionId("publisher-id")
listener1 := &TestMcuListener{
id: pubId,
}
@ -730,31 +731,31 @@ func Test_JanusPublisherFilterOffer(t *testing.T) {
defer pub.Close(context.Background())
// Send offer containing candidates that will be blocked / filtered.
data := &MessageClientMessageData{
data := &api.MessageClientMessageData{
Type: "offer",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioOnly,
"sdp": mock.MockSdpOfferAudioOnly,
},
}
require.NoError(data.CheckValid())
var wg sync.WaitGroup
wg.Add(1)
pub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
pub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer wg.Done()
if assert.NoError(err) {
if sdpValue, found := m["sdp"]; assert.True(found) {
sdpText, ok := sdpValue.(string)
if assert.True(ok) {
assert.Equal(MockSdpAnswerAudioOnly, strings.ReplaceAll(sdpText, "\r\n", "\n"))
assert.Equal(mock.MockSdpAnswerAudioOnly, strings.ReplaceAll(sdpText, "\r\n", "\n"))
}
}
}
})
wg.Wait()
data = &MessageClientMessageData{
data = &api.MessageClientMessageData{
Type: "candidate",
Payload: api.StringMap{
"candidate": api.StringMap{
@ -764,7 +765,7 @@ func Test_JanusPublisherFilterOffer(t *testing.T) {
}
require.NoError(data.CheckValid())
wg.Add(1)
pub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
pub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer wg.Done()
assert.ErrorContains(err, "filtered")
@ -772,7 +773,7 @@ func Test_JanusPublisherFilterOffer(t *testing.T) {
})
wg.Wait()
data = &MessageClientMessageData{
data = &api.MessageClientMessageData{
Type: "candidate",
Payload: api.StringMap{
"candidate": api.StringMap{
@ -782,7 +783,7 @@ func Test_JanusPublisherFilterOffer(t *testing.T) {
}
require.NoError(data.CheckValid())
wg.Add(1)
pub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
pub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer wg.Done()
assert.NoError(err)
@ -805,7 +806,7 @@ func Test_JanusSubscriberFilterAnswer(t *testing.T) {
if sdpValue, found := jsep["sdp"]; assert.True(found) {
sdpText, ok := sdpValue.(string)
if assert.True(ok) {
assert.Equal(MockSdpAnswerAudioOnlyNoFilter, strings.ReplaceAll(sdpText, "\r\n", "\n"))
assert.Equal(mock.MockSdpAnswerAudioOnlyNoFilter, strings.ReplaceAll(sdpText, "\r\n", "\n"))
}
}
}
@ -830,7 +831,7 @@ func Test_JanusSubscriberFilterAnswer(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
pubId := PublicSessionId("publisher-id")
pubId := api.PublicSessionId("publisher-id")
listener1 := &TestMcuListener{
id: pubId,
}
@ -856,17 +857,17 @@ func Test_JanusSubscriberFilterAnswer(t *testing.T) {
defer sub.Close(context.Background())
// Send answer containing candidates that will be blocked / filtered.
data := &MessageClientMessageData{
data := &api.MessageClientMessageData{
Type: "answer",
Payload: api.StringMap{
"sdp": MockSdpAnswerAudioOnly,
"sdp": mock.MockSdpAnswerAudioOnly,
},
}
require.NoError(data.CheckValid())
var wg sync.WaitGroup
wg.Add(1)
sub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
sub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer wg.Done()
if assert.NoError(err) {
@ -875,7 +876,7 @@ func Test_JanusSubscriberFilterAnswer(t *testing.T) {
})
wg.Wait()
data = &MessageClientMessageData{
data = &api.MessageClientMessageData{
Type: "candidate",
Payload: api.StringMap{
"candidate": api.StringMap{
@ -885,7 +886,7 @@ func Test_JanusSubscriberFilterAnswer(t *testing.T) {
}
require.NoError(data.CheckValid())
wg.Add(1)
sub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
sub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer wg.Done()
assert.ErrorContains(err, "filtered")
@ -893,7 +894,7 @@ func Test_JanusSubscriberFilterAnswer(t *testing.T) {
})
wg.Wait()
data = &MessageClientMessageData{
data = &api.MessageClientMessageData{
Type: "candidate",
Payload: api.StringMap{
"candidate": api.StringMap{
@ -903,7 +904,7 @@ func Test_JanusSubscriberFilterAnswer(t *testing.T) {
}
require.NoError(data.CheckValid())
wg.Add(1)
sub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
sub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer wg.Done()
assert.NoError(err)
@ -925,14 +926,14 @@ func Test_JanusPublisherGetStreamsAudioOnly(t *testing.T) {
if sdpValue, found := jsep["sdp"]; assert.True(found) {
sdpText, ok := sdpValue.(string)
if assert.True(ok) {
assert.Equal(MockSdpOfferAudioOnly, strings.ReplaceAll(sdpText, "\r\n", "\n"))
assert.Equal(mock.MockSdpOfferAudioOnly, strings.ReplaceAll(sdpText, "\r\n", "\n"))
}
}
}
return &janus.EventMsg{
Jsep: api.StringMap{
"sdp": MockSdpAnswerAudioOnly,
"sdp": mock.MockSdpAnswerAudioOnly,
},
}, nil
},
@ -941,7 +942,7 @@ func Test_JanusPublisherGetStreamsAudioOnly(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
pubId := PublicSessionId("publisher-id")
pubId := api.PublicSessionId("publisher-id")
listener1 := &TestMcuListener{
id: pubId,
}
@ -955,23 +956,23 @@ func Test_JanusPublisherGetStreamsAudioOnly(t *testing.T) {
require.NoError(err)
defer pub.Close(context.Background())
data := &MessageClientMessageData{
data := &api.MessageClientMessageData{
Type: "offer",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioOnly,
"sdp": mock.MockSdpOfferAudioOnly,
},
}
require.NoError(data.CheckValid())
done := make(chan struct{})
pub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
pub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer close(done)
if assert.NoError(err) {
if sdpValue, found := m["sdp"]; assert.True(found) {
sdpText, ok := sdpValue.(string)
if assert.True(ok) {
assert.Equal(MockSdpAnswerAudioOnly, strings.ReplaceAll(sdpText, "\r\n", "\n"))
assert.Equal(mock.MockSdpAnswerAudioOnly, strings.ReplaceAll(sdpText, "\r\n", "\n"))
}
}
}
@ -1011,7 +1012,7 @@ func Test_JanusPublisherGetStreamsAudioVideo(t *testing.T) {
return &janus.EventMsg{
Jsep: api.StringMap{
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}, nil
},
@ -1020,7 +1021,7 @@ func Test_JanusPublisherGetStreamsAudioVideo(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
pubId := PublicSessionId("publisher-id")
pubId := api.PublicSessionId("publisher-id")
listener1 := &TestMcuListener{
id: pubId,
}
@ -1034,10 +1035,10 @@ func Test_JanusPublisherGetStreamsAudioVideo(t *testing.T) {
require.NoError(err)
defer pub.Close(context.Background())
data := &MessageClientMessageData{
data := &api.MessageClientMessageData{
Type: "offer",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}
require.NoError(data.CheckValid())
@ -1045,14 +1046,14 @@ func Test_JanusPublisherGetStreamsAudioVideo(t *testing.T) {
// Defer sending of offer / answer so "GetStreams" will wait.
go func() {
done := make(chan struct{})
pub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
pub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer close(done)
if assert.NoError(err) {
if sdpValue, found := m["sdp"]; assert.True(found) {
sdpText, ok := sdpValue.(string)
if assert.True(ok) {
assert.Equal(MockSdpAnswerAudioAndVideo, strings.ReplaceAll(sdpText, "\r\n", "\n"))
assert.Equal(mock.MockSdpAnswerAudioAndVideo, strings.ReplaceAll(sdpText, "\r\n", "\n"))
}
}
}
@ -1114,7 +1115,7 @@ func Test_JanusPublisherSubscriber(t *testing.T) {
assert.EqualValues(0, stats.incoming)
assert.EqualValues(0, stats.outgoing)
pubId := PublicSessionId("publisher-id")
pubId := api.PublicSessionId("publisher-id")
listener1 := &TestMcuListener{
id: pubId,
}
@ -1188,7 +1189,7 @@ func Test_JanusSubscriberPublisher(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
pubId := PublicSessionId("publisher-id")
pubId := api.PublicSessionId("publisher-id")
listener1 := &TestMcuListener{
id: pubId,
}
@ -1248,7 +1249,7 @@ func Test_JanusSubscriberRequestOffer(t *testing.T) {
return &janus.EventMsg{
Jsep: api.StringMap{
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}, nil
},
@ -1257,7 +1258,7 @@ func Test_JanusSubscriberRequestOffer(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
pubId := PublicSessionId("publisher-id")
pubId := api.PublicSessionId("publisher-id")
listener1 := &TestMcuListener{
id: pubId,
}
@ -1283,10 +1284,10 @@ func Test_JanusSubscriberRequestOffer(t *testing.T) {
defer sub.Close(context.Background())
go func() {
data := &MessageClientMessageData{
data := &api.MessageClientMessageData{
Type: "offer",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}
if !assert.NoError(data.CheckValid()) {
@ -1294,14 +1295,14 @@ func Test_JanusSubscriberRequestOffer(t *testing.T) {
}
done := make(chan struct{})
pub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
pub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer close(done)
if assert.NoError(err) {
if sdpValue, found := m["sdp"]; assert.True(found) {
sdpText, ok := sdpValue.(string)
if assert.True(ok) {
assert.Equal(MockSdpAnswerAudioAndVideo, strings.ReplaceAll(sdpText, "\r\n", "\n"))
assert.Equal(mock.MockSdpAnswerAudioAndVideo, strings.ReplaceAll(sdpText, "\r\n", "\n"))
}
}
}
@ -1309,13 +1310,13 @@ func Test_JanusSubscriberRequestOffer(t *testing.T) {
<-done
}()
data := &MessageClientMessageData{
data := &api.MessageClientMessageData{
Type: "requestoffer",
}
require.NoError(data.CheckValid())
done := make(chan struct{})
sub.SendMessage(ctx, &MessageClientMessage{}, data, func(err error, m api.StringMap) {
sub.SendMessage(ctx, &api.MessageClientMessage{}, data, func(err error, m api.StringMap) {
defer close(done)
if assert.NoError(err) {
@ -1477,7 +1478,7 @@ func Test_JanusSubscriberNoSuchRoom(t *testing.T) {
return &janus.EventMsg{
Jsep: api.StringMap{
"type": "answer",
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}, nil
},
@ -1524,38 +1525,38 @@ func Test_JanusSubscriberNoSuchRoom(t *testing.T) {
checkReceiveClientEvent(ctx, t, client1, "update", nil)
checkReceiveClientEvent(ctx, t, client2, "update", nil)
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo)
client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo)
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
MustSucceed2(t, client2.RunUntilError, ctx, "processing_failed") // nolint
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo)
}
func test_JanusSubscriberAlreadyJoined(t *testing.T) {
@ -1579,7 +1580,7 @@ func test_JanusSubscriberAlreadyJoined(t *testing.T) {
return &janus.EventMsg{
Jsep: api.StringMap{
"type": "answer",
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}, nil
},
@ -1626,23 +1627,23 @@ func test_JanusSubscriberAlreadyJoined(t *testing.T) {
checkReceiveClientEvent(ctx, t, client1, "update", nil)
checkReceiveClientEvent(ctx, t, client2, "update", nil)
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo)
client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo)
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
@ -1650,16 +1651,16 @@ func test_JanusSubscriberAlreadyJoined(t *testing.T) {
if strings.Contains(t.Name(), "AttachError") {
MustSucceed2(t, client2.RunUntilError, ctx, "processing_failed") // nolint
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
}
client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo)
}
func Test_JanusSubscriberAlreadyJoined(t *testing.T) {
@ -1694,7 +1695,7 @@ func Test_JanusSubscriberTimeout(t *testing.T) {
return &janus.EventMsg{
Jsep: api.StringMap{
"type": "answer",
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}, nil
},
@ -1741,25 +1742,25 @@ func Test_JanusSubscriberTimeout(t *testing.T) {
checkReceiveClientEvent(ctx, t, client1, "update", nil)
checkReceiveClientEvent(ctx, t, client2, "update", nil)
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo)
client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo)
oldTimeout := mcu.settings.timeout.Swap(100 * int64(time.Millisecond))
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
@ -1768,15 +1769,15 @@ func Test_JanusSubscriberTimeout(t *testing.T) {
mcu.settings.timeout.Store(oldTimeout)
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo)
}
func Test_JanusSubscriberCloseEmptyStreams(t *testing.T) {
@ -1801,7 +1802,7 @@ func Test_JanusSubscriberCloseEmptyStreams(t *testing.T) {
return &janus.EventMsg{
Jsep: api.StringMap{
"type": "answer",
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}, nil
},
@ -1848,28 +1849,28 @@ func Test_JanusSubscriberCloseEmptyStreams(t *testing.T) {
checkReceiveClientEvent(ctx, t, client1, "update", nil)
checkReceiveClientEvent(ctx, t, client2, "update", nil)
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo)
client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo)
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo)
sess2 := hub.GetSessionByPublicId(hello2.Hello.SessionId)
require.NotNil(sess2)
@ -1915,7 +1916,7 @@ func Test_JanusSubscriberRoomDestroyed(t *testing.T) {
return &janus.EventMsg{
Jsep: api.StringMap{
"type": "answer",
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}, nil
},
@ -1962,28 +1963,28 @@ func Test_JanusSubscriberRoomDestroyed(t *testing.T) {
checkReceiveClientEvent(ctx, t, client1, "update", nil)
checkReceiveClientEvent(ctx, t, client2, "update", nil)
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo)
client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo)
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo)
sess2 := hub.GetSessionByPublicId(hello2.Hello.SessionId)
require.NotNil(sess2)
@ -2029,7 +2030,7 @@ func Test_JanusSubscriberUpdateOffer(t *testing.T) {
return &janus.EventMsg{
Jsep: api.StringMap{
"type": "answer",
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
},
}, nil
},
@ -2076,29 +2077,29 @@ func Test_JanusSubscriberUpdateOffer(t *testing.T) {
checkReceiveClientEvent(ctx, t, client1, "update", nil)
checkReceiveClientEvent(ctx, t, client2, "update", nil)
require.NoError(client1.SendMessage(MessageClientMessageRecipient{
require.NoError(client1.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "offer",
RoomType: "video",
Payload: api.StringMap{
"sdp": MockSdpOfferAudioAndVideo,
"sdp": mock.MockSdpOfferAudioAndVideo,
},
}))
client1.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo)
client1.RunUntilAnswer(ctx, mock.MockSdpAnswerAudioAndVideo)
require.NoError(client2.SendMessage(MessageClientMessageRecipient{
require.NoError(client2.SendMessage(api.MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}, MessageClientMessageData{
}, api.MessageClientMessageData{
Type: "requestoffer",
RoomType: "video",
}))
client2.RunUntilOffer(ctx, MockSdpOfferAudioAndVideo)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioAndVideo)
// Test MCU will trigger an updated offer.
client2.RunUntilOffer(ctx, MockSdpOfferAudioOnly)
client2.RunUntilOffer(ctx, mock.MockSdpOfferAudioOnly)
}

View file

@ -147,11 +147,11 @@ func (c *mcuProxyPubSubCommon) doProcessPayload(client McuClient, msg *PayloadPr
type mcuProxyPublisher struct {
mcuProxyPubSubCommon
id PublicSessionId
id api.PublicSessionId
settings NewPublisherSettings
}
func newMcuProxyPublisher(logger log.Logger, id PublicSessionId, sid string, streamType StreamType, maxBitrate api.Bandwidth, settings NewPublisherSettings, proxyId string, conn *mcuProxyConnection, listener McuListener) *mcuProxyPublisher {
func newMcuProxyPublisher(logger log.Logger, id api.PublicSessionId, sid string, streamType StreamType, maxBitrate api.Bandwidth, settings NewPublisherSettings, proxyId string, conn *mcuProxyConnection, listener McuListener) *mcuProxyPublisher {
return &mcuProxyPublisher{
mcuProxyPubSubCommon: mcuProxyPubSubCommon{
logger: logger,
@ -168,7 +168,7 @@ func newMcuProxyPublisher(logger log.Logger, id PublicSessionId, sid string, str
}
}
func (p *mcuProxyPublisher) PublisherId() PublicSessionId {
func (p *mcuProxyPublisher) PublisherId() api.PublicSessionId {
return p.id
}
@ -209,7 +209,7 @@ func (p *mcuProxyPublisher) Close(ctx context.Context) {
p.logger.Printf("Deleted publisher %s at %s", p.proxyId, p.conn)
}
func (p *mcuProxyPublisher) SendMessage(ctx context.Context, message *MessageClientMessage, data *MessageClientMessageData, callback func(error, api.StringMap)) {
func (p *mcuProxyPublisher) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
msg := &ProxyClientMessage{
Type: "payload",
Payload: &PayloadProxyClientMessage{
@ -241,11 +241,11 @@ func (p *mcuProxyPublisher) ProcessEvent(msg *EventProxyServerMessage) {
type mcuProxySubscriber struct {
mcuProxyPubSubCommon
publisherId PublicSessionId
publisherId api.PublicSessionId
publisherConn *mcuProxyConnection
}
func newMcuProxySubscriber(logger log.Logger, publisherId PublicSessionId, sid string, streamType StreamType, maxBitrate api.Bandwidth, proxyId string, conn *mcuProxyConnection, listener McuListener, publisherConn *mcuProxyConnection) *mcuProxySubscriber {
func newMcuProxySubscriber(logger log.Logger, publisherId api.PublicSessionId, sid string, streamType StreamType, maxBitrate api.Bandwidth, proxyId string, conn *mcuProxyConnection, listener McuListener, publisherConn *mcuProxyConnection) *mcuProxySubscriber {
return &mcuProxySubscriber{
mcuProxyPubSubCommon: mcuProxyPubSubCommon{
logger: logger,
@ -263,7 +263,7 @@ func newMcuProxySubscriber(logger log.Logger, publisherId PublicSessionId, sid s
}
}
func (s *mcuProxySubscriber) Publisher() PublicSessionId {
func (s *mcuProxySubscriber) Publisher() api.PublicSessionId {
return s.publisherId
}
@ -311,7 +311,7 @@ func (s *mcuProxySubscriber) Close(ctx context.Context) {
}
}
func (s *mcuProxySubscriber) SendMessage(ctx context.Context, message *MessageClientMessage, data *MessageClientMessageData, callback func(error, api.StringMap)) {
func (s *mcuProxySubscriber) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
msg := &ProxyClientMessage{
Type: "payload",
Payload: &PayloadProxyClientMessage{
@ -389,7 +389,7 @@ type mcuProxyConnection struct {
// +checklocks:publishersLock
publishers map[string]*mcuProxyPublisher
// +checklocks:publishersLock
publisherIds map[StreamId]PublicSessionId
publisherIds map[StreamId]api.PublicSessionId
subscribersLock sync.RWMutex
// +checklocks:subscribersLock
@ -413,7 +413,7 @@ func newMcuProxyConnection(proxy *mcuProxy, baseUrl string, ip net.IP, token str
closedDone: internal.NewCloser(),
callbacks: make(map[string]mcuProxyCallback),
publishers: make(map[string]*mcuProxyPublisher),
publisherIds: make(map[StreamId]PublicSessionId),
publisherIds: make(map[StreamId]api.PublicSessionId),
subscribers: make(map[string]*mcuProxySubscriber),
}
conn.reconnectInterval.Store(int64(initialReconnectInterval))
@ -548,13 +548,13 @@ func (c *mcuProxyConnection) Features() []string {
return c.features.Load().([]string)
}
func (c *mcuProxyConnection) SessionId() PublicSessionId {
func (c *mcuProxyConnection) SessionId() api.PublicSessionId {
sid := c.sessionId.Load()
if sid == nil {
return ""
}
return sid.(PublicSessionId)
return sid.(api.PublicSessionId)
}
func (c *mcuProxyConnection) IsConnected() bool {
@ -989,7 +989,7 @@ func (c *mcuProxyConnection) processMessage(msg *ProxyServerMessage) {
c.clearPublishers()
c.clearSubscribers()
c.clearCallbacks()
c.sessionId.Store(PublicSessionId(""))
c.sessionId.Store(api.PublicSessionId(""))
if err := c.sendHello(); err != nil {
c.logger.Printf("Could not send hello request to %s: %s", c, err)
c.scheduleReconnect()
@ -1157,7 +1157,7 @@ func (c *mcuProxyConnection) processBye(msg *ProxyServerMessage) {
default:
c.logger.Printf("Received bye with unsupported reason from %s %+v", c, bye)
}
c.sessionId.Store(PublicSessionId(""))
c.sessionId.Store(api.PublicSessionId(""))
}
func (c *mcuProxyConnection) sendHello() error {
@ -1253,7 +1253,7 @@ func (c *mcuProxyConnection) performSyncRequest(ctx context.Context, msg *ProxyC
}
}
func (c *mcuProxyConnection) deferredDeletePublisher(id PublicSessionId, streamType StreamType, response *ProxyServerMessage) {
func (c *mcuProxyConnection) deferredDeletePublisher(id api.PublicSessionId, streamType StreamType, response *ProxyServerMessage) {
if response.Type == "error" {
c.logger.Printf("Publisher for %s was not created at %s: %s", id, c, response.Error)
return
@ -1283,7 +1283,7 @@ func (c *mcuProxyConnection) deferredDeletePublisher(id PublicSessionId, streamT
c.logger.Printf("Deleted publisher %s at %s", proxyId, c)
}
func (c *mcuProxyConnection) newPublisher(ctx context.Context, listener McuListener, id PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings) (McuPublisher, error) {
func (c *mcuProxyConnection) newPublisher(ctx context.Context, listener McuListener, id api.PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings) (McuPublisher, error) {
msg := &ProxyClientMessage{
Type: "command",
Command: &CommandProxyClientMessage{
@ -1314,14 +1314,14 @@ func (c *mcuProxyConnection) newPublisher(ctx context.Context, listener McuListe
publisher := newMcuProxyPublisher(c.logger, id, sid, streamType, response.Command.Bitrate, settings, proxyId, c, listener)
c.publishersLock.Lock()
c.publishers[proxyId] = publisher
c.publisherIds[getStreamId(id, streamType)] = PublicSessionId(proxyId)
c.publisherIds[getStreamId(id, streamType)] = api.PublicSessionId(proxyId)
c.publishersLock.Unlock()
statsPublishersCurrent.WithLabelValues(string(streamType)).Inc()
statsPublishersTotal.WithLabelValues(string(streamType)).Inc()
return publisher, nil
}
func (c *mcuProxyConnection) deferredDeleteSubscriber(publisherSessionId PublicSessionId, streamType StreamType, publisherConn *mcuProxyConnection, response *ProxyServerMessage) {
func (c *mcuProxyConnection) deferredDeleteSubscriber(publisherSessionId api.PublicSessionId, streamType StreamType, publisherConn *mcuProxyConnection, response *ProxyServerMessage) {
if response.Type == "error" {
c.logger.Printf("Subscriber for %s was not created at %s: %s", publisherSessionId, c, response.Error)
return
@ -1364,7 +1364,7 @@ func (c *mcuProxyConnection) deferredDeleteSubscriber(publisherSessionId PublicS
}
}
func (c *mcuProxyConnection) newSubscriber(ctx context.Context, listener McuListener, publisherId PublicSessionId, publisherSessionId PublicSessionId, streamType StreamType) (McuSubscriber, error) {
func (c *mcuProxyConnection) newSubscriber(ctx context.Context, listener McuListener, publisherId api.PublicSessionId, publisherSessionId api.PublicSessionId, streamType StreamType) (McuSubscriber, error) {
msg := &ProxyClientMessage{
Type: "command",
Command: &CommandProxyClientMessage{
@ -1397,7 +1397,7 @@ func (c *mcuProxyConnection) newSubscriber(ctx context.Context, listener McuList
return subscriber, nil
}
func (c *mcuProxyConnection) newRemoteSubscriber(ctx context.Context, listener McuListener, publisherId PublicSessionId, publisherSessionId PublicSessionId, streamType StreamType, publisherConn *mcuProxyConnection, remoteToken string) (McuSubscriber, error) {
func (c *mcuProxyConnection) newRemoteSubscriber(ctx context.Context, listener McuListener, publisherId api.PublicSessionId, publisherSessionId api.PublicSessionId, streamType StreamType, publisherConn *mcuProxyConnection, remoteToken string) (McuSubscriber, error) {
if c == publisherConn {
return c.newSubscriber(ctx, listener, publisherId, publisherSessionId, streamType)
}
@ -2024,7 +2024,7 @@ func (m *mcuProxy) removePublisher(publisher *mcuProxyPublisher) {
delete(m.publishers, getStreamId(publisher.id, publisher.StreamType()))
}
func (m *mcuProxy) createPublisher(ctx context.Context, listener McuListener, id PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator, connections []*mcuProxyConnection, isAllowed func(c *mcuProxyConnection) bool) McuPublisher {
func (m *mcuProxy) createPublisher(ctx context.Context, listener McuListener, id api.PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator, connections []*mcuProxyConnection, isAllowed func(c *mcuProxyConnection) bool) McuPublisher {
var maxBitrate api.Bandwidth
if streamType == StreamTypeScreen {
maxBitrate = m.settings.MaxScreenBitrate()
@ -2063,7 +2063,7 @@ func (m *mcuProxy) createPublisher(ctx context.Context, listener McuListener, id
return nil
}
func (m *mcuProxy) NewPublisher(ctx context.Context, listener McuListener, id PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator) (McuPublisher, error) {
func (m *mcuProxy) NewPublisher(ctx context.Context, listener McuListener, id api.PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator) (McuPublisher, error) {
connections := m.getSortedConnections(initiator)
publisher := m.createPublisher(ctx, listener, id, sid, streamType, settings, initiator, connections, func(c *mcuProxyConnection) bool {
bw := c.Bandwidth()
@ -2116,14 +2116,14 @@ func (m *mcuProxy) NewPublisher(ctx context.Context, listener McuListener, id Pu
return publisher, nil
}
func (m *mcuProxy) getPublisherConnection(publisher PublicSessionId, streamType StreamType) *mcuProxyConnection {
func (m *mcuProxy) getPublisherConnection(publisher api.PublicSessionId, streamType StreamType) *mcuProxyConnection {
m.mu.RLock()
defer m.mu.RUnlock()
return m.publishers[getStreamId(publisher, streamType)]
}
func (m *mcuProxy) waitForPublisherConnection(ctx context.Context, publisher PublicSessionId, streamType StreamType) *mcuProxyConnection {
func (m *mcuProxy) waitForPublisherConnection(ctx context.Context, publisher api.PublicSessionId, streamType StreamType) *mcuProxyConnection {
m.mu.Lock()
defer m.mu.Unlock()
@ -2155,13 +2155,13 @@ func (m *mcuProxy) waitForPublisherConnection(ctx context.Context, publisher Pub
}
type proxyPublisherInfo struct {
id PublicSessionId
id api.PublicSessionId
conn *mcuProxyConnection
token string
err error
}
func (m *mcuProxy) createSubscriber(ctx context.Context, listener McuListener, info *proxyPublisherInfo, publisher PublicSessionId, streamType StreamType, connections []*mcuProxyConnection, isAllowed func(c *mcuProxyConnection) bool) McuSubscriber {
func (m *mcuProxy) createSubscriber(ctx context.Context, listener McuListener, info *proxyPublisherInfo, publisher api.PublicSessionId, streamType StreamType, connections []*mcuProxyConnection, isAllowed func(c *mcuProxyConnection) bool) McuSubscriber {
for _, conn := range connections {
if !isAllowed(conn) || conn.IsShutdownScheduled() || conn.IsTemporary() {
continue
@ -2188,7 +2188,7 @@ func (m *mcuProxy) createSubscriber(ctx context.Context, listener McuListener, i
return nil
}
func (m *mcuProxy) NewSubscriber(ctx context.Context, listener McuListener, publisher PublicSessionId, streamType StreamType, initiator McuInitiator) (McuSubscriber, error) {
func (m *mcuProxy) NewSubscriber(ctx context.Context, listener McuListener, publisher api.PublicSessionId, streamType StreamType, initiator McuInitiator) (McuSubscriber, error) {
var publisherInfo *proxyPublisherInfo
if conn := m.getPublisherConnection(publisher, streamType); conn != nil {
// Fast common path: publisher is available locally.

View file

@ -49,6 +49,7 @@ import (
"github.com/stretchr/testify/require"
"go.etcd.io/etcd/server/v3/embed"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/internal"
"github.com/strukturag/nextcloud-spreed-signaling/log"
)
@ -199,7 +200,7 @@ func Test_sortConnectionsForCountryWithOverride(t *testing.T) {
type proxyServerClientHandler func(msg *ProxyClientMessage) (*ProxyServerMessage, error)
type testProxyServerPublisher struct {
id PublicSessionId
id api.PublicSessionId
}
type testProxyServerSubscriber struct {
@ -219,7 +220,7 @@ type testProxyServerClient struct {
processMessage proxyServerClientHandler
mu sync.Mutex
sessionId PublicSessionId
sessionId api.PublicSessionId
}
func (c *testProxyServerClient) processHello(msg *ProxyClientMessage) (*ProxyServerMessage, error) {
@ -233,7 +234,7 @@ func (c *testProxyServerClient) processHello(msg *ProxyClientMessage) (*ProxySer
response := &ProxyServerMessage{
Id: msg.Id,
Type: "error",
Error: &Error{
Error: &api.Error{
Code: "no_such_session",
},
}
@ -248,7 +249,7 @@ func (c *testProxyServerClient) processHello(msg *ProxyClientMessage) (*ProxySer
Hello: &HelloProxyServerMessage{
Version: "1.0",
SessionId: c.sessionId,
Server: &WelcomeServerMessage{
Server: &api.WelcomeServerMessage{
Version: "1.0",
Country: c.server.country,
},
@ -284,7 +285,7 @@ func (c *testProxyServerClient) processHello(msg *ProxyClientMessage) (*ProxySer
Hello: &HelloProxyServerMessage{
Version: "1.0",
SessionId: c.sessionId,
Server: &WelcomeServerMessage{
Server: &api.WelcomeServerMessage{
Version: "1.0",
Country: c.server.country,
},
@ -347,7 +348,7 @@ func (c *testProxyServerClient) processCommandMessage(msg *ProxyClientMessage) (
defer c.server.Wakeup()
}
if pub, found := c.server.deletePublisher(PublicSessionId(msg.Command.ClientId)); !found {
if pub, found := c.server.deletePublisher(api.PublicSessionId(msg.Command.ClientId)); !found {
response = msg.NewWrappedErrorServerMessage(fmt.Errorf("publisher %s not found", msg.Command.ClientId))
} else {
response = &ProxyServerMessage{
@ -564,9 +565,9 @@ type TestProxyServerHandler struct {
incoming atomic.Pointer[float64]
outgoing atomic.Pointer[float64]
// +checklocks:mu
clients map[PublicSessionId]*testProxyServerClient
clients map[api.PublicSessionId]*testProxyServerClient
// +checklocks:mu
publishers map[PublicSessionId]*testProxyServerPublisher
publishers map[api.PublicSessionId]*testProxyServerPublisher
// +checklocks:mu
subscribers map[string]*testProxyServerSubscriber
@ -577,7 +578,7 @@ func (h *TestProxyServerHandler) createPublisher() *testProxyServerPublisher {
h.mu.Lock()
defer h.mu.Unlock()
pub := &testProxyServerPublisher{
id: PublicSessionId(newRandomString(32)),
id: api.PublicSessionId(newRandomString(32)),
}
for {
@ -585,20 +586,20 @@ func (h *TestProxyServerHandler) createPublisher() *testProxyServerPublisher {
break
}
pub.id = PublicSessionId(newRandomString(32))
pub.id = api.PublicSessionId(newRandomString(32))
}
h.publishers[pub.id] = pub
return pub
}
func (h *TestProxyServerHandler) getPublisher(id PublicSessionId) *testProxyServerPublisher {
func (h *TestProxyServerHandler) getPublisher(id api.PublicSessionId) *testProxyServerPublisher {
h.mu.Lock()
defer h.mu.Unlock()
return h.publishers[id]
}
func (h *TestProxyServerHandler) deletePublisher(id PublicSessionId) (*testProxyServerPublisher, bool) {
func (h *TestProxyServerHandler) deletePublisher(id api.PublicSessionId) (*testProxyServerPublisher, bool) {
h.mu.Lock()
defer h.mu.Unlock()
@ -748,7 +749,7 @@ func (h *TestProxyServerHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
t: h.t,
server: h,
ws: ws,
sessionId: PublicSessionId(newRandomString(32)),
sessionId: api.PublicSessionId(newRandomString(32)),
}
h.setClient(client.sessionId, client)
@ -756,14 +757,14 @@ func (h *TestProxyServerHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
go client.run()
}
func (h *TestProxyServerHandler) getClient(sessionId PublicSessionId) *testProxyServerClient {
func (h *TestProxyServerHandler) getClient(sessionId api.PublicSessionId) *testProxyServerClient {
h.mu.Lock()
defer h.mu.Unlock()
return h.clients[sessionId]
}
func (h *TestProxyServerHandler) setClient(sessionId PublicSessionId, client *testProxyServerClient) {
func (h *TestProxyServerHandler) setClient(sessionId api.PublicSessionId, client *testProxyServerClient) {
h.mu.Lock()
defer h.mu.Unlock()
@ -820,8 +821,8 @@ func NewProxyServerForTest(t *testing.T, country string) *TestProxyServerHandler
tokens: make(map[string]*rsa.PublicKey),
upgrader: &upgrader,
country: country,
clients: make(map[PublicSessionId]*testProxyServerClient),
publishers: make(map[PublicSessionId]*testProxyServerPublisher),
clients: make(map[api.PublicSessionId]*testProxyServerClient),
publishers: make(map[api.PublicSessionId]*testProxyServerPublisher),
subscribers: make(map[string]*testProxyServerSubscriber),
wakeupChan: make(chan struct{}),
}
@ -1150,7 +1151,7 @@ func Test_ProxyPublisherSubscriber(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -1185,7 +1186,7 @@ func Test_ProxyPublisherCodecs(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -1211,7 +1212,7 @@ func Test_ProxyWaitForPublisher(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -1265,7 +1266,7 @@ func Test_ProxyPublisherBandwidth(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pub1Id := PublicSessionId("the-publisher-1")
pub1Id := api.PublicSessionId("the-publisher-1")
pub1Sid := "1234567890"
pub1Listener := &MockMcuListener{
publicId: pub1Id + "-public",
@ -1304,7 +1305,7 @@ func Test_ProxyPublisherBandwidth(t *testing.T) {
time.Sleep(time.Millisecond)
}
pub2Id := PublicSessionId("the-publisher-2")
pub2Id := api.PublicSessionId("the-publisher-2")
pub2id := "1234567890"
pub2Listener := &MockMcuListener{
publicId: pub2Id + "-public",
@ -1334,7 +1335,7 @@ func Test_ProxyPublisherBandwidthOverload(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pub1Id := PublicSessionId("the-publisher-1")
pub1Id := api.PublicSessionId("the-publisher-1")
pub1Sid := "1234567890"
pub1Listener := &MockMcuListener{
publicId: pub1Id + "-public",
@ -1376,7 +1377,7 @@ func Test_ProxyPublisherBandwidthOverload(t *testing.T) {
time.Sleep(time.Millisecond)
}
pub2Id := PublicSessionId("the-publisher-2")
pub2Id := api.PublicSessionId("the-publisher-2")
pub2id := "1234567890"
pub2Listener := &MockMcuListener{
publicId: pub2Id + "-public",
@ -1406,7 +1407,7 @@ func Test_ProxyPublisherLoad(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pub1Id := PublicSessionId("the-publisher-1")
pub1Id := api.PublicSessionId("the-publisher-1")
pub1Sid := "1234567890"
pub1Listener := &MockMcuListener{
publicId: pub1Id + "-public",
@ -1425,7 +1426,7 @@ func Test_ProxyPublisherLoad(t *testing.T) {
mcu.nextSort.Store(0)
time.Sleep(100 * time.Millisecond)
pub2Id := PublicSessionId("the-publisher-2")
pub2Id := api.PublicSessionId("the-publisher-2")
pub2id := "1234567890"
pub2Listener := &MockMcuListener{
publicId: pub2Id + "-public",
@ -1455,7 +1456,7 @@ func Test_ProxyPublisherCountry(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubDEId := PublicSessionId("the-publisher-de")
pubDEId := api.PublicSessionId("the-publisher-de")
pubDESid := "1234567890"
pubDEListener := &MockMcuListener{
publicId: pubDEId + "-public",
@ -1472,7 +1473,7 @@ func Test_ProxyPublisherCountry(t *testing.T) {
assert.Equal(t, serverDE.URL, pubDE.(*mcuProxyPublisher).conn.rawUrl)
pubUSId := PublicSessionId("the-publisher-us")
pubUSId := api.PublicSessionId("the-publisher-us")
pubUSSid := "1234567890"
pubUSListener := &MockMcuListener{
publicId: pubUSId + "-public",
@ -1502,7 +1503,7 @@ func Test_ProxyPublisherContinent(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubDEId := PublicSessionId("the-publisher-de")
pubDEId := api.PublicSessionId("the-publisher-de")
pubDESid := "1234567890"
pubDEListener := &MockMcuListener{
publicId: pubDEId + "-public",
@ -1519,7 +1520,7 @@ func Test_ProxyPublisherContinent(t *testing.T) {
assert.Equal(t, serverDE.URL, pubDE.(*mcuProxyPublisher).conn.rawUrl)
pubFRId := PublicSessionId("the-publisher-fr")
pubFRId := api.PublicSessionId("the-publisher-fr")
pubFRSid := "1234567890"
pubFRListener := &MockMcuListener{
publicId: pubFRId + "-public",
@ -1549,7 +1550,7 @@ func Test_ProxySubscriberCountry(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -1592,7 +1593,7 @@ func Test_ProxySubscriberContinent(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -1635,7 +1636,7 @@ func Test_ProxySubscriberBandwidth(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -1698,7 +1699,7 @@ func Test_ProxySubscriberBandwidthOverload(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -1754,14 +1755,14 @@ type mockGrpcServerHub struct {
proxy atomic.Pointer[mcuProxy]
sessionsLock sync.Mutex
// +checklocks:sessionsLock
sessionByPublicId map[PublicSessionId]Session
sessionByPublicId map[api.PublicSessionId]Session
}
func (h *mockGrpcServerHub) addSession(session *ClientSession) {
h.sessionsLock.Lock()
defer h.sessionsLock.Unlock()
if h.sessionByPublicId == nil {
h.sessionByPublicId = make(map[PublicSessionId]Session)
h.sessionByPublicId = make(map[api.PublicSessionId]Session)
}
h.sessionByPublicId[session.PublicId()] = session
}
@ -1772,17 +1773,17 @@ func (h *mockGrpcServerHub) removeSession(session *ClientSession) {
delete(h.sessionByPublicId, session.PublicId())
}
func (h *mockGrpcServerHub) GetSessionByResumeId(resumeId PrivateSessionId) Session {
func (h *mockGrpcServerHub) GetSessionByResumeId(resumeId api.PrivateSessionId) Session {
return nil
}
func (h *mockGrpcServerHub) GetSessionByPublicId(sessionId PublicSessionId) Session {
func (h *mockGrpcServerHub) GetSessionByPublicId(sessionId api.PublicSessionId) Session {
h.sessionsLock.Lock()
defer h.sessionsLock.Unlock()
return h.sessionByPublicId[sessionId]
}
func (h *mockGrpcServerHub) GetSessionIdByRoomSessionId(roomSessionId RoomSessionId) (PublicSessionId, error) {
func (h *mockGrpcServerHub) GetSessionIdByRoomSessionId(roomSessionId api.RoomSessionId) (api.PublicSessionId, error) {
return "", nil
}
@ -1842,7 +1843,7 @@ func Test_ProxyRemotePublisher(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -1937,7 +1938,7 @@ func Test_ProxyMultipleRemotePublisher(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -2027,7 +2028,7 @@ func Test_ProxyRemotePublisherWait(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -2120,7 +2121,7 @@ func Test_ProxyRemotePublisherTemporary(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -2231,7 +2232,7 @@ func Test_ProxyConnectToken(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -2316,7 +2317,7 @@ func Test_ProxyPublisherToken(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -2368,7 +2369,7 @@ func Test_ProxyPublisherTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",
@ -2408,7 +2409,7 @@ func Test_ProxySubscriberTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()
pubId := PublicSessionId("the-publisher")
pubId := api.PublicSessionId("the-publisher")
pubSid := "1234567890"
pubListener := &MockMcuListener{
publicId: pubId + "-public",

View file

@ -34,6 +34,7 @@ import (
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/mock"
)
var (
@ -45,7 +46,7 @@ type TestMCU struct {
t *testing.T
mu sync.Mutex
// +checklocks:mu
publishers map[PublicSessionId]*TestMCUPublisher
publishers map[api.PublicSessionId]*TestMCUPublisher
// +checklocks:mu
subscribers map[string]*TestMCUSubscriber
@ -57,7 +58,7 @@ func NewTestMCU(t *testing.T) *TestMCU {
return &TestMCU{
t: t,
publishers: make(map[PublicSessionId]*TestMCUPublisher),
publishers: make(map[api.PublicSessionId]*TestMCUPublisher),
subscribers: make(map[string]*TestMCUSubscriber),
}
}
@ -95,7 +96,7 @@ func (m *TestMCU) GetServerInfoSfu() *BackendServerInfoSfu {
return nil
}
func (m *TestMCU) NewPublisher(ctx context.Context, listener McuListener, id PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator) (McuPublisher, error) {
func (m *TestMCU) NewPublisher(ctx context.Context, listener McuListener, id api.PublicSessionId, sid string, streamType StreamType, settings NewPublisherSettings, initiator McuInitiator) (McuPublisher, error) {
var maxBitrate api.Bandwidth
if streamType == StreamTypeScreen {
maxBitrate = TestMaxBitrateScreen
@ -125,7 +126,7 @@ func (m *TestMCU) NewPublisher(ctx context.Context, listener McuListener, id Pub
return pub, nil
}
func (m *TestMCU) GetPublishers() map[PublicSessionId]*TestMCUPublisher {
func (m *TestMCU) GetPublishers() map[api.PublicSessionId]*TestMCUPublisher {
m.mu.Lock()
defer m.mu.Unlock()
@ -133,14 +134,14 @@ func (m *TestMCU) GetPublishers() map[PublicSessionId]*TestMCUPublisher {
return result
}
func (m *TestMCU) GetPublisher(id PublicSessionId) *TestMCUPublisher {
func (m *TestMCU) GetPublisher(id api.PublicSessionId) *TestMCUPublisher {
m.mu.Lock()
defer m.mu.Unlock()
return m.publishers[id]
}
func (m *TestMCU) NewSubscriber(ctx context.Context, listener McuListener, publisher PublicSessionId, streamType StreamType, initiator McuInitiator) (McuSubscriber, error) {
func (m *TestMCU) NewSubscriber(ctx context.Context, listener McuListener, publisher api.PublicSessionId, streamType StreamType, initiator McuInitiator) (McuSubscriber, error) {
m.mu.Lock()
defer m.mu.Unlock()
@ -206,8 +207,8 @@ type TestMCUPublisher struct {
sdp string
}
func (p *TestMCUPublisher) PublisherId() PublicSessionId {
return PublicSessionId(p.id)
func (p *TestMCUPublisher) PublisherId() api.PublicSessionId {
return api.PublicSessionId(p.id)
}
func (p *TestMCUPublisher) HasMedia(mt MediaType) bool {
@ -218,7 +219,7 @@ func (p *TestMCUPublisher) SetMedia(mt MediaType) {
p.settings.MediaTypes = mt
}
func (p *TestMCUPublisher) SendMessage(ctx context.Context, message *MessageClientMessage, data *MessageClientMessageData, callback func(error, api.StringMap)) {
func (p *TestMCUPublisher) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
go func() {
if p.isClosed() {
callback(errors.New("Already closed"), nil)
@ -231,16 +232,16 @@ func (p *TestMCUPublisher) SendMessage(ctx context.Context, message *MessageClie
if sdp, ok := sdp.(string); ok {
p.sdp = sdp
switch sdp {
case MockSdpOfferAudioOnly:
case mock.MockSdpOfferAudioOnly:
callback(nil, api.StringMap{
"type": "answer",
"sdp": MockSdpAnswerAudioOnly,
"sdp": mock.MockSdpAnswerAudioOnly,
})
return
case MockSdpOfferAudioAndVideo:
case mock.MockSdpOfferAudioAndVideo:
callback(nil, api.StringMap{
"type": "answer",
"sdp": MockSdpAnswerAudioAndVideo,
"sdp": mock.MockSdpAnswerAudioAndVideo,
})
return
}
@ -256,11 +257,11 @@ func (p *TestMCUPublisher) GetStreams(ctx context.Context) ([]PublisherStream, e
return nil, errors.New("not implemented")
}
func (p *TestMCUPublisher) PublishRemote(ctx context.Context, remoteId PublicSessionId, hostname string, port int, rtcpPort int) error {
func (p *TestMCUPublisher) PublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error {
return errors.New("remote publishing not supported")
}
func (p *TestMCUPublisher) UnpublishRemote(ctx context.Context, remoteId PublicSessionId, hostname string, port int, rtcpPort int) error {
func (p *TestMCUPublisher) UnpublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error {
return errors.New("remote publishing not supported")
}
@ -270,11 +271,11 @@ type TestMCUSubscriber struct {
publisher *TestMCUPublisher
}
func (s *TestMCUSubscriber) Publisher() PublicSessionId {
func (s *TestMCUSubscriber) Publisher() api.PublicSessionId {
return s.publisher.PublisherId()
}
func (s *TestMCUSubscriber) SendMessage(ctx context.Context, message *MessageClientMessage, data *MessageClientMessageData, callback func(error, api.StringMap)) {
func (s *TestMCUSubscriber) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
go func() {
if s.isClosed() {
callback(errors.New("Already closed"), nil)

View file

@ -19,7 +19,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package signaling
package mock
const (
// See https://tools.ietf.org/id/draft-ietf-rtcweb-sdp-08.html#rfc.section.5.2.1

View file

@ -40,6 +40,7 @@ import (
"github.com/gorilla/websocket"
signaling "github.com/strukturag/nextcloud-spreed-signaling"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
)
@ -84,7 +85,7 @@ type RemoteConnection struct {
// +checklocks:mu
helloMsgId string
// +checklocks:mu
sessionId signaling.PublicSessionId
sessionId api.PublicSessionId
// +checklocks:mu
helloReceived bool
@ -128,7 +129,7 @@ func (c *RemoteConnection) String() string {
return c.url.String()
}
func (c *RemoteConnection) SessionId() signaling.PublicSessionId {
func (c *RemoteConnection) SessionId() api.PublicSessionId {
c.mu.Lock()
defer c.mu.Unlock()
return c.sessionId
@ -546,7 +547,7 @@ func (c *RemoteConnection) processEvent(msg *signaling.ProxyServerMessage) {
// Ignore
case "publisher-closed":
c.logger.Printf("Remote publisher %s was closed on %s", msg.Event.ClientId, c)
c.p.RemotePublisherDeleted(signaling.PublicSessionId(msg.Event.ClientId))
c.p.RemotePublisherDeleted(api.PublicSessionId(msg.Event.ClientId))
default:
c.logger.Printf("Received unsupported event %+v from %s", msg, c)
}

View file

@ -92,24 +92,24 @@ type ContextKey string
var (
ContextKeySession = ContextKey("session")
TimeoutCreatingPublisher = signaling.NewError("timeout", "Timeout creating publisher.")
TimeoutCreatingSubscriber = signaling.NewError("timeout", "Timeout creating subscriber.")
TokenAuthFailed = signaling.NewError("auth_failed", "The token could not be authenticated.")
TokenExpired = signaling.NewError("token_expired", "The token is expired.")
TokenNotValidYet = signaling.NewError("token_not_valid_yet", "The token is not valid yet.")
UnknownClient = signaling.NewError("unknown_client", "Unknown client id given.")
UnsupportedCommand = signaling.NewError("bad_request", "Unsupported command received.")
UnsupportedMessage = signaling.NewError("bad_request", "Unsupported message received.")
UnsupportedPayload = signaling.NewError("unsupported_payload", "Unsupported payload type.")
ShutdownScheduled = signaling.NewError("shutdown_scheduled", "The server is scheduled to shutdown.")
RemoteSubscribersNotSupported = signaling.NewError("unsupported_subscriber", "Remote subscribers are not supported.")
TimeoutCreatingPublisher = api.NewError("timeout", "Timeout creating publisher.")
TimeoutCreatingSubscriber = api.NewError("timeout", "Timeout creating subscriber.")
TokenAuthFailed = api.NewError("auth_failed", "The token could not be authenticated.")
TokenExpired = api.NewError("token_expired", "The token is expired.")
TokenNotValidYet = api.NewError("token_not_valid_yet", "The token is not valid yet.")
UnknownClient = api.NewError("unknown_client", "Unknown client id given.")
UnsupportedCommand = api.NewError("bad_request", "Unsupported command received.")
UnsupportedMessage = api.NewError("bad_request", "Unsupported message received.")
UnsupportedPayload = api.NewError("unsupported_payload", "Unsupported payload type.")
ShutdownScheduled = api.NewError("shutdown_scheduled", "The server is scheduled to shutdown.")
RemoteSubscribersNotSupported = api.NewError("unsupported_subscriber", "Remote subscribers are not supported.")
)
type ProxyServer struct {
version string
country string
welcomeMessage string
welcomeMsg *signaling.WelcomeServerMessage
welcomeMsg *api.WelcomeServerMessage
config *goconf.ConfigFile
mcuTimeout time.Duration
logger log.Logger
@ -349,7 +349,7 @@ func NewProxyServer(ctx context.Context, r *mux.Router, version string, config *
version: version,
country: country,
welcomeMessage: string(welcomeMessage) + "\n",
welcomeMsg: &signaling.WelcomeServerMessage{
welcomeMsg: &api.WelcomeServerMessage{
Version: version,
Country: country,
Features: defaultProxyFeatures,
@ -783,7 +783,7 @@ func (s *ProxyServer) processMessage(client *ProxyClient, data []byte) {
}
var session *ProxySession
if resumeId := signaling.PublicSessionId(message.Hello.ResumeId); resumeId != "" {
if resumeId := api.PublicSessionId(message.Hello.ResumeId); resumeId != "" {
if data, err := s.cookie.DecodePublic(resumeId); err == nil {
session = s.GetSession(data.Sid)
}
@ -804,7 +804,7 @@ func (s *ProxyServer) processMessage(client *ProxyClient, data []byte) {
} else {
var err error
if session, err = s.NewSession(message.Hello); err != nil {
if e, ok := err.(*signaling.Error); ok {
if e, ok := err.(*api.Error); ok {
client.SendMessage(message.NewErrorServerMessage(e))
} else {
client.SendMessage(message.NewWrappedErrorServerMessage(err))
@ -827,7 +827,7 @@ func (s *ProxyServer) processMessage(client *ProxyClient, data []byte) {
Id: message.Id,
Type: "hello",
Hello: &signaling.HelloProxyServerMessage{
Version: signaling.HelloVersionV1,
Version: api.HelloVersionV1,
SessionId: session.PublicId(),
Server: s.welcomeMsg,
},
@ -866,10 +866,10 @@ type proxyRemotePublisher struct {
proxy *ProxyServer
remoteUrl string
publisherId signaling.PublicSessionId
publisherId api.PublicSessionId
}
func (p *proxyRemotePublisher) PublisherId() signaling.PublicSessionId {
func (p *proxyRemotePublisher) PublisherId() api.PublicSessionId {
return p.publisherId
}
@ -1009,7 +1009,7 @@ func (s *ProxyServer) processCommand(ctx context.Context, client *ProxyClient, s
MediaTypes: cmd.MediaTypes, // nolint
}
}
publisher, err := s.mcu.NewPublisher(ctx2, session, signaling.PublicSessionId(id), cmd.Sid, cmd.StreamType, *settings, &emptyInitiator{})
publisher, err := s.mcu.NewPublisher(ctx2, session, api.PublicSessionId(id), cmd.Sid, cmd.StreamType, *settings, &emptyInitiator{})
if err == context.DeadlineExceeded {
s.logger.Printf("Timeout while creating %s publisher %s for %s", cmd.StreamType, id, session.PublicId())
session.sendMessage(message.NewErrorServerMessage(TimeoutCreatingPublisher))
@ -1069,7 +1069,7 @@ func (s *ProxyServer) processCommand(ctx context.Context, client *ProxyClient, s
claims, _, err := s.parseToken(cmd.RemoteToken)
if err != nil {
if e, ok := err.(*signaling.Error); ok {
if e, ok := err.(*api.Error); ok {
client.SendMessage(message.NewErrorServerMessage(e))
} else {
client.SendMessage(message.NewWrappedErrorServerMessage(err))
@ -1339,7 +1339,7 @@ func (s *ProxyServer) processPayload(ctx context.Context, client *ProxyClient, s
statsPayloadMessagesTotal.WithLabelValues(payload.Type).Inc()
var mcuData *signaling.MessageClientMessageData
var mcuData *api.MessageClientMessageData
switch payload.Type {
case "offer":
fallthrough
@ -1348,7 +1348,7 @@ func (s *ProxyServer) processPayload(ctx context.Context, client *ProxyClient, s
case "selectStream":
fallthrough
case "candidate":
mcuData = &signaling.MessageClientMessageData{
mcuData = &api.MessageClientMessageData{
RoomType: string(mcuClient.StreamType()),
Type: payload.Type,
Sid: payload.Sid,
@ -1368,7 +1368,7 @@ func (s *ProxyServer) processPayload(ctx context.Context, client *ProxyClient, s
case "requestoffer":
fallthrough
case "sendoffer":
mcuData = &signaling.MessageClientMessageData{
mcuData = &api.MessageClientMessageData{
RoomType: string(mcuClient.StreamType()),
Type: payload.Type,
Sid: payload.Sid,
@ -1389,7 +1389,7 @@ func (s *ProxyServer) processPayload(ctx context.Context, client *ProxyClient, s
mcuClient.SendMessage(ctx2, nil, mcuData, func(err error, response api.StringMap) {
var responseMsg *signaling.ProxyServerMessage
if errors.Is(err, signaling.ErrCandidateFiltered) {
if errors.Is(err, api.ErrCandidateFiltered) {
// Silently ignore filtered candidates.
err = nil
}
@ -1717,7 +1717,7 @@ func (s *ProxyServer) PublisherDeleted(publisher signaling.McuPublisher) {
}
}
func (s *ProxyServer) RemotePublisherDeleted(publisherId signaling.PublicSessionId) {
func (s *ProxyServer) RemotePublisherDeleted(publisherId api.PublicSessionId) {
s.sessionsLock.RLock()
defer s.sessionsLock.RUnlock()

View file

@ -391,16 +391,16 @@ func (m *TestMCU) GetServerInfoSfu() *signaling.BackendServerInfoSfu {
return nil
}
func (m *TestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id signaling.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
func (m *TestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id api.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
return nil, errors.New("not implemented")
}
func (m *TestMCU) NewSubscriber(ctx context.Context, listener signaling.McuListener, publisher signaling.PublicSessionId, streamType signaling.StreamType, initiator signaling.McuInitiator) (signaling.McuSubscriber, error) {
func (m *TestMCU) NewSubscriber(ctx context.Context, listener signaling.McuListener, publisher api.PublicSessionId, streamType signaling.StreamType, initiator signaling.McuInitiator) (signaling.McuSubscriber, error) {
return nil, errors.New("not implemented")
}
type TestMCUPublisher struct {
id signaling.PublicSessionId
id api.PublicSessionId
sid string
streamType signaling.StreamType
}
@ -409,7 +409,7 @@ func (p *TestMCUPublisher) Id() string {
return string(p.id)
}
func (p *TestMCUPublisher) PublisherId() signaling.PublicSessionId {
func (p *TestMCUPublisher) PublisherId() api.PublicSessionId {
return p.id
}
@ -428,7 +428,7 @@ func (p *TestMCUPublisher) MaxBitrate() api.Bandwidth {
func (p *TestMCUPublisher) Close(ctx context.Context) {
}
func (p *TestMCUPublisher) SendMessage(ctx context.Context, message *signaling.MessageClientMessage, data *signaling.MessageClientMessageData, callback func(error, api.StringMap)) {
func (p *TestMCUPublisher) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
callback(errors.New("not implemented"), nil)
}
@ -443,11 +443,11 @@ func (p *TestMCUPublisher) GetStreams(ctx context.Context) ([]signaling.Publishe
return nil, errors.New("not implemented")
}
func (p *TestMCUPublisher) PublishRemote(ctx context.Context, remoteId signaling.PublicSessionId, hostname string, port int, rtcpPort int) error {
func (p *TestMCUPublisher) PublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error {
return errors.New("not implemented")
}
func (p *TestMCUPublisher) UnpublishRemote(ctx context.Context, remoteId signaling.PublicSessionId, hostname string, port int, rtcpPort int) error {
func (p *TestMCUPublisher) UnpublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error {
return errors.New("not implemented")
}
@ -465,7 +465,7 @@ func (p *TestPublisherWithBandwidth) Bandwidth() *signaling.McuClientBandwidthIn
return p.bandwidth
}
func (m *PublisherTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id signaling.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
func (m *PublisherTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id api.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
publisher := &TestPublisherWithBandwidth{
TestMCUPublisher: TestMCUPublisher{
id: id,
@ -573,7 +573,7 @@ func NewHangingTestMCU(t *testing.T) *HangingTestMCU {
}
}
func (m *HangingTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id signaling.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
func (m *HangingTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id api.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
ctx2, cancel := context.WithTimeout(m.ctx, testTimeout*2)
defer cancel()
@ -591,7 +591,7 @@ func (m *HangingTestMCU) NewPublisher(ctx context.Context, listener signaling.Mc
}
}
func (m *HangingTestMCU) NewSubscriber(ctx context.Context, listener signaling.McuListener, publisher signaling.PublicSessionId, streamType signaling.StreamType, initiator signaling.McuInitiator) (signaling.McuSubscriber, error) {
func (m *HangingTestMCU) NewSubscriber(ctx context.Context, listener signaling.McuListener, publisher api.PublicSessionId, streamType signaling.StreamType, initiator signaling.McuInitiator) (signaling.McuSubscriber, error) {
ctx2, cancel := context.WithTimeout(m.ctx, testTimeout*2)
defer cancel()
@ -678,7 +678,7 @@ func NewCodecsTestMCU(t *testing.T) *CodecsTestMCU {
}
}
func (m *CodecsTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id signaling.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
func (m *CodecsTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id api.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
assert.Equal(m.t, "opus,g722", settings.AudioCodec)
assert.Equal(m.t, "vp9,vp8,av1", settings.VideoCodec)
return &TestMCUPublisher{
@ -745,7 +745,7 @@ type StreamsTestPublisher struct {
streams []signaling.PublisherStream
}
func (m *StreamTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id signaling.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
func (m *StreamTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id api.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
return &StreamsTestPublisher{
TestMCUPublisher: TestMCUPublisher{
id: id,
@ -878,7 +878,7 @@ func (p *TestRemotePublisher) Id() string {
return "id"
}
func (p *TestRemotePublisher) PublisherId() signaling.PublicSessionId {
func (p *TestRemotePublisher) PublisherId() api.PublicSessionId {
return "id"
}
@ -907,7 +907,7 @@ func (p *TestRemotePublisher) Close(ctx context.Context) {
}
}
func (p *TestRemotePublisher) SendMessage(ctx context.Context, message *signaling.MessageClientMessage, data *signaling.MessageClientMessageData, callback func(error, api.StringMap)) {
func (p *TestRemotePublisher) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
callback(errors.New("not implemented"), nil)
}
@ -972,12 +972,12 @@ func (s *TestRemoteSubscriber) Close(ctx context.Context) {
s.closeFunc()
}
func (s *TestRemoteSubscriber) SendMessage(ctx context.Context, message *signaling.MessageClientMessage, data *signaling.MessageClientMessageData, callback func(error, api.StringMap)) {
func (s *TestRemoteSubscriber) SendMessage(ctx context.Context, message *api.MessageClientMessage, data *api.MessageClientMessageData, callback func(error, api.StringMap)) {
callback(errors.New("not implemented"), nil)
}
func (s *TestRemoteSubscriber) Publisher() signaling.PublicSessionId {
return signaling.PublicSessionId(s.publisher.Id())
func (s *TestRemoteSubscriber) Publisher() api.PublicSessionId {
return api.PublicSessionId(s.publisher.Id())
}
func (m *RemoteSubscriberTestMCU) NewRemoteSubscriber(ctx context.Context, listener signaling.McuListener, publisher signaling.McuRemotePublisher) (signaling.McuRemoteSubscriber, error) {
@ -1024,7 +1024,7 @@ func TestProxyRemoteSubscriber(t *testing.T) {
_, err := client.RunUntilLoad(ctx, 0)
assert.NoError(err)
publisherId := signaling.PublicSessionId("the-publisher-id")
publisherId := api.PublicSessionId("the-publisher-id")
claims := &signaling.TokenClaims{
RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now().Add(-maxTokenAge / 2)),
@ -1119,7 +1119,7 @@ func TestProxyCloseRemoteOnSessionClose(t *testing.T) {
_, err := client.RunUntilLoad(ctx, 0)
assert.NoError(err)
publisherId := signaling.PublicSessionId("the-publisher-id")
publisherId := api.PublicSessionId("the-publisher-id")
claims := &signaling.TokenClaims{
RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now().Add(-maxTokenAge / 2)),
@ -1188,12 +1188,12 @@ type UnpublishRemoteTestPublisher struct {
mu sync.RWMutex
// +checklocks:mu
remoteId signaling.PublicSessionId
remoteId api.PublicSessionId
// +checklocks:mu
remoteData *remotePublisherData
}
func (m *UnpublishRemoteTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id signaling.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
func (m *UnpublishRemoteTestMCU) NewPublisher(ctx context.Context, listener signaling.McuListener, id api.PublicSessionId, sid string, streamType signaling.StreamType, settings signaling.NewPublisherSettings, initiator signaling.McuInitiator) (signaling.McuPublisher, error) {
publisher := &UnpublishRemoteTestPublisher{
TestMCUPublisher: TestMCUPublisher{
id: id,
@ -1207,7 +1207,7 @@ func (m *UnpublishRemoteTestMCU) NewPublisher(ctx context.Context, listener sign
return publisher, nil
}
func (p *UnpublishRemoteTestPublisher) getRemoteId() signaling.PublicSessionId {
func (p *UnpublishRemoteTestPublisher) getRemoteId() api.PublicSessionId {
p.mu.RLock()
defer p.mu.RUnlock()
return p.remoteId
@ -1226,7 +1226,7 @@ func (p *UnpublishRemoteTestPublisher) clearRemote() {
p.remoteData = nil
}
func (p *UnpublishRemoteTestPublisher) PublishRemote(ctx context.Context, remoteId signaling.PublicSessionId, hostname string, port int, rtcpPort int) error {
func (p *UnpublishRemoteTestPublisher) PublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error {
p.mu.Lock()
defer p.mu.Unlock()
if assert.Empty(p.t, p.remoteId) {
@ -1240,7 +1240,7 @@ func (p *UnpublishRemoteTestPublisher) PublishRemote(ctx context.Context, remote
return nil
}
func (p *UnpublishRemoteTestPublisher) UnpublishRemote(ctx context.Context, remoteId signaling.PublicSessionId, hostname string, port int, rtcpPort int) error {
func (p *UnpublishRemoteTestPublisher) UnpublishRemote(ctx context.Context, remoteId api.PublicSessionId, hostname string, port int, rtcpPort int) error {
p.mu.Lock()
defer p.mu.Unlock()
assert.Equal(p.t, remoteId, p.remoteId)
@ -1278,7 +1278,7 @@ func TestProxyUnpublishRemote(t *testing.T) {
_, err := client1.RunUntilLoad(ctx, 0)
assert.NoError(err)
publisherId := signaling.PublicSessionId("the-publisher-id")
publisherId := api.PublicSessionId("the-publisher-id")
require.NoError(client1.WriteJSON(&signaling.ProxyClientMessage{
Id: "2345",
Type: "command",
@ -1395,7 +1395,7 @@ func TestProxyUnpublishRemotePublisherClosed(t *testing.T) {
_, err := client1.RunUntilLoad(ctx, 0)
assert.NoError(err)
publisherId := signaling.PublicSessionId("the-publisher-id")
publisherId := api.PublicSessionId("the-publisher-id")
require.NoError(client1.WriteJSON(&signaling.ProxyClientMessage{
Id: "2345",
Type: "command",
@ -1527,7 +1527,7 @@ func TestProxyUnpublishRemoteOnSessionClose(t *testing.T) {
_, err := client1.RunUntilLoad(ctx, 0)
assert.NoError(err)
publisherId := signaling.PublicSessionId("the-publisher-id")
publisherId := api.PublicSessionId("the-publisher-id")
require.NoError(client1.WriteJSON(&signaling.ProxyClientMessage{
Id: "2345",
Type: "command",

View file

@ -39,7 +39,7 @@ const (
)
type remotePublisherData struct {
id signaling.PublicSessionId
id api.PublicSessionId
hostname string
port int
rtcpPort int
@ -48,7 +48,7 @@ type remotePublisherData struct {
type ProxySession struct {
logger log.Logger
proxy *ProxyServer
id signaling.PublicSessionId
id api.PublicSessionId
sid uint64
lastUsed atomic.Int64
ctx context.Context
@ -77,7 +77,7 @@ type ProxySession struct {
remotePublishers map[signaling.McuRemoteAwarePublisher]map[string]*remotePublisherData
}
func NewProxySession(proxy *ProxyServer, sid uint64, id signaling.PublicSessionId) *ProxySession {
func NewProxySession(proxy *ProxyServer, sid uint64, id api.PublicSessionId) *ProxySession {
ctx, closeFunc := context.WithCancel(context.Background())
result := &ProxySession{
logger: proxy.logger,
@ -101,7 +101,7 @@ func (s *ProxySession) Context() context.Context {
return s.ctx
}
func (s *ProxySession) PublicId() signaling.PublicSessionId {
func (s *ProxySession) PublicId() api.PublicSessionId {
return s.id
}
@ -469,7 +469,7 @@ func (s *ProxySession) OnRemoteAwarePublisherDeleted(publisher signaling.McuRemo
}
}
func (s *ProxySession) OnRemotePublisherDeleted(publisherId signaling.PublicSessionId) {
func (s *ProxySession) OnRemotePublisherDeleted(publisherId api.PublicSessionId) {
s.subscribersLock.Lock()
defer s.subscribersLock.Unlock()

View file

@ -34,7 +34,9 @@ import (
"github.com/gorilla/websocket"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
signaling "github.com/strukturag/nextcloud-spreed-signaling"
"github.com/strukturag/nextcloud-spreed-signaling/api"
)
var (
@ -52,7 +54,7 @@ type ProxyTestClient struct {
messageChan chan []byte
readErrorChan chan error
sessionId signaling.PublicSessionId
sessionId api.PublicSessionId
}
func NewProxyTestClient(ctx context.Context, t *testing.T, url string) *ProxyTestClient {

View file

@ -28,6 +28,7 @@ import (
"sync/atomic"
"time"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
)
@ -36,12 +37,12 @@ type RemoteSession struct {
hub *Hub
client *Client
remoteClient *GrpcClient
sessionId PublicSessionId
sessionId api.PublicSessionId
proxy atomic.Pointer[SessionProxy]
}
func NewRemoteSession(hub *Hub, client *Client, remoteClient *GrpcClient, sessionId PublicSessionId) (*RemoteSession, error) {
func NewRemoteSession(hub *Hub, client *Client, remoteClient *GrpcClient, sessionId api.PublicSessionId) (*RemoteSession, error) {
remoteSession := &RemoteSession{
logger: hub.logger,
hub: hub,
@ -80,12 +81,12 @@ func (s *RemoteSession) IsConnected() bool {
return true
}
func (s *RemoteSession) Start(message *ClientMessage) error {
func (s *RemoteSession) Start(message *api.ClientMessage) error {
return s.sendMessage(message)
}
func (s *RemoteSession) OnProxyMessage(msg *ServerSessionMessage) error {
var message *ServerMessage
var message *api.ServerMessage
if err := json.Unmarshal(msg.Message, &message); err != nil {
return err
}

156
room.go
View file

@ -79,7 +79,7 @@ type Room struct {
mu *sync.RWMutex
asyncCh AsyncChannel
// +checklocks:mu
sessions map[PublicSessionId]Session
sessions map[api.PublicSessionId]Session
// +checklocks:mu
internalSessions map[*ClientSession]bool
// +checklocks:mu
@ -87,7 +87,7 @@ type Room struct {
// +checklocks:mu
inCallSessions map[Session]bool
// +checklocks:mu
roomSessionData map[PublicSessionId]*RoomSessionData
roomSessionData map[api.PublicSessionId]*RoomSessionData
// +checklocks:mu
statsRoomSessionsCurrent *prometheus.GaugeVec
@ -122,12 +122,12 @@ func NewRoom(roomId string, properties json.RawMessage, hub *Hub, events AsyncEv
closer: internal.NewCloser(),
mu: &sync.RWMutex{},
asyncCh: make(AsyncChannel, DefaultAsyncChannelSize),
sessions: make(map[PublicSessionId]Session),
sessions: make(map[api.PublicSessionId]Session),
internalSessions: make(map[*ClientSession]bool),
virtualSessions: make(map[*VirtualSession]bool),
inCallSessions: make(map[Session]bool),
roomSessionData: make(map[PublicSessionId]*RoomSessionData),
roomSessionData: make(map[api.PublicSessionId]*RoomSessionData),
statsRoomSessionsCurrent: statsRoomSessionsCurrent.MustCurryWith(prometheus.Labels{
"backend": backend.Id(),
@ -226,9 +226,9 @@ func (r *Room) Close() []Session {
result = append(result, s)
}
r.sessions = nil
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(HelloClientTypeClient)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(HelloClientTypeInternal)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(HelloClientTypeVirtual)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(api.HelloClientTypeClient)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(api.HelloClientTypeInternal)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(api.HelloClientTypeVirtual)})
r.mu.Unlock()
return result
}
@ -303,7 +303,7 @@ func (r *Room) processBackendRoomRequestAsyncRoom(message *AsyncRoomMessage) {
switch message.Type {
case "sessionjoined":
r.notifySessionJoined(message.SessionId)
if message.ClientType == HelloClientTypeInternal {
if message.ClientType == api.HelloClientTypeInternal {
r.publishUsersChangedWithInternal()
}
default:
@ -331,7 +331,7 @@ func (r *Room) AddSession(session Session, sessionData json.RawMessage) {
}
var publishUsersChanged bool
switch session.ClientType() {
case HelloClientTypeInternal:
case api.HelloClientTypeInternal:
clientSession, ok := session.(*ClientSession)
if !ok {
delete(r.sessions, sid)
@ -339,7 +339,7 @@ func (r *Room) AddSession(session Session, sessionData json.RawMessage) {
panic(fmt.Sprintf("Expected a client session, got %v (%T)", session, session))
}
r.internalSessions[clientSession] = true
case HelloClientTypeVirtual:
case api.HelloClientTypeVirtual:
virtualSession, ok := session.(*VirtualSession)
if !ok {
delete(r.sessions, sid)
@ -383,7 +383,7 @@ func (r *Room) AddSession(session Session, sessionData json.RawMessage) {
}
}
func (r *Room) getOtherSessions(ignoreSessionId PublicSessionId) (Session, []Session) {
func (r *Room) getOtherSessions(ignoreSessionId api.PublicSessionId) (Session, []Session) {
r.mu.Lock()
defer r.mu.Unlock()
@ -399,19 +399,19 @@ func (r *Room) getOtherSessions(ignoreSessionId PublicSessionId) (Session, []Ses
return r.sessions[ignoreSessionId], sessions
}
func (r *Room) notifySessionJoined(sessionId PublicSessionId) {
func (r *Room) notifySessionJoined(sessionId api.PublicSessionId) {
session, sessions := r.getOtherSessions(sessionId)
if len(sessions) == 0 {
return
}
if session != nil && session.ClientType() != HelloClientTypeClient {
if session != nil && session.ClientType() != api.HelloClientTypeClient {
session = nil
}
events := make([]EventServerMessageSessionEntry, 0, len(sessions))
events := make([]api.EventServerMessageSessionEntry, 0, len(sessions))
for _, s := range sessions {
entry := EventServerMessageSessionEntry{
entry := api.EventServerMessageSessionEntry{
SessionId: s.PublicId(),
UserId: s.UserId(),
User: s.UserData(),
@ -419,14 +419,14 @@ func (r *Room) notifySessionJoined(sessionId PublicSessionId) {
if s, ok := s.(*ClientSession); ok {
entry.Features = s.GetFeatures()
entry.RoomSessionId = s.RoomSessionId()
entry.Federated = s.ClientType() == HelloClientTypeFederation
entry.Federated = s.ClientType() == api.HelloClientTypeFederation
}
events = append(events, entry)
}
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "join",
Join: events,
@ -452,12 +452,12 @@ func (r *Room) notifySessionJoined(sessionId PublicSessionId) {
continue
}
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "participants",
Type: "flags",
Flags: &RoomFlagsServerMessage{
Flags: &api.RoomFlagsServerMessage{
RoomId: r.id,
SessionId: vsess.PublicId(),
Flags: vsess.Flags(),
@ -504,7 +504,7 @@ func (r *Room) RemoveSession(session Session) bool {
// Handle case where virtual session was also sent by Nextcloud.
users := make([]api.StringMap, 0, len(r.users))
for _, u := range r.users {
if value, found := api.GetStringMapString[PublicSessionId](u, "sessionId"); !found || value != sid {
if value, found := api.GetStringMapString[api.PublicSessionId](u, "sessionId"); !found || value != sid {
users = append(users, u)
}
}
@ -528,9 +528,9 @@ func (r *Room) RemoveSession(session Session) bool {
}
r.hub.removeRoom(r)
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(HelloClientTypeClient)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(HelloClientTypeInternal)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(HelloClientTypeVirtual)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(api.HelloClientTypeClient)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(api.HelloClientTypeInternal)})
r.statsRoomSessionsCurrent.Delete(prometheus.Labels{"clienttype": string(api.HelloClientTypeVirtual)})
r.unsubscribeBackend()
r.doClose()
r.mu.Unlock()
@ -542,7 +542,7 @@ func (r *Room) RemoveSession(session Session) bool {
return false
}
func (r *Room) publish(message *ServerMessage) error {
func (r *Room) publish(message *api.ServerMessage) error {
return r.events.PublishRoomMessage(r.id, r.backend, &AsyncMessage{
Type: "message",
Message: message,
@ -559,9 +559,9 @@ func (r *Room) UpdateProperties(properties json.RawMessage) {
}
r.properties = properties
message := &ServerMessage{
message := &api.ServerMessage{
Type: "room",
Room: &RoomServerMessage{
Room: &api.RoomServerMessage{
RoomId: r.id,
Properties: r.properties,
},
@ -588,12 +588,12 @@ func (r *Room) PublishSessionJoined(session Session, sessionData *RoomSessionDat
userid = sessionData.UserId
}
message := &ServerMessage{
message := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "join",
Join: []EventServerMessageSessionEntry{
Join: []api.EventServerMessageSessionEntry{
{
SessionId: sessionId,
UserId: userid,
@ -605,7 +605,7 @@ func (r *Room) PublishSessionJoined(session Session, sessionData *RoomSessionDat
if session, ok := session.(*ClientSession); ok {
message.Event.Join[0].Features = session.GetFeatures()
message.Event.Join[0].RoomSessionId = session.RoomSessionId()
message.Event.Join[0].Federated = session.ClientType() == HelloClientTypeFederation
message.Event.Join[0].Federated = session.ClientType() == api.HelloClientTypeFederation
}
if err := r.publish(message); err != nil {
r.logger.Printf("Could not publish session joined message in room %s: %s", r.Id(), err)
@ -618,12 +618,12 @@ func (r *Room) PublishSessionLeft(session Session) {
return
}
message := &ServerMessage{
message := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "leave",
Leave: []PublicSessionId{
Leave: []api.PublicSessionId{
sessionId,
},
},
@ -632,13 +632,13 @@ func (r *Room) PublishSessionLeft(session Session) {
r.logger.Printf("Could not publish session left message in room %s: %s", r.Id(), err)
}
if session.ClientType() == HelloClientTypeInternal {
if session.ClientType() == api.HelloClientTypeInternal {
r.publishUsersChangedWithInternal()
}
}
// +checklocksread:r.mu
func (r *Room) getClusteredInternalSessionsRLocked() (internal map[PublicSessionId]*InternalSessionData, virtual map[PublicSessionId]*VirtualSessionData) {
func (r *Room) getClusteredInternalSessionsRLocked() (internal map[api.PublicSessionId]*InternalSessionData, virtual map[api.PublicSessionId]*VirtualSessionData) {
if r.hub.rpcClients == nil {
return nil, nil
}
@ -665,11 +665,11 @@ func (r *Room) getClusteredInternalSessionsRLocked() (internal map[PublicSession
mu.Lock()
defer mu.Unlock()
if internal == nil {
internal = make(map[PublicSessionId]*InternalSessionData, len(clientInternal))
internal = make(map[api.PublicSessionId]*InternalSessionData, len(clientInternal))
}
maps.Copy(internal, clientInternal)
if virtual == nil {
virtual = make(map[PublicSessionId]*VirtualSessionData, len(clientVirtual))
virtual = make(map[api.PublicSessionId]*VirtualSessionData, len(clientVirtual))
}
maps.Copy(virtual, clientVirtual)
}(client)
@ -694,9 +694,9 @@ func (r *Room) addInternalSessions(users []api.StringMap) []api.StringMap {
return users
}
skipSession := make(map[PublicSessionId]bool)
skipSession := make(map[api.PublicSessionId]bool)
for _, user := range users {
sessionid, found := api.GetStringMapString[PublicSessionId](user, "sessionId")
sessionid, found := api.GetStringMapString[api.PublicSessionId](user, "sessionId")
if !found || sessionid == "" {
continue
}
@ -811,9 +811,9 @@ func (r *Room) PublishUsersInCallChanged(changed []api.StringMap, users []api.St
continue
}
sessionId, found := api.GetStringMapString[PublicSessionId](user, "sessionId")
sessionId, found := api.GetStringMapString[api.PublicSessionId](user, "sessionId")
if !found {
sessionId, found = api.GetStringMapString[PublicSessionId](user, "sessionid")
sessionId, found = api.GetStringMapString[api.PublicSessionId](user, "sessionid")
if !found {
continue
}
@ -844,12 +844,12 @@ func (r *Room) PublishUsersInCallChanged(changed []api.StringMap, users []api.St
changed = r.filterPermissions(changed)
users = r.filterPermissions(users)
message := &ServerMessage{
message := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "participants",
Type: "update",
Update: &RoomEventServerMessage{
Update: &api.RoomEventServerMessage{
RoomId: r.id,
Changed: changed,
Users: r.addInternalSessions(users),
@ -868,15 +868,15 @@ func (r *Room) PublishUsersInCallChangedAll(inCall int) {
var notify []*ClientSession
if inCall&FlagInCall != 0 {
// All connected sessions join the call.
var joined []PublicSessionId
var joined []api.PublicSessionId
for _, session := range r.sessions {
clientSession, ok := session.(*ClientSession)
if !ok {
continue
}
if session.ClientType() == HelloClientTypeInternal ||
session.ClientType() == HelloClientTypeFederation {
if session.ClientType() == api.HelloClientTypeInternal ||
session.ClientType() == api.HelloClientTypeFederation {
continue
}
@ -929,12 +929,12 @@ func (r *Room) PublishUsersInCallChangedAll(inCall int) {
inCallMsg := json.RawMessage(strconv.FormatInt(int64(inCall), 10))
message := &ServerMessage{
message := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "participants",
Type: "update",
Update: &RoomEventServerMessage{
Update: &api.RoomEventServerMessage{
RoomId: r.id,
InCall: inCallMsg,
All: true,
@ -953,12 +953,12 @@ func (r *Room) PublishUsersChanged(changed []api.StringMap, users []api.StringMa
changed = r.filterPermissions(changed)
users = r.filterPermissions(users)
message := &ServerMessage{
message := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "participants",
Type: "update",
Update: &RoomEventServerMessage{
Update: &api.RoomEventServerMessage{
RoomId: r.id,
Changed: changed,
Users: r.addInternalSessions(users),
@ -970,15 +970,15 @@ func (r *Room) PublishUsersChanged(changed []api.StringMap, users []api.StringMa
}
}
func (r *Room) getParticipantsUpdateMessage(users []api.StringMap) *ServerMessage {
func (r *Room) getParticipantsUpdateMessage(users []api.StringMap) *api.ServerMessage {
users = r.filterPermissions(users)
message := &ServerMessage{
message := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "participants",
Type: "update",
Update: &RoomEventServerMessage{
Update: &api.RoomEventServerMessage{
RoomId: r.id,
Users: r.addInternalSessions(users),
},
@ -997,7 +997,7 @@ func (r *Room) NotifySessionResumed(session *ClientSession) {
}
func (r *Room) NotifySessionChanged(session Session, flags SessionChangeFlag) {
if flags&SessionChangeFlags != 0 && session.ClientType() == HelloClientTypeVirtual {
if flags&SessionChangeFlags != 0 && session.ClientType() == api.HelloClientTypeVirtual {
// Only notify if a virtual session has changed.
if virtual, ok := session.(*VirtualSession); ok {
r.publishSessionFlagsChanged(virtual)
@ -1050,12 +1050,12 @@ func (r *Room) publishUsersChangedWithInternal() {
}
func (r *Room) publishSessionFlagsChanged(session *VirtualSession) {
message := &ServerMessage{
message := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "participants",
Type: "flags",
Flags: &RoomFlagsServerMessage{
Flags: &api.RoomFlagsServerMessage{
RoomId: r.id,
SessionId: session.PublicId(),
Flags: session.Flags(),
@ -1093,7 +1093,7 @@ func (r *Room) publishActiveSessions() (int, *sync.WaitGroup) {
parsedBackendUrl := parsed
var sid RoomSessionId
var sid api.RoomSessionId
var uid string
switch sess := session.(type) {
case *ClientSession:
@ -1102,7 +1102,7 @@ func (r *Room) publishActiveSessions() (int, *sync.WaitGroup) {
uid = sess.AuthUserId()
case *VirtualSession:
// Use our internal generated session id (will be added to Nextcloud).
sid = RoomSessionId(sess.PublicId())
sid = api.RoomSessionId(sess.PublicId())
uid = sess.UserId()
default:
continue
@ -1151,12 +1151,12 @@ func (r *Room) publishRoomMessage(message *BackendRoomMessageRequest) {
return
}
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "message",
Message: &RoomEventMessage{
Message: &api.RoomEventMessage{
RoomId: r.id,
Data: message.Data,
},
@ -1170,12 +1170,12 @@ func (r *Room) publishRoomMessage(message *BackendRoomMessageRequest) {
func (r *Room) publishSwitchTo(message *BackendRoomSwitchToMessageRequest) {
var wg sync.WaitGroup
if len(message.SessionsList) > 0 {
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "switchto",
SwitchTo: &EventServerMessageSwitchTo{
SwitchTo: &api.EventServerMessageSwitchTo{
RoomId: message.RoomId,
},
},
@ -1183,7 +1183,7 @@ func (r *Room) publishSwitchTo(message *BackendRoomSwitchToMessageRequest) {
for _, sessionId := range message.SessionsList {
wg.Add(1)
go func(sessionId PublicSessionId) {
go func(sessionId api.PublicSessionId) {
defer wg.Done()
if err := r.events.PublishSessionMessage(sessionId, r.backend, &AsyncMessage{
@ -1199,15 +1199,15 @@ func (r *Room) publishSwitchTo(message *BackendRoomSwitchToMessageRequest) {
if len(message.SessionsMap) > 0 {
for sessionId, details := range message.SessionsMap {
wg.Add(1)
go func(sessionId PublicSessionId, details json.RawMessage) {
go func(sessionId api.PublicSessionId, details json.RawMessage) {
defer wg.Done()
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "switchto",
SwitchTo: &EventServerMessageSwitchTo{
SwitchTo: &api.EventServerMessageSwitchTo{
RoomId: message.RoomId,
Details: details,
},
@ -1227,9 +1227,9 @@ func (r *Room) publishSwitchTo(message *BackendRoomSwitchToMessageRequest) {
}
func (r *Room) notifyInternalRoomDeleted() {
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "event",
Event: &EventServerMessage{
Event: &api.EventServerMessage{
Target: "room",
Type: "delete",
},

View file

@ -24,6 +24,8 @@ package signaling
import (
"context"
"errors"
"github.com/strukturag/nextcloud-spreed-signaling/api"
)
var (
@ -31,9 +33,9 @@ var (
)
type RoomSessions interface {
SetRoomSession(session Session, roomSessionId RoomSessionId) error
SetRoomSession(session Session, roomSessionId api.RoomSessionId) error
DeleteRoomSession(session Session)
GetSessionId(roomSessionId RoomSessionId) (PublicSessionId, error)
LookupSessionId(ctx context.Context, roomSessionId RoomSessionId, disconnectReason string) (PublicSessionId, error)
GetSessionId(roomSessionId api.RoomSessionId) (api.PublicSessionId, error)
LookupSessionId(ctx context.Context, roomSessionId api.RoomSessionId, disconnectReason string) (api.PublicSessionId, error)
}

View file

@ -27,29 +27,30 @@ import (
"sync"
"sync/atomic"
"github.com/strukturag/nextcloud-spreed-signaling/api"
"github.com/strukturag/nextcloud-spreed-signaling/log"
)
type BuiltinRoomSessions struct {
mu sync.RWMutex
// +checklocks:mu
sessionIdToRoomSession map[PublicSessionId]RoomSessionId
sessionIdToRoomSession map[api.PublicSessionId]api.RoomSessionId
// +checklocks:mu
roomSessionToSessionid map[RoomSessionId]PublicSessionId
roomSessionToSessionid map[api.RoomSessionId]api.PublicSessionId
clients *GrpcClients
}
func NewBuiltinRoomSessions(clients *GrpcClients) (RoomSessions, error) {
return &BuiltinRoomSessions{
sessionIdToRoomSession: make(map[PublicSessionId]RoomSessionId),
roomSessionToSessionid: make(map[RoomSessionId]PublicSessionId),
sessionIdToRoomSession: make(map[api.PublicSessionId]api.RoomSessionId),
roomSessionToSessionid: make(map[api.RoomSessionId]api.PublicSessionId),
clients: clients,
}, nil
}
func (r *BuiltinRoomSessions) SetRoomSession(session Session, roomSessionId RoomSessionId) error {
func (r *BuiltinRoomSessions) SetRoomSession(session Session, roomSessionId api.RoomSessionId) error {
if roomSessionId == "" {
r.DeleteRoomSession(session)
return nil
@ -87,7 +88,7 @@ func (r *BuiltinRoomSessions) DeleteRoomSession(session Session) {
}
}
func (r *BuiltinRoomSessions) GetSessionId(roomSessionId RoomSessionId) (PublicSessionId, error) {
func (r *BuiltinRoomSessions) GetSessionId(roomSessionId api.RoomSessionId) (api.PublicSessionId, error) {
r.mu.RLock()
defer r.mu.RUnlock()
sid, found := r.roomSessionToSessionid[roomSessionId]
@ -98,7 +99,7 @@ func (r *BuiltinRoomSessions) GetSessionId(roomSessionId RoomSessionId) (PublicS
return sid, nil
}
func (r *BuiltinRoomSessions) LookupSessionId(ctx context.Context, roomSessionId RoomSessionId, disconnectReason string) (PublicSessionId, error) {
func (r *BuiltinRoomSessions) LookupSessionId(ctx context.Context, roomSessionId api.RoomSessionId, disconnectReason string) (api.PublicSessionId, error) {
sid, err := r.GetSessionId(roomSessionId)
if err == nil {
return sid, nil
@ -146,5 +147,5 @@ func (r *BuiltinRoomSessions) LookupSessionId(ctx context.Context, roomSessionId
return "", ErrNoSuchRoomSession
}
return value.(PublicSessionId), nil
return value.(api.PublicSessionId), nil
}

View file

@ -34,22 +34,22 @@ import (
)
type DummySession struct {
publicId PublicSessionId
publicId api.PublicSessionId
}
func (s *DummySession) Context() context.Context {
return context.Background()
}
func (s *DummySession) PrivateId() PrivateSessionId {
func (s *DummySession) PrivateId() api.PrivateSessionId {
return ""
}
func (s *DummySession) PublicId() PublicSessionId {
func (s *DummySession) PublicId() api.PublicSessionId {
return s.publicId
}
func (s *DummySession) ClientType() ClientType {
func (s *DummySession) ClientType() api.ClientType {
return ""
}
@ -88,6 +88,10 @@ func (s *DummySession) GetRoom() *Room {
return nil
}
func (s *DummySession) IsInRoom(id string) bool {
return false
}
func (s *DummySession) LeaveRoom(notify bool) *Room {
return nil
}
@ -99,15 +103,15 @@ func (s *DummySession) HasPermission(permission Permission) bool {
return false
}
func (s *DummySession) SendError(e *Error) bool {
func (s *DummySession) SendError(e *api.Error) bool {
return false
}
func (s *DummySession) SendMessage(message *ServerMessage) bool {
func (s *DummySession) SendMessage(message *api.ServerMessage) bool {
return false
}
func checkSession(t *testing.T, sessions RoomSessions, sessionId PublicSessionId, roomSessionId RoomSessionId) Session {
func checkSession(t *testing.T, sessions RoomSessions, sessionId api.PublicSessionId, roomSessionId api.RoomSessionId) Session {
session := &DummySession{
publicId: sessionId,
}

View file

@ -51,9 +51,9 @@ var (
type Session interface {
Context() context.Context
PrivateId() PrivateSessionId
PublicId() PublicSessionId
ClientType() ClientType
PrivateId() api.PrivateSessionId
PublicId() api.PublicSessionId
ClientType() api.ClientType
Data() *SessionIdData
UserId() string
@ -67,13 +67,14 @@ type Session interface {
SetRoom(room *Room)
GetRoom() *Room
LeaveRoom(notify bool) *Room
IsInRoom(id string) bool
Close()
HasPermission(permission Permission) bool
SendError(e *Error) bool
SendMessage(message *ServerMessage) bool
SendError(e *api.Error) bool
SendMessage(message *api.ServerMessage) bool
}
type SessionWithInCall interface {

View file

@ -37,6 +37,8 @@ import (
"unsafe"
"google.golang.org/protobuf/proto"
"github.com/strukturag/nextcloud-spreed-signaling/api"
)
const (
@ -235,14 +237,14 @@ func (c *SessionIdCodec) decodeRaw(name string, value []byte) (*SessionIdData, e
return data, nil
}
func (c *SessionIdCodec) EncodePrivate(sessionData *SessionIdData) (PrivateSessionId, error) {
func (c *SessionIdCodec) EncodePrivate(sessionData *SessionIdData) (api.PrivateSessionId, error) {
id, err := c.encodeRaw(privateSessionName, sessionData)
if err != nil {
return "", err
}
defer c.bytesPool.Put(id)
return PrivateSessionId(c.encodeToString(id)), nil
return api.PrivateSessionId(c.encodeToString(id)), nil
}
func (c *SessionIdCodec) reverseSessionId(data []byte) {
@ -251,7 +253,7 @@ func (c *SessionIdCodec) reverseSessionId(data []byte) {
}
}
func (c *SessionIdCodec) EncodePublic(sessionData *SessionIdData) (PublicSessionId, error) {
func (c *SessionIdCodec) EncodePublic(sessionData *SessionIdData) (api.PublicSessionId, error) {
encoded, err := c.encodeRaw(publicSessionName, sessionData)
if err != nil {
return "", err
@ -265,10 +267,10 @@ func (c *SessionIdCodec) EncodePublic(sessionData *SessionIdData) (PublicSession
c.reverseSessionId(encoded)
defer c.bytesPool.Put(encoded)
return PublicSessionId(c.encodeToString(encoded)), nil
return api.PublicSessionId(c.encodeToString(encoded)), nil
}
func (c *SessionIdCodec) DecodePrivate(encodedData PrivateSessionId) (*SessionIdData, error) {
func (c *SessionIdCodec) DecodePrivate(encodedData api.PrivateSessionId) (*SessionIdData, error) {
decoded, err := c.decodeFromString(string(encodedData))
if err != nil {
return nil, fmt.Errorf("invalid session id: %w", err)
@ -278,7 +280,7 @@ func (c *SessionIdCodec) DecodePrivate(encodedData PrivateSessionId) (*SessionId
return c.decodeRaw(privateSessionName, decoded)
}
func (c *SessionIdCodec) DecodePublic(encodedData PublicSessionId) (*SessionIdData, error) {
func (c *SessionIdCodec) DecodePublic(encodedData api.PublicSessionId) (*SessionIdData, error) {
decoded, err := c.decodeFromString(string(encodedData))
if err != nil {
return nil, fmt.Errorf("invalid session id: %w", err)

View file

@ -27,6 +27,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/strukturag/nextcloud-spreed-signaling/api"
)
func TestReverseSessionId(t *testing.T) {
@ -158,11 +160,11 @@ func TestPublicPrivate(t *testing.T) {
codec.Put(data)
}
if data, err := codec.DecodePublic(PublicSessionId(private)); !assert.Error(err) {
if data, err := codec.DecodePublic(api.PublicSessionId(private)); !assert.Error(err) {
assert.Fail("should have failed", "received %+v", data)
codec.Put(data)
}
if data, err := codec.DecodePrivate(PrivateSessionId(public)); !assert.Error(err) {
if data, err := codec.DecodePrivate(api.PrivateSessionId(public)); !assert.Error(err) {
assert.Fail("should have failed", "received %+v", data)
codec.Put(data)
}

View file

@ -70,7 +70,7 @@ func getWebsocketUrl(url string) string {
}
}
func getPubliceSessionIdData(h *Hub, publicId PublicSessionId) *SessionIdData {
func getPubliceSessionIdData(h *Hub, publicId api.PublicSessionId) *SessionIdData {
decodedPublic := h.decodePublicSessionId(publicId)
if decodedPublic == nil {
panic("invalid public session id")
@ -78,7 +78,7 @@ func getPubliceSessionIdData(h *Hub, publicId PublicSessionId) *SessionIdData {
return decodedPublic
}
func checkMessageType(t *testing.T, message *ServerMessage, expectedType string) bool {
func checkMessageType(t *testing.T, message *api.ServerMessage, expectedType string) bool {
assert := assert.New(t)
if !assert.NotNil(message, "no message received") {
return false
@ -115,7 +115,7 @@ func checkMessageType(t *testing.T, message *ServerMessage, expectedType string)
return !failed
}
func checkMessageSender(t *testing.T, hub *Hub, sender *MessageServerMessageSender, senderType string, hello *HelloServerMessage) bool {
func checkMessageSender(t *testing.T, hub *Hub, sender *api.MessageServerMessageSender, senderType string, hello *api.HelloServerMessage) bool {
assert := assert.New(t)
return assert.Equal(senderType, sender.Type, "invalid sender type in %+v", sender) &&
assert.Equal(hello.SessionId, sender.SessionId, "invalid session id, expectd %+v, got %+v in %+v",
@ -126,7 +126,7 @@ func checkMessageSender(t *testing.T, hub *Hub, sender *MessageServerMessageSend
assert.Equal(hello.UserId, sender.UserId, "invalid userid in %+v", sender)
}
func checkReceiveClientMessageWithSenderAndRecipient(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *HelloServerMessage, payload any, sender **MessageServerMessageSender, recipient **MessageClientMessageRecipient) bool {
func checkReceiveClientMessageWithSenderAndRecipient(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *api.HelloServerMessage, payload any, sender **api.MessageServerMessageSender, recipient **api.MessageClientMessageRecipient) bool {
assert := assert.New(t)
message, ok := client.RunUntilMessage(ctx)
if !ok ||
@ -145,15 +145,15 @@ func checkReceiveClientMessageWithSenderAndRecipient(ctx context.Context, t *tes
return true
}
func checkReceiveClientMessageWithSender(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *HelloServerMessage, payload any, sender **MessageServerMessageSender) bool {
func checkReceiveClientMessageWithSender(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *api.HelloServerMessage, payload any, sender **api.MessageServerMessageSender) bool {
return checkReceiveClientMessageWithSenderAndRecipient(ctx, t, client, senderType, hello, payload, sender, nil)
}
func checkReceiveClientMessage(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *HelloServerMessage, payload any) bool {
func checkReceiveClientMessage(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *api.HelloServerMessage, payload any) bool {
return checkReceiveClientMessageWithSenderAndRecipient(ctx, t, client, senderType, hello, payload, nil, nil)
}
func checkReceiveClientControlWithSenderAndRecipient(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *HelloServerMessage, payload any, sender **MessageServerMessageSender, recipient **MessageClientMessageRecipient) bool {
func checkReceiveClientControlWithSenderAndRecipient(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *api.HelloServerMessage, payload any, sender **api.MessageServerMessageSender, recipient **api.MessageClientMessageRecipient) bool {
assert := assert.New(t)
message, ok := client.RunUntilMessage(ctx)
if !ok ||
@ -172,15 +172,15 @@ func checkReceiveClientControlWithSenderAndRecipient(ctx context.Context, t *tes
return true
}
func checkReceiveClientControlWithSender(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *HelloServerMessage, payload any, sender **MessageServerMessageSender) bool { // nolint
func checkReceiveClientControlWithSender(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *api.HelloServerMessage, payload any, sender **api.MessageServerMessageSender) bool { // nolint
return checkReceiveClientControlWithSenderAndRecipient(ctx, t, client, senderType, hello, payload, sender, nil)
}
func checkReceiveClientControl(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *HelloServerMessage, payload any) bool {
func checkReceiveClientControl(ctx context.Context, t *testing.T, client *TestClient, senderType string, hello *api.HelloServerMessage, payload any) bool {
return checkReceiveClientControlWithSenderAndRecipient(ctx, t, client, senderType, hello, payload, nil, nil)
}
func checkReceiveClientEvent(ctx context.Context, t *testing.T, client *TestClient, eventType string, msg **EventServerMessage) bool {
func checkReceiveClientEvent(ctx context.Context, t *testing.T, client *TestClient, eventType string, msg **api.EventServerMessage) bool {
assert := assert.New(t)
message, ok := client.RunUntilMessage(ctx)
if !ok ||
@ -210,7 +210,7 @@ type TestClient struct {
messageChan chan []byte
readErrorChan chan error
publicId PublicSessionId
publicId api.PublicSessionId
}
func NewTestClientContext(ctx context.Context, t *testing.T, server *httptest.Server, hub *Hub) *TestClient {
@ -272,7 +272,7 @@ func NewTestClient(t *testing.T, server *httptest.Server, hub *Hub) *TestClient
return client
}
func NewTestClientWithHello(ctx context.Context, t *testing.T, server *httptest.Server, hub *Hub, userId string) (*TestClient, *ServerMessage) {
func NewTestClientWithHello(ctx context.Context, t *testing.T, server *httptest.Server, hub *Hub, userId string) (*TestClient, *api.ServerMessage) {
client := NewTestClient(t, server, hub)
t.Cleanup(func() {
client.CloseWithBye()
@ -345,7 +345,7 @@ func (c *TestClient) WaitForClientRemoved(ctx context.Context) error {
return nil
}
func (c *TestClient) WaitForSessionRemoved(ctx context.Context, sessionId PublicSessionId) error {
func (c *TestClient) WaitForSessionRemoved(ctx context.Context, sessionId api.PublicSessionId) error {
data := c.hub.decodePublicSessionId(sessionId)
if data == nil {
return errors.New("Invalid session id passed")
@ -374,7 +374,7 @@ func (c *TestClient) WaitForSessionRemoved(ctx context.Context, sessionId Public
func (c *TestClient) WriteJSON(data any) error {
if !strings.Contains(c.t.Name(), "HelloUnsupportedVersion") {
if msg, ok := data.(*ClientMessage); ok {
if msg, ok := data.(*api.ClientMessage); ok {
if err := msg.CheckValid(); err != nil {
return err
}
@ -398,7 +398,7 @@ func (c *TestClient) SendHelloV1(userid string) error {
params := TestBackendClientAuthParams{
UserId: userid,
}
return c.SendHelloParams(c.server.URL, HelloVersionV1, "", nil, params)
return c.SendHelloParams(c.server.URL, api.HelloVersionV1, "", nil, params)
}
func (c *TestClient) SendHelloV2(userid string) error {
@ -416,7 +416,7 @@ func (c *TestClient) CreateHelloV2TokenWithUserdata(userid string, issuedAt time
return "", err
}
claims := &HelloV2TokenClaims{
claims := &api.HelloV2TokenClaims{
RegisteredClaims: jwt.RegisteredClaims{
Issuer: c.server.URL,
Subject: userid,
@ -458,18 +458,18 @@ func (c *TestClient) SendHelloV2WithTimesAndFeatures(userid string, issuedAt tim
tokenString, err := c.CreateHelloV2Token(userid, issuedAt, expiresAt)
require.NoError(c.t, err)
params := HelloV2AuthParams{
params := api.HelloV2AuthParams{
Token: tokenString,
}
return c.SendHelloParams(c.server.URL, HelloVersionV2, "", features, params)
return c.SendHelloParams(c.server.URL, api.HelloVersionV2, "", features, params)
}
func (c *TestClient) SendHelloResume(resumeId PrivateSessionId) error {
hello := &ClientMessage{
func (c *TestClient) SendHelloResume(resumeId api.PrivateSessionId) error {
hello := &api.ClientMessage{
Id: "1234",
Type: "hello",
Hello: &HelloClientMessage{
Version: HelloVersionV1,
Hello: &api.HelloClientMessage{
Version: api.HelloVersionV1,
ResumeId: resumeId,
},
}
@ -484,7 +484,7 @@ func (c *TestClient) SendHelloClientWithFeatures(userid string, features []strin
params := TestBackendClientAuthParams{
UserId: userid,
}
return c.SendHelloParams(c.server.URL, HelloVersionV1, "client", features, params)
return c.SendHelloParams(c.server.URL, api.HelloVersionV1, "client", features, params)
}
func (c *TestClient) SendHelloInternal() error {
@ -498,25 +498,25 @@ func (c *TestClient) SendHelloInternalWithFeatures(features []string) error {
token := hex.EncodeToString(mac.Sum(nil))
backend := c.server.URL
params := ClientTypeInternalAuthParams{
params := api.ClientTypeInternalAuthParams{
Random: random,
Token: token,
Backend: backend,
}
return c.SendHelloParams("", HelloVersionV1, "internal", features, params)
return c.SendHelloParams("", api.HelloVersionV1, "internal", features, params)
}
func (c *TestClient) SendHelloParams(url string, version string, clientType ClientType, features []string, params any) error {
func (c *TestClient) SendHelloParams(url string, version string, clientType api.ClientType, features []string, params any) error {
data, err := json.Marshal(params)
require.NoError(c.t, err)
hello := &ClientMessage{
hello := &api.ClientMessage{
Id: "1234",
Type: "hello",
Hello: &HelloClientMessage{
Hello: &api.HelloClientMessage{
Version: version,
Features: features,
Auth: &HelloClientMessageAuth{
Auth: &api.HelloClientMessageAuth{
Type: clientType,
Url: url,
Params: data,
@ -527,22 +527,22 @@ func (c *TestClient) SendHelloParams(url string, version string, clientType Clie
}
func (c *TestClient) SendBye() error {
hello := &ClientMessage{
hello := &api.ClientMessage{
Id: "9876",
Type: "bye",
Bye: &ByeClientMessage{},
Bye: &api.ByeClientMessage{},
}
return c.WriteJSON(hello)
}
func (c *TestClient) SendMessage(recipient MessageClientMessageRecipient, data any) error {
func (c *TestClient) SendMessage(recipient api.MessageClientMessageRecipient, data any) error {
payload, err := json.Marshal(data)
require.NoError(c.t, err)
message := &ClientMessage{
message := &api.ClientMessage{
Id: "abcd",
Type: "message",
Message: &MessageClientMessage{
Message: &api.MessageClientMessage{
Recipient: recipient,
Data: payload,
},
@ -550,15 +550,15 @@ func (c *TestClient) SendMessage(recipient MessageClientMessageRecipient, data a
return c.WriteJSON(message)
}
func (c *TestClient) SendControl(recipient MessageClientMessageRecipient, data any) error {
func (c *TestClient) SendControl(recipient api.MessageClientMessageRecipient, data any) error {
payload, err := json.Marshal(data)
require.NoError(c.t, err)
message := &ClientMessage{
message := &api.ClientMessage{
Id: "abcd",
Type: "control",
Control: &ControlClientMessage{
MessageClientMessage: MessageClientMessage{
Control: &api.ControlClientMessage{
MessageClientMessage: api.MessageClientMessage{
Recipient: recipient,
Data: payload,
},
@ -567,11 +567,11 @@ func (c *TestClient) SendControl(recipient MessageClientMessageRecipient, data a
return c.WriteJSON(message)
}
func (c *TestClient) SendInternalAddSession(msg *AddSessionInternalClientMessage) error {
message := &ClientMessage{
func (c *TestClient) SendInternalAddSession(msg *api.AddSessionInternalClientMessage) error {
message := &api.ClientMessage{
Id: "abcd",
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "addsession",
AddSession: msg,
},
@ -579,11 +579,11 @@ func (c *TestClient) SendInternalAddSession(msg *AddSessionInternalClientMessage
return c.WriteJSON(message)
}
func (c *TestClient) SendInternalUpdateSession(msg *UpdateSessionInternalClientMessage) error {
message := &ClientMessage{
func (c *TestClient) SendInternalUpdateSession(msg *api.UpdateSessionInternalClientMessage) error {
message := &api.ClientMessage{
Id: "abcd",
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "updatesession",
UpdateSession: msg,
},
@ -591,11 +591,11 @@ func (c *TestClient) SendInternalUpdateSession(msg *UpdateSessionInternalClientM
return c.WriteJSON(message)
}
func (c *TestClient) SendInternalRemoveSession(msg *RemoveSessionInternalClientMessage) error {
message := &ClientMessage{
func (c *TestClient) SendInternalRemoveSession(msg *api.RemoveSessionInternalClientMessage) error {
message := &api.ClientMessage{
Id: "abcd",
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "removesession",
RemoveSession: msg,
},
@ -603,11 +603,11 @@ func (c *TestClient) SendInternalRemoveSession(msg *RemoveSessionInternalClientM
return c.WriteJSON(message)
}
func (c *TestClient) SendInternalDialout(msg *DialoutInternalClientMessage) error {
message := &ClientMessage{
func (c *TestClient) SendInternalDialout(msg *api.DialoutInternalClientMessage) error {
message := &api.ClientMessage{
Id: "abcd",
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "dialout",
Dialout: msg,
},
@ -619,10 +619,10 @@ func (c *TestClient) SetTransientData(key string, value any, ttl time.Duration)
payload, err := json.Marshal(value)
require.NoError(c.t, err)
message := &ClientMessage{
message := &api.ClientMessage{
Id: "efgh",
Type: "transient",
TransientData: &TransientDataClientMessage{
TransientData: &api.TransientDataClientMessage{
Type: "set",
Key: key,
Value: payload,
@ -633,10 +633,10 @@ func (c *TestClient) SetTransientData(key string, value any, ttl time.Duration)
}
func (c *TestClient) RemoveTransientData(key string) error {
message := &ClientMessage{
message := &api.ClientMessage{
Id: "ijkl",
Type: "transient",
TransientData: &TransientDataClientMessage{
TransientData: &api.TransientDataClientMessage{
Type: "remove",
Key: key,
},
@ -659,20 +659,20 @@ func (c *TestClient) DrainMessages(ctx context.Context) error {
return nil
}
func (c *TestClient) GetPendingMessages(ctx context.Context) ([]*ServerMessage, error) {
var result []*ServerMessage
func (c *TestClient) GetPendingMessages(ctx context.Context) ([]*api.ServerMessage, error) {
var result []*api.ServerMessage
select {
case err := <-c.readErrorChan:
return nil, err
case msg := <-c.messageChan:
var m ServerMessage
var m api.ServerMessage
if err := json.Unmarshal(msg, &m); err != nil {
return nil, err
}
result = append(result, &m)
n := len(c.messageChan)
for range n {
var m ServerMessage
var m api.ServerMessage
msg = <-c.messageChan
if err := json.Unmarshal(msg, &m); err != nil {
return nil, err
@ -694,7 +694,7 @@ func (c *TestClient) RunUntilClosed(ctx context.Context) bool {
c.assert.NoError(err, "Received unexpected error")
case msg := <-c.messageChan:
var m ServerMessage
var m api.ServerMessage
if err := json.Unmarshal(msg, &m); c.assert.NoError(err, "error decoding received message") {
c.assert.Fail("Server should have closed the connection", "received %+v", m)
}
@ -709,7 +709,7 @@ func (c *TestClient) RunUntilErrorIs(ctx context.Context, targets ...error) bool
select {
case err = <-c.readErrorChan:
case msg := <-c.messageChan:
var m ServerMessage
var m api.ServerMessage
if err := json.Unmarshal(msg, &m); c.assert.NoError(err, "error decoding received message") {
c.assert.Fail("received message", "expected one of errors %+v, got message %+v", targets, m)
}
@ -731,13 +731,13 @@ func (c *TestClient) RunUntilErrorIs(ctx context.Context, targets ...error) bool
return false
}
func (c *TestClient) RunUntilMessage(ctx context.Context) (*ServerMessage, bool) {
func (c *TestClient) RunUntilMessage(ctx context.Context) (*api.ServerMessage, bool) {
select {
case err := <-c.readErrorChan:
c.assert.NoError(err, "error reading while waiting for message")
return nil, false
case msg := <-c.messageChan:
var m ServerMessage
var m api.ServerMessage
if err := json.Unmarshal(msg, &m); c.assert.NoError(err, "error decoding received message") {
return &m, true
}
@ -747,7 +747,7 @@ func (c *TestClient) RunUntilMessage(ctx context.Context) (*ServerMessage, bool)
return nil, false
}
func (c *TestClient) RunUntilMessageOrClosed(ctx context.Context) (*ServerMessage, bool) {
func (c *TestClient) RunUntilMessageOrClosed(ctx context.Context) (*api.ServerMessage, bool) {
select {
case err := <-c.readErrorChan:
if c.assert.Error(err) && websocket.IsCloseError(err, websocket.CloseNoStatusReceived) {
@ -757,7 +757,7 @@ func (c *TestClient) RunUntilMessageOrClosed(ctx context.Context) (*ServerMessag
c.assert.NoError(err, "Received unexpected error")
return nil, false
case msg := <-c.messageChan:
var m ServerMessage
var m api.ServerMessage
if err := json.Unmarshal(msg, &m); c.assert.NoError(err, "error decoding received message") {
return &m, true
}
@ -767,7 +767,7 @@ func (c *TestClient) RunUntilMessageOrClosed(ctx context.Context) (*ServerMessag
return nil, false
}
func (c *TestClient) RunUntilError(ctx context.Context, code string) (*Error, bool) {
func (c *TestClient) RunUntilError(ctx context.Context, code string) (*api.Error, bool) {
message, ok := c.RunUntilMessage(ctx)
if !ok ||
!checkMessageType(c.t, message, "error") ||
@ -778,7 +778,7 @@ func (c *TestClient) RunUntilError(ctx context.Context, code string) (*Error, bo
return message.Error, true
}
func (c *TestClient) RunUntilHello(ctx context.Context) (*ServerMessage, bool) {
func (c *TestClient) RunUntilHello(ctx context.Context) (*api.ServerMessage, bool) {
message, ok := c.RunUntilMessage(ctx)
if !ok ||
!checkMessageType(c.t, message, "hello") {
@ -789,15 +789,15 @@ func (c *TestClient) RunUntilHello(ctx context.Context) (*ServerMessage, bool) {
return message, true
}
func (c *TestClient) JoinRoom(ctx context.Context, roomId string) (*ServerMessage, bool) {
return c.JoinRoomWithRoomSession(ctx, roomId, RoomSessionId(fmt.Sprintf("%s-%s", roomId, c.publicId)))
func (c *TestClient) JoinRoom(ctx context.Context, roomId string) (*api.ServerMessage, bool) {
return c.JoinRoomWithRoomSession(ctx, roomId, api.RoomSessionId(fmt.Sprintf("%s-%s", roomId, c.publicId)))
}
func (c *TestClient) JoinRoomWithRoomSession(ctx context.Context, roomId string, roomSessionId RoomSessionId) (message *ServerMessage, ok bool) {
msg := &ClientMessage{
func (c *TestClient) JoinRoomWithRoomSession(ctx context.Context, roomId string, roomSessionId api.RoomSessionId) (message *api.ServerMessage, ok bool) {
msg := &api.ClientMessage{
Id: "ABCD",
Type: "room",
Room: &RoomClientMessage{
Room: &api.RoomClientMessage{
RoomId: roomId,
SessionId: roomSessionId,
},
@ -815,7 +815,7 @@ func (c *TestClient) JoinRoomWithRoomSession(ctx context.Context, roomId string,
return message, true
}
func checkMessageRoomId(t *testing.T, message *ServerMessage, roomId string) bool {
func checkMessageRoomId(t *testing.T, message *api.ServerMessage, roomId string) bool {
return checkMessageType(t, message, "room") &&
assert.Equal(t, roomId, message.Room.RoomId, "invalid room id in %+v", message)
}
@ -825,18 +825,18 @@ func (c *TestClient) RunUntilRoom(ctx context.Context, roomId string) bool {
return ok && checkMessageRoomId(c.t, message, roomId)
}
func (c *TestClient) checkMessageJoined(message *ServerMessage, hello *HelloServerMessage) bool {
func (c *TestClient) checkMessageJoined(message *api.ServerMessage, hello *api.HelloServerMessage) bool {
return c.checkMessageJoinedSession(message, hello.SessionId, hello.UserId)
}
func (c *TestClient) checkSingleMessageJoined(message *ServerMessage) bool {
func (c *TestClient) checkSingleMessageJoined(message *api.ServerMessage) bool {
return checkMessageType(c.t, message, "event") &&
c.assert.Equal("room", message.Event.Target, "invalid event target in %+v", message) &&
c.assert.Equal("join", message.Event.Type, "invalid event type in %+v", message) &&
c.assert.Len(message.Event.Join, 1, "invalid number of join event entries in %+v", message)
}
func (c *TestClient) checkMessageJoinedSession(message *ServerMessage, sessionId PublicSessionId, userId string) bool {
func (c *TestClient) checkMessageJoinedSession(message *api.ServerMessage, sessionId api.PublicSessionId, userId string) bool {
if !c.checkSingleMessageJoined(message) {
return false
}
@ -858,10 +858,10 @@ func (c *TestClient) checkMessageJoinedSession(message *ServerMessage, sessionId
return !failed
}
func (c *TestClient) RunUntilJoinedAndReturn(ctx context.Context, hello ...*HelloServerMessage) ([]EventServerMessageSessionEntry, []*ServerMessage, bool) {
received := make([]EventServerMessageSessionEntry, len(hello))
var ignored []*ServerMessage
hellos := make(map[*HelloServerMessage]int, len(hello))
func (c *TestClient) RunUntilJoinedAndReturn(ctx context.Context, hello ...*api.HelloServerMessage) ([]api.EventServerMessageSessionEntry, []*api.ServerMessage, bool) {
received := make([]api.EventServerMessageSessionEntry, len(hello))
var ignored []*api.ServerMessage
hellos := make(map[*api.HelloServerMessage]int, len(hello))
for idx, h := range hello {
hellos[h] = idx
}
@ -905,16 +905,16 @@ func (c *TestClient) RunUntilJoinedAndReturn(ctx context.Context, hello ...*Hell
return received, ignored, true
}
func (c *TestClient) RunUntilJoined(ctx context.Context, hello ...*HelloServerMessage) bool {
func (c *TestClient) RunUntilJoined(ctx context.Context, hello ...*api.HelloServerMessage) bool {
_, unexpected, ok := c.RunUntilJoinedAndReturn(ctx, hello...)
return ok && c.assert.Empty(unexpected, "Received unexpected messages: %+v", unexpected)
}
func (c *TestClient) checkMessageRoomLeave(message *ServerMessage, hello *HelloServerMessage) bool {
func (c *TestClient) checkMessageRoomLeave(message *api.ServerMessage, hello *api.HelloServerMessage) bool {
return c.checkMessageRoomLeaveSession(message, hello.SessionId)
}
func (c *TestClient) checkMessageRoomLeaveSession(message *ServerMessage, sessionId PublicSessionId) bool {
func (c *TestClient) checkMessageRoomLeaveSession(message *api.ServerMessage, sessionId api.PublicSessionId) bool {
return checkMessageType(c.t, message, "event") &&
c.assert.Equal("room", message.Event.Target, "invalid target in %+v", message) &&
c.assert.Equal("leave", message.Event.Type, "invalid event type in %+v", message) &&
@ -926,12 +926,12 @@ func (c *TestClient) checkMessageRoomLeaveSession(message *ServerMessage, sessio
)
}
func (c *TestClient) RunUntilLeft(ctx context.Context, hello *HelloServerMessage) bool {
func (c *TestClient) RunUntilLeft(ctx context.Context, hello *api.HelloServerMessage) bool {
message, ok := c.RunUntilMessage(ctx)
return ok && c.checkMessageRoomLeave(message, hello)
}
func checkMessageRoomlistUpdate(t *testing.T, message *ServerMessage) (*RoomEventServerMessage, bool) {
func checkMessageRoomlistUpdate(t *testing.T, message *api.ServerMessage) (*api.RoomEventServerMessage, bool) {
assert := assert.New(t)
if !checkMessageType(t, message, "event") ||
!assert.Equal("roomlist", message.Event.Target, "invalid event target in %+v", message) ||
@ -943,7 +943,7 @@ func checkMessageRoomlistUpdate(t *testing.T, message *ServerMessage) (*RoomEven
return message.Event.Update, true
}
func (c *TestClient) RunUntilRoomlistUpdate(ctx context.Context) (*RoomEventServerMessage, bool) {
func (c *TestClient) RunUntilRoomlistUpdate(ctx context.Context) (*api.RoomEventServerMessage, bool) {
message, ok := c.RunUntilMessage(ctx)
if !ok {
return nil, false
@ -952,7 +952,7 @@ func (c *TestClient) RunUntilRoomlistUpdate(ctx context.Context) (*RoomEventServ
return checkMessageRoomlistUpdate(c.t, message)
}
func checkMessageRoomlistDisinvite(t *testing.T, message *ServerMessage) (*RoomDisinviteEventServerMessage, bool) {
func checkMessageRoomlistDisinvite(t *testing.T, message *api.ServerMessage) (*api.RoomDisinviteEventServerMessage, bool) {
assert := assert.New(t)
if !checkMessageType(t, message, "event") ||
!assert.Equal("roomlist", message.Event.Target, "invalid event target in %+v", message) ||
@ -964,7 +964,7 @@ func checkMessageRoomlistDisinvite(t *testing.T, message *ServerMessage) (*RoomD
return message.Event.Disinvite, true
}
func (c *TestClient) RunUntilRoomlistDisinvite(ctx context.Context) (*RoomDisinviteEventServerMessage, bool) {
func (c *TestClient) RunUntilRoomlistDisinvite(ctx context.Context) (*api.RoomDisinviteEventServerMessage, bool) {
message, ok := c.RunUntilMessage(ctx)
if !ok {
return nil, false
@ -973,7 +973,7 @@ func (c *TestClient) RunUntilRoomlistDisinvite(ctx context.Context) (*RoomDisinv
return checkMessageRoomlistDisinvite(c.t, message)
}
func checkMessageParticipantsInCall(t *testing.T, message *ServerMessage) (*RoomEventServerMessage, bool) {
func checkMessageParticipantsInCall(t *testing.T, message *api.ServerMessage) (*api.RoomEventServerMessage, bool) {
assert := assert.New(t)
if !checkMessageType(t, message, "event") ||
!assert.Equal("participants", message.Event.Target, "invalid event target in %+v", message) ||
@ -985,7 +985,7 @@ func checkMessageParticipantsInCall(t *testing.T, message *ServerMessage) (*Room
return message.Event.Update, true
}
func checkMessageParticipantFlags(t *testing.T, message *ServerMessage) (*RoomFlagsServerMessage, bool) {
func checkMessageParticipantFlags(t *testing.T, message *api.ServerMessage) (*api.RoomFlagsServerMessage, bool) {
assert := assert.New(t)
if !checkMessageType(t, message, "event") ||
!assert.Equal("participants", message.Event.Target, "invalid event target in %+v", message) ||
@ -997,7 +997,7 @@ func checkMessageParticipantFlags(t *testing.T, message *ServerMessage) (*RoomFl
return message.Event.Flags, true
}
func checkMessageRoomMessage(t *testing.T, message *ServerMessage) (*RoomEventMessage, bool) {
func checkMessageRoomMessage(t *testing.T, message *api.ServerMessage) (*api.RoomEventMessage, bool) {
assert := assert.New(t)
if !checkMessageType(t, message, "event") ||
!assert.Equal("room", message.Event.Target, "invalid event target in %+v", message) ||
@ -1009,7 +1009,7 @@ func checkMessageRoomMessage(t *testing.T, message *ServerMessage) (*RoomEventMe
return message.Event.Message, true
}
func (c *TestClient) RunUntilRoomMessage(ctx context.Context) (*RoomEventMessage, bool) {
func (c *TestClient) RunUntilRoomMessage(ctx context.Context) (*api.RoomEventMessage, bool) {
message, ok := c.RunUntilMessage(ctx)
if !ok {
return nil, false
@ -1018,7 +1018,7 @@ func (c *TestClient) RunUntilRoomMessage(ctx context.Context) (*RoomEventMessage
return checkMessageRoomMessage(c.t, message)
}
func checkMessageError(t *testing.T, message *ServerMessage, msgid string) bool {
func checkMessageError(t *testing.T, message *api.ServerMessage, msgid string) bool {
return checkMessageType(t, message, "error") &&
assert.Equal(t, msgid, message.Error.Code, "invalid error code in %+v", message)
}
@ -1059,14 +1059,14 @@ func (c *TestClient) RunUntilAnswer(ctx context.Context, answer string) bool {
return c.RunUntilAnswerFromSender(ctx, answer, nil)
}
func (c *TestClient) RunUntilAnswerFromSender(ctx context.Context, answer string, sender *MessageServerMessageSender) bool {
func (c *TestClient) RunUntilAnswerFromSender(ctx context.Context, answer string, sender *api.MessageServerMessageSender) bool {
message, ok := c.RunUntilMessage(ctx)
if !ok || !checkMessageType(c.t, message, "message") {
return false
}
if sender != nil {
if !checkMessageSender(c.t, c.hub, message.Message.Sender, sender.Type, &HelloServerMessage{
if !checkMessageSender(c.t, c.hub, message.Message.Sender, sender.Type, &api.HelloServerMessage{
SessionId: sender.SessionId,
UserId: sender.UserId,
}) {
@ -1100,7 +1100,7 @@ func (c *TestClient) RunUntilAnswerFromSender(ctx context.Context, answer string
return true
}
func checkMessageTransientSet(t *testing.T, message *ServerMessage, key string, value any, oldValue any) bool {
func checkMessageTransientSet(t *testing.T, message *api.ServerMessage, key string, value any, oldValue any) bool {
assert := assert.New(t)
return checkMessageType(t, message, "transient") &&
assert.Equal("set", message.TransientData.Type, "invalid message type in %+v", message) &&
@ -1109,7 +1109,7 @@ func checkMessageTransientSet(t *testing.T, message *ServerMessage, key string,
assert.EqualValues(oldValue, message.TransientData.OldValue, "invalid old value in %+v", message)
}
func checkMessageTransientRemove(t *testing.T, message *ServerMessage, key string, oldValue any) bool {
func checkMessageTransientRemove(t *testing.T, message *api.ServerMessage, key string, oldValue any) bool {
assert := assert.New(t)
return checkMessageType(t, message, "transient") &&
assert.Equal("remove", message.TransientData.Type, "invalid message type in %+v", message) &&
@ -1117,14 +1117,14 @@ func checkMessageTransientRemove(t *testing.T, message *ServerMessage, key strin
assert.EqualValues(oldValue, message.TransientData.OldValue, "invalid old value in %+v", message)
}
func checkMessageTransientInitial(t *testing.T, message *ServerMessage, data api.StringMap) bool {
func checkMessageTransientInitial(t *testing.T, message *api.ServerMessage, data api.StringMap) bool {
assert := assert.New(t)
return checkMessageType(t, message, "transient") &&
assert.Equal("initial", message.TransientData.Type, "invalid message type in %+v", message) &&
assert.Equal(data, message.TransientData.Data, "invalid initial data in %+v", message)
}
func checkMessageInCallAll(t *testing.T, message *ServerMessage, roomId string, inCall int) bool {
func checkMessageInCallAll(t *testing.T, message *api.ServerMessage, roomId string, inCall int) bool {
assert := assert.New(t)
return checkMessageType(t, message, "event") &&
assert.Equal("update", message.Event.Type, "invalid event type, got %+v", message.Event) &&
@ -1134,7 +1134,7 @@ func checkMessageInCallAll(t *testing.T, message *ServerMessage, roomId string,
assert.EqualValues(strconv.FormatInt(int64(inCall), 10), message.Event.Update.InCall, "expected incall flags %d, got %+v", inCall, message.Event.Update)
}
func checkMessageSwitchTo(t *testing.T, message *ServerMessage, roomId string, details json.RawMessage) (*EventServerMessageSwitchTo, bool) {
func checkMessageSwitchTo(t *testing.T, message *api.ServerMessage, roomId string, details json.RawMessage) (*api.EventServerMessageSwitchTo, bool) {
assert := assert.New(t)
if !checkMessageType(t, message, "event") ||
!assert.Equal("switchto", message.Event.Type, "invalid event type, got %+v", message.Event) ||
@ -1153,7 +1153,7 @@ func checkMessageSwitchTo(t *testing.T, message *ServerMessage, roomId string, d
return message.Event.SwitchTo, true
}
func (c *TestClient) RunUntilSwitchTo(ctx context.Context, roomId string, details json.RawMessage) (*EventServerMessageSwitchTo, bool) {
func (c *TestClient) RunUntilSwitchTo(ctx context.Context, roomId string, details json.RawMessage) (*api.EventServerMessageSwitchTo, bool) {
message, ok := c.RunUntilMessage(ctx)
if !ok {
return nil, false

View file

@ -27,9 +27,11 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/strukturag/nextcloud-spreed-signaling/api"
)
func WaitForUsersJoined(ctx context.Context, t *testing.T, client1 *TestClient, hello1 *ServerMessage, client2 *TestClient, hello2 *ServerMessage) {
func WaitForUsersJoined(ctx context.Context, t *testing.T, client1 *TestClient, hello1 *api.ServerMessage, client2 *TestClient, hello2 *api.ServerMessage) {
t.Helper()
// We will receive "joined" events for all clients. The ordering is not
// defined as messages are processed and sent by asynchronous event handlers.

View file

@ -36,7 +36,7 @@ const (
)
type TransientListener interface {
SendMessage(message *ServerMessage) bool
SendMessage(message *api.ServerMessage) bool
}
type TransientDataEntry struct {
@ -103,7 +103,7 @@ func NewTransientData() *TransientData {
}
// +checklocks:t.mu
func (t *TransientData) sendMessageToListener(listener TransientListener, message *ServerMessage) {
func (t *TransientData) sendMessageToListener(listener TransientListener, message *api.ServerMessage) {
t.mu.Unlock()
defer t.mu.Lock()
@ -112,9 +112,9 @@ func (t *TransientData) sendMessageToListener(listener TransientListener, messag
// +checklocks:t.mu
func (t *TransientData) notifySet(key string, prev, value any) {
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "transient",
TransientData: &TransientDataServerMessage{
TransientData: &api.TransientDataServerMessage{
Type: "set",
Key: key,
Value: value,
@ -128,9 +128,9 @@ func (t *TransientData) notifySet(key string, prev, value any) {
// +checklocks:t.mu
func (t *TransientData) notifyDeleted(key string, prev *TransientDataEntry) {
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "transient",
TransientData: &TransientDataServerMessage{
TransientData: &api.TransientDataServerMessage{
Type: "remove",
Key: key,
},
@ -157,9 +157,9 @@ func (t *TransientData) AddListener(listener TransientListener) {
for k, v := range t.data {
data[k] = v.Value
}
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "transient",
TransientData: &TransientDataServerMessage{
TransientData: &api.TransientDataServerMessage{
Type: "initial",
Data: data,
},
@ -385,9 +385,9 @@ func (t *TransientData) SetInitial(data TransientDataEntries) {
if len(msgData) == 0 {
return
}
msg := &ServerMessage{
msg := &api.ServerMessage{
Type: "transient",
TransientData: &TransientDataServerMessage{
TransientData: &api.TransientDataServerMessage{
Type: "initial",
Data: msgData,
},

View file

@ -104,7 +104,7 @@ type MockTransientListener struct {
data *TransientData
}
func (l *MockTransientListener) SendMessage(message *ServerMessage) bool {
func (l *MockTransientListener) SendMessage(message *api.ServerMessage) bool {
close(l.sending)
time.Sleep(10 * time.Millisecond)
@ -275,7 +275,7 @@ func Test_TransientMessages(t *testing.T) {
_, ignored, ok := client3.RunUntilJoinedAndReturn(ctx, hello2.Hello, hello3.Hello)
require.True(ok)
var msg *ServerMessage
var msg *api.ServerMessage
if len(ignored) == 0 {
msg = MustSucceed1(t, client3.RunUntilMessage, ctx)
} else if len(ignored) == 1 {
@ -392,7 +392,7 @@ func Test_TransientSessionData(t *testing.T) {
client1.CloseWithBye()
assert.NoError(client1.WaitForClientRemoved(ctx))
var messages []*ServerMessage
var messages []*api.ServerMessage
for range 2 {
if msg, ok := client2.RunUntilMessage(ctx); ok {
messages = append(messages, msg)
@ -413,7 +413,7 @@ func Test_TransientSessionData(t *testing.T) {
_, ignored, ok := client3.RunUntilJoinedAndReturn(ctx, hello2.Hello, hello3.Hello)
require.True(ok)
var msg *ServerMessage
var msg *api.ServerMessage
if len(ignored) == 0 {
msg = MustSucceed1(t, client3.RunUntilMessage, ctx)
} else if len(ignored) == 1 {

View file

@ -43,30 +43,30 @@ type VirtualSession struct {
logger log.Logger
hub *Hub
session *ClientSession
privateId PrivateSessionId
publicId PublicSessionId
privateId api.PrivateSessionId
publicId api.PublicSessionId
data *SessionIdData
ctx context.Context
closeFunc context.CancelFunc
room atomic.Pointer[Room]
sessionId PublicSessionId
sessionId api.PublicSessionId
userId string
userData json.RawMessage
inCall Flags
flags Flags
options *AddSessionOptions
options *api.AddSessionOptions
parseUserData func() (api.StringMap, error)
asyncCh AsyncChannel
}
func GetVirtualSessionId(session Session, sessionId PublicSessionId) PublicSessionId {
func GetVirtualSessionId(session Session, sessionId api.PublicSessionId) api.PublicSessionId {
return session.PublicId() + "|" + sessionId
}
func NewVirtualSession(session *ClientSession, privateId PrivateSessionId, publicId PublicSessionId, data *SessionIdData, msg *AddSessionInternalClientMessage) (*VirtualSession, error) {
func NewVirtualSession(session *ClientSession, privateId api.PrivateSessionId, publicId api.PublicSessionId, data *SessionIdData, msg *api.AddSessionInternalClientMessage) (*VirtualSession, error) {
ctx := log.NewLoggerContext(session.Context(), session.hub.logger)
ctx, closeFunc := context.WithCancel(ctx)
@ -95,7 +95,7 @@ func NewVirtualSession(session *ClientSession, privateId PrivateSessionId, publi
if msg.InCall != nil {
result.SetInCall(*msg.InCall)
} else if !session.HasFeature(ClientFeatureInternalInCall) {
} else if !session.HasFeature(api.ClientFeatureInternalInCall) {
result.SetInCall(FlagInCall | FlagWithPhone)
}
if msg.Flags != 0 {
@ -110,16 +110,16 @@ func (s *VirtualSession) Context() context.Context {
return s.ctx
}
func (s *VirtualSession) PrivateId() PrivateSessionId {
func (s *VirtualSession) PrivateId() api.PrivateSessionId {
return s.privateId
}
func (s *VirtualSession) PublicId() PublicSessionId {
func (s *VirtualSession) PublicId() api.PublicSessionId {
return s.publicId
}
func (s *VirtualSession) ClientType() ClientType {
return HelloClientTypeVirtual
func (s *VirtualSession) ClientType() api.ClientType {
return api.HelloClientTypeVirtual
}
func (s *VirtualSession) GetInCall() int {
@ -169,7 +169,7 @@ func (s *VirtualSession) ParsedUserData() (api.StringMap, error) {
func (s *VirtualSession) SetRoom(room *Room) {
s.room.Store(room)
if room != nil {
if err := s.hub.roomSessions.SetRoomSession(s, RoomSessionId(s.PublicId())); err != nil {
if err := s.hub.roomSessions.SetRoomSession(s, api.RoomSessionId(s.PublicId())); err != nil {
s.logger.Printf("Error adding virtual room session %s: %s", s.PublicId(), err)
}
} else {
@ -181,6 +181,11 @@ func (s *VirtualSession) GetRoom() *Room {
return s.room.Load()
}
func (s *VirtualSession) IsInRoom(id string) bool {
room := s.GetRoom()
return room != nil && room.Id() == id
}
func (s *VirtualSession) LeaveRoom(notify bool) *Room {
room := s.GetRoom()
if room == nil {
@ -214,7 +219,7 @@ func (s *VirtualSession) Close() {
s.CloseWithFeedback(nil, nil)
}
func (s *VirtualSession) CloseWithFeedback(session Session, message *ClientMessage) {
func (s *VirtualSession) CloseWithFeedback(session Session, message *api.ClientMessage) {
s.closeFunc()
room := s.GetRoom()
@ -228,13 +233,13 @@ func (s *VirtualSession) CloseWithFeedback(session Session, message *ClientMessa
}
}
func (s *VirtualSession) notifyBackendRemoved(room *Room, session Session, message *ClientMessage) {
func (s *VirtualSession) notifyBackendRemoved(room *Room, session Session, message *api.ClientMessage) {
ctx := log.NewLoggerContext(context.Background(), s.logger)
ctx, cancel := context.WithTimeout(ctx, s.hub.backendTimeout)
defer cancel()
if options := s.Options(); options != nil && options.ActorId != "" && options.ActorType != "" {
request := NewBackendClientRoomRequest(room.Id(), s.UserId(), RoomSessionId(s.PublicId()))
request := NewBackendClientRoomRequest(room.Id(), s.UserId(), api.RoomSessionId(s.PublicId()))
request.Room.Action = "leave"
request.Room.ActorId = options.ActorId
request.Room.ActorType = options.ActorType
@ -244,7 +249,7 @@ func (s *VirtualSession) notifyBackendRemoved(room *Room, session Session, messa
virtualSessionId := GetVirtualSessionId(s.session, s.PublicId())
s.logger.Printf("Could not leave virtual session %s at backend %s: %s", virtualSessionId, s.BackendUrl(), err)
if session != nil && message != nil {
reply := message.NewErrorServerMessage(NewError("remove_failed", "Could not remove virtual session from backend."))
reply := message.NewErrorServerMessage(api.NewError("remove_failed", "Could not remove virtual session from backend."))
session.SendMessage(reply)
}
return
@ -254,13 +259,13 @@ func (s *VirtualSession) notifyBackendRemoved(room *Room, session Session, messa
virtualSessionId := GetVirtualSessionId(s.session, s.PublicId())
if session != nil && message != nil && (response.Error == nil || response.Error.Code != "no_such_room") {
s.logger.Printf("Could not leave virtual session %s at backend %s: %+v", virtualSessionId, s.BackendUrl(), response.Error)
reply := message.NewErrorServerMessage(NewError("remove_failed", response.Error.Error()))
reply := message.NewErrorServerMessage(api.NewError("remove_failed", response.Error.Error()))
session.SendMessage(reply)
}
return
}
} else {
request := NewBackendClientSessionRequest(room.Id(), "remove", s.PublicId(), &AddSessionInternalClientMessage{
request := NewBackendClientSessionRequest(room.Id(), "remove", s.PublicId(), &api.AddSessionInternalClientMessage{
UserId: s.userId,
User: s.userData,
})
@ -269,7 +274,7 @@ func (s *VirtualSession) notifyBackendRemoved(room *Room, session Session, messa
if err != nil {
s.logger.Printf("Could not remove virtual session %s from backend %s: %s", s.PublicId(), s.BackendUrl(), err)
if session != nil && message != nil {
reply := message.NewErrorServerMessage(NewError("remove_failed", "Could not remove virtual session from backend."))
reply := message.NewErrorServerMessage(api.NewError("remove_failed", "Could not remove virtual session from backend."))
session.SendMessage(reply)
}
}
@ -284,7 +289,7 @@ func (s *VirtualSession) Session() *ClientSession {
return s.session
}
func (s *VirtualSession) SessionId() PublicSessionId {
func (s *VirtualSession) SessionId() api.PublicSessionId {
return s.sessionId
}
@ -304,7 +309,7 @@ func (s *VirtualSession) Flags() uint32 {
return s.flags.Get()
}
func (s *VirtualSession) Options() *AddSessionOptions {
func (s *VirtualSession) Options() *api.AddSessionOptions {
return s.options
}
@ -327,7 +332,7 @@ func (s *VirtualSession) processAsyncMessage(message *AsyncMessage) {
message.Message.Message.Recipient.Type == "session" &&
message.Message.Message.Recipient.SessionId == s.PublicId() {
// The client should see his session id as recipient.
message.Message.Message.Recipient = &MessageClientMessageRecipient{
message.Message.Message.Recipient = &api.MessageClientMessageRecipient{
Type: "session",
SessionId: s.SessionId(),
UserId: s.UserId(),
@ -356,10 +361,10 @@ func (s *VirtualSession) processAsyncMessage(message *AsyncMessage) {
s.session.processAsyncMessage(&AsyncMessage{
Type: "message",
SendTime: message.SendTime,
Message: &ServerMessage{
Message: &api.ServerMessage{
Type: "control",
Control: &ControlServerMessage{
Recipient: &MessageClientMessageRecipient{
Control: &api.ControlServerMessage{
Recipient: &api.MessageClientMessageRecipient{
Type: "session",
SessionId: s.SessionId(),
UserId: s.UserId(),
@ -375,7 +380,7 @@ func (s *VirtualSession) processAsyncMessage(message *AsyncMessage) {
message.Message.Control.Recipient.Type == "session" &&
message.Message.Control.Recipient.SessionId == s.PublicId() {
// The client should see his session id as recipient.
message.Message.Control.Recipient = &MessageClientMessageRecipient{
message.Message.Control.Recipient = &api.MessageClientMessageRecipient{
Type: "session",
SessionId: s.SessionId(),
UserId: s.UserId(),
@ -386,10 +391,10 @@ func (s *VirtualSession) processAsyncMessage(message *AsyncMessage) {
}
}
func (s *VirtualSession) SendError(e *Error) bool {
func (s *VirtualSession) SendError(e *api.Error) bool {
return s.session.SendError(e)
}
func (s *VirtualSession) SendMessage(message *ServerMessage) bool {
func (s *VirtualSession) SendMessage(message *api.ServerMessage) bool {
return s.session.SendMessage(message)
}

View file

@ -68,14 +68,14 @@ func TestVirtualSession(t *testing.T) {
// Ignore "join" events.
assert.NoError(client.DrainMessages(ctx))
internalSessionId := PublicSessionId("session1")
internalSessionId := api.PublicSessionId("session1")
userId := "user1"
msgAdd := &ClientMessage{
msgAdd := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "addsession",
AddSession: &AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
AddSession: &api.AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
@ -92,7 +92,7 @@ func TestVirtualSession(t *testing.T) {
sessionId := msg1.Event.Join[0].SessionId
session := hub.GetSessionByPublicId(sessionId)
if assert.NotNil(session, "Could not get virtual session %s", sessionId) {
assert.Equal(HelloClientTypeVirtual, session.ClientType())
assert.Equal(api.HelloClientTypeVirtual, session.ClientType())
sid := session.(*VirtualSession).SessionId()
assert.Equal(internalSessionId, sid)
}
@ -116,12 +116,12 @@ func TestVirtualSession(t *testing.T) {
}
newFlags := uint32(FLAG_TALKING)
msgFlags := &ClientMessage{
msgFlags := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "updatesession",
UpdateSession: &UpdateSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
UpdateSession: &api.UpdateSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
@ -144,7 +144,7 @@ func TestVirtualSession(t *testing.T) {
require.Equal(roomId, roomMsg.Room.RoomId)
gotFlags := false
var receivedMessages []*ServerMessage
var receivedMessages []*api.ServerMessage
for !gotFlags {
messages, err := client2.GetPendingMessages(ctx)
if err != nil {
@ -175,7 +175,7 @@ func TestVirtualSession(t *testing.T) {
// When sending to a virtual session, the message is sent to the actual
// client and contains a "Recipient" block with the internal session id.
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "session",
SessionId: sessionId,
}
@ -197,12 +197,12 @@ func TestVirtualSession(t *testing.T) {
assert.Equal(data, payload)
}
msgRemove := &ClientMessage{
msgRemove := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "removesession",
RemoveSession: &RemoveSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
RemoveSession: &api.RemoveSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
@ -251,20 +251,20 @@ func TestVirtualSessionActorInformation(t *testing.T) {
// Ignore "join" events.
assert.NoError(client.DrainMessages(ctx))
internalSessionId := PublicSessionId("session1")
internalSessionId := api.PublicSessionId("session1")
userId := "user1"
msgAdd := &ClientMessage{
msgAdd := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "addsession",
AddSession: &AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
AddSession: &api.AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
UserId: userId,
Flags: FLAG_MUTED_SPEAKING,
Options: &AddSessionOptions{
Options: &api.AddSessionOptions{
ActorId: "actor-id",
ActorType: "actor-type",
},
@ -279,7 +279,7 @@ func TestVirtualSessionActorInformation(t *testing.T) {
sessionId := msg1.Event.Join[0].SessionId
session := hub.GetSessionByPublicId(sessionId)
if assert.NotNil(session, "Could not get virtual session %s", sessionId) {
assert.Equal(HelloClientTypeVirtual, session.ClientType())
assert.Equal(api.HelloClientTypeVirtual, session.ClientType())
sid := session.(*VirtualSession).SessionId()
assert.Equal(internalSessionId, sid)
}
@ -303,12 +303,12 @@ func TestVirtualSessionActorInformation(t *testing.T) {
}
newFlags := uint32(FLAG_TALKING)
msgFlags := &ClientMessage{
msgFlags := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "updatesession",
UpdateSession: &UpdateSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
UpdateSession: &api.UpdateSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
@ -331,7 +331,7 @@ func TestVirtualSessionActorInformation(t *testing.T) {
require.Equal(roomId, roomMsg.Room.RoomId)
gotFlags := false
var receivedMessages []*ServerMessage
var receivedMessages []*api.ServerMessage
for !gotFlags {
messages, err := client2.GetPendingMessages(ctx)
if err != nil {
@ -362,7 +362,7 @@ func TestVirtualSessionActorInformation(t *testing.T) {
// When sending to a virtual session, the message is sent to the actual
// client and contains a "Recipient" block with the internal session id.
recipient := MessageClientMessageRecipient{
recipient := api.MessageClientMessageRecipient{
Type: "session",
SessionId: sessionId,
}
@ -384,12 +384,12 @@ func TestVirtualSessionActorInformation(t *testing.T) {
assert.Equal(data, payload)
}
msgRemove := &ClientMessage{
msgRemove := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "removesession",
RemoveSession: &RemoveSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
RemoveSession: &api.RemoveSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
@ -403,11 +403,11 @@ func TestVirtualSessionActorInformation(t *testing.T) {
}
}
func checkHasEntryWithInCall(t *testing.T, message *RoomEventServerMessage, sessionId PublicSessionId, entryType string, inCall int) bool {
func checkHasEntryWithInCall(t *testing.T, message *api.RoomEventServerMessage, sessionId api.PublicSessionId, entryType string, inCall int) bool {
assert := assert.New(t)
found := false
for _, entry := range message.Users {
if sid, ok := api.GetStringMapString[PublicSessionId](entry, "sessionId"); ok && sid == sessionId {
if sid, ok := api.GetStringMapString[api.PublicSessionId](entry, "sessionId"); ok && sid == sessionId {
if value, found := api.GetStringMapEntry[bool](entry, entryType); !assert.True(found, "entry %s not found or invalid in %+v", entryType, entry) ||
!assert.True(value, "entry %s invalid in %+v", entryType, entry) {
return false
@ -443,7 +443,7 @@ func TestVirtualSessionCustomInCall(t *testing.T) {
clientInternal := NewTestClient(t, server, hub)
defer clientInternal.CloseWithBye()
features := []string{
ClientFeatureInternalInCall,
api.ClientFeatureInternalInCall,
}
require.NoError(clientInternal.SendHelloInternalWithFeatures(features))
@ -474,14 +474,14 @@ func TestVirtualSessionCustomInCall(t *testing.T) {
}
client.RunUntilJoined(ctx, helloInternal.Hello, hello.Hello)
internalSessionId := PublicSessionId("session1")
internalSessionId := api.PublicSessionId("session1")
userId := "user1"
msgAdd := &ClientMessage{
msgAdd := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "addsession",
AddSession: &AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
AddSession: &api.AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
@ -498,7 +498,7 @@ func TestVirtualSessionCustomInCall(t *testing.T) {
sessionId := msg1.Event.Join[0].SessionId
session := hub.GetSessionByPublicId(sessionId)
if assert.NotNil(session) {
assert.Equal(HelloClientTypeVirtual, session.ClientType())
assert.Equal(api.HelloClientTypeVirtual, session.ClientType())
sid := session.(*VirtualSession).SessionId()
assert.Equal(internalSessionId, sid)
}
@ -521,11 +521,11 @@ func TestVirtualSessionCustomInCall(t *testing.T) {
}
// The internal session can change its "inCall" flags
msgInCall := &ClientMessage{
msgInCall := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "incall",
InCall: &InCallInternalClientMessage{
InCall: &api.InCallInternalClientMessage{
InCall: FlagInCall | FlagWithAudio,
},
},
@ -542,12 +542,12 @@ func TestVirtualSessionCustomInCall(t *testing.T) {
// The internal session can change the "inCall" flags of a virtual session
newInCall := FlagInCall | FlagWithPhone
msgInCall2 := &ClientMessage{
msgInCall2 := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "updatesession",
UpdateSession: &UpdateSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
UpdateSession: &api.UpdateSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
@ -601,14 +601,14 @@ func TestVirtualSessionCleanup(t *testing.T) {
// Ignore "join" events.
assert.NoError(client.DrainMessages(ctx))
internalSessionId := PublicSessionId("session1")
internalSessionId := api.PublicSessionId("session1")
userId := "user1"
msgAdd := &ClientMessage{
msgAdd := &api.ClientMessage{
Type: "internal",
Internal: &InternalClientMessage{
Internal: &api.InternalClientMessage{
Type: "addsession",
AddSession: &AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
AddSession: &api.AddSessionInternalClientMessage{
CommonSessionInternalClientMessage: api.CommonSessionInternalClientMessage{
SessionId: internalSessionId,
RoomId: roomId,
},
@ -625,7 +625,7 @@ func TestVirtualSessionCleanup(t *testing.T) {
sessionId := msg1.Event.Join[0].SessionId
session := hub.GetSessionByPublicId(sessionId)
if assert.NotNil(session) {
assert.Equal(HelloClientTypeVirtual, session.ClientType())
assert.Equal(api.HelloClientTypeVirtual, session.ClientType())
sid := session.(*VirtualSession).SessionId()
assert.Equal(internalSessionId, sid)
}