summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2015-12-19 16:17:40 +0100
committerAlfred E. Heggestad <aeh@db.org>2015-12-19 16:17:40 +0100
commit0e186ba40e7876c39a25e02a16aae6ad651797cf (patch)
tree0b7a76c12485e284f6749b727e97a7c6b8d641cd
parent6a8e3d34355826b66457c86424e8c7f3e8a8260a (diff)
parent6decfc46392a8f68d4eab8f81b2bbe3bdbda2bb6 (diff)
Merge pull request #95 from sreimers/master
Multi Call Echo Module - Experimental
-rw-r--r--modules/echo/echo.c157
-rw-r--r--modules/echo/module.mk9
2 files changed, 166 insertions, 0 deletions
diff --git a/modules/echo/echo.c b/modules/echo/echo.c
new file mode 100644
index 0000000..3fac5ba
--- /dev/null
+++ b/modules/echo/echo.c
@@ -0,0 +1,157 @@
+/**
+ * @file echo.c Echo module
+ */
+#include <re.h>
+#include <baresip.h>
+
+/**
+ *
+ * Multi Call Echo module
+ *
+ * REQUIRES: aubridge
+ * NOTE: This module is experimental.
+ *
+ */
+
+struct session {
+ struct le le;
+ struct call *call_in;
+};
+
+
+static struct list sessionl;
+
+
+static void destructor(void *arg)
+{
+ struct session *sess = arg;
+
+ debug("echo: session destroyed (in=%p)\n",
+ sess->call_in);
+
+ list_unlink(&sess->le);
+ mem_deref(sess->call_in);
+}
+
+
+static void call_event_handler(struct call *call, enum call_event ev,
+ const char *str, void *arg)
+{
+ struct session *sess = arg;
+
+ switch (ev) {
+
+ case CALL_EVENT_CLOSED:
+ debug("echo: CALL_CLOSED: %s\n", str);
+ mem_deref(sess);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static void call_dtmf_handler(struct call *call, char key, void *arg)
+{
+ (void)arg;
+
+ debug("echo: relaying DTMF event: key = '%c'\n", key ? key : '.');
+
+ call_send_digit(call, key);
+}
+
+
+static int new_session(struct call *call)
+{
+ struct session *sess;
+ char a[64];
+ int err = 0;
+
+ sess = mem_zalloc(sizeof(*sess), destructor);
+ if (!sess)
+ return ENOMEM;
+
+ sess->call_in = call;
+
+ re_snprintf(a, sizeof(a), "A-%x", sess);
+
+ audio_set_devicename(call_audio(sess->call_in), a, a);
+
+ call_set_handlers(sess->call_in, call_event_handler,
+ call_dtmf_handler, sess);
+
+ list_append(&sessionl, &sess->le, sess);
+ ua_answer(uag_current(), NULL);
+
+ if (err)
+ mem_deref(sess);
+
+ return err;
+}
+
+
+static void ua_event_handler(struct ua *ua, enum ua_event ev,
+ struct call *call, const char *prm, void *arg)
+{
+ int err;
+ (void)prm;
+ (void)arg;
+
+ switch (ev) {
+
+ case UA_EVENT_CALL_INCOMING:
+ debug("echo: CALL_INCOMING: peer=%s --> local=%s\n",
+ call_peeruri(call),
+ call_localuri(call));
+
+ err = new_session(call);
+ if (err) {
+ ua_hangup(ua, call, 500, "Server Error");
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static int module_init(void)
+{
+ int err;
+
+ list_init(&sessionl);
+
+ err = uag_event_register(ua_event_handler, 0);
+ if (err)
+ return err;
+
+ debug("echo: module loaded\n");
+
+ return 0;
+}
+
+
+static int module_close(void)
+{
+ debug("echo: module closing..\n");
+
+ if (!list_isempty(&sessionl)) {
+
+ info("echo: flushing %u sessions\n", list_count(&sessionl));
+ list_flush(&sessionl);
+ }
+
+ uag_event_unregister(ua_event_handler);
+
+ return 0;
+}
+
+
+const struct mod_export DECL_EXPORTS(echo) = {
+ "echo",
+ "application",
+ module_init,
+ module_close
+};
diff --git a/modules/echo/module.mk b/modules/echo/module.mk
new file mode 100644
index 0000000..0c7ee6f
--- /dev/null
+++ b/modules/echo/module.mk
@@ -0,0 +1,9 @@
+#
+# module.mk
+#
+#
+
+MOD := echo
+$(MOD)_SRCS += echo.c
+
+include mk/mod.mk