Adding mod_smpp as an event_handler module.

FS-7730 #resolve
This commit is contained in:
William King 2014-10-15 18:26:29 -04:00
parent 1a47cd0d44
commit 775ce5c0a8
11 changed files with 1260 additions and 0 deletions

View File

@ -106,6 +106,7 @@ event_handlers/mod_event_socket
#event_handlers/mod_radius_cdr
#event_handlers/mod_odbc_cdr
#event_handlers/mod_rayo
#event_handlers/mod_smpp
#event_handlers/mod_snmp
#event_handlers/mod_event_zmq
#formats/mod_imagick

View File

@ -0,0 +1,15 @@
<configuration name="smpp.conf" description="SMPP client and server Gateway">
<gateways>
<gateway name="example.com">
<params>
<param name="host" value="example.com"/>
<param name="port" value="2775"/>
<param name="debug" value="1"/>
<param name="profile" value="default"/>
<param name="system_id" value="username"/>
<param name="password" value="password"/>
<param name="system_type" value="remote_smpp"/>
</params>
</gateway>
</gateways>
</configuration>

View File

@ -1383,6 +1383,10 @@ PKG_CHECK_MODULES([AMQP], [librabbitmq >= 0.5.2],[
AM_CONDITIONAL([HAVE_AMQP],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_AMQP],[false])])
PKG_CHECK_MODULES([SMPP34], [libsmpp34 >= 1.10],[
AM_CONDITIONAL([HAVE_SMPP34],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_SMPP34],[false])])
AC_ARG_ENABLE(core-libedit-support,
[AS_HELP_STRING([--disable-core-libedit-support], [Compile without libedit Support])])
@ -1771,6 +1775,7 @@ AC_CONFIG_FILES([Makefile
src/mod/event_handlers/mod_radius_cdr/Makefile
src/mod/event_handlers/mod_odbc_cdr/Makefile
src/mod/event_handlers/mod_rayo/Makefile
src/mod/event_handlers/mod_smpp/Makefile
src/mod/event_handlers/mod_snmp/Makefile
src/mod/event_handlers/mod_event_zmq/Makefile
src/mod/formats/mod_imagick/Makefile

View File

@ -0,0 +1,17 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_smpp
if HAVE_SMPP34
mod_LTLIBRARIES = mod_smpp.la
mod_smpp_la_SOURCES = mod_smpp_utils.c mod_smpp_gateway.c mod_smpp_message.c mod_smpp.c
mod_smpp_la_CFLAGS = $(AM_CFLAGS) $(SMPP34_CFLAGS)
mod_smpp_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_smpp_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(SMPP34_LIBS) $(SWITCH_AM_LDFLAGS)
else
install: error
all: error
error:
$(error You must install libsmpp34-dev to build this module)
endif

View File

@ -0,0 +1,9 @@
TODO:
1. add more encoding options
2. Improve partial read and write support
3. Add storage options, and registration delivery checks.
4. SSL connection support
5. SMPP 5.0 support
6. async message support
7. Add support for configuring chatplan profile for inbound messages from a gateway
8. ... ?

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<include>
<context name="default">
<extension name="smpp34_demo_in">
<condition field="to_user" expression="^12345551234$"/>
<condition field="from_user" expression="^(\d{11})$">
<action application="set" data="to=1001@192.168.100.100"/>
<action application="set" data="from=$1@192.168.100.100"/>
<action application="set" data="proto="/>
<action application="set" data="dest_proto=sip"/>
<action application="info"/>
<action application="set" data="final_delivery=1"/>
<action application="send"/>
</condition>
</extension>
</context>
<context name="public">
<extension name="smpp34_demo_out">
<condition field="from_user" expression="^1001$"/>
<condition field="to_user" expression="^(\d{11})$">
<action application="set" data="from_user=12345551234"/>
<action application="set" data="final_delivery=1"/>
<action application="info"/>
<action application="smpp_send" data="smppgateway"/>
</condition>
</extension>
</context>
</include>

View File

@ -0,0 +1,273 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* William King <william.king@quentustech.com>
*
* mod_smpp.c -- smpp client and server implementation using libsmpp
*
* using libsmpp from: http://cgit.osmocom.org/libsmpp/
*
*/
#include <mod_smpp.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_smpp_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_smpp_shutdown);
SWITCH_MODULE_DEFINITION(mod_smpp, mod_smpp_load, mod_smpp_shutdown, NULL);
mod_smpp_globals_t mod_smpp_globals;
switch_status_t mod_smpp_interface_chat_send(switch_event_t *event)
{
mod_smpp_gateway_t *gateway = NULL;
char *gw_name = switch_event_get_header(event, "smpp_gateway");
if (zstr(gw_name)) {
gw_name = "default";
}
gateway = switch_core_hash_find(mod_smpp_globals.gateways, gw_name);
if (!gateway) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "NO SUCH SMPP GATEWAY[%s].", gw_name);
return SWITCH_STATUS_GENERR;
}
mod_smpp_gateway_send_message(gateway, event);
return SWITCH_STATUS_SUCCESS;
}
/* static switch_status_t name (switch_event_t *message, const char *data) */
SWITCH_STANDARD_CHAT_APP(mod_smpp_chat_send_function)
{
mod_smpp_gateway_t *gateway = NULL;
gateway = switch_core_hash_find(mod_smpp_globals.gateways, data);
if ( !gateway ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "NO SUCH SMPP GATEWAY[%s].", data);
return SWITCH_STATUS_GENERR;
}
mod_smpp_gateway_send_message(gateway, message);
return SWITCH_STATUS_SUCCESS;
}
/* static void name (switch_core_session_t *session, const char *data) */
SWITCH_STANDARD_APP(mod_smpp_app_send_function)
{
switch_event_header_t *chan_var = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_t *message = NULL;
if (switch_event_create(&message, SWITCH_EVENT_MESSAGE) != SWITCH_STATUS_SUCCESS) {
return;
}
/* Copy over recognized channel vars. Then call the chat send function */
/* Cycle through all of the channel headers, and ones with 'smpp_' prefix copy over without the prefix */
for ( chan_var = switch_channel_variable_first(channel); chan_var; chan_var = chan_var->next) {
if ( !strncmp(chan_var->name, "smpp_", 5) ) {
switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, chan_var->name + 5, chan_var->value);
} else {
switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, chan_var->name, chan_var->value);
}
}
/* Unlock the channel variables */
switch_channel_variable_last(channel);
mod_smpp_chat_send_function(message, data);
return;
}
/* static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream) */
SWITCH_STANDARD_API(mod_smpp_debug_api)
{
mod_smpp_globals.debug = switch_true(cmd);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "debug is %s\n", (mod_smpp_globals.debug ? "on" : "off") );
return SWITCH_STATUS_SUCCESS;
}
/* static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream) */
SWITCH_STANDARD_API(mod_smpp_send_api)
{
mod_smpp_gateway_t *gateway = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_event_t *message = NULL;
char *argv[1024] = { 0 };
int argc = 0;
char *cmd_dup = strdup(cmd);
if (!(argc = switch_separate_string(cmd_dup, '|', argv, (sizeof(argv) / sizeof(argv[0]))))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid format. Must be | separated like: gateway|destination|source|message\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
gateway = switch_core_hash_find(mod_smpp_globals.gateways, argv[0]);
if ( !gateway ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "NO SUCH SMPP GATEWAY[%s].", argv[0]);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if (switch_event_create(&message, SWITCH_EVENT_MESSAGE) != SWITCH_STATUS_SUCCESS) {
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, "destination_addr", argv[1]);
switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, "source_addr", argv[2]);
switch_event_set_body(message, argv[3]);
if (mod_smpp_gateway_send_message(gateway, message) != SWITCH_STATUS_SUCCESS) {
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
done:
switch_safe_free(cmd_dup);
return status;
}
switch_status_t mod_smpp_do_config()
{
char *conf = "smpp.conf";
switch_xml_t xml, cfg, gateways, gateway, params, param;
if (!(xml = switch_xml_open_cfg(conf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", conf);
goto err;
}
if ( (gateways = switch_xml_child(cfg, "gateways")) != NULL) {
for (gateway = switch_xml_child(gateways, "gateway"); gateway; gateway = gateway->next) {
mod_smpp_gateway_t *new_gateway = NULL;
char *host = NULL, *system_id = NULL, *password = NULL, *profile = NULL, *system_type = NULL;
int port = 0, debug = 0;
char *name = (char *)switch_xml_attr_soft(gateway, "name");
// Load params
if ( (params = switch_xml_child(gateway, "params")) != NULL) {
for (param = switch_xml_child(params, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
if ( ! strncmp(var, "host", 4) ) {
host = (char *) switch_xml_attr_soft(param, "value");
} else if ( ! strncmp(var, "port", 4) ) {
port = atoi(switch_xml_attr_soft(param, "value"));
} else if ( ! strncmp(var, "debug", 5) ) {
debug = atoi(switch_xml_attr_soft(param, "value"));
} else if ( ! strncmp(var, "system_id", 9) ) {
system_id = (char *) switch_xml_attr_soft(param, "value");
} else if ( ! strncmp(var, "password", 8) ) {
password = (char *) switch_xml_attr_soft(param, "value");
} else if ( ! strncmp(var, "profile", 7) ) {
profile = (char *) switch_xml_attr_soft(param, "value");
} else if ( ! strncmp(var, "system_type", 11) ) {
system_type = (char *) switch_xml_attr_soft(param, "value");
}
}
}
if ( mod_smpp_gateway_create(&new_gateway, name, host, port, debug, system_id, password, system_type, profile) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created gateway[%s]\n", name);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create gateway[%s]\n", name);
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Gateways config is missing\n");
goto err;
}
return SWITCH_STATUS_SUCCESS;
err:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Configuration failed\n");
return SWITCH_STATUS_GENERR;
}
/* switch_status_t name (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION(mod_smpp_load)
{
switch_api_interface_t *mod_smpp_api_interface;
switch_chat_interface_t *mod_smpp_chat_interface;
switch_chat_application_interface_t *mod_smpp_chat_app_interface;
switch_application_interface_t *mod_smpp_app_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
memset(&mod_smpp_globals, 0, sizeof(mod_smpp_globals_t));
mod_smpp_globals.pool = pool;
mod_smpp_globals.debug = 0;
switch_core_hash_init(&(mod_smpp_globals.gateways));
if ( mod_smpp_do_config() != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load due to bad configs\n");
return SWITCH_STATUS_TERM;
}
SWITCH_ADD_CHAT(mod_smpp_chat_interface, "smpp", mod_smpp_interface_chat_send);
SWITCH_ADD_API(mod_smpp_api_interface, "smpp_debug", "mod_smpp toggle debug", mod_smpp_debug_api, NULL);
SWITCH_ADD_API(mod_smpp_api_interface, "smpp_send", "mod_smpp send", mod_smpp_send_api, NULL);
SWITCH_ADD_CHAT_APP(mod_smpp_chat_app_interface, "smpp_send", "send message to gateway", "send message to gateway",
mod_smpp_chat_send_function, "", SCAF_NONE);
SWITCH_ADD_APP(mod_smpp_app_interface, "smpp_send", NULL, NULL, mod_smpp_app_send_function,
"smpp_send", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_smpp_shutdown)
{
switch_hash_index_t *hi;
mod_smpp_gateway_t *gateway = NULL;
/* loop through gateways, and destroy them */
/* destroy gateways hash */
while ((hi = switch_core_hash_first(mod_smpp_globals.gateways))) {
switch_core_hash_this(hi, NULL, NULL, (void **)&gateway);
mod_smpp_gateway_destroy(&gateway);
switch_safe_free(hi);
}
switch_core_hash_destroy(&(mod_smpp_globals.gateways));
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,109 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* William King <william.king@quentustech.com>
*
* mod_smpp.c -- smpp client and server implementation using libsmpp
*
* using libsmpp from: http://cgit.osmocom.org/libsmpp/
*
*/
#ifndef MOD_SMPP_H
#define MOD_SMPP_H
#include <switch.h>
#include <smpp34.h>
#include <smpp34_structs.h>
#include <smpp34_params.h>
typedef struct mod_smpp_globals_s {
switch_memory_pool_t *pool;
switch_hash_t *gateways;
uint8_t debug;
} mod_smpp_globals_t;
extern mod_smpp_globals_t mod_smpp_globals;
typedef struct mod_smpp_gateway_s {
char *name;
char *host;
char *system_id;
char *password;
char *profile;
char *system_type;
char address_range[64];
uint32_t port;
uint32_t sequence;
uint32_t running;
uint32_t debug;
switch_socket_t *socket;
switch_sockaddr_t *socketaddr;
switch_thread_t *thread;
switch_threadattr_t *thd_attr;
switch_mutex_t *conn_mutex;
switch_memory_pool_t *pool;
} mod_smpp_gateway_t;
typedef struct mod_smpp_message_s {
submit_sm_t req;
submit_sm_resp_t res;
} mod_smpp_message_t;
#define MOD_SMPP_TRANS_RESP "mod_smpp::bind_transceiver_resp"
/* mod_smpp_gateway.c */
switch_status_t mod_smpp_gateway_authenticate(mod_smpp_gateway_t *gateway);
switch_status_t mod_smpp_gateway_connect(mod_smpp_gateway_t *gateway);
switch_status_t mod_smpp_gateway_create(mod_smpp_gateway_t **gw, char *name, char*host, int port, int debug, char *system_id,
char *password, char *system_type, char *profile);
switch_status_t mod_smpp_gateway_destroy(mod_smpp_gateway_t **gateway);
switch_status_t mod_smpp_gateway_send_message(mod_smpp_gateway_t *gateway, switch_event_t *message);
switch_status_t mod_smpp_gateway_get_next_sequence(mod_smpp_gateway_t *gateway, uint32_t *seq);
switch_status_t mod_smpp_gateway_connection_read(mod_smpp_gateway_t *gateway, switch_event_t **event, unsigned int *command_id);
switch_status_t mod_smpp_gateway_send_enquire_link_response(mod_smpp_gateway_t *gateway);
switch_status_t mod_smpp_gateway_send_deliver_sm_response(mod_smpp_gateway_t *gateway, switch_event_t *event);
/* mod_smpp_message.c */
switch_status_t mod_smpp_message_encode_body(char *body, int length, unsigned char *bin, uint8_t *enc_length);
switch_status_t mod_smpp_message_create(mod_smpp_gateway_t *gateway, switch_event_t *event, mod_smpp_message_t **message);
switch_status_t mod_smpp_message_decode(mod_smpp_gateway_t *gateway, deliver_sm_t *res, switch_event_t **event);
switch_status_t mod_smpp_message_destroy(mod_smpp_message_t **msg);
/* mod_smpp_utils.c */
void mod_smpp_dump_pdu(void *pdu);
#endif /* MOD_SMPP_H */
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,549 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* William King <william.king@quentustech.com>
*
* mod_smpp.c -- smpp client and server implementation using libsmpp
*
* using libsmpp from: http://cgit.osmocom.org/libsmpp/
*
*/
#include <mod_smpp.h>
static void *SWITCH_THREAD_FUNC mod_smpp_gateway_read_thread(switch_thread_t *thread, void *obj);
switch_status_t mod_smpp_gateway_create(mod_smpp_gateway_t **gw, char *name, char *host, int port, int debug, char *system_id,
char *password, char *system_type, char *profile) {
mod_smpp_gateway_t *gateway = NULL;
switch_memory_pool_t *pool = NULL;
switch_core_new_memory_pool(&pool);
gateway = switch_core_alloc(pool, sizeof(mod_smpp_gateway_t));
gateway->pool = pool;
gateway->running = 1;
gateway->sequence = 1;
gateway->name = name ? switch_core_strdup(gateway->pool, name) : "default";
gateway->host = host ? switch_core_strdup(gateway->pool, host) : "localhost";
gateway->port = port ? port : 8000;
gateway->debug = debug;
gateway->system_id = system_id ? switch_core_strdup(gateway->pool, system_id) : "username";
gateway->password = password ? switch_core_strdup(gateway->pool, password) : "password";
gateway->system_type = system_type ? switch_core_strdup(gateway->pool, system_type) : "freeswitch_smpp";
gateway->profile = profile ? switch_core_strdup(gateway->pool, profile) : "default";
if ( switch_sockaddr_info_get(&(gateway->socketaddr), gateway->host, SWITCH_INET,
gateway->port, 0, mod_smpp_globals.pool) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get socketaddr info\n");
goto err;
}
if ( switch_socket_create(&(gateway->socket), switch_sockaddr_get_family(gateway->socketaddr),
SOCK_STREAM, SWITCH_PROTO_TCP, mod_smpp_globals.pool) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create the socket\n");
goto err;
}
switch_mutex_init(&(gateway->conn_mutex), SWITCH_MUTEX_UNNESTED, mod_smpp_globals.pool);
if (mod_smpp_gateway_connect(gateway) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to connect to gateway[%s]\n", gateway->name);
goto err;
}
/* Start gateway read thread */
switch_threadattr_create(&(gateway->thd_attr), mod_smpp_globals.pool);
switch_threadattr_detach_set(gateway->thd_attr, 1);
switch_threadattr_stacksize_set(gateway->thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&(gateway->thread), gateway->thd_attr, mod_smpp_gateway_read_thread, (void *) gateway, mod_smpp_globals.pool);
switch_core_hash_insert(mod_smpp_globals.gateways, name, (void *) gateway);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Gateway %s created\n", gateway->host);
*gw = gateway;
return SWITCH_STATUS_SUCCESS;
err:
mod_smpp_gateway_destroy(&gateway);
return SWITCH_STATUS_GENERR;
}
switch_status_t mod_smpp_gateway_authenticate(mod_smpp_gateway_t *gateway) {
bind_transceiver_t *req_b = calloc(sizeof(bind_transceiver_t), 1);
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_event_t *event = NULL;
switch_size_t write_len = 0;
unsigned int command_id = 0;
uint8_t local_buffer[1024] = {0};
int local_buffer_len = 1024;
req_b->command_length = 0;
req_b->command_id = BIND_TRANSCEIVER;
req_b->command_status = ESME_ROK;
req_b->addr_npi = 1;
req_b->addr_ton = 1;
strncpy( (char *)req_b->address_range, gateway->host, sizeof(req_b->address_range));
if ( gateway->system_id ) {
strncpy((char *)req_b->system_id, gateway->system_id, sizeof(req_b->system_id));
}
if ( gateway->password ) {
strncpy((char *)req_b->password, gateway->password, sizeof(req_b->password));
}
if ( gateway->system_type ) {
strncpy((char *)req_b->system_type, gateway->system_type, sizeof(req_b->system_type));
}
req_b->interface_version = SMPP_VERSION;
mod_smpp_gateway_get_next_sequence(gateway, &(req_b->sequence_number));
// Not thread safe due to smpp34_errno and smpp34_strerror since they are global to running process.
// The risk here is that the errno and strerror variables will be corrupted due to race conditions if there are errors
if ( smpp34_pack2( local_buffer, sizeof(local_buffer), &local_buffer_len, (void*)req_b) != 0 ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error in smpp_pack():%d:\n%s\n", smpp34_errno, smpp34_strerror);
status = SWITCH_STATUS_GENERR;
goto done;
}
write_len = local_buffer_len;
if ( mod_smpp_globals.debug || gateway->debug ) {
mod_smpp_dump_pdu((void *) req_b);
}
if ( switch_socket_send(gateway->socket, (char *) local_buffer, &write_len) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send on the socket\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if( write_len != local_buffer_len ){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: Was not able to send entire buffer\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
/* Receive the response */
if ( mod_smpp_gateway_connection_read(gateway, &event, &command_id) != SWITCH_STATUS_SUCCESS){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Authentication failed for gateawy[%s]\n", gateway->name);
switch_goto_status(SWITCH_STATUS_GENERR, done);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Authentication successful for gateway[%s]\n", gateway->name);
}
done:
if ( (mod_smpp_globals.debug || gateway->debug ) && event ) {
char *str = NULL;
switch_event_serialize(event, &str, SWITCH_TRUE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Auth response: %s\n", str);
switch_safe_free(str);
}
if ( req_b ) {
switch_safe_free(req_b);
}
return status;
}
/* When connecting to a gateway, the first message must be an authentication attempt */
switch_status_t mod_smpp_gateway_connect(mod_smpp_gateway_t *gateway) {
switch_status_t status;
if ( (status = switch_socket_connect(gateway->socket, gateway->socketaddr)) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to connect the socket %d\n", status);
return SWITCH_STATUS_GENERR;
}
if ( mod_smpp_gateway_authenticate(gateway) != SWITCH_STATUS_SUCCESS ) {
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
/* Expects the gateway to be locked already */
switch_status_t mod_smpp_gateway_connection_read(mod_smpp_gateway_t *gateway, switch_event_t **event, unsigned int *command_id)
{
switch_size_t read_len = 4; /* Default to reading only the first 4 bytes to read how large the PDU is */
switch_status_t status = SWITCH_STATUS_SUCCESS;
uint8_t *local_buffer = calloc(2048, 1);
uint32_t *local_buffer32 = (uint32_t *) local_buffer; /* TODO: Convert this into a union */
switch_event_t *evt = NULL;
generic_nack_t *gennack = NULL;
char data[2048] = {0}; /* local buffer for unpacked PDU */
/* Read from socket */
/* TODO: Add/Expand support for partial reads */
if ( switch_socket_recv(gateway->socket, (char *) local_buffer, &read_len) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to recv on the socket\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if ( read_len != 4 ){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error in recv(PEEK) %d\n", (unsigned int )read_len);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
read_len = ntohl(*local_buffer32 );
if ( read_len > 1500 ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Corrupted PDU size from gateway [%s]\n", gateway->name);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if ( ( status = switch_socket_recv(gateway->socket, (char *) local_buffer + 4, &read_len)) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to recv on the socket %d\n", status);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if ( smpp34_unpack2((void *)data, local_buffer, read_len + 4) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: error decoding the receive buffer:%d:%s\n", smpp34_errno, smpp34_strerror);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if ( mod_smpp_globals.debug || gateway->debug ) {
mod_smpp_dump_pdu((void *) data);
}
gennack = (generic_nack_t *) data;
*command_id = gennack->command_id;
switch(*command_id) {
case BIND_TRANSCEIVER_RESP:
if ( gennack->command_status != ESME_ROK ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Authentication Failure %d\n", gennack->command_status);
}
break;
case DELIVER_SM:
if ( gennack->command_status == ESME_ROK ) {
deliver_sm_t *res = (deliver_sm_t *) data;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New SMS received from[%s] to[%s] message[%s]\n",
res->source_addr, res->destination_addr, res->short_message);
mod_smpp_message_decode(gateway, res, &evt);
}
break;
case ENQUIRE_LINK:
case ENQUIRE_LINK_RESP:
case SUBMIT_SM_RESP:
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unrecognized Command ID: %u\n", *command_id);
}
/* Only need to create/expand the event if it is one of the PDU's that we care about */
if (evt) {
*event = evt;
}
done:
switch_safe_free(local_buffer);
return status;
}
static void *SWITCH_THREAD_FUNC mod_smpp_gateway_read_thread(switch_thread_t *thread, void *obj)
{
mod_smpp_gateway_t *gateway = (mod_smpp_gateway_t *) obj;
while ( gateway->running ) {
switch_event_t *event = NULL;
unsigned int command_id = 0;
if ( mod_smpp_gateway_connection_read(gateway, &event, &command_id) != SWITCH_STATUS_SUCCESS) {
if ( gateway->running ) {
if ( mod_smpp_gateway_connect(gateway) != SWITCH_STATUS_SUCCESS) {
switch_sleep(1000 * 1000);
}
}
continue;
}
if ( (mod_smpp_globals.debug || gateway->debug) && event) {
char *str = NULL;
switch_event_serialize(event, &str, 0);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Received message[%d]:\n%s\n\n", command_id, str);
switch_safe_free(str);
}
switch(command_id) {
case BIND_TRANSCEIVER_RESP:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Why did we get an unexpected authentication response?\n");
break;
case ENQUIRE_LINK:
mod_smpp_gateway_send_enquire_link_response(gateway);
break;
case DELIVER_SM:
if ( event ) {
char *str = NULL;
switch_event_serialize(event, &str, SWITCH_TRUE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Inbound SMS packet event: \n%s\n\n", str);
switch_safe_free(str);
}
mod_smpp_gateway_send_deliver_sm_response(gateway, event);
switch_core_chat_send("smpp", event);
switch_event_destroy(&event);
/* Fire message to the chat plan, then respond */
break;
case SUBMIT_SM_RESP:
case ENQUIRE_LINK_RESP:
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown command_id[%d]\n", command_id);
if ( event ) {
char *str = NULL;
switch_event_serialize(event, &str, SWITCH_FALSE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown packet event: %s\n", str);
switch_safe_free(str);
}
}
}
return 0;
}
switch_status_t mod_smpp_gateway_send_enquire_link_response(mod_smpp_gateway_t *gateway)
{
enquire_link_resp_t *enquire_resp = calloc(sizeof(enquire_link_resp_t), 1);
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_size_t write_len = 0;
uint8_t local_buffer[128] = {0};
int local_buffer_len = sizeof(local_buffer);
enquire_resp->command_length = 0;
enquire_resp->command_id = ENQUIRE_LINK_RESP;
enquire_resp->command_status = ESME_ROK;
mod_smpp_gateway_get_next_sequence(gateway, &(enquire_resp->sequence_number));
if ( smpp34_pack2( local_buffer, sizeof(local_buffer), &local_buffer_len, (void*)enquire_resp) != 0 ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error in smpp_pack():%d:\n%s\n", smpp34_errno, smpp34_strerror);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
write_len = local_buffer_len;
if ( mod_smpp_globals.debug || gateway->debug ) {
mod_smpp_dump_pdu((void *) enquire_resp);
}
if ( switch_socket_send(gateway->socket, (char *) local_buffer, &write_len) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send on the socket\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if( write_len != local_buffer_len ){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: Was not able to send entire buffer\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
done:
switch_safe_free(enquire_resp);
return status;
}
switch_status_t mod_smpp_gateway_send_deliver_sm_response(mod_smpp_gateway_t *gateway, switch_event_t *event)
{
deliver_sm_resp_t *deliver_sm_resp = calloc(sizeof(deliver_sm_resp_t), 1);
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_size_t write_len = 0;
uint8_t local_buffer[128] = {0};
int local_buffer_len = sizeof(local_buffer);
deliver_sm_resp->command_length = 0;
deliver_sm_resp->command_id = DELIVER_SM_RESP;
deliver_sm_resp->command_status = ESME_ROK;
/* deliver_sm_resp->message_id = 0; Not used. calloc defaults to 0 */
deliver_sm_resp->sequence_number = atoi(switch_event_get_header(event, "sequence_number"));
if ( smpp34_pack2( local_buffer, sizeof(local_buffer), &local_buffer_len, (void*)deliver_sm_resp) != 0 ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error in smpp_pack():%d:\n%s\n", smpp34_errno, smpp34_strerror);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
write_len = local_buffer_len;
if ( mod_smpp_globals.debug || gateway->debug ) {
mod_smpp_dump_pdu((void *) deliver_sm_resp);
}
if ( switch_socket_send(gateway->socket, (char *) local_buffer, &write_len) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send on the socket\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if( write_len != local_buffer_len ){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: Was not able to send entire buffer\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
done:
switch_safe_free(deliver_sm_resp);
return status;
}
switch_status_t mod_smpp_gateway_send_unbind(mod_smpp_gateway_t *gateway)
{
unbind_t *unbind_req = calloc(sizeof(unbind_t), 1);
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_size_t write_len = 0;
uint8_t local_buffer[128] = {0};
int local_buffer_len = sizeof(local_buffer);
unbind_req->command_length = 0;
unbind_req->command_id = UNBIND;
unbind_req->command_status = ESME_ROK;
mod_smpp_gateway_get_next_sequence(gateway, &(unbind_req->sequence_number));
if ( smpp34_pack2( local_buffer, sizeof(local_buffer), &local_buffer_len, (void*)unbind_req) != 0 ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error in smpp_pack():%d:\n%s\n", smpp34_errno, smpp34_strerror);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
write_len = local_buffer_len;
if ( mod_smpp_globals.debug || gateway->debug ) {
mod_smpp_dump_pdu((void *) unbind_req);
}
if ( switch_socket_send(gateway->socket, (char *) local_buffer, &write_len) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send on the socket\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if( write_len != local_buffer_len ){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: Was not able to send entire buffer\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
done:
switch_safe_free(unbind_req);
return status;
}
switch_status_t mod_smpp_gateway_destroy(mod_smpp_gateway_t **gw)
{
mod_smpp_gateway_t *gateway = NULL;
if ( !gw || !*gw ) {
return SWITCH_STATUS_SUCCESS;
}
gateway = *gw;
switch_core_hash_delete(mod_smpp_globals.gateways, gateway->name);
gateway->running = 0;
mod_smpp_gateway_send_unbind(gateway);
switch_socket_shutdown(gateway->socket, SWITCH_SHUTDOWN_READWRITE);
switch_socket_close(gateway->socket);
switch_core_destroy_memory_pool(&(gateway->pool));
switch_mutex_destroy(gateway->conn_mutex);
*gw = NULL;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t mod_smpp_gateway_get_next_sequence(mod_smpp_gateway_t *gateway, uint32_t *seq)
{
switch_mutex_lock(gateway->conn_mutex);
gateway->sequence++;
*seq = gateway->sequence;
switch_mutex_unlock(gateway->conn_mutex);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t mod_smpp_gateway_send_message(mod_smpp_gateway_t *gateway, switch_event_t *message) {
mod_smpp_message_t *msg = NULL;
uint8_t local_buffer[1024];
int local_buffer_len = sizeof(local_buffer);
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_size_t write_len = 0;
if ( mod_smpp_message_create(gateway, message, &msg) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to send message due to message_create failure\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
memset(local_buffer, 0, sizeof(local_buffer));
if( smpp34_pack2( local_buffer, sizeof(local_buffer), &local_buffer_len, (void*)&(msg->req)) != 0 ){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: Unable to encode message:%d:\n%s\n", smpp34_errno, smpp34_strerror);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
write_len = local_buffer_len;
if ( mod_smpp_gateway_get_next_sequence(gateway, &(msg->req.sequence_number)) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to fetch next gateway sequence number\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if ( mod_smpp_globals.debug || gateway->debug ) {
mod_smpp_dump_pdu((void *) &(msg->req));
}
if ( switch_socket_send(gateway->socket, (char *) local_buffer, &write_len) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send on the socket\n");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if ( write_len != local_buffer_len ){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "smpp: Did not send all of message to gateway");
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
done:
mod_smpp_message_destroy(&msg);
return status;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,192 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* William King <william.king@quentustech.com>
*
* mod_smpp.c -- smpp client and server implementation using libsmpp
*
* using libsmpp from: http://cgit.osmocom.org/libsmpp/
*
*/
#include <mod_smpp.h>
switch_status_t mod_smpp_message_encode_body(char *body, int length, unsigned char *bin, uint8_t *enc_length)
{
int i = 0;
for ( i = 0; i < length; i++ ) {
bin[i*2] = body[i] / 16;
bin[i*2 + 1] = body[i] % 16;
}
*enc_length = (i * 2) + 1;
return SWITCH_STATUS_SUCCESS;
}
/*
Scratch notes taken during development/interop:
char *message = "5361792048656c6c6f20746f204d79204c6974746c6520467269656e64";
''.join('%02x' % ord(c) for c in u'Скажите привет моему маленькому другу'.encode('utf16'))
Variable length UTF-16 russian text:
char *message = "fffe21043a043004360438044204350420003f044004380432043504420420003c043e0435043c04430420003c0430043b0435043d044c043a043e043c044304200034044004430433044304";
char *mesg_txt = "This is a test SMS message from FreeSWITCH over SMPP";
*/
switch_status_t mod_smpp_message_create(mod_smpp_gateway_t *gateway, switch_event_t *event, mod_smpp_message_t **message)
{
mod_smpp_message_t *msg = calloc(1, sizeof(mod_smpp_message_t));
char *body = switch_event_get_body(event);
assert(*message == NULL);
if ( !body ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to encode message missing body\n");
goto err;
}
if ( mod_smpp_globals.debug || gateway->debug ) {
char *str = NULL;
switch_event_serialize(event, &str, 0);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Creating message from event:\n%s\n", str);
switch_safe_free(str);
}
msg->req.command_id = SUBMIT_SM;
msg->req.command_status = ESME_ROK;
msg->req.command_length = 0;
msg->req.protocol_id = 0;
msg->req.priority_flag = 0;
msg->req.registered_delivery = 0;
msg->req.replace_if_present_flag = 0;
msg->req.sm_default_msg_id = 0;
msg->req.data_coding = 0;
msg->req.source_addr_ton = 1;
msg->req.source_addr_npi = 1;
msg->req.dest_addr_ton = 1;
msg->req.dest_addr_npi = 1;
msg->req.esm_class = 1; /* 0 => default, 1 => datagram, 2 => forward(transaction), 3 => store and forward
2 is endpoint delivery, all others are into a DB first.
*/
mod_smpp_gateway_get_next_sequence(gateway, &(msg->req.sequence_number));
snprintf((char *)msg->req.service_type, sizeof(msg->req.service_type), "%s", "SMS");
snprintf((char *)msg->req.source_addr, sizeof(msg->req.source_addr), "%s", switch_event_get_header(event, "from_user"));
snprintf((char *)msg->req.destination_addr, sizeof(msg->req.destination_addr), "%s", switch_event_get_header(event, "to_user"));
snprintf((char *)msg->req.schedule_delivery_time, sizeof(msg->req.schedule_delivery_time), "%s", "");
snprintf((char *)msg->req.validity_period, sizeof(msg->req.validity_period), "%s", "");
snprintf((char *)msg->req.short_message, sizeof(msg->req.short_message), "%s", body);
msg->req.sm_length = strlen(body);
if ( 0 && mod_smpp_message_encode_body(body, strlen(body),
(unsigned char *) &(msg->req.short_message), &(msg->req.sm_length)) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to encode message body\n");
goto err;
}
*message = msg;
return SWITCH_STATUS_SUCCESS;
err:
switch_safe_free(msg);
return SWITCH_STATUS_GENERR;
}
switch_status_t mod_smpp_message_decode(mod_smpp_gateway_t *gateway, deliver_sm_t *res, switch_event_t **event)
{
switch_event_t *evt = NULL;
char *str = NULL;
if (switch_event_create(&evt, SWITCH_EVENT_MESSAGE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new event\n");
}
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "endpoint", "mod_smpp");
str = switch_mprintf("%d", res->sequence_number);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "sequence_number", str);
str = switch_mprintf("%d", res->command_status);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "command_status", str);
str = switch_mprintf("%d", res->command_id);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "command_id", str);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "smpp_gateway", gateway->name);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "proto", "smpp");
str = switch_mprintf("%d", res->source_addr_ton);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "source_addr_ton", str);
str = switch_mprintf("%d", res->source_addr_npi);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "source_addr_npi", str);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "from_user", (const char *) res->source_addr);
str = switch_mprintf("%d", res->dest_addr_ton);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "dest_addr_ton", str);
str = switch_mprintf("%d", res->dest_addr_npi);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "dest_addr_npi", str);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "to_user", (const char *) res->destination_addr);
str = switch_mprintf("%d", res->data_coding);
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "data_coding", str);
str = NULL;
switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "profile", gateway->profile);
switch_event_add_body(evt, "%s", (const char *) res->short_message);
*event = evt;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t mod_smpp_message_destroy(mod_smpp_message_t **msg)
{
if ( msg ) {
switch_safe_free(*msg);
}
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -0,0 +1,58 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* William King <william.king@quentustech.com>
*
* mod_smpp.c -- smpp client and server implementation using libsmpp
*
* using libsmpp from: http://cgit.osmocom.org/libsmpp/
*
*/
#include <mod_smpp.h>
void mod_smpp_dump_pdu(void *pdu)
{
uint8_t *print_buffer = calloc(4096, 1);
if ( !smpp34_dumpPdu2(print_buffer, 4096, (void*) pdu) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "PDU \n%s\n", print_buffer);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error in smpp_dumpPdu():%d:\n%s\n", smpp34_errno, smpp34_strerror);
}
free(print_buffer);
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/