diff --git a/.codecov.yml b/.codecov.yml
index f59167a..241b309 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -62,6 +62,10 @@ component_management:
name: server
paths:
- server/**
+ - component_id: module_talk
+ name: talk
+ paths:
+ - talk/**
- component_id: module_test
name: test
paths:
diff --git a/Makefile b/Makefile
index d511c32..a203c28 100644
--- a/Makefile
+++ b/Makefile
@@ -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))
+EASYJSON_FILES := $(filter-out $(TEST_GO_FILES),$(wildcard api*.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))
diff --git a/api_backend.go b/api_backend.go
index 28b6462..b295d5e 100644
--- a/api_backend.go
+++ b/api_backend.go
@@ -418,24 +418,6 @@ func NewBackendClientSessionRequest(roomid string, action string, sessionid Publ
return request
}
-type OcsMeta struct {
- Status string `json:"status"`
- StatusCode int `json:"statuscode"`
- Message string `json:"message"`
-}
-
-type OcsBody struct {
- Meta OcsMeta `json:"meta"`
- Data json.RawMessage `json:"data"`
-}
-
-type OcsResponse struct {
- json.Marshaler
- json.Unmarshaler
-
- Ocs *OcsBody `json:"ocs"`
-}
-
// See https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
type TurnCredentials struct {
Username string `json:"username"`
diff --git a/backend_client.go b/backend_client.go
index 826e816..1032d49 100644
--- a/backend_client.go
+++ b/backend_client.go
@@ -35,6 +35,7 @@ import (
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/pool"
+ "github.com/strukturag/nextcloud-spreed-signaling/talk"
)
var (
@@ -54,7 +55,7 @@ type BackendClient struct {
backends *BackendConfiguration
pool *pool.HttpClientPool
- capabilities *Capabilities
+ capabilities *talk.Capabilities
buffers pool.BufferPool
}
@@ -75,7 +76,7 @@ func NewBackendClient(ctx context.Context, config *goconf.ConfigFile, maxConcurr
return nil, err
}
- capabilities, err := NewCapabilities(version, pool)
+ capabilities, err := talk.NewCapabilities(version, pool)
if err != nil {
return nil, err
}
@@ -113,10 +114,6 @@ func (b *BackendClient) IsUrlAllowed(u *url.URL) bool {
return b.backends.IsUrlAllowed(u)
}
-func isOcsRequest(u *url.URL) bool {
- return strings.Contains(u.Path, "/ocs/v2.php") || strings.Contains(u.Path, "/ocs/v1.php")
-}
-
// PerformJSONRequest sends a JSON POST request to the given url and decodes
// the result into "response".
func (b *BackendClient) PerformJSONRequest(ctx context.Context, u *url.URL, request any, response any) error {
@@ -131,7 +128,7 @@ func (b *BackendClient) PerformJSONRequest(ctx context.Context, u *url.URL, requ
}
var requestUrl *url.URL
- if b.capabilities.HasCapabilityFeature(ctx, u, FeatureSignalingV3Api) {
+ if b.capabilities.HasCapabilityFeature(ctx, u, talk.FeatureSignalingV3Api) {
newUrl := *u
newUrl.Path = strings.ReplaceAll(newUrl.Path, "/spreed/api/v1/signaling/", "/spreed/api/v3/signaling/")
newUrl.Path = strings.ReplaceAll(newUrl.Path, "/spreed/api/v2/signaling/", "/spreed/api/v3/signaling/")
@@ -205,7 +202,7 @@ func (b *BackendClient) PerformJSONRequest(ctx context.Context, u *url.URL, requ
defer b.buffers.Put(body)
- if isOcsRequest(u) || req.Header.Get("OCS-APIRequest") != "" {
+ if talk.IsOcsRequest(u) || req.Header.Get("OCS-APIRequest") != "" {
// OCS response are wrapped in an OCS container that needs to be parsed
// to get the actual contents:
// {
@@ -214,7 +211,7 @@ func (b *BackendClient) PerformJSONRequest(ctx context.Context, u *url.URL, requ
// "data": { ... }
// }
// }
- var ocs OcsResponse
+ var ocs talk.OcsResponse
if err := json.Unmarshal(body.Bytes(), &ocs); err != nil {
logger.Printf("Could not decode OCS response %s from %s: %s", body.String(), req.URL, err)
statsBackendClientError.WithLabelValues(backend.Id(), "error_decoding_ocs").Inc()
diff --git a/backend_client_test.go b/backend_client_test.go
index 3b60930..25625cb 100644
--- a/backend_client_test.go
+++ b/backend_client_test.go
@@ -37,12 +37,13 @@ import (
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/pool"
+ "github.com/strukturag/nextcloud-spreed-signaling/talk"
)
func returnOCS(t *testing.T, w http.ResponseWriter, body []byte) {
- response := OcsResponse{
- Ocs: &OcsBody{
- Meta: OcsMeta{
+ response := talk.OcsResponse{
+ Ocs: &talk.OcsBody{
+ Meta: talk.OcsMeta{
Status: "OK",
StatusCode: http.StatusOK,
Message: "OK",
@@ -51,7 +52,7 @@ func returnOCS(t *testing.T, w http.ResponseWriter, body []byte) {
},
}
if strings.Contains(t.Name(), "Throttled") {
- response.Ocs.Meta = OcsMeta{
+ response.Ocs.Meta = talk.OcsMeta{
Status: "failure",
StatusCode: 429,
Message: "Reached maximum delay",
diff --git a/client/main.go b/client/main.go
index bbfdd17..5d87f3f 100644
--- a/client/main.go
+++ b/client/main.go
@@ -49,6 +49,7 @@ import (
signaling "github.com/strukturag/nextcloud-spreed-signaling"
"github.com/strukturag/nextcloud-spreed-signaling/internal"
+ "github.com/strukturag/nextcloud-spreed-signaling/talk"
)
var (
@@ -458,9 +459,9 @@ func registerAuthHandler(router *mux.Router) {
}
rawdata := json.RawMessage(data)
- payload := &signaling.OcsResponse{
- Ocs: &signaling.OcsBody{
- Meta: signaling.OcsMeta{
+ payload := &talk.OcsResponse{
+ Ocs: &talk.OcsBody{
+ Meta: talk.OcsMeta{
Status: "ok",
StatusCode: http.StatusOK,
Message: http.StatusText(http.StatusOK),
diff --git a/hub.go b/hub.go
index 917546a..9a3783c 100644
--- a/hub.go
+++ b/hub.go
@@ -56,6 +56,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/talk"
)
var (
@@ -1403,7 +1404,7 @@ func (h *Hub) processHelloV2(ctx context.Context, client HandlerClient, message
tokenString = message.Hello.Auth.helloV2Params.Token
tokenClaims = &HelloV2TokenClaims{}
case HelloClientTypeFederation:
- if !h.backend.capabilities.HasCapabilityFeature(ctx, url, FeatureFederationV2) {
+ if !h.backend.capabilities.HasCapabilityFeature(ctx, url, talk.FeatureFederationV2) {
return nil, nil, ErrFederationNotSupported
}
diff --git a/hub_test.go b/hub_test.go
index 2fc6f3a..1ea1fd7 100644
--- a/hub_test.go
+++ b/hub_test.go
@@ -58,6 +58,7 @@ import (
"github.com/strukturag/nextcloud-spreed-signaling/internal"
"github.com/strukturag/nextcloud-spreed-signaling/log"
"github.com/strukturag/nextcloud-spreed-signaling/nats"
+ "github.com/strukturag/nextcloud-spreed-signaling/talk"
"github.com/strukturag/nextcloud-spreed-signaling/test"
)
@@ -374,9 +375,9 @@ func validateBackendChecksum(t *testing.T, f func(http.ResponseWriter, *http.Req
assert.NoError(err)
if r.Header.Get("OCS-APIRequest") != "" {
- var ocs OcsResponse
- ocs.Ocs = &OcsBody{
- Meta: OcsMeta{
+ var ocs talk.OcsResponse
+ ocs.Ocs = &talk.OcsBody{
+ Meta: talk.OcsMeta{
Status: "ok",
StatusCode: http.StatusOK,
Message: http.StatusText(http.StatusOK),
@@ -778,8 +779,8 @@ func registerBackendHandlerUrl(t *testing.T, router *mux.Router, url string) {
"config": config,
})
assert.NoError(t, err)
- response := &CapabilitiesResponse{
- Version: CapabilitiesVersion{
+ response := &talk.CapabilitiesResponse{
+ Version: talk.CapabilitiesVersion{
Major: 20,
},
Capabilities: map[string]json.RawMessage{
@@ -790,9 +791,9 @@ func registerBackendHandlerUrl(t *testing.T, router *mux.Router, url string) {
data, err := json.Marshal(response)
assert.NoError(t, err, "Could not marshal %+v", response)
- var ocs OcsResponse
- ocs.Ocs = &OcsBody{
- Meta: OcsMeta{
+ var ocs talk.OcsResponse
+ ocs.Ocs = &talk.OcsBody{
+ Meta: talk.OcsMeta{
Status: "ok",
StatusCode: http.StatusOK,
Message: http.StatusText(http.StatusOK),
diff --git a/room_ping.go b/room_ping.go
index 38b5930..1034c5d 100644
--- a/room_ping.go
+++ b/room_ping.go
@@ -30,6 +30,7 @@ import (
"github.com/strukturag/nextcloud-spreed-signaling/internal"
"github.com/strukturag/nextcloud-spreed-signaling/log"
+ "github.com/strukturag/nextcloud-spreed-signaling/talk"
)
type pingEntries struct {
@@ -70,13 +71,13 @@ type RoomPing struct {
closer *internal.Closer
backend *BackendClient
- capabilities *Capabilities
+ capabilities *talk.Capabilities
// +checklocks:mu
entries map[string]*pingEntries
}
-func NewRoomPing(backend *BackendClient, capabilities *Capabilities) (*RoomPing, error) {
+func NewRoomPing(backend *BackendClient, capabilities *talk.Capabilities) (*RoomPing, error) {
result := &RoomPing{
closer: internal.NewCloser(),
backend: backend,
diff --git a/capabilities.go b/talk/capabilities.go
similarity index 98%
rename from capabilities.go
rename to talk/capabilities.go
index 784c18e..d629d8f 100644
--- a/capabilities.go
+++ b/talk/capabilities.go
@@ -19,7 +19,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
-package signaling
+package talk
import (
"context"
@@ -59,6 +59,10 @@ const (
var (
ErrUnexpectedHttpStatus = errors.New("unexpected_http_status") // +checklocksignore: Global readonly variable.
+
+ ErrUnsupportedContentType = errors.New("unsupported_content_type") // +checklocksignore: Global readonly variable.
+
+ ErrIncompleteResponse = errors.New("incomplete OCS response") // +checklocksignore: Global readonly variable.
)
type capabilitiesEntry struct {
diff --git a/capabilities_test.go b/talk/capabilities_test.go
similarity index 99%
rename from capabilities_test.go
rename to talk/capabilities_test.go
index b3980c9..2f64aaa 100644
--- a/capabilities_test.go
+++ b/talk/capabilities_test.go
@@ -19,7 +19,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
-package signaling
+package talk
import (
"context"
@@ -46,6 +46,10 @@ import (
"github.com/strukturag/nextcloud-spreed-signaling/pool"
)
+const (
+ testTimeout = 10 * time.Second
+)
+
func NewCapabilitiesForTestWithCallback(t *testing.T, callback func(*CapabilitiesResponse, http.ResponseWriter) error) (*url.URL, *Capabilities) {
require := require.New(t)
assert := assert.New(t)
diff --git a/talk/ocs.go b/talk/ocs.go
new file mode 100644
index 0000000..32b933c
--- /dev/null
+++ b/talk/ocs.go
@@ -0,0 +1,50 @@
+/**
+ * Standalone signaling server for the Nextcloud Spreed app.
+ * Copyright (C) 2025 struktur AG
+ *
+ * @author Joachim Bauch
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package talk
+
+import (
+ "encoding/json"
+ "net/url"
+ "strings"
+)
+
+type OcsMeta struct {
+ Status string `json:"status"`
+ StatusCode int `json:"statuscode"`
+ Message string `json:"message"`
+}
+
+type OcsBody struct {
+ Meta OcsMeta `json:"meta"`
+ Data json.RawMessage `json:"data"`
+}
+
+type OcsResponse struct {
+ json.Marshaler
+ json.Unmarshaler
+
+ Ocs *OcsBody `json:"ocs"`
+}
+
+func IsOcsRequest(u *url.URL) bool {
+ return strings.Contains(u.Path, "/ocs/v2.php") || strings.Contains(u.Path, "/ocs/v1.php")
+}