From 35a3fea1f8b0e1b899a22d40d9eb3f746f33ef7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20C=20McCord?= Date: Sat, 7 Mar 2020 13:20:09 -0500 Subject: [PATCH] reorder v5 --- README.md | 22 +- _examples/bridge/main.go | 2 +- _examples/play/main.go | 2 +- _examples/record/main.go | 2 +- _examples/stasisStart/main.go | 2 +- client/application.go | 2 +- client/application_test.go | 2 +- client/asterisk.go | 2 +- client/asterisk_test.go | 2 +- client/bridge.go | 2 +- client/bridge_test.go | 2 +- client/channel.go | 2 +- client/channel_test.go | 2 +- client/client.go | 6 +- client/clientserver_test.go | 2 +- client/config.go | 2 +- client/config_test.go | 2 +- client/device.go | 2 +- client/device_test.go | 2 +- client/endpoint.go | 2 +- client/endpoint_test.go | 2 +- client/liveRecording.go | 2 +- client/liveRecording_test.go | 2 +- client/logging.go | 2 +- client/logging_test.go | 2 +- client/mailbox.go | 2 +- client/mailbox_test.go | 2 +- client/modules.go | 2 +- client/modules_test.go | 2 +- client/playback.go | 2 +- client/playback_test.go | 2 +- client/sound.go | 2 +- client/sound_test.go | 2 +- client/storedRecording.go | 2 +- cmd.go | 2 +- docker_login | 2 - go.mod | 4 +- go.sum | 4 +- server/application.go | 2 +- server/application_test.go | 2 +- server/asterisk.go | 2 +- server/asterisk_test.go | 2 +- server/bridge.go | 6 +- server/bridge_test.go | 2 +- server/channel.go | 2 +- server/channel_test.go | 2 +- server/clientserver_test.go | 2 +- server/config.go | 3 +- server/config_test.go | 2 +- server/device.go | 2 +- server/device_test.go | 2 +- server/endpoint.go | 2 +- server/endpoint_test.go | 2 +- server/handler.go | 2 +- server/liveRecording.go | 2 +- server/liveRecording_test.go | 2 +- server/logging.go | 2 +- server/logging_test.go | 2 +- server/mailbox.go | 2 +- server/mailbox_test.go | 2 +- server/modules.go | 2 +- server/modules_test.go | 2 +- server/playback.go | 3 +- server/playback_test.go | 2 +- server/server.go | 8 +- server/sound.go | 3 +- server/sound_test.go | 2 +- server/storedRecording.go | 2 +- v5/.gitignore | 31 - v5/.goreleaser.yml | 31 - v5/LICENSE | 14 - v5/Makefile | 23 - v5/README.md | 238 ----- v5/_examples/bridge/main.go | 143 --- v5/_examples/play/main.go | 61 -- v5/_examples/record/main.go | 72 -- v5/_examples/stasisStart/main.go | 133 --- v5/client/application.go | 60 -- v5/client/application_test.go | 27 - v5/client/asterisk.go | 62 -- v5/client/asterisk_test.go | 19 - v5/client/bridge.go | 250 ----- v5/client/bridge_test.go | 39 - v5/client/bus/bus.go | 171 ---- v5/client/bus/bus_test.go | 52 - v5/client/channel.go | 432 --------- v5/client/channel_test.go | 51 - v5/client/client.go | 656 ------------- v5/client/clientserver_test.go | 54 -- v5/client/cluster/cluster.go | 149 --- v5/client/cluster/cluster_test.go | 109 --- v5/client/config.go | 42 - v5/client/config_test.go | 19 - v5/client/device.go | 57 -- v5/client/device_test.go | 23 - v5/client/doc.go | 2 - v5/client/endpoint.go | 50 - v5/client/endpoint_test.go | 19 - v5/client/errors.go | 82 -- v5/client/listen.go | 63 -- v5/client/liveRecording.go | 95 -- v5/client/liveRecording_test.go | 41 - v5/client/logger.go | 15 - v5/client/logging.go | 68 -- v5/client/logging_test.go | 23 - v5/client/mailbox.go | 58 -- v5/client/mailbox_test.go | 23 - v5/client/modules.go | 61 -- v5/client/modules_test.go | 27 - v5/client/playback.go | 65 -- v5/client/playback_test.go | 19 - v5/client/request.go | 1 - v5/client/sound.go | 31 - v5/client/sound_test.go | 15 - v5/client/storedRecording.go | 62 -- v5/client/subscription.go | 54 -- v5/cmd.go | 117 --- v5/go.mod | 28 - v5/go.sum | 108 --- v5/internal/integration/application.go | 156 --- v5/internal/integration/asterisk.go | 138 --- v5/internal/integration/bridge.go | 343 ------- v5/internal/integration/channel.go | 1119 ---------------------- v5/internal/integration/clientserver.go | 105 -- v5/internal/integration/config.go | 149 --- v5/internal/integration/device.go | 128 --- v5/internal/integration/doc.go | 2 - v5/internal/integration/endpoint.go | 126 --- v5/internal/integration/liverecording.go | 160 ---- v5/internal/integration/logging.go | 141 --- v5/internal/integration/mailbox.go | 180 ---- v5/internal/integration/mock.go | 82 -- v5/internal/integration/modules.go | 174 ---- v5/internal/integration/playback.go | 105 -- v5/internal/integration/sound.go | 86 -- v5/main.go | 9 - v5/proxy/subjects.go | 15 - v5/proxy/types.go | 373 -------- v5/server/application.go | 89 -- v5/server/application_test.go | 27 - v5/server/asterisk.go | 45 - v5/server/asterisk_test.go | 19 - v5/server/bridge.go | 287 ------ v5/server/bridge_test.go | 39 - v5/server/channel.go | 433 --------- v5/server/channel_test.go | 115 --- v5/server/clientserver_test.go | 55 -- v5/server/closegroup.go | 28 - v5/server/config.go | 29 - v5/server/config_test.go | 19 - v5/server/device.go | 53 - v5/server/device_test.go | 23 - v5/server/dialog/manager.go | 98 -- v5/server/dialog/manager_test.go | 144 --- v5/server/doc.go | 3 - v5/server/endpoint.go | 57 -- v5/server/endpoint_test.go | 19 - v5/server/events.go | 10 - v5/server/handler.go | 13 - v5/server/liveRecording.go | 65 -- v5/server/liveRecording_test.go | 41 - v5/server/logging.go | 65 -- v5/server/logging_test.go | 23 - v5/server/mailbox.go | 53 - v5/server/mailbox_test.go | 23 - v5/server/modules.go | 57 -- v5/server/modules_test.go | 27 - v5/server/options.go | 17 - v5/server/playback.go | 51 - v5/server/playback_test.go | 19 - v5/server/server.go | 594 ------------ v5/server/sound.go | 39 - v5/server/sound_test.go | 15 - v5/server/storedRecording.go | 61 -- v5/session/dialog.go | 17 - v5/session/events.go | 10 - v5/session/message.go | 8 - v5/session/objects.go | 69 -- v5/session/objects_test.go | 121 --- v5/session/transport.go | 13 - v5/session/utils_test.go | 45 - 181 files changed, 83 insertions(+), 10868 deletions(-) delete mode 100755 docker_login delete mode 100644 v5/.gitignore delete mode 100644 v5/.goreleaser.yml delete mode 100644 v5/LICENSE delete mode 100644 v5/Makefile delete mode 100644 v5/README.md delete mode 100644 v5/_examples/bridge/main.go delete mode 100644 v5/_examples/play/main.go delete mode 100644 v5/_examples/record/main.go delete mode 100644 v5/_examples/stasisStart/main.go delete mode 100644 v5/client/application.go delete mode 100644 v5/client/application_test.go delete mode 100644 v5/client/asterisk.go delete mode 100644 v5/client/asterisk_test.go delete mode 100644 v5/client/bridge.go delete mode 100644 v5/client/bridge_test.go delete mode 100644 v5/client/bus/bus.go delete mode 100644 v5/client/bus/bus_test.go delete mode 100644 v5/client/channel.go delete mode 100644 v5/client/channel_test.go delete mode 100644 v5/client/client.go delete mode 100644 v5/client/clientserver_test.go delete mode 100644 v5/client/cluster/cluster.go delete mode 100644 v5/client/cluster/cluster_test.go delete mode 100644 v5/client/config.go delete mode 100644 v5/client/config_test.go delete mode 100644 v5/client/device.go delete mode 100644 v5/client/device_test.go delete mode 100644 v5/client/doc.go delete mode 100644 v5/client/endpoint.go delete mode 100644 v5/client/endpoint_test.go delete mode 100644 v5/client/errors.go delete mode 100644 v5/client/listen.go delete mode 100644 v5/client/liveRecording.go delete mode 100644 v5/client/liveRecording_test.go delete mode 100644 v5/client/logger.go delete mode 100644 v5/client/logging.go delete mode 100644 v5/client/logging_test.go delete mode 100644 v5/client/mailbox.go delete mode 100644 v5/client/mailbox_test.go delete mode 100644 v5/client/modules.go delete mode 100644 v5/client/modules_test.go delete mode 100644 v5/client/playback.go delete mode 100644 v5/client/playback_test.go delete mode 100644 v5/client/request.go delete mode 100644 v5/client/sound.go delete mode 100644 v5/client/sound_test.go delete mode 100644 v5/client/storedRecording.go delete mode 100644 v5/client/subscription.go delete mode 100644 v5/cmd.go delete mode 100644 v5/go.mod delete mode 100644 v5/go.sum delete mode 100644 v5/internal/integration/application.go delete mode 100644 v5/internal/integration/asterisk.go delete mode 100644 v5/internal/integration/bridge.go delete mode 100644 v5/internal/integration/channel.go delete mode 100644 v5/internal/integration/clientserver.go delete mode 100644 v5/internal/integration/config.go delete mode 100644 v5/internal/integration/device.go delete mode 100644 v5/internal/integration/doc.go delete mode 100644 v5/internal/integration/endpoint.go delete mode 100644 v5/internal/integration/liverecording.go delete mode 100644 v5/internal/integration/logging.go delete mode 100644 v5/internal/integration/mailbox.go delete mode 100644 v5/internal/integration/mock.go delete mode 100644 v5/internal/integration/modules.go delete mode 100644 v5/internal/integration/playback.go delete mode 100644 v5/internal/integration/sound.go delete mode 100644 v5/main.go delete mode 100644 v5/proxy/subjects.go delete mode 100644 v5/proxy/types.go delete mode 100644 v5/server/application.go delete mode 100644 v5/server/application_test.go delete mode 100644 v5/server/asterisk.go delete mode 100644 v5/server/asterisk_test.go delete mode 100644 v5/server/bridge.go delete mode 100644 v5/server/bridge_test.go delete mode 100644 v5/server/channel.go delete mode 100644 v5/server/channel_test.go delete mode 100644 v5/server/clientserver_test.go delete mode 100644 v5/server/closegroup.go delete mode 100644 v5/server/config.go delete mode 100644 v5/server/config_test.go delete mode 100644 v5/server/device.go delete mode 100644 v5/server/device_test.go delete mode 100644 v5/server/dialog/manager.go delete mode 100644 v5/server/dialog/manager_test.go delete mode 100644 v5/server/doc.go delete mode 100644 v5/server/endpoint.go delete mode 100644 v5/server/endpoint_test.go delete mode 100644 v5/server/events.go delete mode 100644 v5/server/handler.go delete mode 100644 v5/server/liveRecording.go delete mode 100644 v5/server/liveRecording_test.go delete mode 100644 v5/server/logging.go delete mode 100644 v5/server/logging_test.go delete mode 100644 v5/server/mailbox.go delete mode 100644 v5/server/mailbox_test.go delete mode 100644 v5/server/modules.go delete mode 100644 v5/server/modules_test.go delete mode 100644 v5/server/options.go delete mode 100644 v5/server/playback.go delete mode 100644 v5/server/playback_test.go delete mode 100644 v5/server/server.go delete mode 100644 v5/server/sound.go delete mode 100644 v5/server/sound_test.go delete mode 100644 v5/server/storedRecording.go delete mode 100644 v5/session/dialog.go delete mode 100644 v5/session/events.go delete mode 100644 v5/session/message.go delete mode 100644 v5/session/objects.go delete mode 100644 v5/session/objects_test.go delete mode 100644 v5/session/transport.go delete mode 100644 v5/session/utils_test.go diff --git a/README.md b/README.md index c45dc45..7713b1c 100644 --- a/README.md +++ b/README.md @@ -55,20 +55,10 @@ You may need to explicitly install dependencies for this to work ## Client library -`ari-proxy` uses semantic versioning and [dep](https://github.com/golang/dep). -To use it in your own Go package, simply reference the -`github.com/CyCoreSystems/ari-proxy/client` package, and your dependency management -tool should be able to manage it. - -For manual dependency management: - -``` - go get github.com/CyCoreSystems/ari-proxy - cd $GOPATH/github.com/CyCoreSystems/ari-proxy - dep ensure -``` - -`master` should be the latest stable, so a simple `go get` is required: +`ari-proxy` uses semantic versioning and standard Go modules. To use it in your +own Go package, simply reference the +`github.com/CyCoreSystems/ari-proxy/client/v5` package, and your dependency +management tool should be able to manage it. ### Usage @@ -76,8 +66,8 @@ Connecting the client to NATS is simple: ```go import ( - "github.com/CyCoreSystems/ari" - "github.com/CyCoreSystems/ari-proxy/client" + "github.com/CyCoreSystems/ari/v5" + "github.com/CyCoreSystems/ari-proxy/v5/client" ) func connect(ctx context.Context, appName string) (ari.Client,error) { diff --git a/_examples/bridge/main.go b/_examples/bridge/main.go index 423f0b7..5c37bc1 100644 --- a/_examples/bridge/main.go +++ b/_examples/bridge/main.go @@ -6,7 +6,7 @@ import ( "github.com/inconshreveable/log15" - "github.com/CyCoreSystems/ari-proxy/client" + "github.com/CyCoreSystems/ari-proxy/v5/client" rid "github.com/CyCoreSystems/ari-rid" "github.com/CyCoreSystems/ari/v5" "github.com/CyCoreSystems/ari/v5/ext/play" diff --git a/_examples/play/main.go b/_examples/play/main.go index 01b5870..916d9b7 100644 --- a/_examples/play/main.go +++ b/_examples/play/main.go @@ -5,7 +5,7 @@ import ( "github.com/inconshreveable/log15" - "github.com/CyCoreSystems/ari-proxy/client" + "github.com/CyCoreSystems/ari-proxy/v5/client" "github.com/CyCoreSystems/ari/v5" "github.com/CyCoreSystems/ari/v5/ext/play" ) diff --git a/_examples/record/main.go b/_examples/record/main.go index e46f546..b427860 100644 --- a/_examples/record/main.go +++ b/_examples/record/main.go @@ -5,7 +5,7 @@ import ( "github.com/inconshreveable/log15" - "github.com/CyCoreSystems/ari-proxy/client" + "github.com/CyCoreSystems/ari-proxy/v5/client" "github.com/CyCoreSystems/ari/v5" "github.com/CyCoreSystems/ari/v5/ext/record" ) diff --git a/_examples/stasisStart/main.go b/_examples/stasisStart/main.go index f7643b1..b9f2db7 100644 --- a/_examples/stasisStart/main.go +++ b/_examples/stasisStart/main.go @@ -5,7 +5,7 @@ import ( "net/http" "sync" - "github.com/CyCoreSystems/ari-proxy/client" + "github.com/CyCoreSystems/ari-proxy/v5/client" "github.com/CyCoreSystems/ari/v5" "github.com/CyCoreSystems/ari/v5/client/native" diff --git a/client/application.go b/client/application.go index 60a8424..896acbe 100644 --- a/client/application.go +++ b/client/application.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/application_test.go b/client/application_test.go index 75fb263..ff24299 100644 --- a/client/application_test.go +++ b/client/application_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestApplicationList(t *testing.T) { diff --git a/client/asterisk.go b/client/asterisk.go index 357adb0..369514e 100644 --- a/client/asterisk.go +++ b/client/asterisk.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/asterisk_test.go b/client/asterisk_test.go index ffb27ea..593e3e7 100644 --- a/client/asterisk_test.go +++ b/client/asterisk_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestAsteriskInfo(t *testing.T) { diff --git a/client/bridge.go b/client/bridge.go index b8f7c80..40dcb12 100644 --- a/client/bridge.go +++ b/client/bridge.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" rid "github.com/CyCoreSystems/ari-rid" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/bridge_test.go b/client/bridge_test.go index f8be568..8f85579 100644 --- a/client/bridge_test.go +++ b/client/bridge_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestBridgeCreate(t *testing.T) { diff --git a/client/channel.go b/client/channel.go index 5bb1f7c..85b0aeb 100644 --- a/client/channel.go +++ b/client/channel.go @@ -3,7 +3,7 @@ package client import ( "time" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" rid "github.com/CyCoreSystems/ari-rid" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/channel_test.go b/client/channel_test.go index ad570f8..0772cf0 100644 --- a/client/channel_test.go +++ b/client/channel_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestChannelData(t *testing.T) { diff --git a/client/client.go b/client/client.go index 6a6376b..5c4e83f 100644 --- a/client/client.go +++ b/client/client.go @@ -5,9 +5,9 @@ import ( "os" "time" - "github.com/CyCoreSystems/ari-proxy/client/bus" - "github.com/CyCoreSystems/ari-proxy/client/cluster" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/client/bus" + "github.com/CyCoreSystems/ari-proxy/v5/client/cluster" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" rid "github.com/CyCoreSystems/ari-rid" "github.com/CyCoreSystems/ari/v5" diff --git a/client/clientserver_test.go b/client/clientserver_test.go index 2184a36..716c290 100644 --- a/client/clientserver_test.go +++ b/client/clientserver_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/CyCoreSystems/ari-proxy/server" + "github.com/CyCoreSystems/ari-proxy/v5/server" rid "github.com/CyCoreSystems/ari-rid" "github.com/CyCoreSystems/ari/v5" "github.com/nats-io/nats.go" diff --git a/client/config.go b/client/config.go index 15e89e3..89dec4d 100644 --- a/client/config.go +++ b/client/config.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/config_test.go b/client/config_test.go index e470641..5932aa0 100644 --- a/client/config_test.go +++ b/client/config_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestConfigData(t *testing.T) { diff --git a/client/device.go b/client/device.go index 9085a5d..d190991 100644 --- a/client/device.go +++ b/client/device.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/device_test.go b/client/device_test.go index a159300..7724ac3 100644 --- a/client/device_test.go +++ b/client/device_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestDeviceData(t *testing.T) { diff --git a/client/endpoint.go b/client/endpoint.go index 77126e0..7e3845e 100644 --- a/client/endpoint.go +++ b/client/endpoint.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/endpoint_test.go b/client/endpoint_test.go index 7f5491c..1adedec 100644 --- a/client/endpoint_test.go +++ b/client/endpoint_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestEndpointList(t *testing.T) { diff --git a/client/liveRecording.go b/client/liveRecording.go index 0bff41b..496480d 100644 --- a/client/liveRecording.go +++ b/client/liveRecording.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/liveRecording_test.go b/client/liveRecording_test.go index 91d9ae6..70de5e2 100644 --- a/client/liveRecording_test.go +++ b/client/liveRecording_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestLiveRecordingData(t *testing.T) { diff --git a/client/logging.go b/client/logging.go index efbbaf7..6844cbb 100644 --- a/client/logging.go +++ b/client/logging.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/logging_test.go b/client/logging_test.go index caca92b..cebbfda 100644 --- a/client/logging_test.go +++ b/client/logging_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestLoggingList(t *testing.T) { diff --git a/client/mailbox.go b/client/mailbox.go index 42d5ea7..633e724 100644 --- a/client/mailbox.go +++ b/client/mailbox.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/mailbox_test.go b/client/mailbox_test.go index d7ef5aa..2aeddc3 100644 --- a/client/mailbox_test.go +++ b/client/mailbox_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestMailboxList(t *testing.T) { diff --git a/client/modules.go b/client/modules.go index 7365b21..9e9eee5 100644 --- a/client/modules.go +++ b/client/modules.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/modules_test.go b/client/modules_test.go index a513799..fbeb25b 100644 --- a/client/modules_test.go +++ b/client/modules_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestModulesData(t *testing.T) { diff --git a/client/playback.go b/client/playback.go index a3a6258..b13345b 100644 --- a/client/playback.go +++ b/client/playback.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/playback_test.go b/client/playback_test.go index ce0771a..289c7f4 100644 --- a/client/playback_test.go +++ b/client/playback_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestPlaybackData(t *testing.T) { diff --git a/client/sound.go b/client/sound.go index 4f2819f..5ed0e26 100644 --- a/client/sound.go +++ b/client/sound.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/client/sound_test.go b/client/sound_test.go index 9ffd9f0..68b6a9a 100644 --- a/client/sound_test.go +++ b/client/sound_test.go @@ -3,7 +3,7 @@ package client import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestSoundData(t *testing.T) { diff --git a/client/storedRecording.go b/client/storedRecording.go index 038b443..1c6f9cc 100644 --- a/client/storedRecording.go +++ b/client/storedRecording.go @@ -1,7 +1,7 @@ package client import ( - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" "github.com/CyCoreSystems/ari/v5" ) diff --git a/cmd.go b/cmd.go index 64341a2..2dbb4ae 100644 --- a/cmd.go +++ b/cmd.go @@ -6,7 +6,7 @@ import ( "os" "strings" - "github.com/CyCoreSystems/ari-proxy/server" + "github.com/CyCoreSystems/ari-proxy/v5/server" "github.com/CyCoreSystems/ari/v5/client/native" "github.com/inconshreveable/log15" diff --git a/docker_login b/docker_login deleted file mode 100755 index e97b6cb..0000000 --- a/docker_login +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin diff --git a/go.mod b/go.mod index 8eff866..bed847a 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ -module github.com/CyCoreSystems/ari-proxy +module github.com/CyCoreSystems/ari-proxy/v5 go 1.13 require ( github.com/BurntSushi/toml v0.3.1 // indirect github.com/CyCoreSystems/ari-rid v0.1.0 - github.com/CyCoreSystems/ari/v5 v5.0.1 + github.com/CyCoreSystems/ari/v5 v5.0.3 github.com/fsnotify/fsnotify v0.0.0-20170329110642-4da3e2cfbabc // indirect github.com/gogo/protobuf v1.3.1 // indirect github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e // indirect diff --git a/go.sum b/go.sum index b8c1165..12105bb 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/CyCoreSystems/ari-rid v0.1.0 h1:QSn7/1Jc0b3Se/LIaMa9taGxC9n/zyBlCEw9Conrdrk= github.com/CyCoreSystems/ari-rid v0.1.0/go.mod h1:vFD6moqOBGXaUM28Yck9X16+5cj+NbFmiyCvpUYuKr4= -github.com/CyCoreSystems/ari/v5 v5.0.1 h1:TfJOwETj6MumVBJPnZJoYqLtfUAo7W8FKnnssMlQ8PM= -github.com/CyCoreSystems/ari/v5 v5.0.1/go.mod h1:5fdxhNmHG+sUJkeIgPfMafi7d7Ec1B8QpPSCFvDDVc0= +github.com/CyCoreSystems/ari/v5 v5.0.3 h1:WF0J0lA4uSgV5Sk9t3V0vtRh6NPonYeRoHTJVXMMMzE= +github.com/CyCoreSystems/ari/v5 v5.0.3/go.mod h1:5fdxhNmHG+sUJkeIgPfMafi7d7Ec1B8QpPSCFvDDVc0= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/server/application.go b/server/application.go index 61a2564..f8a281f 100644 --- a/server/application.go +++ b/server/application.go @@ -5,7 +5,7 @@ import ( "errors" "strings" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) applicationData(ctx context.Context, reply string, req *proxy.Request) { diff --git a/server/application_test.go b/server/application_test.go index f90dcb0..20f7022 100644 --- a/server/application_test.go +++ b/server/application_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestApplicationList(t *testing.T) { diff --git a/server/asterisk.go b/server/asterisk.go index c661d90..1bdd80d 100644 --- a/server/asterisk.go +++ b/server/asterisk.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) asteriskInfo(ctx context.Context, reply string, req *proxy.Request) { diff --git a/server/asterisk_test.go b/server/asterisk_test.go index 02ba3fb..6f56e8e 100644 --- a/server/asterisk_test.go +++ b/server/asterisk_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestAsteriskInfo(t *testing.T) { diff --git a/server/bridge.go b/server/bridge.go index 952a882..3b409a4 100644 --- a/server/bridge.go +++ b/server/bridge.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" rid "github.com/CyCoreSystems/ari-rid" "github.com/CyCoreSystems/ari/v5" ) @@ -259,10 +259,10 @@ func (s *Server) bridgeVideoSource(ctx context.Context, reply string, req *proxy // bind dialog if req.Key.Dialog != "" { s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "channel", req.VideoSource.Channel) + s.Dialog.Bind(req.Key.Dialog, "channel", req.BridgeVideoSource.Channel) } - err := s.ari.Bridge().VideoSource(req.Key, req.VideoSource.Channel) + err := s.ari.Bridge().VideoSource(req.Key, req.BridgeVideoSource.Channel) if err != nil { s.sendError(reply, err) return diff --git a/server/bridge_test.go b/server/bridge_test.go index bf42c0e..220f5fe 100644 --- a/server/bridge_test.go +++ b/server/bridge_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestBridgeCreate(t *testing.T) { diff --git a/server/channel.go b/server/channel.go index 15c15a1..a1c82bf 100644 --- a/server/channel.go +++ b/server/channel.go @@ -4,7 +4,7 @@ import ( "context" "errors" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" rid "github.com/CyCoreSystems/ari-rid" "github.com/CyCoreSystems/ari/v5" ) diff --git a/server/channel_test.go b/server/channel_test.go index 46ca28b..8df16e4 100644 --- a/server/channel_test.go +++ b/server/channel_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestChannelData(t *testing.T) { diff --git a/server/clientserver_test.go b/server/clientserver_test.go index b5139d8..ac9e7d8 100644 --- a/server/clientserver_test.go +++ b/server/clientserver_test.go @@ -7,7 +7,7 @@ import ( "time" - "github.com/CyCoreSystems/ari-proxy/client" + "github.com/CyCoreSystems/ari-proxy/v5/client" "github.com/CyCoreSystems/ari/v5" "github.com/CyCoreSystems/ari/v5/rid" "github.com/nats-io/nats.go" diff --git a/server/config.go b/server/config.go index 0c1ad71..03acfd6 100644 --- a/server/config.go +++ b/server/config.go @@ -3,11 +3,10 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) asteriskConfigData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Asterisk().Config().Data(req.Key) if err != nil { s.sendError(reply, err) diff --git a/server/config_test.go b/server/config_test.go index 448663b..c27856d 100644 --- a/server/config_test.go +++ b/server/config_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestConfigData(t *testing.T) { diff --git a/server/device.go b/server/device.go index 1cfc4ec..b9934d5 100644 --- a/server/device.go +++ b/server/device.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) deviceStateData(ctx context.Context, reply string, req *proxy.Request) { diff --git a/server/device_test.go b/server/device_test.go index a83ee46..315faa1 100644 --- a/server/device_test.go +++ b/server/device_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestDeviceData(t *testing.T) { diff --git a/server/endpoint.go b/server/endpoint.go index b18c1ba..4fa3526 100644 --- a/server/endpoint.go +++ b/server/endpoint.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) endpointData(ctx context.Context, reply string, req *proxy.Request) { diff --git a/server/endpoint_test.go b/server/endpoint_test.go index aca1c3a..68018f7 100644 --- a/server/endpoint_test.go +++ b/server/endpoint_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestEndpointList(t *testing.T) { diff --git a/server/handler.go b/server/handler.go index c96888b..6d2c8c8 100644 --- a/server/handler.go +++ b/server/handler.go @@ -1,6 +1,6 @@ package server -import "github.com/CyCoreSystems/ari-proxy/session" +import "github.com/CyCoreSystems/ari-proxy/v5/session" // Reply is a function which, when called, replies to the request via the // response object or error. diff --git a/server/liveRecording.go b/server/liveRecording.go index ce00a44..1007bdf 100644 --- a/server/liveRecording.go +++ b/server/liveRecording.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) recordingLiveData(ctx context.Context, reply string, req *proxy.Request) { diff --git a/server/liveRecording_test.go b/server/liveRecording_test.go index 10534de..84c9ecc 100644 --- a/server/liveRecording_test.go +++ b/server/liveRecording_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestLiveRecordingData(t *testing.T) { diff --git a/server/logging.go b/server/logging.go index bc49fc7..8225d98 100644 --- a/server/logging.go +++ b/server/logging.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) asteriskLoggingList(ctx context.Context, reply string, req *proxy.Request) { diff --git a/server/logging_test.go b/server/logging_test.go index d9743aa..717dcc6 100644 --- a/server/logging_test.go +++ b/server/logging_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestLoggingList(t *testing.T) { diff --git a/server/mailbox.go b/server/mailbox.go index 6440c56..7280ad8 100644 --- a/server/mailbox.go +++ b/server/mailbox.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) mailboxData(ctx context.Context, reply string, req *proxy.Request) { diff --git a/server/mailbox_test.go b/server/mailbox_test.go index b070013..fa1092c 100644 --- a/server/mailbox_test.go +++ b/server/mailbox_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestMailboxList(t *testing.T) { diff --git a/server/modules.go b/server/modules.go index cc42018..344b9df 100644 --- a/server/modules.go +++ b/server/modules.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) asteriskModuleLoad(ctx context.Context, reply string, req *proxy.Request) { diff --git a/server/modules_test.go b/server/modules_test.go index b8b4467..98cd7d4 100644 --- a/server/modules_test.go +++ b/server/modules_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestModulesData(t *testing.T) { diff --git a/server/playback.go b/server/playback.go index 0dd8b99..e23d0ba 100644 --- a/server/playback.go +++ b/server/playback.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) playbackControl(ctx context.Context, reply string, req *proxy.Request) { @@ -42,7 +42,6 @@ func (s *Server) playbackStop(ctx context.Context, reply string, req *proxy.Requ } func (s *Server) playbackSubscribe(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog if req.Key.Dialog != "" { s.Dialog.Bind(req.Key.Dialog, "playback", req.Key.ID) diff --git a/server/playback_test.go b/server/playback_test.go index d2ebff4..0435a1e 100644 --- a/server/playback_test.go +++ b/server/playback_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestPlaybackData(t *testing.T) { diff --git a/server/server.go b/server/server.go index 78cc513..22cd5e0 100644 --- a/server/server.go +++ b/server/server.go @@ -5,8 +5,8 @@ import ( "fmt" "time" - "github.com/CyCoreSystems/ari-proxy/proxy" - "github.com/CyCoreSystems/ari-proxy/server/dialog" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/server/dialog" "github.com/CyCoreSystems/ari/v5" "github.com/CyCoreSystems/ari/v5/client/native" @@ -392,6 +392,10 @@ func (s *Server) dispatchRequest(ctx context.Context, reply string, req *proxy.R f = s.bridgeSubscribe case "BridgeUnsubscribe": f = s.bridgeUnsubscribe + case "BridgeVideoSource": + f = s.bridgeVideoSource + case "BridgeVideoSourceDelete": + f = s.bridgeVideoSourceDelete case "ChannelAnswer": f = s.channelAnswer case "ChannelBusy": diff --git a/server/sound.go b/server/sound.go index 9672e4c..1e99342 100644 --- a/server/sound.go +++ b/server/sound.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) soundData(ctx context.Context, reply string, req *proxy.Request) { @@ -21,7 +21,6 @@ func (s *Server) soundData(ctx context.Context, reply string, req *proxy.Request } func (s *Server) soundList(ctx context.Context, reply string, req *proxy.Request) { - filters := req.SoundList.Filters if len(filters) == 0 { diff --git a/server/sound_test.go b/server/sound_test.go index b9a8b14..e700e16 100644 --- a/server/sound_test.go +++ b/server/sound_test.go @@ -3,7 +3,7 @@ package server import ( "testing" - "github.com/CyCoreSystems/ari-proxy/internal/integration" + "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" ) func TestSoundData(t *testing.T) { diff --git a/server/storedRecording.go b/server/storedRecording.go index 50d946e..497d020 100644 --- a/server/storedRecording.go +++ b/server/storedRecording.go @@ -3,7 +3,7 @@ package server import ( "context" - "github.com/CyCoreSystems/ari-proxy/proxy" + "github.com/CyCoreSystems/ari-proxy/v5/proxy" ) func (s *Server) recordingStoredCopy(ctx context.Context, reply string, req *proxy.Request) { diff --git a/v5/.gitignore b/v5/.gitignore deleted file mode 100644 index aada0b8..0000000 --- a/v5/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test -bin - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - -*.swp - -/vendor/* -/dist/ -/ari-proxy diff --git a/v5/.goreleaser.yml b/v5/.goreleaser.yml deleted file mode 100644 index 0339d61..0000000 --- a/v5/.goreleaser.yml +++ /dev/null @@ -1,31 +0,0 @@ -project_name: Asterisk ARI Proxy -builds: - - binary: ari-proxy - env: - - CGO_ENABLED=0 - goos: - - windows - - darwin - - linux - goarch: - - amd64 - -archive: - format: binary -checksum: - name_template: 'checksums.txt' -snapshot: - name_template: "{{ .Tag }}-next" -changelog: - sort: asc - filters: - exclude: - - '^docs:' - - '^test:' - -dockers: - - image_templates: - - 'cycoresystems/ari-proxy:{{ .Tag }}' - - 'cycoresystems/ari-proxy:v{{ .Major }}' - - 'cycoresystems/ari-proxy:v{{ .Major }}.{{ .Minor }}' - - 'cycoresystems/ari-proxy:latest' diff --git a/v5/LICENSE b/v5/LICENSE deleted file mode 100644 index 76c9fda..0000000 --- a/v5/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -Copyright 2016 CyCore Systems, Inc. - - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/v5/Makefile b/v5/Makefile deleted file mode 100644 index e2c0787..0000000 --- a/v5/Makefile +++ /dev/null @@ -1,23 +0,0 @@ - -all: dep check build test - -ci: check build test - -build: - go build ./... - go build - -check: - go mod verify - golangci-lint run - -dep: - go mod tidy - -docker: all - docker build -t cycoresystems/ari-proxy ./ - docker push cycoresystems/ari-proxy - -test: - go test ./... - diff --git a/v5/README.md b/v5/README.md deleted file mode 100644 index 7713b1c..0000000 --- a/v5/README.md +++ /dev/null @@ -1,238 +0,0 @@ -# ari-proxy -[![Build Status](https://travis-ci.org/CyCoreSystems/ari-proxy.png)](https://travis-ci.org/CyCoreSystems/ari-proxy) [![](https://godoc.org/github.com/CyCoreSystems/ari-proxy?status.svg)](https://godoc.org/github.com/CyCoreSystems/ari-proxy) - -Proxy for the Asterisk REST interface (ARI). - -The ARI proxy facilitates scaling of both applications and Asterisk, -independently and with minimal coordination. Each Asterisk instance and ARI -application pair runs an `ari-proxy` server instance, which talks to a common -NATS cluster. Each client application talks to the same NATS cluster. The -clients automatically and continuously discover new Asterisk instances, so the -only coordination needed is the common location of the NATS cluster. - -The ARI proxy allows for: - - Any number of applications running the ARI client - - Any number of `ari-proxy` services running on any number of Asterisk - instances - - Simple call control throughout the cluster, regardless of which Asterisk - instance is controlling the call - - Simple call distribution regardless of the number of potential application - services. (New calls are automatically sent to a single recipient - application.) - - Simple call event reception by any number of application clients. (No - single-app lockout) - - -## Proxy server - - -Docker images are kept up to date with releases and are tagged accordingly. The -`ari-proxy` does not expose any services, so no ports need to be opened for it. -However, it does need to know how to connect to both Asterisk and NATS. - -``` - docker run \ - -e ARI_APPLICATION="my_test_app" \ - -e ARI_USERNAME="demo-user" \ - -e ARI_PASSWORD="supersecret" \ - -e ARI_HTTP_URL="http://asterisk:8088/ari" \ - -e ARI_WEBSOCKET_URL="ws://asterisk:8088/ari/events" \ - -e NATS_URL="nats://nats:4222" \ - cycoresystems/ari-proxy -``` - -Binary releases are available on the [releases page](https://github.com/CyCoreSystems/ari-proxy/releases). - -You can also install the server manually. It is not (yet) go-gettable, but we -use [dep](https://github.com/golang/dep) for dependency management. - -``` - dep ensure - go install -``` - -You may need to explicitly install dependencies for this to work - -## Client library - -`ari-proxy` uses semantic versioning and standard Go modules. To use it in your -own Go package, simply reference the -`github.com/CyCoreSystems/ari-proxy/client/v5` package, and your dependency -management tool should be able to manage it. - -### Usage - -Connecting the client to NATS is simple: - -```go -import ( - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari-proxy/v5/client" -) - -func connect(ctx context.Context, appName string) (ari.Client,error) { - c, err := client.New(ctx, - client.WithApplication(appName), - client.WithURI("nats://natshost:4222"), - ) -} -``` - -Configuration of the client can also be done with environment variables. -`ARI_APPLICATION` can be used to set the ARI application name, and `NATS_URI` -can be used to set the NATS URI. Doing so allows you to get a client connection -simply with `client.New(ctx)`. - -Once an `ari.Client` is obtained, the client functions exactly as the native -[ari](https://github.com/CyCoreSystems/ari) client. - -More documentation: - - * [ARI library docs](https://godoc.org/github.com/CyCoreSystems/ari) - - * [ARI client examples](https://github.com/CyCoreSystems/ari/tree/master/_examples) - - -### Context - -Note the use of the `context.Context` parameter. This can be useful to properly -shutdown the client by a controlling context. This shutdown will also close any -open subscriptions on the client. - -Layers of clients can be used efficiently with different contexts using the -`New(context.Context)` function of each client instance. Subtended clients will -be closed with their parents, use a common internal NATS connection, and can be -severally closed by their individual contexts. This makes managing many active -channels easy and efficient. - -### Lifecycle - -There are two levels of client in use. The first is a connection, which is a -long-lived network connection to the NATS cluster. In general, the end user -should not close this connection. However, it is available, if necessary, as -`DefaultConn` and offers a `Close()` function for itself. - -The second level is the ARI client. Any number of ARI clients may make use of -the same underlying connection, but each client maintains its own separate bus -and subscription implementation. Thus, when a user closes its client, the -connection is maintained, but all subscriptions are released. Users should -always `Close()` their clients when done with them to avoid accumulating stale -subscriptions. - -### Clustering - -The ARI proxy works in a cluster setting by utilizing two coordinates: - - - The Asterisk ID - - The ARI Application - -Between the two of these, we can uniquely address each ARI resource, regardless -of where the client is located. These pieces of information are handled -transparently and internally by the ARI proxy and the ARI proxy client to route -commands and events where they should be sent. - -### NATS protocol details - -The protocol details described below are only necessary to know if you do not use the -provided client and/or server. By using both components in this repository, the -protocol details below are transparently handled for you. - -#### Subject structure - -The NATS subject prefix defaults to `ari.`, and all messages used by this proxy -will be prefixed by that term. - -Next is added one of four resource classifications: - - - `event` - Messages from Asterisk to clients - - `get` - Read-only requests from clients to Asterisk - - `command` - Non-creation operational requests from clients to Asterisk - - `create` - Creation-related requests from clients to Asterisk - -After the resource, the ARI application is appended. - -Finally, the Asterisk ID will be added to the end. Thus, the subject for an event for the -ARI application "test" from the Asterisk box with ID "00:01:02:03:04:05" would -look like: - -`ari.event.test.00:01:02:03:04:05` - -For a channel creation command to the same app and node: - -`ari.create.test.00:01:02:03:04:05` - -The Asterisk ID component of the subject is optional for commands. If a command -does not include an Asterisk ID, any ARI proxy running the provided ARI -application may respond to the request. (Thus, implicitly, each ARI proxy -service listens to both its Asterisk ID-specific command subject and its generic -ARI application command subject. In fact, each ARI proxy listens to each of the -three levels. A request to `ari.command` will result in all ARI proxies -responding.) - -This setup allows for a variable generalization in the listeners by using NATS -wildcard subscriptions. For instance, if you want to receive all events for the -"test" application regardless from which Asterisk machine they come, you would -subscribe to: - -`ari.event.test.>` - -#### Dialogs - -Events may be further classified by the arbitrary "dialog" ID. If any command -specifies a Dialog ID in its metadata, the ARI proxy will further classify -events related to that dialog. Relationships are defined by the entity type on -which the Dialog-infused command operates. - -Dialog-related events are published on their own NATS subject tree, -`dialogevent`. Thus dialogs abstract ARI application and Asterisk ID. An event -for dialog "testme123" would be published to: - -`ari.dialogevent.testme123` - -Keep in mind that regardless of dialog associations, all events are _also_ -published to their appropriate canonical NATS subjects. Dialogs are intended as -a mechanism to: - - - reduce client message traffic load - - transcend ARI Applications and/or Asterisk nodes while maintaining logical - separation of events - -#### Message delivery - -The means of a delivery for a generically-routed message depends on the type of -message it is. - - - Events are always delivered to all listeners. - - Read-only commands are delivered to all listeners. - - Non-creation operation commands are delivered to all listeners. - - Creation-related commands are delivered to only one listener. - -Thus, for efficiency, it is always recommended to use as precise a subject line -as possible. - -#### Node discovery - -Each ARI proxy sends out a periodic ping announcing itself in the cluster. -Clients may aggregate these pings to construct an expected map of machines in -the cluster. Knowing this map allows the client to optimize its all-listener -commands by cancelling the wait period if it receives responses from all nodes -before the timeout has elapsed. - -ARI proxies listen to `ari.ping` and send announcements on `ari.announce`. The -structure of the announcement is thus: - -```json -{ - "asterisk": "00:10:20:30:40:50", - "application": "test" -} -``` - -#### Payload structure - -For most requests, payloads exactly match their ARI library values. However, -treatment of handlers is slightly different. - -Instead of a handler, an `Entity` or array of `Entity`s is returned. This -response type contains the Metadata for the entity (ARI application, Asterisk -ID, and optionally Dialog) as well as the unique ID of the entity. diff --git a/v5/_examples/bridge/main.go b/v5/_examples/bridge/main.go deleted file mode 100644 index 5c37bc1..0000000 --- a/v5/_examples/bridge/main.go +++ /dev/null @@ -1,143 +0,0 @@ -package main - -import ( - "context" - "sync" - - "github.com/inconshreveable/log15" - - "github.com/CyCoreSystems/ari-proxy/v5/client" - rid "github.com/CyCoreSystems/ari-rid" - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/ext/play" - "github.com/pkg/errors" -) - -var ariApp = "test" - -var log = log15.New() - -var bridge *ari.BridgeHandle - -func main() { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // connect - log.Info("Connecting to ARI") - cl, err := client.New(ctx, client.WithApplication(ariApp), client.WithLogger(log)) - if err != nil { - log.Error("Failed to build ARI client", "error", err) - return - } - - // setup app - - log.Info("Starting listener app") - - err = client.Listen(ctx, cl, appStart(ctx, cl)) - if err != nil { - log.Error("failed to listen for new calls") - } - <-ctx.Done() - - return -} - -func appStart(ctx context.Context, cl ari.Client) func(*ari.ChannelHandle, *ari.StasisStart) { - return func(h *ari.ChannelHandle, startEvent *ari.StasisStart) { - log.Info("running app", "channel", h.Key().ID) - - if err := h.Answer(); err != nil { - log.Error("failed to answer call", "error", err) - // return - } - - if err := ensureBridge(ctx, cl, h.Key()); err != nil { - log.Error("failed to manage bridge", "error", err) - return - } - - if err := bridge.AddChannel(h.Key().ID); err != nil { - log.Error("failed to add channel to bridge", "error", err) - return - } - - log.Info("channel added to bridge") - return - } -} - -type bridgeManager struct { - h *ari.BridgeHandle -} - -func ensureBridge(ctx context.Context, cl ari.Client, src *ari.Key) (err error) { - if bridge != nil { - log.Debug("Bridge already exists") - return nil - } - - key := src.New(ari.BridgeKey, rid.New(rid.Bridge)) - bridge, err = cl.Bridge().Create(key, "mixing", key.ID) - if err != nil { - bridge = nil - return errors.Wrap(err, "failed to create bridge") - } - - wg := new(sync.WaitGroup) - wg.Add(1) - go manageBridge(ctx, bridge, wg) - wg.Wait() - - return nil -} - -func manageBridge(ctx context.Context, h *ari.BridgeHandle, wg *sync.WaitGroup) { - // Delete the bridge when we exit - defer h.Delete() - - destroySub := h.Subscribe(ari.Events.BridgeDestroyed) - defer destroySub.Cancel() - - enterSub := h.Subscribe(ari.Events.ChannelEnteredBridge) - defer enterSub.Cancel() - - leaveSub := h.Subscribe(ari.Events.ChannelLeftBridge) - defer leaveSub.Cancel() - - wg.Done() - for { - select { - case <-ctx.Done(): - return - case <-destroySub.Events(): - log.Debug("bridge destroyed") - return - case e, ok := <-enterSub.Events(): - if !ok { - log.Error("channel entered subscription closed") - return - } - v := e.(*ari.ChannelEnteredBridge) - log.Debug("channel entered bridge", "channel", v.Channel.Name) - go func() { - if err := play.Play(ctx, h, play.URI("sound:confbridge-join")).Err(); err != nil { - log.Error("failed to play join sound", "error", err) - } - }() - case e, ok := <-leaveSub.Events(): - if !ok { - log.Error("channel left subscription closed") - return - } - v := e.(*ari.ChannelLeftBridge) - log.Debug("channel left bridge", "channel", v.Channel.Name) - go func() { - if err := play.Play(ctx, h, play.URI("sound:confbridge-leave")).Err(); err != nil { - log.Error("failed to play leave sound", "error", err) - } - }() - } - } -} diff --git a/v5/_examples/play/main.go b/v5/_examples/play/main.go deleted file mode 100644 index 916d9b7..0000000 --- a/v5/_examples/play/main.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "context" - - "github.com/inconshreveable/log15" - - "github.com/CyCoreSystems/ari-proxy/v5/client" - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/ext/play" -) - -var ariApp = "test" - -var log = log15.New() - -func main() { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // connect - log.Info("Connecting to ARI") - cl, err := client.New(ctx, client.WithApplication(ariApp), client.WithLogger(log)) - if err != nil { - log.Error("Failed to build ARI client", "error", err) - return - } - - // setup app - - log.Info("Starting listener app") - - err = client.Listen(ctx, cl, appStart(ctx)) - if err != nil { - log.Error("failed to listen for new calls") - } - <-ctx.Done() - - return -} - -func appStart(ctx context.Context) func(*ari.ChannelHandle, *ari.StasisStart) { - return func(h *ari.ChannelHandle, startEvent *ari.StasisStart) { - defer h.Hangup() - - log.Info("running app", "channel", h.Key().ID) - - if err := h.Answer(); err != nil { - log.Error("failed to answer call", "error", err) - // return - } - - if err := play.Play(ctx, h, play.URI("sound:tt-monkeys")).Err(); err != nil { - log.Error("failed to play sound", "error", err) - return - } - - log.Info("completed playback") - return - } -} diff --git a/v5/_examples/record/main.go b/v5/_examples/record/main.go deleted file mode 100644 index b427860..0000000 --- a/v5/_examples/record/main.go +++ /dev/null @@ -1,72 +0,0 @@ -package main - -import ( - "context" - - "github.com/inconshreveable/log15" - - "github.com/CyCoreSystems/ari-proxy/v5/client" - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/ext/record" -) - -var ariApp = "test" - -var log = log15.New() - -func main() { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - record.Logger = log - - // connect - log.Info("Connecting to ARI") - cl, err := client.New(ctx, client.WithApplication(ariApp), client.WithLogger(log)) - if err != nil { - log.Error("Failed to build ARI client", "error", err) - return - } - - // setup app - - log.Info("Starting listener app") - - err = client.Listen(ctx, cl, appStart(ctx)) - if err != nil { - log.Error("failed to listen for new calls") - } - <-ctx.Done() - - return -} - -func appStart(ctx context.Context) func(*ari.ChannelHandle, *ari.StasisStart) { - return func(h *ari.ChannelHandle, startEvent *ari.StasisStart) { - defer h.Hangup() - - log.Info("running app", "channel", h.Key().ID) - - if err := h.Answer(); err != nil { - log.Error("failed to answer call", "error", err) - // return - } - - res, err := record.Record(ctx, h, - record.TerminateOn("any"), - record.IfExists("overwrite"), - ).Result() - if err != nil { - log.Error("failed to record", "error", err) - return - } - - if err = res.Save("test-recording"); err != nil { - log.Error("failed to save recording", "error", err) - } - - log.Info("completed recording") - - h.Hangup() - } -} diff --git a/v5/_examples/stasisStart/main.go b/v5/_examples/stasisStart/main.go deleted file mode 100644 index b9f2db7..0000000 --- a/v5/_examples/stasisStart/main.go +++ /dev/null @@ -1,133 +0,0 @@ -package main - -import ( - "context" - "net/http" - "sync" - - "github.com/CyCoreSystems/ari-proxy/v5/client" - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/client/native" - - "github.com/inconshreveable/log15" -) - -var ariApp = "test" - -var log = log15.New() - -func main() { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // connect - native.Logger = log - - log.Info("Connecting to ARI") - cl, err := client.New(ctx, client.WithApplication(ariApp)) - if err != nil { - log.Error("Failed to build ARI client", "error", err) - return - } - - // setup app - - log.Info("Starting listener app") - - listenApp(ctx, cl, channelHandler) - - // start call start listener - - log.Info("Starting HTTP Handler") - - http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // make call - log.Info("Make sample call") - h, err := createCall(cl) - if err != nil { - log.Error("Failed to create call", "error", err) - w.WriteHeader(http.StatusBadGateway) - w.Write([]byte("Failed to create call: " + err.Error())) - return - } - - w.WriteHeader(http.StatusOK) - w.Write([]byte(h.ID())) - })) - - log.Info("Listening for requests on port 9990") - http.ListenAndServe(":9990", nil) - - return -} - -func listenApp(ctx context.Context, cl ari.Client, handler func(*ari.ChannelHandle, *ari.StasisStart)) { - err := client.Listen(ctx, cl, func(ch *ari.ChannelHandle, v *ari.StasisStart) { - log.Info("Got stasis start", "channel", v.Channel.ID) - go handler(ch, v) - }) - if err != nil { - log.Crit("failed to listen for new calls", "error", err) - } - return -} - -func createCall(cl ari.Client) (h *ari.ChannelHandle, err error) { - h, err = cl.Channel().Create(nil, ari.ChannelCreateRequest{ - Endpoint: "Local/1000", - App: ariApp, - }) - - return -} - -func channelHandler(h *ari.ChannelHandle, startEvent *ari.StasisStart) { - log.Info("Running channel handler") - - // Subscribe to channel state changes - stateChange := h.Subscribe(ari.Events.ChannelStateChange) - defer stateChange.Cancel() - - // Subscribe to StasisEnd events (channel leaving ARI app) - end := h.Subscribe(ari.Events.StasisEnd) - defer end.Cancel() - - // Pull the current channel data - data, err := h.Data() - if err != nil { - log.Error("Error getting data", "error", err) - return - } - log.Info("Channel State", "state", data.State) - - var wg sync.WaitGroup - - wg.Add(1) - go func() { - log.Info("Waiting for channel events") - - defer wg.Done() - - for { - select { - case <-end.Events(): - log.Info("Got stasis end") - return - case e := <-stateChange.Events(): - v, ok := e.(*ari.ChannelStateChange) - if !ok { - log.Error("failed to interpret event as ChannelStateChange", "error", err) - return - } - - log.Info("New Channel State", "state", v.Channel.State) - } - } - }() - - h.Answer() - - wg.Wait() - - h.Hangup() -} diff --git a/v5/client/application.go b/v5/client/application.go deleted file mode 100644 index 896acbe..0000000 --- a/v5/client/application.go +++ /dev/null @@ -1,60 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type application struct { - c *Client -} - -func (a *application) List(filter *ari.Key) ([]*ari.Key, error) { - return a.c.listRequest(&proxy.Request{ - Kind: "ApplicationList", - Key: filter, - }) -} - -func (a *application) Data(key *ari.Key) (*ari.ApplicationData, error) { - ret, err := a.c.dataRequest(&proxy.Request{ - Kind: "ApplicationData", - Key: key, - }) - if err != nil { - return nil, err - } - return ret.Application, nil -} - -func (a *application) Get(key *ari.Key) *ari.ApplicationHandle { - k, err := a.c.getRequest(&proxy.Request{ - Kind: "ApplicationGet", - Key: key, - }) - if err != nil { - a.c.log.Warn("failed to make data request for application", "error", err) - return ari.NewApplicationHandle(key, a) - } - return ari.NewApplicationHandle(k, a) -} - -func (a *application) Subscribe(key *ari.Key, eventSource string) (err error) { - return a.c.commandRequest(&proxy.Request{ - Kind: "ApplicationSubscribe", - Key: key, - ApplicationSubscribe: &proxy.ApplicationSubscribe{ - EventSource: eventSource, - }, - }) -} - -func (a *application) Unsubscribe(key *ari.Key, eventSource string) (err error) { - return a.c.commandRequest(&proxy.Request{ - Kind: "ApplicationUnsubscribe", - Key: key, - ApplicationSubscribe: &proxy.ApplicationSubscribe{ - EventSource: eventSource, - }, - }) -} diff --git a/v5/client/application_test.go b/v5/client/application_test.go deleted file mode 100644 index ff24299..0000000 --- a/v5/client/application_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestApplicationList(t *testing.T) { - integration.TestApplicationList(t, &srv{}) -} - -func TestApplicationData(t *testing.T) { - integration.TestApplicationData(t, &srv{}) -} - -func TestApplicationSubscribe(t *testing.T) { - integration.TestApplicationSubscribe(t, &srv{}) -} - -func TestApplicationUnsubscribe(t *testing.T) { - integration.TestApplicationUnsubscribe(t, &srv{}) -} - -func TestApplicationGet(t *testing.T) { - integration.TestApplicationGet(t, &srv{}) -} diff --git a/v5/client/asterisk.go b/v5/client/asterisk.go deleted file mode 100644 index 369514e..0000000 --- a/v5/client/asterisk.go +++ /dev/null @@ -1,62 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type asterisk struct { - c *Client -} - -func (a *asterisk) Config() ari.Config { - return &config{a.c} -} - -type asteriskVariables struct { - c *Client -} - -func (a *asterisk) Logging() ari.Logging { - return &logging{a.c} -} - -func (a *asterisk) Modules() ari.Modules { - return &modules{a.c} -} - -func (a *asterisk) Info(key *ari.Key) (*ari.AsteriskInfo, error) { - resp, err := a.c.dataRequest(&proxy.Request{ - Kind: "AsteriskInfo", - Key: key, - }) - if err != nil { - return nil, err - } - return resp.Asterisk, nil -} - -func (a *asterisk) Variables() ari.AsteriskVariables { - return &asteriskVariables{a.c} -} - -func (a *asteriskVariables) Get(key *ari.Key) (ret string, err error) { - data, err := a.c.dataRequest(&proxy.Request{ - Kind: "AsteriskVariableGet", - Key: key, - }) - if err != nil { - return "", err - } - return data.Variable, err -} - -func (a *asteriskVariables) Set(key *ari.Key, val string) (err error) { - return a.c.commandRequest(&proxy.Request{ - Kind: "AsteriskVariableSet", - Key: key, - AsteriskVariableSet: &proxy.AsteriskVariableSet{ - Value: val, - }, - }) -} diff --git a/v5/client/asterisk_test.go b/v5/client/asterisk_test.go deleted file mode 100644 index 593e3e7..0000000 --- a/v5/client/asterisk_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestAsteriskInfo(t *testing.T) { - integration.TestAsteriskInfo(t, &srv{}) -} - -func TestAsteriskVariablesGet(t *testing.T) { - integration.TestAsteriskVariablesGet(t, &srv{}) -} - -func TestAsteriskVariablesSet(t *testing.T) { - integration.TestAsteriskVariablesSet(t, &srv{}) -} diff --git a/v5/client/bridge.go b/v5/client/bridge.go deleted file mode 100644 index 40dcb12..0000000 --- a/v5/client/bridge.go +++ /dev/null @@ -1,250 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - rid "github.com/CyCoreSystems/ari-rid" - "github.com/CyCoreSystems/ari/v5" -) - -type bridge struct { - c *Client -} - -func (b *bridge) Create(key *ari.Key, btype, name string) (*ari.BridgeHandle, error) { - k, err := b.c.createRequest(&proxy.Request{ - Kind: "BridgeCreate", - Key: key, - BridgeCreate: &proxy.BridgeCreate{ - Type: btype, - Name: name, - }, - }) - if err != nil { - return nil, err - } - return ari.NewBridgeHandle(k, b, nil), nil -} - -func (b *bridge) StageCreate(key *ari.Key, btype, name string) (*ari.BridgeHandle, error) { - k, err := b.c.createRequest(&proxy.Request{ - Kind: "BridgeStageCreate", - Key: key, - BridgeCreate: &proxy.BridgeCreate{ - Type: btype, - Name: name, - }, - }) - if err != nil { - return nil, err - } - return ari.NewBridgeHandle(k, b, func(h *ari.BridgeHandle) error { - _, err := b.Create(k, btype, name) - return err - }), nil -} - -func (b *bridge) Get(key *ari.Key) *ari.BridgeHandle { - k, err := b.c.getRequest(&proxy.Request{ - Kind: "BridgeGet", - Key: key, - }) - if err != nil { - b.c.log.Warn("failed to get bridge for handle", "error", err) - return ari.NewBridgeHandle(key, b, nil) - } - return ari.NewBridgeHandle(k, b, nil) -} - -func (b *bridge) List(filter *ari.Key) ([]*ari.Key, error) { - return b.c.listRequest(&proxy.Request{ - Kind: "BridgeList", - Key: filter, - }) -} - -func (b *bridge) Data(key *ari.Key) (*ari.BridgeData, error) { - resp, err := b.c.dataRequest(&proxy.Request{ - Kind: "BridgeData", - Key: key, - }) - if err != nil { - return nil, err - } - return resp.Bridge, nil -} - -func (b *bridge) AddChannel(key *ari.Key, channelID string) error { - return b.AddChannelWithOptions(key, channelID, nil) -} - -func (b *bridge) AddChannelWithOptions(key *ari.Key, channelID string, options *ari.BridgeAddChannelOptions) error { - if options == nil { - options = new(ari.BridgeAddChannelOptions) - } - - return b.c.commandRequest(&proxy.Request{ - Kind: "BridgeAddChannel", - Key: key, - BridgeAddChannel: &proxy.BridgeAddChannel{ - Channel: channelID, - AbsorbDTMF: options.AbsorbDTMF, - Mute: options.Mute, - Role: options.Role, - }, - }) -} - -func (b *bridge) RemoveChannel(key *ari.Key, channelID string) error { - return b.c.commandRequest(&proxy.Request{ - Kind: "BridgeRemoveChannel", - Key: key, - BridgeRemoveChannel: &proxy.BridgeRemoveChannel{ - Channel: channelID, - }, - }) -} - -func (b *bridge) Delete(key *ari.Key) error { - return b.c.commandRequest(&proxy.Request{ - Kind: "BridgeDelete", - Key: key, - }) -} - -func (b *bridge) MOH(key *ari.Key, class string) error { - return b.c.commandRequest(&proxy.Request{ - Kind: "BridgeMOH", - Key: key, - BridgeMOH: &proxy.BridgeMOH{ - Class: class, - }, - }) -} - -func (b *bridge) StopMOH(key *ari.Key) error { - return b.c.commandRequest(&proxy.Request{ - Kind: "BridgeStopMOH", - Key: key, - }) -} - -func (b *bridge) Play(key *ari.Key, id string, uri string) (*ari.PlaybackHandle, error) { - if id == "" { - id = rid.New(rid.Playback) - } - k, err := b.c.createRequest(&proxy.Request{ - Kind: "BridgePlay", - Key: key, - BridgePlay: &proxy.BridgePlay{ - MediaURI: uri, - PlaybackID: id, - }, - }) - if err != nil { - return nil, err - } - return ari.NewPlaybackHandle(k.New(ari.PlaybackKey, id), b.c.Playback(), nil), nil -} - -func (b *bridge) StagePlay(key *ari.Key, id string, uri string) (*ari.PlaybackHandle, error) { - if id == "" { - id = rid.New(rid.Playback) - } - k, err := b.c.getRequest(&proxy.Request{ - Kind: "BridgeStagePlay", - Key: key, - BridgePlay: &proxy.BridgePlay{ - MediaURI: uri, - PlaybackID: id, - }, - }) - if err != nil { - return nil, err - } - - return ari.NewPlaybackHandle(k.New(ari.PlaybackKey, id), b.c.Playback(), func(h *ari.PlaybackHandle) error { - _, err := b.Play(k.New(ari.BridgeKey, key.ID), id, uri) - return err - }), nil -} - -func (b *bridge) Record(key *ari.Key, name string, opts *ari.RecordingOptions) (*ari.LiveRecordingHandle, error) { - if opts == nil { - opts = &ari.RecordingOptions{} - } - if name == "" { - name = rid.New(rid.Recording) - } - - k, err := b.c.createRequest(&proxy.Request{ - Kind: "BridgeRecord", - Key: key, - BridgeRecord: &proxy.BridgeRecord{ - Name: name, - Options: opts, - }, - }) - if err != nil { - return nil, err - } - return ari.NewLiveRecordingHandle(k.New(ari.LiveRecordingKey, name), b.c.LiveRecording(), nil), nil -} - -func (b *bridge) StageRecord(key *ari.Key, name string, opts *ari.RecordingOptions) (*ari.LiveRecordingHandle, error) { - if opts == nil { - opts = &ari.RecordingOptions{} - } - if name == "" { - name = rid.New(rid.Recording) - } - - k, err := b.c.getRequest(&proxy.Request{ - Kind: "BridgeStageRecord", - Key: key, - BridgeRecord: &proxy.BridgeRecord{ - Name: name, - Options: opts, - }, - }) - if err != nil { - return nil, err - } - - return ari.NewLiveRecordingHandle(k.New(ari.LiveRecordingKey, name), b.c.LiveRecording(), func(h *ari.LiveRecordingHandle) error { - _, err := b.Record(k.New(ari.BridgeKey, key.ID), name, opts) - return err - }), nil -} - -func (b *bridge) Subscribe(key *ari.Key, n ...string) ari.Subscription { - err := b.c.commandRequest(&proxy.Request{ - Kind: "BridgeSubscribe", - Key: key, - }) - if err != nil { - b.c.log.Warn("failed to call bridge subscribe") - if key.Dialog != "" { - b.c.log.Error("dialog present; failing") - return nil - } - } - - return b.c.Bus().Subscribe(key, n...) -} - -func (b *bridge) VideoSource(key *ari.Key, channelID string) error { - return b.c.commandRequest(&proxy.Request{ - Kind: "BridgeVideoSource", - Key: key, - BridgeVideoSource: &proxy.BridgeVideoSource{ - Channel: channelID, - }, - }) -} - -func (b *bridge) VideoSourceDelete(key *ari.Key) error { - return b.c.commandRequest(&proxy.Request{ - Kind: "BridgeVideoSourceDelete", - Key: key, - }) -} diff --git a/v5/client/bridge_test.go b/v5/client/bridge_test.go deleted file mode 100644 index 8f85579..0000000 --- a/v5/client/bridge_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestBridgeCreate(t *testing.T) { - integration.TestBridgeCreate(t, &srv{}) -} - -func TestBridgeList(t *testing.T) { - integration.TestBridgeList(t, &srv{}) -} - -func TestBridgeData(t *testing.T) { - integration.TestBridgeData(t, &srv{}) -} - -func TestBridgeAddChannel(t *testing.T) { - integration.TestBridgeAddChannel(t, &srv{}) -} - -func TestBridgeRemoveChannel(t *testing.T) { - integration.TestBridgeRemoveChannel(t, &srv{}) -} - -func TestBridgeDelete(t *testing.T) { - integration.TestBridgeDelete(t, &srv{}) -} - -func TestBridgePlay(t *testing.T) { - integration.TestBridgePlay(t, &srv{}) -} - -func TestBridgeRecord(t *testing.T) { - integration.TestBridgeRecord(t, &srv{}) -} diff --git a/v5/client/bus/bus.go b/v5/client/bus/bus.go deleted file mode 100644 index 677f5be..0000000 --- a/v5/client/bus/bus.go +++ /dev/null @@ -1,171 +0,0 @@ -package bus - -import ( - "fmt" - "sync" - - "github.com/CyCoreSystems/ari/v5" - "github.com/inconshreveable/log15" - - "github.com/nats-io/nats.go" -) - -// EventChanBufferLength is the number of unhandled events which can be queued -// to the event channel buffer before further events are lost. -var EventChanBufferLength = 10 - -// Bus provides an ari.Bus interface to NATS -type Bus struct { - prefix string - - log log15.Logger - - nc *nats.EncodedConn -} - -// New returns a new Bus -func New(prefix string, nc *nats.EncodedConn, log log15.Logger) *Bus { - return &Bus{ - prefix: prefix, - log: log, - nc: nc, - } -} - -func (b *Bus) subjectFromKey(key *ari.Key) string { - if key == nil { - return fmt.Sprintf("%sevent.>", b.prefix) - } - - if key.Dialog != "" { - return fmt.Sprintf("%sdialogevent.%s", b.prefix, key.Dialog) - } - - subj := fmt.Sprintf("%sevent.", b.prefix) - if key.App == "" { - return subj + ">" - } - subj += key.App + "." - - if key.Node == "" { - return subj + ">" - } - return subj + key.Node -} - -// Subscription represents an ari.Subscription over NATS -type Subscription struct { - key *ari.Key - - log log15.Logger - - subscription *nats.Subscription - - eventChan chan ari.Event - - events []string - - closed bool - - mu sync.RWMutex -} - -// Close implements ari.Bus -func (b *Bus) Close() { - // No-op -} - -// Send implements ari.Bus -func (b *Bus) Send(e ari.Event) { - // No-op -} - -// Subscribe implements ari.Bus -func (b *Bus) Subscribe(key *ari.Key, n ...string) ari.Subscription { - var err error - - s := &Subscription{ - key: key, - log: b.log, - eventChan: make(chan ari.Event, EventChanBufferLength), - events: n, - } - - s.subscription, err = b.nc.Subscribe(b.subjectFromKey(key), func(m *nats.Msg) { - s.receive(m) - }) - if err != nil { - b.log.Error("failed to subscribe to NATS", "error", err) - return nil - } - return s -} - -// Events returns the channel on which events from this subscription will be sent -func (s *Subscription) Events() <-chan ari.Event { - return s.eventChan -} - -// Cancel destroys the subscription -func (s *Subscription) Cancel() { - if s == nil { - return - } - - if s.subscription != nil { - err := s.subscription.Unsubscribe() - if err != nil { - s.log.Error("failed unsubscribe from NATS", "error", err) - } - } - - s.mu.Lock() - if !s.closed { - s.closed = true - close(s.eventChan) - } - s.mu.Unlock() -} - -func (s *Subscription) receive(o *nats.Msg) { - e, err := ari.DecodeEvent(o.Data) - if err != nil { - s.log.Error("failed to convert received message to ari.Event", "error", err) - return - } - - if s.matchEvent(e) { - s.mu.RLock() - if !s.closed { - s.eventChan <- e - } - s.mu.RUnlock() - } -} - -func (s *Subscription) matchEvent(o ari.Event) bool { - // First, filter by type - var match bool - for _, kind := range s.events { - if kind == o.GetType() || kind == ari.Events.All { - match = true - break - } - } - if !match { - return false - } - - // If we don't have a resource ID, we match everything - // Next, match the entity - if s.key == nil || s.key.ID == "" { - return true - } - - for _, k := range o.Keys() { - if s.key.Match(k) { - return true - } - } - return false -} diff --git a/v5/client/bus/bus_test.go b/v5/client/bus/bus_test.go deleted file mode 100644 index b1e9dcd..0000000 --- a/v5/client/bus/bus_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package bus - -import ( - "testing" - "time" - - "github.com/inconshreveable/log15" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestMatchEvent(t *testing.T) { - key := &ari.Key{ - Kind: ari.ChannelKey, - ID: "testA", - Node: "0test0", - App: "testApp", - } - - e := &ari.StasisEnd{ - EventData: ari.EventData{ - Type: "StasisEnd", - Application: "testApp", - Node: "0test0", - Timestamp: ari.DateTime(time.Now()), - }, - Header: make(ari.Header), - Channel: ari.ChannelData{ - Key: nil, - ID: "testB", - Name: "Local/bozo", - State: "up", - Accountcode: "49er", - Dialplan: &ari.DialplanCEP{ - Context: "default", - Exten: "s", - Priority: 1, - }, - }, - } - - s := &Subscription{ - key: key, - log: log15.New(), - eventChan: make(chan ari.Event, EventChanBufferLength), - events: []string{"StasisEnd"}, - } - - if s.matchEvent(e) { - t.Error("matched incorrect event") - } -} diff --git a/v5/client/channel.go b/v5/client/channel.go deleted file mode 100644 index 85b0aeb..0000000 --- a/v5/client/channel.go +++ /dev/null @@ -1,432 +0,0 @@ -package client - -import ( - "time" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - rid "github.com/CyCoreSystems/ari-rid" - "github.com/CyCoreSystems/ari/v5" -) - -type channel struct { - c *Client -} - -func (c *channel) Get(key *ari.Key) *ari.ChannelHandle { - k, err := c.c.getRequest(&proxy.Request{ - Kind: "ChannelGet", - Key: key, - }) - if err != nil { - c.c.log.Warn("failed to make data request for channel", "error", err) - return ari.NewChannelHandle(key, c, nil) - } - return ari.NewChannelHandle(k, c, nil) -} - -func (c *channel) List(filter *ari.Key) ([]*ari.Key, error) { - return c.c.listRequest(&proxy.Request{ - Kind: "ChannelList", - Key: filter, - }) -} - -func (c *channel) Originate(referenceKey *ari.Key, o ari.OriginateRequest) (*ari.ChannelHandle, error) { - k, err := c.c.createRequest(&proxy.Request{ - Kind: "ChannelOriginate", - Key: referenceKey, - ChannelOriginate: &proxy.ChannelOriginate{ - OriginateRequest: o, - }, - }) - if err != nil { - return nil, err - } - return ari.NewChannelHandle(k, c, nil), nil -} - -func (c *channel) StageOriginate(referenceKey *ari.Key, o ari.OriginateRequest) (*ari.ChannelHandle, error) { - if o.ChannelID == "" { - o.ChannelID = rid.New(rid.Channel) - } - - // We go ahead an call the createRequest on the server so that we lock in an - // Asterisk box at the time of staging even though this staging call will - // never actually be used. - k, err := c.c.createRequest(&proxy.Request{ - Kind: "ChannelStageOriginate", - Key: referenceKey, - ChannelOriginate: &proxy.ChannelOriginate{ - OriginateRequest: o, - }, - }) - if err != nil { - return nil, err - } - return ari.NewChannelHandle(k.New(ari.ChannelKey, o.ChannelID), c, func(h *ari.ChannelHandle) error { - _, err := c.Originate(referenceKey, o) - return err - }), nil -} - -func (c *channel) Create(key *ari.Key, o ari.ChannelCreateRequest) (*ari.ChannelHandle, error) { - k, err := c.c.createRequest(&proxy.Request{ - Kind: "ChannelCreate", - Key: key, - ChannelCreate: &proxy.ChannelCreate{ - ChannelCreateRequest: o, - }, - }) - if err != nil { - return nil, err - } - return ari.NewChannelHandle(k.New(ari.ChannelKey, o.ChannelID), c, nil), nil -} - -func (c *channel) Data(key *ari.Key) (*ari.ChannelData, error) { - data, err := c.c.dataRequest(&proxy.Request{ - Kind: "ChannelData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.Channel, nil -} - -func (c *channel) Continue(key *ari.Key, context string, extension string, priority int) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelContinue", - Key: key, - ChannelContinue: &proxy.ChannelContinue{ - Context: context, - Extension: extension, - Priority: priority, - }, - }) -} - -func (c *channel) Busy(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelBusy", - Key: key, - }) -} - -func (c *channel) Congestion(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelCongestion", - Key: key, - }) -} - -func (c *channel) Hangup(key *ari.Key, reason string) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelHangup", - Key: key, - ChannelHangup: &proxy.ChannelHangup{ - Reason: reason, - }, - }) -} - -func (c *channel) Answer(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelAnswer", - Key: key, - }) -} - -func (c *channel) Ring(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelRing", - Key: key, - }) -} - -func (c *channel) StopRing(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelStopRing", - Key: key, - }) -} - -func (c *channel) SendDTMF(key *ari.Key, dtmf string, opts *ari.DTMFOptions) error { - if opts == nil { - opts = &ari.DTMFOptions{} - } - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelSendDTMF", - Key: key, - ChannelSendDTMF: &proxy.ChannelSendDTMF{ - DTMF: dtmf, - Options: opts, - }, - }) -} - -func (c *channel) Hold(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelHold", - Key: key, - }) -} - -func (c *channel) StopHold(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelStopHold", - Key: key, - }) -} - -func (c *channel) Mute(key *ari.Key, dir ari.Direction) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelMute", - Key: key, - ChannelMute: &proxy.ChannelMute{ - Direction: dir, - }, - }) -} - -func (c *channel) Unmute(key *ari.Key, dir ari.Direction) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelUnmute", - Key: key, - ChannelMute: &proxy.ChannelMute{ - Direction: dir, - }, - }) -} - -func (c *channel) MOH(key *ari.Key, moh string) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelMOH", - Key: key, - ChannelMOH: &proxy.ChannelMOH{ - Music: moh, - }, - }) -} - -func (c *channel) StopMOH(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelStopMOH", - Key: key, - }) -} - -func (c *channel) Silence(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelSilence", - Key: key, - }) -} - -func (c *channel) StopSilence(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelStopSilence", - Key: key, - }) -} - -func (c *channel) Snoop(key *ari.Key, snoopID string, opts *ari.SnoopOptions) (*ari.ChannelHandle, error) { - k, err := c.c.createRequest(&proxy.Request{ - Kind: "ChannelSnoop", - Key: key, - ChannelSnoop: &proxy.ChannelSnoop{ - SnoopID: snoopID, - Options: opts, - }, - }) - if err != nil { - return nil, err - } - return ari.NewChannelHandle(k.New(ari.ChannelKey, snoopID), c, nil), nil -} - -func (c *channel) StageSnoop(key *ari.Key, snoopID string, opts *ari.SnoopOptions) (*ari.ChannelHandle, error) { - // this getRequest is done merely to locate the Asterisk box on which the - // snoop will be initiated. It will never actually be Exec'd - k, err := c.c.getRequest(&proxy.Request{ - Kind: "ChannelStageSnoop", - Key: key, - ChannelSnoop: &proxy.ChannelSnoop{ - SnoopID: snoopID, - Options: opts, - }, - }) - if err != nil { - return nil, err - } - return ari.NewChannelHandle(k, c, func(h *ari.ChannelHandle) error { - _, err := c.Snoop(k.New(ari.ChannelKey, key.ID), snoopID, opts) - return err - }), nil -} - -func (c *channel) ExternalMedia(referenceKey *ari.Key, opts ari.ExternalMediaOptions) (*ari.ChannelHandle, error) { - if opts.ChannelID == "" { - opts.ChannelID = rid.New(rid.Channel) - } - k, err := c.c.createRequest(&proxy.Request{ - Kind: "ChannelExternalMedia", - Key: referenceKey, - ChannelExternalMedia: &proxy.ChannelExternalMedia{ - Options: opts, - }, - }) - if err != nil { - return nil, err - } - return ari.NewChannelHandle(k, c, nil), nil -} - -func (c *channel) StageExternalMedia(referenceKey *ari.Key, opts ari.ExternalMediaOptions) (*ari.ChannelHandle, error) { - if opts.ChannelID == "" { - opts.ChannelID = rid.New(rid.Channel) - } - - // We go ahead an call the createRequest on the server so that we lock in an - // Asterisk box at the time of staging even though this staging call will - // never actually be used. - k, err := c.c.createRequest(&proxy.Request{ - Kind: "ChannelStageOriginate", - Key: referenceKey, - ChannelExternalMedia: &proxy.ChannelExternalMedia{ - Options: opts, - }, - }) - if err != nil { - return nil, err - } - return ari.NewChannelHandle(k, c, func(h *ari.ChannelHandle) error { - _, err := c.ExternalMedia(k, opts) - return err - }), nil -} - -func (c *channel) Dial(key *ari.Key, caller string, timeout time.Duration) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelDial", - Key: key, - ChannelDial: &proxy.ChannelDial{ - Caller: caller, - Timeout: timeout, - }, - }) -} - -func (c *channel) Play(key *ari.Key, playbackID string, mediaURI string) (*ari.PlaybackHandle, error) { - if playbackID == "" { - playbackID = rid.New(rid.Playback) - } - - k, err := c.c.createRequest(&proxy.Request{ - Kind: "ChannelPlay", - Key: key, - ChannelPlay: &proxy.ChannelPlay{ - PlaybackID: playbackID, - MediaURI: mediaURI, - }, - }) - if err != nil { - return nil, err - } - return ari.NewPlaybackHandle(k.New(ari.PlaybackKey, playbackID), c.c.Playback(), nil), nil -} - -func (c *channel) StagePlay(key *ari.Key, playbackID string, mediaURI string) (*ari.PlaybackHandle, error) { - if playbackID == "" { - playbackID = rid.New(rid.Playback) - } - - k, err := c.c.getRequest(&proxy.Request{ - Kind: "ChannelStagePlay", - Key: key, - ChannelPlay: &proxy.ChannelPlay{ - PlaybackID: playbackID, - MediaURI: mediaURI, - }, - }) - if err != nil { - return nil, err - } - return ari.NewPlaybackHandle(k.New(ari.PlaybackKey, playbackID), c.c.Playback(), func(h *ari.PlaybackHandle) error { - _, err := c.Play(k.New(ari.ChannelKey, key.ID), playbackID, mediaURI) - return err - }), nil -} - -func (c *channel) Record(key *ari.Key, name string, opts *ari.RecordingOptions) (*ari.LiveRecordingHandle, error) { - rb, err := c.c.createRequest(&proxy.Request{ - Kind: "ChannelRecord", - Key: key, - ChannelRecord: &proxy.ChannelRecord{ - Name: name, - Options: opts, - }, - }) - if err != nil { - return nil, err - } - return ari.NewLiveRecordingHandle(rb.New(ari.LiveRecordingKey, name), c.c.LiveRecording(), nil), nil -} - -func (c *channel) StageRecord(key *ari.Key, name string, opts *ari.RecordingOptions) (*ari.LiveRecordingHandle, error) { - k, err := c.c.getRequest(&proxy.Request{ - Kind: "ChannelStageRecord", - Key: key, - ChannelRecord: &proxy.ChannelRecord{ - Name: name, - Options: opts, - }, - }) - if err != nil { - return nil, err - } - return ari.NewLiveRecordingHandle(k.New(ari.LiveRecordingKey, k.ID), c.c.LiveRecording(), func(h *ari.LiveRecordingHandle) error { - _, err := c.Record(k.New(ari.ChannelKey, key.ID), k.ID, opts) - return err - }), nil -} - -func (c *channel) Subscribe(key *ari.Key, n ...string) ari.Subscription { - err := c.c.commandRequest(&proxy.Request{ - Kind: "ChannelSubscribe", - Key: key, - }) - if err != nil { - c.c.log.Warn("failed to call channel subscribe") - if key.Dialog != "" { - c.c.log.Error("dialog present; failing") - return nil - } - } - return c.c.Bus().Subscribe(key, n...) -} - -func (c *channel) GetVariable(key *ari.Key, name string) (string, error) { - data, err := c.c.dataRequest(&proxy.Request{ - Kind: "ChannelVariableGet", - Key: key, - ChannelVariable: &proxy.ChannelVariable{ - Name: name, - }, - }) - if err != nil { - return "", err - } - return data.Variable, nil -} - -func (c *channel) SetVariable(key *ari.Key, name, value string) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "ChannelVariableSet", - Key: key, - ChannelVariable: &proxy.ChannelVariable{ - Name: name, - Value: value, - }, - }) -} diff --git a/v5/client/channel_test.go b/v5/client/channel_test.go deleted file mode 100644 index 0772cf0..0000000 --- a/v5/client/channel_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestChannelData(t *testing.T) { - integration.TestChannelData(t, &srv{}) -} - -func TestChannelAnswer(t *testing.T) { - integration.TestChannelAnswer(t, &srv{}) -} - -func TestChannelBusy(t *testing.T) { - integration.TestChannelBusy(t, &srv{}) -} - -func TestChannelCongestion(t *testing.T) { - integration.TestChannelCongestion(t, &srv{}) -} - -func TestChannelHangup(t *testing.T) { - integration.TestChannelHangup(t, &srv{}) -} - -func TestChannelList(t *testing.T) { - integration.TestChannelList(t, &srv{}) -} - -func TestChannelMute(t *testing.T) { - integration.TestChannelMute(t, &srv{}) -} - -func TestChannelUnmute(t *testing.T) { - integration.TestChannelUnmute(t, &srv{}) -} - -func TestChannelMOH(t *testing.T) { - integration.TestChannelMOH(t, &srv{}) -} - -func TestChannelStopMOH(t *testing.T) { - integration.TestChannelStopMOH(t, &srv{}) -} - -func TestChannelContinue(t *testing.T) { - integration.TestChannelContinue(t, &srv{}) -} diff --git a/v5/client/client.go b/v5/client/client.go deleted file mode 100644 index 5c4e83f..0000000 --- a/v5/client/client.go +++ /dev/null @@ -1,656 +0,0 @@ -package client - -import ( - "context" - "os" - "time" - - "github.com/CyCoreSystems/ari-proxy/v5/client/bus" - "github.com/CyCoreSystems/ari-proxy/v5/client/cluster" - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - rid "github.com/CyCoreSystems/ari-rid" - "github.com/CyCoreSystems/ari/v5" - - "github.com/inconshreveable/log15" - "github.com/nats-io/nats.go" - "github.com/pkg/errors" -) - -// ClosureGracePeriod is the amount of time to wait after the closure of the -// context to close the client. The delay here is important in order to allow -// wrap-up code to finish processing before losing connection to ARI. -// Depending on the characteristics of traffic and code, this value may need to -// be tweaked. -// -// NOTE: It is always possible to call `Close()` on the client to close it -// immediately. -var ClosureGracePeriod = 10 * time.Second - -// DefaultRequestTimeout is the default timeout for a NATS request. (Note: Answer() takes longer than 250ms on average) -const DefaultRequestTimeout = 500 * time.Millisecond - -// DefaultInputBufferLength is the default size of the event buffer for events -// coming in from NATS -const DefaultInputBufferLength = 100 - -// DefaultClusterMaxAge is the default maximum age for cluster members to be -// considered by this client -var DefaultClusterMaxAge = 5 * time.Minute - -// ErrNil indicates that the request returned an empty response -var ErrNil = errors.New("Nil") - -// core is the core, functional piece of a Client which is the same across the -// family of derived clients. It manages stateful elements such as the bus, -// the NATS connection, and the cluster membership -type core struct { - // cluster describes the cluster of ARI proxies - cluster *cluster.Cluster - - // clusterMaxAge is the maximum age of cluster members to include in queries - clusterMaxAge time.Duration - - // inputBufferLength is the size of the buffer for events coming in from NATS - inputBufferLength int - - log log15.Logger - - // nc provides the nats.EncodedConn over which messages will be transceived. - // One of NATS or NATSURI must be specified. - nc *nats.EncodedConn - - // prefix is the prefix to use on all NATS subjects. It defaults to "ari.". - prefix string - - // refCounter is the reference counter for derived clients. When there are - // no more referenced clients, the core is shut down. - refCounter int - - // requestTimeout is the timeout duration of a request - requestTimeout time.Duration - - // timeoutRetries is the amount of times to retry on nats timeout - timeoutRetries int - - // countTimeouts tracks how many timeouts the client has received, for metrics. - countTimeouts int64 // nolint: structcheck - - // uri provies the URI to which a NATS connection should be established. One - // of NATS or NATSURI must be specified. This option may also be supplied by - // the `NATS_URI` environment variable. - uri string - - // annSub is the NATS subscription to proxy announcements - annSub *nats.Subscription - - // closeChan is the signal channel responsible for shutting down core - // services. When it is closed, all core services should exit. - closeChan chan struct{} - - // closed indicates the core has been closed - closed bool - - // closeNATSOnClose indicates that the NATS connection should be closed when - // the ari.Client is closed - closeNATSOnClose bool - - // started indicates whether this core has been started; a started core will - // no-op core.start() - started bool -} - -// clientClosed is called any time a derived ARI client is closed; if the -// reference counter is ever dropped to zero, the core is also shut down -func (c *core) ClientClosed() { - c.refCounter-- - - if c.refCounter < 1 { - c.close() - } -} - -// close shuts down the core -func (c *core) close() { - if !c.closed { - c.closed = true - close(c.closeChan) - } - - if c.annSub != nil { - err := c.annSub.Unsubscribe() - if err != nil { - c.log.Debug("failed to unsubscribe from NATS proxy announcements", "error", err) - } - } - - if c.closeNATSOnClose && c.nc != nil { - c.nc.Close() - } -} - -func (c *core) Start() error { - // increment the client reference counter - c.refCounter++ - - // Only start the core once - if c.started { - return nil - } - c.started = true - - c.closeChan = make(chan struct{}) - - // Connect to NATS, if we do not already have a connection - if c.nc == nil { - n, err := nats.Connect(c.uri) - if err != nil { - c.close() - return errors.Wrap(err, "failed to connect to NATS") - } - - c.nc, err = nats.NewEncodedConn(n, nats.JSON_ENCODER) - if err != nil { - n.Close() // need this here because nc is not yet bound to the core - c.close() - return errors.Wrap(err, "failed to encode NATS connection") - } - - c.closeNATSOnClose = true - } - - // Create and start the cluster - c.cluster = cluster.New() - - // Maintain the cluster - err := c.maintainCluster() - if err != nil { - c.close() - return errors.Wrap(err, "failed to start cluster maintenance") - } - - return nil -} - -func (c *core) maintainCluster() (err error) { - c.annSub, err = c.nc.Subscribe(proxy.AnnouncementSubject(c.prefix), func(o *proxy.Announcement) { - c.cluster.Update(o.Node, o.Application) - }) - if err != nil { - return errors.Wrap(err, "failed to listen to proxy announcements") - } - - // Send an initial ping for proxy announcements - return c.nc.Publish(proxy.PingSubject(c.prefix), &proxy.Request{}) -} - -// Client provides an ari.Client for an ari-proxy server -type Client struct { - *core - - bus ari.Bus - - appName string - - cancel context.CancelFunc - - // closed indicates that this client has been closed and is no longer attached to a core - closed bool -} - -// New creates a new Client to the Asterisk ARI NATS proxy. -func New(ctx context.Context, opts ...OptionFunc) (*Client, error) { - ctx, cancel := context.WithCancel(ctx) - - c := &Client{ - appName: os.Getenv("ARI_APPLICATION"), - core: &core{ - cluster: cluster.New(), - clusterMaxAge: DefaultClusterMaxAge, - inputBufferLength: DefaultInputBufferLength, - log: log15.New(), - prefix: "ari.", - requestTimeout: DefaultRequestTimeout, - uri: "nats://localhost:4222", - }, - cancel: cancel, - } - c.log.SetHandler(log15.DiscardHandler()) - - // Load environment-based configurations - if os.Getenv("NATS_URI") != "" { - c.core.uri = os.Getenv("NATS_URI") - } - - // Load explicit configurations - for _, opt := range opts { - opt(c) - } - - // Start the core, if it is not already started - err := c.core.Start() - if err != nil { - return nil, errors.Wrap(err, "failed to start core") - } - - // Create the bus - c.bus = bus.New(c.core.prefix, c.core.nc, c.core.log) - - // Call Close whenever the context is closed - go func() { - <-ctx.Done() - if !c.closed { - // Only wait the grace period if we have not - // already been closed. - <-time.After(ClosureGracePeriod) - } - - c.Close() - }() - - return c, nil -} - -// New returns a new client from the existing one. The new client will have a -// separate event bus and lifecycle, allowing the closure of all subscriptions -// and handles derived from the client by simply closing the client. The -// underlying NATS connection and cluster awareness (the common Core) will be -// preserved across derived Client lifecycles. -func (c *Client) New(ctx context.Context) *Client { - _, cancel := context.WithCancel(ctx) - - return &Client{ - appName: c.appName, - cancel: cancel, - core: c.core, - bus: bus.New(c.core.prefix, c.core.nc, c.core.log), - } -} - -// OptionFunc is a function which configures options on a Client -type OptionFunc func(*Client) - -// FromClient configures the ARI Application to use the transport details from -// another ARI Client. Transport-related details are copied, such as the NATS -// Client, the NATS prefix, the timeout values. -// -// Specifically NOT copied are dialog, application, and asterisk details. -// -// NOTE: use of this function will cause NATS connection leakage if there is a -// mix of uses of FromClient and not over a period of time. If you intend to -// use FromClient, it is recommended that you always pass a NATS client in to -// the first ari.Client and maintain lifecycle control of it manually. -func FromClient(cl ari.Client) OptionFunc { - return func(c *Client) { - old, ok := cl.(*Client) - if ok { - c.core = old.core - } - } -} - -// WithApplication configures the ARI Client to use the provided ARI Application -func WithApplication(name string) OptionFunc { - return func(c *Client) { - c.appName = name - } -} - -// WithLogger sets the logger on a Client. -func WithLogger(l log15.Logger) OptionFunc { - return func(c *Client) { - c.log = l - } -} - -// WithLogHandler sets the logging handler on a Client logger -func WithLogHandler(h log15.Handler) OptionFunc { - return func(c *Client) { - c.log.SetHandler(h) - } -} - -// WithURI sets the NATS URI to which the client will attempt to connect. -// The NATS URI may also be configured by the environment variable `NATS_URI`. -func WithURI(uri string) OptionFunc { - return func(c *Client) { - c.core.uri = uri - } -} - -// WithNATS binds an existing NATS connection -func WithNATS(nc *nats.EncodedConn) OptionFunc { - return func(c *Client) { - c.nc = nc - } -} - -// WithPrefix configures the NATS Prefix to use on a Client -func WithPrefix(prefix string) OptionFunc { - return func(c *Client) { - c.core.prefix = prefix - } -} - -// WithTimeoutRetries configures the amount of times to retry on request timeout for a Client -func WithTimeoutRetries(count int) OptionFunc { - return func(c *Client) { - c.core.timeoutRetries = count - } -} - -// ApplicationName returns the ARI application's name -func (c *Client) ApplicationName() string { - return c.appName -} - -// Connected indicates whether the client is connected through to at least one ARI websocket -func (c *Client) Connected() bool { - if c.closed { - return false - } - - // TODO: this is a surrogate indicator with low resolution... we should have - // something more proactive and concrete - if len(c.cluster.App(c.appName, proxy.AnnouncementInterval*2)) < 1 { - return false - } - return true -} - -// Close shuts down the client -func (c *Client) Close() { - if c.cancel != nil { - c.cancel() - } - - if c.bus != nil { - c.bus.Close() - } - - if !c.closed && c.core != nil { - c.closed = true - c.core.ClientClosed() - } -} - -// Application is the application operation accessor -func (c *Client) Application() ari.Application { - return &application{c} -} - -// Asterisk is the asterisk operation accessor -func (c *Client) Asterisk() ari.Asterisk { - return &asterisk{c} -} - -// Bridge is the bridge operation accessor -func (c *Client) Bridge() ari.Bridge { - return &bridge{c} -} - -// Bus is the bus operation accessor -func (c *Client) Bus() ari.Bus { - return c.bus -} - -// Channel is the channel operation accessor -func (c *Client) Channel() ari.Channel { - return &channel{c} -} - -// DeviceState is the device state operation accessor -func (c *Client) DeviceState() ari.DeviceState { - return &deviceState{c} -} - -// Endpoint is the endpoint accessor -func (c *Client) Endpoint() ari.Endpoint { - return &endpoint{c} -} - -// LiveRecording is the live recording accessor -func (c *Client) LiveRecording() ari.LiveRecording { - return &liveRecording{c} -} - -// Mailbox is the mailbox accessor -func (c *Client) Mailbox() ari.Mailbox { - return &mailbox{c} -} - -// Playback is the media playback accessor -func (c *Client) Playback() ari.Playback { - return &playback{c} -} - -// Sound is the sound accessor -func (c *Client) Sound() ari.Sound { - return &sound{c} -} - -// StoredRecording is the stored recording accessor -func (c *Client) StoredRecording() ari.StoredRecording { - return &storedRecording{c} -} - -// TextMessage is the text message accessor -func (c *Client) TextMessage() ari.TextMessage { - return nil -} - -func (c *Client) commandRequest(req *proxy.Request) error { - resp, err := c.makeRequest("command", req) - if err != nil { - return err - } - return resp.Err() -} - -func (c *Client) createRequest(req *proxy.Request) (*ari.Key, error) { - resp, err := c.makeRequest("create", req) - if err != nil { - return nil, err - } - if resp.Err() != nil { - return nil, resp.Err() - } - if resp.Key == nil { - return nil, ErrNil - } - return resp.Key, nil -} - -func (c *Client) getRequest(req *proxy.Request) (*ari.Key, error) { - resp, err := c.makeRequest("get", req) - if err != nil { - return nil, err - } - if resp.Err() != nil { - return nil, resp.Err() - } - if resp.Key == nil { - return nil, ErrNil - } - return resp.Key, nil -} - -func (c *Client) dataRequest(req *proxy.Request) (*proxy.EntityData, error) { - resp, err := c.makeRequest("data", req) - if err != nil { - return nil, err - } - if resp.Err() != nil { - return nil, resp.Err() - } - if resp.Data == nil { - return nil, ErrNil - } - return resp.Data, nil -} - -func (c *Client) listRequest(req *proxy.Request) ([]*ari.Key, error) { - var list []*ari.Key - - responses, err := c.makeRequests("get", req) - if err != nil { - return nil, err - } - - for _, r := range responses { - err = r.Err() - if r.Err() != nil || r.Keys == nil { - continue - } - list = append(list, r.Keys...) - } - return list, err -} - -func (c *Client) makeRequest(class string, req *proxy.Request) (*proxy.Response, error) { - var resp proxy.Response - var err error - - if !c.completeCoordinates(req) { - return c.makeBroadcastRequestReturnFirstGoodResponse(class, req) - } - - for i := 0; i <= c.core.timeoutRetries; i++ { - err = c.nc.Request(c.subject(class, req), req, &resp, c.requestTimeout) - if err == nats.ErrTimeout { - c.countTimeouts++ - continue - } - return &resp, err - } - - return nil, err -} - -func (c *Client) makeRequests(class string, req *proxy.Request) (responses []*proxy.Response, err error) { - if req == nil { - return nil, errors.New("empty request") - } - if req.Key == nil { - req.Key = ari.NewKey("", "") - } - - var responseCount int - expected := len(c.core.cluster.Matching(req.Key.Node, req.Key.App, c.core.clusterMaxAge)) - reply := rid.New("rp") - replyChan := make(chan *proxy.Response) - replySub, err := c.core.nc.Subscribe(reply, func(o *proxy.Response) { - responseCount++ - - replyChan <- o - - if responseCount >= expected { - close(replyChan) - } - }) - if err != nil { - return nil, errors.Wrap(err, "failed to subscribe to data responses") - } - defer replySub.Unsubscribe() // nolint: errcheck - - // Make an all-call for the entity data - err = c.core.nc.PublishRequest(c.subject(class, req), reply, req) - if err != nil { - return nil, errors.Wrap(err, "failed to make request for data") - } - - // Wait for replies - for { - select { - case <-time.After(c.requestTimeout): - return responses, nil - case resp, ok := <-replyChan: - if !ok { - return responses, nil - } - responses = append(responses, resp) - } - } -} - -// TODO: simplify -// nolint: gocyclo -func (c *Client) makeBroadcastRequestReturnFirstGoodResponse(class string, req *proxy.Request) (*proxy.Response, error) { - if req == nil { - return nil, errors.New("empty request") - } - if req.Key == nil { - req.Key = ari.NewKey("", "") - } - - expected := len(c.core.cluster.Matching(req.Key.Node, req.Key.App, c.core.clusterMaxAge)) - reply := rid.New("rp") - replyChan := make(chan *proxy.Response) - - var responseCount int - replySub, err := c.core.nc.Subscribe(reply, func(o *proxy.Response) { - responseCount++ - - // always send up reply, so we can track errors. - replyChan <- o - - if responseCount >= expected { - close(replyChan) - } - }) - if err != nil { - return nil, errors.Wrap(err, "failed to subscribe to data responses") - } - defer replySub.Unsubscribe() // nolint: errcheck - - // Make an all-call for the entity data - err = c.core.nc.PublishRequest(c.subject(class, req), reply, req) - if err != nil { - return nil, errors.Wrap(err, "failed to make request for data") - } - - // Wait for replies - for { - select { - case <-time.After(c.requestTimeout): - // Return the last error if we got one; otherwise, return a timeout error - if err == nil { - err = errors.New("timeout") - } - return nil, err - case resp, more := <-replyChan: - if !more { - if err == nil { - err = errors.New("no data") - } - return nil, err - } - if resp != nil { - err = resp.Err() // store the error for later return - if err == nil { // No error means to return the current value - return resp, nil - } - } - } - } -} - -func (c *Client) completeCoordinates(req *proxy.Request) bool { - if req == nil || req.Key == nil { - return false - } - - // coordinates are complete if we have both app and node - return req.Key.App != "" && req.Key.Node != "" -} - -func (c *Client) subject(class string, req *proxy.Request) string { - if req == nil || req.Key == nil { - return proxy.Subject(c.core.prefix, class, c.appName, "") - } - return proxy.Subject(c.core.prefix, class, req.Key.App, req.Key.Node) -} - -// TimeoutCount is the amount of times the NATS communication times out -func (c *Client) TimeoutCount() int64 { - return c.countTimeouts -} diff --git a/v5/client/clientserver_test.go b/v5/client/clientserver_test.go deleted file mode 100644 index 716c290..0000000 --- a/v5/client/clientserver_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package client - -import ( - "context" - "errors" - "testing" - "time" - - "github.com/CyCoreSystems/ari-proxy/v5/server" - rid "github.com/CyCoreSystems/ari-rid" - "github.com/CyCoreSystems/ari/v5" - "github.com/nats-io/nats.go" -) - -type srv struct { - s *server.Server -} - -func (s *srv) Start(ctx context.Context, t *testing.T, mockClient ari.Client, nc *nats.EncodedConn, completeCh chan struct{}) (ari.Client, error) { - s.s = server.New() - - // tests may run in parallel so we don't want two separate proxy servers to conflict. - s.s.NATSPrefix = rid.New("") + "." - - go func() { - if err := s.s.ListenOn(ctx, mockClient, nc); err != nil { - if err != context.Canceled { - t.Errorf("Failed to start server: %s", err) - } - } - close(completeCh) - }() - - select { - case <-s.s.Ready(): - case <-time.After(500 * time.Millisecond): - return nil, errors.New("Timeout waiting for server ready") - } - - cl, err := New(ctx, WithTimeoutRetries(4), WithPrefix(s.s.NATSPrefix), WithApplication("asdf")) - if err != nil { - return nil, err - } - - return cl, nil -} - -func (s *srv) Ready() <-chan struct{} { - return s.s.Ready() -} - -func (s *srv) Close() error { - return nil -} diff --git a/v5/client/cluster/cluster.go b/v5/client/cluster/cluster.go deleted file mode 100644 index 8a55efd..0000000 --- a/v5/client/cluster/cluster.go +++ /dev/null @@ -1,149 +0,0 @@ -package cluster - -import ( - "strings" - "sync" - "time" -) - -// AutoPurgeInterval is the maximum amount of time to wait before automatically purging the cluster of stale members -var AutoPurgeInterval = 24 * time.Hour - -// AutoPurgeAge is the maximum age allowed for members' last update when automatically purging. -var AutoPurgeAge = 12 * time.Hour - -// Cluster describes the set of ari proxies in a system. The list is indexed by a hash of the asterisk ID and the ARI application and indicates the time of last contact. -type Cluster struct { - lastPurge time.Time - - members map[string]time.Time - - mu sync.Mutex -} - -// New returns a new Cluster -func New() *Cluster { - return &Cluster{ - members: make(map[string]time.Time), - } -} - -// hash returns the key for a given proxy instance -func hash(id, app string) string { - return id + "|" + app -} - -// dehash returns the Asterisk ID and ARI application represented by the given key -func dehash(key string) (id string, app string) { - pieces := strings.Split(key, "|") - if len(pieces) < 2 { - return - } - return pieces[0], pieces[1] -} - -// Member describes the state of a Member of an application cluster -type Member struct { - // ID is the unique identifier for the Asterisk node - ID string - - // App indicates the ARI application of this proxy - App string - - // LastActive is the timestamp of the last occurrence of this node - LastActive time.Time -} - -// All returns a list of all cluster members whose LastActive time is no older thatn the given maxAge. -func (c *Cluster) All(maxAge time.Duration) (list []Member) { - c.mu.Lock() - defer c.mu.Unlock() - - for k, v := range c.members { - if maxAge == 0 || time.Since(v) < maxAge { - id, app := dehash(k) - list = append(list, Member{ - ID: id, - App: app, - LastActive: v, - }) - } - } - return -} - -// App returns a list of all cluster members for the given ARI Application whose LastActive time is no older than the given maxAge. -func (c *Cluster) App(app string, maxAge time.Duration) (list []Member) { - c.mu.Lock() - defer c.mu.Unlock() - - for k, v := range c.members { - i, a := dehash(k) - if app == a && (maxAge == 0 || time.Since(v) < maxAge) { - list = append(list, Member{ - ID: i, - App: a, - LastActive: v, - }) - } - } - return -} - -// Matching returns a list of all cluster members for whom the given proxy Metadata matches -func (c *Cluster) Matching(id, app string, maxAge time.Duration) (list []Member) { - c.mu.Lock() - defer c.mu.Unlock() - - for k, v := range c.members { - if time.Since(v) > maxAge { - continue - } - - i, a := dehash(k) - if id != "" && id != i { - continue - } - if app != "" && app != a { - continue - } - list = append(list, Member{ - ID: i, - App: a, - LastActive: v, - }) - } - return -} - -// Update adds (or updates) a proxy to/in the cluster -func (c *Cluster) Update(id, app string) { - c.mu.Lock() - c.members[hash(id, app)] = time.Now() - c.mu.Unlock() - - // See if it is time to auto-purge - if time.Since(c.lastPurge) > AutoPurgeInterval { - c.Purge(AutoPurgeAge) - } -} - -// Purge removes any proxies in the cluster which are older than the given maxAge. -func (c *Cluster) Purge(maxAge time.Duration) { - c.mu.Lock() - defer c.mu.Unlock() - - c.lastPurge = time.Now() - - var removalKeys []string - - for k, v := range c.members { - if maxAge == 0 || time.Since(v) > maxAge { - removalKeys = append(removalKeys, k) - } - } - - for _, key := range removalKeys { - delete(c.members, key) - } -} diff --git a/v5/client/cluster/cluster_test.go b/v5/client/cluster/cluster_test.go deleted file mode 100644 index 4328374..0000000 --- a/v5/client/cluster/cluster_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package cluster - -import ( - "strings" - "testing" - "time" - - rid "github.com/CyCoreSystems/ari-rid" -) - -func TestHash(t *testing.T) { - id := rid.New("") - app := rid.New("") - - testID, testApp := dehash(hash(id, app)) - if id != testID { - t.Error("Asterisk IDs do not match") - } - if app != testApp { - t.Error("ARI Applications do not match") - } -} - -func TestAll(t *testing.T) { - c := New() - c.Update("A1", "TestApp") - c.Update("A2", "TestApp") - - list := c.All(0) - if len(list) != 2 { - t.Errorf("Incorrect number of cluster members: %d != 2", len(list)) - } - - c.Update("B1", "TestApp2") - c.Update("B2", "TestApp2") - - list = c.All(0) - if len(list) != 4 { - t.Errorf("Incorrect number of cluster members: %d != 4", len(list)) - } -} - -func TestApp(t *testing.T) { - c := New() - c.Update("A1", "TestApp") - c.Update("A2", "TestApp") - c.Update("B1", "TestApp2") - c.Update("B2", "TestApp2") - - list := c.App("TestApp", 0) - if len(list) != 2 { - t.Errorf("Incorrect number of cluster members: %d != 2", len(list)) - } - if list[1].App != "TestApp" { - t.Errorf("Incorrect app: %s != TestApp", list[0].App) - } - if !strings.HasPrefix(list[0].ID, "A") { - t.Errorf("Incorrect ID: %s does not begin with A", list[1].ID) - } - - list = c.App("TestApp2", 0) - if len(list) != 2 { - t.Errorf("Incorrect number of cluster members: %d != 2", len(list)) - } - if list[0].App != "TestApp2" { - t.Errorf("Incorrect app: %s != TestApp2", list[0].App) - } - if !strings.HasPrefix(list[1].ID, "B") { - t.Errorf("Incorrect ID: %s does not begin with B", list[1].ID) - } -} - -func TestPurge(t *testing.T) { - c := New() - c.Update("A1", "TestApp") - c.Update("A2", "TestApp") - c.Update("B1", "TestApp2") - c.Update("B2", "TestApp2") - - list := c.All(0) - if len(list) != 4 { - t.Errorf("Incorrect number of cluster members: %d != 4", len(list)) - } - - c.Purge(50 * time.Millisecond) - - list = c.All(0) - if len(list) != 4 { - t.Errorf("Incorrect number of cluster members: %d != 4", len(list)) - } - - time.Sleep(50 * time.Millisecond) - - c.Update("B1", "TestApp2") - - c.Purge(45 * time.Millisecond) - - list = c.All(0) - if len(list) != 1 { - t.Errorf("Incorrect number of cluster members: %d != 1", len(list)) - } - - c.Update("A2", "TestApp") - - list = c.All(0) - if len(list) != 2 { - t.Errorf("Incorrect number of cluster members: %d != 2", len(list)) - } -} diff --git a/v5/client/config.go b/v5/client/config.go deleted file mode 100644 index 89dec4d..0000000 --- a/v5/client/config.go +++ /dev/null @@ -1,42 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type config struct { - c *Client -} - -func (c *config) Get(key *ari.Key) *ari.ConfigHandle { - return ari.NewConfigHandle(key, c) -} - -func (c *config) Data(key *ari.Key) (*ari.ConfigData, error) { - data, err := c.c.dataRequest(&proxy.Request{ - Kind: "AsteriskConfigData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.Config, nil -} - -func (c *config) Update(key *ari.Key, tuples []ari.ConfigTuple) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "AsteriskConfigUpdate", - Key: key, - AsteriskConfig: &proxy.AsteriskConfig{ - Tuples: tuples, - }, - }) -} - -func (c *config) Delete(key *ari.Key) error { - return c.c.commandRequest(&proxy.Request{ - Kind: "AsteriskConfigDelete", - Key: key, - }) -} diff --git a/v5/client/config_test.go b/v5/client/config_test.go deleted file mode 100644 index 5932aa0..0000000 --- a/v5/client/config_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestConfigData(t *testing.T) { - integration.TestConfigData(t, &srv{}) -} - -func TestConfigDelete(t *testing.T) { - integration.TestConfigDelete(t, &srv{}) -} - -func TestConfigUpdate(t *testing.T) { - integration.TestConfigUpdate(t, &srv{}) -} diff --git a/v5/client/device.go b/v5/client/device.go deleted file mode 100644 index d190991..0000000 --- a/v5/client/device.go +++ /dev/null @@ -1,57 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type deviceState struct { - c *Client -} - -func (ds *deviceState) Get(key *ari.Key) *ari.DeviceStateHandle { - k, err := ds.c.getRequest(&proxy.Request{ - Kind: "DeviceStateGet", - Key: key, - }) - if err != nil { - ds.c.log.Warn("failed to get device state for handle") - return ari.NewDeviceStateHandle(key, ds) - } - return ari.NewDeviceStateHandle(k, ds) -} - -func (ds *deviceState) List(filter *ari.Key) ([]*ari.Key, error) { - return ds.c.listRequest(&proxy.Request{ - Kind: "DeviceStateList", - Key: filter, - }) -} - -func (ds *deviceState) Data(key *ari.Key) (*ari.DeviceStateData, error) { - data, err := ds.c.dataRequest(&proxy.Request{ - Kind: "DeviceStateData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.DeviceState, nil -} - -func (ds *deviceState) Update(key *ari.Key, state string) error { - return ds.c.commandRequest(&proxy.Request{ - Kind: "DeviceStateUpdate", - Key: key, - DeviceStateUpdate: &proxy.DeviceStateUpdate{ - State: state, - }, - }) -} - -func (ds *deviceState) Delete(key *ari.Key) error { - return ds.c.commandRequest(&proxy.Request{ - Kind: "DeviceStateDelete", - Key: key, - }) -} diff --git a/v5/client/device_test.go b/v5/client/device_test.go deleted file mode 100644 index 7724ac3..0000000 --- a/v5/client/device_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestDeviceData(t *testing.T) { - integration.TestDeviceData(t, &srv{}) -} - -func TestDeviceDelete(t *testing.T) { - integration.TestDeviceDelete(t, &srv{}) -} - -func TestDeviceUpdate(t *testing.T) { - integration.TestDeviceUpdate(t, &srv{}) -} - -func TestDeviceList(t *testing.T) { - integration.TestDeviceList(t, &srv{}) -} diff --git a/v5/client/doc.go b/v5/client/doc.go deleted file mode 100644 index 9650286..0000000 --- a/v5/client/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package client provides an ari.Client implementation for a NATS-based ARI proxy cluster -package client diff --git a/v5/client/endpoint.go b/v5/client/endpoint.go deleted file mode 100644 index 7e3845e..0000000 --- a/v5/client/endpoint.go +++ /dev/null @@ -1,50 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type endpoint struct { - c *Client -} - -func (e *endpoint) Data(key *ari.Key) (*ari.EndpointData, error) { - data, err := e.c.dataRequest(&proxy.Request{ - Kind: "EndpointData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.Endpoint, nil -} - -func (e *endpoint) Get(key *ari.Key) *ari.EndpointHandle { - k, err := e.c.getRequest(&proxy.Request{ - Kind: "EndpointGet", - Key: key, - }) - if err != nil { - e.c.log.Warn("failed to get endpoint for handle", "error", err) - return ari.NewEndpointHandle(key, e) - } - return ari.NewEndpointHandle(k, e) -} - -func (e *endpoint) List(filter *ari.Key) ([]*ari.Key, error) { - return e.c.listRequest(&proxy.Request{ - Kind: "EndpointList", - Key: filter, - }) -} - -func (e *endpoint) ListByTech(tech string, filter *ari.Key) ([]*ari.Key, error) { - return e.c.listRequest(&proxy.Request{ - Kind: "EndpointListByTech", - Key: filter, - EndpointListByTech: &proxy.EndpointListByTech{ - Tech: tech, - }, - }) -} diff --git a/v5/client/endpoint_test.go b/v5/client/endpoint_test.go deleted file mode 100644 index 1adedec..0000000 --- a/v5/client/endpoint_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestEndpointList(t *testing.T) { - integration.TestEndpointList(t, &srv{}) -} - -func TestEndpointListByTech(t *testing.T) { - integration.TestEndpointListByTech(t, &srv{}) -} - -func TestEndpointData(t *testing.T) { - integration.TestEndpointData(t, &srv{}) -} diff --git a/v5/client/errors.go b/v5/client/errors.go deleted file mode 100644 index c3d40b8..0000000 --- a/v5/client/errors.go +++ /dev/null @@ -1,82 +0,0 @@ -package client - -import "errors" - -type wrappedError struct { - Message string - Err error -} - -func (err *wrappedError) Cause() error { - return err.Err -} - -func (err *wrappedError) Error() string { - return err.Message + ": " + err.Err.Error() -} - -// remote error, used wrap the error response before sending - -type codedError struct { - err error - code int -} - -func (err *codedError) Error() string { - return err.err.Error() -} - -func (err *codedError) Code() int { - return err.code -} - -type causer interface { - Cause() error -} - -type coded interface { - Code() int -} - -// ErrorToMap converts an error type to a key-value map -func ErrorToMap(err error, parent string) map[string]interface{} { - data := make(map[string]interface{}) - if parent == err.Error() { - // NOTE: this is done because of how errors.Wrap works, internally, - // to build a stacktrace. We end up with duplicate - // entries in the tree of errors. - if c, ok := err.(causer); ok { - return ErrorToMap(c.Cause(), parent) - } - } - data["message"] = err.Error() - if c, ok := err.(coded); ok { - data["code"] = c.Code() - } - if c, ok := err.(causer); ok { - data["cause"] = ErrorToMap(c.Cause(), data["message"].(string)) - } - return data -} - -// MapToError converts a JSON parsed map to an error type -func MapToError(i map[string]interface{}) error { - msg, _ := i["message"].(string) - code, codeOK := i["code"].(int) - cause, causeOK := i["cause"].(map[string]interface{}) - - err := errors.New(msg) - - if codeOK { - err = &codedError{err, code} - } - - if causeOK { - causeError := MapToError(cause) - l := len(msg) - len(causeError.Error()) - msg = msg[:l-2] - err = &wrappedError{msg, causeError} - } - - return err -} diff --git a/v5/client/listen.go b/v5/client/listen.go deleted file mode 100644 index 5e114ae..0000000 --- a/v5/client/listen.go +++ /dev/null @@ -1,63 +0,0 @@ -package client - -import ( - "context" - "fmt" - - "github.com/CyCoreSystems/ari/v5" - "github.com/nats-io/nats.go" - "github.com/pkg/errors" -) - -// ListenQueue is the queue group to use for distributing StasisStart events to Listeners. -var ListenQueue = "ARIProxyStasisStartDistributorQueue" - -// Listen listens for StasisStart events, filtered by the given key. Any -// matching events will be sent down the returned StasisStart channel. The -// context which is passed to Listen can be used to stop the Listen execution. -// -// Importantly, the StasisStart events are listened in a NATS Queue, which -// means that this may be used to deliver new calls to only a single handler -// out of a set of 1 or more handlers in a cluster. -func Listen(ctx context.Context, ac ari.Client, h func(*ari.ChannelHandle, *ari.StasisStart)) error { - c, ok := ac.(*Client) - if !ok { - return errors.New("ARI Client must be a proxy client") - } - - subj := fmt.Sprintf("%sevent.%s.>", c.core.prefix, c.ApplicationName()) - - c.log.Debug("listening for events", "subject", subj) - sub, err := c.nc.QueueSubscribe(subj, ListenQueue, listenProcessor(ac, h)) - if err != nil { - return errors.Wrap(err, "failed to subscribe to events") - } - defer sub.Unsubscribe() // nolint: errcheck - - <-ctx.Done() - - return nil -} - -func listenProcessor(ac ari.Client, h func(*ari.ChannelHandle, *ari.StasisStart)) func(*nats.Msg) { - return func(m *nats.Msg) { - e, err := ari.DecodeEvent(m.Data) - if err != nil { - Logger.Error("failed to decode event", "error", err) - return - } - - Logger.Debug("received event", e.GetType()) - if e.GetType() != "StasisStart" { - return - } - - v, ok := e.(*ari.StasisStart) - if !ok { - Logger.Error("failed to type-assert StasisStart event") - return - } - - h(ari.NewChannelHandle(v.Key(ari.ChannelKey, v.Channel.ID), ac.Channel(), nil), v) - } -} diff --git a/v5/client/liveRecording.go b/v5/client/liveRecording.go deleted file mode 100644 index 496480d..0000000 --- a/v5/client/liveRecording.go +++ /dev/null @@ -1,95 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type liveRecording struct { - c *Client -} - -func (l *liveRecording) Get(key *ari.Key) *ari.LiveRecordingHandle { - k, err := l.c.getRequest(&proxy.Request{ - Kind: "RecordingLiveGet", - Key: key, - }) - if err != nil { - l.c.log.Warn("failed to get liveRecording for handle", "error", err) - return ari.NewLiveRecordingHandle(key, l, nil) - } - return ari.NewLiveRecordingHandle(k, l, nil) -} - -func (l *liveRecording) Data(key *ari.Key) (*ari.LiveRecordingData, error) { - data, err := l.c.dataRequest(&proxy.Request{ - Kind: "RecordingLiveData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.LiveRecording, nil -} - -func (l *liveRecording) Stop(key *ari.Key) error { - return l.c.commandRequest(&proxy.Request{ - Kind: "RecordingLiveStop", - Key: key, - }) -} - -func (l *liveRecording) Pause(key *ari.Key) error { - return l.c.commandRequest(&proxy.Request{ - Kind: "RecordingLivePause", - Key: key, - }) -} - -func (l *liveRecording) Resume(key *ari.Key) error { - return l.c.commandRequest(&proxy.Request{ - Kind: "RecordingLiveResume", - Key: key, - }) -} - -func (l *liveRecording) Mute(key *ari.Key) error { - return l.c.commandRequest(&proxy.Request{ - Kind: "RecordingLiveMute", - Key: key, - }) -} - -func (l *liveRecording) Unmute(key *ari.Key) error { - return l.c.commandRequest(&proxy.Request{ - Kind: "RecordingLiveUnmute", - Key: key, - }) -} - -func (l *liveRecording) Scrap(key *ari.Key) error { - return l.c.commandRequest(&proxy.Request{ - Kind: "RecordingLiveScrap", - Key: key, - }) -} - -func (l *liveRecording) Stored(key *ari.Key) *ari.StoredRecordingHandle { - return ari.NewStoredRecordingHandle(key.New(ari.StoredRecordingKey, key.ID), l.c.StoredRecording(), nil) -} - -func (l *liveRecording) Subscribe(key *ari.Key, n ...string) ari.Subscription { - err := l.c.commandRequest(&proxy.Request{ - Kind: "RecordingLiveSubscribe", - Key: key, - }) - if err != nil { - l.c.log.Warn("failed to call liveRecording Subscribe") - if key.Dialog != "" { - l.c.log.Error("dialog present; failing") - return nil - } - } - - return l.c.Bus().Subscribe(key, n...) -} diff --git a/v5/client/liveRecording_test.go b/v5/client/liveRecording_test.go deleted file mode 100644 index 70de5e2..0000000 --- a/v5/client/liveRecording_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestLiveRecordingData(t *testing.T) { - integration.TestLiveRecordingData(t, &srv{}) -} - -/* -func TestLiveRecordingDelete(t *testing.T) { - integration.TestLiveRecordingDelete(t, &srv{}) -} -*/ - -func TestLiveRecordingMute(t *testing.T) { - integration.TestLiveRecordingMute(t, &srv{}) -} - -func TestLiveRecordingUnmute(t *testing.T) { - integration.TestLiveRecordingUnmute(t, &srv{}) -} - -func TestLiveRecordingPause(t *testing.T) { - integration.TestLiveRecordingPause(t, &srv{}) -} - -func TestLiveRecordingStop(t *testing.T) { - integration.TestLiveRecordingStop(t, &srv{}) -} - -func TestLiveRecordingResume(t *testing.T) { - integration.TestLiveRecordingResume(t, &srv{}) -} - -func TestLiveRecordingScrap(t *testing.T) { - integration.TestLiveRecordingScrap(t, &srv{}) -} diff --git a/v5/client/logger.go b/v5/client/logger.go deleted file mode 100644 index 65a646e..0000000 --- a/v5/client/logger.go +++ /dev/null @@ -1,15 +0,0 @@ -package client - -import "github.com/inconshreveable/log15" - -// Logger defaults to a discard handler (null output). -// If you wish to enable logging, you can set your own -// handler like so: -// ari.Logger.SetHandler(log15.StderrHandler) -// -var Logger = log15.New() - -func init() { - // Null logger, by default - Logger.SetHandler(log15.DiscardHandler()) -} diff --git a/v5/client/logging.go b/v5/client/logging.go deleted file mode 100644 index 6844cbb..0000000 --- a/v5/client/logging.go +++ /dev/null @@ -1,68 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type logging struct { - c *Client -} - -func (l *logging) Create(key *ari.Key, levels string) (*ari.LogHandle, error) { - k, err := l.c.createRequest(&proxy.Request{ - Kind: "AsteriskLoggingCreate", - Key: key, - AsteriskLoggingChannel: &proxy.AsteriskLoggingChannel{ - Levels: levels, - }, - }) - if err != nil { - return nil, err - } - return ari.NewLogHandle(k, l), nil -} - -func (l *logging) Data(key *ari.Key) (*ari.LogData, error) { - data, err := l.c.dataRequest(&proxy.Request{ - Kind: "AsteriskLoggingData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.Log, nil -} - -func (l *logging) Get(key *ari.Key) *ari.LogHandle { - k, err := l.c.getRequest(&proxy.Request{ - Kind: "AsteriskLoggingGet", - Key: key, - }) - if err != nil { - l.c.log.Warn("failed to get logging key for handle", "error", err) - return ari.NewLogHandle(key, l) - } - return ari.NewLogHandle(k, l) -} - -func (l *logging) List(filter *ari.Key) ([]*ari.Key, error) { - return l.c.listRequest(&proxy.Request{ - Kind: "AsteriskLoggingList", - Key: filter, - }) -} - -func (l *logging) Rotate(key *ari.Key) error { - return l.c.commandRequest(&proxy.Request{ - Kind: "AsteriskLoggingRotate", - Key: key, - }) -} - -func (l *logging) Delete(key *ari.Key) error { - return l.c.commandRequest(&proxy.Request{ - Kind: "AsteriskLoggingDelete", - Key: key, - }) -} diff --git a/v5/client/logging_test.go b/v5/client/logging_test.go deleted file mode 100644 index cebbfda..0000000 --- a/v5/client/logging_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestLoggingList(t *testing.T) { - integration.TestLoggingList(t, &srv{}) -} - -func TestLoggingCreate(t *testing.T) { - integration.TestLoggingCreate(t, &srv{}) -} - -func TestLoggingRotate(t *testing.T) { - integration.TestLoggingRotate(t, &srv{}) -} - -func TestLoggingDelete(t *testing.T) { - integration.TestLoggingDelete(t, &srv{}) -} diff --git a/v5/client/mailbox.go b/v5/client/mailbox.go deleted file mode 100644 index 633e724..0000000 --- a/v5/client/mailbox.go +++ /dev/null @@ -1,58 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type mailbox struct { - c *Client -} - -func (m *mailbox) Get(key *ari.Key) *ari.MailboxHandle { - k, err := m.c.getRequest(&proxy.Request{ - Kind: "MailboxGet", - Key: key, - }) - if err != nil { - m.c.log.Warn("failed to get bridge for handle", "error", err) - return ari.NewMailboxHandle(key, m) - } - return ari.NewMailboxHandle(k, m) -} - -func (m *mailbox) List(filter *ari.Key) ([]*ari.Key, error) { - return m.c.listRequest(&proxy.Request{ - Kind: "MailboxList", - Key: filter, - }) -} - -func (m *mailbox) Data(key *ari.Key) (*ari.MailboxData, error) { - data, err := m.c.dataRequest(&proxy.Request{ - Kind: "MailboxData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.Mailbox, nil -} - -func (m *mailbox) Update(key *ari.Key, oldMessages int, newMessages int) error { - return m.c.commandRequest(&proxy.Request{ - Kind: "MailboxUpdate", - Key: key, - MailboxUpdate: &proxy.MailboxUpdate{ - New: newMessages, - Old: oldMessages, - }, - }) -} - -func (m *mailbox) Delete(key *ari.Key) error { - return m.c.commandRequest(&proxy.Request{ - Kind: "MailboxDelete", - Key: key, - }) -} diff --git a/v5/client/mailbox_test.go b/v5/client/mailbox_test.go deleted file mode 100644 index 2aeddc3..0000000 --- a/v5/client/mailbox_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestMailboxList(t *testing.T) { - integration.TestMailboxList(t, &srv{}) -} - -func TestMailboxUpdate(t *testing.T) { - integration.TestMailboxUpdate(t, &srv{}) -} - -func TestMailboxDelete(t *testing.T) { - integration.TestMailboxDelete(t, &srv{}) -} - -func TestMailboxData(t *testing.T) { - integration.TestMailboxData(t, &srv{}) -} diff --git a/v5/client/modules.go b/v5/client/modules.go deleted file mode 100644 index 9e9eee5..0000000 --- a/v5/client/modules.go +++ /dev/null @@ -1,61 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type modules struct { - c *Client -} - -func (m *modules) Data(key *ari.Key) (*ari.ModuleData, error) { - data, err := m.c.dataRequest(&proxy.Request{ - Kind: "AsteriskModuleData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.Module, nil -} - -func (m *modules) Get(key *ari.Key) *ari.ModuleHandle { - k, err := m.c.getRequest(&proxy.Request{ - Kind: "AsteriskModuleGet", - Key: key, - }) - if err != nil { - m.c.log.Warn("failed to get module for handle", "error", err) - return ari.NewModuleHandle(key, m) - } - return ari.NewModuleHandle(k, m) -} - -func (m *modules) List(filter *ari.Key) ([]*ari.Key, error) { - return m.c.listRequest(&proxy.Request{ - Kind: "AsteriskModuleList", - Key: filter, - }) -} - -func (m *modules) Load(key *ari.Key) error { - return m.c.commandRequest(&proxy.Request{ - Kind: "AsteriskModuleLoad", - Key: key, - }) -} - -func (m *modules) Reload(key *ari.Key) error { - return m.c.commandRequest(&proxy.Request{ - Kind: "AsteriskModuleReload", - Key: key, - }) -} - -func (m *modules) Unload(key *ari.Key) error { - return m.c.commandRequest(&proxy.Request{ - Kind: "AsteriskModuleUnload", - Key: key, - }) -} diff --git a/v5/client/modules_test.go b/v5/client/modules_test.go deleted file mode 100644 index fbeb25b..0000000 --- a/v5/client/modules_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestModulesData(t *testing.T) { - integration.TestModulesData(t, &srv{}) -} - -func TestModulesLoad(t *testing.T) { - integration.TestModulesLoad(t, &srv{}) -} - -func TestModulesReload(t *testing.T) { - integration.TestModulesReload(t, &srv{}) -} - -func TestModulesUnload(t *testing.T) { - integration.TestModulesUnload(t, &srv{}) -} - -func TestModulesList(t *testing.T) { - integration.TestModulesList(t, &srv{}) -} diff --git a/v5/client/playback.go b/v5/client/playback.go deleted file mode 100644 index b13345b..0000000 --- a/v5/client/playback.go +++ /dev/null @@ -1,65 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type playback struct { - c *Client -} - -func (p *playback) Get(key *ari.Key) *ari.PlaybackHandle { - k, err := p.c.getRequest(&proxy.Request{ - Kind: "PlaybackGet", - Key: key, - }) - if err != nil { - p.c.log.Warn("failed to get playback for handle", "error", err) - return ari.NewPlaybackHandle(key, p, nil) - } - return ari.NewPlaybackHandle(k, p, nil) -} - -func (p *playback) Data(key *ari.Key) (*ari.PlaybackData, error) { - data, err := p.c.dataRequest(&proxy.Request{ - Kind: "PlaybackData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.Playback, nil -} - -func (p *playback) Control(key *ari.Key, op string) error { - return p.c.commandRequest(&proxy.Request{ - Kind: "PlaybackControl", - Key: key, - PlaybackControl: &proxy.PlaybackControl{ - Command: op, - }, - }) -} - -func (p *playback) Stop(key *ari.Key) error { - return p.c.commandRequest(&proxy.Request{ - Kind: "PlaybackStop", - Key: key, - }) -} - -func (p *playback) Subscribe(key *ari.Key, n ...string) ari.Subscription { - err := p.c.commandRequest(&proxy.Request{ - Kind: "PlaybackSubscribe", - Key: key, - }) - if err != nil { - p.c.log.Warn("failed to call bridge subscribe", "error", err) - if key.Dialog != "" { - p.c.log.Error("dialog present; failing", "error", err) - return nil - } - } - return p.c.Bus().Subscribe(key, n...) -} diff --git a/v5/client/playback_test.go b/v5/client/playback_test.go deleted file mode 100644 index 289c7f4..0000000 --- a/v5/client/playback_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestPlaybackData(t *testing.T) { - integration.TestPlaybackData(t, &srv{}) -} - -func TestPlaybackControl(t *testing.T) { - integration.TestPlaybackControl(t, &srv{}) -} - -func TestPlaybackStop(t *testing.T) { - integration.TestPlaybackStop(t, &srv{}) -} diff --git a/v5/client/request.go b/v5/client/request.go deleted file mode 100644 index da13c8e..0000000 --- a/v5/client/request.go +++ /dev/null @@ -1 +0,0 @@ -package client diff --git a/v5/client/sound.go b/v5/client/sound.go deleted file mode 100644 index 5ed0e26..0000000 --- a/v5/client/sound.go +++ /dev/null @@ -1,31 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type sound struct { - c *Client -} - -func (s *sound) List(filters map[string]string, keyFilter *ari.Key) ([]*ari.Key, error) { - return s.c.listRequest(&proxy.Request{ - Kind: "SoundList", - Key: keyFilter, - SoundList: &proxy.SoundList{ - Filters: filters, - }, - }) -} - -func (s *sound) Data(key *ari.Key) (*ari.SoundData, error) { - data, err := s.c.dataRequest(&proxy.Request{ - Kind: "SoundData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.Sound, nil -} diff --git a/v5/client/sound_test.go b/v5/client/sound_test.go deleted file mode 100644 index 68b6a9a..0000000 --- a/v5/client/sound_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package client - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestSoundData(t *testing.T) { - integration.TestSoundData(t, &srv{}) -} - -func TestSoundList(t *testing.T) { - integration.TestSoundList(t, &srv{}) -} diff --git a/v5/client/storedRecording.go b/v5/client/storedRecording.go deleted file mode 100644 index 1c6f9cc..0000000 --- a/v5/client/storedRecording.go +++ /dev/null @@ -1,62 +0,0 @@ -package client - -import ( - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari/v5" -) - -type storedRecording struct { - c *Client -} - -func (s *storedRecording) List(filter *ari.Key) ([]*ari.Key, error) { - return s.c.listRequest(&proxy.Request{ - Kind: "RecordingStoredList", - Key: filter, - }) -} - -func (s *storedRecording) Get(key *ari.Key) *ari.StoredRecordingHandle { - k, err := s.c.getRequest(&proxy.Request{ - Kind: "RecordingStoredGet", - Key: key, - }) - if err != nil { - s.c.log.Warn("failed to get stored recording for handle", "error", err) - return ari.NewStoredRecordingHandle(key, s, nil) - } - return ari.NewStoredRecordingHandle(k, s, nil) -} - -func (s *storedRecording) Data(key *ari.Key) (*ari.StoredRecordingData, error) { - data, err := s.c.dataRequest(&proxy.Request{ - Kind: "RecordingStoredData", - Key: key, - }) - if err != nil { - return nil, err - } - return data.StoredRecording, nil -} - -func (s *storedRecording) Copy(key *ari.Key, dest string) (*ari.StoredRecordingHandle, error) { - h := ari.NewStoredRecordingHandle(key.New(ari.StoredRecordingKey, dest), s, nil) - - err := s.c.commandRequest(&proxy.Request{ - Kind: "RecordingStoredCopy", - Key: key, - RecordingStoredCopy: &proxy.RecordingStoredCopy{ - Destination: dest, - }, - }) - - // NOTE: Always return the handle, even when we have an error - return h, err -} - -func (s *storedRecording) Delete(key *ari.Key) error { - return s.c.commandRequest(&proxy.Request{ - Kind: "RecordingStoredDelete", - Key: key, - }) -} diff --git a/v5/client/subscription.go b/v5/client/subscription.go deleted file mode 100644 index 2cad74c..0000000 --- a/v5/client/subscription.go +++ /dev/null @@ -1,54 +0,0 @@ -package client - -/* -type natsSubscription struct { - m ari.Matcher - closeChan chan struct{} - closed bool - events chan ari.Event -} - -func newSubscription(m ari.Matcher) *natsSubscription { - return &natsSubscription{ - m: m, - closeChan: make(chan struct{}), - events: make(chan ari.Event, 10), - } -} - -func (ns *natsSubscription) Start(s ari.Subscriber, n ...string) { - - sub := s.Subscribe(n...) - - go func() { - defer sub.Cancel() - for { - select { - case <-ns.closeChan: - return - case evt, ok := <-sub.Events(): - if !ok { - ns.Cancel() - continue - } - if ns.m == nil { - ns.events <- evt - } else if ns.m.Match(evt) { - ns.events <- evt - } - } - } - }() -} - -func (ns *natsSubscription) Events() chan ari.Event { - return ns.events -} - -func (ns *natsSubscription) Cancel() { - if !ns.closed && ns.closeChan != nil { - ns.closed = true - close(ns.closeChan) - } -} -*/ diff --git a/v5/cmd.go b/v5/cmd.go deleted file mode 100644 index 2dbb4ae..0000000 --- a/v5/cmd.go +++ /dev/null @@ -1,117 +0,0 @@ -package main - -import ( - "context" - "fmt" - "os" - "strings" - - "github.com/CyCoreSystems/ari-proxy/v5/server" - "github.com/CyCoreSystems/ari/v5/client/native" - - "github.com/inconshreveable/log15" - "github.com/nats-io/nats.go" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -// Log is the package logger -var Log log15.Logger - -// RootCmd is the Cobra root command descriptor -var RootCmd = &cobra.Command{ - Use: "ari-proxy", - Short: "Proxy for the Asterisk REST interface.", - Long: `ari-proxy is a proxy for working the Asterisk daemon over NATS. - ARI commands are exposed over NATS for operation.`, - RunE: func(cmd *cobra.Command, args []string) error { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - if ok, _ := cmd.PersistentFlags().GetBool("version"); ok { // nolint: gas - fmt.Println(version) - os.Exit(0) - } - - handler := log15.StdoutHandler - if viper.GetBool("verbose") { - Log.Info("verbose logging enabled") - handler = log15.LvlFilterHandler(log15.LvlDebug, handler) - } else { - handler = log15.LvlFilterHandler(log15.LvlInfo, handler) - } - Log.SetHandler(handler) - - native.Logger.SetHandler(handler) - - return runServer(ctx, Log) - }, -} - -var cfgFile string - -func init() { - Log = log15.New() - - cobra.OnInitialize(readConfig) - - p := RootCmd.PersistentFlags() - - p.BoolP("version", "V", false, "Print version information and exit") - - p.StringVar(&cfgFile, "config", "", "config file (default is $HOME/.ari-proxy.yaml)") - p.BoolP("verbose", "v", false, "Enable verbose logging") - - p.String("nats.url", nats.DefaultURL, "URL for connecting to the NATS cluster") - p.String("ari.application", "", "ARI Stasis Application") - p.String("ari.username", "", "Username for connecting to ARI") - p.String("ari.password", "", "Password for connecting to ARI") - p.String("ari.http_url", "http://localhost:8088/ari", "HTTP Base URL for connecting to ARI") - p.String("ari.websocket_url", "ws://localhost:8088/ari/events", "Websocket URL for connecting to ARI") - - for _, n := range []string{"verbose", "nats.url", "ari.application", "ari.username", "ari.password", "ari.http_url", "ari.websocket_url"} { - err := viper.BindPFlag(n, p.Lookup(n)) - if err != nil { - panic("failed to bind flag " + n) - } - } -} - -// readConfig reads in config file and ENV variables if set. -func readConfig() { - viper.SetConfigName(".ari-proxy") // name of config file (without extension) - viper.AddConfigPath("$HOME") // adding home directory as first search path - - if cfgFile != "" { // enable ability to specify config file via flag - viper.SetConfigFile(cfgFile) - } - - // Load from the environment, as well - viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) - viper.AutomaticEnv() // read in environment variables that match - - // If a config file is found, read it in. - err := viper.ReadInConfig() - if err == nil { - Log.Debug("read configuration from file") - } -} - -func runServer(ctx context.Context, log log15.Logger) error { - natsURL := viper.GetString("nats.url") - if os.Getenv("NATS_SERVICE_HOST") != "" { - natsURL = "nats://" + os.Getenv("NATS_SERVICE_HOST") + ":" + os.Getenv("NATS_SERVICE_PORT_CLIENT") - } - - srv := server.New() - srv.Log = log - - log.Info("starting ari-proxy server", "version", version) - return srv.Listen(ctx, &native.Options{ - Application: viper.GetString("ari.application"), - Username: viper.GetString("ari.username"), - Password: viper.GetString("ari.password"), - URL: viper.GetString("ari.http_url"), - WebsocketURL: viper.GetString("ari.websocket_url"), - }, natsURL) -} diff --git a/v5/go.mod b/v5/go.mod deleted file mode 100644 index e3a494d..0000000 --- a/v5/go.mod +++ /dev/null @@ -1,28 +0,0 @@ -module github.com/CyCoreSystems/ari-proxy/v5 - -go 1.13 - -require ( - github.com/BurntSushi/toml v0.3.1 // indirect - github.com/CyCoreSystems/ari-rid v0.1.0 - github.com/CyCoreSystems/ari/v5 v5.0.2 - github.com/fsnotify/fsnotify v0.0.0-20170329110642-4da3e2cfbabc // indirect - github.com/gogo/protobuf v1.3.1 // indirect - github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e // indirect - github.com/inconshreveable/log15 v0.0.0-20171019012758-0decfc6c20d9 - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/magiconair/properties v1.7.3 // indirect - github.com/mattn/go-colorable v0.1.6 // indirect - github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992 // indirect - github.com/nats-io/nats-server/v2 v2.0.0 // indirect - github.com/nats-io/nats.go v1.8.1 - github.com/pelletier/go-toml v0.0.0-20170817000623-4692b8f9babf // indirect - github.com/pkg/errors v0.8.1 - github.com/spf13/afero v0.0.0-20170217164146-9be650865eab // indirect - github.com/spf13/cast v1.1.0 // indirect - github.com/spf13/cobra v0.0.2 - github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046 // indirect - github.com/spf13/pflag v1.0.0 // indirect - github.com/spf13/viper v1.0.2 - github.com/stretchr/testify v1.4.0 -) diff --git a/v5/go.sum b/v5/go.sum deleted file mode 100644 index cface7f..0000000 --- a/v5/go.sum +++ /dev/null @@ -1,108 +0,0 @@ -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/CyCoreSystems/ari-rid v0.1.0 h1:QSn7/1Jc0b3Se/LIaMa9taGxC9n/zyBlCEw9Conrdrk= -github.com/CyCoreSystems/ari-rid v0.1.0/go.mod h1:vFD6moqOBGXaUM28Yck9X16+5cj+NbFmiyCvpUYuKr4= -github.com/CyCoreSystems/ari/v5 v5.0.2 h1:m571GpaqACJxkkL8uU0mDzZFy6jo9twuzX6Crwfjccw= -github.com/CyCoreSystems/ari/v5 v5.0.2/go.mod h1:5fdxhNmHG+sUJkeIgPfMafi7d7Ec1B8QpPSCFvDDVc0= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v0.0.0-20170329110642-4da3e2cfbabc h1:fqUzyjP8DApxXq0dOZJE/NvqQkyjxiTy9ARNyRwBPEw= -github.com/fsnotify/fsnotify v0.0.0-20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e h1:KJWs1uTCkN3E/J5ofCH9Pf8KKsibTFc3fv0CA9+WsVo= -github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= -github.com/inconshreveable/log15 v0.0.0-20171019012758-0decfc6c20d9 h1:LmBUkXNSSmEV5hExb65hKje7sDuuDug3xsPAba7x5fw= -github.com/inconshreveable/log15 v0.0.0-20171019012758-0decfc6c20d9/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.7.3 h1:6AOjgCKyZFMG/1yfReDPDz3CJZPxnYk7DGmj2HtyF24= -github.com/magiconair/properties v1.7.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992 h1:W7VHAEVflA5/eTyRvQ53Lz5j8bhRd1myHZlI/IZFvbU= -github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/nats-io/jwt v0.2.6 h1:eAyoYvGgGLXR2EpnsBUvi/FcFrBqN6YKFVbOoEfPN4k= -github.com/nats-io/jwt v0.2.6/go.mod h1:mQxQ0uHQ9FhEVPIcTSKwx2lqZEpXWWcCgA7R6NrWvvY= -github.com/nats-io/nats-server/v2 v2.0.0 h1:rbFV7gfUPErVdKImVMOlW8Qb1V22nlcpqup5cb9rYa8= -github.com/nats-io/nats-server/v2 v2.0.0/go.mod h1:RyVdsHHvY4B6c9pWG+uRLpZ0h0XsqiuKp2XCTurP5LI= -github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ= -github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= -github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M= -github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/pelletier/go-toml v0.0.0-20170817000623-4692b8f9babf h1:XjB5kVAWxe9qH3eZIUfsW4gLh7prYlRJmZ5zRjyvCeg= -github.com/pelletier/go-toml v0.0.0-20170817000623-4692b8f9babf/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/spf13/afero v0.0.0-20170217164146-9be650865eab h1:IVAbBHQR8rXL2Fc8Zba/lMF7KOnTi70lqdx91UTuAwQ= -github.com/spf13/afero v0.0.0-20170217164146-9be650865eab/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.1.0 h1:0Rhw4d6C8J9VPu6cjZLIhZ8+aAOHcDvGeKn+cq5Aq3k= -github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cobra v0.0.2 h1:NfkwRbgViGoyjBKsLI0QMDcuMnhM+SBg3T0cGfpvKDE= -github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046 h1:RpxSq53NruItMGgp6q5MsDYoZynisJgEpisQdWJ7PyM= -github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.0 h1:oaPbdDe/x0UncahuwiPxW1GYJyilRAdsPnq3e1yaPcI= -github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso= -github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/v5/internal/integration/application.go b/v5/internal/integration/application.go deleted file mode 100644 index 00b88b3..0000000 --- a/v5/internal/integration/application.go +++ /dev/null @@ -1,156 +0,0 @@ -package integration - -import ( - "testing" - - "github.com/CyCoreSystems/ari/v5" - "github.com/pkg/errors" - tmock "github.com/stretchr/testify/mock" -) - -func TestApplicationList(t *testing.T, s Server) { - runTest("emptyList", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Application.On("List", (*ari.Key)(nil)).Return([]*ari.Key{}, nil) - - if _, err := cl.Application().List(nil); err != nil { - t.Errorf("Unexpected error in remote List call: %v", err) - } - }) - - runTest("nonEmptyList", t, s, func(t *testing.T, m *mock, cl ari.Client) { - h1 := ari.NewKey(ari.ApplicationKey, "1") - h2 := ari.NewKey(ari.ApplicationKey, "2") - m.Application.On("List", (*ari.Key)(nil)).Return([]*ari.Key{h1, h2}, nil) - - items, err := cl.Application().List(nil) - if err != nil { - t.Errorf("Unexpected error in remote List call: %v", err) - } - if len(items) != 2 { - t.Errorf("Expected items to be length 2, got %d", len(items)) - } else { - if items[0].ID != "1" { - t.Errorf("Expected item 0 to be '1', got %s", items[0].ID) - } - if items[1].ID != "2" { - t.Errorf("Expected item 1 to be '2', got %s", items[1].ID) - } - } - }) -} - -func TestApplicationData(t *testing.T, s Server) { - key := ari.NewKey(ari.ApplicationKey, "1") - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - ad := &ari.ApplicationData{} - ad.Name = "app1" - - m.Application.On("Data", tmock.Anything).Return(ad, nil) - - res, err := cl.Application().Data(key) - if err != nil { - t.Errorf("Unexpected error in remote Data call: %v", err) - } - if res == nil || res.Name != ad.Name { - t.Errorf("Expected application data name %s, got %s", ad, res) - } - - m.Shutdown() - m.Application.AssertCalled(t, "Data", key) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("unknown error") - - m.Application.On("Data", key).Return(nil, expected) - - res, err := cl.Application().Data(key) - if err == nil || errors.Cause(err).Error() != expected.Error() { - t.Errorf("Expected error '%v', got '%v'", expected, err) - } - if res != nil { - t.Errorf("Expected application data result to be empty, got %s", res) - } - - m.Shutdown() - - m.Application.AssertCalled(t, "Data", key) - }) -} - -func TestApplicationSubscribe(t *testing.T, s Server) { - key := ari.NewKey(ari.ApplicationKey, "1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Application.On("Subscribe", key, "2").Return(nil) - - if err := cl.Application().Subscribe(key, "2"); err != nil { - t.Errorf("Unexpected error in remote Subscribe call: %v", err) - } - - m.Shutdown() - - m.Application.AssertCalled(t, "Subscribe", key, "2") - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("unknown error") - - m.Application.On("Subscribe", key, "2").Return(expected) - - if err := cl.Application().Subscribe(key, "2"); err == nil || errors.Cause(err).Error() != expected.Error() { - t.Errorf("Expected error '%v', got '%v'", expected, err) - } - - m.Shutdown() - - m.Application.AssertCalled(t, "Subscribe", key, "2") - }) -} - -func TestApplicationUnsubscribe(t *testing.T, s Server) { - key := ari.NewKey(ari.ApplicationKey, "1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Application.On("Unsubscribe", key, "2").Return(nil) - - if err := cl.Application().Unsubscribe(key, "2"); err != nil { - t.Errorf("Unexpected error in remote Unsubscribe call: %T", err) - } - - m.Shutdown() - - m.Application.AssertCalled(t, "Unsubscribe", key, "2") - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("unknown error") - - m.Application.On("Unsubscribe", key, "2").Return(expected) - - if err := cl.Application().Unsubscribe(key, "2"); err == nil || errors.Cause(err).Error() != expected.Error() { - t.Errorf("Expected error '%v', got '%v'", expected, err) - } - - m.Application.AssertCalled(t, "Unsubscribe", key, "2") - }) -} - -func TestApplicationGet(t *testing.T, s Server) { - key := ari.NewKey(ari.ApplicationKey, "1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - ad := &ari.ApplicationData{} - ad.Name = "app1" - - m.Application.On("Data", tmock.Anything).Return(ad, nil) - - if h := cl.Application().Get(key); h == nil { - t.Errorf("Unexpected nil-handle") - } - - m.Shutdown() - - m.Application.AssertCalled(t, "Data", key) - }) -} diff --git a/v5/internal/integration/asterisk.go b/v5/internal/integration/asterisk.go deleted file mode 100644 index 07dc0d6..0000000 --- a/v5/internal/integration/asterisk.go +++ /dev/null @@ -1,138 +0,0 @@ -package integration - -import ( - "testing" - - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/client/arimocks" - "github.com/pkg/errors" -) - -func TestAsteriskInfo(t *testing.T, s Server) { - runTest("noFilter", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var ai ari.AsteriskInfo - ai.SystemInfo.EntityID = "1" - - m.Asterisk.On("Info", ari.NodeKey("asdf", "1")).Return(&ai, nil) - - ret, err := cl.Asterisk().Info(ari.NodeKey("asdf", "1")) - if err != nil { - t.Errorf("Unexpected error in remote Info call: %v", err) - } - if ret == nil || ret.SystemInfo.EntityID != ai.SystemInfo.EntityID { - t.Errorf("Expected asterisk info %v, got %v", ai, ret) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Info", ari.NodeKey("asdf", "1")) - }) - - runTest("noFilterError", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("unknown error") - - m.Asterisk.On("Info", ari.NodeKey("asdf", "1")).Return(nil, expected) - - ret, err := cl.Asterisk().Info(ari.NodeKey("asdf", "1")) - if err == nil || errors.Cause(err).Error() != expected.Error() { - t.Errorf("Expected error '%v', got '%v'", expected, err) - } - if ret != nil { - t.Errorf("Expected nil ret, got '%v'", ret) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Info", ari.NodeKey("asdf", "1")) - }) -} - -func TestAsteriskVariablesGet(t *testing.T, s Server) { - key := ari.NewKey(ari.VariableKey, "s") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var ai ari.AsteriskInfo - ai.SystemInfo.EntityID = "1" - - mv := arimocks.AsteriskVariables{} - mv.On("Get", key).Return("hello", nil) - m.Asterisk.On("Variables").Return(&mv) - - ret, err := cl.Asterisk().Variables().Get(key) - if err != nil { - t.Errorf("Unexpected error in remote Variables Get call: %v", err) - } - if ret != "hello" { - t.Errorf("Expected Variables Get return %v, got %v", "hello", ret) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Variables") - mv.AssertCalled(t, "Get", key) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("unknown error") - - mv := arimocks.AsteriskVariables{} - mv.On("Get", key).Return("", expected) - - m.Asterisk.On("Variables").Return(&mv) - - ret, err := cl.Asterisk().Variables().Get(key) - if err == nil || errors.Cause(err).Error() != expected.Error() { - t.Errorf("Expected error '%v', got '%v'", expected, err) - } - if ret != "" { - t.Errorf("Expected Variables Get return %v, got %v", "", ret) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Variables") - mv.AssertCalled(t, "Get", key) - }) -} - -func TestAsteriskVariablesSet(t *testing.T, s Server) { - key := ari.NewKey(ari.VariableKey, "s") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var ai ari.AsteriskInfo - ai.SystemInfo.EntityID = "1" - - mv := arimocks.AsteriskVariables{} - m.Asterisk.On("Variables").Return(&mv) - mv.On("Set", key, "hello").Return(nil) - - err := cl.Asterisk().Variables().Set(key, "hello") - if err != nil { - t.Errorf("Unexpected error in remote Variables Set call: %v", err) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Variables") - mv.AssertCalled(t, "Set", key, "hello") - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var ai ari.AsteriskInfo - ai.SystemInfo.EntityID = "1" - - mv := arimocks.AsteriskVariables{} - m.Asterisk.On("Variables").Return(&mv) - mv.On("Set", key, "hello").Return(errors.New("error")) - - err := cl.Asterisk().Variables().Set(key, "hello") - if err == nil { - t.Errorf("Expected error in remote Variables Set call: %v", err) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Variables") - mv.AssertCalled(t, "Set", key, "hello") - }) -} diff --git a/v5/internal/integration/bridge.go b/v5/internal/integration/bridge.go deleted file mode 100644 index b31f8af..0000000 --- a/v5/internal/integration/bridge.go +++ /dev/null @@ -1,343 +0,0 @@ -package integration - -import ( - "testing" - - "github.com/CyCoreSystems/ari/v5" - "github.com/pkg/errors" -) - -func TestBridgeCreate(t *testing.T, s Server) { - key := ari.NewKey(ari.BridgeKey, "bridgeID") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - bh := ari.NewBridgeHandle(key, m.Bridge, nil) - - m.Bridge.On("Create", key, "bridgeType", "bridgeName").Return(bh, nil) - - ret, err := cl.Bridge().Create(key, "bridgeType", "bridgeName") - if err != nil { - t.Errorf("Unexpected error in remote create call: %v", err) - } - if ret == nil { - t.Errorf("Unexpected nil bridge handle") - } - if ret == nil || ret.ID() != key.ID { - t.Errorf("Expected bridge id %v, got %v", key.ID, ret) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Create", key, "bridgeType", "bridgeName") - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("unknown error") - - m.Bridge.On("Create", key, "bridgeType", "bridgeName").Return(nil, expected) - - ret, err := cl.Bridge().Create(key, "bridgeType", "bridgeName") - if err == nil || errors.Cause(err).Error() != expected.Error() { - t.Errorf("Expected error '%v', got '%v'", expected, err) - } - if ret != nil { - t.Errorf("Expected nil bridge handle, got %v", ret) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Create", key, "bridgeType", "bridgeName") - }) -} - -func TestBridgeList(t *testing.T, s Server) { - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var handles []*ari.Key - h1 := ari.NewKey(ari.BridgeKey, "h1") - h2 := ari.NewKey(ari.BridgeKey, "h2") - - handles = append(handles, h1) - handles = append(handles, h2) - - m.Bridge.On("List", (*ari.Key)(nil)).Return(handles, nil) - - ret, err := cl.Bridge().List(nil) - if err != nil { - t.Errorf("Unexpected error in remote create call: %v", err) - } - if len(ret) != len(handles) { - t.Errorf("Expected handle list of length %d, got %d", len(handles), len(ret)) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("unknown error") - - m.Bridge.On("List", (*ari.Key)(nil)).Return([]*ari.Key{}, expected) - - ret, err := cl.Bridge().List(nil) - if err == nil || errors.Cause(err).Error() != expected.Error() { - t.Errorf("Expected error '%v', got '%v'", expected, err) - } - if len(ret) != 0 { - t.Errorf("Expected handle list of length %d, got %d", 0, len(ret)) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "List", (*ari.Key)(nil)) - }) -} - -func TestBridgeData(t *testing.T, s Server) { - key := ari.NewKey(ari.BridgeKey, "bridge1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - bd := &ari.BridgeData{ - ID: "bridge1", - Class: "class1", - ChannelIDs: []string{"channel1", "channel2"}, - } - m.Bridge.On("Data", key).Return(bd, nil) - - ret, err := cl.Bridge().Data(key) - if err != nil { - t.Errorf("Unexpected error in remote data call: %v", err) - } - if ret == nil || ret.ID != bd.ID || ret.Class != bd.Class { - t.Errorf("bridge data mismatchde") - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Data", key) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Bridge.On("Data", key).Return(nil, errors.New("Error getting data")) - - ret, err := cl.Bridge().Data(key) - if err == nil { - t.Errorf("Expected error to be non-nil") - } - if ret != nil { - t.Errorf("Expected bridge data to be nil") - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Data", key) - }) -} - -func TestBridgeAddChannel(t *testing.T, s Server) { - key := ari.NewKey(ari.BridgeKey, "bridge1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Bridge.On("AddChannel", key, "channel1").Return(nil) - - err := cl.Bridge().AddChannel(key, "channel1") - if err != nil { - t.Errorf("Unexpected error in remote AddChannel call: %v", err) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "AddChannel", key, "channel1") - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Bridge.On("AddChannel", key, "channel1").Return(errors.New("unknown error")) - - err := cl.Bridge().AddChannel(key, "channel1") - if err == nil { - t.Errorf("Expected error to be non-nil") - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "AddChannel", key, "channel1") - }) -} - -func TestBridgeRemoveChannel(t *testing.T, s Server) { - key := ari.NewKey(ari.BridgeKey, "bridge1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Bridge.On("RemoveChannel", key, "channel1").Return(nil) - - err := cl.Bridge().RemoveChannel(key, "channel1") - if err != nil { - t.Errorf("Unexpected error in remote RemoveChannel call: %v", err) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "RemoveChannel", key, "channel1") - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Bridge.On("RemoveChannel", key, "channel1").Return(errors.New("unknown error")) - - err := cl.Bridge().RemoveChannel(key, "channel1") - if err == nil { - t.Errorf("Expected error to be non-nil") - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "RemoveChannel", key, "channel1") - }) -} - -func TestBridgeDelete(t *testing.T, s Server) { - key := ari.NewKey(ari.BridgeKey, "bridge1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Bridge.On("Delete", key).Return(nil) - - err := cl.Bridge().Delete(key) - if err != nil { - t.Errorf("Unexpected error in remote Delete call: %v", err) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Delete", key) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Bridge.On("Delete", key).Return(errors.New("unknown error")) - - err := cl.Bridge().Delete(key) - if err == nil { - t.Errorf("Expected error to be non-nil") - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Delete", key) - }) -} - -func TestBridgePlay(t *testing.T, s Server) { - key := ari.NewKey(ari.BridgeKey, "bridge1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - ph := ari.NewPlaybackHandle(ari.NewKey(ari.PlaybackKey, "playback1"), m.Playback, nil) - - m.Bridge.On("Play", key, "playback1", "mediaURI").Return(ph, nil) - - ret, err := cl.Bridge().Play(key, "playback1", "mediaURI") - if err != nil { - t.Errorf("Unexpected error in remote Play call: %v", err) - } - if ret == nil || ret.ID() != ph.ID() { - t.Errorf("Expected playback handle '%v', got '%v'", ph.ID(), ret.ID()) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Play", key, "playback1", "mediaURI") - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Bridge.On("Play", key, "playback1", "mediaURI").Return(nil, errors.New("unknown error")) - - ret, err := cl.Bridge().Play(key, "playback1", "mediaURI") - if err == nil { - t.Errorf("Expected error to be non-nil") - } - if ret != nil { - t.Errorf("Expected empty playback handle") - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Play", key, "playback1", "mediaURI") - }) -} - -func TestBridgeRecord(t *testing.T, s Server) { - key := ari.NewKey(ari.BridgeKey, "bridge1") - - runTest("customOpts", t, s, func(t *testing.T, m *mock, cl ari.Client) { - opts := &ari.RecordingOptions{Format: "", MaxDuration: 0, MaxSilence: 0, Exists: "", Beep: false, Terminate: "#"} - - lrh := ari.NewLiveRecordingHandle(ari.NewKey(ari.LiveRecordingKey, "recording1"), m.LiveRecording, nil) - - bd := &ari.BridgeData{ - ID: "bridge1", - Class: "class1", - ChannelIDs: []string{"channel1", "channel2"}, - } - m.Bridge.On("Data", key).Return(bd, nil) - m.Bridge.On("Record", key, "recording1", opts).Return(lrh, nil) - - ret, err := cl.Bridge().Record(key, "recording1", opts) - if err != nil { - t.Errorf("Unexpected error in remote Record call: %v", err) - } - if ret == nil || ret.ID() != lrh.ID() { - t.Errorf("Expected liverecording handle '%v', got '%v'", lrh.ID(), ret.ID()) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Record", key, "recording1", opts) - }) - - runTest("nilOpts", t, s, func(t *testing.T, m *mock, cl ari.Client) { - opts := &ari.RecordingOptions{} - - lrh := ari.NewLiveRecordingHandle(ari.NewKey(ari.LiveRecordingKey, "recording1"), m.LiveRecording, nil) - - bd := &ari.BridgeData{ - ID: "bridge1", - Class: "class1", - ChannelIDs: []string{"channel1", "channel2"}, - } - m.Bridge.On("Data", key).Return(bd, nil) - m.Bridge.On("Record", key, "recording1", opts).Return(lrh, nil) - - ret, err := cl.Bridge().Record(key, "recording1", nil) - if err != nil { - t.Errorf("Unexpected error in remote Record call: %v", err) - } - if ret == nil || ret.ID() != lrh.ID() { - t.Errorf("Expected liverecording handle '%v', got '%v'", lrh, ret) - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Record", key, "recording1", opts) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - bd := &ari.BridgeData{ - ID: "bridge1", - Class: "class1", - ChannelIDs: []string{"channel1", "channel2"}, - } - m.Bridge.On("Data", key).Return(bd, nil) - - opts := &ari.RecordingOptions{} - m.Bridge.On("Record", key, "recording1", opts).Return(nil, errors.New("unknown error")) - - ret, err := cl.Bridge().Record(key, "recording1", opts) - if err == nil { - t.Errorf("Expected error to be non-nil") - } - if ret != nil { - t.Errorf("Expected empty liverecording handle") - } - - m.Shutdown() - - m.Bridge.AssertCalled(t, "Record", key, "recording1", opts) - }) -} diff --git a/v5/internal/integration/channel.go b/v5/internal/integration/channel.go deleted file mode 100644 index 9e2d514..0000000 --- a/v5/internal/integration/channel.go +++ /dev/null @@ -1,1119 +0,0 @@ -package integration - -import ( - "errors" - "testing" - "time" - - rid "github.com/CyCoreSystems/ari-rid" - "github.com/CyCoreSystems/ari/v5" - tmock "github.com/stretchr/testify/mock" -) - -var _ = tmock.Anything - -var nonEmpty = tmock.MatchedBy(func(s string) bool { return s != "" }) - -func TestChannelData(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var expected ari.ChannelData - expected.ID = "c1" - expected.Name = "channe1" - expected.State = "Up" - - m.Channel.On("Data", key).Return(&expected, nil) - - cd, err := cl.Channel().Data(key) - if err != nil { - t.Errorf("Unexpected error in remote Data call %s", err) - } - - if cd == nil || cd.ID != expected.ID || cd.Name != expected.Name || cd.State != expected.State { - t.Errorf("Expected channel data %v, got %v", expected, cd) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Data", key) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("Unknown error") - - m.Channel.On("Data", key).Return(nil, expected) - - cd, err := cl.Channel().Data(key) - if err == nil { - t.Errorf("Expected error in remote Data call") - } - - if cd != nil { - t.Errorf("Expected channel data %v, got %v", nil, cd) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Data", key) - }) -} - -func TestChannelAnswer(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Answer", key).Return(nil) - - err := cl.Channel().Answer(key) - if err != nil { - t.Errorf("Unexpected error in remote Data call %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Answer", key) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("Unknown error") - - m.Channel.On("Answer", key).Return(expected) - - err := cl.Channel().Answer(key) - if err == nil { - t.Errorf("Expected error in remote Answer call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Answer", key) - }) -} - -func TestChannelBusy(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Busy", key).Return(nil) - - err := cl.Channel().Busy(key) - if err != nil { - t.Errorf("Unexpected error in remote Busy call %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Busy", key) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("Unknown error") - - m.Channel.On("Busy", key).Return(expected) - - err := cl.Channel().Busy(key) - if err == nil { - t.Errorf("Expected error in remote Busy call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Busy", key) - }) -} - -func TestChannelCongestion(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("simple", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Congestion", key).Return(nil) - - err := cl.Channel().Congestion(key) - if err != nil { - t.Errorf("Unexpected error in remote Congestion call %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Congestion", key) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("Unknown error") - - m.Channel.On("Congestion", key).Return(expected) - - err := cl.Channel().Congestion(key) - if err == nil { - t.Errorf("Expected error in remote Congestion call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Congestion", key) - }) -} - -func TestChannelHangup(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("noReason", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Hangup", key, "").Return(nil) - - err := cl.Channel().Hangup(key, "") - if err != nil { - t.Errorf("Unexpected error in remote Hangup call %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Hangup", key, "") - }) - - runTest("aReason", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Hangup", key, "busy").Return(nil) - - err := cl.Channel().Hangup(key, "busy") - if err != nil { - t.Errorf("Unexpected error in remote Hangup call %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Hangup", key, "busy") - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("Unknown error") - - m.Channel.On("Hangup", key, "busy").Return(expected) - - err := cl.Channel().Hangup(key, "busy") - if err == nil { - t.Errorf("Expected error in remote Hangup call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Hangup", key, "busy") - }) -} - -func TestChannelList(t *testing.T, s Server) { - runTest("empty", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("List", (*ari.Key)(nil)).Return([]*ari.Key{}, nil) - - ret, err := cl.Channel().List(nil) - if err != nil { - t.Errorf("Unexpected error in remote List call: %s", err) - } - if len(ret) != 0 { - t.Errorf("Expected return length to be 0, got %d", len(ret)) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - - runTest("nonEmpty", t, s, func(t *testing.T, m *mock, cl ari.Client) { - h1 := ari.NewKey(ari.ChannelKey, "h1") - h2 := ari.NewKey(ari.ChannelKey, "h2") - - m.Channel.On("List", (*ari.Key)(nil)).Return([]*ari.Key{h1, h2}, nil) - - ret, err := cl.Channel().List(nil) - if err != nil { - t.Errorf("Unexpected error in remote List call: %s", err) - } - if len(ret) != 2 { - t.Errorf("Expected return length to be 2, got %d", len(ret)) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("List", (*ari.Key)(nil)).Return(nil, errors.New("unknown error")) - - ret, err := cl.Channel().List(nil) - if err == nil { - t.Errorf("Expected error in remote List call") - } - if len(ret) != 0 { - t.Errorf("Expected return length to be 0, got %d", len(ret)) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "List", (*ari.Key)(nil)) - }) -} - -func TestChannelMute(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("both-ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Mute", key, ari.DirectionBoth).Return(nil) - - err := cl.Channel().Mute(key, ari.DirectionBoth) - if err != nil { - t.Errorf("Unexpected error in remote Mute call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Mute", key, ari.DirectionBoth) - }) - - runTest("both-err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Mute", key, ari.DirectionBoth).Return(errors.New("error")) - - err := cl.Channel().Mute(key, ari.DirectionBoth) - if err == nil { - t.Errorf("Expected error in remote Mute call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Mute", key, ari.DirectionBoth) - }) - - runTest("none-ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Mute", key, ari.DirectionNone).Return(nil) - - err := cl.Channel().Mute(key, ari.DirectionNone) - if err != nil { - t.Errorf("Unexpected error in remote Mute call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Mute", key, ari.DirectionNone) - }) - - runTest("none-err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Mute", key, ari.DirectionNone).Return(errors.New("error")) - - err := cl.Channel().Mute(key, ari.DirectionNone) - if err == nil { - t.Errorf("Expected error in remote Mute call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Mute", key, ari.DirectionNone) - }) -} - -func TestChannelUnmute(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("both-ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Unmute", key, ari.DirectionBoth).Return(nil) - - err := cl.Channel().Unmute(key, ari.DirectionBoth) - if err != nil { - t.Errorf("Unexpected error in remote Unmute call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Unmute", key, ari.DirectionBoth) - }) - - runTest("both-err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Unmute", key, ari.DirectionBoth).Return(errors.New("error")) - - err := cl.Channel().Unmute(key, ari.DirectionBoth) - if err == nil { - t.Errorf("Expected error in remote Unmute call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Unmute", key, ari.DirectionBoth) - }) - - runTest("none-ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Unmute", key, ari.DirectionNone).Return(nil) - - err := cl.Channel().Unmute(key, ari.DirectionNone) - if err != nil { - t.Errorf("Unexpected error in remote Unmute call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Unmute", key, ari.DirectionNone) - }) - - runTest("none-err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Unmute", key, ari.DirectionNone).Return(errors.New("error")) - - err := cl.Channel().Unmute(key, ari.DirectionNone) - if err == nil { - t.Errorf("Expected error in remote Unmute call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Unmute", key, ari.DirectionNone) - }) -} - -func TestChannelMOH(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("MOH", key, "music").Return(nil) - - err := cl.Channel().MOH(key, "music") - if err != nil { - t.Errorf("Unexpected error in remote MOH call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "MOH", key, "music") - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("MOH", key, "music").Return(errors.New("error")) - - err := cl.Channel().MOH(key, "music") - if err == nil { - t.Errorf("Expected error in remote Mute call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "MOH", key, "music") - }) -} - -func TestChannelStopMOH(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("StopMOH", key).Return(nil) - - err := cl.Channel().StopMOH(key) - if err != nil { - t.Errorf("Unexpected error in remote StopMOH call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "StopMOH", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("StopMOH", key).Return(errors.New("error")) - - err := cl.Channel().StopMOH(key) - if err == nil { - t.Errorf("Expected error in remote StopMOH call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "StopMOH", key) - }) -} - -func TestChannelCreate(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - req := ari.ChannelCreateRequest{} - req.App = "App" - req.ChannelID = "1234" - - chkey := ari.NewKey(ari.ChannelKey, "ch2") - expected := ari.NewChannelHandle(chkey, m.Channel, nil) - - m.Channel.On("Create", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, req).Return(expected, nil) - - h, err := cl.Channel().Create(nil, req) - if err != nil { - t.Errorf("Unexpected error in remote Create call: %s", err) - } - if h == nil { - t.Errorf("Expected non-nil channel handle") - } else if h.ID() != req.ChannelID { - t.Errorf("Expected handle id '%s', got '%s'", h.ID(), req.ChannelID) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Create", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, ari.ChannelCreateRequest{App: "App", ChannelID: "1234"}) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - req := ari.ChannelCreateRequest{} - req.App = "App" - req.ChannelID = "1234" - - m.Channel.On("Create", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, req).Return(nil, errors.New("error")) - - h, err := cl.Channel().Create(nil, req) - if err == nil { - t.Errorf("Expected error in remote Create call") - } - if h != nil { - t.Errorf("Expected nil channel handle") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Create", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, ari.ChannelCreateRequest{App: "App", ChannelID: "1234"}) - }) -} - -func TestChannelContinue(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Continue", key, "ctx1", "ext1", 0).Return(nil) - - err := cl.Channel().Continue(key, "ctx1", "ext1", 0) - if err != nil { - t.Errorf("Unexpected error in remote Continue call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Continue", key, "ctx1", "ext1", 0) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Continue", key, "ctx1", "ext1", 0).Return(errors.New("error")) - - err := cl.Channel().Continue(key, "ctx1", "ext1", 0) - if err == nil { - t.Errorf("Expected error in remote Continue call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Continue", key, "ctx1", "ext1", 0) - }) -} - -func TestChannelDial(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Dial", key, "caller", 5*time.Second).Return(nil) - - err := cl.Channel().Dial(key, "caller", 5*time.Second) - if err != nil { - t.Errorf("Unexpected error in remote Dial call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Dial", key, "caller", 5*time.Second) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Dial", key, "caller", 5*time.Second).Return(errors.New("error")) - - err := cl.Channel().Dial(key, "caller", 5*time.Second) - if err == nil { - t.Errorf("Expected error in remote Dial call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Dial", key, "caller", 5*time.Second) - }) -} - -func TestChannelHold(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Hold", key).Return(nil) - - err := cl.Channel().Hold(key) - if err != nil { - t.Errorf("Unexpected error in remote Hold call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Hold", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Hold", key).Return(errors.New("error")) - - err := cl.Channel().Hold(key) - if err == nil { - t.Errorf("Expected error in remote Hold call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Hold", key) - }) -} - -func TestChannelStopHold(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("StopHold", key).Return(nil) - - err := cl.Channel().StopHold(key) - if err != nil { - t.Errorf("Unexpected error in remote StopHold call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "StopHold", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("StopHold", key).Return(errors.New("error")) - - err := cl.Channel().StopHold(key) - if err == nil { - t.Errorf("Expected error in remote StopHold call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "StopHold", key) - }) -} - -func TestChannelRing(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Ring", key).Return(nil) - - err := cl.Channel().Ring(key) - if err != nil { - t.Errorf("Unexpected error in remote Ring call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Ring", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Ring", key).Return(errors.New("error")) - - err := cl.Channel().Ring(key) - if err == nil { - t.Errorf("Expected error in remote Ring call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Ring", key) - }) -} - -func TestChannelSilence(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Silence", key).Return(nil) - - err := cl.Channel().Silence(key) - if err != nil { - t.Errorf("Unexpected error in remote Silence call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Silence", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Silence", key).Return(errors.New("error")) - - err := cl.Channel().Silence(key) - if err == nil { - t.Errorf("Expected error in remote Silence call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Silence", key) - }) -} - -func TestChannelStopSilence(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("StopSilence", key).Return(nil) - - err := cl.Channel().StopSilence(key) - if err != nil { - t.Errorf("Unexpected error in remote StopSilence call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "StopSilence", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("StopSilence", key).Return(errors.New("error")) - - err := cl.Channel().StopSilence(key) - if err == nil { - t.Errorf("Expected error in remote StopSilence call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "StopSilence", key) - }) -} - -func TestChannelStopRing(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("StopRing", key).Return(nil) - - err := cl.Channel().StopRing(key) - if err != nil { - t.Errorf("Unexpected error in remote StopRing call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "StopRing", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("StopRing", key).Return(errors.New("error")) - - err := cl.Channel().StopRing(key) - if err == nil { - t.Errorf("Expected error in remote StopRing call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "StopRing", key) - }) -} - -func TestChannelOriginate(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := ari.NewChannelHandle(key, m.Channel, nil) - - var req ari.OriginateRequest - req.App = "App" - req.ChannelID = "1234" - - m.Channel.On("Originate", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, req).Return(expected, nil) - - h, err := cl.Channel().Originate(nil, req) - if err != nil { - t.Errorf("Unexpected error in remote Originate call: %s", err) - } - if h == nil { - t.Error("Expected non-nil handle") - } else if h.ID() != req.ChannelID { - t.Errorf("Expected handle id '%s', got '%s'", h.ID(), req.ChannelID) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Originate", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, req) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var req ari.OriginateRequest - req.App = "App" - req.ChannelID = "1234" - - m.Channel.On("Originate", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, req).Return(nil, errors.New("error")) - - h, err := cl.Channel().Originate(nil, req) - if err == nil { - t.Errorf("Expected error in remote Originate call") - } - if h != nil { - t.Error("Expected nil handle") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Originate", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, req) - }) -} - -func TestChannelPlay(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - var cd ari.ChannelData - cd.ID = "c1" - cd.Name = "channe1" - cd.State = "Up" - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - pbkey := ari.NewKey(ari.PlaybackKey, "pb1") - expected := ari.NewPlaybackHandle(pbkey, m.Playback, nil) - - m.Channel.On("Data", key).Return(&cd, nil) - m.Channel.On("Play", key, "playbackID", "sound:hello").Return(expected, nil) - - h, err := cl.Channel().Play(key, "playbackID", "sound:hello") - if err != nil { - t.Errorf("Unexpected error in remote Play call: %s", err) - } - if h == nil { - t.Error("Expected non-nil handle") - } else if h.ID() != "playbackID" { - t.Errorf("Expected handle id '%s', got '%s'", h.ID(), "playbackID") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Play", key, "playbackID", "sound:hello") - }) - - runTest("no-id", t, s, func(t *testing.T, m *mock, cl ari.Client) { - pbkey := ari.NewKey(ari.PlaybackKey, "pb1") - expected := ari.NewPlaybackHandle(pbkey, m.Playback, nil) - - m.Channel.On("Data", key).Return(&cd, nil) - m.Channel.On("Play", key, nonEmpty, "sound:hello").Return(expected, nil) - - h, err := cl.Channel().Play(key, "", "sound:hello") - if err != nil { - t.Errorf("Unexpected error in remote Play call: %s", err) - } - if h == nil { - t.Error("Expected non-nil handle") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Play", key, nonEmpty, "sound:hello") - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("Data", key).Return(&cd, nil) - m.Channel.On("Play", key, "playbackID", "sound:hello").Return(nil, errors.New("error")) - - h, err := cl.Channel().Play(key, "playbackID", "sound:hello") - if err == nil { - t.Errorf("Expected error in remote Play call") - } - if h != nil { - t.Error("Expected nil handle") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Play", key, "playbackID", "sound:hello") - }) -} - -func TestChannelRecord(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var opts *ari.RecordingOptions - - lrkey := ari.NewKey(ari.LiveRecordingKey, "lrh1") - expected := ari.NewLiveRecordingHandle(lrkey, m.LiveRecording, nil) - - m.Channel.On("Record", key, "recordid", opts).Return(expected, nil) - - h, err := cl.Channel().Record(key, "recordid", nil) - if err != nil { - t.Errorf("Unexpected error in remote Record call: %s", err) - } - if h == nil { - t.Error("Expected non-nil handle") - } else if h.ID() != "recordid" { - t.Errorf("Expected handle id '%s', got '%s'", "recordid", h.ID()) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Record", key, "recordid", opts) - }) - - runTest("no-id", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var opts *ari.RecordingOptions - - lrkey := ari.NewKey(ari.LiveRecordingKey, "lrh1") - expected := ari.NewLiveRecordingHandle(lrkey, m.LiveRecording, nil) - - m.Channel.On("Record", key, nonEmpty, opts).Return(expected, nil) - - h, err := cl.Channel().Record(key, "", nil) - if err != nil { - t.Errorf("Unexpected error in remote Record call: %s", err) - } - if h == nil { - t.Error("Expected non-nil handle") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Record", key, nonEmpty, opts) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var opts *ari.RecordingOptions - - m.Channel.On("Record", key, "recordid", opts).Return(nil, errors.New("error")) - - h, err := cl.Channel().Record(key, "recordid", nil) - if err == nil { - t.Errorf("Expected error in remote Record call") - } - if h != nil { - t.Error("Expected nil handle") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Record", key, "recordid", opts) - }) -} - -func TestChannelSnoop(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var opts *ari.SnoopOptions - - chkey := ari.NewKey(ari.ChannelKey, "ch2") - expected := ari.NewChannelHandle(chkey, m.Channel, nil) - - m.Channel.On("Snoop", key, "snoopID", opts).Return(expected, nil) - - h, err := cl.Channel().Snoop(key, "snoopID", nil) - if err != nil { - t.Errorf("Unexpected error in remote Snoop call: %s", err) - } - if h == nil { - t.Error("Expected non-nil handle") - } else if h.ID() != "snoopID" { - t.Errorf("Expected handle id '%s', got '%s'", "snoopID", h.ID()) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Snoop", key, "snoopID", opts) - }) - - runTest("no-id", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var opts *ari.SnoopOptions - - chkey := ari.NewKey(ari.ChannelKey, "ch2") - expected := ari.NewChannelHandle(chkey, m.Channel, nil) - - m.Channel.On("Snoop", key, tmock.Anything, opts).Return(expected, nil) - - h, err := cl.Channel().Snoop(key, "", nil) - if err != nil { - t.Errorf("Unexpected error in remote Snoop call: %s", err) - } - if h == nil { - t.Error("Expected non-nil handle") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Snoop", key, tmock.Anything, opts) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var opts *ari.SnoopOptions - - m.Channel.On("Snoop", key, "ch2", opts).Return(nil, errors.New("error")) - - h, err := cl.Channel().Snoop(key, "ch2", nil) - if err == nil { - t.Errorf("Expected error in remote Snoop call") - } - if h != nil { - t.Error("Expected nil handle") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "Snoop", key, "ch2", opts) - }) -} - -func TestChannelExternalMedia(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - key := ari.NewKey(ari.ChannelKey, rid.New(rid.Channel)) - - opts := ari.ExternalMediaOptions{ - ChannelID: key.ID, - App: cl.ApplicationName(), - ExternalHost: "localhost:1234", - Format: "slin16", - } - - m.Channel.On("ExternalMedia", nil, opts).Return(nil, errors.New("error")) - - h, err := cl.Channel().ExternalMedia(nil, opts) - if err != nil { - t.Errorf("error calling ExternalMedia: %v", err) - } else if h.ID() != key.ID { - t.Errorf("expected handle id '%s', got '%s'", key.ID, h.ID()) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "ExternalMedia", nil, opts) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - key := ari.NewKey(ari.ChannelKey, rid.New(rid.Channel)) - - opts := ari.ExternalMediaOptions{ - ChannelID: key.ID, - App: cl.ApplicationName(), - ExternalHost: "localhost:1234", - // Format: "slin16", // Format is required - } - - m.Channel.On("ExternalMedia", nil, opts).Return(nil, errors.New("error")) - - h, err := cl.Channel().ExternalMedia(nil, opts) - if err == nil { - t.Error("expected error in ExternalMedia call, but got nil") - } - if h != nil { - t.Errorf("expected nil channel handle, but got key with ID: %s", h.ID()) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "ExternalMedia", nil, opts) - }) -} - -func TestChannelSendDTMF(t *testing.T, s Server) { - key := ari.NewKey(ari.ChannelKey, "c1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("SendDTMF", key, "1", &ari.DTMFOptions{}).Return(nil) - - err := cl.Channel().SendDTMF(key, "1", nil) - if err != nil { - t.Errorf("Unexpected error in remote SendDTMF call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "SendDTMF", key, "1", &ari.DTMFOptions{}) - }) - - runTest("with-options", t, s, func(t *testing.T, m *mock, cl ari.Client) { - opts := &ari.DTMFOptions{ - After: 4 * time.Second, - } - - m.Channel.On("SendDTMF", key, "1", opts).Return(nil) - - err := cl.Channel().SendDTMF(key, "1", opts) - if err != nil { - t.Errorf("Unexpected error in remote SendDTMF call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "SendDTMF", key, "1", opts) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("SendDTMF", key, "1", &ari.DTMFOptions{}).Return(errors.New("err")) - - err := cl.Channel().SendDTMF(key, "1", nil) - if err == nil { - t.Errorf("Expected error in remote SendDTMF call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "SendDTMF", key, "1", &ari.DTMFOptions{}) - }) -} - -func TestChannelVariableGet(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("GetVariable", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, "v1").Return("value", nil) - - val, err := cl.Channel().GetVariable(nil, "v1") - if err != nil { - t.Errorf("Unexpected error in remote Variables Get call: %s", err) - } - if val != "value" { - t.Errorf("Expected channel variable to be 'value', got '%s'", val) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "GetVariable", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, "v1") - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("GetVariable", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, "v1").Return("", errors.New("1")) - - val, err := cl.Channel().GetVariable(nil, "v1") - if err == nil { - t.Errorf("Expected error in remote Variables Get call") - } - if val != "" { - t.Errorf("Expected empty value, got '%s'", val) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "GetVariable", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, "v1") - }) -} - -func TestChannelVariableSet(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("SetVariable", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, "v1", "value").Return(nil) - - err := cl.Channel().SetVariable(nil, "v1", "value") - if err != nil { - t.Errorf("Unexpected error in remote Variables Set call: %s", err) - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "SetVariable", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, "v1", "value") - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Channel.On("SetVariable", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, "v1", "value").Return(errors.New("error")) - - err := cl.Channel().SetVariable(nil, "v1", "value") - if err == nil { - t.Errorf("Expected error in remote Variables Set call") - } - - m.Shutdown() - - m.Channel.AssertCalled(t, "SetVariable", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}, "v1", "value") - }) -} diff --git a/v5/internal/integration/clientserver.go b/v5/internal/integration/clientserver.go deleted file mode 100644 index b50599b..0000000 --- a/v5/internal/integration/clientserver.go +++ /dev/null @@ -1,105 +0,0 @@ -package integration - -import ( - "context" - "fmt" - "os" - "testing" - - "sync" - - "github.com/CyCoreSystems/ari/v5" - "github.com/nats-io/nats.go" - "github.com/pkg/errors" -) - -func natsConnect() (*nats.EncodedConn, error) { - c, err := nats.Connect(nats.DefaultURL) - if err != nil { - return nil, errors.Wrap(err, "failed to connect to NATS") - } - nc, err := nats.NewEncodedConn(c, nats.JSON_ENCODER) - if err != nil { - return nil, errors.Wrap(err, "failed to encode NATS connection") - } - return nc, err -} - -// Server represents a generalized ari-proxy server -type Server interface { - Start(ctx context.Context, t *testing.T, client ari.Client, nc *nats.EncodedConn, completeCh chan struct{}) (ari.Client, error) - Ready() <-chan struct{} - Close() error -} - -// TestHandler is the interface for test execution -type testHandler func(t *testing.T, m *mock, cl ari.Client) - -func runTest(desc string, t *testing.T, s Server, fn testHandler) { - defer func() { - // recover from panic if one occured. Set err to nil otherwise. - if err := recover(); err != nil { - t.Errorf("PANIC") - } - }() - - t.Run(desc, func(t *testing.T) { - // setup mocking - m := standardMock() - - // setup ari-proxy server - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - nc, err := natsConnect() - if err != nil { - t.Skipf("Error connecting to nats: %s", err) - } - - completeCh := make(chan struct{}) - - cl, err := s.Start(ctx, t, m.Client, nc, completeCh) - if err != nil { - t.Errorf("Failed to start client/server: %s", err) - return - } - defer cl.Close() - - var once sync.Once - - m.Shutdown = func() { - once.Do(func() { - s.Close() - - cancel() - <-completeCh - }) - } - - fn(t, m, cl) - - m.Shutdown() - - timeout, ok := TimeoutCount(cl) - if !ok { - t.Errorf("Failed to get timeout count from ari-proxy client") - } else { - if timeout > 0 { - fmt.Fprintf(os.Stderr, "Timeouts: %d\n", timeout) - } - } - }) -} - -type timeoutCounter interface { - TimeoutCount() int64 -} - -// TimeoutCount gets the timeout count from the ari client, if available. -func TimeoutCount(c ari.Client) (int64, bool) { - cl, ok := c.(timeoutCounter) - if !ok { - return 0, false - } - return cl.TimeoutCount(), true -} diff --git a/v5/internal/integration/config.go b/v5/internal/integration/config.go deleted file mode 100644 index 6da1338..0000000 --- a/v5/internal/integration/config.go +++ /dev/null @@ -1,149 +0,0 @@ -package integration - -import ( - "errors" - "testing" - - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/client/arimocks" - tmock "github.com/stretchr/testify/mock" -) - -var _ = tmock.Anything - -func TestConfigData(t *testing.T, s Server) { - key := ari.NewKey("config", ari.ConfigID("c1", "o1", "id1")) - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var expected ari.ConfigData - expected.Class = "c1" - expected.Key = key - expected.Type = "o1" - expected.Fields = []ari.ConfigTuple{ - ari.ConfigTuple{ - Value: "v1", - Attribute: "a1", - }, - } - - cfg := arimocks.Config{} - m.Asterisk.On("Config").Return(&cfg) - cfg.On("Data", key).Return(&expected, nil) - - data, err := cl.Asterisk().Config().Data(key) - if err != nil { - t.Errorf("Unexpected error in remove config data call: %s", err) - } - if data == nil { - t.Errorf("Expected non-nil data") - } else { - failed := false - failed = failed || data.Class != expected.Class - failed = failed || data.ID() != expected.ID() - failed = failed || data.Type != expected.Type - failed = failed || len(data.Fields) != len(expected.Fields) - for idx := range data.Fields { - failed = failed || data.Fields[idx].Attribute != expected.Fields[idx].Attribute - failed = failed || data.Fields[idx].Value != expected.Fields[idx].Value - } - if failed { - t.Errorf("Expected config data '%v', got '%v'", expected, data) - } - } - - m.Asterisk.AssertCalled(t, "Config") - cfg.AssertCalled(t, "Data", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - cfg := arimocks.Config{} - m.Asterisk.On("Config").Return(&cfg) - cfg.On("Data", key).Return(nil, errors.New("error")) - - data, err := cl.Asterisk().Config().Data(key) - if err == nil { - t.Errorf("Expected error in remove config data call") - } - if data != nil { - t.Errorf("Expected nil data") - } - - m.Asterisk.AssertCalled(t, "Config") - cfg.AssertCalled(t, "Data", key) - }) -} - -func TestConfigDelete(t *testing.T, s Server) { - key := ari.NewKey("config", ari.ConfigID("c1", "o1", "id1")) - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - cfg := arimocks.Config{} - m.Asterisk.On("Config").Return(&cfg) - cfg.On("Delete", key).Return(nil) - - err := cl.Asterisk().Config().Delete(key) - if err != nil { - t.Errorf("Unexpected error in remove config delete call: %s", err) - } - - m.Asterisk.AssertCalled(t, "Config") - cfg.AssertCalled(t, "Delete", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - cfg := arimocks.Config{} - m.Asterisk.On("Config").Return(&cfg) - cfg.On("Delete", key).Return(errors.New("error")) - - err := cl.Asterisk().Config().Delete(key) - if err == nil { - t.Errorf("Expected error in remove config delete call") - } - - m.Asterisk.AssertCalled(t, "Config") - cfg.AssertCalled(t, "Delete", key) - }) -} - -func TestConfigUpdate(t *testing.T, s Server) { - key := ari.NewKey("config", ari.ConfigID("c1", "o1", "id1")) - - tuples := []ari.ConfigTuple{ - ari.ConfigTuple{ - Value: "v1", - Attribute: "a1", - }, - ari.ConfigTuple{ - Value: "v2", - Attribute: "a2", - }, - } - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - cfg := arimocks.Config{} - m.Asterisk.On("Config").Return(&cfg) - cfg.On("Update", key, tuples).Return(nil) - - err := cl.Asterisk().Config().Update(key, tuples) - if err != nil { - t.Errorf("Unexpected error in remove config Update call: %s", err) - } - - m.Asterisk.AssertCalled(t, "Config") - cfg.AssertCalled(t, "Update", key, tuples) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - cfg := arimocks.Config{} - m.Asterisk.On("Config").Return(&cfg) - cfg.On("Update", key, tuples).Return(errors.New("error")) - - err := cl.Asterisk().Config().Update(key, tuples) - if err == nil { - t.Errorf("Expected error in remove config Update call") - } - - m.Asterisk.AssertCalled(t, "Config") - cfg.AssertCalled(t, "Update", key, tuples) - }) -} diff --git a/v5/internal/integration/device.go b/v5/internal/integration/device.go deleted file mode 100644 index 3d44cbc..0000000 --- a/v5/internal/integration/device.go +++ /dev/null @@ -1,128 +0,0 @@ -package integration - -import ( - "errors" - "testing" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestDeviceData(t *testing.T, s Server) { - key := ari.NewKey(ari.DeviceStateKey, "d1") - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var expected ari.DeviceStateData - expected.State = "deviceData1" - expected.Key = ari.NewKey(ari.DeviceStateKey, "d1") - - m.DeviceState.On("Data", key).Return(&expected, nil) - - data, err := cl.DeviceState().Data(key) - if err != nil { - t.Errorf("Error in remote device state data call: %s", err) - } - if data == nil || data.State != expected.State { - t.Errorf("Expected data '%s', got '%v'", expected, data) - } - - m.DeviceState.AssertCalled(t, "Data", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.DeviceState.On("Data", key).Return(nil, errors.New("err")) - - data, err := cl.DeviceState().Data(key) - if err == nil { - t.Errorf("Expected error in remote device state data call: %s", err) - } - if data != nil { - t.Errorf("Expected data to be nil, got '%v'", *data) - } - - m.DeviceState.AssertCalled(t, "Data", key) - }) -} - -func TestDeviceDelete(t *testing.T, s Server) { - key := ari.NewKey(ari.DeviceStateKey, "d1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.DeviceState.On("Delete", key).Return(nil) - - err := cl.DeviceState().Delete(key) - if err != nil { - t.Errorf("Error in remote device state Delete call: %s", err) - } - - m.DeviceState.AssertCalled(t, "Delete", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.DeviceState.On("Delete", key).Return(errors.New("err")) - - err := cl.DeviceState().Delete(key) - if err == nil { - t.Errorf("Expected error in remote device state Delete call: %s", err) - } - - m.DeviceState.AssertCalled(t, "Delete", key) - }) -} - -func TestDeviceUpdate(t *testing.T, s Server) { - key := ari.NewKey(ari.DeviceStateKey, "d1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.DeviceState.On("Update", key, "st1").Return(nil) - - err := cl.DeviceState().Update(key, "st1") - if err != nil { - t.Errorf("Error in remote device state Update call: %s", err) - } - - m.DeviceState.AssertCalled(t, "Update", key, "st1") - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.DeviceState.On("Update", key, "st1").Return(errors.New("err")) - - err := cl.DeviceState().Update(key, "st1") - if err == nil { - t.Errorf("Expected error in remote device state Update call: %s", err) - } - - m.DeviceState.AssertCalled(t, "Update", key, "st1") - }) -} - -func TestDeviceList(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - h1 := ari.NewKey(ari.DeviceStateKey, "h1") - h2 := ari.NewKey(ari.DeviceStateKey, "h2") - - m.DeviceState.On("List", (*ari.Key)(nil)).Return([]*ari.Key{h1, h2}, nil) - - list, err := cl.DeviceState().List(nil) - if err != nil { - t.Errorf("Error in remote device state List call: %s", err) - } - if len(list) != 2 { - t.Errorf("Expected list of length 2, got %d", len(list)) - } - - m.DeviceState.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.DeviceState.On("List", (*ari.Key)(nil)).Return([]*ari.Key{}, errors.New("error")) - - list, err := cl.DeviceState().List(nil) - if err == nil { - t.Errorf("Expected error in remote device state List call") - } - if len(list) != 0 { - t.Errorf("Expected list of length 0, got %d", len(list)) - } - - m.DeviceState.AssertCalled(t, "List", (*ari.Key)(nil)) - }) -} diff --git a/v5/internal/integration/doc.go b/v5/internal/integration/doc.go deleted file mode 100644 index bcce5a3..0000000 --- a/v5/internal/integration/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package integration contains integration tests for server to client communications -package integration diff --git a/v5/internal/integration/endpoint.go b/v5/internal/integration/endpoint.go deleted file mode 100644 index 99894ea..0000000 --- a/v5/internal/integration/endpoint.go +++ /dev/null @@ -1,126 +0,0 @@ -package integration - -import ( - "errors" - "testing" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestEndpointList(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - h1 := ari.NewEndpointKey("h1", "1") - h2 := ari.NewEndpointKey("h1", "2") - - m.Endpoint.On("List", (*ari.Key)(nil)).Return([]*ari.Key{h1, h2}, nil) - - list, err := cl.Endpoint().List(nil) - if err != nil { - t.Errorf("Error in remote Endpoint List call: %s", err) - } - if len(list) != 2 { - t.Errorf("Expected list of length 2, got %d", len(list)) - } - - m.Endpoint.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Endpoint.On("List", (*ari.Key)(nil)).Return([]*ari.Key{}, errors.New("error")) - - list, err := cl.Endpoint().List(nil) - if err == nil { - t.Errorf("Expected error in remote Endpoint List call") - } - if len(list) != 0 { - t.Errorf("Expected list of length 0, got %d", len(list)) - } - - m.Endpoint.AssertCalled(t, "List", (*ari.Key)(nil)) - }) -} - -func TestEndpointListByTech(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - h1 := ari.NewEndpointKey("h1", "1") - h2 := ari.NewEndpointKey("h1", "2") - - m.Endpoint.On("ListByTech", "tech", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}).Return([]*ari.Key{h1, h2}, nil) - - list, err := cl.Endpoint().ListByTech("tech", nil) - if err != nil { - t.Errorf("Error in remote Endpoint List call: %s", err) - } - if len(list) != 2 { - t.Errorf("Expected list of length 2, got %d", len(list)) - } - - m.Endpoint.AssertCalled(t, "ListByTech", "tech", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Endpoint.On("ListByTech", "tech", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}).Return([]*ari.Key{}, errors.New("error")) - - list, err := cl.Endpoint().ListByTech("tech", nil) - if err == nil { - t.Errorf("Expected error in remote Endpoint List call") - } - if len(list) != 0 { - t.Errorf("Expected list of length 0, got %d", len(list)) - } - - m.Endpoint.AssertCalled(t, "ListByTech", "tech", &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}) - }) -} - -func TestEndpointData(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var expected ari.EndpointData - expected.State = "st1" - expected.Technology = "tech1" - expected.Resource = "resource" - - h1 := ari.NewEndpointKey(expected.Technology, expected.Resource) - - m.Endpoint.On("Data", h1).Return(&expected, nil) - - data, err := cl.Endpoint().Data(h1) - if err != nil { - t.Errorf("Error in remote Endpoint Data call: %s", err) - } - if data == nil { - t.Errorf("Expected data to be non-nil") - } else { - failed := false - failed = failed || expected.State != data.State - failed = failed || expected.Resource != data.Resource - failed = failed || expected.Technology != data.Technology - if failed { - t.Errorf("Expected '%v', got '%v'", expected, data) - } - } - - m.Endpoint.AssertCalled(t, "Data", h1) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var expected ari.EndpointData - expected.State = "st1" - expected.Technology = "tech1" - expected.Resource = "resource" - - h1 := ari.NewEndpointKey(expected.Technology, expected.Resource) - - m.Endpoint.On("Data", h1).Return(nil, errors.New("error")) - - data, err := cl.Endpoint().Data(h1) - if err == nil { - t.Errorf("Expected error in remote Endpoint Data call") - } - if data != nil { - t.Errorf("Expected data to be nil") - } - - m.Endpoint.AssertCalled(t, "Data", h1) - }) -} diff --git a/v5/internal/integration/liverecording.go b/v5/internal/integration/liverecording.go deleted file mode 100644 index 030314f..0000000 --- a/v5/internal/integration/liverecording.go +++ /dev/null @@ -1,160 +0,0 @@ -package integration - -import ( - "errors" - "testing" - "time" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestLiveRecordingData(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := ari.LiveRecordingData{ - Name: "n1", - Format: "format", - Cause: "c1", - Silence: ari.DurationSec(3 * time.Second), - State: "st1", - Talking: ari.DurationSec(3 * time.Second), - TargetURI: "uri1", - Duration: ari.DurationSec(6 * time.Second), - } - - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - m.LiveRecording.On("Data", key).Return(&expected, nil) - - ret, err := cl.LiveRecording().Data(key) - if err != nil { - t.Errorf("Unexpected error in liverecording Data: %s", err) - } - if ret == nil { - t.Errorf("Expected live recording data to be non-nil") - } else { - failed := false - failed = failed || ret.Name != expected.Name - failed = failed || ret.Format != expected.Format - failed = failed || ret.Cause != expected.Cause - failed = failed || ret.Silence != expected.Silence - failed = failed || ret.State != expected.State - failed = failed || ret.Talking != expected.Talking - failed = failed || ret.TargetURI != expected.TargetURI - failed = failed || ret.Duration != expected.Duration - if failed { - t.Errorf("Expected '%v', got '%v'", expected, ret) - } - } - - m.LiveRecording.AssertCalled(t, "Data", key) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - m.LiveRecording.On("Data", key).Return(nil, errors.New("err")) - - ret, err := cl.LiveRecording().Data(key) - if err == nil { - t.Errorf("Expected error in liverecording Data") - } - if ret != nil { - t.Errorf("Expected live recording data to be nil") - } - - m.LiveRecording.AssertCalled(t, "Data", key) - }) -} - -func testLiveRecordingCommand(t *testing.T, m *mock, name string, id *ari.Key, expected error, fn func(*ari.Key) error) { - m.LiveRecording.On(name, id).Return(expected) - err := fn(id) - failed := false - failed = failed || err == nil && expected != nil - failed = failed || err != nil && expected == nil - failed = failed || err != nil && expected != nil && err.Error() != expected.Error() - if failed { - t.Errorf("Expected live recording %s(%s) to return '%v', got '%v'", - name, id, expected, err, - ) - } - m.LiveRecording.AssertCalled(t, name, id) -} - -/* -func TestLiveRecordingDelete(t *testing.T, s Server) { - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Delete", key, nil, cl.LiveRecording().Delete) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Delete", key, errors.New("err"), cl.LiveRecording().Delete) - }) -} -*/ - -func TestLiveRecordingMute(t *testing.T, s Server) { - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Mute", key, nil, cl.LiveRecording().Mute) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Mute", key, errors.New("err"), cl.LiveRecording().Mute) - }) -} - -func TestLiveRecordingPause(t *testing.T, s Server) { - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Pause", key, nil, cl.LiveRecording().Pause) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Pause", key, errors.New("err"), cl.LiveRecording().Pause) - }) -} - -func TestLiveRecordingStop(t *testing.T, s Server) { - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Stop", key, nil, cl.LiveRecording().Stop) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Stop", key, errors.New("err"), cl.LiveRecording().Stop) - }) -} - -func TestLiveRecordingUnmute(t *testing.T, s Server) { - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Unmute", key, nil, cl.LiveRecording().Unmute) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Unmute", key, errors.New("err"), cl.LiveRecording().Unmute) - }) -} - -func TestLiveRecordingResume(t *testing.T, s Server) { - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Resume", key, nil, cl.LiveRecording().Resume) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Resume", key, errors.New("err"), cl.LiveRecording().Resume) - }) -} - -func TestLiveRecordingScrap(t *testing.T, s Server) { - key := ari.NewKey(ari.LiveRecordingKey, "lr1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Scrap", key, nil, cl.LiveRecording().Scrap) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testLiveRecordingCommand(t, m, "Scrap", key, errors.New("err"), cl.LiveRecording().Scrap) - }) -} diff --git a/v5/internal/integration/logging.go b/v5/internal/integration/logging.go deleted file mode 100644 index 5f64af2..0000000 --- a/v5/internal/integration/logging.go +++ /dev/null @@ -1,141 +0,0 @@ -package integration - -import ( - "errors" - "testing" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestLoggingList(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := []*ari.Key{ - ari.NewKey(ari.LoggingKey, "n1"), - } - - m.Logging.On("List", (*ari.Key)(nil)).Return(expected, nil) - - ld, err := cl.Asterisk().Logging().List(nil) - if err != nil { - t.Errorf("Unexpected error in logging list: %s", err) - } - if len(ld) != len(expected) { - t.Errorf("Expected return of length %d, got %d", len(expected), len(ld)) - } else { - for idx := range ld { - failed := false - failed = failed || ld[idx].ID != expected[idx].ID - - if failed { - t.Errorf("Expected item '%d' to be '%v', got '%v", - idx, expected[idx], ld[idx]) - } - } - } - - m.Logging.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var expected []*ari.Key - - m.Logging.On("List", (*ari.Key)(nil)).Return(expected, errors.New("error")) - - ld, err := cl.Asterisk().Logging().List(nil) - if err == nil { - t.Errorf("Expected error in logging list") - } - if len(ld) != len(expected) { - t.Errorf("Expected return of length %d, got %d", len(expected), len(ld)) - } else { - for idx := range ld { - failed := false - failed = failed || ld[idx].ID != expected[idx].ID // nolint - - if failed { - t.Errorf("Expected item '%d' to be '%v', got '%v", - idx, expected[idx], ld[idx]) // nolint - } - } - } - - m.Logging.AssertCalled(t, "List", (*ari.Key)(nil)) - }) -} - -func TestLoggingCreate(t *testing.T, s Server) { - key := ari.NewKey(ari.LoggingKey, "n1") - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Logging.On("Create", key, "l1").Return(ari.NewLogHandle(key, m.Logging), nil) - - _, err := cl.Asterisk().Logging().Create(key, "l1") - if err != nil { - t.Errorf("Unexpected error in logging create: %s", err) - } - - m.Logging.AssertCalled(t, "Create", key, "l1") - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Logging.On("Create", key, "l1").Return(nil, errors.New("error")) - - _, err := cl.Asterisk().Logging().Create(key, "l1") - if err == nil { - t.Errorf("Expected error in logging create") - } - - m.Logging.AssertCalled(t, "Create", key, "l1") - }) -} - -func TestLoggingDelete(t *testing.T, s Server) { - key := ari.NewKey(ari.LoggingKey, "n1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Logging.On("Delete", key).Return(nil) - - err := cl.Asterisk().Logging().Delete(key) - if err != nil { - t.Errorf("Unexpected error in logging Delete: %s", err) - } - - m.Logging.AssertCalled(t, "Delete", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Logging.On("Delete", key).Return(errors.New("error")) - - err := cl.Asterisk().Logging().Delete(key) - if err == nil { - t.Errorf("Expected error in logging Delete") - } - - m.Logging.AssertCalled(t, "Delete", key) - }) -} - -func TestLoggingRotate(t *testing.T, s Server) { - key := ari.NewKey(ari.LoggingKey, "n1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Logging.On("Rotate", key).Return(nil) - - err := cl.Asterisk().Logging().Rotate(key) - if err != nil { - t.Errorf("Unexpected error in logging Rotate: %s", err) - } - - m.Logging.AssertCalled(t, "Rotate", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Logging.On("Rotate", key).Return(errors.New("error")) - - err := cl.Asterisk().Logging().Rotate(key) - if err == nil { - t.Errorf("Expected error in logging Rotate") - } - - m.Logging.AssertCalled(t, "Rotate", key) - }) -} diff --git a/v5/internal/integration/mailbox.go b/v5/internal/integration/mailbox.go deleted file mode 100644 index 89ce2c2..0000000 --- a/v5/internal/integration/mailbox.go +++ /dev/null @@ -1,180 +0,0 @@ -package integration - -import ( - "errors" - "testing" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestMailboxList(t *testing.T, s Server) { - runTest("empty", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Mailbox.On("List", (*ari.Key)(nil)).Return([]*ari.Key{}, nil) - - ret, err := cl.Mailbox().List(nil) - if err != nil { - t.Errorf("Unexpected error in remote List call") - } - if len(ret) != 0 { - t.Errorf("Expected return length to be 0, got %d", len(ret)) - } - - m.Shutdown() - - m.Mailbox.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - - runTest("nonEmpty", t, s, func(t *testing.T, m *mock, cl ari.Client) { - h1 := ari.NewKey(ari.MailboxKey, "h1") - h2 := ari.NewKey(ari.MailboxKey, "h2") - - m.Mailbox.On("List", (*ari.Key)(nil)).Return([]*ari.Key{h1, h2}, nil) - - ret, err := cl.Mailbox().List(nil) - if err != nil { - t.Errorf("Unexpected error in remote List call") - } - if len(ret) != 2 { - t.Errorf("Expected return length to be 2, got %d", len(ret)) - } - - m.Shutdown() - - m.Mailbox.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - - runTest("error", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Mailbox.On("List", (*ari.Key)(nil)).Return(nil, errors.New("unknown error")) - - ret, err := cl.Mailbox().List(nil) - if err == nil { - t.Errorf("Expected error in remote List call") - } - if len(ret) != 0 { - t.Errorf("Expected return length to be 0, got %d", len(ret)) - } - - m.Shutdown() - - m.Mailbox.AssertCalled(t, "List", (*ari.Key)(nil)) - }) -} - -func testMailboxCommand(t *testing.T, m *mock, name string, id *ari.Key, expected error, fn func(*ari.Key) error) { - m.Mailbox.On(name, id).Return(expected) - err := fn(id) - failed := false - failed = failed || err == nil && expected != nil - failed = failed || err != nil && expected == nil - failed = failed || err != nil && expected != nil && err.Error() != expected.Error() - if failed { - t.Errorf("Expected mailbox %s(%s) to return '%v', got '%v'", - name, id, expected, err, - ) - } - m.Mailbox.AssertCalled(t, name, id) -} - -func TestMailboxDelete(t *testing.T, s Server) { - key := ari.NewKey(ari.MailboxKey, "mbox1") - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testMailboxCommand(t, m, "Delete", key, nil, cl.Mailbox().Delete) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - testMailboxCommand(t, m, "Delete", key, errors.New("err"), cl.Mailbox().Delete) - }) -} - -func TestMailboxUpdate(t *testing.T, s Server) { - key := ari.NewKey(ari.MailboxKey, "mbox1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var expected error - - m.Mailbox.On("Update", key, 1, 1).Return(expected) - - err := cl.Mailbox().Update(key, 1, 1) - - failed := false - failed = failed || err == nil && expected != nil - failed = failed || err != nil && expected == nil - failed = failed || err != nil && expected != nil && err.Error() != expected.Error() // nolint - if failed { - t.Errorf("Expected mailbox %s(%s) to return '%v', got '%v'", - "Update", "mbox1", expected, err, - ) - } - - m.Mailbox.AssertCalled(t, "Update", key, 1, 1) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("error") - - m.Mailbox.On("Update", key, 1, 1).Return(expected) - - err := cl.Mailbox().Update(key, 1, 1) - - failed := false - failed = failed || err == nil && expected != nil - failed = failed || err != nil && expected == nil - failed = failed || err != nil && expected != nil && err.Error() != expected.Error() - if failed { - t.Errorf("Expected mailbox %s(%s) to return '%v', got '%v'", - "Update", "mbox1", expected, err, - ) - } - - m.Mailbox.AssertCalled(t, "Update", key, 1, 1) - }) -} - -func TestMailboxData(t *testing.T, s Server) { - key := ari.NewKey(ari.MailboxKey, "mbox1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var expected ari.MailboxData - expected.Name = "mbox1" - expected.NewMessages = 2 - expected.OldMessages = 3 - - m.Mailbox.On("Data", key).Return(&expected, nil) - - data, err := cl.Mailbox().Data(key) - if err != nil { - t.Errorf("Unexpected error in remote mailbox Data: %s", err) - } - if data == nil { - t.Errorf("Expected non-nil mailbox data") - } else { - failed := data.Name != expected.Name - failed = failed || data.NewMessages != expected.NewMessages - failed = failed || data.OldMessages != expected.OldMessages - if failed { - t.Errorf("Expected data '%v', got '%v'", expected, data) - } - } - - m.Mailbox.AssertCalled(t, "Data", key) - }) - - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - expected := errors.New("error") - - m.Mailbox.On("Data", key).Return(nil, expected) - - _, err := cl.Mailbox().Data(key) - - failed := false - failed = failed || err == nil && expected != nil - failed = failed || err != nil && expected == nil - failed = failed || err != nil && expected != nil && err.Error() != expected.Error() - if failed { - t.Errorf("Expected mailbox %s(%s) to return '%v', got '%v'", - "Data", "mbox1", expected, err, - ) - } - - m.Mailbox.AssertCalled(t, "Data", key) - }) -} diff --git a/v5/internal/integration/mock.go b/v5/internal/integration/mock.go deleted file mode 100644 index 02ca63f..0000000 --- a/v5/internal/integration/mock.go +++ /dev/null @@ -1,82 +0,0 @@ -package integration - -import ( - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/client/arimocks" - tmock "github.com/stretchr/testify/mock" -) - -type mock struct { - Bus *arimocks.Bus - Client *arimocks.Client - - Application *arimocks.Application - Asterisk *arimocks.Asterisk - Bridge *arimocks.Bridge - Channel *arimocks.Channel - DeviceState *arimocks.DeviceState - Endpoint *arimocks.Endpoint - LiveRecording *arimocks.LiveRecording - Logging *arimocks.Logging - Mailbox *arimocks.Mailbox - Modules *arimocks.Modules - Playback *arimocks.Playback - Sound *arimocks.Sound - - AllSub *arimocks.Subscription - AllEventChannel <-chan ari.Event - - Shutdown func() -} - -func standardMock() *mock { - m := &mock{} - - m.Bus = &arimocks.Bus{} - m.Client = &arimocks.Client{} - - m.Asterisk = &arimocks.Asterisk{} - m.Application = &arimocks.Application{} - m.Bridge = &arimocks.Bridge{} - m.Channel = &arimocks.Channel{} - m.DeviceState = &arimocks.DeviceState{} - m.Endpoint = &arimocks.Endpoint{} - m.LiveRecording = &arimocks.LiveRecording{} - m.Logging = &arimocks.Logging{} - m.Mailbox = &arimocks.Mailbox{} - m.Modules = &arimocks.Modules{} - m.Playback = &arimocks.Playback{} - m.Sound = &arimocks.Sound{} - - m.AllSub = &arimocks.Subscription{} - - eventCh := make(<-chan ari.Event) - - m.AllSub.On("Cancel").Return(nil) - m.AllSub.On("Events").Return(eventCh) - m.Bus.On("Subscribe", tmock.Anything, "all").Return(m.AllSub).Times(1) - - m.Client.On("Bus").Return(m.Bus) - - m.Client.On("ApplicationName").Return("asdf") - m.Client.On("Asterisk").Return(m.Asterisk) - m.Client.On("Application").Return(m.Application) - m.Client.On("Bridge").Return(m.Bridge) - m.Client.On("Channel").Return(m.Channel) - m.Client.On("DeviceState").Return(m.DeviceState) - m.Client.On("Endpoint").Return(m.Endpoint) - m.Client.On("LiveRecording").Return(m.LiveRecording) - m.Asterisk.On("Logging").Return(m.Logging) - m.Client.On("Mailbox").Return(m.Mailbox) - m.Asterisk.On("Modules").Return(m.Modules) - m.Client.On("Playback").Return(m.Playback) - m.Client.On("Sound").Return(m.Sound) - - m.Asterisk.On("Info", (*ari.Key)(nil)).Return(&ari.AsteriskInfo{ - SystemInfo: ari.SystemInfo{ - EntityID: "1", - }, - }, nil).Times(1) // ensure that downstream tests of Info do not struggle to test additional cases - - return m -} diff --git a/v5/internal/integration/modules.go b/v5/internal/integration/modules.go deleted file mode 100644 index 8bd6d9d..0000000 --- a/v5/internal/integration/modules.go +++ /dev/null @@ -1,174 +0,0 @@ -package integration - -import ( - "errors" - "testing" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestModulesLoad(t *testing.T, s Server) { - key := ari.NewKey(ari.ModuleKey, "m1") - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Modules.On("Load", key).Return(nil) - - if err := cl.Asterisk().Modules().Load(key); err != nil { - t.Errorf("Unexpected error in module load: %s", err) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "Load", key) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Modules.On("Load", key).Return(errors.New("error")) - - if err := cl.Asterisk().Modules().Load(key); err == nil { - t.Errorf("Expected error in module load") - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "Load", key) - }) -} - -func TestModulesUnload(t *testing.T, s Server) { - key := ari.NewKey(ari.ModuleKey, "m1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Modules.On("Unload", key).Return(nil) - - if err := cl.Asterisk().Modules().Unload(key); err != nil { - t.Errorf("Unexpected error in module Unload: %s", err) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "Unload", key) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Modules.On("Unload", key).Return(errors.New("error")) - - if err := cl.Asterisk().Modules().Unload(key); err == nil { - t.Errorf("Expected error in module Unload") - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "Unload", key) - }) -} - -func TestModulesReload(t *testing.T, s Server) { - key := ari.NewKey(ari.ModuleKey, "m1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Modules.On("Reload", key).Return(nil) - - if err := cl.Asterisk().Modules().Reload(key); err != nil { - t.Errorf("Unexpected error in module Reload: %s", err) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "Reload", key) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Modules.On("Reload", key).Return(errors.New("error")) - - if err := cl.Asterisk().Modules().Reload(key); err == nil { - t.Errorf("Expected error in module Reload") - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "Reload", key) - }) -} - -func TestModulesData(t *testing.T, s Server) { - key := ari.NewKey(ari.ModuleKey, "m1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var d ari.ModuleData - d.Description = "Desc" - d.Name = "name" - - m.Modules.On("Data", key).Return(&d, nil) - - ret, err := cl.Asterisk().Modules().Data(key) - if err != nil { - t.Errorf("Unexpected error in module Data: %s", err) - } - if ret == nil { - t.Errorf("Expected module data to be non-nil") - } else { - if ret.Description != d.Description { - t.Errorf("description mismatch: %v %v", ret.Description, d.Description) - } - if ret.Name != d.Name { - t.Errorf("name mismatch: expected '%v', got '%v'", d, ret) - } - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "Data", key) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Modules.On("Data", key).Return(nil, errors.New("error")) - - _, err := cl.Asterisk().Modules().Data(key) - if err == nil { - t.Errorf("Expected error in module Data: %s", err) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "Data", key) - }) -} - -func TestModulesList(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m1 := ari.NewKey(ari.ModuleKey, "m1") - m2 := ari.NewKey(ari.ModuleKey, "m2") - - m.Modules.On("List", (*ari.Key)(nil)).Return([]*ari.Key{m1, m2}, nil) - - ret, err := cl.Asterisk().Modules().List(nil) - if err != nil { - t.Errorf("Unepected error in module List: %s", err) - } - if len(ret) != 2 { - t.Errorf("Expected handle list length of size '2', got '%d'", len(ret)) - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "List", (*ari.Key)(nil)) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Modules.On("List", (*ari.Key)(nil)).Return([]*ari.Key{}, errors.New("error")) - - _, err := cl.Asterisk().Modules().List(nil) - if err == nil { - t.Errorf("Expected error in module List") - } - - m.Shutdown() - - m.Asterisk.AssertCalled(t, "Modules") - m.Modules.AssertCalled(t, "List", (*ari.Key)(nil)) - }) -} diff --git a/v5/internal/integration/playback.go b/v5/internal/integration/playback.go deleted file mode 100644 index 3107e9a..0000000 --- a/v5/internal/integration/playback.go +++ /dev/null @@ -1,105 +0,0 @@ -package integration - -import ( - "errors" - "testing" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestPlaybackData(t *testing.T, s Server) { - key := ari.NewKey(ari.PlaybackKey, "pb1") - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var pb ari.PlaybackData - pb.ID = "pb1" - pb.State = "st1" - - m.Playback.On("Data", key).Return(&pb, nil) - - ret, err := cl.Playback().Data(key) - if err != nil { - t.Errorf("Unexpected error in Playback Data: %s", err) - } - if ret == nil { - t.Errorf("Expected Playback data to be non-nil") - } else { - if ret.ID != "pb1" && ret.State != "st1" { - t.Errorf("got '%v', expected '%v'", pb, ret) - } - } - - m.Shutdown() - - m.Playback.AssertCalled(t, "Data", key) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Playback.On("Data", key).Return(nil, errors.New("error")) - - _, err := cl.Playback().Data(key) - if err == nil { - t.Errorf("Expected error in Playback Data: %s", err) - } - - m.Shutdown() - - m.Playback.AssertCalled(t, "Data", key) - }) -} - -func TestPlaybackControl(t *testing.T, s Server) { - key := ari.NewKey(ari.PlaybackKey, "pb1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Playback.On("Control", key, "op").Return(nil) - - err := cl.Playback().Control(key, "op") - if err != nil { - t.Errorf("Unexpected error in Playback Control: %s", err) - } - - m.Shutdown() - - m.Playback.AssertCalled(t, "Control", key, "op") - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Playback.On("Control", key, "op").Return(errors.New("error")) - - err := cl.Playback().Control(key, "op") - if err == nil { - t.Errorf("Expected error in Playback Control: %s", err) - } - - m.Shutdown() - - m.Playback.AssertCalled(t, "Control", key, "op") - }) -} - -func TestPlaybackStop(t *testing.T, s Server) { - key := ari.NewKey(ari.PlaybackKey, "pb1") - - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Playback.On("Stop", key).Return(nil) - - err := cl.Playback().Stop(key) - if err != nil { - t.Errorf("Unexpected error in Playback Stop: %s", err) - } - - m.Shutdown() - - m.Playback.AssertCalled(t, "Stop", key) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Playback.On("Stop", key).Return(errors.New("error")) - - err := cl.Playback().Stop(key) - if err == nil { - t.Errorf("Expected error in Playback Stop: %s", err) - } - - m.Shutdown() - - m.Playback.AssertCalled(t, "Stop", key) - }) -} diff --git a/v5/internal/integration/sound.go b/v5/internal/integration/sound.go deleted file mode 100644 index 7525251..0000000 --- a/v5/internal/integration/sound.go +++ /dev/null @@ -1,86 +0,0 @@ -package integration - -import ( - "errors" - "testing" - - "github.com/CyCoreSystems/ari/v5" -) - -func TestSoundData(t *testing.T, s Server) { - key := ari.NewKey(ari.SoundKey, "s1") - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var sd ari.SoundData - sd.ID = "s1" - sd.Text = "text" - - m.Sound.On("Data", key).Return(&sd, nil) - - ret, err := cl.Sound().Data(key) - if err != nil { - t.Errorf("Unexpected error in Sound Data: %s", err) - } - if ret == nil { - t.Errorf("Expected data to be non-nil") - } else { - if ret.ID != sd.ID || ret.Text != sd.Text { - t.Errorf("Expected '%v', got '%v'", sd, ret) - } - } - - m.Shutdown() - - m.Sound.AssertCalled(t, "Data", key) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - m.Sound.On("Data", key).Return(nil, errors.New("error")) - - _, err := cl.Sound().Data(key) - if err == nil { - t.Errorf("Expected error in Sound Data: %s", err) - } - - m.Shutdown() - - m.Sound.AssertCalled(t, "Data", key) - }) -} - -func TestSoundList(t *testing.T, s Server) { - runTest("ok", t, s, func(t *testing.T, m *mock, cl ari.Client) { - sh1 := ari.NewKey(ari.SoundKey, "sh1") - sh2 := ari.NewKey(ari.SoundKey, "sh2") - - var filter map[string]string - - m.Sound.On("List", filter, &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}).Return([]*ari.Key{sh1, sh2}, nil) - - ret, err := cl.Sound().List(nil, nil) - if err != nil { - t.Errorf("Unexpected error in Sound List: %s", err) - } - if len(ret) != 2 { - t.Errorf("Expected handle list length to be 2, got '%d'", len(ret)) - } - - m.Shutdown() - - m.Sound.AssertCalled(t, "List", filter, &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}) - }) - runTest("err", t, s, func(t *testing.T, m *mock, cl ari.Client) { - var filter map[string]string - - m.Sound.On("List", filter, &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}).Return(nil, errors.New("error")) - - ret, err := cl.Sound().List(nil, nil) - if err == nil { - t.Errorf("Expected error in Sound Data: %s", err) - } - if len(ret) != 0 { - t.Errorf("Expected handle list length to be 0, got '%d'", len(ret)) - } - m.Shutdown() - - m.Sound.AssertCalled(t, "List", filter, &ari.Key{Kind: "", ID: "", Node: "", Dialog: "", App: ""}) - }) -} diff --git a/v5/main.go b/v5/main.go deleted file mode 100644 index 916ddea..0000000 --- a/v5/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -var version = "master" - -func main() { - if err := RootCmd.Execute(); err != nil { - Log.Error("server died", "error", err) - } -} diff --git a/v5/proxy/subjects.go b/v5/proxy/subjects.go deleted file mode 100644 index 11d307c..0000000 --- a/v5/proxy/subjects.go +++ /dev/null @@ -1,15 +0,0 @@ -package proxy - -import "fmt" - -// Subject returns the communication subject for the given parameters -func Subject(prefix, class, appName, asterisk string) (ret string) { - ret = fmt.Sprintf("%s%s", prefix, class) - if appName != "" { - ret += "." + appName - if asterisk != "" { - ret += "." + asterisk - } - } - return -} diff --git a/v5/proxy/types.go b/v5/proxy/types.go deleted file mode 100644 index 6ec6c12..0000000 --- a/v5/proxy/types.go +++ /dev/null @@ -1,373 +0,0 @@ -package proxy - -import ( - "errors" - "fmt" - "time" - - "github.com/CyCoreSystems/ari/v5" -) - -// AnnouncementInterval is the amount of time to wait between periodic service availability announcements -var AnnouncementInterval = time.Minute - -// Announcement describes the structure of an ARI proxy's announcement of availability on the network. These are sent periodically and upon request (by a Ping). -type Announcement struct { - // Node indicates the Asterisk ID to which the proxy is connected - Node string `json:"node"` - - // Application indicates the ARI application as which the proxy is connected - Application string `json:"application"` -} - -// AnnouncementSubject returns the NATS subject -func AnnouncementSubject(prefix string) string { - return fmt.Sprintf("%sannounce", prefix) -} - -// PingSubject returns the NATS subject for a cluster-wide proxy ping for presence -func PingSubject(prefix string) string { - return fmt.Sprintf("%sping", prefix) -} - -// EntityData is a response which returns the data for a specific entity. -type EntityData struct { - Application *ari.ApplicationData `json:"application,omitempty"` - Asterisk *ari.AsteriskInfo `json:"asterisk,omitempty"` - Bridge *ari.BridgeData `json:"bridge,omitempty"` - Channel *ari.ChannelData `json:"channel,omitempty"` - Config *ari.ConfigData `json:"config,omitempty"` - DeviceState *ari.DeviceStateData `json:"device_state,omitempty"` - Endpoint *ari.EndpointData `json:"endpoint,omitempty"` - LiveRecording *ari.LiveRecordingData `json:"live_recording,omitempty"` - Log *ari.LogData `json:"log,omitempty"` - Mailbox *ari.MailboxData `json:"mailbox,omitempty"` - Module *ari.ModuleData `json:"module,omitempty"` - Playback *ari.PlaybackData `json:"playback,omitempty"` - Sound *ari.SoundData `json:"sound,omitempty"` - StoredRecording *ari.StoredRecordingData `json:"stored_recording,omitempty"` - TextMessage *ari.TextMessageData `json:"text_message,omitempty"` - - Variable string `json:"variable,omitempty"` -} - -// ErrNotFound indicates that the operation did not return a result -var ErrNotFound = errors.New("Not found") - -// Response is a response to a request. This acts as a base type for more complicated responses, as well. -type Response struct { - // Error is the error encountered - Error string `json:"error"` - - // Data is the returned entity data, if applicable - Data *EntityData `json:"data,omitempty"` - - // Key is the key of the returned entity, if applicable - Key *ari.Key `json:"key,omitempty"` - - // Keys is the list of keys of any matching entities, if applicable - Keys []*ari.Key `json:"keys,omitempty"` -} - -// Err returns an error from the Response. If the response's Error is empty, a nil error is returned. Otherwise, the error will be filled with the value of response.Error. -func (e *Response) Err() error { - if e == nil { - return nil - } - if e.Error != "" { - return errors.New(e.Error) - } - return nil -} - -// IsNotFound indicates that the retuned error response was a Not Found error response -func (e *Response) IsNotFound() bool { - return e.Error == "Not found" -} - -// NewErrorResponse wraps an error as an ErrorResponse -func NewErrorResponse(err error) *Response { - if err == nil { - return &Response{} - } - return &Response{Error: err.Error()} -} - -// Request describes a request which is sent from an ARI proxy Client to an ARI proxy Server -type Request struct { - // Kind indicates the type of request - Kind string `json:"kind"` - - // Key is the key or key filter on which this request should be processed - Key *ari.Key `json:"key"` - - ApplicationSubscribe *ApplicationSubscribe `json:"application_subscribe,omitempty"` - - AsteriskConfig *AsteriskConfig `json:"asterisk_config,omitempty"` - AsteriskLoggingChannel *AsteriskLoggingChannel `json:"asterisk_logging_channel,omitempty"` - AsteriskVariableSet *AsteriskVariableSet `json:"asterisk_variable_set,omitempty"` - - BridgeAddChannel *BridgeAddChannel `json:"bridge_add_channel,omitempty"` - BridgeCreate *BridgeCreate `json:"bridge_create,omitempty"` - BridgeMOH *BridgeMOH `json:"bridge_moh,omitempty"` - BridgePlay *BridgePlay `json:"bridge_play,omitempty"` - BridgeRecord *BridgeRecord `json:"bridge_record,omitempty"` - BridgeRemoveChannel *BridgeRemoveChannel `json:"bridge_remove_channel,omitempty"` - BridgeVideoSource *BridgeVideoSource `json:"bridge_video_source,omitempty"` - - ChannelCreate *ChannelCreate `json:"channel_create,omitempty"` - ChannelContinue *ChannelContinue `json:"channel_continue,omitempty"` - ChannelDial *ChannelDial `json:"channel_dial,omitempty"` - ChannelHangup *ChannelHangup `json:"channel_hangup,omitempty"` - ChannelMOH *ChannelMOH `json:"channel_moh,omitempty"` - ChannelMute *ChannelMute `json:"channel_mute,omitempty"` - ChannelOriginate *ChannelOriginate `json:"channel_originate,omitempty"` - ChannelPlay *ChannelPlay `json:"channel_play,omitempty"` - ChannelRecord *ChannelRecord `json:"channel_record,omitempty"` - ChannelSendDTMF *ChannelSendDTMF `json:"channel_send_dtmf,omitempty"` - ChannelSnoop *ChannelSnoop `json:"channel_snoop,omitempty"` - ChannelExternalMedia *ChannelExternalMedia `json:"channel_external_media,omitempty"` - ChannelVariable *ChannelVariable `json:"channel_variable,omitempty"` - - DeviceStateUpdate *DeviceStateUpdate `json:"device_state_update,omitempty"` - - EndpointListByTech *EndpointListByTech `json:"endpoint_list_by_tech,omitempty"` - - MailboxUpdate *MailboxUpdate `json:"mailbox_update,omitempty"` - - PlaybackControl *PlaybackControl `json:"playback_control,omitempty"` - - RecordingStoredCopy *RecordingStoredCopy `json:"recording_stored_copy,omitempty"` - - SoundList *SoundList `json:"sound_list,omitempty"` -} - -// ApplicationSubscribe describes a request to subscribe/unsubscribe a particular ARI application to an EventSource -type ApplicationSubscribe struct { - // EventSource is the ARI event source to which the subscription is requested. This should be one of: - // - channel: - // - bridge: - // - endpoint:/ (e.g. SIP/102) - // - deviceState: - EventSource string `json:"event_source"` -} - -// AsteriskVariableSet is the request type for setting an asterisk variable -type AsteriskVariableSet struct { - // Value is the value to set - Value string `json:"value"` -} - -// BridgeAddChannel is the request type for adding a channel to a bridge -type BridgeAddChannel struct { - // Channel is the channel ID to add to the bridge - Channel string `json:"channel"` - - // AbsorbDTMF indicates that DTMF coming from this channel will not be passed through to the bridge - AbsorbDTMF bool `json:"absorbDTMF,omitempty"` - - // Mute indicates that the channel should be muted, preventing audio from it passing through to the bridge - Mute bool `json:"mute,omitempty"` - - // Role indicates the channel's role in the bridge - Role string `json:"role,omitempty"` -} - -// BridgeCreate is the request type for creating a bridge -type BridgeCreate struct { - // Type is the comma-separated list of bridge type attributes (mixing, - // holding, dtmf_events, proxy_media). If not set, the default (mixing) - // will be used. - Type string `json:"type"` - - // Name is the name to assign to the bridge (optional) - Name string `json:"name,omitempty"` -} - -// BridgeMOH is the request type for playing Music on Hold to a bridge -type BridgeMOH struct { - // Class is the Music On Hold class to be played - Class string `json:"class"` -} - -// BridgePlay is the request type for playing audio on the bridge -type BridgePlay struct { - // PlaybackID is the unique identifier for this playback - PlaybackID string `json:"playback_id"` - - // MediaURI is the URI from which to obtain the playback media - MediaURI string `json:"media_uri"` -} - -// BridgeRecord is the request for recording a bridge -type BridgeRecord struct { - // Name is the name for the recording - Name string `json:"name"` - - // Options is the list of recording Options - Options *ari.RecordingOptions `json:"options,omitempty"` -} - -// BridgeRemoveChannel is the request for removing a channel on the bridge -type BridgeRemoveChannel struct { - // Channel is the name of the channel to remove - Channel string `json:"channel"` -} - -// BridgeVideoSource describes the details of a request to set the video source of a bridge explicitly -type BridgeVideoSource struct { - // Channel is the name of the channel to use as the explicit video source - Channel string `json:"channel"` -} - -// ChannelCreate describes a request to create a new channel -type ChannelCreate struct { - // ChannelCreateRequest is the request for creating the channel - ChannelCreateRequest ari.ChannelCreateRequest `json:"channel_create_request"` -} - -// ChannelContinue describes a request to continue an ARI application -type ChannelContinue struct { - // Context is the context into which the channel should be continued - Context string `json:"context"` - - // Extension is the extension into which the channel should be continued - Extension string `json:"extension"` - - // Priority is the priority at which the channel should be continued - Priority int `json:"priority"` -} - -// ChannelDial describes a request to dial -type ChannelDial struct { - // Caller is the channel ID of the "caller" channel; if specified, the media parameters of the dialing channel will be matched to the "caller" channel. - Caller string `json:"caller"` - - // Timeout is the maximum time which should be allowed for the dial to complete - Timeout time.Duration `json:"timeout"` -} - -// ChannelHangup is the request for hanging up a channel -type ChannelHangup struct { - // Reason is the reason the channel is being hung up - Reason string `json:"reason"` -} - -// ChannelMOH is the request playing hold on music on a channel -type ChannelMOH struct { - // Music is the music to play - Music string `json:"music"` -} - -// ChannelMute is the request for muting or unmuting a channel -type ChannelMute struct { - // Direction is the direction to mute - Direction ari.Direction `json:"direction,omitempty"` -} - -// ChannelOriginate is the request for creating a channel -type ChannelOriginate struct { - // OriginateRequest contains the information for originating a channel - OriginateRequest ari.OriginateRequest `json:"originate_request"` -} - -// ChannelPlay is the request for playing audio on a channel -type ChannelPlay struct { - // PlaybackID is the unique identifier for this playback - PlaybackID string `json:"playback_id"` - - // MediaURI is the URI from which to obtain the playback media - MediaURI string `json:"media_uri"` -} - -// ChannelRecord is the request for recording a channel -type ChannelRecord struct { - // Name is the name for the recording - Name string `json:"name"` - - // Options is the list of recording Options - Options *ari.RecordingOptions `json:"options,omitempty"` -} - -// ChannelSendDTMF is the request for sending a DTMF event to a channel -type ChannelSendDTMF struct { - // DTMF is the series of DTMF inputs to send - DTMF string `json:"dtmf"` - - // Options are the DTMF options - Options *ari.DTMFOptions `json:"options,omitempty"` -} - -// ChannelSnoop is the request for snooping on a channel -type ChannelSnoop struct { - // SnoopID is the ID to use for the snoop channel which will be created. - SnoopID string `json:"snoop_id"` - - // Options describe the parameters for the snoop session - Options *ari.SnoopOptions `json:"options,omitempty"` -} - -// ChannelExternalMedia describes the request for an external media channel -type ChannelExternalMedia struct { - Options ari.ExternalMediaOptions `json:"options"` -} - -// ChannelVariable is the request type to read or modify a channel variable -type ChannelVariable struct { - // Name is the name of the channel variable - Name string `json:"name"` - - // Value is the value to set to the channel variable - Value string `json:"value,omitempty"` -} - -// DeviceStateUpdate describes the request for updating the device state -type DeviceStateUpdate struct { - // State is the new state of the device to set - State string `json:"state"` -} - -// EndpointListByTech describes the request for listing endpoints by technology -type EndpointListByTech struct { - // Tech is the technology for the endpoint - Tech string `json:"tech"` -} - -// MailboxUpdate describes the request for updating a mailbox -type MailboxUpdate struct { - // New is the number of New (unread) messages in the mailbox - New int `json:"new"` - - // Old is the number of Old (read) messages in the mailbox - Old int `json:"old"` -} - -// PlaybackControl describes the request for performing a playback command -type PlaybackControl struct { - // Command is the playback control command to run - Command string `json:"command"` -} - -// RecordingStoredCopy describes the request for copying a stored recording -type RecordingStoredCopy struct { - // Destination is the destination location to copy to - Destination string `json:"destination"` -} - -// SoundList describes the request for listing the sounds -type SoundList struct { - // Filters are the filters to apply when listing the sounds - Filters map[string]string `json:"filters"` -} - -// AsteriskConfig describes the request relating to asterisk configuration -type AsteriskConfig struct { - // Tuples is the list of configuration tuples to update - Tuples []ari.ConfigTuple `json:"tuples,omitempty"` -} - -// AsteriskLoggingChannel describes a request relating to an asterisk logging channel -type AsteriskLoggingChannel struct { - // Levels is the set of logging levels for this logging channel (comma-separated string) - Levels string `json:"config"` -} diff --git a/v5/server/application.go b/v5/server/application.go deleted file mode 100644 index f8a281f..0000000 --- a/v5/server/application.go +++ /dev/null @@ -1,89 +0,0 @@ -package server - -import ( - "context" - "errors" - "strings" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) applicationData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Application().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Application: data, - }, - }) -} - -func (s *Server) applicationList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.Application().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} - -func (s *Server) applicationGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Application().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func parseEventSource(src string) (string, string, error) { - var err error - - pieces := strings.Split(src, ":") - if len(pieces) != 2 { - return "", "", errors.New("Invalid EventSource") - } - - switch pieces[0] { - case "channel": - case "bridge": - case "endpoint": - case "deviceState": - default: - err = errors.New("Unhandled EventSource type") - } - return pieces[0], pieces[1], err -} - -func (s *Server) applicationSubscribe(ctx context.Context, reply string, req *proxy.Request) { - err := s.ari.Application().Subscribe(req.Key, req.ApplicationSubscribe.EventSource) - if err != nil { - s.sendError(reply, err) - return - } - - if req.Key.Dialog != "" { - eType, eID, err := parseEventSource(req.ApplicationSubscribe.EventSource) - if err != nil { - s.Log.Warn("failed to parse event source", "error", err, "eventsource", req.ApplicationSubscribe.EventSource) - } else { - s.Dialog.Bind(req.Key.Dialog, eType, eID) - } - } - - s.sendError(reply, nil) -} - -func (s *Server) applicationUnsubscribe(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Application().Unsubscribe(req.Key, req.ApplicationSubscribe.EventSource)) -} diff --git a/v5/server/application_test.go b/v5/server/application_test.go deleted file mode 100644 index 20f7022..0000000 --- a/v5/server/application_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestApplicationList(t *testing.T) { - integration.TestApplicationList(t, &srv{}) -} - -func TestApplicationData(t *testing.T) { - integration.TestApplicationData(t, &srv{}) -} - -func TestApplicationSubscribe(t *testing.T) { - integration.TestApplicationSubscribe(t, &srv{}) -} - -func TestApplicationUnsubscribe(t *testing.T) { - integration.TestApplicationUnsubscribe(t, &srv{}) -} - -func TestApplicationGet(t *testing.T) { - integration.TestApplicationGet(t, &srv{}) -} diff --git a/v5/server/asterisk.go b/v5/server/asterisk.go deleted file mode 100644 index 1bdd80d..0000000 --- a/v5/server/asterisk.go +++ /dev/null @@ -1,45 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) asteriskInfo(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Asterisk().Info(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Asterisk: data, - }, - }) -} - -func (s *Server) asteriskVariableGet(ctx context.Context, reply string, req *proxy.Request) { - val, err := s.ari.Asterisk().Variables().Get(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Variable: val, - }, - }) -} - -func (s *Server) asteriskVariableSet(ctx context.Context, reply string, req *proxy.Request) { - err := s.ari.Asterisk().Variables().Set(req.Key, req.AsteriskVariableSet.Value) - if err != nil { - s.sendError(reply, err) - return - } - - s.sendError(reply, nil) -} diff --git a/v5/server/asterisk_test.go b/v5/server/asterisk_test.go deleted file mode 100644 index 6f56e8e..0000000 --- a/v5/server/asterisk_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestAsteriskInfo(t *testing.T) { - integration.TestAsteriskInfo(t, &srv{}) -} - -func TestAsteriskVariablesGet(t *testing.T) { - integration.TestAsteriskVariablesGet(t, &srv{}) -} - -func TestAsteriskVariablesSet(t *testing.T) { - integration.TestAsteriskVariablesSet(t, &srv{}) -} diff --git a/v5/server/bridge.go b/v5/server/bridge.go deleted file mode 100644 index 3b409a4..0000000 --- a/v5/server/bridge.go +++ /dev/null @@ -1,287 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - rid "github.com/CyCoreSystems/ari-rid" - "github.com/CyCoreSystems/ari/v5" -) - -func (s *Server) bridgeAddChannel(ctx context.Context, reply string, req *proxy.Request) { - channel := req.BridgeAddChannel.Channel - - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "channel", channel) - } - - err := s.ari.Bridge().AddChannel(req.Key, channel) - if err != nil { - s.sendError(reply, err) - return - } - - s.sendError(reply, nil) -} - -func (s *Server) bridgeCreate(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - } - - h, err := s.ari.Bridge().Create(req.Key, req.BridgeCreate.Type, req.BridgeCreate.Name) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) bridgeStageCreate(ctx context.Context, reply string, req *proxy.Request) { - bh := s.ari.Bridge().Get(req.Key) - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - } - - s.publish(reply, &proxy.Response{ - Key: bh.Key(), - }) -} - -func (s *Server) bridgeData(ctx context.Context, reply string, req *proxy.Request) { - bd, err := s.ari.Bridge().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Bridge: bd, - }, - }) -} - -func (s *Server) bridgeDelete(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - } - - err := s.ari.Bridge().Delete(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.sendError(reply, nil) -} - -func (s *Server) bridgeGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Bridge().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) bridgeList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.Bridge().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} - -func (s *Server) bridgeMOH(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - } - - s.sendError( - reply, - s.ari.Bridge().MOH(req.Key, req.BridgeMOH.Class), - ) -} - -func (s *Server) bridgeStopMOH(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - } - - s.sendError( - reply, - s.ari.Bridge().StopMOH(req.Key), - ) -} - -func (s *Server) bridgePlay(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "playback", req.BridgePlay.PlaybackID) - } - - ph, err := s.ari.Bridge().Play(req.Key, req.BridgePlay.PlaybackID, req.BridgePlay.MediaURI) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: ph.Key(), - }) -} - -func (s *Server) bridgeStagePlay(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Bridge().Data(req.Key) - if err != nil || data == nil { - s.sendError(reply, err) - return - } - - if req.BridgePlay.PlaybackID == "" { - req.BridgePlay.PlaybackID = rid.New(rid.Playback) - } - - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "playback", req.BridgePlay.PlaybackID) - } - - s.publish(reply, &proxy.Response{ - Key: s.ari.Playback().Get(ari.NewKey(ari.PlaybackKey, req.BridgePlay.PlaybackID)).Key(), - }) -} - -func (s *Server) bridgeRecord(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Bridge().Data(req.Key) - if err != nil || data == nil { - s.sendError(reply, err) - return - } - - if req.BridgeRecord.Name == "" { - req.BridgeRecord.Name = rid.New(rid.Recording) - } - - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "recording", req.BridgeRecord.Name) - } - - h, err := s.ari.Bridge().Record(req.Key, req.BridgeRecord.Name, req.BridgeRecord.Options) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) bridgeStageRecord(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Bridge().Data(req.Key) - if err != nil || data == nil { - s.sendError(reply, err) - return - } - - if req.BridgeRecord.Name == "" { - req.BridgeRecord.Name = rid.New(rid.Recording) - } - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", data.ID) - s.Dialog.Bind(req.Key.Dialog, "recording", req.BridgeRecord.Name) - } - - s.publish(reply, &proxy.Response{ - Key: data.Key.New(ari.LiveRecordingKey, req.BridgeRecord.Name), - }) -} - -func (s *Server) bridgeRemoveChannel(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "channel", req.BridgeRemoveChannel.Channel) - } - - err := s.ari.Bridge().RemoveChannel(req.Key, req.BridgeRemoveChannel.Channel) - if err != nil { - s.sendError(reply, err) - return - } - - s.sendError(reply, nil) -} - -func (s *Server) bridgeSubscribe(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - } - - s.sendError(reply, nil) -} - -func (s *Server) bridgeUnsubscribe(ctx context.Context, reply string, req *proxy.Request) { - // no-op for now; may want to eventually optimize away the dialog subscription - s.sendError(reply, nil) -} - -func (s *Server) bridgeVideoSource(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "channel", req.BridgeVideoSource.Channel) - } - - err := s.ari.Bridge().VideoSource(req.Key, req.BridgeVideoSource.Channel) - if err != nil { - s.sendError(reply, err) - return - } - - s.sendError(reply, nil) -} - -func (s *Server) bridgeVideoSourceDelete(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "bridge", req.Key.ID) - } - - err := s.ari.Bridge().VideoSourceDelete(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.sendError(reply, nil) -} diff --git a/v5/server/bridge_test.go b/v5/server/bridge_test.go deleted file mode 100644 index 220f5fe..0000000 --- a/v5/server/bridge_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestBridgeCreate(t *testing.T) { - integration.TestBridgeCreate(t, &srv{}) -} - -func TestBridgeList(t *testing.T) { - integration.TestBridgeList(t, &srv{}) -} - -func TestBridgeData(t *testing.T) { - integration.TestBridgeData(t, &srv{}) -} - -func TestBridgeAddChannel(t *testing.T) { - integration.TestBridgeAddChannel(t, &srv{}) -} - -func TestBridgeRemoveChannel(t *testing.T) { - integration.TestBridgeRemoveChannel(t, &srv{}) -} - -func TestBridgeDelete(t *testing.T) { - integration.TestBridgeDelete(t, &srv{}) -} - -func TestBridgePlay(t *testing.T) { - integration.TestBridgePlay(t, &srv{}) -} - -func TestBridgeRecord(t *testing.T) { - integration.TestBridgeRecord(t, &srv{}) -} diff --git a/v5/server/channel.go b/v5/server/channel.go deleted file mode 100644 index a1c82bf..0000000 --- a/v5/server/channel.go +++ /dev/null @@ -1,433 +0,0 @@ -package server - -import ( - "context" - "errors" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - rid "github.com/CyCoreSystems/ari-rid" - "github.com/CyCoreSystems/ari/v5" -) - -func (s *Server) channelAnswer(ctx context.Context, reply string, req *proxy.Request) { - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", req.Key.ID) - } - - s.sendError(reply, s.ari.Channel().Answer(req.Key)) -} - -func (s *Server) channelBusy(ctx context.Context, reply string, req *proxy.Request) { - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", req.Key.ID) - } - - s.sendError(reply, s.ari.Channel().Busy(req.Key)) -} - -func (s *Server) channelCongestion(ctx context.Context, reply string, req *proxy.Request) { - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", req.Key.ID) - } - - s.sendError(reply, s.ari.Channel().Congestion(req.Key)) -} - -func (s *Server) channelCreate(ctx context.Context, reply string, req *proxy.Request) { - create := req.ChannelCreate.ChannelCreateRequest - - if create.ChannelID == "" { - create.ChannelID = rid.New(rid.Channel) - } - - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", create.ChannelID) - s.Dialog.Bind(req.Key.Dialog, "channel", create.OtherChannelID) - } - - h, err := s.ari.Channel().Create(req.Key, create) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) channelData(ctx context.Context, reply string, req *proxy.Request) { - d, err := s.ari.Channel().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Channel: d, - }, - }) -} - -func (s *Server) channelGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Channel().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) channelContinue(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().Continue(req.Key, req.ChannelContinue.Context, req.ChannelContinue.Extension, req.ChannelContinue.Priority)) -} - -func (s *Server) channelDial(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().Dial(req.Key, req.ChannelDial.Caller, req.ChannelDial.Timeout)) -} - -func (s *Server) channelHangup(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().Hangup(req.Key, req.ChannelHangup.Reason)) -} - -func (s *Server) channelHold(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().Hold(req.Key)) -} - -func (s *Server) channelList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.Channel().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} - -func (s *Server) channelMOH(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().MOH(req.Key, req.ChannelMOH.Music)) -} - -func (s *Server) channelMute(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().Mute(req.Key, req.ChannelMute.Direction)) -} - -func (s *Server) channelOriginate(ctx context.Context, reply string, req *proxy.Request) { - if req.ChannelOriginate == nil { - s.sendError(reply, errors.New("OriginateRequest is mandatory")) - return - } - orig := req.ChannelOriginate.OriginateRequest - - if orig.ChannelID == "" { - orig.ChannelID = rid.New(rid.Channel) - } - - if req.Key != nil && req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", orig.ChannelID) - if orig.OtherChannelID != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", orig.OtherChannelID) - } - if orig.Originator != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", orig.Originator) - } - if req.Key.ID != orig.Originator { - s.Dialog.Bind(req.Key.Dialog, "channel", req.Key.ID) - } - } - - h, err := s.ari.Channel().Originate(req.Key, orig) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) channelStageOriginate(ctx context.Context, reply string, req *proxy.Request) { - if req.ChannelOriginate == nil { - s.sendError(reply, errors.New("OriginateRequest is mandatory")) - return - } - orig := req.ChannelOriginate.OriginateRequest - - if orig.ChannelID == "" { - orig.ChannelID = rid.New(rid.Channel) - } - - if req.Key != nil && req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", orig.ChannelID) - if orig.OtherChannelID != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", orig.OtherChannelID) - } - if orig.Originator != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", orig.Originator) - } - if req.Key.ID != orig.Originator { - s.Dialog.Bind(req.Key.Dialog, "channel", req.Key.ID) - } - } - - h, err := s.ari.Channel().StageOriginate(req.Key, orig) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) channelPlay(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Channel().Data(req.Key) - if err != nil || data == nil { - s.sendError(reply, err) - return - } - - if req.ChannelPlay.PlaybackID == "" { - req.ChannelPlay.PlaybackID = rid.New(rid.Playback) - } - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "playback", req.ChannelPlay.PlaybackID) - } - - ph, err := s.ari.Channel().Play(req.Key, req.ChannelPlay.PlaybackID, req.ChannelPlay.MediaURI) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: ph.Key(), - }) -} - -func (s *Server) channelStagePlay(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Channel().Data(req.Key) - if err != nil || data == nil { - s.Log.Debug("failed to get channel data", "channel", req.Key) - s.sendError(reply, err) - return - } - - if req.ChannelPlay.PlaybackID == "" { - req.ChannelPlay.PlaybackID = rid.New(rid.Playback) - } - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", data.ID) - s.Dialog.Bind(req.Key.Dialog, "playback", req.ChannelPlay.PlaybackID) - } - - s.publish(reply, &proxy.Response{ - Key: s.ari.Playback().Get(ari.NewKey(ari.PlaybackKey, req.ChannelPlay.PlaybackID)).Key(), - }) -} - -func (s *Server) channelRecord(ctx context.Context, reply string, req *proxy.Request) { - if req.ChannelRecord.Name == "" { - req.ChannelRecord.Name = rid.New(rid.Recording) - } - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", req.Key.ID) - s.Dialog.Bind(req.Key.Dialog, "recording", req.ChannelRecord.Name) - } - - h, err := s.ari.Channel().Record(req.Key, req.ChannelRecord.Name, req.ChannelRecord.Options) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) channelStageRecord(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Channel().Data(req.Key) - if err != nil || data == nil { - s.sendError(reply, err) - return - } - - if req.ChannelRecord.Name == "" { - req.ChannelRecord.Name = rid.New(rid.Recording) - } - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", data.ID) - s.Dialog.Bind(req.Key.Dialog, "recording", req.ChannelRecord.Name) - } - - s.publish(reply, &proxy.Response{ - Key: data.Key.New(ari.LiveRecordingKey, req.ChannelRecord.Name), - }) -} - -func (s *Server) channelRing(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().Ring(req.Key)) -} - -func (s *Server) channelSendDTMF(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().SendDTMF(req.Key, req.ChannelSendDTMF.DTMF, req.ChannelSendDTMF.Options)) -} - -func (s *Server) channelSilence(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().Silence(req.Key)) -} - -func (s *Server) channelSnoop(ctx context.Context, reply string, req *proxy.Request) { - if req.ChannelSnoop.SnoopID == "" { - req.ChannelSnoop.SnoopID = rid.New(rid.Snoop) - } - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", req.ChannelSnoop.SnoopID) - } - - h, err := s.ari.Channel().Snoop(req.Key, req.ChannelSnoop.SnoopID, req.ChannelSnoop.Options) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) channelStageSnoop(ctx context.Context, reply string, req *proxy.Request) { - // Snoop requires a reference channel to exist - data, err := s.ari.Channel().Data(req.Key) - if err != nil || data == nil { - s.sendError(reply, err) - return - } - - if req.ChannelSnoop.SnoopID == "" { - req.ChannelSnoop.SnoopID = rid.New(rid.Snoop) - } - - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", req.ChannelSnoop.SnoopID) - } - - s.publish(reply, &proxy.Response{ - Key: s.ari.Channel().Get(ari.NewKey(ari.ChannelKey, req.ChannelSnoop.SnoopID)).Key(), - }) -} - -func (s *Server) channelExternalMedia(ctx context.Context, reply string, req *proxy.Request) { - if req.ChannelExternalMedia == nil { - s.sendError(reply, errors.New("ExternalMediaOptions is required")) - return - } - opts := req.ChannelExternalMedia.Options - - if opts.ChannelID == "" { - opts.ChannelID = rid.New(rid.Channel) - } - - if req.Key != nil && req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", opts.ChannelID) - } - - h, err := s.ari.Channel().ExternalMedia(req.Key, opts) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) channelStageExternalMedia(ctx context.Context, reply string, req *proxy.Request) { - if req.ChannelExternalMedia == nil { - s.sendError(reply, errors.New("ExternalMediaOptions is required")) - return - } - opts := req.ChannelExternalMedia.Options - - if opts.ChannelID == "" { - opts.ChannelID = rid.New(rid.Channel) - } - - if req.Key != nil && req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", opts.ChannelID) - } - - h, err := s.ari.Channel().StageExternalMedia(req.Key, opts) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) channelStopHold(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().StopHold(req.Key)) -} - -func (s *Server) channelStopMOH(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().StopMOH(req.Key)) -} - -func (s *Server) channelStopRing(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().StopRing(req.Key)) -} - -func (s *Server) channelStopSilence(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().StopSilence(req.Key)) -} - -func (s *Server) channelSubscribe(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "channel", req.Key.ID) - } - - s.sendError(reply, nil) -} - -func (s *Server) channelUnmute(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().Unmute(req.Key, req.ChannelMute.Direction)) -} - -func (s *Server) channelVariableGet(ctx context.Context, reply string, req *proxy.Request) { - val, err := s.ari.Channel().GetVariable(req.Key, req.ChannelVariable.Name) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Variable: val, - }, - }) -} - -func (s *Server) channelVariableSet(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Channel().SetVariable(req.Key, req.ChannelVariable.Name, req.ChannelVariable.Value)) -} diff --git a/v5/server/channel_test.go b/v5/server/channel_test.go deleted file mode 100644 index 8df16e4..0000000 --- a/v5/server/channel_test.go +++ /dev/null @@ -1,115 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestChannelData(t *testing.T) { - integration.TestChannelData(t, &srv{}) -} - -func TestChannelAnswer(t *testing.T) { - integration.TestChannelAnswer(t, &srv{}) -} - -func TestChannelBusy(t *testing.T) { - integration.TestChannelBusy(t, &srv{}) -} - -func TestChannelCongestion(t *testing.T) { - integration.TestChannelCongestion(t, &srv{}) -} - -func TestChannelHangup(t *testing.T) { - integration.TestChannelHangup(t, &srv{}) -} - -func TestChannelList(t *testing.T) { - integration.TestChannelList(t, &srv{}) -} - -func TestChannelMute(t *testing.T) { - integration.TestChannelMute(t, &srv{}) -} - -func TestChannelUnmute(t *testing.T) { - integration.TestChannelUnmute(t, &srv{}) -} - -func TestChannelMOH(t *testing.T) { - integration.TestChannelMOH(t, &srv{}) -} - -func TestChannelStopMOH(t *testing.T) { - integration.TestChannelStopMOH(t, &srv{}) -} - -func TestChannelCreate(t *testing.T) { - integration.TestChannelCreate(t, &srv{}) -} - -func TestChannelContinue(t *testing.T) { - integration.TestChannelContinue(t, &srv{}) -} - -func TestChannelDial(t *testing.T) { - integration.TestChannelDial(t, &srv{}) -} - -func TestChannelHold(t *testing.T) { - integration.TestChannelHold(t, &srv{}) -} - -func TestChannelStopHold(t *testing.T) { - integration.TestChannelStopHold(t, &srv{}) -} - -func TestChannelRing(t *testing.T) { - integration.TestChannelRing(t, &srv{}) -} - -func TestChannelStopRing(t *testing.T) { - integration.TestChannelStopRing(t, &srv{}) -} - -func TestChannelSilence(t *testing.T) { - integration.TestChannelSilence(t, &srv{}) -} - -func TestChannelStopSilence(t *testing.T) { - integration.TestChannelStopSilence(t, &srv{}) -} - -func TestChannelOriginate(t *testing.T) { - integration.TestChannelOriginate(t, &srv{}) -} - -func TestChannelPlay(t *testing.T) { - integration.TestChannelPlay(t, &srv{}) -} - -func TestChannelRecord(t *testing.T) { - integration.TestChannelRecord(t, &srv{}) -} - -func TestChannelSnoop(t *testing.T) { - integration.TestChannelSnoop(t, &srv{}) -} - -func TestChannelExternalMedia(t *testing.T) { - integration.TestChannelExternalMedia(t, &srv{}) -} - -func TestChannelSendDTMF(t *testing.T) { - integration.TestChannelSendDTMF(t, &srv{}) -} - -func TestChannelVariableGet(t *testing.T) { - integration.TestChannelVariableGet(t, &srv{}) -} - -func TestChannelVariableSet(t *testing.T) { - integration.TestChannelVariableSet(t, &srv{}) -} diff --git a/v5/server/clientserver_test.go b/v5/server/clientserver_test.go deleted file mode 100644 index ac9e7d8..0000000 --- a/v5/server/clientserver_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package server - -import ( - "context" - "errors" - "testing" - - "time" - - "github.com/CyCoreSystems/ari-proxy/v5/client" - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/rid" - "github.com/nats-io/nats.go" -) - -type srv struct { - s *Server -} - -func (s *srv) Start(ctx context.Context, t *testing.T, mockClient ari.Client, nc *nats.EncodedConn, completeCh chan struct{}) (ari.Client, error) { - s.s = New() - // tests may run in parallel so we don't want two separate proxy servers to conflict. - s.s.NATSPrefix = rid.New("") + "." - s.s.Application = "asdf" - - go func() { - if err := s.s.ListenOn(ctx, mockClient, nc); err != nil { - if err != context.Canceled { - t.Errorf("Failed to start server: %s", err) - } - } - close(completeCh) - }() - - select { - case <-s.s.Ready(): - case <-time.After(600 * time.Millisecond): - return nil, errors.New("Timeout waiting for server ready") - } - - cl, err := client.New(ctx, client.WithTimeoutRetries(4), client.WithPrefix(s.s.NATSPrefix), client.WithApplication("asdf")) - if err != nil { - return nil, err - } - - return cl, nil -} - -func (s *srv) Ready() <-chan struct{} { - return s.s.Ready() -} - -func (s *srv) Close() error { - return nil -} diff --git a/v5/server/closegroup.go b/v5/server/closegroup.go deleted file mode 100644 index f859c53..0000000 --- a/v5/server/closegroup.go +++ /dev/null @@ -1,28 +0,0 @@ -package server - -type closeGroup struct { - count int - closeCh chan struct{} -} - -func (cg *closeGroup) Add(fn func() error) func() { - if cg.count == 0 { - cg.closeCh = make(chan struct{}) - } - cg.count++ - return func() { - err := fn() - if err != nil { - panic(err.Error()) - } - cg.count-- - if cg.count == 0 { - close(cg.closeCh) - cg.count = -1 - } - } -} - -func (cg *closeGroup) Done() chan struct{} { - return cg.closeCh -} diff --git a/v5/server/config.go b/v5/server/config.go deleted file mode 100644 index 03acfd6..0000000 --- a/v5/server/config.go +++ /dev/null @@ -1,29 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) asteriskConfigData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Asterisk().Config().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Config: data, - }, - }) -} - -func (s *Server) asteriskConfigDelete(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Asterisk().Config().Delete(req.Key)) -} - -func (s *Server) asteriskConfigUpdate(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Asterisk().Config().Update(req.Key, req.AsteriskConfig.Tuples)) -} diff --git a/v5/server/config_test.go b/v5/server/config_test.go deleted file mode 100644 index c27856d..0000000 --- a/v5/server/config_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestConfigData(t *testing.T) { - integration.TestConfigData(t, &srv{}) -} - -func TestConfigDelete(t *testing.T) { - integration.TestConfigDelete(t, &srv{}) -} - -func TestConfigUpdate(t *testing.T) { - integration.TestConfigUpdate(t, &srv{}) -} diff --git a/v5/server/device.go b/v5/server/device.go deleted file mode 100644 index b9934d5..0000000 --- a/v5/server/device.go +++ /dev/null @@ -1,53 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) deviceStateData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.DeviceState().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - DeviceState: data, - }, - }) -} - -func (s *Server) deviceStateGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.DeviceState().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) deviceStateDelete(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.DeviceState().Delete(req.Key)) -} - -func (s *Server) deviceStateList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.DeviceState().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} - -func (s *Server) deviceStateUpdate(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.DeviceState().Update(req.Key, req.DeviceStateUpdate.State)) -} diff --git a/v5/server/device_test.go b/v5/server/device_test.go deleted file mode 100644 index 315faa1..0000000 --- a/v5/server/device_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestDeviceData(t *testing.T) { - integration.TestDeviceData(t, &srv{}) -} - -func TestDeviceDelete(t *testing.T) { - integration.TestDeviceDelete(t, &srv{}) -} - -func TestDeviceUpdate(t *testing.T) { - integration.TestDeviceUpdate(t, &srv{}) -} - -func TestDeviceList(t *testing.T) { - integration.TestDeviceList(t, &srv{}) -} diff --git a/v5/server/dialog/manager.go b/v5/server/dialog/manager.go deleted file mode 100644 index 6d9e3a1..0000000 --- a/v5/server/dialog/manager.go +++ /dev/null @@ -1,98 +0,0 @@ -package dialog - -import "sync" - -// Manager is a dialog manager, which tracks associations between dialogs and entities -type Manager interface { - // List returns a list of dialogs for the given entity type-ID pair - List(eType, id string) []string - - // Bind binds the given dialog to an entity type-ID pair - Bind(dialog, eType, id string) - - // Unbind removes bindings for the given entity type-ID pair - Unbind(eType, id string) - - // UnbindDialog removes all bindings for the given dialog - UnbindDialog(dialog string) -} - -func bindingHash(eType, id string) string { - return eType + ":" + id -} - -type memManager struct { - bindings map[string][]string - - mu sync.RWMutex -} - -// NewMemManager returns a new in-memory dialog manager -func NewMemManager() Manager { - return &memManager{ - bindings: make(map[string][]string), - } -} - -func (m *memManager) List(eType, id string) []string { - m.mu.RLock() - defer m.mu.RUnlock() - - list, ok := m.bindings[bindingHash(eType, id)] - if !ok { - return nil - } - return list -} - -func (m *memManager) Bind(dialog, eType, id string) { - if dialog == "" || eType == "" || id == "" { - return - } - - m.mu.Lock() - defer m.mu.Unlock() - - list, ok := m.bindings[bindingHash(eType, id)] - if !ok { - list = []string{dialog} - } else { - // Don't add the binding if it is already there - for _, b := range list { - if b == dialog { - return - } - } - - // Add the dialog - list = append(list, dialog) - } - m.bindings[bindingHash(eType, id)] = list -} - -func (m *memManager) Unbind(eType, id string) { - m.mu.Lock() - delete(m.bindings, bindingHash(eType, id)) - m.mu.Unlock() -} - -func (m *memManager) UnbindDialog(dialog string) { - - var dialogIndex int - - m.mu.Lock() - for k, v := range m.bindings { - dialogIndex = -1 - for i, d := range v { - if d == dialog { - dialogIndex = i - } - } - if dialogIndex >= 0 { - v[dialogIndex] = v[len(v)-1] - v = v[:len(v)-1] - m.bindings[k] = v - } - } - m.mu.Unlock() -} diff --git a/v5/server/dialog/manager_test.go b/v5/server/dialog/manager_test.go deleted file mode 100644 index 0120673..0000000 --- a/v5/server/dialog/manager_test.go +++ /dev/null @@ -1,144 +0,0 @@ -package dialog - -import "testing" - -func TestMemBind(t *testing.T) { - m := NewMemManager().(*memManager) - - m.Bind("testDialog", "testType", "testID") - - if len(m.bindings) != 1 { - t.Errorf("Binding failed; count %d != 1", len(m.bindings)) - } -} - -func TestMemUnbindDialog(t *testing.T) { - m := NewMemManager().(*memManager) - - m.Bind("testDialog", "testType", "testID") - - if len(m.bindings) != 1 { - t.Errorf("Binding failed; count %d != 1", len(m.bindings)) - } - - m.UnbindDialog("testDialog") - - // The unbinding of a dialog doesn't clear the testType/testID - if len(m.bindings) != 1 { - t.Errorf("Unbinding Dialog failed; count %d != 0", len(m.bindings)) - } - - // But it should make the testType/testID empty - if i := len(m.List("testType", "testID")); i != 0 { - t.Errorf("List('testType','testID'); count %d != 0", i) - } -} - -func TestMemBindUnbind(t *testing.T) { - m := NewMemManager().(*memManager) - - m.Bind("testDialog", "testType", "testID") - - if len(m.bindings) != 1 { - t.Errorf("Binding failed; count %d != 1", len(m.bindings)) - } - - m.Unbind("testType", "testID") - - if len(m.bindings) != 0 { - t.Errorf("Unbinding failed; count %d != 0", len(m.bindings)) - } - -} - -func TestMemBindMultiple(t *testing.T) { - m := NewMemManager().(*memManager) - - m.Bind("testDialog", "testType", "testID") - m.Bind("testDialog2", "testType", "testID") - - m.Bind("testDialog", "testType", "testID2") - - m.Bind("testDialog", "testType2", "testID") - m.Bind("testDialog3", "testType2", "testID") - - if len(m.bindings) != 3 { - t.Errorf("Binding failed; count %d != 3", len(m.bindings)) - } -} - -func TestMemBindUnbindMultiple(t *testing.T) { - m := NewMemManager().(*memManager) - - m.Bind("testDialog", "testType", "testID") - m.Bind("testDialog2", "testType", "testID") - - m.Bind("testDialog", "testType", "testID2") - - m.Bind("testDialog", "testType2", "testID") - m.Bind("testDialog3", "testType2", "testID") - - if len(m.bindings) != 3 { - t.Errorf("Binding failed; count %d != 3", len(m.bindings)) - } - - m.Unbind("testType", "testID") - - if len(m.bindings) != 2 { - t.Errorf("Unbinding failed; count %d != 2", len(m.bindings)) - } - - if len(m.List("testType", "testID")) != 0 { - t.Errorf("Unbinding failed; List('testType','testID') => len %d != 2", len(m.bindings)) - } - - m.Unbind("testType2", "testID") - - if len(m.bindings) != 1 { - t.Errorf("Binding failed; count %d != 1", len(m.bindings)) - } - -} - -func TestMemBindDuplicate(t *testing.T) { - m := NewMemManager().(*memManager) - - m.Bind("testDialog", "testType", "testID") - m.Bind("testDialog", "testType", "testID") - - if len(m.bindings) != 1 { - t.Errorf("Binding failed; count %d != 1", len(m.bindings)) - } -} - -func TestMemList(t *testing.T) { - m := NewMemManager().(*memManager) - m.Bind("testDialog", "testType", "testID") - m.Bind("testDialog", "testType", "testID2") - m.Bind("testDialog", "testType2", "testID") - m.Bind("testDialog2", "testType", "testID") - m.Bind("testDialog3", "testType2", "testID") - - list := m.List("testType", "testID") - - if len(list) != 2 { - t.Errorf("Incorrect count %d != 1", len(list)) - } - - var testFound int - var test2Found int - for _, d := range list { - if d == "testDialog" { - testFound++ - } - if d == "testDialog2" { - test2Found++ - } - } - if testFound != 1 { - t.Errorf("Incorrect number of testDialog dialogs: %d != 1", testFound) - } - if test2Found != 1 { - t.Errorf("Incorrect number of testDialog2 dialogs: %d != 1", test2Found) - } -} diff --git a/v5/server/doc.go b/v5/server/doc.go deleted file mode 100644 index 359f5bf..0000000 --- a/v5/server/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package server provides a proxy for ARI calls. It is -// usable via the client/nc Client and can use any given ari.Client -package server diff --git a/v5/server/endpoint.go b/v5/server/endpoint.go deleted file mode 100644 index 4fa3526..0000000 --- a/v5/server/endpoint.go +++ /dev/null @@ -1,57 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) endpointData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Endpoint().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Endpoint: data, - }, - }) -} - -func (s *Server) endpointGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Endpoint().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) endpointList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.Endpoint().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} - -func (s *Server) endpointListByTech(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.Endpoint().ListByTech(req.EndpointListByTech.Tech, req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} diff --git a/v5/server/endpoint_test.go b/v5/server/endpoint_test.go deleted file mode 100644 index 68018f7..0000000 --- a/v5/server/endpoint_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestEndpointList(t *testing.T) { - integration.TestEndpointList(t, &srv{}) -} - -func TestEndpointListByTech(t *testing.T) { - integration.TestEndpointListByTech(t, &srv{}) -} - -func TestEndpointData(t *testing.T) { - integration.TestEndpointData(t, &srv{}) -} diff --git a/v5/server/events.go b/v5/server/events.go deleted file mode 100644 index 6ff1a77..0000000 --- a/v5/server/events.go +++ /dev/null @@ -1,10 +0,0 @@ -package server - -import "github.com/CyCoreSystems/ari/v5" - -func (s *Server) dialogsForEvent(e ari.Event) (ret []string) { - for _, k := range e.Keys() { - ret = append(ret, s.Dialog.List(k.Kind, k.ID)...) - } - return -} diff --git a/v5/server/handler.go b/v5/server/handler.go deleted file mode 100644 index 6d2c8c8..0000000 --- a/v5/server/handler.go +++ /dev/null @@ -1,13 +0,0 @@ -package server - -import "github.com/CyCoreSystems/ari-proxy/v5/session" - -// Reply is a function which, when called, replies to the request via the -// response object or error. -type Reply func(interface{}, error) - -// A Handler2 is a function which provides a session-aware request-response for nats -type Handler2 func(msg *session.Message, reply Reply) - -// Handler is left for compat -type Handler func(subj string, request []byte, reply Reply) diff --git a/v5/server/liveRecording.go b/v5/server/liveRecording.go deleted file mode 100644 index 1007bdf..0000000 --- a/v5/server/liveRecording.go +++ /dev/null @@ -1,65 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) recordingLiveData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.LiveRecording().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, proxy.Response{ - Data: &proxy.EntityData{ - LiveRecording: data, - }, - }) -} - -func (s *Server) recordingLiveGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.LiveRecording().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) recordingLiveMute(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.LiveRecording().Mute(req.Key)) -} - -func (s *Server) recordingLivePause(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.LiveRecording().Pause(req.Key)) -} - -func (s *Server) recordingLiveResume(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.LiveRecording().Resume(req.Key)) -} - -func (s *Server) recordingLiveScrap(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.LiveRecording().Scrap(req.Key)) -} - -func (s *Server) recordingLiveSubscribe(ctx context.Context, reply string, req *proxy.Request) { - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "recording", req.Key.ID) - } - - s.sendError(reply, nil) -} - -func (s *Server) recordingLiveStop(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.LiveRecording().Stop(req.Key)) -} - -func (s *Server) recordingLiveUnmute(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.LiveRecording().Unmute(req.Key)) -} diff --git a/v5/server/liveRecording_test.go b/v5/server/liveRecording_test.go deleted file mode 100644 index 84c9ecc..0000000 --- a/v5/server/liveRecording_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestLiveRecordingData(t *testing.T) { - integration.TestLiveRecordingData(t, &srv{}) -} - -/* -func TestLiveRecordingDelete(t *testing.T) { - integration.TestLiveRecordingDelete(t, &srv{}) -} -*/ - -func TestLiveRecordingMute(t *testing.T) { - integration.TestLiveRecordingMute(t, &srv{}) -} - -func TestLiveRecordingUnmute(t *testing.T) { - integration.TestLiveRecordingUnmute(t, &srv{}) -} - -func TestLiveRecordingPause(t *testing.T) { - integration.TestLiveRecordingPause(t, &srv{}) -} - -func TestLiveRecordingStop(t *testing.T) { - integration.TestLiveRecordingStop(t, &srv{}) -} - -func TestLiveRecordingResume(t *testing.T) { - integration.TestLiveRecordingResume(t, &srv{}) -} - -func TestLiveRecordingScrap(t *testing.T) { - integration.TestLiveRecordingScrap(t, &srv{}) -} diff --git a/v5/server/logging.go b/v5/server/logging.go deleted file mode 100644 index 8225d98..0000000 --- a/v5/server/logging.go +++ /dev/null @@ -1,65 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) asteriskLoggingList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.Asterisk().Logging().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} - -func (s *Server) asteriskLoggingGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Asterisk().Logging().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) asteriskLoggingCreate(ctx context.Context, reply string, req *proxy.Request) { - h, err := s.ari.Asterisk().Logging().Create(req.Key, req.AsteriskLoggingChannel.Levels) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) asteriskLoggingData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Asterisk().Logging().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Log: data, - }, - }) -} - -func (s *Server) asteriskLoggingRotate(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Asterisk().Logging().Rotate(req.Key)) -} - -func (s *Server) asteriskLoggingDelete(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Asterisk().Logging().Delete(req.Key)) -} diff --git a/v5/server/logging_test.go b/v5/server/logging_test.go deleted file mode 100644 index 717dcc6..0000000 --- a/v5/server/logging_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestLoggingList(t *testing.T) { - integration.TestLoggingList(t, &srv{}) -} - -func TestLoggingCreate(t *testing.T) { - integration.TestLoggingCreate(t, &srv{}) -} - -func TestLoggingRotate(t *testing.T) { - integration.TestLoggingRotate(t, &srv{}) -} - -func TestLoggingDelete(t *testing.T) { - integration.TestLoggingDelete(t, &srv{}) -} diff --git a/v5/server/mailbox.go b/v5/server/mailbox.go deleted file mode 100644 index 7280ad8..0000000 --- a/v5/server/mailbox.go +++ /dev/null @@ -1,53 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) mailboxData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Mailbox().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Mailbox: data, - }, - }) -} - -func (s *Server) mailboxGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Mailbox().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) mailboxDelete(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Mailbox().Delete(req.Key)) -} - -func (s *Server) mailboxList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.Mailbox().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} - -func (s *Server) mailboxUpdate(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Mailbox().Update(req.Key, req.MailboxUpdate.Old, req.MailboxUpdate.New)) -} diff --git a/v5/server/mailbox_test.go b/v5/server/mailbox_test.go deleted file mode 100644 index fa1092c..0000000 --- a/v5/server/mailbox_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestMailboxList(t *testing.T) { - integration.TestMailboxList(t, &srv{}) -} - -func TestMailboxUpdate(t *testing.T) { - integration.TestMailboxUpdate(t, &srv{}) -} - -func TestMailboxDelete(t *testing.T) { - integration.TestMailboxDelete(t, &srv{}) -} - -func TestMailboxData(t *testing.T) { - integration.TestMailboxData(t, &srv{}) -} diff --git a/v5/server/modules.go b/v5/server/modules.go deleted file mode 100644 index 344b9df..0000000 --- a/v5/server/modules.go +++ /dev/null @@ -1,57 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) asteriskModuleLoad(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Asterisk().Modules().Load(req.Key)) -} - -func (s *Server) asteriskModuleUnload(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Asterisk().Modules().Unload(req.Key)) -} - -func (s *Server) asteriskModuleReload(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Asterisk().Modules().Reload(req.Key)) -} - -func (s *Server) asteriskModuleData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Asterisk().Modules().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Module: data, - }, - }) -} - -func (s *Server) asteriskModuleGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Asterisk().Modules().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) asteriskModuleList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.Asterisk().Modules().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} diff --git a/v5/server/modules_test.go b/v5/server/modules_test.go deleted file mode 100644 index 98cd7d4..0000000 --- a/v5/server/modules_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestModulesData(t *testing.T) { - integration.TestModulesData(t, &srv{}) -} - -func TestModulesLoad(t *testing.T) { - integration.TestModulesLoad(t, &srv{}) -} - -func TestModulesReload(t *testing.T) { - integration.TestModulesReload(t, &srv{}) -} - -func TestModulesUnload(t *testing.T) { - integration.TestModulesUnload(t, &srv{}) -} - -func TestModulesList(t *testing.T) { - integration.TestModulesList(t, &srv{}) -} diff --git a/v5/server/options.go b/v5/server/options.go deleted file mode 100644 index 086ce52..0000000 --- a/v5/server/options.go +++ /dev/null @@ -1,17 +0,0 @@ -package server - -import ( - "context" - - "github.com/inconshreveable/log15" -) - -// Options are the group of options for the ari-proxy server -type Options struct { - //TODO: include nats options - - URL string - - Logger log15.Logger - Parent context.Context -} diff --git a/v5/server/playback.go b/v5/server/playback.go deleted file mode 100644 index e23d0ba..0000000 --- a/v5/server/playback.go +++ /dev/null @@ -1,51 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) playbackControl(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Playback().Control(req.Key, req.PlaybackControl.Command)) -} - -func (s *Server) playbackData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Playback().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Playback: data, - }, - }) -} - -func (s *Server) playbackGet(ctx context.Context, reply string, req *proxy.Request) { - s.Log.Debug("Fetching playback data", "playback", req.Key) - data, err := s.ari.Playback().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) playbackStop(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.Playback().Stop(req.Key)) -} - -func (s *Server) playbackSubscribe(ctx context.Context, reply string, req *proxy.Request) { - // bind dialog - if req.Key.Dialog != "" { - s.Dialog.Bind(req.Key.Dialog, "playback", req.Key.ID) - } - - s.sendError(reply, nil) -} diff --git a/v5/server/playback_test.go b/v5/server/playback_test.go deleted file mode 100644 index 0435a1e..0000000 --- a/v5/server/playback_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestPlaybackData(t *testing.T) { - integration.TestPlaybackData(t, &srv{}) -} - -func TestPlaybackControl(t *testing.T) { - integration.TestPlaybackControl(t, &srv{}) -} - -func TestPlaybackStop(t *testing.T) { - integration.TestPlaybackStop(t, &srv{}) -} diff --git a/v5/server/server.go b/v5/server/server.go deleted file mode 100644 index 22cd5e0..0000000 --- a/v5/server/server.go +++ /dev/null @@ -1,594 +0,0 @@ -package server - -import ( - "context" - "fmt" - "time" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" - "github.com/CyCoreSystems/ari-proxy/v5/server/dialog" - "github.com/CyCoreSystems/ari/v5" - "github.com/CyCoreSystems/ari/v5/client/native" - - "github.com/inconshreveable/log15" - "github.com/nats-io/nats.go" - "github.com/pkg/errors" -) - -// Server describes the asterisk-facing ARI proxy server -type Server struct { - // Application is the name of the ARI application of this server - Application string - - // AsteriskID is the unique identifier for the Asterisk box - // to which this server is connected. - AsteriskID string - - // NATSPrefix is the string which should be prepended to all NATS subjects, sending and receiving. It defaults to "ari.". - NATSPrefix string - - // ari is the native Asterisk ARI client by which this proxy is directly connected - ari ari.Client - - // nats is the JSON-encoded NATS connection - nats *nats.EncodedConn - - // Dialog is the dialog manager - Dialog dialog.Manager - - readyCh chan struct{} - - // cancel is the context cancel function, by which all subtended subscriptions may be terminated - cancel context.CancelFunc - - // Log is the log15.Logger for the service. You may replace or call SetHandler() on this at any time to change the logging of the service. - Log log15.Logger -} - -// New returns a new Server -func New() *Server { - log := log15.New() - log.SetHandler(log15.DiscardHandler()) - - return &Server{ - NATSPrefix: "ari.", - readyCh: make(chan struct{}), - Dialog: dialog.NewMemManager(), - Log: log, - } -} - -// Listen runs the given server, listening to ARI and NATS, as specified -func (s *Server) Listen(ctx context.Context, ariOpts *native.Options, natsURI string) (err error) { - ctx, cancel := context.WithCancel(ctx) - s.cancel = cancel - - // Connect to ARI - s.ari, err = native.Connect(ariOpts) - if err != nil { - return errors.Wrap(err, "failed to connect to ARI") - } - defer s.ari.Close() - - // Connect to NATS - nc, err := nats.Connect(natsURI) - if err != nil { - return errors.Wrap(err, "failed to connect to NATS") - } - s.nats, err = nats.NewEncodedConn(nc, nats.JSON_ENCODER) - if err != nil { - return errors.Wrap(err, "failed to encode NATS connection") - } - defer s.nats.Close() - - return s.listen(ctx) -} - -// ListenOn runs the given server, listening on the provided ARI and NATS connections -func (s *Server) ListenOn(ctx context.Context, a ari.Client, n *nats.EncodedConn) error { - ctx, cancel := context.WithCancel(ctx) - s.cancel = cancel - - s.ari = a - s.nats = n - - return s.listen(ctx) -} - -// Ready returns a channel which is closed when the Server is ready -func (s *Server) Ready() <-chan struct{} { - if s.readyCh == nil { - s.readyCh = make(chan struct{}) - } - return s.readyCh -} - -// nolint: gocyclo -func (s *Server) listen(ctx context.Context) error { - s.Log.Debug("starting listener") - - var wg closeGroup - defer func() { - select { - case <-wg.Done(): - case <-time.After(500 * time.Millisecond): - panic("timeout waiting for shutdown of sub components") - } - }() - - // First, get the Asterisk ID - - ret, err := s.ari.Asterisk().Info(nil) - if err != nil { - return errors.Wrap(err, "failed to get Asterisk ID") - } - - s.AsteriskID = ret.SystemInfo.EntityID - if s.AsteriskID == "" { - return errors.New("empty Asterisk ID") - } - - // Store the ARI application name for top-level access - s.Application = s.ari.ApplicationName() - - // - // Listen on the initial NATS subjects - // - - // ping handler - pingSub, err := s.nats.Subscribe(proxy.PingSubject(s.NATSPrefix), s.pingHandler) - if err != nil { - return errors.Wrap(err, "failed to subscribe to pings") - } - defer wg.Add(pingSub.Unsubscribe) - - // get a contextualized request handler - requestHandler := s.newRequestHandler(ctx) - - // get handlers - allGet, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "get", "", ""), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create get-all subscription") - } - defer wg.Add(allGet.Unsubscribe)() - - appGet, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "get", s.Application, ""), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create get-app subscription") - } - defer wg.Add(appGet.Unsubscribe)() - idGet, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "get", s.Application, s.AsteriskID), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create get-id subscription") - } - defer wg.Add(idGet.Unsubscribe)() - - // data handlers - allData, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "data", "", ""), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create data-all subscription") - } - defer wg.Add(allData.Unsubscribe)() - appData, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "data", s.Application, ""), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create data-app subscription") - } - defer wg.Add(appData.Unsubscribe)() - idData, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "data", s.Application, s.AsteriskID), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create data-id subscription") - } - defer wg.Add(idData.Unsubscribe)() - - // command handlers - allCommand, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "command", "", ""), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create command-all subscription") - } - defer wg.Add(allCommand.Unsubscribe)() - appCommand, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "command", s.Application, ""), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create command-app subscription") - } - defer wg.Add(appCommand.Unsubscribe)() - idCommand, err := s.nats.Subscribe(proxy.Subject(s.NATSPrefix, "command", s.Application, s.AsteriskID), requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create command-id subscription") - } - defer wg.Add(idCommand.Unsubscribe)() - - // create handlers - allCreate, err := s.nats.QueueSubscribe(proxy.Subject(s.NATSPrefix, "create", "", ""), "ariproxy", requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create create-all subscription") - } - defer wg.Add(allCreate.Unsubscribe)() - appCreate, err := s.nats.QueueSubscribe(proxy.Subject(s.NATSPrefix, "create", s.Application, ""), "ariproxy", requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create create-app subscription") - } - defer wg.Add(appCreate.Unsubscribe)() - idCreate, err := s.nats.QueueSubscribe(proxy.Subject(s.NATSPrefix, "create", s.Application, s.AsteriskID), "ariproxy", requestHandler) - if err != nil { - return errors.Wrap(err, "failed to create create-id subscription") - } - defer wg.Add(idCreate.Unsubscribe)() - - // Run the periodic announcer - go s.runAnnouncer(ctx) - - // Run the event handler - go s.runEventHandler(ctx) - - // TODO: run the dialog cleanup routine (remove bindings for entities which no longer exist) - // go s.runDialogCleaner(ctx) - - // Close the readyChannel to indicate that we are operational - if s.readyCh != nil { - close(s.readyCh) - } - - // Wait for context closure to exit - <-ctx.Done() - return ctx.Err() -} - -// runAnnouncer runs the periodic discovery announcer -func (s *Server) runAnnouncer(ctx context.Context) { - ticker := time.NewTicker(proxy.AnnouncementInterval) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - s.announce() - } - } -} - -// announce publishes the presence of this server to the cluster -func (s *Server) announce() { - s.publish(proxy.AnnouncementSubject(s.NATSPrefix), &proxy.Announcement{ - Node: s.AsteriskID, - Application: s.Application, - }) -} - -// runEventHandler processes events which are received from ARI -func (s *Server) runEventHandler(ctx context.Context) { - sub := s.ari.Bus().Subscribe(nil, ari.Events.All) - defer sub.Cancel() - - for { - s.Log.Debug("listening for events", "application", s.Application) - select { - case <-ctx.Done(): - return - case e := <-sub.Events(): - s.Log.Debug("event received", "kind", e.GetType()) - - // Publish event to canonical destination - s.publish(fmt.Sprintf("%sevent.%s.%s", s.NATSPrefix, s.Application, s.AsteriskID), e) - - // Publish event to any associated dialogs - for _, d := range s.dialogsForEvent(e) { - de := e - de.SetDialog(d) - s.publish(fmt.Sprintf("%sdialogevent.%s", s.NATSPrefix, d), de) - } - } - } -} - -// pingHandler publishes the server's presence -func (s *Server) pingHandler(m *nats.Msg) { - if s.ari.Connected() { - s.announce() - } -} - -// publish sends a message out over NATS, logging any error -func (s *Server) publish(subject string, msg interface{}) { - if err := s.nats.Publish(subject, msg); err != nil { - s.Log.Warn("failed to publish NATS message", "subject", subject, "data", msg, "error", err) - } -} - -// newRequestHandler returns a context-wrapped nats.Handler to handle requests -func (s *Server) newRequestHandler(ctx context.Context) func(subject string, reply string, req *proxy.Request) { - return func(subject string, reply string, req *proxy.Request) { - if !s.ari.Connected() { - s.sendError(reply, errors.New("ARI connection is down")) - return - } - go s.dispatchRequest(ctx, reply, req) - } -} - -// TODO: see if there is a more programmatic approach to this -// nolint: gocyclo -func (s *Server) dispatchRequest(ctx context.Context, reply string, req *proxy.Request) { - var f func(context.Context, string, *proxy.Request) - - s.Log.Debug("received request", "kind", req.Kind) - switch req.Kind { - case "ApplicationData": - f = s.applicationData - case "ApplicationGet": - f = s.applicationGet - case "ApplicationList": - f = s.applicationList - case "ApplicationSubscribe": - f = s.applicationSubscribe - case "ApplicationUnsubscribe": - f = s.applicationUnsubscribe - case "AsteriskConfigData": - f = s.asteriskConfigData - case "AsteriskConfigDelete": - f = s.asteriskConfigDelete - case "AsteriskConfigUpdate": - f = s.asteriskConfigUpdate - case "AsteriskLoggingCreate": - f = s.asteriskLoggingCreate - case "AsteriskLoggingData": - f = s.asteriskLoggingData - case "AsteriskLoggingDelete": - f = s.asteriskLoggingDelete - case "AsteriskLoggingGet": - f = s.asteriskLoggingGet - case "AsteriskLoggingList": - f = s.asteriskLoggingList - case "AsteriskLoggingRotate": - f = s.asteriskLoggingRotate - case "AsteriskModuleData": - f = s.asteriskModuleData - case "AsteriskModuleGet": - f = s.asteriskModuleGet - case "AsteriskModuleLoad": - f = s.asteriskModuleLoad - case "AsteriskModuleList": - f = s.asteriskModuleList - case "AsteriskModuleReload": - f = s.asteriskModuleReload - case "AsteriskModuleUnload": - f = s.asteriskModuleUnload - case "AsteriskInfo": - f = s.asteriskInfo - case "AsteriskVariableGet": - f = s.asteriskVariableGet - case "AsteriskVariableSet": - f = s.asteriskVariableSet - case "BridgeAddChannel": - f = s.bridgeAddChannel - case "BridgeCreate": - f = s.bridgeCreate - case "BridgeStageCreate": - f = s.bridgeStageCreate - case "BridgeData": - f = s.bridgeData - case "BridgeDelete": - f = s.bridgeDelete - case "BridgeGet": - f = s.bridgeGet - case "BridgeList": - f = s.bridgeList - case "BridgeMOH": - f = s.bridgeMOH - case "BridgeStopMOH": - f = s.bridgeStopMOH - case "BridgePlay": - f = s.bridgePlay - case "BridgeStagePlay": - f = s.bridgeStagePlay - case "BridgeRecord": - f = s.bridgeRecord - case "BridgeStageRecord": - f = s.bridgeStageRecord - case "BridgeRemoveChannel": - f = s.bridgeRemoveChannel - case "BridgeSubscribe": - f = s.bridgeSubscribe - case "BridgeUnsubscribe": - f = s.bridgeUnsubscribe - case "BridgeVideoSource": - f = s.bridgeVideoSource - case "BridgeVideoSourceDelete": - f = s.bridgeVideoSourceDelete - case "ChannelAnswer": - f = s.channelAnswer - case "ChannelBusy": - f = s.channelBusy - case "ChannelCongestion": - f = s.channelCongestion - case "ChannelCreate": - f = s.channelCreate - case "ChannelContinue": - f = s.channelContinue - case "ChannelData": - f = s.channelData - case "ChannelDial": - f = s.channelDial - case "ChannelGet": - f = s.channelGet - case "ChannelHangup": - f = s.channelHangup - case "ChannelHold": - f = s.channelHold - case "ChannelList": - f = s.channelList - case "ChannelMOH": - f = s.channelMOH - case "ChannelMute": - f = s.channelMute - case "ChannelOriginate": - f = s.channelOriginate - case "ChannelStageOriginate": - f = s.channelStageOriginate - case "ChannelPlay": - f = s.channelPlay - case "ChannelStagePlay": - f = s.channelStagePlay - case "ChannelRecord": - f = s.channelRecord - case "ChannelStageRecord": - f = s.channelStageRecord - case "ChannelRing": - f = s.channelRing - case "ChannelSendDTMF": - f = s.channelSendDTMF - case "ChannelSilence": - f = s.channelSilence - case "ChannelSnoop": - f = s.channelSnoop - case "ChannelStageSnoop": - f = s.channelStageSnoop - case "ChannelExternalMedia": - f = s.channelExternalMedia - case "ChannelStageExternalMedia": - f = s.channelStageExternalMedia - case "ChannelStopHold": - f = s.channelStopHold - case "ChannelStopMOH": - f = s.channelStopMOH - case "ChannelStopRing": - f = s.channelStopRing - case "ChannelStopSilence": - f = s.channelStopSilence - case "ChannelSubscribe": - f = s.channelSubscribe - case "ChannelUnmute": - f = s.channelUnmute - case "ChannelVariableGet": - f = s.channelVariableGet - case "ChannelVariableSet": - f = s.channelVariableSet - case "DeviceStateData": - f = s.deviceStateData - case "DeviceStateDelete": - f = s.deviceStateDelete - case "DeviceStateGet": - f = s.deviceStateGet - case "DeviceStateList": - f = s.deviceStateList - case "DeviceStateUpdate": - f = s.deviceStateUpdate - case "EndpointData": - f = s.endpointData - case "EndpointGet": - f = s.endpointGet - case "EndpointList": - f = s.endpointList - case "EndpointListByTech": - f = s.endpointListByTech - case "MailboxData": - f = s.mailboxData - case "MailboxDelete": - f = s.mailboxDelete - case "MailboxGet": - f = s.mailboxGet - case "MailboxList": - f = s.mailboxList - case "MailboxUpdate": - f = s.mailboxUpdate - case "PlaybackControl": - f = s.playbackControl - case "PlaybackData": - f = s.playbackData - case "PlaybackGet": - f = s.playbackGet - case "PlaybackStop": - f = s.playbackStop - case "PlaybackSubscribe": - f = s.playbackSubscribe - case "RecordingStoredCopy": - f = s.recordingStoredCopy - case "RecordingStoredData": - f = s.recordingStoredData - case "RecordingStoredDelete": - f = s.recordingStoredDelete - case "RecordingStoredGet": - f = s.recordingStoredGet - case "RecordingStoredList": - f = s.recordingStoredList - case "RecordingLiveData": - f = s.recordingLiveData - case "RecordingLiveGet": - f = s.recordingLiveGet - case "RecordingLiveMute": - f = s.recordingLiveMute - case "RecordingLivePause": - f = s.recordingLivePause - case "RecordingLiveResume": - f = s.recordingLiveResume - case "RecordingLiveScrap": - f = s.recordingLiveScrap - case "RecordingLiveSubscribe": - f = s.recordingLiveSubscribe - case "RecordingLiveStop": - f = s.recordingLiveStop - case "RecordingLiveUnmute": - f = s.recordingLiveUnmute - case "SoundData": - f = s.soundData - case "SoundList": - f = s.soundList - default: - f = func(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, errors.New("Not implemented")) - } - } - - f(ctx, reply, req) -} - -func (s *Server) sendError(reply string, err error) { - s.publish(reply, proxy.NewErrorResponse(err)) -} - -/* -// Start runs the server side instance -func (i *Instance) Start(ctx context.Context) { - i.ctx, i.cancel = context.WithCancel(ctx) - - i.log.Debug("Starting dialog instance") - - go func() { - i.application() - i.asterisk() - i.modules() - i.channel() - i.storedRecording() - i.liveRecording() - i.bridge() - i.device() - i.playback() - i.mailbox() - i.sound() - i.logging() - i.config() - - // do commands last, since that is the one that will be dispatching - i.commands() - - close(i.readyCh) - - <-i.ctx.Done() - }() - - <-i.readyCh -} - -// Stop stops the instance -func (i *Instance) Stop() { - if i == nil { - return - } - i.cancel() -} - -func (i *Instance) String() string { - return fmt.Sprintf("Instance{%s}", i.Dialog.ID) -} -*/ diff --git a/v5/server/sound.go b/v5/server/sound.go deleted file mode 100644 index 1e99342..0000000 --- a/v5/server/sound.go +++ /dev/null @@ -1,39 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) soundData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.Sound().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - Sound: data, - }, - }) -} - -func (s *Server) soundList(ctx context.Context, reply string, req *proxy.Request) { - filters := req.SoundList.Filters - - if len(filters) == 0 { - filters = nil // just send nil to upstream if empty. makes tests easier - } - - list, err := s.ari.Sound().List(filters, req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} diff --git a/v5/server/sound_test.go b/v5/server/sound_test.go deleted file mode 100644 index e700e16..0000000 --- a/v5/server/sound_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package server - -import ( - "testing" - - "github.com/CyCoreSystems/ari-proxy/v5/internal/integration" -) - -func TestSoundData(t *testing.T) { - integration.TestSoundData(t, &srv{}) -} - -func TestSoundList(t *testing.T) { - integration.TestSoundList(t, &srv{}) -} diff --git a/v5/server/storedRecording.go b/v5/server/storedRecording.go deleted file mode 100644 index 497d020..0000000 --- a/v5/server/storedRecording.go +++ /dev/null @@ -1,61 +0,0 @@ -package server - -import ( - "context" - - "github.com/CyCoreSystems/ari-proxy/v5/proxy" -) - -func (s *Server) recordingStoredCopy(ctx context.Context, reply string, req *proxy.Request) { - h, err := s.ari.StoredRecording().Copy(req.Key, req.RecordingStoredCopy.Destination) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: h.Key(), - }) -} - -func (s *Server) recordingStoredData(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.StoredRecording().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Data: &proxy.EntityData{ - StoredRecording: data, - }, - }) -} - -func (s *Server) recordingStoredGet(ctx context.Context, reply string, req *proxy.Request) { - data, err := s.ari.StoredRecording().Data(req.Key) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Key: data.Key, - }) -} - -func (s *Server) recordingStoredDelete(ctx context.Context, reply string, req *proxy.Request) { - s.sendError(reply, s.ari.StoredRecording().Delete(req.Key)) -} - -func (s *Server) recordingStoredList(ctx context.Context, reply string, req *proxy.Request) { - list, err := s.ari.StoredRecording().List(nil) - if err != nil { - s.sendError(reply, err) - return - } - - s.publish(reply, &proxy.Response{ - Keys: list, - }) -} diff --git a/v5/session/dialog.go b/v5/session/dialog.go deleted file mode 100644 index 01c0dea..0000000 --- a/v5/session/dialog.go +++ /dev/null @@ -1,17 +0,0 @@ -package session - -// A Dialog is a session between the ARI proxy client and the ARI proxy server -type Dialog struct { - ID string - Transport Transport - Objects Objects - ChannelID string // The channel ID from the StasisStart event -} - -// NewDialog creates a new dialog with the given transport -func NewDialog(id string, transport Transport) *Dialog { - return &Dialog{ - ID: id, - Transport: transport, - } -} diff --git a/v5/session/events.go b/v5/session/events.go deleted file mode 100644 index 83a58dd..0000000 --- a/v5/session/events.go +++ /dev/null @@ -1,10 +0,0 @@ -package session - -// AppStart is the event sent on the start of an application and the creation of a server side dialog -type AppStart struct { - ServerID string `json:"server"` - DialogID string `json:"dialog"` - Application string `json:"application"` - AppArgs []string `json:"appargs"` - ChannelID string `json:"channel"` // The channel from the stasis start event -} diff --git a/v5/session/message.go b/v5/session/message.go deleted file mode 100644 index f26b55e..0000000 --- a/v5/session/message.go +++ /dev/null @@ -1,8 +0,0 @@ -package session - -// Message is the wrapper for a command sent over a dialog -type Message struct { - Command string `json:"command"` - Object string `json:"object"` - Payload []byte `json:"payload"` -} diff --git a/v5/session/objects.go b/v5/session/objects.go deleted file mode 100644 index 6eaf54b..0000000 --- a/v5/session/objects.go +++ /dev/null @@ -1,69 +0,0 @@ -package session - -import ( - "sort" - "sync" -) - -// Objects tracks a list of object IDs that are associated with the dialog -type Objects struct { - ids []string - mutex sync.RWMutex -} - -// Contains finds the id, if it exists -func (o *Objects) Contains(id string) (int, bool) { - o.mutex.RLock() - defer o.mutex.RUnlock() - - idx := sort.SearchStrings(o.ids, id) - - if idx == len(o.ids) || o.ids[idx] != id { - return -1, false - } - - return idx, true -} - -// Add adds the given object -func (o *Objects) Add(id string) bool { - - if _, ok := o.Contains(id); ok { - return false - } - - o.mutex.Lock() - defer o.mutex.Unlock() - - o.ids = append(o.ids, id) - sort.Strings(o.ids) - - return true -} - -// Remove removes the given object, if it exists -func (o *Objects) Remove(id string) bool { - idx, ok := o.Contains(id) - if !ok { - return false - } - - o.mutex.Lock() - defer o.mutex.Unlock() - o.ids = append(o.ids[:idx], o.ids[idx+1:]...) - - return true -} - -// Clear removes all the objects -func (o *Objects) Clear() { - o.mutex.Lock() - defer o.mutex.Unlock() - - o.ids = make([]string, 0) -} - -// Items returns the list of items -func (o *Objects) Items() []string { - return o.ids -} diff --git a/v5/session/objects_test.go b/v5/session/objects_test.go deleted file mode 100644 index 61432d9..0000000 --- a/v5/session/objects_test.go +++ /dev/null @@ -1,121 +0,0 @@ -package session - -import "testing" - -var addTests = []struct { - Items []string - Expected []string - Return []bool - Description string -}{ - // Single adding - {[]string{"1"}, []string{"1"}, []bool{true}, "Add('%v') => '%v'; '%v'. Expected '%v'; '%v'."}, - - // Duplicate - {[]string{"1", "1"}, []string{"1"}, []bool{true, false}, "Add('%v') => '%v'; '%v'. Expected '%v'; '%v'."}, - - // Sorting - {[]string{"2", "1"}, []string{"1", "2"}, []bool{true, true}, "Add('%v') => '%v'; '%v'. Expected '%v'; '%v'."}, -} - -func TestObjectsAdd(t *testing.T) { - - for _, test := range addTests { - var failed bool - var objects Objects - var returns []bool - for idx, item := range test.Items { - returns = append(returns, objects.Add(item)) - if returns[idx] != test.Return[idx] { - failed = true - } - } - - failed = failed || !stringSliceEq(objects.ids, test.Expected) - - if failed { - t.Errorf(test.Description, - test.Items, // input - returns, objects.ids, //actual output - test.Return, test.Expected, // expected output - ) - } - } -} - -var removeTests = []struct { - Initial []string - Items []string - Return []bool - Expected []string - Description string -}{ - // single remove - {[]string{"1", "2", "3"}, []string{"2"}, []bool{true}, []string{"1", "3"}, "Remove('%v') => '%v'; '%v'. Expected '%v'; '%v'."}, - - // duplicate remove - {[]string{"1", "2", "3"}, []string{"2", "2"}, []bool{true, false}, []string{"1", "3"}, "Remove('%v') => '%v'; '%v'. Expected '%v'; '%v'."}, - - // missing remove - {[]string{}, []string{"2"}, []bool{false}, []string{}, "Remove('%v') => '%v'; '%v'. Expected '%v'; '%v'."}, - - // remove at end - {[]string{"1", "2", "3"}, []string{"3"}, []bool{true}, []string{"1", "2"}, "Remove('%v') => '%v'; '%v'. Expected '%v'; '%v'."}, -} - -func TestObjectsRemove(t *testing.T) { - - for _, test := range removeTests { - - var objects Objects - objects.ids = test.Initial - - var failed bool - var returns []bool - for idx, item := range test.Items { - returns = append(returns, objects.Remove(item)) - if returns[idx] != test.Return[idx] { - failed = true - } - } - - failed = failed || !stringSliceEq(objects.ids, test.Expected) - - if failed { - t.Errorf(test.Description, - test.Items, // input - returns, objects.ids, //actual output - test.Return, test.Expected, // expected output - ) - } - } -} - -var clearTests = []struct { - Initial []string - Description string -}{ - {[]string{"1", "2", "3"}, "'%v'.Clear() => '%v'. Expected empty list."}, - {[]string{}, "'%v'.Clear() => '%v'. Expected empty list."}, -} - -func TestObjectsClear(t *testing.T) { - for _, test := range clearTests { - - var failed bool - - var objects Objects - objects.ids = test.Initial - - objects.Clear() - - failed = len(objects.ids) != 0 - - if failed { - t.Errorf(test.Description, - test.Initial, // input - objects.ids, //actual output - ) - } - } -} diff --git a/v5/session/transport.go b/v5/session/transport.go deleted file mode 100644 index 0c2ddac..0000000 --- a/v5/session/transport.go +++ /dev/null @@ -1,13 +0,0 @@ -package session - -import "github.com/CyCoreSystems/ari/v5" - -// Transport defines how the commands and events are sent. -type Transport interface { - - // Command sends a command and waits for a response - Command(name string, body interface{}, resp interface{}) error - - // Event dispatches an event - Event(evt ari.Event) error -} diff --git a/v5/session/utils_test.go b/v5/session/utils_test.go deleted file mode 100644 index 61a1cc3..0000000 --- a/v5/session/utils_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package session - -import "testing" - -func stringSliceEq(left []string, right []string) bool { - if len(left) != len(right) { - return false - } - - for idx := range left { - if left[idx] != right[idx] { - return false - } - } - - return true -} - -var stringSliceEqTests = []struct { - Left []string - Right []string - Expected bool - Description string -}{ - {[]string{"1"}, []string{"1"}, true, "stringSliceEq('%v','%v') => '%v'. Expected '%v'"}, - {[]string{}, []string{}, true, "stringSliceEq('%v','%v') => '%v'. Expected '%v'"}, - {[]string{"1"}, []string{"2"}, false, "stringSliceEq('%v','%v') => '%v'. Expected '%v'"}, - {[]string{"2", "2"}, []string{"2"}, false, "stringSliceEq('%v','%v') => '%v'. Expected '%v'"}, -} - -func TestStringSliceEq(t *testing.T) { - for _, test := range stringSliceEqTests { - var failed bool - - ok := stringSliceEq(test.Left, test.Right) - failed = ok != test.Expected - if failed { - t.Errorf(test.Description, - test.Left, test.Right, // input - ok, // actual output - test.Expected, // expected output - ) - } - } -}