From 221dd7da938b5a6d08dcdcaea2cf838a6cb2df3d Mon Sep 17 00:00:00 2001 From: InterLinked1 <24227567+InterLinked1@users.noreply.github.com> Date: Mon, 27 Nov 2023 09:00:10 -0500 Subject: [PATCH] res_msp: Add Message Send Protocol support. This adds support for sending messages via the Message Send Protocol (version 2), using the existing message API. --- README.md | 1 + res/res_msp.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100755 res/res_msp.c diff --git a/README.md b/README.md index 3a3ff2f..c87dc4e 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ PhreakScript installs: - Broadworks compatible device feature key synchronization (PJSIP) - Broadworks compatible Shared Call Appearances (PJSIP) - Presence publishing (PJSIP) + - Message Send Protocol send support - AGI `RECORD FILE` option to require noise before silence detection - Optional build enhancements - `chan_sccp` (improved community Skinny/SCCP channel driver) diff --git a/res/res_msp.c b/res/res_msp.c new file mode 100755 index 0000000..82b68ec --- /dev/null +++ b/res/res_msp.c @@ -0,0 +1,151 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2023, Naveen Albert + * + * Naveen Albert + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Send a message via the RFC1312 Message Send Protocol (version 2) + * + * \author Naveen Albert + * + * \ingroup applications + */ + +/*** MODULEINFO + extended + ***/ + +#include "asterisk.h" + +#include "asterisk/logger.h" +#include "asterisk/module.h" +#include "asterisk/message.h" +#include "asterisk/netsock2.h" +#include "asterisk/config.h" +#include "asterisk/utils.h" + +/*** DOCUMENTATION + + Specifying a prefix of msp: will send the + message to the specified hostname using the Message Send Protocol version 2. + For example: + same => n,Set(MESSAGE(body)=This is my message) will set the message + and same => n,MessageSend(10.1.2.3,Asterisk,Alice) will + send a message to host 10.1.2.3, with a sender of Asterisk + and a recipient of Alice.. + Other Message Send Protocol parameters are not currently supported. + + + Specifying a prefix of msp: will specify the + name of the sender of the message, as defined by RFC 1312. + + + The name of the recipient, as defined in the Message Send Protocol. + Specifying a prefix of msp: will specify the + name of the recipient, as defined by RFC 1312. + This parameter is optional, but may be required by the MSP server. + +***/ + +static int msp_send(const struct ast_msg *msg, const char *destination, const char *from) +{ + ssize_t res; + int sfd; + struct ast_sockaddr addr; + char destbuf[128]; + char *tmp; + const char *hostname, *recip; + char buf[512]; /* Max size of a MSP message */ + int len; + const char *body; + + if (ast_strlen_zero(destination)) { + ast_log(LOG_ERROR, "Missing destination for MSP message\n"); + return -1; + } else if (ast_strlen_zero(from)) { + ast_log(LOG_ERROR, "Missing sender for MSP message\n"); + } + + ast_copy_string(destbuf, destination, sizeof(destbuf)); + tmp = destbuf; + strsep(&tmp, ":"); /* Skip msp: */ + hostname = tmp; + recip = ast_msg_get_to(msg); + + if (ast_strlen_zero(hostname)) { + ast_log(LOG_ERROR, "Missing hostname\n"); + return -1; + } + + body = ast_msg_get_body(msg); + if (ast_strlen_zero(body)) { + ast_log(LOG_ERROR, "No message body to send\n"); + return -1; + } + + /* Construct MSP message */ + len = snprintf(buf, sizeof(buf), "%c%s%c%c%s%c%s%c%c%c%c", /* To satisfy -Werror=format-contains-nul */ + 'B', /* Version 2 of the MSP protocol */ + S_OR(recip, ""), + '\0', + '\0', + body, + '\0', + from, + '\0', + '\0', '\0', '\0'); + + ast_debug(3, "Sending %d-byte MSP message from %s -> %s@%s: %s\n", len, S_OR(from, ""), S_OR(recip, ""), hostname, body); + ast_debug(3, "TO: %s\n", ast_msg_get_to(msg)); + + memset(&addr, 0, sizeof(addr)); + ast_parse_arg(hostname, PARSE_ADDR, &addr); + ast_sockaddr_set_port(&addr, 18); + + /* Message Send Protocol supports delivery via both TCP and UDP. + * Send via UDP, since there's less overhead, and we don't care about the acknowledgment */ + sfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sfd < 0) { + ast_log(LOG_ERROR, "ast_socket failed: %s\n", strerror(errno)); + return -1; + } + + res = ast_sendto(sfd, buf, len, 0, &addr); + if (res <= 0) { + ast_log(LOG_ERROR, "ast_sendto(%s) failed: %s\n", hostname, strerror(errno)); + } + + close(sfd); + return res <= 0 ? -1 : 0; +} + +static const struct ast_msg_tech msg_tech = { + .name = "msp", + .msg_send = msp_send, +}; + +static int unload_module(void) +{ + return ast_msg_tech_unregister(&msg_tech); +} + +static int load_module(void) +{ + return ast_msg_tech_register(&msg_tech); +} + +AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Message Send Protocol");