Hi list,
please find attached a patch against current CVS HEAD to add support for
keyword/alias based smsbox instance MO routing.
This patch was provided by a user. Unfortunately I can't recall which one it
was, so please feel free to "recall me" on this, so the appropriate people get
their credits in the ChangeLog. :)
What it allows is using this for bearerbox's MO routing towards a connected
smsbox instance:
group = smsbox-route
...
keyword = <keyword>
aliases = "<alias1>;<alias2>;...;<aliasN>"
smsbox-id = foobar
which will ensure (in combination if used with the other 2 directives, 'smsc-id'
and 'shortcode') that any MO with the associated keywords are routed to the
'smsbox-id' identified smsbox instance.
Please review and vote for commit to CVS.
Stipe
--
-------------------------------------------------------------------
Kölner Landstrasse 419
40589 Düsseldorf, NRW, Germany
tolj.org system architecture Kannel Software Foundation (KSF)
http://www.tolj.org/ http://www.kannel.org/
mailto:st_{at}_tolj.org mailto:stolj_{at}_kannel.org
-------------------------------------------------------------------
### Eclipse Workspace Patch 1.0
#P gateway-cvs-head
Index: doc/userguide/userguide.xml
===================================================================
RCS file: /home/cvs/gateway/doc/userguide/userguide.xml,v
retrieving revision 1.342
diff -u -r1.342 userguide.xml
--- doc/userguide/userguide.xml 7 Nov 2008 08:46:08 -0000 1.342
+++ doc/userguide/userguide.xml 18 Nov 2008 21:47:16 -0000
@@ -5596,6 +5596,32 @@
the connections in the smsc-id are matched against the
shortcode list.
</entry></row>
+ <row><entry><literal>keyword</literal></entry>
+ <entry>word</entry>
+ <entry valign="bottom">
+ If set, specifies which keyword for inbound messages should
+ be routed to this smsbox instance. Value contains a single
keyword.
+ This rule may be used to pull keyword specific message
streams
+ to an smsbox instance. If used in combination
+ with config directive smsc-id and/or shortcode, then only
messages
+ originating from the connections in the smsc-id and/or with
shortcode
+ destination address are matched against this keyword. If you
need to
+ apply the same rule for several keywords, then the
+ <literal>aliases</literal> directive can be used.
+ </entry></row>
+
+ <row><entry><literal>aliases</literal></entry>
+ <entry>word-list</entry>
+ <entry valign="bottom">
+ If set, specifies which keyword for inbound messages should
+ be routed to this smsbox instance. List contains keywords
seperated.
+ by semicolon (";"). This rule may be used to pull keyword
+ specific message streams to an smsbox instance. If used in
combination
+ with config directive smsc-id and/or shortcode, then only
messages
+ originating from the connections in the smsc-id and/or with
shortcode
+ destination address are matched against these keyword aliases.
+ </entry></row>
+
</tbody>
</tgroup>
</table>
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.134
diff -u -r1.134 cfg.def
--- gwlib/cfg.def 26 Jul 2008 09:21:17 -0000 1.134
+++ gwlib/cfg.def 18 Nov 2008 21:47:19 -0000
@@ -287,6 +287,8 @@
OCTSTR(smsbox-id)
OCTSTR(smsc-id)
OCTSTR(shortcode)
+ OCTSTR(keyword)
+ OCTSTR(aliases)
)
Index: gw/bb_boxc.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_boxc.c,v
retrieving revision 1.91
diff -u -r1.91 bb_boxc.c
--- gw/bb_boxc.c 9 Jan 2008 20:06:58 -0000 1.91
+++ gw/bb_boxc.c 18 Nov 2008 21:47:18 -0000
@@ -64,6 +64,7 @@
* Alexander Malysh (various fixes)
*/
+#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -111,6 +112,8 @@
static Dict *smsbox_by_smsc;
static Dict *smsbox_by_receiver;
static Dict *smsbox_by_smsc_receiver;
+static Dict *smsbox_by_keyword_smsc_receiver;
+static Dict *smsbox_by_keyword_smsc;
static long smsbox_port;
static int smsbox_port_ssl;
@@ -983,6 +986,10 @@
smsbox_by_receiver = NULL;
dict_destroy(smsbox_by_smsc_receiver);
smsbox_by_smsc_receiver = NULL;
+ dict_destroy(smsbox_by_keyword_smsc_receiver);
+ smsbox_by_keyword_smsc_receiver = NULL;
+ dict_destroy(smsbox_by_keyword_smsc);
+ smsbox_by_keyword_smsc = NULL;
gwlist_remove_producer(flow_threads);
}
@@ -997,7 +1004,7 @@
port = (int) *((long*)arg);
fd = make_server_socket(port, NULL);
- /* XXX add interface_name if required */
+ /* XXX add interface_name if required */
if (fd < 0) {
panic(0, "Could not open wapbox port %d", port);
@@ -1009,16 +1016,13 @@
gwlist_remove_producer(outgoing_wdp);
-
- /* wait for all connections to die and then remove list
- */
-
- while(gwlist_wait_until_nonempty(wapbox_list) == 1)
+ /* wait for all connections to die and then remove list */
+ while (gwlist_wait_until_nonempty(wapbox_list) == 1)
gwthread_sleep(1.0);
/* wait for wdp_to_wapboxes to exit */
- while(gwlist_consume(wapbox_list)!=NULL)
- ;
+ while (gwlist_consume(wapbox_list) != NULL)
+ ;
/* close listen socket */
close(fd);
@@ -1037,8 +1041,8 @@
{
CfgGroup *grp;
List *list, *items;
- Octstr *boxc_id, *smsc_ids, *shortcuts;
- int i, j;
+ Octstr *boxc_id, *smsc_ids, *shortcuts, *keyword, *aliases;
+ int i, j, k;
boxc_id = smsc_ids = shortcuts = NULL;
@@ -1063,9 +1067,15 @@
*/
smsc_ids = cfg_get(grp, octstr_imm("smsc-id"));
shortcuts = cfg_get(grp, octstr_imm("shortcode"));
+ keyword = cfg_get(grp, octstr_imm("keyword"));
+ aliases = cfg_get(grp, octstr_imm("aliases"));
+ if (keyword != NULL) {
+ octstr_convert_range(keyword, 0, octstr_len(keyword), tolower);
+ octstr_strip_blanks(keyword);
+ }
/* consider now the 3 possibilities: */
- if (smsc_ids && !shortcuts) {
+ if (smsc_ids && !shortcuts && !keyword) {
/* smsc-id only, so all MO traffic */
items = octstr_split(smsc_ids, octstr_imm(";"));
for (i = 0; i < gwlist_len(items); i++) {
@@ -1082,7 +1092,7 @@
gwlist_destroy(items, octstr_destroy_item);
octstr_destroy(smsc_ids);
}
- else if (!smsc_ids && shortcuts) {
+ else if (!smsc_ids && shortcuts && !keyword) {
/* shortcode only, so these MOs from all smscs */
items = octstr_split(shortcuts, octstr_imm(";"));
for (i = 0; i < gwlist_len(items); i++) {
@@ -1099,7 +1109,7 @@
gwlist_destroy(items, octstr_destroy_item);
octstr_destroy(shortcuts);
}
- else if (smsc_ids && shortcuts) {
+ else if (smsc_ids && shortcuts && !keyword) {
/* both, so only specified MOs from specified smscs */
items = octstr_split(shortcuts, octstr_imm(";"));
for (i = 0; i < gwlist_len(items); i++) {
@@ -1128,6 +1138,126 @@
gwlist_destroy(items, octstr_destroy_item);
octstr_destroy(shortcuts);
}
+ else if (smsc_ids && shortcuts && keyword && !aliases) {
+ /* all, so only specified MOs from specified smscs and with
specified keyword */
+ items = octstr_split(shortcuts, octstr_imm(";"));
+ for (i = 0; i < gwlist_len(items); i++) {
+ List *subitems;
+ Octstr *item = gwlist_get(items, i);
+ octstr_strip_blanks(item);
+ subitems = octstr_split(smsc_ids, octstr_imm(";"));
+ for (j = 0; j < gwlist_len(subitems); j++) {
+ Octstr *subitem = gwlist_get(subitems, j);
+ octstr_strip_blanks(subitem);
+
+ debug("bb.boxc",0,"Adding smsbox routing to id <%s> "
+ "for receiver no <%s> and smsc id <%s> and keyword
<%s>",
+ octstr_get_cstr(boxc_id), octstr_get_cstr(item),
+ octstr_get_cstr(subitem), octstr_get_cstr(keyword));
+
+ /* construct the dict key
'<keyword>:<shortcode>:<smsc-id>' */
+ octstr_insert(subitem, item, 0);
+ octstr_insert_char(subitem, octstr_len(item), ':');
+ octstr_insert(subitem, keyword, 0);
+ octstr_insert_char(subitem, octstr_len(keyword), ':');
+ if (!dict_put_once(smsbox_by_keyword_smsc_receiver,
subitem, octstr_duplicate(boxc_id)))
+ panic(0, "Routing for keyword:receiver:smsc <%s>
already exists!",
+ octstr_get_cstr(subitem));
+ }
+ gwlist_destroy(subitems, octstr_destroy_item);
+ }
+ gwlist_destroy(items, octstr_destroy_item);
+ octstr_destroy(shortcuts);
+ }
+ else if (smsc_ids && shortcuts && keyword && aliases) {
+ /* lets add keyword to aliases list so it would be easier to parse
it */
+ octstr_insert(aliases, keyword, 0);
+ octstr_insert_char(aliases, octstr_len(keyword), ';');
+
+ /* all, so only specified MOs from specified smscs and with
+ * specified keyword and/or alias */
+ items = octstr_split(shortcuts, octstr_imm(";"));
+ for (i = 0; i < gwlist_len(items); i++) {
+ List *subitems;
+ Octstr *item = gwlist_get(items, i);
+ octstr_strip_blanks(item);
+ subitems = octstr_split(smsc_ids, octstr_imm(";"));
+ for (j = 0; j < gwlist_len(subitems); j++) {
+ Octstr *subitem = gwlist_get(subitems, j);
+ octstr_strip_blanks(subitem);
+
+ List *subsubitems;
+ subsubitems = octstr_split(aliases, octstr_imm(";"));
+
+ for (k = 0; k < gwlist_len(subsubitems); k++) {
+ Octstr *subsubitem = gwlist_get(subsubitems, k);
+ octstr_strip_blanks(subsubitem);
+ octstr_convert_range(subsubitem, 0,
octstr_len(subsubitem), tolower);
+
+ debug("bb.boxc",0,"Adding smsbox routing to id <%s> "
+ "for receiver no <%s> and smsc id <%s> and
keyword/alias <%s>",
+ octstr_get_cstr(boxc_id), octstr_get_cstr(item),
+ octstr_get_cstr(subitem),
octstr_get_cstr(subsubitem));
+
+ /* construct the dict key
'<keyword>:<shortcode>:<smsc-id>' */
+ Octstr *dictitem = octstr_duplicate(subitem);
+ octstr_insert(dictitem, item, 0);
+ octstr_insert_char(dictitem, octstr_len(item), ':');
+ octstr_insert(dictitem, subsubitem, 0);
+ octstr_insert_char(dictitem, octstr_len(subsubitem),
':');
+
+ debug("bb.boxc",0,"Adding smsbox routing <%s> ",
+ octstr_get_cstr(dictitem));
+
+ if (!dict_put_once(smsbox_by_keyword_smsc_receiver,
dictitem,
+ octstr_duplicate(boxc_id)))
+ panic(0, "Routing for keyword:receiver:smsc <%s>
already exists!",
+ octstr_get_cstr(dictitem));
+ }
+ gwlist_destroy(subsubitems, octstr_destroy_item);
+ }
+ gwlist_destroy(subitems, octstr_destroy_item);
+ }
+ gwlist_destroy(items, octstr_destroy_item);
+ octstr_destroy(shortcuts);
+ }
+ else if (smsc_ids && !shortcuts && keyword && aliases) {
+ /* lets add keyword to aliases list so it would be easier to parse
it */
+ octstr_insert(aliases, keyword, 0);
+ octstr_insert_char(aliases, octstr_len(keyword), ';');
+
+ /* both, so only specified MOs from specified smscs */
+ items = octstr_split(aliases, octstr_imm(";"));
+ for (i = 0; i < gwlist_len(items); i++) {
+ List *subitems;
+ Octstr *item = gwlist_get(items, i);
+ octstr_strip_blanks(item);
+ subitems = octstr_split(smsc_ids, octstr_imm(";"));
+ for (j = 0; j < gwlist_len(subitems); j++) {
+ Octstr *subitem = gwlist_get(subitems, j);
+ octstr_strip_blanks(subitem);
+
+ debug("bb.boxc",0,"Adding smsbox routing to id <%s> "
+ "for smsc-id <%s> and smsc id <%s>",
+ octstr_get_cstr(boxc_id), octstr_get_cstr(item),
+ octstr_get_cstr(subitem));
+
+ /* construct the dict key '<keyword>:<smsc-id>' */
+ octstr_insert(subitem, item, 0);
+ octstr_insert_char(subitem, octstr_len(item), ':');
+
+ debug("bb.boxc", 0, "Routing for keyword:smsc <%s> already
exists!",
+ octstr_get_cstr(subitem));
+
+ if (!dict_put_once(smsbox_by_keyword_smsc, subitem,
octstr_duplicate(boxc_id)))
+ panic(0, "Routing for receiver:smsc <%s> already
exists!",
+ octstr_get_cstr(subitem));
+ }
+ gwlist_destroy(subitems, octstr_destroy_item);
+ }
+ gwlist_destroy(items, octstr_destroy_item);
+ octstr_destroy(shortcuts);
+ }
octstr_destroy(boxc_id);
}
@@ -1176,6 +1306,8 @@
smsbox_by_smsc = dict_create(30, (void(*)(void *)) octstr_destroy);
smsbox_by_receiver = dict_create(50, (void(*)(void *)) octstr_destroy);
smsbox_by_smsc_receiver = dict_create(50, (void(*)(void *))
octstr_destroy);
+ smsbox_by_keyword_smsc_receiver = dict_create(50, (void(*)(void *))
octstr_destroy);
+ smsbox_by_keyword_smsc = dict_create(50, (void(*)(void *)) octstr_destroy);
/* load the defined smsbox routing rules */
init_smsbox_routes(cfg);
@@ -1415,9 +1547,12 @@
int route_incoming_to_boxc(Msg *msg)
{
Boxc *bc = NULL, *best = NULL;
- Octstr *s, *r, *rs;
+ Octstr *s, *r, *rs, *krs;
long len, b, i;
int full_found = 0;
+ List *word_list;
+ int num_words;
+ Octstr *keyword;
s = r = NULL;
gw_assert(msg_type(msg) == sms);
@@ -1458,6 +1593,38 @@
* Where the shortcode route has a higher priority then the smsc-id
rule.
* Highest priority has the combined <shortcode>:<smsc-id> route.
*/
+
+ if (msg->sms.msgdata && octstr_len(msg->sms.msgdata)) {
+ word_list = octstr_split_words(msg->sms.msgdata);
+ num_words = gwlist_len(word_list);
+ word_list = octstr_split_words(msg->sms.msgdata);
+ num_words = gwlist_len(word_list);
+ } else {
+ word_list = gwlist_create();
+ num_words = 0;
+ }
+
+ if (num_words >= 1) {
+ keyword = octstr_duplicate(gwlist_get(word_list, 0));
+ Octstr *kos = octstr_format("%s:%s:%s",
+ octstr_get_cstr(keyword),
+ octstr_get_cstr(msg->sms.receiver),
+ octstr_get_cstr(msg->sms.smsc_id));
+ krs = (kos ? dict_get(smsbox_by_keyword_smsc_receiver, kos) :
NULL);
+ octstr_destroy(kos);
+ if (!krs) {
+ Octstr *ks = octstr_format("%s:%s",
+ octstr_get_cstr(keyword),
+ octstr_get_cstr(msg->sms.smsc_id));
+ krs = (ks ? dict_get(smsbox_by_keyword_smsc, ks) : NULL);
+ octstr_destroy(ks);
+ }
+ } else {
+ krs = NULL;
+ }
+
+ gwlist_destroy(word_list, octstr_destroy_item);
+
Octstr *os = octstr_format("%s:%s",
octstr_get_cstr(msg->sms.receiver),
octstr_get_cstr(msg->sms.smsc_id));
@@ -1465,8 +1632,10 @@
r = (msg->sms.receiver ? dict_get(smsbox_by_receiver,
msg->sms.receiver) : NULL);
rs = (os ? dict_get(smsbox_by_smsc_receiver, os) : NULL);
octstr_destroy(os);
- bc = rs ? dict_get(smsbox_by_id, rs) :
- (r ? dict_get(smsbox_by_id, r) : (s ? dict_get(smsbox_by_id, s) :
NULL));
+ bc = krs ? dict_get(smsbox_by_id, krs) : (
+ rs ? dict_get(smsbox_by_id, rs) :
+ (r ? dict_get(smsbox_by_id, r) : (s ?
dict_get(smsbox_by_id, s) : NULL))
+ );
}
/* check if we found our routing */