1
0
Fork 0

Compare commits

...

388 Commits

Author SHA1 Message Date
bagyenda 73955b34cf Patch from jacek -- allow-adaptations on a per-MMSC basis 2014-02-11 12:43:53 +00:00
bagyenda cb989364b8 Updated with Patches from Jacek 2014-02-11 08:47:29 +00:00
bagyenda be8dc0ee28 Added Fix from Jacek Raczkiewicz <jacek@skycore.com> 2013-12-16 09:22:49 +00:00
bagyenda 5208b4311f Added X-Carrier ID header 2012-04-09 23:45:30 +00:00
bagyenda 628fc0c744 more mem leak fixes 2011-10-12 10:21:42 +00:00
bagyenda 58ebfcc0fd mem leak fix 2011-10-12 05:13:29 +00:00
bagyenda 1eb8f06cb6 fixed compilation issues 2011-10-03 14:16:24 +00:00
bagyenda 3cd18abe87 fix for libmms.a 2011-09-29 09:33:23 +00:00
bagyenda 61ff6817fa MM4_delivery_report.RES handling fix 2011-09-23 06:27:37 +00:00
bagyenda 5cd58210fe MM4_Forward.RES fix 2011-09-20 03:59:02 +00:00
bagyenda 0d2974bd27 Misc. code movements 2011-09-12 13:59:01 +00:00
bagyenda f67330f9e0 Misc. additions 2011-09-08 10:47:58 +00:00
bagyenda e7b5faee07 Fixed uaprof timestamp bug 2011-07-27 14:24:11 +00:00
bagyenda 11c50d6217 mmsc_cfg.c fix 2011-05-30 05:03:12 +00:00
bagyenda 044e3ebbe6 further rfc 2047 fixes 2011-05-05 05:40:23 +00:00
bagyenda 265c827fe1 Fixed parsing of plain RFC 2047 strings 2011-05-04 11:19:45 +00:00
bagyenda dc3ad6068d *** empty log message *** 2011-03-31 06:07:47 +00:00
bagyenda d155bd57d4 *** empty log message *** 2011-03-31 06:03:50 +00:00
bagyenda 8efe4605bc Documentation updated with admin-port info 2011-03-30 08:22:01 +00:00
bagyenda 1e14a17e39 moved mm1 mm7 code into base 2011-03-24 12:58:11 +00:00
bagyenda 6a34ce5ca2 Misc changes 2011-03-22 08:00:23 +00:00
bagyenda 9a7952d200 added gprs-off command to mmsbox mm1 module 2011-01-12 09:47:14 +00:00
bagyenda fae80063f8 strip fixes -- more fixes 2011-01-06 06:13:12 +00:00
bagyenda fd2ff89411 strip fixes -- more fixes 2011-01-06 06:10:20 +00:00
bagyenda 919aef48d5 strip fixes -- more fixes 2011-01-06 05:55:35 +00:00
bagyenda 442846f4c0 *** empty log message *** 2011-01-05 12:17:09 +00:00
bagyenda 7c1654c5dd fixed building of shared libs on osx 2011-01-05 06:32:48 +00:00
bagyenda fedce613cf added strip-prefixes option for mmsc 2011-01-05 05:53:14 +00:00
bagyenda 67d8049f1b mmsbox mm1 bug fix from piotr 2011-01-04 18:16:18 +00:00
bagyenda eba4e9e09d fixed dlr-url call when message not delivered 2011-01-03 06:57:50 +00:00
bagyenda cdabed7443 mmsbox now sends multiple recipients per transaction 2010-12-09 10:36:29 +00:00
bagyenda 18dd46568f rfc 2047 bug fix 2010-11-30 05:00:33 +00:00
bagyenda e64d8d322d Added improved encoding of charsets in mm1 2010-11-29 12:30:03 +00:00
bagyenda 17a2cbfc90 default log level fix 2010-11-26 14:26:09 +00:00
bagyenda 2891e9bb27 minor fix 2010-11-23 07:11:39 +00:00
matlads f65646e1b8 remove temporary threads from monitoring 2010-11-22 09:03:26 +00:00
matlads 6a459a63f6 allow the name of the thread in the thread monitor functions 2010-11-18 06:51:17 +00:00
bagyenda 7c777cd10f minor fix 2010-11-16 11:35:02 +00:00
bagyenda e104515d9b updated mmsbox callback interface usage 2010-11-05 06:26:49 +00:00
bagyenda 6cb349ec90 updated mmsbox callback interface usage 2010-11-05 05:49:56 +00:00
bagyenda ea9506fde2 minor compile error fixes 2010-11-04 06:26:31 +00:00
bagyenda 821f4f32bf changed configure.ac 2010-11-03 11:49:26 +00:00
matlads bcfb4ea87b Fix typo in configure.ac. detecting external libs should now work again 2010-11-03 10:17:20 +00:00
bagyenda 83d5d370b3 added smtp sender 2010-10-27 06:08:50 +00:00
bagyenda 60be3311ca misc bug fixes 2010-10-26 17:40:49 +00:00
bagyenda fd2ed9038f added mm4 incoming handler for mmsbox 2010-10-26 10:18:13 +00:00
bagyenda 20ae441d94 added misc logging stuff 2010-10-21 17:51:16 +00:00
bagyenda bf5c6e2c6c *** empty log message *** 2010-09-12 16:54:08 +00:00
bagyenda 92563ae701 *** empty log message *** 2010-08-09 09:38:55 +00:00
bagyenda f23dfb66b9 *** empty log message *** 2010-08-04 10:02:46 +00:00
bagyenda 6e23d68a16 *** empty log message *** 2010-07-02 13:39:27 +00:00
bagyenda 8c51f383d7 *** empty log message *** 2010-05-26 10:36:27 +00:00
bagyenda 3223e679cb *** empty log message *** 2010-01-25 09:40:23 +00:00
bagyenda 9693113f21 *** empty log message *** 2010-01-04 05:00:56 +00:00
bagyenda e6de3e5b31 *** empty log message *** 2009-12-01 05:15:45 +00:00
bagyenda 79cd5a1c7b *** empty log message *** 2009-11-22 03:49:12 +00:00
bagyenda ab8828922d *** empty log message *** 2009-10-14 03:36:32 +00:00
bagyenda 4f185a7032 *** empty log message *** 2009-10-13 12:49:31 +00:00
bagyenda 760b8d734e *** empty log message *** 2009-09-08 12:47:33 +00:00
bagyenda 09e891bcc9 *** empty log message *** 2009-08-13 04:03:36 +00:00
bagyenda 48bc07ef14 *** empty log message *** 2009-08-12 17:00:06 +00:00
bagyenda 41fba4873d *** empty log message *** 2009-08-06 08:39:02 +00:00
bagyenda 8ba2b9b126 *** empty log message *** 2009-08-06 08:07:43 +00:00
bagyenda 7206e8b20d *** empty log message *** 2009-08-06 07:36:39 +00:00
bagyenda 00bdd513fe *** empty log message *** 2009-08-06 07:24:31 +00:00
bagyenda 18cd80e632 *** empty log message *** 2009-08-06 05:13:37 +00:00
bagyenda adc01f651f *** empty log message *** 2009-07-07 07:12:47 +00:00
bagyenda 8e72d4ca3b *** empty log message *** 2009-07-02 07:08:11 +00:00
bagyenda 83a824759b *** empty log message *** 2009-07-02 04:43:34 +00:00
bagyenda a7be9632e7 *** empty log message *** 2009-07-02 04:32:23 +00:00
bagyenda e499aa8131 *** empty log message *** 2009-06-23 05:14:22 +00:00
bagyenda 0ee33f2da1 *** empty log message *** 2009-05-12 05:57:47 +00:00
bagyenda 3d663b90a9 *** empty log message *** 2009-05-06 07:51:53 +00:00
bagyenda 6b35184a7e *** empty log message *** 2009-05-06 07:24:57 +00:00
bagyenda 1db281efec *** empty log message *** 2009-05-06 05:54:51 +00:00
bagyenda 5fcfe061af *** empty log message *** 2009-05-06 05:38:41 +00:00
bagyenda e35d2ffa26 *** empty log message *** 2009-05-06 05:12:32 +00:00
bagyenda 790e15eb20 *** empty log message *** 2009-03-30 13:33:39 +00:00
bagyenda 53b7e978e4 Improved pgsql-queue code 2009-03-30 11:45:10 +00:00
bagyenda b2ba6dfdb5 *** empty log message *** 2009-03-28 12:29:03 +00:00
bagyenda 828a78bcf3 *** empty log message *** 2009-03-13 13:49:57 +00:00
bagyenda 1e761682a5 *** empty log message *** 2009-03-05 04:15:38 +00:00
bagyenda a15d86fa74 *** empty log message *** 2009-03-03 21:08:12 +00:00
bagyenda 5000597c67 *** empty log message *** 2009-03-03 20:35:13 +00:00
bagyenda abb7b6d2d1 *** empty log message *** 2009-03-01 06:34:12 +00:00
bagyenda a721364402 *** empty log message *** 2009-02-26 12:42:39 +00:00
bagyenda cda686d77a *** empty log message *** 2009-02-26 04:10:27 +00:00
bagyenda d27f4c0f8a *** empty log message *** 2009-02-25 14:31:47 +00:00
bagyenda 462972c4a3 *** empty log message *** 2009-02-16 07:30:54 +00:00
bagyenda 9a0785830c *** empty log message *** 2009-02-16 05:55:47 +00:00
bagyenda c2887c0857 *** empty log message *** 2009-02-11 04:16:27 +00:00
bagyenda b00dcbe383 *** empty log message *** 2009-02-11 04:12:52 +00:00
bagyenda af393b2afe *** empty log message *** 2009-02-09 08:48:56 +00:00
bagyenda c96438a274 *** empty log message *** 2009-02-03 03:44:34 +00:00
bagyenda d98f7906b6 *** empty log message *** 2009-01-28 19:38:36 +00:00
bagyenda c2c0ce7fe3 *** empty log message *** 2009-01-22 14:17:10 +00:00
bagyenda 25d8d878c7 *** empty log message *** 2009-01-22 06:34:47 +00:00
bagyenda 2aed655a12 pgsql-queue fix 2009-01-22 06:09:36 +00:00
bagyenda e402334756 *** empty log message *** 2009-01-20 20:33:54 +00:00
bagyenda 7d69e70dc3 improved mmsc logging on transient errors 2009-01-17 04:31:21 +00:00
bagyenda d62e733178 mm1 improvements 2009-01-16 05:47:43 +00:00
bagyenda 037183a65a admin fixes 2009-01-12 15:33:20 +00:00
bagyenda 76cb3e6f5b admin port fixes 2009-01-12 15:12:02 +00:00
bagyenda 591c61f094 *** empty log message *** 2008-12-26 09:56:43 +00:00
bagyenda 967898a995 mm1 speedups 2008-12-24 19:00:30 +00:00
bagyenda 2544b6d718 fixes for mm1 push 2008-12-17 17:29:40 +00:00
bagyenda 0e5dad042b *** empty log message *** 2008-12-10 22:23:35 +00:00
bagyenda 28231a7d7e *** empty log message *** 2008-12-10 16:56:25 +00:00
bagyenda ec32ce868e eaif fix 2008-12-10 11:13:58 +00:00
bagyenda b8ea7dac27 *** empty log message *** 2008-12-10 06:00:43 +00:00
bagyenda cb2e860093 extra headers in mmsbox url service call 2008-12-10 05:35:04 +00:00
bagyenda 5247c97695 fix for msisdn and ip request headers in mmsc 2008-12-09 03:35:26 +00:00
bagyenda 1a1b8ba5e5 *** empty log message *** 2008-12-04 13:15:44 +00:00
bagyenda e60ed679b4 Solaris fixes 2008-12-04 09:06:26 +00:00
bagyenda 8b05add577 *** empty log message *** 2008-12-01 05:41:10 +00:00
bagyenda be5d0a6bc9 misc fixes 2008-12-01 05:14:56 +00:00
bagyenda e090e6795e *** empty log message *** 2008-11-26 18:30:42 +00:00
bagyenda d93be7fce5 mmsbox cdr changes 2008-11-26 09:16:20 +00:00
bagyenda f10b0e4e41 minor mmsbox dlr improvements 2008-11-21 05:19:43 +00:00
bagyenda b064ee14f0 Minor mmsbox fixes 2008-11-20 08:43:52 +00:00
bagyenda b579472a52 *** empty log message *** 2008-11-19 18:00:05 +00:00
bagyenda 3db2d7db6c *** empty log message *** 2008-11-19 17:24:33 +00:00
bagyenda 8aa1a1a0be *** empty log message *** 2008-11-19 04:59:37 +00:00
bagyenda bc1a24200e PGSQL queue module changes: optionally move message storage to file 2008-11-14 08:52:15 +00:00
bagyenda 6c5759f1e9 *** empty log message *** 2008-11-13 17:35:28 +00:00
bagyenda fcebda1812 minor changes to cfg-impl interface 2008-11-12 16:48:47 +00:00
bagyenda e370a86566 added retries to DLR URL calling in mmsbox 2008-11-12 10:30:30 +00:00
bagyenda 39f5cccee4 minor base64 fix 2008-11-04 04:29:22 +00:00
bagyenda 00198c858a minor fix for mmsbox dlr relaying 2008-10-16 14:20:13 +00:00
bagyenda c26a3d3e24 vasp-id added 2008-10-02 13:49:07 +00:00
bagyenda 5cd0188e94 fix for xml output of admin interface 2008-10-01 13:33:15 +00:00
bagyenda bb16c3299a Improved dlr routing for mmsbox 2008-09-29 14:58:23 +00:00
bagyenda 9490de2bc8 *** empty log message *** 2008-09-24 14:22:40 +00:00
bagyenda 09bb2abe14 *** empty log message *** 2008-09-22 17:47:37 +00:00
bagyenda 4a2ad20874 *** empty log message *** 2008-09-22 10:18:19 +00:00
bagyenda 445723dc0f *** empty log message *** 2008-09-19 18:30:42 +00:00
bagyenda a1fa945c5f *** empty log message *** 2008-09-19 15:58:15 +00:00
bagyenda c0e677a7a5 order of xml fields 2008-09-15 10:37:44 +00:00
bagyenda 3e3b9b2b2b improved dlr 2008-09-14 11:33:59 +00:00
bagyenda 0dfdfdc305 DLR relay 2008-09-13 06:37:24 +00:00
bagyenda b480d170a5 added cdr stuff for mmsbox 2008-09-12 12:02:40 +00:00
bagyenda 069455ec3d mm7 changes -- special header add 2008-09-12 08:46:46 +00:00
bagyenda 04037fbb64 added default-vasid param 2008-09-11 19:06:49 +00:00
bagyenda 335682874b *** empty log message *** 2008-09-11 17:47:58 +00:00
bagyenda b82e3f2723 added mmsc type http 2008-09-11 09:11:00 +00:00
bagyenda 671a62699d added mmsc type http 2008-09-11 09:03:59 +00:00
bagyenda 5afec26e5d mmsc admin interface 2008-09-08 11:50:24 +00:00
bagyenda f55d24567f *** empty log message *** 2008-09-06 13:54:43 +00:00
bagyenda 30973cf9e5 *** empty log message *** 2008-09-04 17:20:42 +00:00
bagyenda 02a5ede686 content-id fix for mmsbox 2008-09-04 06:49:36 +00:00
bagyenda 6263d512b8 *** empty log message *** 2008-09-03 04:38:13 +00:00
bagyenda 1a3aa4c9aa Added admin interface for mmsbox 2008-09-02 11:07:16 +00:00
bagyenda 30d9e2c0d4 *** empty log message *** 2008-09-01 17:20:24 +00:00
bagyenda 526ec741fb re-org of mmsc code into one executable: mmsc 2008-09-01 15:18:43 +00:00
bagyenda 2236d0e9e5 *** empty log message *** 2008-08-29 11:26:27 +00:00
bagyenda b7bd482849 misc changes 2008-08-29 10:23:17 +00:00
bagyenda c6591fc15b config can be loaded by a module (e.g. from a db) 2008-08-28 16:07:31 +00:00
bagyenda bf9218da78 *** empty log message *** 2008-08-28 09:40:52 +00:00
bagyenda fb68ed198e added default mmsc to send-mms group 2008-08-20 07:55:29 +00:00
bagyenda 9b99b14955 *** empty log message *** 2008-08-19 15:33:53 +00:00
bagyenda 2ff5dabb9e Misc fixes 2008-08-19 06:45:48 +00:00
bagyenda b477dd843c *** empty log message *** 2008-08-18 07:16:17 +00:00
bagyenda 3b1371f55f Added mms2email functionality to mmsbox 2008-08-14 11:44:58 +00:00
bagyenda f7bc48d88d mms decoder bug/crash fixes 2008-08-08 18:35:12 +00:00
bagyenda 85babd8de0 minor fix to content adaptation module 2008-08-08 12:39:24 +00:00
bagyenda 3f4df1cdc7 fix for dlr and rr 2008-08-06 17:45:08 +00:00
bagyenda 80682bbcb3 *** empty log message *** 2008-08-06 06:09:48 +00:00
bagyenda 49ae1c2a69 *** empty log message *** 2008-08-06 05:01:20 +00:00
bagyenda 13e9649091 minor fix -- mmsproxy 2008-08-05 05:21:34 +00:00
bagyenda d63cc82ea8 *** empty log message *** 2008-07-19 01:08:40 +00:00
bagyenda f654396ea5 *** empty log message *** 2008-07-18 22:58:31 +00:00
bagyenda 7c7de0e22d improved scaling 2008-07-18 21:30:18 +00:00
bagyenda 06e4a94eb0 url-list mime type 2008-07-16 18:50:34 +00:00
bagyenda 590444539c added application/vnd.mbuni.url-list 2008-07-15 22:36:12 +00:00
bagyenda b99cbd96fa *** empty log message *** 2008-07-10 10:13:10 +00:00
bagyenda fe4c53f2be misc. fixes 2008-07-10 09:46:58 +00:00
bagyenda 0cb6626339 fix for DLR in MM4 2008-07-09 04:40:35 +00:00
bagyenda f7fa35d3ea moved to cvs 2008-07-07 14:36:29 +00:00
bagyenda 4cdb712d76 Message-ID fixup 2008-07-07 06:35:43 +00:00
bagyenda 5b5fa1fd7b misc fixes for mms decoding PANICs 2008-07-04 14:51:26 +00:00
bagyenda 6445ca1403 MM4 incoming fix -- now using unified prefix stuff 2008-07-02 16:25:16 +00:00
bagyenda ce84ac2e7b *** empty log message *** 2008-06-27 17:02:28 +00:00
bagyenda 505e998657 *** empty log message *** 2008-06-26 14:42:26 +00:00
bagyenda 47172dbb5f added pgsql-queue into build process 2008-06-26 11:39:49 +00:00
bagyenda 173be8807a *** empty log message *** 2008-06-25 17:28:24 +00:00
bagyenda 769690693d *** empty log message *** 2008-06-24 17:01:19 +00:00
bagyenda 55f9ee3766 *** empty log message *** 2008-06-24 16:08:55 +00:00
bagyenda 82d5a85805 *** empty log message *** 2008-06-24 10:50:23 +00:00
bagyenda 371438118b minor changes to cdr logging 2008-06-24 10:01:03 +00:00
bagyenda 23df285f45 adding qcelp mime type mapping 2008-06-19 17:12:02 +00:00
bagyenda dc10393106 changed min mm7 version 2008-06-03 15:28:34 +00:00
bagyenda 4658ce6b10 misc fixes 2008-05-30 13:56:14 +00:00
bagyenda 6eb3e6629c minor mm4 message fixups 2008-05-14 11:39:03 +00:00
bagyenda 6b472bf22b MM4 number normalisation 2008-05-13 10:53:01 +00:00
bagyenda 4eb54ddffa minor bug fixes: mm4 interface message parsing 2008-05-12 20:13:52 +00:00
bagyenda 483c6d658d minor bug fix: unbase64 2008-05-12 18:12:41 +00:00
bagyenda 7264d4f88d minor bug fix: unbase64 2008-05-12 18:11:16 +00:00
bagyenda 9bf11ffd57 *** empty log message *** 2008-05-05 21:22:44 +00:00
bagyenda d9be1198a5 added normalisation of message internal addresses on mm1 2008-05-05 21:09:44 +00:00
bagyenda fbbec2877b *** empty log message *** 2008-05-05 20:25:13 +00:00
bagyenda e1c18c07a4 Added strip-prefixes config param 2008-05-05 19:29:49 +00:00
bagyenda b31790def4 *** empty log message *** 2008-04-30 18:41:16 +00:00
bagyenda 0fb93b3c90 *** empty log message *** 2008-04-29 19:00:50 +00:00
bagyenda f69e38cd85 *** empty log message *** 2008-04-28 05:26:20 +00:00
bagyenda 72ea4e45f0 *** empty log message *** 2008-04-20 08:11:40 +00:00
bagyenda 232351d5ce various memory leak fixes 2008-04-18 13:54:08 +00:00
bagyenda cf2f4e7d8e various memory leak fixes 2008-04-18 13:45:39 +00:00
bagyenda e78739a3a1 various memory leak fixes 2008-04-18 12:32:31 +00:00
bagyenda ee5c86878d minor change to mm7/soap parameters 2008-04-11 07:01:35 +00:00
bagyenda 2179aa0b3c minor mms-service config fix 2008-03-26 11:30:54 +00:00
bagyenda be411e731b fixed: mms_validate_address looks for null 2008-03-16 16:45:26 +00:00
bagyenda 59e844d16c minor fix for throughput 2008-02-17 14:33:00 +00:00
bagyenda 3ebb5316c1 throughput fix 2008-02-14 14:46:21 +00:00
bagyenda cd52c8f1ee minor logging addition 2008-01-03 16:38:29 +00:00
bagyenda 9748e88621 minor fix to message routing 2008-01-01 06:45:16 +00:00
bagyenda fcad678f3c minor fix to configure.ac for cygwin 2007-12-31 04:12:07 +00:00
bagyenda 5d01704548 minor bug fix in mmsbox message routing 2007-12-26 07:36:54 +00:00
bagyenda a49d02b4e8 fixes to allow SunOS compilation 2007-12-21 10:14:08 +00:00
bagyenda 15888c94ca minor fix to mmsbox 2007-12-19 06:48:37 +00:00
bagyenda b36fe80262 minor fix to mmsbox 2007-12-19 06:18:33 +00:00
bagyenda 421c6f6856 *** empty log message *** 2007-12-18 07:22:21 +00:00
bagyenda d06fa69106 *** empty log message *** 2007-12-18 07:12:12 +00:00
bagyenda 6cad727c78 new configs 2007-12-15 10:07:21 +00:00
bagyenda d0714028b5 new configs 2007-12-15 08:40:22 +00:00
bagyenda cade2f51a9 minor fix in mms_mmbox.c: added include file 2007-12-05 16:58:06 +00:00
bagyenda 2bee4e49db bug fix in mime lib 2007-11-27 06:31:21 +00:00
bagyenda c58cfafec5 added reroute-add-sender flag to mmsbox config 2007-11-07 07:53:29 +00:00
bagyenda a69feb2eb9 fix for mmsbox multipart sendmms handling 2007-10-25 06:32:03 +00:00
bagyenda d05d46cc9f fixed documentation - minor 2007-10-16 12:52:06 +00:00
bagyenda 18dcdf7052 minor fix to mm7/soap composition 2007-09-26 06:06:33 +00:00
bagyenda 650c1c8318 minor fix for minimum mm7 version 2007-09-25 18:03:53 +00:00
bagyenda fc552034da mm7 fix -- conditionally remove prefix 2007-09-25 06:03:48 +00:00
bagyenda 7137d5bd5d minor fix pgsql 2007-09-21 07:46:03 +00:00
bagyenda 0cb610d5bd minor fix to mms_fixup_address 2007-09-20 16:57:44 +00:00
bagyenda 15f61ba8d5 minor fix to mms_fixup_address 2007-09-20 16:51:22 +00:00
bagyenda a87514cc02 minor fix to mmsbox 2007-09-20 15:23:27 +00:00
bagyenda 281b7c220b minor addition to mmsbox_resolve interface 2007-09-20 13:55:36 +00:00
bagyenda c845a51c10 misc fix to load_module call in mmsbox_cfg.c 2007-09-20 12:32:31 +00:00
bagyenda e76995ab27 pluggable mmsc types 2007-09-19 13:06:26 +00:00
bagyenda 970badf660 added mmsbox routing resolver: mmsbox_resolve.h 2007-09-17 13:07:30 +00:00
bagyenda 195b7888b9 minor fix to mms2email: fix for from address 2007-09-16 07:20:15 +00:00
bagyenda 30ed2d83f6 http-interface-name added 2007-09-14 04:14:19 +00:00
bagyenda d2c8efd1aa minor fix to pgsql-queues 2007-09-12 02:56:55 +00:00
bagyenda 5a5e6603ef minor fix to configure 2007-09-11 09:56:24 +00:00
bagyenda fcdd5c442b minor bug fix re address fixup 2007-09-10 12:04:49 +00:00
bagyenda 3059138928 misc. fixes for extras 2007-09-10 08:36:39 +00:00
bagyenda e1f24fdeee minor fixes for linux and dso loading 2007-09-09 07:57:58 +00:00
bagyenda 4308cb1446 more fixes for extras 2007-09-06 07:16:04 +00:00
bagyenda 9640be11c8 misc fixes for extras 2007-09-06 06:59:10 +00:00
bagyenda e48246fa63 minor fixes to extras 2007-09-06 00:52:47 +00:00
bagyenda 45c6276727 minor fixes to extras 2007-09-06 00:46:41 +00:00
bagyenda 61d76e1a14 added extras/ directory 2007-09-05 21:37:04 +00:00
bagyenda 4208985069 misc fix: strip non-essential headers from message part of mm7 packet 2007-08-30 16:35:45 +00:00
bagyenda 4ebf96552e misc cleanups to mmsc 2007-08-29 13:33:11 +00:00
bagyenda 3789d199a7 minor fix for SIGHUP handling 2007-08-29 10:14:45 +00:00
bagyenda 89a6e5007d added matching of .3g2 file extension 2007-08-27 15:31:23 +00:00
bagyenda aea228ecc2 added reroute reroute-mmsc-id to config 2007-08-27 10:16:26 +00:00
bagyenda b3f9f30919 minor fix with mmsc message routing 2007-08-25 04:49:44 +00:00
bagyenda 21f1188c4e minor fixes, renamings 2007-08-22 11:41:57 +00:00
bagyenda 382c48bb69 typo in changelog 2007-08-21 04:17:55 +00:00
bagyenda 4c5a8389c0 generalised queue handling 2007-08-20 11:49:30 +00:00
bagyenda 8438ca779d small fix for read reports 2007-08-17 19:04:32 +00:00
bagyenda 9cbf72f5f1 added send-dlr-on-fetch config param 2007-08-09 09:32:49 +00:00
bagyenda 8124439d44 added params to prov notify script 2007-08-08 05:38:20 +00:00
bagyenda d7d97c695d misc. fix - auth in mmsbox 2007-08-07 08:20:24 +00:00
bagyenda 96811a10b7 misc. fixes: DLR, UAProf on mmsbox side 2007-08-06 11:57:15 +00:00
bagyenda 67cdf0f387 added mms-direction cgi param to send-mms interface 2007-08-03 12:18:45 +00:00
bagyenda d973e24c53 VAS GW fixes for DLR 2007-07-27 17:03:15 +00:00
bagyenda 99318916ea VAS GW fixes for DLR 2007-07-27 16:39:19 +00:00
bagyenda f7da8933d8 minor fix in VAS GW -- better file extension to content ID 2007-07-26 18:42:19 +00:00
bagyenda b3da1b4ead improved mmsbox logging on error 2007-07-25 05:46:29 +00:00
bagyenda 27d9e7f6ec Minor bug fix in mmssend.c -- using variable 'settings' before it is initialised 2007-07-23 11:21:07 +00:00
bagyenda 8ef3978cab adding allow adaptations flag 2007-07-23 04:27:03 +00:00
bagyenda 7c31b97523 minor fix 2007-07-20 12:33:36 +00:00
bagyenda 26b0508487 minor fixes re filtering 2007-07-19 19:58:27 +00:00
bagyenda 3d59903562 minor fixes re filtering 2007-07-19 19:45:24 +00:00
bagyenda cc3a502516 minor fixes re filtering 2007-07-19 18:15:17 +00:00
bagyenda e6a0b2d72c additional minor fixes - message filtering 2007-07-17 12:43:30 +00:00
bagyenda 5e84205190 various fixes: mt mms filter, added sendmms cgi param 2007-07-17 08:26:38 +00:00
bagyenda eef103ae02 misc. changes 2007-07-09 16:43:42 +00:00
bagyenda 7cb159ae13 minor fix: allow file:// in URLs 2007-07-05 06:27:08 +00:00
bagyenda 3a83c61050 bug fix 2007-06-26 13:15:20 +00:00
bagyenda 83312fbf45 minor fix: bearerbox mm7 parsing 2007-06-25 12:48:14 +00:00
bagyenda f0a3e8a350 minor fixes to mm7 error reporting 2007-06-25 10:33:47 +00:00
bagyenda 7eec5761a1 minor improvements to mm7 sender in mmsbox 2007-06-22 10:49:38 +00:00
bagyenda 098ffba5cf minor fix in mmsbox config reader: erroneous catch-all warning 2007-06-22 08:43:42 +00:00
bagyenda 824581609c minor fix in mmsbox: handling of missing keyword 2007-06-21 13:29:49 +00:00
bagyenda eef6e9b967 better mm7 namespace handling 2007-06-21 12:56:29 +00:00
bagyenda 824b57f35f cleanup of mmsc conf reader 2007-06-20 06:47:05 +00:00
bagyenda 71c19b6b30 Minor bug fix in mmsbox: empty text body causes crash 2007-06-14 09:10:11 +00:00
bagyenda 26adfda0db set dlr from address to to address 2007-06-12 11:43:30 +00:00
bagyenda 81adc79a47 Minor fix: remove quotes from incoming MM4 numbers 2007-05-09 11:14:21 +00:00
bagyenda 64722b0299 Bug fixes on MIME conversion 2007-05-08 08:24:19 +00:00
bagyenda a2c99daca6 Minor fixes to dlr handling in mmsbox 2007-05-05 07:46:03 +00:00
bagyenda 7430986871 Minor bug fix for dlr in mmsbox 2007-05-02 07:30:16 +00:00
bagyenda 5271c532c8 Minor fix to mms_util.c for SSL 2007-04-24 13:25:13 +00:00
bagyenda e84a8c67ab minor fix to configure.ac 2007-04-24 13:07:27 +00:00
bagyenda 561dafdca7 Minor fixes to configure script 2007-04-23 13:37:44 +00:00
bagyenda b5aa2c8e63 *** empty log message *** 2007-04-20 17:01:24 +00:00
bagyenda e3aabcccfe minor fix to handling of dlr on mm4 interface 2007-04-18 12:08:24 +00:00
bagyenda c3a4ddcf67 *** empty log message *** 2007-04-17 13:30:59 +00:00
bagyenda e59b517fb8 Improved handling of MM4 ACK messages 2007-04-13 10:50:59 +00:00
bagyenda 65c185e3eb Improved MM7/SOAP schema handling 2007-04-12 08:40:24 +00:00
bagyenda c49a4bbe57 *** empty log message *** 2007-04-11 15:19:20 +00:00
bagyenda 27547cb49b *** empty log message *** 2007-04-11 13:03:01 +00:00
bagyenda b1df15b16d *** empty log message *** 2007-04-10 17:45:44 +00:00
bagyenda 3c990ad7cf Added Digest HTTP authentication 2007-04-10 17:09:05 +00:00
bagyenda a22898306a Allowed setting of MM7/SOAP interface version 2007-04-10 09:56:46 +00:00
bagyenda 89c9b8eddb Changed param name for mmsfromemail proxy 2007-04-02 12:55:24 +00:00
bagyenda d6292f03d9 Added group-id to VAS GW config 2007-04-02 05:29:00 +00:00
bagyenda a8c3ddccf7 Small fixup to remove < > from message id 2007-03-28 12:13:44 +00:00
bagyenda eb1a689a8a Misc. error format cleanups 2007-03-27 10:23:47 +00:00
bagyenda 5af2e53f30 *** empty log message *** 2007-03-21 15:41:31 +00:00
bagyenda 825102fc0a MM4 - fixup of addresses in headers 2007-03-20 17:29:58 +00:00
bagyenda 7a0d166d21 MM4 changes 2007-03-20 16:43:44 +00:00
bagyenda 2255fe303b fix panic for missing queue file entry 2007-03-09 04:53:59 +00:00
bagyenda 222cf4487a - Misc. fixes for MM4 inter-operability
- Allow adapatation fixes
2007-03-06 07:43:08 +00:00
bagyenda fd2d1fbc79 allow-adaptations added as cgi var to sendmms interface 2007-01-31 04:44:09 +00:00
bagyenda 869a6d3eed MM4 incoming message type fix 2007-01-30 17:06:29 +00:00
bagyenda bc7049dbd6 *** empty log message *** 2007-01-24 17:47:53 +00:00
bagyenda a21f21d5d6 *** empty log message *** 2007-01-22 10:40:16 +00:00
bagyenda de6ded80a9 Minor change of order of MM7 tags to please Comverse! 2007-01-03 05:53:03 +00:00
bagyenda 14e44ea421 Removing @ from transactionID 2006-12-28 05:48:29 +00:00
bagyenda 1b9c2dc2ad Minor relaxation of Content-ID comparison in MM7 parser 2006-12-20 10:08:54 +00:00
bagyenda c057093761 Minor syntax fix 2006-12-18 14:28:31 +00:00
bagyenda 7ad9569dce minor credits fix 2006-12-14 18:29:22 +00:00
bagyenda 6ca83011c9 Minor fix to MM7/SOAP parser to lookout for missing "cid:" in Content tag 2006-11-29 09:22:49 +00:00
bagyenda 1075745c33 Minor fix for VASP Error element on VAS GW side 2006-11-28 12:00:20 +00:00
bagyenda 99ad888a54 *** empty log message *** 2006-11-28 10:43:04 +00:00
bagyenda 5eec86d69e Base build on Kannel CVS fully 2006-11-27 15:08:02 +00:00
bagyenda 65a82a7175 Removal of code work-arounds for Kannel MIME bugs (now fixed) 2006-11-25 11:53:40 +00:00
bagyenda 00c7e34515 fix: correct quoting of content-type parameters in mime message 2006-11-18 06:20:05 +00:00
bagyenda 8ece099c13 Fix: reply charging attribute in mm7 module 2006-11-11 05:49:19 +00:00
bagyenda f34daaa335 Improved source organisation, version string & change log 2006-11-07 16:52:23 +00:00
bagyenda 6e363677a0 *** empty log message *** 2006-11-07 15:29:55 +00:00
bagyenda c6b75666ab - Adding version file 2006-11-03 09:39:07 +00:00
bagyenda 0b22c99c69 mm7: removal of some-url dummy in SOAP header 2006-10-30 13:02:42 +00:00
bagyenda 8e6ecf8a5c Minor clean-up: fold *_shell MMSC external modules into main code 2006-10-27 14:27:30 +00:00
bagyenda ea98a5da35 Quotes around content subtype. Logica MMC parsing badly. Sigh! 2006-10-19 11:24:09 +00:00
bagyenda 89fbf157c8 updates to MM7/SOAP: Add mm7 namespace to all tags 2006-10-19 07:30:21 +00:00
bagyenda 63b90a7845 Remove quotes from text/xml content type (to please Logica MMC!) 2006-10-17 07:53:16 +00:00
bagyenda f2d45f4164 fix: mm7/soap error code 4004 erroneously reported as 4001 2006-10-16 12:38:44 +00:00
bagyenda c3feca09ff Mbuni updated to Kannel 1.4.1 -- initial stab 2006-10-12 15:21:46 +00:00
bagyenda 26cf73882b MM7: Minor fix - remove MessageID field from all response types but SubmitRsp 2006-09-14 12:47:37 +00:00
bagyenda caa71ca8ca MM7/SOAP fix: correctly map MessageID field to Message-ID on MM1 side
configure.ac: add -Wall -O4 flags for gcc (Linux/Mac)
2006-09-06 11:49:23 +00:00
bagyenda c73765c7a9 MMSC fix: Do not copy DLRs to VASP who receives copies of local messages 2006-09-02 06:26:13 +00:00
bagyenda 64c2ffe8ed MM7/EAIF: Force the message-id message header to whatever sent by MMSC 2006-09-01 14:35:04 +00:00
bagyenda 356905c4b6 Minor fix: MM7 DeliverRsp should not have message ID parameter 2006-08-28 15:31:44 +00:00
bagyenda 491a6173a8 - Added ServiceCode parameter to both sendmms cgi vars, and also to mms-service 2006-08-11 10:05:46 +00:00
bagyenda 3e010fccd4 - Slight bug fixes - syntax issues 2006-08-07 20:58:13 +00:00
bagyenda e652be1d62 Added message-ID parameter to prov-notify-script 2006-07-27 10:37:10 +00:00
bagyenda 96708be15c configure.ac fix for freebsd 2006-07-17 10:40:17 +00:00
bagyenda c42ddb8aa5 - Improved handling of retrieve-conf message received on send interfaces 2006-07-17 06:52:10 +00:00
bagyenda bbeb0c91e3 - Slight changes in default log file paths (to separate mmsbox log from mmsc log) 2006-07-17 05:43:33 +00:00
bagyenda 88de7ef670 - Add MIME-Version header to email messages outgoing
- check for short code in globalsender before checking if local recipient
2006-07-14 13:11:08 +00:00
bagyenda 79b19bac64 - Minor fix for ? char in sendsms url
- Minor fix for default queue run interval (was 0.1, now 5 secs)
2006-07-13 12:01:24 +00:00
bagyenda 7fd8045dd4 - Allow Send-MMS port to support HTTP POST from HTML-style forms, including enctype multipart/form-data 2006-06-20 13:32:54 +00:00
bagyenda 4d625f2375 Add: default message expiration for mmsbox message 2006-06-02 12:42:42 +00:00
bagyenda e656ec81a7 Initial import - sample mmsbox config 2006-05-30 06:53:33 +00:00
bagyenda 1e21db8592 further improvements to HTTP POST data sent by MMSBox to a service: Always add filename parameter to each variable. 2006-05-30 06:42:05 +00:00
bagyenda b2f178153c MMSbox: Improved sending of data to service - try to send all parts to look like files 2006-05-29 14:00:36 +00:00
bagyenda d48ac96cd7 Max send attempts does not expire message, only expiry time does 2006-05-29 08:49:00 +00:00
bagyenda f8c0ef9a7b fix: reduce length of trans-id and msgid 2006-05-29 06:30:39 +00:00
bagyenda 9e59d79de5 fix: allow mmsbox incoming mmsc conn without auth 2006-05-23 12:38:24 +00:00
bagyenda 1bd576132d Fixed: double-free in mmsglobalsender 2006-05-22 10:06:22 +00:00
bagyenda cfa26d3c75 - Bug fix, failure when x-wap-profile header missing 2006-05-15 17:07:06 +00:00
bagyenda feeb8ab13c - Fix for send local MMS to VASP 2006-05-15 06:40:07 +00:00
bagyenda 0ccc7938d0 - CVS repository change noted in documentation 2006-05-13 09:44:33 +00:00
bagyenda fcebfd2ea1 - Rationalised MM7 config for MMSC
- Moved functions out of mmlib that do not belong there
- Improved logging in mmsproxy
- detokenize module improvements (send full url when no token)
- Add default mms-to-email subject config
- Misc. changes
2006-05-13 09:37:25 +00:00
bagyenda 3e6f552a5f further improvements to detokenizer module usage - send request IP only to module if token missing 2006-05-08 13:25:02 +00:00
bagyenda 11574bb88e - Further fixes to detokenizer module usage
- Code movement (from mmlib to more specific mmsc where it is used)
2006-05-08 11:19:38 +00:00
bagyenda 0f38817669 improved detokenizer_shell module: Added default token as "x" 2006-05-08 06:45:20 +00:00
bagyenda 50fd9b03aa improved detokenizer_shell module: Script now receives 2nd argument as request-ip 2006-05-08 06:42:35 +00:00
bagyenda bc4ef69c40 Minor fix, better detection of IPv6 addresses. 2006-05-06 14:29:14 +00:00
bagyenda 142c9f8342 Improved logging of NotifyResp messages om MM1 interface 2006-05-06 14:08:12 +00:00
bagyenda ea8bce278a - Added config param to restrict response from mms-service (VAS GW)
- Added param for headers that should be sent to MMC are received from mms-service response (VAS GW)
- Fixed bug where omit-empty param for VAS GW was actually ignored
2006-05-03 13:52:40 +00:00
bagyenda ca05acedc9 Minor bug fix (double free) in mmsbox 2006-05-02 13:02:15 +00:00
bagyenda e92035851f Minor type cast -- compiler warning on 64bit machines 2006-04-19 14:48:43 +00:00
bagyenda aa1708af9a - Minor improvements to logging of failed MM7 connections
- Reduced default queue run interval
2006-04-18 04:25:55 +00:00
bagyenda ddcd63dfa2 Misc patches - message-ID format, resolver module fallbacks - thanks to Dziugas Baltrunas 2006-04-12 07:14:45 +00:00
bagyenda ef53251db3 - More mmsbox fixes to please Ericsson MMC
- Added 'vasid' send-mms URL parameter
2006-04-12 06:52:54 +00:00
bagyenda dfc9f52994 Minor addition for MM7/SOAP -- add start element MIME type 2006-04-06 07:55:45 +00:00
menulis 53c8b46e57 - Created contrib directory for various plug-ins and/or tools to use with mbuni
- Added sample mbuni-init.d script
2006-03-28 10:05:46 +00:00
bagyenda 83d1c98991 Further cleanups for MM7/Soap and mmsbox - better error reporting, better xml content 2006-03-28 08:37:25 +00:00
bagyenda dde519afc2 minor fix to shell-based resolver 2006-03-27 13:00:48 +00:00
bagyenda 2a25a4cd3e - Changes to mm7/soap module to please java packages (Resin -- SOAP-ENV header prefered)
- Removal of outdated config params
2006-03-24 16:26:05 +00:00
bagyenda fa8e2b7f02 Minor fix to mmsbox - send_eaif missing X-Mms-Transaction-ID header 2006-03-21 10:46:27 +00:00
bagyenda 6972fad0fe - More graceful crash when config groups mbuni & core missing
- Documentation fixes
2006-03-10 05:38:29 +00:00
89 changed files with 20307 additions and 6273 deletions

View File

@ -4,6 +4,7 @@
*.patch
*.lo
*.o
.gdb_history
mpeg2dec-*.tar.gz
Makefile
Makefile.in
@ -16,3 +17,9 @@ config.cache
libtool
config.status
gmon.out
autom4te.cache
mbuni-config.h
mbuni-config.h.in
.cproject
.project
stamp-h1

340
mbuni/COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
Software Foundation, Inc.
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
@ -10,7 +10,10 @@ unlimited permission to copy, distribute and modify it.
Basic Installation
==================
These are generic installation instructions.
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
@ -23,9 +26,9 @@ debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. (Caching is
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.)
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
@ -35,20 +38,17 @@ some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./bootstrap' followed by `./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
`./configure' to configure the package for your system.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
@ -78,7 +78,7 @@ details on some of the pertinent environment variables.
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
@ -87,31 +87,29 @@ Compiling For Multiple Architectures
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not support the `VPATH'
variable, you have to compile the package for one architecture at a
time in the source code directory. After you have installed the
package for one architecture, use `make distclean' before reconfiguring
for another architecture.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PREFIX'.
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PREFIX', the package will
use PREFIX as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
@ -159,7 +157,7 @@ where SYSTEM can have one of these forms:
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the `--target=TYPE' option to select the type of system they will
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
@ -189,9 +187,14 @@ them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
will cause the specified gcc to be used as the C compiler (unless it is
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================

View File

@ -1,3 +1,3 @@
SUBDIRS = autotools doc misc-patches mmlib mmsc mmsbox
SUBDIRS = autotools doc mmlib mmsc mmsbox extras
EXTRA_DIST = GnuLICENSE KannelLICENSE bootstrap Notes todo
EXTRA_DIST = VERSION GnuLICENSE KannelLICENSE bootstrap Notes

5
mbuni/VERSION Normal file
View File

@ -0,0 +1,5 @@
cvs
$Date$
This file contains the version number of Mbuni, which must be on the first line. Second line is the date

View File

@ -4,7 +4,11 @@ set -e
# Check for automake
amvers="no"
if automake-1.9 --version >/dev/null 2>&1; then
if automake-1.11 --version >/dev/null 2>&1; then
amvers="-1.11"
elif automake-1.10 --version >/dev/null 2>&1; then
amvers="-1.10"
elif automake-1.9 --version >/dev/null 2>&1; then
amvers="-1.9"
elif automake-1.8 --version >/dev/null 2>&1; then
amvers="-1.8"

View File

@ -1,35 +1,51 @@
dnl Mbuni - Open Source MMS Gateway
dnl
dnl Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
dnl Copyright (C) 2003 - 2011, Digital Solutions Ltd. - http://www.dsmagic.com
dnl
dnl Paul Bagyenda <bagyenda@dsmagic.com>
dnl
dnl This program is free software, distributed under the terms of
dnl the GNU General Public License, with a few exceptions granted (see LICENSE)
dnl
AC_PREREQ(2.59)
AC_PREREQ(2.61)
AC_INIT([mbuni],[cvs],[devel@mbuni.org])
dnl Set version
AC_MSG_CHECKING([Retrieving Mbuni version])
M_VERSION=`head -n 1 VERSION`
if test "x$M_VERSION" = "xcvs"; then
CVS_DATE=`head -1 ChangeLog | cut -f 1 -d ' ' | sed 's/-//g'`
M_VERSION="$M_VERSION-$CVS_DATE"
fi
AC_MSG_RESULT([$M_VERSION])
AC_CONFIG_SRCDIR([mmlib/mms_util.c])
AC_CONFIG_AUX_DIR(autotools)
AM_INIT_AUTOMAKE([mbuni],[1.0.0-cvs])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([mbuni],[$M_VERSION])
AC_CONFIG_HEADERS([mbuni-config.h])
AM_MAINTAINER_MODE
AC_CANONICAL_HOST
dnl Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL
AC_PROG_RANLIB
dnl add mmlib to the include path
INCLUDES='-I$(top_srcdir)/mmlib -I$(top_builddir)/mmlib'
INCLUDES='-I$(top_srcdir)/mmlib -I$(top_builddir)/mmsc -I$(top_srcdir)/mmsc -I$(top_builddir)/mmsbox -I$(top_srcdir)/mmlib -I$(top_builddir)/mmsbox'
AC_SUBST([INCLUDES])
dnl Checks for libraries.
AC_CHECK_LIB([dl], [dlsym])
dnl AC_CHECK_LIB([iconv], [libiconv], [LIBS="$LIBS -liconv"])
AC_CHECK_LIB([pthread], [pthread_create])
dnl AC_CHECK_LIB([xml2], [xmlStrcasecmp], [],
dnl AC_MSG_ERROR([LibXML2 is required]))
AC_CHECK_FUNCS([backtrace])
dnl Checks for header files.
AC_HEADER_DIRENT
@ -53,23 +69,31 @@ AC_CHECK_FUNCS([floor localtime_r memset sqrt strerror strrchr strtol])
dnl Change a few things (a la kannel config)
EXE_EXT=""
LIB_EXT="a"
case "$host" in
*-sun-solaris*)
CFLAGS="$CFLAGS -DSunOS=1"
*-sun-solaris* | *SunOS* | *-pc-solaris*)
CFLAGS="$CFLAGS -DSunOS=1 -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT"
;;
*-cygwin*)
EXE_EXT=".exe"
;;
*apple-darwin*)
CFLAGS="$CFLAGS -DDARWIN=1"
CFLAGS="$CFLAGS -DDARWIN=1 -O4 -Wall -D_REENTRANT=1"
LIB_EXT="dylib"
allow_undefined_flag='-flat_namespace -undefined suppress'
;;
*-linux-*)
CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE"
*-linux*)
CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -O4 -Wall -D_REENTRANT=1"
LDFLAGS="$LDFLAGS -rdynamic"
;;
*-*-openbsd* | *-*-freebsd*)
*-*-openbsd*)
CFLAGS="$CFLAGS -pthread"
AC_CHECK_LIB(c_r, pthread_exit, [LIBS="$LIBS -lc_r -lkse"; pthread="yes"])
AC_CHECK_LIB(c_r, pthread_exit, [LIBS="$LIBS -lc_r -lpthread"; pthread="yes"])
;;
*-*-freebsd*)
LDFLAGS="$LDFLAGS -export-dynamic"
CFLAGS="$CFLAGS -DFREEBSD=1 -pthread"
AC_CHECK_LIB(c_r, pthread_exit, [LIBS="$LIBS -lc_r -lpthread"; pthread="yes"])
;;
esac
@ -81,6 +105,15 @@ AC_ARG_WITH(libs,
[ --with-libs=FLAGS use FLAGS for extra libraries],
LIBS="$LIBS $withval")
dnl Check for large file handling
AC_SYS_LARGEFILE(CFLAGS)
if test "${ac_cv_sys_file_offset_bits}" != no ; then
CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=${ac_cv_sys_file_offset_bits}"
fi
if test "${ac_cv_sys_large_files}" != "no" ; then
CFLAGS="$CFLAGS -D_LARGE_FILES=${ac_cv_sys_large_files}"
fi
dnl implement SSL stuff.
dnl Implement the --with-ssl option.
@ -116,7 +149,7 @@ if test "$ssl" = "yes" ; then
dnl test only if --with-ssl has not been used
if test "x$ssllib" = "x" && test "x$sslinc" = "x"; then
for loc in /usr/lib /usr/local/ssl/lib /usr/local/openssl/lib; do
if test -f "$loc/libssl.a"; then
if test -f "$loc/libssl.$LIB_EXT"; then
ssllib="$loc"
fi
done
@ -225,8 +258,9 @@ else
AC_MSG_RESULT([$gw_version])
AC_MSG_CHECKING([Kannel libs])
if ! $GW_CONFIG --libs &>/dev/null ; then
LDFLAGS="$LDFLAGS `$GW_CONFIG --libs`"
gw_libdir=`$GW_CONFIG --libs`
LDFLAGS="$LDFLAGS $gw_libdir"
LIBS="$LIBS $gw_libdir"
AC_MSG_RESULT([$gw_libdir])
fi
AC_MSG_CHECKING([Kannel includes])
@ -240,18 +274,105 @@ fi
AC_CHECK_LIB([gwlib], [cfg_create], [], AC_MSG_ERROR([Kannel gwlib is required!]))
AC_CHECK_LIB([wap], [wsp_headers_pack], [], AC_MSG_ERROR([Kannel WAP lib is required!]))
dnl Implement the --with-pgsql-dir option.
pgsqlloc="/usr/local/pgsql"
AC_ARG_WITH(pgsql-dir,
[ --with-pgsql-dir=DIR where to look for PostgreSQL libs and header files
DIR points to the installation [/usr/local/pgsql] ],
[
pgsqlloc=""
if test -d "$withval" ; then
pgsqlloc="$withval"
fi
])
AC_PATH_PROG(PGSQL_CONFIG, pg_config, no, [$pgsqlloc/bin:$pgsqlloc:/usr/lib/postgresql/bin:${PATH}])
dnl check for PgSQL >= 7.2 style pg_config information
if test "$PGSQL_CONFIG" = "no"; then
found=""
for loc in $pgsqlloc /usr /usr/local ; do
if test "x$found" = "x" ; then
AC_MSG_CHECKING([for PostgresSQL include files in])
AC_MSG_RESULT($loc)
AC_CHECK_FILE("$loc/include/postgresql/libpq-fe.h",
[CFLAGS="$CFLAGS -I$loc/include/postgresql"; LIBS="-L$loc/lib/postgresql -lpq $LIBS"]; found=1,
[AC_CHECK_FILE("$loc/include/pgsql/libpq-fe.h",
[CFLAGS="$CFLAGS -I$loc/include/pgsql"; LIBS=" -L$loc/lib/pgsql $LIBS -lpq"]; found=1,
[AC_CHECK_FILE("$loc/pgsql/include/libpq-fe.h",
[CFLAGS="-I$loc/pgsql/include $CFLAGS"; LIBS="-L$loc/pgsql/lib $LIBS -lpq"]; found=1,
)]
)]
)
fi
done
else
dnl pg_config found
AC_MSG_CHECKING([PostgreSQL version])
pgsql_version=`$PGSQL_CONFIG --version`
AC_MSG_RESULT([$pgsql_version])
AC_MSG_CHECKING([PostgreSQL libs])
if $PGSQL_CONFIG --libdir &>/dev/null ; then
LIBS="-L`$PGSQL_CONFIG --libdir` $LIBS -lpq "
pg_libdir="`$PGSQL_CONFIG --libdir`"
AC_MSG_RESULT([$pg_libdir])
fi
AC_MSG_CHECKING([PostgreSQL includes])
if $PGSQL_CONFIG --includedir &>/dev/null ; then
CFLAGS="-I`$PGSQL_CONFIG --includedir` $CFLAGS"
pg_incdir=`$PGSQL_CONFIG --includedir`
AC_MSG_RESULT([$pg_incdir])
fi
fi
# set HAVE_LIBpq if we have libpq
AC_CHECK_LIB([pq], [PQexec], [has_pgsql=true])
AM_CONDITIONAL([BUILD_PGSQLQ], [test x$has_pgsql = xtrue])
# Look for curl lib
AC_PATH_PROG(CURL_CONFIG, curl-config, no, [${PATH}])
if test "$CURL_CONFIG" != "no"; then
dnl curl-config found
AC_MSG_CHECKING([curl lib version])
curl_version=`$CURL_CONFIG --version`
AC_MSG_RESULT([$curl_version])
AC_MSG_CHECKING([curl libs])
if $CURL_CONFIG --libs &>/dev/null ; then
curl_libs=`$CURL_CONFIG --libs`
AC_MSG_RESULT([$curl_libs])
LIBS="$LIBS $curl_libs"
fi
AC_MSG_CHECKING([curl includes])
if $CURL_CONFIG --cflags &>/dev/null ; then
curl_cflags=`$CURL_CONFIG --cflags`
CFLAGS="$curl_cflags $CFLAGS"
AC_MSG_RESULT([$curl_cflags])
fi
fi
AC_CHECK_LIB([curl], [curl_global_init], [
CFLAGS="-DHAVE_LIBCURL=1 $CFLAGS";
has_libcurl=true
])
AM_CONDITIONAL([BUILD_MMSBOXMM1], [test x$has_libcurl = xtrue])
dnl Add mbuni version to Cflags
# CFLAGS="$CFLAGS -DMBUNI_VERSION=\"$M_VERSION\""
AC_DEFINE_UNQUOTED(MBUNI_VERSION, "$M_VERSION", "Mbuni Version")
dnl May be we need to check for media conversion tools (imagemagick, etc)?
AC_CONFIG_FILES([Makefile autotools/Makefile doc/Makefile doc/examples/Makefile doc/images/Makefile misc-patches/Makefile mmlib/Makefile mmsc/Makefile mmsbox/Makefile])
AC_CONFIG_FILES([Makefile autotools/Makefile doc/Makefile doc/examples/Makefile doc/images/Makefile mmlib/Makefile mmsc/Makefile mmsbox/Makefile extras/Makefile extras/pgsql-queue/Makefile extras/mmsbox-mm1/Makefile])
AC_OUTPUT
cat<<X
License:
Mbuni - Open Source MMS Gateway - http://www.mbuni.org/
Mbuni (version $M_VERSION) - Open Source MMS Gateway - http://www.mbuni.org/
Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
Copyright (C) 2003 - 2011, Digital Solutions Ltd. - http://www.dsmagic.com
This program is free software, distributed under the terms of
the GNU General Public License, with a few exceptions granted (see LICENSE)

53
mbuni/contrib/mbuni-init.d Executable file
View File

@ -0,0 +1,53 @@
#!/bin/sh
MBUNI=/usr/local/mbuni
BINDIR=$MBUNI/bin
PIDFILES=$MBUNI/run
CONF=$MBUNI/etc/mmsc.conf
MP=mmsproxy
MR=mmsrelay
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MBUNI/lib/mbuni
export LD_LIBRARY_PATH
test -x $BINDIR/$MP && test -x $BINDIR/$MR || exit 0
case "$1" in
start)
echo -n "Starting MMSC: mmsproxy"
$BINDIR/$MP --daemonize --parachute --pid-file $PIDFILES/$MP.pid -- $CONF
sleep 1
echo -n " mmsrelay"
$BINDIR/$MR --daemonize --parachute --pid-file $PIDFILES/$MR.pid -- $CONF
echo "."
;;
stop)
echo -n "Stopping MMSC: mmsrelay"
kill `cat $PIDFILES/$MR.pid`
sleep 1
echo -n " mmsproxy"
kill `cat $PIDFILES/$MP.pid`
echo "."
;;
reload)
# We don't have support for this yet.
exit 1
;;
restart|force-reload)
$0 stop
sleep 1
$0 start
;;
*)
echo "Usage: $0 {start|stop|reload|restart|force-reload}"
exit 1
esac
exit 0

View File

@ -1 +1,2 @@
SUBDIRS = examples images
EXTRA_DIST = userguide.shtml

View File

@ -1 +1 @@
EXTRA_DIST = mmsc.conf
EXTRA_DIST = mmsc.conf mmsbox.conf

View File

@ -0,0 +1,59 @@
group = core
log-file = /var/log/mmsbox.log
access-log = /var/log/mmsbox-access.log
log-level = 0
group = mbuni
storage-directory = /var/spool/mbuni
max-send-threads = 5
maximum-send-attempts = 50
default-message-expiry = 360000
queue-run-interval = 5
send-attempt-back-off = 300
sendmms-port = 10001
group = mmsc
id = local
mmsc-url = http://mbuni:test@localhost:1982/soap
incoming-username = user
incoming-password = pass
incoming-port = 12345
type = soap
# Sample conf for MMSBox using a modem (MM1)
group = mmsc
id = modem
type = mm1
mm1-sms-on-command = lynx -dump 'http://localhost:13000/start-smsc?password=bar&smsc=nokia-modem'
mm1-sms-off-command = lynx -dump 'http://localhost:13000/stop-smsc?password=bar&smsc=nokia-modem'
mm1-msisdn = "100"
mm1-http-proxy = 10.11.12.13:8080
incoming-port = 13014
mmsc-url = http://net.mmsc/servlets/mms
mm1-gprs-on-command = /usr/local/sbin/start-net-gprs
mm1-gprs-pid-command = "cat /var/run/ppp-net.pid|head -1"
group = mms-service
name = me
post-url = http://localhost/~bagyenda/test-mbuni.php
catch-all = true
http-post-parameters = fx=true&images[]=%i&text[]=%t&skip=1
accept-x-mbuni-headers = true
pass-thro-headers = X-NOKIA-MMSC-Charging,X-NOKIA-MMSC-Charged-Party
keyword = test
omit-empty = no
suppress-reply = true
service-code = regular
group = mms-service
name = fullmessage
get-url = http://localhost/images/apache_pb.gif
# http-post-parameters = fx=true&image=%i&text=%t
accept-x-mbuni-headers = true
keyword = thixs
group = send-mms-user
username = tester
password = foobar
faked-sender = 100

View File

@ -1,21 +1,24 @@
group = core
log-file = /tmp/log/mbuni.log
access-log = /tmp/log/access.log
log-file = /tmp/log/mbuni-mmsc.log
access-log = /tmp/log/mmsc-access.log
log-level = 0
group = mbuni
name = "My MMSC"
hostname = ds.co.ug
host-alias = mmsc
local-mmsc-domains = dsmagic.com
local-prefixes = 037;+25637;25637
storage-directory = /tmp/spool
max-send-threads = 5
send-mail-prog = /usr/sbin/sendmail -f '%f' '%t'
unified-prefix = "+25637,037,37"
maximum-send-attempts = 50
mm1-maximum-notify-attempts = 1
default-message-expiry = 360000
queue-run-interval = 0.1
max-message-expiry = 720000
mmsc-services = Relay,MM1
queue-run-interval = 5
mm1-queue-run-interval = 300
send-attempt-back-off = 300
sendsms-url = http://localhost:13013/cgi-bin/sendsms
sendsms-username = tester
@ -31,59 +34,20 @@ billing-module-parameters = "/tmp/log/cdr.log"
content-adaptation = true
notify-unprovisioned = yes
mms-notify-text = "You have received a multimedia message from %S, go to XXX to view it"
mm-box-host = local.ds.co.ug
mms-notify-unprovisioned-text = "This is a test"
mms-to-email-txt = "This is a multimedia message (HTML suppressed)"
mms-to-email-html = "This is a multimedia message powered by <emph>Digital Solutions</emph>"
mms-to-email-default-subject = "This is a multimedia message"
mms-message-too-large-txt = "You have received a multimedia message from %S that is too large for your phone. Go to xxx to view it"
sendmms-port = 10001
group = send-mms-user
username = tester
password = foobar
# faked-sender = 100
group = send-mms-user
username = binary
password = "user"
faked-sender = 111
group = mmsc
id = testone
mmsc-url = http://mbuni:test@192.168.129.52:8080/eaif
# mmsc-url = http://localhost:8080/vasp/servlet/messagerouter
incoming-username = user
incoming-password = pass
incoming-port = 10002
type = eaif
group = mms-service
name = me
file = /tmp/start.smil
catch-all = true
# http-post-parameters = fx=true&images.=%i&text.=%t
accept-x-mbuni-headers = true
keyword = test
group = mms-service
name = fullmessage
get-url = http://localhost/~bagyenda/images/apache_pb.gif
# http-post-parameters = fx=true&image=%i&text=%t
accept-x-mbuni-headers = true
keyword = thixs
strip-prefixes = "1;2"
group = mms-vasp
vasp-id = newscorp
type = soap
short-code = 111
vasp-username = newscorp
vasp-password = news123
vasp-url = http://localhost:23535/
mmsc-username = user
mmsc-password = secret
mms-to-email-handler = true
mms-to-local-copy-handler = true
vasp-username = mbuni
vasp-password = test
vasp-url = http://user:pass@localhost:12345/
group = mmsproxy
name = "A test mms proxy"

File diff suppressed because it is too large Load Diff

7
mbuni/extras/Makefile.am Normal file
View File

@ -0,0 +1,7 @@
if BUILD_PGSQLQ
X = pgsql-queue
endif
if BUILD_MMSBOXMM1
Y = mmsbox-mm1
endif
SUBDIRS = $(X) $(Y)

View File

@ -0,0 +1,3 @@
lib_LTLIBRARIES = libmmsbox_mm1.la
libmmsbox_mm1_la_SOURCES = mmsbox_mm1.c
libmmsbox_mm1_la_LDFLAGS = -module

View File

@ -0,0 +1,761 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Mbuni MmsBox MM1 Component - Send & Receive MMS using a GPRS/EDGE/3G modem
*
* Copyright (C) 2007-2009, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include "mmsbox_mmsc.h"
#include "mmsbox_cfg.h"
#include "mmsbox.h"
#include "mms_util.h"
typedef struct {
Octstr *mmsc_url; /* mmsc-url. */
Octstr *msisdn; /* my msisdn. */
Octstr *proxy; /* form is host:port. */
Octstr *gprs_on; /* Command to start GPRS link. Must not exit. */
Octstr *gprs_off; /* Command to stop GPRS link. */
Octstr *gprs_pid; /* command to call to get PID of GPRS for stopping GPRS link (i.e. pppd). */
Octstr *smsc_on; /* command to start smsc connection */
Octstr *smsc_off; /* commadn to stop smsc connection */
int port; /* port for incoming messages. */
Octstr *interface; /* specific interface to listen on. */
Octstr *unified_prefix; /* copies from above, do not edit! */
List *strip_prefixes;
/* internal data. */
MmscGrp *info;
MmsQueueHandlerFuncs *qfs;
List *requests; /* list of requests. */
long h_tid, d_tid; /* thread IDs. */
int sender_alive;
} MM1Settings;
typedef struct {
enum {MM1_GET, MM1_PUSH} type;
int waiter_exists; /* set to true if after handling, should signal and NOT destroy struct.*/
pthread_cond_t cond;
pthread_mutex_t mutex;
union {
MmsMsg *m; /* for push. */
Octstr *url; /* for get */
} u;
void *result; /* set to the result for a PUSH */
Octstr *error;
} MM1Request;
static void stop_gprs(Octstr *cmd);
static void handle_notify(MM1Settings *mm1);
static void handle_mm1(MM1Settings *mm1);
static int open_mm1(MmscGrp *mmc, MmsQueueHandlerFuncs *qfs,
Octstr *unified_prefix, List *strip_prefixes,
void **data)
{
Octstr *x, *y;
List *l;
Octstr *mmsc_url = NULL;
Octstr *proxy = NULL;
Octstr *gprs_on = NULL;
Octstr *gprs_off = NULL;
Octstr *gprs_pid = NULL;
Octstr *smsc_on = NULL;
Octstr *smsc_off = NULL;
int port = 80;
Octstr *interface = NULL;
Octstr *msisdn = NULL;
MM1Settings *mm1;
/* parse the settings. */
x = octstr_duplicate(mmc->settings);
l = octstr_split(x, octstr_imm(";"));
octstr_destroy(x);
if (l)
while ((y = gwlist_extract_first(l)) != NULL) {
int i = octstr_search_char(y, '=', 0);
Octstr *item = (i>=0) ? octstr_copy(y, 0, i) : NULL;
Octstr *value = (i>=0) ? octstr_copy(y, i+1, octstr_len(y)) : NULL;
if (item == NULL)
octstr_destroy(value);
else if (octstr_str_case_compare(item, "mmsc-url") == 0)
mmsc_url = value;
else if (octstr_str_case_compare(item, "proxy") == 0)
proxy = value;
else if (octstr_str_case_compare(item, "gprs-on") == 0)
gprs_on = value;
else if (octstr_str_case_compare(item, "gprs-off") == 0)
gprs_off = value;
else if (octstr_str_case_compare(item, "gprs-pid") == 0)
gprs_pid = value;
else if (octstr_str_case_compare(item, "port") == 0) {
port = value ? atoi(octstr_get_cstr(value)) : 80;
if (http_open_port(port, 0) != 0)
mms_warning(0, "mmsbox-mm1", NULL, "failed to open incoming notifications port %d: %s",
port, strerror(errno));
}else if (octstr_str_case_compare(item, "http-interface") == 0)
interface = value;
else if (octstr_str_case_compare(item, "smsc-on") == 0)
smsc_on = value;
else if (octstr_str_case_compare(item, "smsc-off") == 0)
smsc_off = value;
else if (octstr_str_case_compare(item, "msisdn") == 0)
msisdn = value;
else {
mms_error(0, "mmsbox-mm1", NULL, "unknown/unsupported option: %s", octstr_get_cstr(item));
octstr_destroy(value);
}
octstr_destroy(item);
octstr_destroy(y);
}
else {
mms_error(0, "mmsbox-mm1", NULL, "failed to parse settings string: %s", octstr_get_cstr(mmc->settings));
return -1;
}
gwlist_destroy(l, NULL);
mm1 = gw_malloc(sizeof *mm1);
mm1->mmsc_url = mmsc_url;
mm1->proxy = proxy;
mm1->gprs_on = gprs_on;
mm1->gprs_off = gprs_off;
mm1->gprs_pid = gprs_pid;
mm1->smsc_on = smsc_on;
mm1->smsc_off = smsc_off;
mm1->port = port;
mm1->interface = interface;
mm1->msisdn = msisdn;
mm1->unified_prefix = unified_prefix;
mm1->strip_prefixes = strip_prefixes;
mm1->qfs = qfs;
mm1->info = mmc;
mm1->requests = gwlist_create();
mm1->sender_alive = 0;
gwlist_add_producer(mm1->requests); /* so that when first listener starts, knows there is a consumer. */
mm1->h_tid = gwthread_create((gwthread_func_t *)handle_notify, mm1);
mm1->d_tid = gwthread_create((gwthread_func_t *)handle_mm1, mm1);
*data = mm1;
return 0;
}
static void handle_notify(MM1Settings *mm1)
{
HTTPClient *client = NULL;
Octstr *ip = NULL, *url = NULL;
Octstr *body = NULL;
List *cgivars = NULL, *h = NULL;
while ((client = http_accept_request(mm1->port, &ip, &url, &h, &body, &cgivars)) != NULL) {
List *cgivar_ctypes = NULL;
Octstr *text, *rb = NULL, *s = NULL, *loc = NULL;
MmsMsg *m = NULL;
int hdrlen, status = HTTP_ACCEPTED, mtype;
List *mh = NULL, *to = gwlist_create(), *rh = http_create_empty_headers();
time_t expiryt = -1, deliveryt = -1;
Octstr *from = NULL, *subject = NULL, *otransid = NULL, *mmc_id = NULL;
Octstr *qdir;
parse_cgivars(h, body, &cgivars, &cgivar_ctypes);
text = http_cgi_variable(cgivars, "text");
if (!text) {
rb = octstr_imm("mmsbox-mm1: missing 'text' CGI parameter!");
status = HTTP_NOT_FOUND;
goto loop;
}
/* now parse the MMS, determine what kind it is,
queue the fetch request or deal with it directly.
*/
hdrlen = octstr_get_char(text, 2);
if ((s = octstr_copy(text, 3 + hdrlen, octstr_len(text))) != NULL)
m = mms_frombinary(s, mm1->msisdn);
else
m = NULL;
if (m == NULL) {
rb = octstr_imm("mmsbox-mm1: mal-formed mms packet on interface!");
status = HTTP_FORBIDDEN;
goto loop;
} else
mms_msgdump(m, 1);
/* rest of this copied largely from EAIF code. */
mh = mms_message_headers(m);
mtype = mms_messagetype(m);
mms_collect_envdata_from_msgheaders(mh, &to, &subject,
&otransid, &expiryt, &deliveryt,
DEFAULT_EXPIRE, -1,
octstr_get_cstr(mm1->unified_prefix),
mm1->strip_prefixes);
from = http_header_value(mh, octstr_imm("From"));
qdir = get_mmsbox_queue_dir(from, to, mm1->info, &mmc_id); /* get routing info. */
switch (mtype) {
Octstr *qf;
Octstr *dlr_url, *status_value, *msgid;
List *rqh;
case MMS_MSGTYPE_DELIVERY_IND: /* notification of a delivery. */
case MMS_MSGTYPE_READ_ORIG_IND: /* message read. */
msgid = http_header_value(mh, octstr_imm("Message-ID"));
status_value = http_header_value(mh,
(mtype == MMS_MSGTYPE_DELIVERY_IND) ?
octstr_imm("X-Mms-Status") :
octstr_imm("X-Mms-Read-Status"));
rqh = http_create_empty_headers();
dlr_url = mmsbox_get_report_info(m, mm1->info, mmc_id,
(mtype == MMS_MSGTYPE_DELIVERY_IND) ?
"delivery-report" : "read-report",
status_value, rqh, NULL, 0, msgid);
qf = mm1->qfs->mms_queue_add(from, to, NULL,
mm1->info->id, mmc_id,
0, time(NULL) + default_msgexpiry, m, NULL,
NULL, NULL,
dlr_url, NULL,
rqh,
0,
octstr_get_cstr(qdir),
"MM7/MM1-IN",
octstr_imm(MM_NAME));
if (qf)
/* Log to access log */
mms_log((mtype == MMS_MSGTYPE_DELIVERY_IND) ? "Received DLR" : "Received RR",
from, to, -1, msgid, status_value, mm1->info->id,
"MMSBox", octstr_imm("MM1"), NULL);
else
status = HTTP_INTERNAL_SERVER_ERROR;
octstr_destroy(qf);
octstr_destroy(msgid);
octstr_destroy(dlr_url);
octstr_destroy(status_value);
http_destroy_headers(rqh);
break;
case MMS_MSGTYPE_NOTIFICATION_IND: /* notification of an incoming message. */
if ((loc = http_header_value(mh, octstr_imm("X-Mms-Content-Location"))) != NULL) {
MM1Request *r = gw_malloc(sizeof *r);
memset(r, 0, sizeof *r);
r->type = MM1_GET;
r->u.url = loc;
r->waiter_exists = 0;
loc = NULL;
gwlist_produce(mm1->requests, r);
} else
rb = octstr_format("mmsbox-mm1: notification with content-location??");
break;
default:
rb = octstr_format("mmsbox-mm1: unexpected message type: %s",
mms_message_type_to_cstr(mtype));
status = HTTP_NOT_FOUND;
break;
}
loop:
/* send reply. */
http_header_add(rh, "Content-Type", "text/plain");
http_send_reply(client, status, rh, rb ? rb : octstr_imm(""));
octstr_destroy(s);
octstr_destroy(ip);
octstr_destroy(url);
octstr_destroy(loc);
octstr_destroy(mmc_id);
octstr_destroy(from);
octstr_destroy(subject);
octstr_destroy(otransid);
octstr_destroy(body);
octstr_destroy(rb);
gwlist_destroy(to, (void *)octstr_destroy);
http_destroy_headers(h);
http_destroy_headers(rh);
http_destroy_headers(mh);
http_destroy_cgiargs(cgivars);
http_destroy_cgiargs(cgivar_ctypes);
mms_destroy(m);
}
mms_info(0, "mmsbox-mm1", NULL, "handle_notify exits");
gwlist_remove_producer(mm1->requests); /* cause consumers to shut down. */
}
static Octstr *send_msg(void *data, Octstr *from, Octstr *to,
Octstr *transid,
Octstr *linkedid, char *vasid, Octstr *service_code,
MmsMsg *m, List *hdrs, Octstr **err, int *retry)
{
MM1Request *r = gw_malloc(sizeof *r);
MM1Settings *s = data;
Octstr *id;
gw_assert(data);
gw_assert(m);
if (!s->sender_alive) {
*err = octstr_imm("internal error, mm1 notify not started!");
*retry = 1;
return NULL;
}
/* Remove the from address first of all, replace the to address as well */
mms_replace_header_value(m, "From", "#insert");
mms_replace_header_value(m, "To", octstr_get_cstr(to));
mms_remove_headers(m, "Message-ID");
r->u.m = m;
pthread_cond_init(&r->cond, NULL);
pthread_mutex_init(&r->mutex, NULL);
r->waiter_exists = 1;
r->type = MM1_PUSH;
r->result = NULL;
r->error = NULL;
pthread_mutex_lock(&r->mutex); /* at pickup, must grab mutex before signalling. otherwise race condition.*/
gwlist_produce(s->requests, r);
pthread_cond_wait(&r->cond, &r->mutex);
*err = r->error;
id = r->result;
mms_info(0, "mmsbox-mm1", NULL, "sent message, type=%s, result=%s",
mms_message_type_to_cstr(mms_messagetype(m)), r->error ? octstr_get_cstr(r->error) : "(none)");
/* destroy the structure. */
if(r->error && (octstr_compare(r->error, octstr_imm("Error-service-denied")) == 0 ||
octstr_compare(r->error, octstr_imm("Error-permanent-failure")) == 0))
*retry = 0;
else
*retry = 1;
pthread_cond_destroy(&r->cond);
pthread_mutex_destroy(&r->mutex);
gw_free(r);
return id;
}
static long start_gprs(Octstr *cmd, Octstr *pid_cmd);
static Octstr *fetch_content(Octstr *url, Octstr *proxy, Octstr *body, int *hstatus);
static void handle_mm1(MM1Settings *mm1)
{
/* stop smsc, start GPRS, transact, stop GPRS, start SMSC. And so on. */
MM1Request *r;
mms_info(0, "mmsbox-mm1", NULL, "handle_mm1 started");
mm1->sender_alive++;
while ((r = gwlist_consume(mm1->requests)) != NULL) {
long n, pid = -1;
if (mm1->smsc_off) {
n = system(octstr_get_cstr(mm1->smsc_off));
gwthread_sleep(5); /* allow it to die. */
}
if (mm1->gprs_on)
pid = start_gprs(mm1->gprs_on, mm1->gprs_pid);
if (pid < 0) {
mms_warning(0, "mmsbox-mm1", NULL,
"Failed to start GPRS connection. waiting...");
gwthread_sleep(2);
goto kill_gprs;
} else
mms_info(0, "mmsbox-mm1", NULL, "start_gprs returned PID: %ld", pid);
do {
Octstr *body;
Octstr *url;
int hstatus = 0;
Octstr *ms;
MmsMsg *m;
int msize;
if (r->waiter_exists)
pthread_mutex_lock(&r->mutex); /* grab lock to avoid race condition */
body = (r->type == MM1_PUSH) ? mms_tobinary(r->u.m) : NULL;
url = (r->type == MM1_PUSH) ? mm1->mmsc_url : r->u.url;
ms = fetch_content(url, mm1->proxy, body, &hstatus);
msize = ms ? octstr_len(ms) : 0;
m = (hstatus == 0 && ms) ? mms_frombinary(ms, mm1->msisdn) : NULL;
if (r->type == MM1_GET) {
if (m == NULL)
mms_error(0, "mmsbox-mm1", NULL, "failed to fetch mms from URL: %s!",
octstr_get_cstr(url));
else {
List *mh = mms_message_headers(m), *to = gwlist_create();
Octstr *subject = NULL, *otransid = NULL, *msgid = NULL, *value;
Octstr *hfrom = mh ? http_header_value(mh, octstr_imm("From")) : octstr_imm("anon@anon");
Octstr *qf = NULL, *qdir = NULL, *mmc_id = NULL;
time_t expiryt = -1, deliveryt = -1;
int dlr;
/* we assume it is a true message (send_req|retrieve_conf) */
mms_collect_envdata_from_msgheaders(mh, &to, &subject,
&otransid, &expiryt, &deliveryt,
DEFAULT_EXPIRE, -1,
octstr_get_cstr(mm1->unified_prefix),
mm1->strip_prefixes);
msgid = http_header_value(mh, octstr_imm("Message-ID"));
value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"));
if (value &&
octstr_case_compare(value, octstr_imm("Yes")) == 0)
dlr = 1;
else
dlr = 0;
octstr_destroy(value);
if (deliveryt < 0)
deliveryt = time(NULL);
if (expiryt < 0)
expiryt = time(NULL) + DEFAULT_EXPIRE;
if (hfrom == NULL)
hfrom = http_header_value(mh, octstr_imm("From"));
mms_remove_headers(m, "Bcc");
mms_remove_headers(m, "X-Mms-Delivery-Time");
mms_remove_headers(m, "X-Mms-Expiry");
mms_remove_headers(m, "X-Mms-Sender-Visibility");
qdir = get_mmsbox_queue_dir(hfrom, to, mm1->info, &mmc_id); /* get routing info. */
/* Save it, put message id in header, return. */
qf = qfs->mms_queue_add(hfrom, to, subject,
mm1->info->id, mmc_id,
deliveryt, expiryt, m, NULL,
NULL, NULL,
NULL, NULL,
NULL,
dlr,
octstr_get_cstr(qdir),
"MM7/MM1-IN",
octstr_imm(MM_NAME));
if (qf)
/* Log to access log */
mms_log("Received", hfrom, to, msize,
msgid, NULL, mm1->info->id, "MMSBox",octstr_imm("MM1"), NULL);
else
mms_error(0, "mmsbox-mm1", NULL, "failed to create queue entry for URL %s",
octstr_get_cstr(url));
if (otransid) { /* tell mmsc that we fetched fine. */
int _status;
MmsMsg *mresp = mms_notifyresp_ind(octstr_get_cstr(otransid),
mms_message_enc(m), "Retrieved", 1);
Octstr *sm = mms_tobinary(mresp);
Octstr *_x = fetch_content(mm1->mmsc_url, mm1->proxy,
sm, &_status);
octstr_destroy(_x);
octstr_destroy(sm);
mms_destroy(mresp);
}
gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);
octstr_destroy(hfrom);
octstr_destroy(subject);
octstr_destroy(otransid);
octstr_destroy(msgid);
octstr_destroy(qf);
octstr_destroy(mmc_id);
http_destroy_headers(mh);
}
} else if (r->type == MM1_PUSH) {
/* we expect a send-conf. */
if (ms) {
octstr_dump(ms, 0);
mms_msgdump(m, 1);
} else
mms_warning(0, "mmsbox-mm1", NULL,"No send-conf returned by operator");
if (m == NULL ||
(r->result = mms_get_header_value(m, octstr_imm("Message-ID"))) == NULL ||
octstr_compare(mms_get_header_value(m, octstr_imm("X-Mms-Response-Status")),
octstr_imm("Ok")) != 0
) {
Octstr *err = m ? mms_get_header_value(m, octstr_imm("X-Mms-Response-Text")) : NULL;
Octstr *status = m ? mms_get_header_value(m, octstr_imm("X-Mms-Response-Status")) : NULL;
if(status && (octstr_compare(status, octstr_imm("Error-service-denied")) == 0 ||
octstr_compare(status, octstr_imm("Error-permanent-failure")) == 0)) {
r->error = octstr_duplicate(status);
}
r->result = NULL; /* indicate failure to bearerbox */
mms_error(0, "mmsbox-mm1", NULL, "Sending failed: %s, %s!",
err ? octstr_get_cstr(err) : "(none)",
status ? octstr_get_cstr(status) : "(none)");
octstr_destroy(err);
octstr_destroy(status);
}
} else
mms_error(0, "mmsbox-mm1", NULL, "unknown type: %d", r->type);
if (r->waiter_exists) {
pthread_mutex_unlock(&r->mutex);
pthread_cond_signal(&r->cond);
} else /* no waiter, so we free it ourselves. */
gw_free(r);
octstr_destroy(body);
octstr_destroy(ms);
mms_destroy(m);
r = NULL;
pid_t wp;
int st;
wp = waitpid(pid, &st, WNOHANG);
if(wp == pid && WIFEXITED(st)) {
mms_info(0, "mmsbox-mm1", NULL, "GPRS pid (%d) appears to be dead - quitting loop", pid);
goto after_gprs_dead;
}
gwthread_sleep(2); /* according to Piotr Isajew, this makes life better */
} while (gwlist_len(mm1->requests) > 0 &&
(r = gwlist_consume(mm1->requests)) != NULL);
kill_gprs:
if(r != NULL) {
if(r->waiter_exists) {
pthread_mutex_unlock(&r->mutex);
pthread_cond_signal(&r->cond);
} else{
gw_free(r);
}
}
if (mm1->gprs_off) {
stop_gprs(mm1->gprs_off);
} else if (pid > 0) { /* stop GPRS, restart SMSC connection. */
int xkill, status;
pid_t wpid;
do {
xkill = kill(pid, SIGTERM);
mms_info(0, "mmsbox-mm1", NULL, "GPRS turned off returned: %d", xkill);
if (xkill < 0 && errno == ESRCH)
break;
wpid = waitpid(pid, &status, 0);
if (wpid == pid && WIFEXITED(status))
break;
else if (wpid < 0 && errno == ECHILD)
break;
} while (1);
gwthread_sleep(2);
}
after_gprs_dead:
if (mm1->smsc_on) {
system(octstr_get_cstr(mm1->smsc_on));
gwthread_sleep(5);
mms_info(0, "mmsbox-mm1", NULL, "SMSC turned on");
}
}
mm1->sender_alive--;
mms_info(0, "mmsbox-mm1", NULL, "handle_mm1 exits");
}
static int close_mm1(void *data)
{
MM1Settings *s = data;
/* close the port, and all will die. */
http_close_port(s->port);
gwthread_sleep(2);
gwthread_join(s->h_tid);
gwthread_sleep(2);
gwthread_join(s->d_tid);
octstr_destroy(s->mmsc_url);
octstr_destroy(s->msisdn);
octstr_destroy(s->proxy);
octstr_destroy(s->gprs_on);
octstr_destroy(s->gprs_off);
octstr_destroy(s->gprs_pid);
octstr_destroy(s->smsc_on);
octstr_destroy(s->smsc_off);
octstr_destroy(s->interface);
gwlist_destroy(s->requests, NULL);
gw_free(s);
return 0;
}
MmsBoxMmscFuncs mmsc_funcs = {
open_mm1,
close_mm1,
send_msg
};
#include <curl/curl.h>
static int write_octstr_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
Octstr *out = userp;
octstr_append_data(out, buffer, size*nmemb);
mms_info(0, "mmsbox-mm1", NULL, "write_data called with nmemn=%ld, size=%ld",
nmemb, size);
return size*nmemb;
}
static Octstr *fetch_content(Octstr *url, Octstr *proxy, Octstr *body, int *hstatus)
{
CURL *cl;
struct curl_slist *h = NULL;
char errbuf[512];
static int curl_inited = 0;
Octstr *s = octstr_create("");
if (curl_inited == 0) {
curl_global_init(CURL_GLOBAL_ALL);
curl_inited = 1;
}
cl = curl_easy_init();
curl_easy_setopt(cl, CURLOPT_URL, octstr_get_cstr(url));
if (proxy && octstr_len(proxy) > 0)
curl_easy_setopt(cl, CURLOPT_PROXY, octstr_get_cstr(proxy));
curl_easy_setopt(cl, CURLOPT_WRITEFUNCTION, write_octstr_data);
curl_easy_setopt(cl, CURLOPT_WRITEDATA, s);
curl_easy_setopt(cl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(cl, CURLOPT_TIMEOUT, 120L);
curl_easy_setopt(cl, CURLOPT_FORBID_REUSE, 1L);
curl_easy_setopt(cl, CURLOPT_CONNECTTIMEOUT, 40L);
h = curl_slist_append(h, "Accept: */*");
if (body) { /* POST. */
h = curl_slist_append(h, "Content-Type: application/vnd.wap.mms-message");
h = curl_slist_append(h, "User-Agent: Mozilla/5.0 (SymbianOS/9.4;U;"
"Series60/5.0 Nokia5800d-1/52.50.2008.24;"
"Profile/MIDP-2.1Configuration/CLDC-1.1 ) "
"AppleWebKit/413 (KHTML, like Gecko) "
"Safari/413");
curl_easy_setopt(cl, CURLOPT_POSTFIELDS, octstr_get_cstr(body));
curl_easy_setopt(cl, CURLOPT_POSTFIELDSIZE, octstr_len(body));
}
curl_easy_setopt(cl, CURLOPT_HTTPHEADER, h);
curl_easy_setopt(cl, CURLOPT_ERRORBUFFER, errbuf);
*hstatus = curl_easy_perform(cl); /* post away! */
if (*hstatus != 0)
mms_error(0, "mmsbox-mm1", NULL, "failed to fetch/post content to host %s [proxy: %s] [http_status=%d] : %.256s",
octstr_get_cstr(url), octstr_len(proxy) > 0 ? octstr_get_cstr(proxy) : "n/a",
*hstatus, errbuf);
curl_slist_free_all(h); /* free the header list */
curl_easy_setopt(cl, CURLOPT_NOSIGNAL, 0L);
curl_easy_cleanup(cl);
return s;
}
#include <unistd.h>
static void stop_gprs(Octstr *cmd)
{
pid_t pid = fork();
if (pid == 0) {
/* in child */
List *l = octstr_split_words(cmd);
int i, n = gwlist_len(l);
char **args = gw_malloc((n+1) * sizeof *args);
for (i = 0; i < n; i++) {
Octstr *x = gwlist_get(l, i);
args[i] = octstr_get_cstr(x);
printf("arg %d: %s\n", i, args[i]);
}
args[i] = NULL;
printf("Not reached: %d!", execvp(args[0], args));
}
}
#define MAX_GPRS_WAIT 80
#define GPRS_POLL 5
static long start_gprs(Octstr *cmd, Octstr *pid_cmd)
{
pid_t pid = fork();
if (pid > 0) { /* parent. */
int ct = 0;
do {
FILE *f;
long xpid = -1, cpid;
int status;
gwthread_sleep(GPRS_POLL); /* wait a little. */
if ((f = popen(octstr_get_cstr(pid_cmd), "r")) != NULL) {
fscanf(f, "%ld", &xpid);
pclose(f);
if (xpid >= 0)
return xpid;
}
cpid = waitpid(pid, &status, WNOHANG); /* also wait for the child. */
mms_info(0, "mmsbox-mm1", NULL, "waiting for connection: %d, pid=%ld cpid=%ld, ifexited=%d, exitstatus=%d",
ct, (long)pid, cpid, WIFEXITED(status), WEXITSTATUS(status));
if (cpid == pid &&
WIFEXITED(status))
return -1;
} while (GPRS_POLL*ct++ < MAX_GPRS_WAIT);
/* Timed out, but still need to wait for child pid, as
start-gprs script is still running and we don't need a
zombie */
pid_t rpid;
int st;
rpid = waitpid(pid, &st, 0);
mms_info(0, "mmsbox-mm1", NULL, "pid %d terminated", pid);
return -1;
} else if (pid == 0) { /* child. */
List *l = octstr_split_words(cmd);
int i, n = gwlist_len(l);
char **args = gw_malloc((n+1) * sizeof *args);
for (i = 0; i < n; i++) {
Octstr *x = gwlist_get(l, i);
args[i] = octstr_get_cstr(x);
printf("arg %d: %s\n", i, args[i]);
}
args[i] = NULL;
printf("Not reached: %d!", execvp(args[0], args));
} else
mms_error(0, "mmsbox-mm1", NULL, "failed to start process!");
return -1;
}

View File

@ -0,0 +1,4 @@
EXTRA_DIST = tables.sql
lib_LTLIBRARIES = libmms_pgsql_queue.la
libmms_pgsql_queue_la_SOURCES = mms_pgsql_queue.c
libmms_pgsql_queue_la_LDFLAGS = -module

View File

@ -0,0 +1,16 @@
This module provides Queue management for mbuni using PostgreSQL as the storage engine.
To use it, you need only add two lines to the mbuni config 'mbuni' group:
queue-manager-module = "/path_to/libmms_pgsql_queue.so"
queue-module-init-data = "host=dbhost user=db_user password=dbpassword dbname=dbname"
Make sure the database you are trying to connect to has already been created
and the relevant tables created using the supplied file "tables.sql".
Some notes:
- Mbuni will open number_of_db_connections connections to the database at startup.
Ensure your PostgreSQL installation limits are not exceeded. DB connections will
be shared by all parts of Mbuni, which means that in high traffic situations,
you may experience mbuni component slow-down as all db connections might be in use.
- Vacuum your DB often, since a lot of rows are updated/deleted during operation.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
-- Table structure for PostgreSQL MMS storage engine
-- (c) 2007 Digital Solutions
-- Licence: See http://mbuni.org/license.shtml
-- Author: P. A. Bagyenda <bagyenda@dsmagic.com>
-- Requires: PostgresQL v8.2 and above
-- Master messages table
CREATE TABLE mms_messages (
id bigserial PRIMARY KEY,
qdir varchar(256) NOT NULL,
qfname varchar(256) NOT NULL,
sender varchar(256) NOT NULL,
created timestamp with time zone NOT NULL DEFAULT current_timestamp,
last_try timestamp with time zone NOT NULL DEFAULT '-infinity',
send_time timestamp with time zone NOT NULL DEFAULT '-infinity',
expire_date timestamp with time zone NOT NULL,
num_attempts int NOT NULL DEFAULT 0,
data bytea NOT NULL DEFAULT '',
UNIQUE(qdir, qfname)
);
CREATE index mm_idx1 on mms_messages(qdir); -- because we use it for lookups.
CREATE index mm_idx2 on mms_messages(send_time);
CREATE index mm_idx3 on mms_messages(qfname);
-- create a view for message lookup
CREATE VIEW mms_messages_view AS SELECT
*,
EXTRACT(EPOCH FROM created) AS cdate,
EXTRACT(EPOCH FROM last_try) AS lastt,
EXTRACT(EPOCH FROM send_time) AS sendt,
EXTRACT(EPOCH FROM expire_date) AS edate FROM mms_messages;
-- Table for envelope headers.
CREATE TABLE mms_message_headers (
id bigserial PRIMARY KEY,
qid bigint REFERENCES mms_messages ON UPDATE CASCADE ON DELETE CASCADE,
item varchar(64) NOT NULL,
value text NOT NULL
);
-- When messages are deleted from the queue, they are moved to the achived_XXX tables.
-- archive tables are exact copies of old ones, field for field.
-- DBA should clear these tables as needed
CREATE TABLE archived_mms_messages (LIKE mms_messages INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
CREATE TABLE archived_mms_message_headers (LIKE mms_message_headers INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
ALTER table archived_mms_messages add unique(id);
ALTER table archived_mms_message_headers add foreign key (qid)
references archived_mms_messages (id);

View File

@ -1 +0,0 @@
EXTRA_DIST = mbuni-kannel-patch-full

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
noinst_LTLIBRARIES = libmms.la
libmms_la_SOURCES = mms_mmbox.c mms_msg.c mms_queue.c mms_strings.c mms_uaprof.c mms_util.c mms_mm7soap.c mms_cfg.c
lib_LTLIBRARIES = libmms.la
libmms_la_SOURCES = charmibenum.def mms_eventlogger.c mms_mmbox.c mms_msg.c mms_queue.c mms_strings.c mms_uaprof.c mms_util.c mms_mm7soap.c mms_cfg.c
EXTRA_DIST=mms_strings.def mms_mm7soap.h mms_mmbox.h mms_msg.h mms_queue.h mms_strings.h mms_uaprof.h mms_util.h mms_cfg.h mms_cfg.def
EXTRA_DIST=mms_strings.def mms_eventlogger.h mms_mm7soap.h mms_mmbox.h mms_msg.h mms_queue.h mms_strings.h mms_uaprof.h mms_util.h mms_cfg.h mms_cfg.def mms_cfg-impl.h

340
mbuni/mmlib/charmibenum.def Normal file
View File

@ -0,0 +1,340 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Charset MIBenum assignments - pre-processor magic.
*
* Copyright (C) 2003 - , Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#if !defined(CharMIBEnum)
#error "Required macro CharMIBEnum is missing."
#endif
CharMIBEnum(3,ASCII)
CharMIBEnum(3,ANSI_X3.4-1968)
CharMIBEnum(3,ANSI_X3.4-1986)
CharMIBEnum(3,CP367)
CharMIBEnum(3,IBM367)
CharMIBEnum(3,ISO-IR-6)
CharMIBEnum(3,ISO646-US)
CharMIBEnum(3,ISO_646.IRV:1991)
CharMIBEnum(3,US)
CharMIBEnum(3,US-ASCII)
CharMIBEnum(3,CSASCII)
CharMIBEnum(4,CP819)
CharMIBEnum(4,IBM819)
CharMIBEnum(4,ISO-8859-1)
CharMIBEnum(4,ISO-IR-100)
CharMIBEnum(4,ISO8859-1)
CharMIBEnum(4,ISO_8859-1)
CharMIBEnum(4,ISO_8859-1:1987)
CharMIBEnum(4,L1)
CharMIBEnum(4,LATIN1)
CharMIBEnum(4,CSISOLATIN1)
CharMIBEnum(5,ISO-8859-2)
CharMIBEnum(5,ISO-IR-101)
CharMIBEnum(5,ISO8859-2)
CharMIBEnum(5,ISO_8859-2)
CharMIBEnum(5,ISO_8859-2:1987)
CharMIBEnum(5,L2)
CharMIBEnum(5,LATIN2)
CharMIBEnum(5,CSISOLATIN2)
CharMIBEnum(6,ISO-8859-3)
CharMIBEnum(6,ISO-IR-109)
CharMIBEnum(6,ISO8859-3)
CharMIBEnum(6,ISO_8859-3)
CharMIBEnum(6,ISO_8859-3:1988)
CharMIBEnum(6,L3)
CharMIBEnum(6,LATIN3)
CharMIBEnum(6,CSISOLATIN3)
CharMIBEnum(7,ISO-8859-4)
CharMIBEnum(7,ISO-IR-110)
CharMIBEnum(7,ISO8859-4)
CharMIBEnum(7,ISO_8859-4)
CharMIBEnum(7,ISO_8859-4:1988)
CharMIBEnum(7,L4)
CharMIBEnum(7,LATIN4)
CharMIBEnum(7,CSISOLATIN4)
CharMIBEnum(8,CYRILLIC)
CharMIBEnum(8,ISO-8859-5)
CharMIBEnum(8,ISO-IR-144)
CharMIBEnum(8,ISO8859-5)
CharMIBEnum(8,ISO_8859-5)
CharMIBEnum(8,ISO_8859-5:1988)
CharMIBEnum(8,CSISOLATINCYRILLIC)
CharMIBEnum(9,ARABIC)
CharMIBEnum(9,ASMO-708)
CharMIBEnum(9,ECMA-114)
CharMIBEnum(9,ISO-8859-6)
CharMIBEnum(9,ISO-IR-127)
CharMIBEnum(9,ISO8859-6)
CharMIBEnum(9,ISO_8859-6)
CharMIBEnum(9,ISO_8859-6:1987)
CharMIBEnum(9,CSISOLATINARABIC)
CharMIBEnum(10,ECMA-118)
CharMIBEnum(10,ELOT_928)
CharMIBEnum(10,GREEK)
CharMIBEnum(10,GREEK8)
CharMIBEnum(10,ISO-8859-7)
CharMIBEnum(10,ISO-IR-126)
CharMIBEnum(10,ISO8859-7)
CharMIBEnum(10,ISO_8859-7)
CharMIBEnum(10,ISO_8859-7:1987)
CharMIBEnum(10,ISO_8859-7:2003)
CharMIBEnum(10,CSISOLATINGREEK)
CharMIBEnum(11,HEBREW)
CharMIBEnum(11,ISO-8859-8)
CharMIBEnum(11,ISO-IR-138)
CharMIBEnum(11,ISO8859-8)
CharMIBEnum(11,ISO_8859-8)
CharMIBEnum(11,ISO_8859-8:1988)
CharMIBEnum(11,CSISOLATINHEBREW)
CharMIBEnum(12,ISO-8859-9)
CharMIBEnum(12,ISO-IR-148)
CharMIBEnum(12,ISO8859-9)
CharMIBEnum(12,ISO_8859-9)
CharMIBEnum(12,ISO_8859-9:1989)
CharMIBEnum(12,L5)
CharMIBEnum(12,LATIN5)
CharMIBEnum(12,CSISOLATIN5)
CharMIBEnum(13,ISO-8859-10)
CharMIBEnum(13,ISO-IR-157)
CharMIBEnum(13,ISO8859-10)
CharMIBEnum(13,ISO_8859-10)
CharMIBEnum(13,ISO_8859-10:1992)
CharMIBEnum(13,L6)
CharMIBEnum(13,LATIN6)
CharMIBEnum(13,CSISOLATIN6)
CharMIBEnum(15,JISX0201-1976)
CharMIBEnum(15,JIS_X0201)
CharMIBEnum(15,X0201)
CharMIBEnum(15,CSHALFWIDTHKATAKANA)
CharMIBEnum(17,MS_KANJI)
CharMIBEnum(17,SHIFT-JIS)
CharMIBEnum(17,SHIFT_JIS)
CharMIBEnum(17,SJIS)
CharMIBEnum(17,CSSHIFTJIS)
CharMIBEnum(17,SHIFT_JIS-2004)
CharMIBEnum(17,SHIFT_JISX0213)
CharMIBEnum(18,EUC-JP)
CharMIBEnum(18,EUCJP)
CharMIBEnum(18,EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE)
CharMIBEnum(18,CSEUCPKDFMTJAPANESE)
CharMIBEnum(36,ISO-IR-149)
CharMIBEnum(36,KOREAN)
CharMIBEnum(36,KSC_5601)
CharMIBEnum(36,KS_C_5601-1987)
CharMIBEnum(36,KS_C_5601-1989)
CharMIBEnum(36,CSKSC56011987)
CharMIBEnum(37,ISO-2022-KR)
CharMIBEnum(37,CSISO2022KR)
CharMIBEnum(38,EUC-KR)
CharMIBEnum(38,EUCKR)
CharMIBEnum(38,CSEUCKR)
CharMIBEnum(39,ISO-2022-JP)
CharMIBEnum(39,CSISO2022JP)
CharMIBEnum(39,ISO-2022-JP-1)
CharMIBEnum(39,ISO-2022-JP-2)
CharMIBEnum(39,CSISO2022JP2)
CharMIBEnum(39,ISO-2022-JP-2004)
CharMIBEnum(39,ISO-2022-JP-3)
CharMIBEnum(40,ISO-2022-JP-2)
CharMIBEnum(40,CSISO2022JP2)
CharMIBEnum(40,ISO-2022-JP-2004)
CharMIBEnum(40,ISO-2022-JP-3)
CharMIBEnum(42,ISO-IR-14)
CharMIBEnum(42,ISO646-JP)
CharMIBEnum(42,JIS_C6220-1969-RO)
CharMIBEnum(42,JP)
CharMIBEnum(42,CSISO14JISC6220RO)
CharMIBEnum(56,CN)
CharMIBEnum(56,GB_1988-80)
CharMIBEnum(56,ISO-IR-57)
CharMIBEnum(56,ISO646-CN)
CharMIBEnum(56,CSISO57GB1988)
CharMIBEnum(57,CHINESE)
CharMIBEnum(57,GB_2312-80)
CharMIBEnum(57,ISO-IR-58)
CharMIBEnum(57,CSISO58GB231280)
CharMIBEnum(63,ISO-IR-87)
CharMIBEnum(63,JIS0208)
CharMIBEnum(63,JIS_C6226-1983)
CharMIBEnum(63,JIS_X0208)
CharMIBEnum(63,JIS_X0208-1983)
CharMIBEnum(63,JIS_X0208-1990)
CharMIBEnum(63,X0208)
CharMIBEnum(63,CSISO87JISX0208)
CharMIBEnum(98,ISO-IR-159)
CharMIBEnum(98,JIS_X0212)
CharMIBEnum(98,JIS_X0212-1990)
CharMIBEnum(98,JIS_X0212.1990-0)
CharMIBEnum(98,X0212)
CharMIBEnum(98,CSISO159JISX02121990)
CharMIBEnum(103,UNICODE-1-1-UTF-7)
CharMIBEnum(103,UTF-7)
CharMIBEnum(103,CSUNICODE11UTF7)
CharMIBEnum(104,ISO-2022-CN)
CharMIBEnum(104,CSISO2022CN)
CharMIBEnum(104,ISO-2022-CN-EXT)
CharMIBEnum(105,ISO-2022-CN-EXT)
CharMIBEnum(106,UTF-8)
CharMIBEnum(106,UTF-8-MAC)
CharMIBEnum(106,UTF8-MAC)
CharMIBEnum(109,ISO-8859-13)
CharMIBEnum(109,ISO-IR-179)
CharMIBEnum(109,ISO8859-13)
CharMIBEnum(109,ISO_8859-13)
CharMIBEnum(109,L7)
CharMIBEnum(109,LATIN7)
CharMIBEnum(110,ISO-8859-14)
CharMIBEnum(110,ISO-CELTIC)
CharMIBEnum(110,ISO-IR-199)
CharMIBEnum(110,ISO8859-14)
CharMIBEnum(110,ISO_8859-14)
CharMIBEnum(110,ISO_8859-14:1998)
CharMIBEnum(110,L8)
CharMIBEnum(110,LATIN8)
CharMIBEnum(111,ISO-8859-15)
CharMIBEnum(111,ISO-IR-203)
CharMIBEnum(111,ISO8859-15)
CharMIBEnum(111,ISO_8859-15)
CharMIBEnum(111,ISO_8859-15:1998)
CharMIBEnum(111,LATIN-9)
CharMIBEnum(112,ISO-8859-16)
CharMIBEnum(112,ISO-IR-226)
CharMIBEnum(112,ISO8859-16)
CharMIBEnum(112,ISO_8859-16)
CharMIBEnum(112,ISO_8859-16:2001)
CharMIBEnum(112,L10)
CharMIBEnum(112,LATIN10)
CharMIBEnum(113,GBK)
CharMIBEnum(114,GB18030)
CharMIBEnum(1000,ISO-10646-UCS-2)
CharMIBEnum(1000,UCS-2)
CharMIBEnum(1000,CSUNICODE)
CharMIBEnum(1001,ISO-10646-UCS-4)
CharMIBEnum(1001,UCS-4)
CharMIBEnum(1001,CSUCS4)
CharMIBEnum(1010,UCS-2BE)
CharMIBEnum(1010,UNICODE-1-1)
CharMIBEnum(1010,UNICODEBIG)
CharMIBEnum(1010,CSUNICODE11)
CharMIBEnum(1010,UNICODE-1-1-UTF-7)
CharMIBEnum(1010,UTF-7)
CharMIBEnum(1010,CSUNICODE11UTF7)
CharMIBEnum(1012,UNICODE-1-1-UTF-7)
CharMIBEnum(1012,UTF-7)
CharMIBEnum(1012,CSUNICODE11UTF7)
CharMIBEnum(1013,UTF-16BE)
CharMIBEnum(1014,UTF-16LE)
CharMIBEnum(1015,UTF-16)
CharMIBEnum(1015,UTF-16BE)
CharMIBEnum(1015,UTF-16LE)
CharMIBEnum(1017,UTF-32)
CharMIBEnum(1017,UTF-32BE)
CharMIBEnum(1017,UTF-32LE)
CharMIBEnum(1018,UTF-32BE)
CharMIBEnum(1019,UTF-32LE)
CharMIBEnum(2004,HP-ROMAN8)
CharMIBEnum(2004,R8)
CharMIBEnum(2004,ROMAN8)
CharMIBEnum(2004,CSHPROMAN8)
CharMIBEnum(2009,850)
CharMIBEnum(2009,CP850)
CharMIBEnum(2009,IBM850)
CharMIBEnum(2009,CSPC850MULTILINGUAL)
CharMIBEnum(2013,862)
CharMIBEnum(2013,CP862)
CharMIBEnum(2013,IBM862)
CharMIBEnum(2013,CSPC862LATINHEBREW)
CharMIBEnum(2025,CHINESE)
CharMIBEnum(2025,GB_2312-80)
CharMIBEnum(2025,ISO-IR-58)
CharMIBEnum(2025,CSISO58GB231280)
CharMIBEnum(2025,CN-GB)
CharMIBEnum(2025,EUC-CN)
CharMIBEnum(2025,EUCCN)
CharMIBEnum(2025,GB2312)
CharMIBEnum(2025,CSGB2312)
CharMIBEnum(2026,BIG-5)
CharMIBEnum(2026,BIG-FIVE)
CharMIBEnum(2026,BIG5)
CharMIBEnum(2026,BIGFIVE)
CharMIBEnum(2026,CN-BIG5)
CharMIBEnum(2026,CSBIG5)
CharMIBEnum(2026,BIG5-HKSCS:1999)
CharMIBEnum(2026,BIG5-HKSCS:2001)
CharMIBEnum(2026,BIG5-HKSCS)
CharMIBEnum(2026,BIG5-HKSCS:2004)
CharMIBEnum(2026,BIG5HKSCS)
CharMIBEnum(2026,BIG5-2003)
CharMIBEnum(2027,MAC)
CharMIBEnum(2027,MACINTOSH)
CharMIBEnum(2027,MACROMAN)
CharMIBEnum(2027,CSMACINTOSH)
CharMIBEnum(2082,VISCII)
CharMIBEnum(2082,VISCII1.1-1)
CharMIBEnum(2082,CSVISCII)
CharMIBEnum(2084,KOI8-R)
CharMIBEnum(2084,CSKOI8R)
CharMIBEnum(2084,KOI8-RU)
CharMIBEnum(2085,HZ)
CharMIBEnum(2085,HZ-GB-2312)
CharMIBEnum(2086,866)
CharMIBEnum(2086,CP866)
CharMIBEnum(2086,IBM866)
CharMIBEnum(2086,CSIBM866)
CharMIBEnum(2088,KOI8-U)
CharMIBEnum(2101,BIG5-HKSCS:1999)
CharMIBEnum(2101,BIG5-HKSCS:2001)
CharMIBEnum(2101,BIG5-HKSCS)
CharMIBEnum(2101,BIG5-HKSCS:2004)
CharMIBEnum(2101,BIG5HKSCS)
CharMIBEnum(2103,CP154)
CharMIBEnum(2103,CYRILLIC-ASIAN)
CharMIBEnum(2103,PT154)
CharMIBEnum(2103,PTCP154)
CharMIBEnum(2103,CSPTCP154)
CharMIBEnum(2109,CP874)
CharMIBEnum(2109,WINDOWS-874)
CharMIBEnum(2250,CP1250)
CharMIBEnum(2250,MS-EE)
CharMIBEnum(2250,WINDOWS-1250)
CharMIBEnum(2251,CP1251)
CharMIBEnum(2251,MS-CYRL)
CharMIBEnum(2251,WINDOWS-1251)
CharMIBEnum(2252,CP1252)
CharMIBEnum(2252,MS-ANSI)
CharMIBEnum(2252,WINDOWS-1252)
CharMIBEnum(2253,CP1253)
CharMIBEnum(2253,MS-GREEK)
CharMIBEnum(2253,WINDOWS-1253)
CharMIBEnum(2254,CP1254)
CharMIBEnum(2254,MS-TURK)
CharMIBEnum(2254,WINDOWS-1254)
CharMIBEnum(2255,CP1255)
CharMIBEnum(2255,MS-HEBR)
CharMIBEnum(2255,WINDOWS-1255)
CharMIBEnum(2256,CP1256)
CharMIBEnum(2256,MS-ARAB)
CharMIBEnum(2256,WINDOWS-1256)
CharMIBEnum(2257,CP1257)
CharMIBEnum(2257,WINBALTRIM)
CharMIBEnum(2257,WINDOWS-1257)
CharMIBEnum(2258,CP1258)
CharMIBEnum(2258,WINDOWS-1258)
CharMIBEnum(2259,ISO-IR-166)
CharMIBEnum(2259,TIS-620)
CharMIBEnum(2259,TIS620)
CharMIBEnum(2259,TIS620-0)
CharMIBEnum(2259,TIS620.2529-1)
CharMIBEnum(2259,TIS620.2533-0)
CharMIBEnum(2259,TIS620.2533-1)
#undef CharMIBEnum

View File

@ -0,0 +1,32 @@
/*
* Mbuni - Open Source MMS Gateway
*
* config file functions (when conf is loaded from another source)
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMS_CFG_IMPL__INCLUDED__
#define __MMS_CFG_IMPL__INCLUDED__
#include "mms_cfg.h"
typedef struct mCfgImpl mCfgImpl; /* Implementation-specific struct for config info. */
/* each implementation must export struct, symbol 'cfg_funcs'. */
typedef struct mCfgImpFuncs {
mCfgImpl *(*read)(Octstr *init_param);
void (*destroy)(mCfgImpl *);
mCfgGrp *(*cfg_get_single)(mCfgImpl *cfg, Octstr *name);
List *(*get_multi)(mCfgImpl *cfg,Octstr *name); /* List of mCfgGrp */
mCfgGrp *(*get_multi_by_field)(mCfgImpl *cfg, Octstr *name, Octstr *field, Octstr *value);
Octstr *(*get)(mCfgImpl *cfg, mCfgGrp *grp, Octstr *name);
Octstr *(*get_grp_name)(mCfgImpl *, mCfgGrp *);
void (*destroy_grp)(mCfgImpl *cfg, mCfgGrp *);
} mCfgImpFuncs;
#endif

View File

@ -3,7 +3,7 @@
*
* MMS Config file reader functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -16,7 +16,8 @@
#include <errno.h>
#include "mms_cfg.h"
#include "mms_cfg-impl.h"
#include "mms_util.h"
/* config file representation.
* 'grps' var is indexed by group name.
@ -26,11 +27,14 @@
struct mCfg {
Octstr *file;
Dict *grps;
mCfgImpl *xcfg; /* If set, then this is the real source of conf info. */
mCfgImpFuncs *cfg_funcs; /* Config funcs or NULL */
};
struct mCfgGrp {
struct mCfgGrp { /* when using file-based, this is our implementation of a group. */
Octstr *name;
Dict *fields;
Dict *fields;
};
static void fixup_value(Octstr *value, int lineno)
@ -43,7 +47,7 @@ static void fixup_value(Octstr *value, int lineno)
if (octstr_get_char(value, 0) != '"')
return;
if (octstr_get_char(value, octstr_len(value) - 1) != '"')
error(0, "Missing enclosing '\"' at line %d in conf file", lineno);
mms_error(0, "mms_cfg", NULL, "Missing enclosing '\"' at line %d in conf file", lineno);
octstr_delete(value, 0,1); /* strip quotes. */
octstr_delete(value, octstr_len(value) - 1, 1);
@ -83,9 +87,9 @@ static int is_multigroup(Octstr *grpname)
{
#define OCTSTR(x)
#define SINGLE_GROUP(name, fields) \
if (octstr_case_compare(grpname, octstr_imm(#name)) == 0) return 0;
if (octstr_str_case_compare(grpname, #name) == 0) return 0;
#define MULTI_GROUP(name, fields) \
if (octstr_case_compare(grpname, octstr_imm(#name)) == 0) return 1;
if (octstr_str_case_compare(grpname, #name) == 0) return 1;
#include "mms_cfg.def"
return -1;
@ -94,9 +98,9 @@ static int is_multigroup(Octstr *grpname)
static int valid_in_group(Octstr *grp, Octstr *field)
{
/* first validate whether field is permitted in the group. */
#define OCTSTR(parm) else if (octstr_case_compare(field,octstr_imm(#parm)) == 0) return 1;
#define OCTSTR(parm) else if (octstr_str_case_compare(field,#parm) == 0) return 1;
#define SINGLE_GROUP(grpname, fields) \
else if (octstr_case_compare(grp, octstr_imm(#grpname)) == 0) { \
else if (octstr_str_case_compare(grp, #grpname) == 0) { \
if (0) (void)0; \
fields \
}
@ -112,13 +116,26 @@ static int valid_in_group(Octstr *grp, Octstr *field)
static void check_and_add_field(mCfgGrp *grp, Octstr *field, Octstr *value, int lineno)
{
if (!valid_in_group(grp->name, field))
info(0, "field `%s' is not expected within group `%s' at line %d in conf file - skipped",
mms_info(0, "mms_cfg", NULL, "field `%s' is not expected within group `%s' at line %d in conf file - skipped",
octstr_get_cstr(field), octstr_get_cstr(grp->name), lineno);
else if (dict_put_once(grp->fields, field, octstr_duplicate(value)) == 0)
panic(0, "Duplicate field `%s' at line %d in conf file",
mms_error(0, "mms_cfg", NULL, "Duplicate field `%s' at line %d in conf file, ignored",
octstr_get_cstr(field), lineno);
}
static mCfg *make_cfg(Octstr *file)
{
mCfg *cfg;
cfg = gw_malloc(sizeof *cfg);
cfg->file = file ? octstr_duplicate(file) : NULL;
cfg->grps = dict_create(7, NULL);
cfg->xcfg = NULL;
cfg->cfg_funcs = NULL;
return cfg;
}
mCfg *mms_cfg_read(Octstr *file)
{
Octstr *sf;
@ -131,17 +148,15 @@ mCfg *mms_cfg_read(Octstr *file)
gw_assert(file);
if ((sf = octstr_read_file(octstr_get_cstr(file))) == NULL) {
error(errno, "failed to read config from `%s'", octstr_get_cstr(file));
mms_error(errno, "mms_cfg", NULL, "failed to read config from `%s'", octstr_get_cstr(file));
return NULL;
}
cfg = gw_malloc(sizeof *cfg);
cfg->file = octstr_duplicate(file);
cfg->grps = dict_create(7, NULL);
cfg = make_cfg(file);
lines = octstr_split(sf, octstr_imm("\n"));
for (i = 0, n = list_len(lines); i < n; i++) {
Octstr *current = list_get(lines,i);
for (i = 0, n = gwlist_len(lines); i < n; i++) {
Octstr *current = gwlist_get(lines,i);
int pos;
octstr_strip_blanks(current);
@ -161,16 +176,16 @@ mCfg *mms_cfg_read(Octstr *file)
octstr_strip_blanks(field);
fixup_value(value, i+1);
#if 0
info(0, "field/value: [%s - %s]", octstr_get_cstr(field),
mms_info(0, "mms_cfg", NULL, "field/value: [%s - %s]", octstr_get_cstr(field),
octstr_get_cstr(value));
#endif
if (octstr_case_compare(field, octstr_imm("group")) == 0)
if (octstr_str_case_compare(field, "group") == 0)
if (grp == NULL) { /* grp name. */
int ismulti = is_multigroup(value);
if (ismulti < 0) {
info(0, "Skipping unknown group `%s' at line %d of conf file",
mms_info(0, "mms_cfg", NULL, "Skipping unknown group `%s' at line %d of conf file",
octstr_get_cstr(value), i+1);
skip = 1;
} else {
@ -182,10 +197,10 @@ mCfg *mms_cfg_read(Octstr *file)
List *l = dict_get(cfg->grps, value);
if (l == NULL) {
l = list_create();
l = gwlist_create();
dict_put(cfg->grps, value, l);
}
list_append(l, grp);
gwlist_append(l, grp);
} else if (dict_put_once(cfg->grps, value, grp) == 0)
panic(0, "Group `%s' [at line %d] cannot appear more "
"than once in config!",
@ -207,8 +222,45 @@ mCfg *mms_cfg_read(Octstr *file)
panic(0, "mal-formed entry in conf file at line %d!", i+1);
}
list_destroy(lines, (list_item_destructor_t *)octstr_destroy);
gwlist_destroy(lines, (gwlist_item_destructor_t *)octstr_destroy);
octstr_destroy(sf);
/* Now check if config-source is set, use that. */
if ((grp = mms_cfg_get_single(cfg, octstr_imm("config-source"))) != NULL) {
Octstr *init = mms_cfg_get(cfg, grp, octstr_imm("config-library-init-param"));
cfg->cfg_funcs = _mms_load_module(cfg, grp, "config-library", "cfg_funcs", NULL);
if (cfg->cfg_funcs == NULL ||
cfg->cfg_funcs->read == NULL ||
(cfg->xcfg = cfg->cfg_funcs->read(init)) == NULL) {
mms_error(0, "mms_cfg", NULL, "Failed to load cfg reader library from conf!");
mms_cfg_destroy(cfg);
cfg = NULL;
}
octstr_destroy(init);
}
return cfg;
}
mCfg *mms_cfg_read2(mCfgImpFuncs *cfgfuncs, Octstr *init)
{
mCfg *cfg;
gw_assert(cfgfuncs);
cfg = make_cfg(NULL);
cfg->cfg_funcs = cfgfuncs;
if (cfg->cfg_funcs->read == NULL ||
(cfg->xcfg = cfg->cfg_funcs->read(init)) == NULL) {
mms_error(0, "mms_cfg", NULL, "Failed to load cfg reader: read failed in cfg_read2!");
mms_cfg_destroy(cfg);
cfg = NULL;
}
return cfg;
}
@ -226,20 +278,26 @@ void mms_cfg_destroy(mCfg *cfg)
gw_assert(cfg);
for (i = 0, l = dict_keys(cfg->grps), n = list_len(l); i < n; i++) {
Octstr *grpname = list_get(l, i);
for (i = 0, l = dict_keys(cfg->grps), n = gwlist_len(l); i < n; i++) {
Octstr *grpname = gwlist_get(l, i);
void *val = dict_get(cfg->grps, grpname);
if (is_multigroup(grpname)) {
if (is_multigroup(grpname)) { /* item is a list. */
List *gl = val;
int j, m = list_len(gl);
int j, m = gwlist_len(gl);
for (j = 0; j < m; j++)
mGrp_destroy(list_get(gl, j));
mGrp_destroy(gwlist_get(gl, j));
gwlist_destroy(gl, NULL);
} else
mGrp_destroy(val);
}
list_destroy(l, (list_item_destructor_t *)octstr_destroy);
gwlist_destroy(l, (gwlist_item_destructor_t *)octstr_destroy);
dict_destroy(cfg->grps);
octstr_destroy(cfg->file);
if (cfg->xcfg && cfg->cfg_funcs &&
cfg->cfg_funcs->destroy)
cfg->cfg_funcs->destroy(cfg->xcfg);
gw_free(cfg);
}
@ -248,46 +306,94 @@ mCfgGrp *mms_cfg_get_single(mCfg *cfg, Octstr *name)
gw_assert(name);
gw_assert(is_multigroup(name) == 0);
return dict_get(cfg->grps, name);
if (cfg->xcfg == NULL)
return dict_get(cfg->grps, name);
else
return cfg->cfg_funcs->cfg_get_single(cfg->xcfg, name);
}
List *mms_cfg_get_multi(mCfg *cfg, Octstr *name)
{
List *l = NULL, *r;
int i;
gw_assert(name);
gw_assert(is_multigroup(name) == 1);
r = dict_get(cfg->grps, name);
if (r)
for (i = 0, l = list_create(); i < list_len(r); i++)
list_append(l, list_get(r,i));
return l;
if (cfg->xcfg == NULL) {
List *l = NULL, *r;
int i;
r = dict_get(cfg->grps, name);
if (r)
for (i = 0, l = gwlist_create(); i < gwlist_len(r); i++)
gwlist_append(l, gwlist_get(r,i));
return l;
} else
return cfg->cfg_funcs->get_multi(cfg->xcfg, name);
}
Octstr *mms_cfg_get(mCfgGrp *grp, Octstr *name)
void mms_cfg_destroy_grp(mCfg *cfg, mCfgGrp *grp)
{
gw_assert(cfg);
if (cfg->xcfg == NULL || cfg->cfg_funcs == NULL || cfg->cfg_funcs->destroy_grp == NULL)
return;
else
cfg->cfg_funcs->destroy_grp(cfg->xcfg, grp);
}
mCfgGrp *mms_get_multi_by_field(mCfg *cfg, Octstr *name, Octstr *field, Octstr *value)
{
gw_assert(name);
gw_assert(is_multigroup(name) == 1);
if (!valid_in_group(name, field))
panic(0, "Request for invalid field/variable `%s' in group `%s', unexpected!",
octstr_get_cstr(field), octstr_get_cstr(name));
if (cfg->xcfg == NULL) {
mCfgGrp *grp;
Octstr *val;
List *r;
int i;
r = dict_get(cfg->grps, name);
if (r)
for (i = 0; i < gwlist_len(r); i++)
if ((grp = gwlist_get(r, i)) != NULL &&
(val = dict_get(grp->fields, field)) != NULL &&
octstr_compare(val, value) == 0)
return grp;
return NULL;
} else
return cfg->cfg_funcs->get_multi_by_field(cfg->xcfg, name, field, value);
}
Octstr *mms_cfg_get(mCfg *cfg, mCfgGrp *grp, Octstr *name)
{
Octstr *val;
gw_assert(grp);
if (!valid_in_group(grp->name, name))
Octstr *grp_name = cfg->xcfg ? cfg->cfg_funcs->get_grp_name(cfg->xcfg, grp) :
octstr_duplicate(grp->name);
if (!valid_in_group(grp_name, name))
panic(0, "Request for invalid field/variable `%s' in group `%s', unexpected!",
octstr_get_cstr(name), octstr_get_cstr(grp->name));
octstr_get_cstr(name), octstr_get_cstr(grp_name));
val = dict_get(grp->fields, name);
if (!val)
return NULL;
else
return octstr_duplicate(val);
octstr_destroy(grp_name);
if (cfg->xcfg == NULL) {
gw_assert(grp);
val = dict_get(grp->fields, name);
val = octstr_duplicate(val);
} else {
val = cfg->cfg_funcs->get(cfg->xcfg, grp, name);
if (val)
fixup_value(val, 0);
}
return val;
}
int mms_cfg_get_int(mCfgGrp *grp, Octstr *name, long *n)
int mms_cfg_get_int(mCfg *cfg, mCfgGrp *grp, Octstr *name, long *n)
{
Octstr *val = mms_cfg_get(grp, name);
Octstr *val = mms_cfg_get(cfg, grp, name);
int ret;
if (!val)
return -1;
@ -297,24 +403,28 @@ int mms_cfg_get_int(mCfgGrp *grp, Octstr *name, long *n)
}
int mms_cfg_get_bool(mCfgGrp *grp, Octstr *name, int *bool)
int mms_cfg_get_bool(mCfg *cfg, mCfgGrp *grp, Octstr *name, int *bool)
{
Octstr *val = mms_cfg_get(grp, name);
Octstr *val = mms_cfg_get(cfg, grp, name);
int ret = 0;
if (!val)
return -1;
if (octstr_case_compare(val, octstr_imm("yes")) == 0 ||
octstr_case_compare(val, octstr_imm("true")) == 0 ||
octstr_case_compare(val, octstr_imm("1")) == 0)
if (octstr_str_case_compare(val, "yes") == 0 ||
octstr_str_case_compare(val, "true") == 0 ||
octstr_str_case_compare(val, "1") == 0)
*bool = 1;
else if (octstr_case_compare(val, octstr_imm("no")) == 0 ||
octstr_case_compare(val, octstr_imm("false")) == 0 ||
octstr_case_compare(val, octstr_imm("0")) == 0)
else if (octstr_str_case_compare(val, "no") == 0 ||
octstr_str_case_compare(val, "false") == 0 ||
octstr_str_case_compare(val, "0") == 0)
*bool = 0;
else {
error(0, "Unable to convert value `%s' to boolean for field `%s' in group `%s'",
octstr_get_cstr(val), octstr_get_cstr(name), octstr_get_cstr(grp->name));
Octstr *grp_name = cfg->xcfg ? cfg->cfg_funcs->get_grp_name(cfg->xcfg, grp) :
octstr_duplicate(grp->name);
mms_error(0, "mms_cfg", NULL, "Unable to convert value `%s' to boolean for field `%s' in group `%s'",
octstr_get_cstr(val), octstr_get_cstr(name), octstr_get_cstr(grp_name));
octstr_destroy(grp_name);
ret = -1;
}
@ -322,9 +432,9 @@ int mms_cfg_get_bool(mCfgGrp *grp, Octstr *name, int *bool)
return ret;
}
List *mms_cfg_get_list(mCfgGrp *grp, Octstr *name)
List *mms_cfg_get_list(mCfg *cfg, mCfgGrp *grp, Octstr *name)
{
Octstr *val = mms_cfg_get(grp, name);
Octstr *val = mms_cfg_get(cfg, grp, name);
List *l;
if (val == NULL)

View File

@ -3,7 +3,7 @@
*
* MMS Config structure definitions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 20058 Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -23,6 +23,16 @@
#error MULTI_GROUP not defined.
#endif
/* config-source: If it exists, the rest of the conf file is
* ignored. Instead, use the provided lib as the reader of the
* config info. (See mms_cfg-impl.h for details)
*/
SINGLE_GROUP(config-source,
OCTSTR(config-library)
OCTSTR(config-library-init-param)
)
SINGLE_GROUP(core,
OCTSTR(log-file)
OCTSTR(log-level)
@ -36,22 +46,28 @@ SINGLE_GROUP(core,
OCTSTR(ssl-server-cert-file)
OCTSTR(ssl-server-key-file)
OCTSTR(ssl-trusted-ca-file)
OCTSTR(http-interface-name)
)
SINGLE_GROUP(mbuni,
OCTSTR(name)
OCTSTR(hostname)
OCTSTR(host-alias)
OCTSTR(local-mmsc-domains)
OCTSTR(local-prefixes)
OCTSTR(storage-directory)
OCTSTR(queue-manager-module)
OCTSTR(queue-module-init-data)
OCTSTR(max-send-threads)
OCTSTR(send-mail-prog)
OCTSTR(unified-prefix)
OCTSTR(strip-prefixes)
OCTSTR(maximum-send-attempts)
OCTSTR(mm1-maximum-notify-attempts)
OCTSTR(mmsbox-maximum-request-attempts)
OCTSTR(default-message-expiry)
OCTSTR(max-message-expiry)
OCTSTR(queue-run-interval)
OCTSTR(mm1-queue-run-interval)
OCTSTR(send-attempt-back-off)
OCTSTR(sendsms-url)
OCTSTR(sendsms-username)
@ -59,6 +75,7 @@ SINGLE_GROUP(mbuni,
OCTSTR(sendsms-global-sender)
OCTSTR(mms-port)
OCTSTR(mm7-port)
OCTSTR(mm4-port)
OCTSTR(allow-ip)
OCTSTR(deny-ip)
OCTSTR(email2mms-relay-hosts)
@ -73,18 +90,40 @@ SINGLE_GROUP(mbuni,
OCTSTR(notify-unprovisioned)
OCTSTR(mms-notify-text)
OCTSTR(mms-notify-unprovisioned-text)
OCTSTR(mm-box-host)
OCTSTR(mms-to-email-txt)
OCTSTR(mms-to-email-html)
OCTSTR(mms-to-email-default-subject)
OCTSTR(mms-message-too-large-txt)
OCTSTR(mms-client-msisdn-header)
OCTSTR(mms-client-ip-header)
OCTSTR(allow-ip-type)
OCTSTR(optimize-notification-size)
OCTSTR(content-adaptation)
OCTSTR(send-dlr-on-fetch)
OCTSTR(sendmms-port)
OCTSTR(sendmms-port-ssl)
OCTSTR(mmsbox-mt-filter-library)
OCTSTR(mmsbox-mt-always-multipart)
OCTSTR(mmsbox-admin-port)
OCTSTR(mmsc-admin-port)
OCTSTR(admin-port-ssl)
OCTSTR(admin-password)
OCTSTR(admin-allow-ip)
OCTSTR(admin-deny-ip)
OCTSTR(event-logger-module)
OCTSTR(event-logger-module-parameters)
OCTSTR(mm5-module)
OCTSTR(mm5-module-parameters)
OCTSTR(mmsbox-cdr-module)
OCTSTR(mmsbox-cdr-module-parameters)
OCTSTR(mmsc-services)
OCTSTR(smtp-relay)
)
MULTI_GROUP(mmsproxy,
@ -92,19 +131,27 @@ MULTI_GROUP(mmsproxy,
OCTSTR(host)
OCTSTR(allowed-prefix)
OCTSTR(denied-prefix)
OCTSTR(send-mail-prog)
OCTSTR(confirmed-delivery)
OCTSTR(unified-prefix)
OCTSTR(strip-prefixes)
)
MULTI_GROUP(mms-vasp,
OCTSTR(vasp-id)
OCTSTR(type)
OCTSTR(mm7-version)
OCTSTR(mm7-soap-xmlns)
OCTSTR(use-mm7-soap-namespace-prefix)
OCTSTR(short-code)
OCTSTR(short-codes)
OCTSTR(vasp-username)
OCTSTR(vasp-password)
OCTSTR(vasp-url)
OCTSTR(mms-to-email-handler)
OCTSTR(mms-to-local-copy-handler)
OCTSTR(mmsc-username)
OCTSTR(mmsc-password)
OCTSTR(mms-to-local-copy-handler)
OCTSTR(send-uaprof)
OCTSTR(throughput)
)
MULTI_GROUP(send-mms-user,
@ -113,10 +160,13 @@ MULTI_GROUP(send-mms-user,
OCTSTR(faked-sender)
OCTSTR(delivery-report-url)
OCTSTR(read-report-url)
OCTSTR(mmsc)
)
MULTI_GROUP(mmsc,
OCTSTR(id)
OCTSTR(group-id)
OCTSTR(vasp-id)
OCTSTR(mmsc-url)
OCTSTR(incoming-username)
OCTSTR(incoming-password)
@ -125,9 +175,40 @@ MULTI_GROUP(mmsc,
OCTSTR(deny-ip)
OCTSTR(allowed-prefix)
OCTSTR(denied-prefix)
OCTSTR(denied-sender-prefix)
OCTSTR(allowed-sender-prefix)
OCTSTR(incoming-port-ssl)
OCTSTR(max-throughput)
OCTSTR(type)
OCTSTR(allow-adaptations)
OCTSTR(mm7-version)
OCTSTR(mm7-soap-xmlns)
OCTSTR(use-mm7-soap-namespace-prefix)
OCTSTR(mm7-mt-filter-params)
OCTSTR(reroute)
OCTSTR(reroute-mmsc-id)
OCTSTR(reroute-add-sender-to-subject)
OCTSTR(mmsc-library)
OCTSTR(custom-settings)
OCTSTR(no-sender-address)
OCTSTR(default-vasid)
OCTSTR(maximum-request-size)
OCTSTR(strip-domain)
OCTSTR(max-recipients)
OCTSTR(strip-prefixes)
OCTSTR(retry-statuses)
OCTSTR(mm1-http-proxy)
OCTSTR(mm1-gprs-on-command)
OCTSTR(mm1-gprs-off-command)
OCTSTR(mm1-gprs-pid-command)
OCTSTR(mm1-sms-on-command)
OCTSTR(mm1-sms-off-command)
OCTSTR(mm1-msisdn)
OCTSTR(mm1-ua-string)
OCTSTR(carrier-id-header)
)
MULTI_GROUP(mms-service,
@ -140,13 +221,19 @@ MULTI_GROUP(mms-service,
OCTSTR(faked-sender)
OCTSTR(catch-all)
OCTSTR(omit-empty)
OCTSTR(suppress-reply)
OCTSTR(accept-x-mbuni-headers)
OCTSTR(pass-thro-headers)
OCTSTR(assume-plain-text)
OCTSTR(accepted-mmscs)
OCTSTR(denied-mmscs)
OCTSTR(denied-receiver-prefix)
OCTSTR(allowed-receiver-prefix)
OCTSTR(keyword)
OCTSTR(aliases)
OCTSTR(http-post-parameters)
OCTSTR(service-code)
OCTSTR(extra-reply-content-header)
)
#undef OCTSTR
#undef SINGLE_GROUP

View File

@ -3,7 +3,7 @@
*
* config file functions
*
* Copyright (C) 2003 - 2006, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -16,15 +16,18 @@
#include "gwlib/gwlib.h"
#include "gwlib/mime.h"
#include "config.h"
#include "mbuni-config.h"
typedef struct mCfg mCfg; /* config file structure. */
typedef struct mCfgGrp mCfgGrp; /* A config group. */
struct mCfgImpFuncs; /* Defined in mms_cfg-impl.h */
/* Read a config file, return the structure. */
mCfg *mms_cfg_read(Octstr *file);
/* Read conf from a module */
mCfg *mms_cfg_read2(struct mCfgImpFuncs *cfgfuncs, Octstr *init);
/* Destroy it all . */
void mms_cfg_destroy(mCfg *cfg);
@ -34,22 +37,29 @@ mCfgGrp *mms_cfg_get_single(mCfg *cfg, Octstr *name);
/* Get a multiple groups all of same name. */
List *mms_cfg_get_multi(mCfg *cfg,Octstr *name);
mCfgGrp *mms_get_multi_by_field(mCfg *cfg, Octstr *name, Octstr *field, Octstr *value);
/* Destroy a group object after user -- call this to cleanup memory used by group object
* always!
*/
void mms_cfg_destroy_grp(mCfg *, mCfgGrp *);
/* Get a string field value from a group. */
Octstr *mms_cfg_get(mCfgGrp *grp, Octstr *name);
Octstr *mms_cfg_get(mCfg *cfg, mCfgGrp *grp, Octstr *name);
/* Get an integer field value from a group.
* returns 0 on success, -1 on error.
*/
int mms_cfg_get_int(mCfgGrp *grp, Octstr *name, long *n);
int mms_cfg_get_int(mCfg *cfg, mCfgGrp *grp, Octstr *name, long *n);
/* Get a boolean field value from a group.
* returns 0 on success, -1 on error
*/
int mms_cfg_get_bool(mCfgGrp *grp, Octstr *name, int *bool);
int mms_cfg_get_bool(mCfg *cfg, mCfgGrp *grp, Octstr *name, int *val);
/* Get a field value from a group. */
List *mms_cfg_get_list(mCfgGrp *grp, Octstr *name);
List *mms_cfg_get_list(mCfg *cfg, mCfgGrp *grp, Octstr *name);
#endif

View File

@ -0,0 +1,147 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Event logger module
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include "mms_eventlogger.h"
#include "mms_util.h"
static Octstr *shell_cmd;
/* So that below compiles fine. */
#undef error
#undef warning
#undef info
static void default_logger(enum mbuni_event_type_t type, const char *subtype, int err, const char *file,
int line,
const char *function,
const char *interface, Octstr *id,
Octstr *msg)
{
void (*f)(int, const char *,...);
switch(type) {
case MBUNI_INFO:
f = info;
break;
case MBUNI_WARNING:
f = warning;
break;
default: /* including error. */
f = error;
break;
}
f(err, "%s:%d <%s> [%s] [%s] %s",
file, line, function,
interface ? interface : "n/a",
id ? octstr_get_cstr(id) : "n/a",
octstr_get_cstr(msg));
}
static void shell_logger(enum mbuni_event_type_t type, const char *subtype, int err, const char *file,
int line, const char *function,
const char *interface, Octstr *id,
Octstr *msg)
{
char *xtype;
Octstr *cmd, *xid = octstr_duplicate(id);
gw_assert(shell_cmd);
switch(type) {
case MBUNI_INFO:
xtype = "INFO";
break;
case MBUNI_WARNING:
xtype = "WARNING";
break;
default: /* including error. */
xtype = "ERROR";
break;
}
escape_shell_chars(msg);
escape_shell_chars(id);
cmd = octstr_format("%S '%s' '%s' %d '%s' '%s' %d '%S' '%S'",
shell_cmd, xtype, subtype ? subtype : "", err, interface ? interface : "", file, line, xid ? xid : octstr_imm(""), msg);
system(octstr_get_cstr(cmd));
octstr_destroy(cmd);
octstr_destroy(xid);
}
static int init_default_logger(Octstr *param)
{
return 0;
}
static int init_shell_logger(Octstr *cmd)
{
shell_cmd = octstr_duplicate(cmd);
return 0;
}
static int cleanup_shell_logger(void)
{
octstr_destroy(shell_cmd);
shell_cmd = NULL;
return 0;
}
static MmsEventLoggerFuncs default_handler = {init_default_logger, default_logger}, *log_handler = &default_handler;
MmsEventLoggerFuncs shell_event_logger = {
init_shell_logger,
shell_logger,
cleanup_shell_logger
};
int mms_event_logger_init(MmsEventLoggerFuncs *funcs, Octstr *init_param)
{
if (funcs && (funcs->init == NULL ||
funcs->init(init_param) == 0)) {
log_handler = funcs;
return 0;
}
return -1;
}
extern void mms_event_logger(enum mbuni_event_type_t type, const char *subtype, int err, const char *file,
int line, const char *function, char *interface, Octstr *id,
char *fmt,...)
{
Octstr *x;
va_list ap;
va_start(ap, fmt);
x = octstr_format_valist(fmt, ap);
va_end(ap);
log_handler->log_event(type,subtype, err, file, line, function, interface, id, x);
octstr_destroy(x);
}
void mms_event_logger_cleanup(void)
{
if (log_handler->cleanup)
log_handler->cleanup();
}

View File

@ -0,0 +1,59 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Event logger module
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMS_EVENTLOGGER__INCLUDED__
#define __MMS_EVENTLOGGER__INCLUDED__
#include <stdarg.h>
#include "gwlib/gwlib.h"
typedef enum mbuni_event_type_t {MBUNI_ERROR, MBUNI_INFO, MBUNI_WARNING} mbuni_event_type_t;
typedef struct MmsEventLoggerFuncs {
int (*init)(Octstr *init_param);
void (*log_event)(enum mbuni_event_type_t type, const char *subtype, int err, const char *file,
int line,
const char *function,
const char *interface, Octstr *id,
Octstr *msg);
int (*cleanup)(void);
} MmsEventLoggerFuncs;
/* A module should expose a module of the above type with name: logger */
extern int mms_event_logger_init(MmsEventLoggerFuncs *funcs, Octstr *init_param);
/* logger function:
* - interface is one of MM1, MM4, etc.
* - id is an id for the interface element (e.g. mmsc id)
*/
extern void mms_event_logger_cleanup(void);
extern void mms_event_logger(enum mbuni_event_type_t type, const char *subtype,
int err, const char *file,
int line, const char *function,
char *interface, Octstr *id,
char *fmt,...);
#define mms_error(err,intf,id,fmt,...) mms_event_logger(MBUNI_ERROR, NULL, (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
#define mms_info(err,intf,id,fmt,...) mms_event_logger(MBUNI_INFO, NULL, (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
#define mms_warning(err,intf,id,fmt,...) mms_event_logger(MBUNI_WARNING, NULL, (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
#define mms_error_ex(subtype,err,intf,id,fmt,...) mms_event_logger(MBUNI_ERROR, (subtype), (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
#define mms_info_ex(subtype,err,intf,id,fmt,...) mms_event_logger(MBUNI_INFO, (subtype), (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
#define mms_warning_ex(subtype,err,intf,id,fmt,...) mms_event_logger(MBUNI_WARNING, (subtype), (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
extern MmsEventLoggerFuncs shell_event_logger; /* For logging using a shell command. */
/* Stop all from using gwlib info, error and warning functions */
#define error use_mms_error_instead
#define warning use_mms_warning_instead
#define info use_mms_info_instead
#endif

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* MM7/SOAP message encoder/decoder and helper functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -16,17 +16,34 @@
#define MM7_SOAP_OK 1000
#define MM7_SOAP_FORMAT_CORRUPT 2007
#define MM7_SOAP_COMMAND_REJECTED 3005
#define MM7_SOAP_UNSUPPORTED_OPERATION 4003
#define MM7_SOAP_STATUS_OK(e) ((e) / 1000 == 1)
#define MM7_DEFAULT_VERSION "5.3.0"
#define MM7_SOAP_STATUS_OK(e) (((e) / 1000) == 1)
#define MM7_SOAP_CLIENT_ERROR(e) (((e) / 1000) == 2)
#if 0
#define MM7_DEFAULT_VERSION MMS_3GPP_VERSION
#define MM7_VERSION "5.3.0"
#endif
#define DEFAULT_MM7_VERSION MAKE_VERSION(5,3,0)
typedef struct MSoapMsg_t MSoapMsg_t;
typedef struct MM7Version_t {
int major, minor1, minor2; /* e.g. 5.1.0. */
int use_mm7_namespace; /* whether to put in the namespace prefix. */
char xmlns[128];
} MM7Version_t;
/* Parse SOAP message given http headers and body. */
extern MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body);
/* Convert message type to mm7 type code */
extern int mm7_msgtype_to_soaptype(int mtype, int isclientside);
/* Convert SOAP message to http headers and body. */
extern int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, List **hdrs, Octstr **body);
extern int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, MM7Version_t *ver, List **hdrs, Octstr **body);
/* Convert SOAP message to an MMS message. */
extern MmsMsg *mm7_soap_to_mmsmsg(MSoapMsg_t *m, Octstr *from);
@ -44,7 +61,9 @@ extern int mm7_get_envelope(MSoapMsg_t *m, Octstr **sender,
List **to, Octstr **subject,
Octstr **vasid,
time_t *expiry_t,
time_t *delivery_t);
time_t *delivery_t,
Octstr **uaprof,
time_t *uaprof_tstamp);
/* Delete the thingie... */
extern void mm7_soap_destroy(MSoapMsg_t *m);
@ -54,8 +73,14 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
Octstr *transid, Octstr *srvcode,
Octstr *linkedid,
int isclientside,
char *vaspid, char *vasid);
MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid);
char *vaspid, char *vasid,
Octstr *uaprof,
time_t uaprof_tstamp,
List *extra_hdrs);
MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid, int isclientside);
/* Return the header value for some header. */
Octstr *mm7_soap_header_value(MSoapMsg_t *m, Octstr *header);
/* Return (a copy of) all the headers */
List *mm7_soap_headers(MSoapMsg_t *m);
#endif

View File

@ -3,7 +3,7 @@
*
* Mbuni MMBox implementation
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -12,6 +12,7 @@
*/
#include <sys/file.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@ -91,7 +92,7 @@ static Octstr *user_mmbox_dir(char *mmbox_root, char *userid)
if (mkdir(fbuf,
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST) {
error(0, "mmbox: failed to create dir [%s] "
mms_error(0, "mmbox", NULL, "Failed to create dir [%s] "
"while initialising mmbox for %s: %s!",
fbuf, userid, strerror(errno));
return NULL;
@ -105,7 +106,7 @@ static Octstr *user_mmbox_dir(char *mmbox_root, char *userid)
if (mkdir(octstr_get_cstr(s),
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST) {
error(0, "mmbox: failed to create dir [%s] "
mms_error(0, "mmbox", NULL, "Failed to create dir [%s] "
"while initialising mmbox for %s: %s!",
octstr_get_cstr(s), userid, strerror(errno));
octstr_destroy(s);
@ -139,7 +140,7 @@ static int mkdf(char df[64], char *mmbox_home)
if (mkdir(octstr_get_cstr(tmp),
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST) {
error(0, "mmbox.mkdf: failed to create dir [%s] "
mms_error(0, "mmbox", NULL, "failed to create dir [%s] "
" in mmbox home %s: %s!",
octstr_get_cstr(tmp), mmbox_home, strerror(errno));
octstr_destroy(tmp);
@ -158,7 +159,7 @@ static int mkdf(char df[64], char *mmbox_home)
if (mkdir(octstr_get_cstr(tmp),
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST) {
error(0, "mmbox.mkdf: failed to create dir [%s] "
mms_error(0, "mmbox", NULL, "Failed to create dir [%s] "
" in mmbox home %s: %s!",
octstr_get_cstr(tmp), mmbox_home, strerror(errno));
octstr_destroy(tmp);
@ -177,7 +178,7 @@ static int mkdf(char df[64], char *mmbox_home)
if (fd >= 0 &&
mm_lockfile(fd,ctmp,1) != 0) {
unlink(ctmp);
close(fd);
unlock_and_close(fd);
fd = -1;
}
octstr_destroy(tmp);
@ -197,11 +198,11 @@ static int open_mmbox_index(char *mmbox_dir, int shouldblock)
i = 0;
do
if ((fd = open(fbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)) < 0) {
error(0, "Failed to open mmbox index file [%s], error: %s!",
mms_error(0, "mmbox", NULL, "Failed to open mmbox index file [%s], error: %s!",
fbuf, strerror(errno));
break;
} else if (mm_lockfile(fd, fbuf, shouldblock) != 0) {
close(fd);
unlock_and_close(fd);
fd = -1;
}
while (i++ < MAXTRIES && fd < 0);
@ -215,8 +216,8 @@ static Octstr *linearise_string_list(List *l, char *sep)
Octstr *s = octstr_create("");
for (i = 0, n = list_len(l); i < n; i++) {
Octstr *p = list_get(l,i);
for (i = 0, n = gwlist_len(l); i < n; i++) {
Octstr *p = gwlist_get(l,i);
if (p)
octstr_format_append(s, "%s%S", (i == 0) ? "" : sep, p);
}
@ -227,10 +228,10 @@ static List *parse_string_list(char *buf)
{
int i = 0;
char sbuf[128], *p = buf;
List *l = list_create();
List *l = gwlist_create();
while (sscanf(p, "%s%n", sbuf, &i) > 0) {
list_append(l, octstr_create(sbuf));
gwlist_append(l, octstr_create(sbuf));
p += i;
}
@ -263,15 +264,15 @@ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd,
tempfd = open(fbuf,
O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
if (tempfd < 0 ) {
error(0, "mmbox.update_index: Failed to open temp file %s: error = %s\n",
mms_error(0, "mmbox", NULL,"Failed to open temp file %s: error = %s\n",
fbuf, strerror(errno));
goto done;
} else if (mm_lockfile(tempfd, fbuf, 0) != 0) { /* Lock it. */
error(0, "mmbox.update_index: Failed lock temp file %s: error = %s\n",
mms_error(0, "mmbox", NULL,"Failed lock temp file %s: error = %s\n",
fbuf, strerror(errno));
close(tempfd);
unlock_and_close(tempfd);
tempfd = -1;
goto done;
@ -279,11 +280,11 @@ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd,
fp = fdopen(fd, "r");
if (!fp) {
error(0, "mmbox.update_index: Failed fdopen on tempfd, file %s: error = %s\n",
mms_error(0, "mmbox", NULL,"Failed fdopen on tempfd, file %s: error = %s\n",
fbuf, strerror(errno));
close(tempfd);
unlock_and_close(tempfd);
tempfd = -1;
goto done;
}
@ -341,19 +342,19 @@ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd,
static List *make_mm_flags(List *oflags, List *flag_cmds)
{
List *l = oflags ? oflags : list_create();
List *l = oflags ? oflags : gwlist_create();
int i, n;
for (i = 0, n = list_len(l); i < n; i++) { /* cleanup list. */
Octstr *x = list_get(l,i);
for (i = 0, n = gwlist_len(l); i < n; i++) { /* cleanup list. */
Octstr *x = gwlist_get(l,i);
int ch = octstr_get_char(x, 0);
if (ch == '+' || ch == '-' || ch == '/')
octstr_delete(x,0,1);
}
for (i = 0, n = (flag_cmds ? list_len(flag_cmds) : 0); i<n; i++) {
Octstr *x = list_get(flag_cmds,i);
for (i = 0, n = (flag_cmds ? gwlist_len(flag_cmds) : 0); i<n; i++) {
Octstr *x = gwlist_get(flag_cmds,i);
int ch = octstr_get_char(x, 0);
char *s = octstr_get_cstr(x);
int j, m, cmd;
@ -365,17 +366,17 @@ static List *make_mm_flags(List *oflags, List *flag_cmds)
cmd = '+';
/* Find it in original. If existent, remove it. */
for (j = 0, m = list_len(l); j < m; j++)
if (octstr_str_compare(list_get(l,j),s) == 0) {
Octstr *y = list_get(l,j);
list_delete(l,j,1);
for (j = 0, m = gwlist_len(l); j < m; j++)
if (octstr_str_compare(gwlist_get(l,j),s) == 0) {
Octstr *y = gwlist_get(l,j);
gwlist_delete(l,j,1);
octstr_destroy(y);
j--;
m--;
}
if (cmd == '+' || cmd == '/')
list_append(l, octstr_create(s));
gwlist_append(l, octstr_create(s));
}
@ -400,7 +401,7 @@ Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, List *flag_c
goto done;
if ((dfd = mkdf(df, octstr_get_cstr(home))) < 0) {
error(0, "mmbox_add: failed to create data file, home=%s - %s!",
mms_error(0, "mmbox", NULL, "failed to create data file, home=%s - %s!",
octstr_get_cstr(home), strerror(errno));
goto done;
}
@ -433,18 +434,14 @@ Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, List *flag_c
octstr_replace(sdf, octstr_imm("/"), octstr_imm("-"));
done:
if (dfd > 0)
close(dfd);
unlock_and_close(dfd);
if (ifd > 0)
close(ifd);
unlock_and_close(ifd);
if (s)
octstr_destroy(s);
if (home)
octstr_destroy(home);
if (state)
octstr_destroy(state);
if (flags)
list_destroy(flags, (list_item_destructor_t *)octstr_destroy);
octstr_destroy(s);
octstr_destroy(home);
octstr_destroy(state);
gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy);
return sdf;
}
@ -478,7 +475,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref,
s = octstr_read_file(octstr_get_cstr(fname));
if ( s == NULL || octstr_len(s) == 0) {
error(0, "mmbox.mod: failed to read data file [%s] - %s!",
mms_error(0, "mmbox", NULL, "Failed to read data file [%s] - %s!",
octstr_get_cstr(fname), strerror(errno));
goto done;
}
@ -486,7 +483,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref,
m = mms_frombinary(s, octstr_imm("anon@anon"));
if (!m) {
error(0, "mmbox.mod: failed to read data file [%s]!",
mms_error(0, "mmbox", NULL, "Failed to read data file [%s]!",
octstr_get_cstr(fname));
goto done;
}
@ -519,7 +516,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref,
if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_MOD, sdf, nstate, flags, msize)) < 0) {
/* Not good, we wrote but could not update the index file. scream. */
error(0, "mmbox.mod: failed to update index file, home is %s!",
mms_error(0, "mmbox", NULL, "Failed to update index file, home is %s!",
octstr_get_cstr(home));
goto done;
}
@ -546,7 +543,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref,
if (nstate)
octstr_destroy(nstate);
if (flags)
list_destroy(flags, (list_item_destructor_t *)octstr_destroy);
gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy);
if (m)
mms_destroy(m);
return res;
@ -577,7 +574,7 @@ int mms_mmbox_delmsg(char *mmbox_root, char *user, Octstr *msgref)
if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_DEL, sdf, NULL, NULL,0)) < 0) {
error(0, "mmbox.del: failed to update index file, home is %s!",
mms_error(0, "mmbox", NULL,"Failed to update index file, home is %s!",
octstr_get_cstr(home));
goto done;
}
@ -604,8 +601,8 @@ static int string_in_list(Octstr *s, List *l)
{
int i, n;
for (i = 0, n = list_len(l); i<n; i++) {
Octstr *x = list_get(l,i);
for (i = 0, n = gwlist_len(l); i<n; i++) {
Octstr *x = gwlist_get(l,i);
char *p = octstr_get_cstr(x);
if (p[0] == '+' ||
@ -653,51 +650,51 @@ List *mms_mmbox_search(char *mmbox_root, char *user,
if ((tmpfd = dup(ifd)) < 0 ||
(fp = fdopen(tmpfd, "r")) == NULL) {
error(0, "mmbox.search_index: %s Failed to dup descriptor for index "
"file, fp = %d: error = %s\n", octstr_get_cstr(home),
(int)fp, strerror(errno));
mms_error(0, "mmbox", NULL, "%s Failed to dup descriptor for index "
"file, fp = %p: error = %s\n", octstr_get_cstr(home),
fp, strerror(errno));
goto done;
}
flags = make_mm_flags(NULL, flag_cmds);
ct = 1;
dflist = list_create();
dflist = gwlist_create();
while (fgets(linbuf, sizeof linbuf, fp) != NULL) {
char idx[128], xstate[32];
List *xflags = NULL;
int i, size;
int match = (!state && (!msgrefs || list_len(msgrefs) == 0) && (!xflags || list_len(xflags) == 0));
int match = (!state && (!msgrefs || gwlist_len(msgrefs) == 0) && (!xflags || gwlist_len(xflags) == 0));
sscanf(linbuf, "%s %s %d%n", idx, xstate, &size, &i);
/* search: by id list if given, by states if given, by flags if given */
if (!match && state && list_search(state, xstate,
(list_item_matches_t *)_x_octstr_str_compare) != NULL)
if (!match && state && gwlist_search(state, xstate,
(gwlist_item_matches_t *)_x_octstr_str_compare) != NULL)
match = 1;
/* For the rest we only match if nothing else matched. Save time */
replace_slash(idx);
if (!match && msgrefs &&
list_search(msgrefs, idx,
(list_item_matches_t *)_x_octstr_str_compare) != NULL)
gwlist_search(msgrefs, idx,
(gwlist_item_matches_t *)_x_octstr_str_compare) != NULL)
match = 1;
if (!match &&
flag_cmds &&
((xflags = parse_string_list(linbuf + i)) != NULL &&
list_search(xflags, flags, (list_item_matches_t *)string_in_list) != NULL))
gwlist_search(xflags, flags, (gwlist_item_matches_t *)string_in_list) != NULL))
match = 1;
if (match && ct >= start && list_len(dflist) <= limit) {
if (match && ct >= start && gwlist_len(dflist) <= limit) {
Octstr *x = octstr_create(idx);
/* octstr_replace(x, octstr_imm("/"), octstr_imm("-")); */
list_append(dflist, x);
gwlist_append(dflist, x);
}
ct++;
if (xflags)
list_destroy(xflags, (list_item_destructor_t *)octstr_destroy);
gwlist_destroy(xflags, (gwlist_item_destructor_t *)octstr_destroy);
}
done:
@ -710,7 +707,7 @@ List *mms_mmbox_search(char *mmbox_root, char *user,
close(ifd);
if (flags)
list_destroy(flags, (list_item_destructor_t *)octstr_destroy);
gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy);
if (home)
octstr_destroy(home);
@ -779,9 +776,9 @@ int mms_mmbox_count(char *mmbox_root, char *user, unsigned long *msgcount, unsi
if ((tmpfd = dup(ifd)) < 0 ||
(fp = fdopen(tmpfd, "r")) == NULL) {
error(0, "mmbox.count: %s Failed to dup descriptor for index "
"file, fp = %d: error = %s\n", octstr_get_cstr(home),
(int)fp, strerror(errno));
mms_error(0, "mmbox", NULL, "%s Failed to dup descriptor for index "
"file, fp = %p: error = %s\n", octstr_get_cstr(home),
fp, strerror(errno));
goto done;
}

View File

@ -3,7 +3,7 @@
*
* Mbuni MMBox implementation
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* MMS message encoder/decoder and helper functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -24,7 +24,9 @@ typedef struct MmsMsg MmsMsg; /* Opaque type. */
typedef MmsMsg *MmsMsgGetFunc_t(void *p1, void *p2, Octstr *msgref, unsigned long *msize);
extern int mms_validate_address(Octstr *s);
enum AddressType_t {MMS_UNKNOWN_ADDRESS=-1, MMS_EMAIL_ADDRESS, MMS_IPV4_ADDRESS, MMS_IPV6_ADDRESS, MMS_NUMBER_ADDRESS};
extern int mms_validate_address_real(Octstr *s, enum AddressType_t *address_type);
#define mms_validate_address(s) mms_validate_address_real((s), NULL)
/*
* mms_frombinary: Parse MMS binary representation, return a Message or NULL.
@ -32,7 +34,9 @@ extern int mms_validate_address(Octstr *s);
* Takes from param which is put in if insert-address is requested.
* NOTE: function may modify 'msg' argument as it parses.
*/
extern MmsMsg *mms_frombinary(Octstr *msg, Octstr *from);
extern MmsMsg *mms_frombinary_ex(Octstr *msg, Octstr *from, char *unified_prefix, List *strip_prefixes);
#define mms_frombinary(msg, from) mms_frombinary_ex((msg), (from), NULL, NULL)
/*
* mms_tobinary: Return binary encoded Mms message
@ -57,7 +61,8 @@ extern void mms_msgdump(MmsMsg *m, int headers_only);
extern void mms_destroy(MmsMsg *msg);
/* Make a delivery report message. */
extern MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *to, time_t date, Octstr *status);
extern MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *from,
Octstr *to, time_t date, Octstr *status);
MmsMsg *mms_readreport(Octstr *msgid, Octstr *from, Octstr *to, time_t date, Octstr *status);
@ -65,14 +70,17 @@ MmsMsg *mms_readreport(Octstr *msgid, Octstr *from, Octstr *to, time_t date, Oct
extern List *mms_message_headers(MmsMsg *msg);
/* Make a notification message out of this one and the url given. */
extern MmsMsg *mms_notification(MmsMsg *msg, unsigned int msize,
extern MmsMsg *mms_notification(Octstr *from, Octstr *subject,
Octstr *mclass, unsigned int msize,
Octstr *url,
Octstr *transactionid, time_t expiryt, int optimizesize);
MmsMsg *mms_notifyresp_ind(char *transid, int menc, char *status, int report_allowed);
MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid, char *err, char *errtxt, Octstr *opt_from, int menc);
int mms_remove_headers(MmsMsg *m, char *name);
MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward, int menc);
Octstr *mms_get_header_value(MmsMsg *msg, Octstr *header);
/* Returns a list of values for the header given. */
@ -118,4 +126,22 @@ int mms_clearbody(MmsMsg *msg);
* Use function with extreme caution! It should be for testing only really!!!!
*/
int mms_putbody(MmsMsg *msg, void *body, int ismultipart);
/* Convert a retrieve_conf message to a send_req messagre
* checked runtime error to pass anything but a send_req/retrieve_conf.
* returns 0 on success.
*/
int mms_make_sendreq(MmsMsg *retrieveconf);
/* Compute message size -- not altogether efficiently */
int mms_msgsize(MmsMsg *m);
/* MM4 stuff */
enum MM4_types_t {MM4_FORWARD_REQ = 0, MM4_FORWARD_RES, MM4_READ_REPLY_REPORT_REQ,
MM4_READ_REPLY_REPORT_RES, MM4_DELIVERY_REPORT_REQ, MM4_DELIVERY_REPORT_RES};
extern struct MM4_types_map_t {
char *mm4str;
int mm1_type;
} mm4_types[];
#endif

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* Queue management functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -14,17 +14,20 @@
#ifndef _MMS_QUEUE_INCLUDED__
#define _MMS_QUEUE_INCLUDED__
#include <signal.h>
#include "mms_msg.h"
#include "mms_util.h"
#define QFNAMEMAX 128
typedef struct MmsEnvelopeTo {
Octstr *rcpt; /* Recipient address. */
Octstr *rcpt; /* Recipient address. */
int process; /* 1 if delivery to this recipient should be attempted.
* Flags below for details.
*/
enum {SFailed=0, SSuccess, SDefered, SUnknown} flag;
void *_x; /* Used by client modules */
} MmsEnvelopeTo;
typedef struct MmsEnvelope {
@ -32,15 +35,17 @@ typedef struct MmsEnvelope {
Octstr *msgId; /* message id (for reference). */
Octstr *token; /* User level token, may be null. */
Octstr *from; /* from address. */
Octstr *mclass; /* Message class. */
Octstr *vaspid; /* VASPID (if any) */
Octstr *vasid; /* VASID (if any) */
Octstr *url1; /* Generic URLs (2) associated with message. */
Octstr *url2;
List *hdrs; /* Generic list of headers associated with message. */
List *to; /* List of recipients: MmsEnvelopeTo */
List *to; /* List of recipients: MmsEnvelopeTo (if process=0 then already sent to)*/
Octstr *subject; /* Message subject (if any). */
time_t created; /* date/time this queue entry was made. */
@ -63,49 +68,61 @@ typedef struct MmsEnvelope {
Octstr *mdata; /* Generic string data used by any interface. */
Octstr *fromproxy; /* Which proxy sent us this message.*/
Octstr *viaproxy; /* Which proxy must we send this message through. */
char src_interface[16]; /* source interface of this message. */
char _extra_space; /* A bit of sugar, just in case... */
void *_x; /* Generic storage field used by module clients. */
/* DO NOT MODIFY ANYTHING BEYOND THIS POINT. */
struct { /* Name of the queue file, pointer to it (locked). DO NOT USE THESE! */
char name[QFNAMEMAX]; /* Name of the file. */
char dir[QFNAMEMAX]; /* Directory in which file is .*/
char subdir[64]; /* and the sub-directory. */
char _pad[16];
int fd;
} qf;
void *qfs_data; /* Queue handler module structure -- allocated for you by queue_create
* function.
*/
char xqfname[64+QFNAMEMAX]; /* The full ID for the queue. Use this. */
} MmsEnvelope;
/* Given a queue directory, initialise it. Must be called at least once on each queue dir. */
int mms_init_queuedir(Octstr *qdir);
typedef struct MmsQueueHandlerFuncs {
/* Initialise queue module. Must be called at least once on each queue dir.
* max_concurrent is a best guess as to number of concurrent queue requests
*/
int (*mms_init_queue_module)(Octstr *init_data, char *top_storage_dir, int max_concurrent);
/* initialise a queue directory. There can be multiple directories,
* upperlevel decides what a directory is.
* module returns a directory string.
*/
Octstr *(*mms_init_queue_dir)(char *qdir, int *error);
/* cleanup module, e.g. on exit. */
int (*mms_cleanup_queue_module)(void);
/*
* Add a message to the queue, returns 0 on success -1 otherwise (error is logged).
* 'to' is a list of Octstr * *.
* Returns a queue file name.
*/
extern Octstr *mms_queue_add(Octstr *from, List *to,
Octstr *subject,
Octstr *fromproxy, Octstr *viaproxy,
time_t senddate, time_t expirydate, MmsMsg *m, Octstr *token,
Octstr *vaspid, Octstr *vasid,
Octstr *url1, Octstr *url2,
int dlr,
char *directory, Octstr *mmscname);
Octstr *(*mms_queue_add)(Octstr *from, List *to,
Octstr *subject,
Octstr *fromproxy, Octstr *viaproxy,
time_t senddate, time_t expirydate, MmsMsg *m,
Octstr *token,
Octstr *vaspid, Octstr *vasid,
Octstr *url1, Octstr *url2,
List *hdrs,
int dlr,
char *directory, char *src_interface,
Octstr *mmscname);
/*
* Update queue status. Returns -1 on error, 0 if queue is updated fine and
* envelope is still valid, 1 if envelope is no longer valid (no more recipients.)
*/
extern int mms_queue_update(MmsEnvelope *e);
int (*mms_queue_update)(MmsEnvelope *e);
/*
* Get the message associated with this queue entry.
*/
extern MmsMsg *mms_queue_getdata(MmsEnvelope *e);
MmsMsg *(*mms_queue_getdata)(MmsEnvelope *e);
/* Replace data for this queue item -- used by mm7 interface. */
int mms_queue_replacedata(MmsEnvelope *e, MmsMsg *m);
int (*mms_queue_replacedata)(MmsEnvelope *e, MmsMsg *m);
/*
* Reads queue, returns up to lim queue entries that are ready for processing. send 0 for no limit.
@ -119,7 +136,7 @@ int mms_queue_replacedata(MmsEnvelope *e, MmsMsg *m);
* - If should block is 1, then does a potentially blocking attempt to lock the file.
*/
MmsEnvelope *mms_queue_readenvelope(char *qf, char *dir, int shouldblock);
MmsEnvelope *(*mms_queue_readenvelope)(char *qf, char *dir, int shouldblock);
/*
* Run the queue in the given directory. For each envelope that is due for sending, call
@ -128,12 +145,43 @@ MmsEnvelope *mms_queue_readenvelope(char *qf, char *dir, int shouldblock);
* if deliver() returns 1, it has deleted envelope.
* Also if rstop becomes true, queue run must stop.
*/
void mms_queue_run(char *dir,
int (*deliver)(MmsEnvelope *),
double sleepsecs,
int num_threads,
int *rstop);
void (*mms_queue_run)(char *dir,
int (*deliver)(MmsEnvelope *),
double sleepsecs,
int num_threads,
volatile sig_atomic_t *rstop);
/* Get rid of memory used by this. Typically does internal cleanup then calls
* the general structure free-ing function below.
*/
int (*mms_queue_free_env)(MmsEnvelope *e);
} MmsQueueHandlerFuncs;
/* Module must export this symbol:
* extern MmsQueueHandlerFuncs qfuncs;
*/
extern MmsQueueHandlerFuncs default_qfuncs; /* default queue handler module, file-based */
/* Utility functions, generally defined. */
/* Creates the queue envelope object, returns it. Returns the binary MMS in 'binary_mms' if NOT NULL */
MmsEnvelope *mms_queue_create_envelope(Octstr *from, List *to,
Octstr *subject,
Octstr *fromproxy, Octstr *viaproxy,
time_t senddate, time_t expirydate,
Octstr *token,
Octstr *vaspid, Octstr *vasid,
Octstr *url1, Octstr *url2,
List *hdrs,
int dlr,
Octstr *mmscname,
MmsMsg *m,
char *xqfname,
char *src_interface,
int extra_space,
Octstr **binary_mms);
/* Get rid of memory used by this. */
extern int mms_queue_free_env(MmsEnvelope *e);
void mms_queue_free_envelope(MmsEnvelope *e);
/* utility function for 'cleaning up' addresses. */
Octstr *copy_and_clean_address(Octstr *addr);
#endif

View File

@ -3,7 +3,7 @@
*
* MMS strings module
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -107,7 +107,7 @@ static Octstr *number_to_string(long number, struct table *table)
return octstr_duplicate(table->strings[i]);
}
}
return NULL;
return octstr_imm("");
}
static unsigned char *number_to_cstr(long number, struct table *table)

View File

@ -293,6 +293,7 @@ VNSTRING(MM7_5, "StatusText",MM7_TAG_StatusText)
VNSTRING(MM7_5, "Subject",MM7_TAG_Subject)
VNSTRING(MM7_5, "SubmitReq",MM7_TAG_SubmitReq)
VNSTRING(MM7_5, "SubmitRsp",MM7_TAG_SubmitRsp)
VNSTRING(MM7_5, "TimeStamp",MM7_TAG_TimeStamp)
VNSTRING(MM7_5, "To",MM7_TAG_To)
VNSTRING(MM7_5, "TransactionID",MM7_TAG_TransactionID)
@ -307,6 +308,9 @@ VNSTRING(MM7_5, "MessageType",MM7_TAG_MessageType)
VNSTRING(MM7_5, "replyChargingSize", MM7_TAG_replyChargingSize)
VNSTRING(MM7_5, "replyDeadline", MM7_TAG_replyDeadline)
VNSTRING(MM7_5, "DeliveryReport", MM7_TAG_DeliveryReport)
VNSTRING(MM7_5, "allowAdaptations", MM7_TAG_allowAdaptations)
VNSTRING(MM7_5, "DistributionIndicator",MM7_TAG_distributionIndicator)
VNSTRING(MM7_5, "UACapabilities",MM7_TAG_UACapabilities)
)
NUMBERED(soap_status,
@ -324,6 +328,7 @@ ASSIGN("Server Error", 3000)
ASSIGN("Not Possible", 3001)
ASSIGN("Message rejected", 3002)
ASSIGN("Multiple addresses not supported", 3003)
ASSIGN("Command Rejected", 3005)
ASSIGN("General service error", 4000)
ASSIGN("Improper identification", 4001)
ASSIGN("Unsupported version", 4002)

View File

@ -3,7 +3,7 @@
*
* MMS strings module
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* User-Agent profiles handling, content adaptation.
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* Misc. functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -15,51 +15,69 @@
#include "gwlib/gwlib.h"
#include "gwlib/mime.h"
#include "gwlib/regex.h"
#include "config.h"
#include "mbuni-config.h"
#include "mms_strings.h"
#include "mms_msg.h"
#include "mms_mm7soap.h"
#include "mms_cfg.h"
#include "mms_mmbox.h"
#include "mms_eventlogger.h"
/* supported 3GPP MMS version */
#define MAKE_VERSION(a,b,c) ((a)<<16 | (b)<<8 | (c))
#define MAJOR_VERSION(v) (((v)>>16)&0xF)
#define MINOR1_VERSION(v) (((v)>>8)&0xF)
#define MINOR2_VERSION(v) ((v)&0xF)
#define MMS_3GPP_VERSION MAKE_VERSION(5,5,0)
/* Send errors */
#define MMS_SEND_OK 0
#define MMS_SEND_QUEUED 1
#define MMS_SEND_ERROR_TRANSIENT -1
#define MMS_SEND_ERROR_FATAL -2
#define SEND_ERROR_STR(e) ((e) == MMS_SEND_OK ? "Sent" : (e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : "Failed")
/* Aging of old (internal) records... */
#define DEFAULT_DELETE_AGE 10*60
#define SEND_ERROR_STR(e) ((e) == MMS_SEND_OK ? "Sent" : \
(e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : \
((e) == MMS_SEND_QUEUED ? "Queued" : "Failed"))
/* Useful headers. */
#define XMSISDN_HEADER "X-WAP-Network-Client-MSISDN"
#define XIP_HEADER "X-WAP-Network-Client-IP"
#define MM_NAME "Mbuni"
#define EAIF_VERSION "3.0"
#define EAIF_VERSION "%d.%d"
/* used by mmbox and queue code -- directory stuff. */
#define _TT "0123456789abcdefghijklmnopqrstuvwxyz"
#define _TTSIZE (-1 + sizeof _TT)
#define MBUNI_MULTIPART_TYPE "application/vnd.mbuni.url-list"
/* Global variables and shared code used by all modules. */
#define MMSC_VERSION VERSION
#define MMSC_VERSION MBUNI_VERSION
#define MMS_NAME PACKAGE
#define DRM_CONTENT_TYPE(ctype) ((ctype) && octstr_case_search(ctype, octstr_imm("application/vnd.oma.drm"), 0) == 0)
/* Message location flags: Used to distinguish fetch-urls */
enum mms_loc_t {MMS_LOC_MMBOX = 1, MMS_LOC_MQUEUE=2};
extern int mms_load_core_settings(mCfgGrp *cgrp);
extern int mms_load_core_settings(mCfg *cfg, mCfgGrp *cgrp);
extern Octstr *mms_maketransid(char *qf, Octstr *mmscname);
extern Octstr *mms_make_msgid(char *qf, Octstr *mmscname);
extern Octstr *mms_getqf_fromtransid(Octstr *transid);
extern int mms_decodefetchurl(Octstr *fetch_url,
Octstr **qf, Octstr **token, int *loc);
Octstr *mms_find_sender_ip(List *request_hdrs, Octstr *ip_header, Octstr *ip, int *isv6);
extern Octstr *mms_getqf_from_msgid(Octstr *msgid);
extern Octstr *mms_isodate(time_t t);
void mms_lib_init(void);
@ -75,27 +93,39 @@ List *get_value_parameters(Octstr *params);
Octstr *make_value_parameters(List *params);
/* Get parameter from http header value and strip it */
Octstr *get_stripped_param_value(Octstr *value, Octstr *param);
/* Where value is comma-separated, make separate header items. */
void unpack_mimeheaders(MIMEEntity *m);
/* Where element has base64 encoding, decode. */
void unbase64_mimeparts(MIMEEntity *m);
/* Where element contains binary data, encode it base64. */
void base64_mimeparts(MIMEEntity *m);
/* Where element contains binary data, encode it base64. Set all = 1 to ignore whether body is binary
* and should be coded.
*/
void base64_mimeparts(MIMEEntity *m, int all);
void notify_prov_server(char *cmd, char *from, char *event, char *arg);
int mms_ind_send(Octstr *prov_cmd, Octstr *to);
/* Send this message to email recipient: Returns 0 on success 1 or 2 on profile error
* (negate to get right one), -ve on some other error
*/
int mms_sendtoemail(Octstr *from, Octstr *to,
int mms_sendtoemail(Octstr *from, List *lto,
Octstr *subject, Octstr *msgid,
MmsMsg *msg, int dlr, Octstr **error,
char *sendmail_cmd, Octstr *myhostname,
int trans_msg,
int trans_smil, char *txt, char *html, int append_hostname);
int trans_smil, char *txt, char *html, int mm4,
char *transid, List *extra_headers,
Octstr *relay_host, int relay_port);
/* Send directly to email. */
int mm_send_to_email(Octstr *to, Octstr *from, Octstr *subject,
Octstr *msgid,
MIMEEntity *m, int append_hostname, Octstr **error,
char *sendmail_cmd, Octstr *myhostname,
Octstr *relay_host, int relay_port);
/* log to access log. */
void mms_log(char *logmsg, Octstr *from, List *to,
@ -118,28 +148,41 @@ void mms_log2(char *logmsg, Octstr *from, Octstr *to,
*/
int mm_lockfile(int fd, char *fname, int shouldblock);
/* This should be elsewhere, but it isn't, so we do it here... */
extern MIMEEntity *mime_entity_duplicate(MIMEEntity *m);
/* Returns true if the character is printable or space */
int _mms_gw_isprint(int c);
int lockfile(int fd, int shouldblock);
/*
* unlock_and_fclose/unlock_and_close are wrappers around fclose/close
* needed to maintain the state of the global list on Solaris.
*/
int unlock_and_fclose(FILE *fp);
int unlock_and_close(int fd);
/* Special form of cfg_get which returns zero-length string when there is nothing. */
Octstr *_mms_cfg_getx(mCfgGrp *grp, Octstr *item);
Octstr *_mms_cfg_getx(mCfg *cfg, mCfgGrp *grp, Octstr *item);
/* Get envelope data from message headers. */
void mms_collect_envdata_from_msgheaders(List *mh, List **xto,
Octstr **subject,
Octstr **otransid, time_t *expiryt,
time_t *deliveryt, long default_msgexpiry);
time_t *deliveryt, long default_msgexpiry,
long max_msgexpiry,
char *unified_prefix, List *strip_prefixes);
/* Simple hash function */
unsigned long _mshash(char *s);
/* Tell us whether address is a phone number. */
int isphonenum(Octstr *s);
/* Fixup an address: Add type, etc. */
void _mms_fixup_address(Octstr *address);
int isphonenum_ex(Octstr *s, int offset);
/* Fixup an address: Normalize number (if prefix given), Add type (if keep_suffix is set), etc. */
void _mms_fixup_address(Octstr **address, char *unified_prefix, List *strip_prefixes, int keep_suffix);
/* normalize a phone number: Strip any prefixes, then normalize. */
void mms_normalize_phonenum(Octstr **num, char *unified_prefix, List *strip_prefixes);
/* Check that host is one of hosts in semi-colon separated list in host_list */
int is_allowed_host(Octstr *host, Octstr *host_list);
@ -147,8 +190,138 @@ int is_allowed_host(Octstr *host, Octstr *host_list);
/* escape (backlash) special shell characters. */
void escape_shell_chars(Octstr *str);
/* Parse CGI variables out of a HTTP POST request.
* This function understands both standard POST and enctype multipart/form-data
* For the latter it puts the content type of each of the variables found into
* cgivars_ctypes (as HTTPCGIVars where name is the field name and value is the content type)
* cgivars argument is the cgivars as passed to us by http_accept_request. For GET
* HTTP requests this is returned unchanged, otherwise it is augmented with the
* variables found.
*/
int parse_cgivars(List *request_headers, Octstr *request_body,
List **cgivars, List **cgivar_ctypes);
/* get content-ID header, fix: WAP decoder may leave " at beginning */
Octstr *_x_get_content_id(List *headers);
/* Remove the boundary element from a list of headers. */
void strip_boundary_element(List *headers, char *s);
/* Fetch a URL. If necessary, authenticate, etc. also understands data: url scheme. */
int mms_url_fetch_content(int method, Octstr *url, List *request_headers,
Octstr *body, List **reply_headers, Octstr **reply_body);
/* check that the token is valid. */
int mms_is_token(Octstr *token);
/* try to guess content type from file name extension. */
Octstr *filename2content_type(char *fname);
/* try to give a good extension name based on the url or content type. */
char *make_file_ext(Octstr *url, Octstr *ctype, char fext[5]);
/* return true if node has a child... */
int has_node_children(xmlNodePtr node);
/* strip non-essential headers from top-level */
void strip_non_essential_headers(MIMEEntity *mime);
/* Get phone number out of mms formatted one, and unify. */
Octstr *extract_phonenum(Octstr *num, Octstr *unified_prefix);
/* strip quotes off a quoted string. */
void strip_quoted_string(Octstr *s);
/* Remove quotes from string */
void strip_quotes(Octstr *s);
/* Make a mime entity representing a multipart/form-data HTTP request. */
MIMEEntity *make_multipart_formdata(void);
/* Add a form field to the multipart/form-data entity. */
void add_multipart_form_field(MIMEEntity *multipart, char *field_name,
char *ctype, char *content_loc,
Octstr *data);
/* Build a multipart message from a list of URLs. Fetch each one and add. Result is a multipart/mixed message. */
MIMEEntity *multipart_from_urls(List *url_list);
/* load a shared object, then load a symbol from it. */
void *_mms_load_module(mCfg *cfg, mCfgGrp *grp, char *config_key, char *symbolname,
void *shell_builtin);
/* Clean addresses by type: remove prefixes, etc. */
void fixup_address_type(List *headers, char *hdr,
char *unified_prefix,
List *strip_prefixes);
/* Convert charset mib enum to charset and vice versa */
extern const char *mibenum_to_charset(int val);
extern int charset_to_mibenum(char *charset);
Octstr *pack_rfc2047_text(Octstr *in, int charset_mib_enum);
Octstr *parse_rfc2047_text(Octstr *in, int *mibenum);
/* Utility func */
void mygw_free(void *);
/* Authenticate using HTTP Basic auth */
int http_auth_check(char *user, char *pass, List *headers, int *has_auth_hdr);
/* Add @host to an mms address */
void addmmscname(Octstr *address, char *myhostname);
/* Get (copy of) keyword from mime thingie */
Octstr *get_keyword_from_mime(MIMEEntity *me);
enum _xurltype {FILE_TYPE, URL_TYPE};
void get_content_from_sendmms_request(Octstr *body, List *headers, List *cgivars, List *cgivar_ctypes,
List **rh, Octstr **ctype, Octstr **data,
Octstr **rb,
Octstr **base_url, Octstr **data_url);
MmsMsg *make_msg_from_sendmms_request(Octstr *from, List *to,
Octstr *msgId,
Octstr *subject,
Octstr *data, Octstr *ctype,
List *reply_headers,
Octstr *msg_url,
Octstr *base_url, int type,
Octstr *mmc,
Octstr *svc_name,
time_t expiryt,
int do_multipart,
int do_rr,
int do_dlr,
Octstr *allow_adaptations,
int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id),
Octstr **err);
#define US_ASCII_MIB_VAL 3
#define UTF8_MIB_VAL 106
#define MAXQTRIES 100
#define BACKOFF_FACTOR 5*60 /* In seconds */
#define QUEUERUN_INTERVAL 15*60 /* 15 minutes. */
#define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */
#define DEFAULT_EXPIRE 3600*24*7 /* One week */
#define DEFAULT_SIMUL_RCPTS 10
#define HTTP_REPLACE_HEADER(hdr, hname, value) do { \
http_header_remove_all((hdr), (hname)); \
http_header_add((hdr), (hname), (value)); \
} while (0)
List *gwlist_create_ex_real(const char *file, const char *func, int line,...);
#define gwlist_create_ex(...) gwlist_create_ex_real(__FILE__,__FUNCTION__,__LINE__, __VA_ARGS__, NULL)
#define LINEARISE_STR_LIST(res,lst,sep) do { \
Octstr *__res; \
int __i; \
for (__res = octstr_create(""), __i = 0; __i < gwlist_len(lst); __i++) \
octstr_format_append(__res, "%s%S", \
octstr_len(__res) == 0 ? "" : (sep), gwlist_get((lst), __i)); \
(res) = __res; \
} while (0)
#endif

View File

@ -1,7 +1,8 @@
libmms = $(top_builddir)/mmlib/libmms.la
lib_LTLIBRARIES = libmmsbox.la
libmmsbox_la_SOURCES = mmsbox_cdr.c mmsbox_cfg.h mmsbox_cfg.c dlr.c bearerbox.c mmsbox_resolve.c mmsbox_resolve_shell.c
bin_PROGRAMS = mmsbox
mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c dlr.c bearerbox.c
mmsbox_LDADD = $(libmms)
mmsbox_SOURCES = mmsbox.c mmsbox.h
mmsbox_LDADD = libmmsbox.la $(libmms)
EXTRA_DIST = mmsbox_cfg.h mmsbox.h
EXTRA_DIST = mmsbox_cdr.h mmsbox_cfg.h mmsbox.h mmsbox_mt_filter.h mmsbox_resolve_shell.h mmsbox_resolve.h mmsbox_mmsc.h

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* MMSBox Dlr: Dlr storage for MMSBox
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -17,6 +17,10 @@
#include <errno.h>
#include <dlfcn.h>
#ifdef SunOS
#include <fcntl.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@ -24,7 +28,7 @@
#include "mms_queue.h"
#define MAXTRIES 10
static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **efname)
static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_gid, Octstr **efname)
{
char d1[2], d2[3], fbuf[512], *p;
unsigned long h = _mshash(msgid);
@ -43,17 +47,17 @@ static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **ef
d2[2] = '\0';
/* Try and create the next level dir (first level was created by root_init) */
sprintf(fbuf, "%s/%s/%s", octstr_get_cstr(dlr_dir), d1, d2);
sprintf(fbuf, "%.128s/%s/%s", octstr_get_cstr(dlr_dir), d1, d2);
if (mkdir(fbuf,
S_IRWXU|S_IRWXG) < 0 &&
errno != EEXIST) {
error(0, "mmsbox: failed to create dir [%s] "
mms_error(0, "mmsbox", NULL, "failed to create dir [%s] "
"while initialising dlr dir for %s: %s!",
fbuf, msgid, strerror(errno));
return -1;
}
t = octstr_format("%S-%s_%s", mmc_id, msgid, rtype); /* Put mmc id into name. */
t = octstr_format("%S-%s_%s", mmc_gid, msgid, rtype); /* Put mmc id into name. */
octstr_replace(t, octstr_imm("/"), octstr_imm("$")); /* XXX safe in all cases?? */
s = octstr_format("%s/%S", fbuf, t);
@ -64,11 +68,11 @@ static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **ef
i = 0;
do
if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)) < 0) {
error(0, "Failed to open DLR URL store file [%s], error: %s!",
mms_error(0, "mmsbox", NULL, "Failed to open DLR URL store file [%s], error: %s!",
p, strerror(errno));
break;
} else if (mm_lockfile(fd, p, 1) != 0) {
close(fd);
unlock_and_close(fd);
fd = -1;
}
while (i++ < MAXTRIES && fd < 0);
@ -81,42 +85,53 @@ static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **ef
return fd;
}
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_id, Octstr *dlr_url)
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr *dlr_url, Octstr *transid)
{
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, NULL);
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_gid, NULL);
if (fd >= 0) {
octstr_write_data(dlr_url, fd, 0);
close(fd);
Octstr *x = octstr_format("%S %S", transid ? transid : octstr_imm("x"), dlr_url); /* better have no spaces in transid! */
octstr_write_data(x, fd, 0);
unlock_and_close(fd);
octstr_destroy(x);
}
}
Octstr *mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_id)
int mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr **dlr_url, Octstr **transid)
{
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, NULL);
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_gid, NULL);
FILE *f;
if (fd >= 0 && (f = fdopen(fd, "r+")) != NULL) {
Octstr *s = octstr_read_pipe(f);
fclose(f);
int i, ret;
unlock_and_fclose(f);
if (s && octstr_len(s) == 0) {
octstr_destroy(s);
return NULL;
ret = -1;
} else if ((i = octstr_search_char(s, ' ', 0)) >= 0) {
*transid = octstr_copy(s, 0, i);
*dlr_url = octstr_copy(s, i+1, octstr_len(s));
ret = 0;
} else
return s;
ret = -1;
octstr_destroy(s);
return ret;
} else if (fd >= 0)
close(fd);
return NULL;
unlock_and_close(fd);
return -1;
}
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_id)
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_gid)
{
Octstr *fname = NULL;
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, &fname);
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_gid, &fname);
if (fname)
if (fname) {
unlink(octstr_get_cstr(fname));
octstr_destroy(fname);
}
if (fd >= 0)
close(fd);
unlock_and_close(fd);
}

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* MMSBOX CFG: MMC configuration and misc. functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -14,14 +14,19 @@
#define __MMSBOX_INCLUDED__
#include "mmsbox_cfg.h"
extern int rstop;
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_id, Octstr *dlr_url);
Octstr *mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_id);
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_id);
void mmsc_receive_func(MmscGrp *m);
void mmsbox_outgoing_queue_runner(int *rstop);
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr *dlr_url, Octstr *transid);
int mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr **dlr_url, Octstr **transid);
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_gid);
/* Fetch content given method. also understands data: url scheme. */
int mmsbox_url_fetch_content(int method, Octstr *url, List *request_headers,
Octstr *body, List **reply_headers, Octstr **reply_body);
Octstr *mmsbox_get_report_info(MmsMsg *m, MmscGrp *mmsc, Octstr *out_mmc_id,
char *report_type,
Octstr *status, List *qhdr, Octstr *uaprof,
time_t uaprof_tstamp,
Octstr *msgid);
void mmsc_receive_func(MmscGrp *m);
void mmsbox_outgoing_queue_runner(volatile sig_atomic_t *rstop);
void mm4_receive_func(int *sock);
void handle_mm1_mt_requests(MmscGrp *m); /* MM1 loop */
/* Just a convenience, should go away in future! */
#define mmsbox_url_fetch_content mms_url_fetch_content
#endif

188
mbuni/mmsbox/mmsbox_cdr.c Normal file
View File

@ -0,0 +1,188 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Mbuni MMSBOX base CDR handler module (writes to a CVS file)
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <stdio.h>
#include <stdlib.h>
#include "mmsbox_cdr.h"
#include "mmsbox_cfg.h"
static FILE *cdr_file;
static List *req_list;
static long th_id;
#define CBUFSIZE 256
typedef struct MmsBoxCdrStruct {
time_t sdate;
char from[CBUFSIZE];
char to[CBUFSIZE];
#if 0
char src_ip[CBUFSIZE/4];
char dest_ip[CBUFSIZE/4];
#endif
char msgid[CBUFSIZE];
char mmsc_id[CBUFSIZE];
char src_int[CBUFSIZE/4];
char dst_int[CBUFSIZE/4];
unsigned long msg_size;
char msgtype[CBUFSIZE/8];
char prio[CBUFSIZE/8];
char mclass[CBUFSIZE/8];
char status[CBUFSIZE/8];
unsigned char dlr;
unsigned char rr;
} MmsBoxCdrStruct;
static void cdr_logger_func(void)
{
MmsBoxCdrStruct *cdr;
hmon->register_thread("cdr_logger");
while ((cdr = gwlist_consume(req_list)) != NULL) {
char buf[CBUFSIZE];
struct tm tm;
localtime_r(&cdr->sdate, &tm);
gw_strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &tm);
fprintf(cdr_file, "%s", buf);
/* Print rest of fields one by one. */
#define PRINTF_STR_FIELD(fld) fprintf(cdr_file, "\t%.*s", (int)(sizeof cdr->fld), cdr->fld)
PRINTF_STR_FIELD(src_int);
PRINTF_STR_FIELD(dst_int);
PRINTF_STR_FIELD(from);
PRINTF_STR_FIELD(to);
PRINTF_STR_FIELD(msgid);
PRINTF_STR_FIELD(mmsc_id);
PRINTF_STR_FIELD(msgtype);
PRINTF_STR_FIELD(prio);
PRINTF_STR_FIELD(mclass);
PRINTF_STR_FIELD(status);
fprintf(cdr_file, "\t%ld\t%s\t%s\n",
(long)cdr->msg_size,
cdr->dlr ? "Yes" : "No",
cdr->rr ? "Yes" : "No");
fflush(cdr_file);
gw_free(cdr);
}
hmon->unregister_thread("cdr_logger");
}
static int cdr_module_init(char *settings)
{
cdr_file = fopen(settings, "a"); /* Settings is interpreted as a file name. */
if (cdr_file) {
req_list = gwlist_create();
gwlist_add_producer(req_list);
th_id = gwthread_create((void *)cdr_logger_func, NULL);
return 0;
} else
return -1;
}
static int module_fini(void)
{
gw_assert(req_list);
gw_assert(cdr_file);
gwlist_remove_producer(req_list);
if (th_id >= 0)
gwthread_join(th_id);
gwlist_destroy(req_list, NULL); /* there shouldn't be any requests waiting */
if (cdr_file)
fclose(cdr_file);
return 0;
}
/* utility function. */
static void fill_cdr_struct(MmsBoxCdrStruct *cdr,
time_t sdate, char *from, char *to, char *msgid,
char *mmsc_id, char *src_int, char *dst_int,
#if 0
char *src_ip, char *dst_ip,
#endif
unsigned long msg_size,
char *msgtype, char *prio, char *mclass,
char *status,
int dlr, int rr)
{
memset(cdr, 0, sizeof cdr[0]);
cdr->sdate = sdate;
#define COPY_CDR_FIELD(fld) if (fld) strncpy(cdr->fld, fld, sizeof cdr->fld)
COPY_CDR_FIELD(from);
COPY_CDR_FIELD(to);
COPY_CDR_FIELD(msgid);
COPY_CDR_FIELD(mmsc_id);
COPY_CDR_FIELD(src_int);
COPY_CDR_FIELD(dst_int);
COPY_CDR_FIELD(msgtype);
COPY_CDR_FIELD(prio);
COPY_CDR_FIELD(mclass);
COPY_CDR_FIELD(status);
cdr->dlr = dlr;
cdr->rr = rr;
cdr->msg_size = msg_size;
}
static int cdr_module_logcdr(time_t sdate, char *from, char *to, char *msgid,
char *mmsc_id, char *src_int, char *dst_int,
#if 0
char *src_ip, char *dst_ip,
#endif
unsigned long msg_size,
char *msgtype, char *prio, char *mclass,
char *status,
int dlr, int rr)
{
MmsBoxCdrStruct *xcdr = gw_malloc(sizeof xcdr[0]);
gw_assert(req_list);
fill_cdr_struct(xcdr, sdate, from, to, msgid, mmsc_id, src_int, dst_int,
#if 0
src_ip, dst_ip,
#endif
msg_size, msgtype, prio, mclass, status, dlr, rr);
gwlist_produce(req_list, xcdr);
return 0;
}
MmsBoxCdrFuncStruct mmsbox_cdrfuncs = {
cdr_module_init,
cdr_module_logcdr,
module_fini
};

46
mbuni/mmsbox/mmsbox_cdr.h Normal file
View File

@ -0,0 +1,46 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Mbuni billing integration interface
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMSBOX_CDR_INCLUDED__
#define __MMSBOX_CDR_INCLUDED__
#include <time.h>
#include "gwlib/gwlib.h"
/* MMSBOX CDR module. This file provides prototypes for all CDR functions.
*
*/
typedef struct MmsBoxCdrFuncStruct {
/* This function is called once to initialise the module. Return 0 on success */
int (*init)(char *settings);
/* This function logs a cdr to wherever it is logging to. */
int (*logcdr)(time_t sdate, char *from, char *to, char *msgid,
char *mmsc_id, char *src_int, char *dst_int,
#if 0
char *src_ip, char *dst_ip,
#endif
unsigned long msg_size,
char *msgtype, char *prio, char *mclass,
char *status,
int dlr, int rr);
int (*cleanup)(void);
} MmsBoxCdrFuncStruct;
extern MmsBoxCdrFuncStruct mmsbox_cdrfuncs; /* The module must expose a symbol 'cdr_funcs' */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* MMSBOX CFG: MMC configuration and misc. functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -13,38 +13,137 @@
#ifndef __MMSBOX_CFG_INCLUDED__
#define __MMSBOX_CFG_INCLUDED__
#include "mms_util.h"
#include "mmsbox_mt_filter.h"
#include "mms_queue.h"
#include "mmsbox_resolve.h"
#include "mmsbox_mmsc.h"
#include "mmsbox_cdr.h"
#include "mms_cfg.h"
/* Alarm callback mechanism */
enum MmsBoxAlarms {
MMSBOX_ALARM_HTTP_DOWN = 0,
MMSBOX_ALARM_FILE_WRITE_ERROR,
MMSBOX_ALARM_SOCKET_CONNECT_FAILED,
MMSBOX_ALARM_QUEUE_WRITE_ERROR,
MMSBOX_ALARM_STORAGE_API_ERROR,
MMSBOX_ALARM_MM7_PARSING_FAILURE,
MMSBOX_ALARM_MM7_NON_200_RESULT,
MMSBOX_ALARM_RETRIEVE_MMS_ERROR,
MMSBOX_ALARM_MM4_PARSING_FAILURE,
MMSBOX_ALARM_MM1_ADDRESS_RESOLUTION_ERROR,
MMSBOX_ALARM_MAX_ALARM /* Must be last one */
};
typedef struct MmscGrp {
Octstr *id; /* MMSC id (for logging). */
Octstr *group_id; /* GROUP MMSC id (used for qf). */
Octstr *vasp_id; /* vasp id for SOAP mmsc */
Octstr *mmsc_url; /* URL at which MMSC can be reached. */
struct {
Octstr *user, *pass;
Octstr *allow_ip;
Octstr *deny_ip;
long port;
int ssl;
} incoming; /* user, pass, port (and whether SSL) that MMSC uses to connect to us. */
Octstr *allowed_prefix, *denied_prefix;
enum {UNKNOWN_MMSC, SOAP_MMSC, EAIF_MMSC} type; /* type of connection. */
long throughput; /* Max send rate. */
Octstr *allowed_sender_prefix, *denied_sender_prefix;
Octstr *carrier_id_header; /* http header that has carrier id */
enum {UNKNOWN_MMSC = -1, CUSTOM_MMSC, SOAP_MMSC, EAIF_MMSC, MM4_MMSC, HTTP_MMSC, MM1_MMSC} type; /* type of connection. */
double throughput; /* Max send rate. */
int allow_adaptations; /* turns ON/OFF allow-adaptations in MM7 SOAP XML */
long threadid; /* handler thread. */
int reroute; /* whether messages from this mmsc are re-routed outwards. */
Octstr *reroute_mmsc_id;
int no_senderaddress; /* used by SOAP interface: Don't add a sender address. */
int reroute_mod_subject; /* Set to true if we'll change subject line on reroute. */
MM7Version_t ver; /* supported MM7/SOAP version. */
int use_mt_filter; /* whether to use MT filter on this connection. */
Mutex *mutex;
Octstr *default_vasid; /* default vasid for mm7/soap */
MmsBoxMmscFuncs *fns; /* pointer to functions for handling this mmsc connection type */
Octstr *settings; /* settings for the above module. */
void *data; /* data for above module. */
int started; /* Whether it is active */
unsigned long mt_pdus; /* number of MT PDUs since start. */
unsigned long mo_pdus; /* number of MO PDUs since start. */
unsigned long mt_errors; /* number of MT errors since start */
unsigned long mo_errors; /* number of MO errors since start */
time_t last_pdu; /* time of last PDU */
time_t start_time; /* when was this connection started */
time_t last_alarm[MMSBOX_ALARM_MAX_ALARM];
int use_count; /* use counter. */
time_t delete_after; /* used to control deletion of object -- not very clean, but... */
long max_pkt_size;
int strip_domain; /* MM4 only */
long max_recipients; /* Max recpients per transaction */
List *strip_prefixes; /* List of prefixes to be stripped before sending out*/
List *retry_statuses; /* List of HTTP/MM7 statuses we do retry on, MM7 statuses are checked only on HTTP 200 - they do not overlap*/
struct MM1Info_t { /* Stuff used only by the MM1 MMSC */
Octstr *proxy; /* Proxy within the operator network, form of host:port */
Octstr *gprs_on; /* Command to start GPRS link. Must not exit. */
Octstr *gprs_off; /* Command to stop GPRS link. */
Octstr *gprs_pid; /* command to call to get PID of GPRS for stopping GPRS link (i.e. pppd). */
Octstr *smsc_on; /* command to start smsc connection */
Octstr *smsc_off; /* commadn to stop smsc connection */
Octstr *msisdn; /* Our msisdn */
Octstr *ua; /* User agent string, if given */
List *requests; /* list of requests. */
long d_tid;/* thread ID for mm1 handler. */
int sender_alive;
} mm1;
} MmscGrp;
#define DEFAULT_MAX_PKT_SIZE 1024*1024
#define MMSBOX_MMSC_MARK_INUSE(mmc) do {\
mutex_lock((mmc)->mutex); \
(mmc)->use_count++; \
mutex_unlock(mmc->mutex); \
} while (0)
#define MMSBOX_MMSC_UNMARK_INUSE(mmc) do {\
mutex_lock((mmc)->mutex); \
(mmc)->use_count--; \
mutex_unlock(mmc->mutex); \
} while (0)
typedef struct MmsServiceUrlParam {
Octstr *name;
enum {NO_PART, AUDIO_PART, IMAGE_PART, VIDEO_PART,
TEXT_PART, SMIL_PART , OTHER_PART,
ANY_PART, WHOLE_BINARY} type;
ANY_PART, WHOLE_BINARY, KEYWORD_PART,
RCPT_PART, FROM_PART, SUBJECT_PART, MMSCID_PART,
MSGTYPE_PART, MSGID_PART} type;
Octstr *value; /* for generic value (type == NO_PART),
* or for value that follows spec (e.g. %Tisatest is allowed) */
* or for value that follows spec (e.g. %Tisatest is allowed)
*/
} MmsServiceUrlParam;
typedef struct MmsService {
Octstr *name; /* name of service. */
int isdefault;
int omitempty;
int noreply;
int accept_x_headers;
List *passthro_headers;
int assume_plain_text;
List *keywords; /* List of keywords matched. */
enum {TRANS_TYPE_GET_URL, TRANS_TYPE_POST_URL, TRANS_TYPE_FILE, TRANS_TYPE_EXEC,
@ -54,22 +153,28 @@ typedef struct MmsService {
Octstr *faked_sender;
List *allowed_mmscs; /* List of MMSCs allowed to access this service (by ID). */
List *denied_mmscs; /* List of MMSCs allowed to access this service (by ID). */
List *denied_mmscs; /* List of MMSCs allowed to access this service (by ID). */
Octstr *service_code; /* Service code (MM7/SOAP only) */
Octstr *allowed_receiver_prefix, *denied_receiver_prefix;
Octstr *special_header; /* To be added to each content element. */
} MmsService;
typedef struct SendMmsUser {
Octstr *user, *pass;
Octstr *faked_sender;
Octstr *dlr_url, *rr_url;
Octstr *dlr_url, *rr_url, *mmsc;
} SendMmsUser;
/* Basic settings for the mmsbox. */
extern List *sendmms_users; /* list of SendMmsUser structs */
extern List *mms_services; /* list of MMS Services */
extern List *mmscs; /* MMSC list. Perhaps turn into a Dict instead? */
extern Octstr *incoming_qdir, *outgoing_qdir, *dlr_dir;
extern Octstr *unified_prefix;
extern long mmsbox_maxsendattempts, mmsbox_send_back_off;
extern Octstr *sendmail_cmd;
extern Octstr *myhostname;
extern List *strip_prefixes;
extern long svc_maxsendattempts, maxsendattempts, mmsbox_send_back_off, default_msgexpiry, max_msgexpiry;
extern long maxthreads;
extern double queue_interval;
extern struct SendMmsPortInfo {
@ -78,6 +183,117 @@ extern struct SendMmsPortInfo {
Octstr *deny_ip;
} sendmms_port;
extern struct MmsBoxMTfilter *mt_filter;
extern MmsQueueHandlerFuncs *qfs;
extern int mt_multipart;
extern int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func);
extern MmsBoxResolverFuncStruct *rfs; /* resolver functions. */
extern void *rfs_data;
extern Octstr *rfs_settings;
extern struct SMTPRelay {
Octstr *host;
int port;
} smtp_relay;
extern MmsBoxCdrFuncStruct *cdrfs;
extern struct MmsBoxHealthMonitors {
void (*register_thread)( char *name); /* Called by each thread to register itself with the health monitor */
void (*unregister_thread)(char *name); /* Called by each thread to unregister itself with the health monitor */
void (*register_port)(short port); /* Called to register each port on which we listen */
void (*unregister_port)(short port); /* Called to unregister each port on which we listen */
} *hmon; /* This should be set if you want to do any thread and port monitoring */
/* mmsbox_event_cb: Called with each mmsc event.
* mmsc - mmsc ID
* mm7_pkt_type - MM7 packet type (using MM7/SOAP codes)
* mm7_ver - value for SOAP or EAIF only
* status - 0 for Ok, -1 if failed (e.g. for submitack
* msg_size - size of mms
* num_retries - number of retries so far
* from - sender (can be NULL)
* to - recipient (can be NULL)
* transid - transaction ID
* message_id - Message ID (for submitack, deliverreq, deliveryreport or readreport)
* hdrs - List of envelope headers
* value - value associated with pkt type: e.g. for deliveryreport, report type
*/
extern void (*mmsbox_event_cb)(Octstr *mmsc, int mm7_pkt_type,
int is_mm4,
Octstr *mm7_ver, int status,
int msg_size, int num_retries,
Octstr *from, Octstr *to, Octstr *message_id, Octstr *transid,
List *hdrs, Octstr *value);
/* mmsbox_alarm_cb: Called when an alarm is raised or cleared
* mmsc - MMSC ID
* alarm - alarm type
* alarm_state - 0 = alarm cleared, 1 = alarm raised
* lev = severity level, 1 = warning, 2 = minor, 3 = major, 4+ = critical
*/
extern void (*mmsbox_alarm_cb)(Octstr*mmsc, enum MmsBoxAlarms alarm, int alarm_state, int lev);
#define MMSC_ISSUE_ALARM(mmc,alarm,lev) do { \
MmscGrp *_mmc = (mmc); \
if (_mmc) \
_mmc->last_alarm[(alarm)] = time(NULL); \
mmsbox_alarm_cb(_mmc ? _mmc->id : NULL, (alarm), 1, (lev)); \
} while (0)
#define MMSC_CLEAR_ALARM(mmc,alarm) do { \
MmscGrp *_mmc = (mmc); \
if (_mmc && _mmc->last_alarm[(alarm)] > 0 ) { \
mmsbox_alarm_cb(_mmc->id, (alarm), 0, 0); \
_mmc->last_alarm[(alarm)] = 0; \
} \
} while (0)
extern int mms_load_mmsbox_settings(struct mCfgImpFuncs *cfg_funcs, Octstr *init,
gwthread_func_t *mmsc_handler_func,
MmsQueueHandlerFuncs *,
MmsEventLoggerFuncs *);
extern void mmsbox_settings_cleanup(void);
extern MmscGrp *get_handler_mmc(Octstr *id, Octstr *to, Octstr *from);
extern void return_mmsc_conn(MmscGrp *m);
extern Octstr *get_mmsbox_queue_dir(Octstr *from, List *to, MmscGrp *m, Octstr **mmc_id);
#if 0
MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *errors, List *warnings);
#endif
int mmsbox_stop_mmsc(Octstr *mmc);
int mmsbox_start_mmsc(Octstr *mmc_id);
MmscGrp *mmsbox_get_mmsc_by_url(Octstr *mmc_url);
void mmsbox_stop_all_mmsc_conn(void);
typedef struct MmsBoxHTTPClientInfo {
HTTPClient *client;
Octstr *ua;
Octstr *ip;
List *headers;
Octstr *url;
Octstr *body;
List *cgivars;
MmscGrp *m;
} MmsBoxHTTPClientInfo;
void free_mmsbox_http_clientInfo(MmsBoxHTTPClientInfo *h, int freeh);
/* parse service url params in list of MmsServiceUrlParm structs */
List *parse_service_url_params(Octstr *input, Octstr *id);
#define add_all_matching_parts(a,b,c,d,e,f,g) add_all_matching_parts_real((a),(b),(c),(d),(e),(f),(g),NULL,NULL,NULL,NULL,-1,NULL)
void add_all_matching_parts_real(MIMEEntity *plist, MmsServiceUrlParam *pm,
Octstr *keyword,
MIMEEntity *me,
MmsMsg *msg, int lev, int count,
Octstr *from, List *lto, char *subject,
char *mmsc_id, int mtype, Octstr *msgid);
MIMEEntity *mmsbox_add_service_url_params(List *params,
Octstr *from, List *lto, char *subject,
char *mmsc_id, int mtype, Octstr *msgid,
MmsMsg *m);
extern volatile sig_atomic_t rstop;
#endif

View File

@ -0,0 +1,42 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSBOX Custom MMSC types: MMC function definitions
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMSBOX_MMSC_CFG_INCLUDED__
#define __MMSBOX_MMSC_CFG_INCLUDED__
#include "mms_util.h"
#include "mms_queue.h"
struct MmscGrp; /* so we compile. */
typedef struct MmsBoxMmscFuncs {
/* start_conn: called once with the module settings, ID of the connection
* and a pointer where to store module specific info.
* should return 0 on success, -1 on error.
*/
int (*start_conn)(struct MmscGrp *mmc, MmsQueueHandlerFuncs *qfs,
Octstr *unified_prefix, List *strip_prefixes,
void **data);
/* stop_conn: Called to stop the MMC connection. */
int (*stop_conn)(void *data);
/* send_msg: called to send a message. Should msg ID if any. On error,
* retry can be set to 1 for sending to be retried later.
* Should set err to the error message (if any).
*/
Octstr *(*send_msg)(void *data, Octstr *from, Octstr *to,
Octstr *transid,
Octstr *linkedid, char *vasid, Octstr *service_code,
MmsMsg *m, List *hdrs, Octstr **err, int *retry);
} MmsBoxMmscFuncs;
extern MmsBoxMmscFuncs mmsc_funcs; /* lib should expose this structure. */
#endif

View File

@ -0,0 +1,48 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Empty wrapper library
*
* Copyright (C) 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is proprietary software, refer to licence holder for details
*/
#include <sys/file.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <dlfcn.h>
#include <strings.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mmsbox_mt_filter.h"
static int myinit(Octstr *mmc_url, Octstr *mmc_id, Octstr *startup_params)
{
return 0;
}
static int myfilter(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id)
{
return 0;
}
static void myclose(Octstr *mmc_id)
{
return;
}
struct MmsBoxMTfilter mmsbox_mt_filter = {
.name = "Empty Wrapper",
.init = myinit,
.filter = myfilter,
.destroy = myclose
};

View File

@ -0,0 +1,36 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSBOX MT MMS filter: Optional filter for MT messages
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMSMT_FILTER_INCLUDED__
#define __MMSMT_FILTER_INCLUDED__
#include "mms_util.h"
struct MmsBoxMTfilter {
/* name of filter. */
char *name;
/* Init: called once for each mmc to determine if to use filter on MT MMS via the particular MMC. Returns 1
* on success, error otherwise
*/
int (*init)(Octstr *mmc_url, Octstr *mmc_id, Octstr *startup_params);
/* filter: Filter/transform the message. Return 0 on success. May modify the message itself of course */
int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id);
/* destroy this mmc's settings in filter. */
void (*destroy)(Octstr *mmc_id);
};
/* Each module must export this symbol, a pointer to the structure.
* WARNING: Ensure your module is thread-safe
*/
extern struct MmsBoxMTfilter mmsbox_mt_filter;
#endif

View File

@ -0,0 +1,40 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Resolving MSISDNs to local/remote MMSBox MMSC - interface
*
* Copyright (C) 2003 - 2007, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <stdio.h>
#include <stdlib.h>
#include "mmsbox_resolve.h"
#include "mmsbox_cfg.h"
static void *_resolvermodule_init(char *settings)
{
return NULL;
}
static int _resolvermodule_fini(void *module_data)
{
return 0;
}
static Octstr *_resolve(Octstr * pfrom, Octstr *pto, char *in_mmsc,
void *module_data, void *settings_p)
{
/* route normally to mms-service. */
return NULL;
}
/* The function itself. */
MmsBoxResolverFuncStruct mmsbox_resolvefuncs = {
_resolvermodule_init,
_resolve,
_resolvermodule_fini
};

View File

@ -0,0 +1,43 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Resolving MSISDNs to local/remote MMSBox MMSC - interface
*
* Copyright (C) 2003 - 2007, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMSBOX_RESOLVE_INCLUDED__
#define __MMSBOX_RESOLVE_INCLUDED__
#include <time.h>
#include "gwlib/gwlib.h"
/* Resolver module. This file provides prototypes for all resolver functions.
* the module is loaded once and _init is called once at load.
* _resolve is called for each incoming message to determine how to route it.
*/
typedef struct MmsBoxResolverFuncStruct {
/* This function is called once to initialise the resolver module. Return a generic object,
* which is passed with each resolution request..
*/
void *(*mmsbox_resolvermodule_init)(char *settings);
/* Looks up the sender and receiver msisdns and returns the ID of the MMC connection through which
* the received message should be sent.
* Note: This function may modify sender and/or receive to match prefered usage.
* Return NULL or the empty string to send the message to a service (normal behavior)
*/
Octstr *(*mmsbox_resolve)(Octstr *pfrom, Octstr *pto, char *from_mmsc,
void *module_data, void *settings);
int (*mmsbox_resolvermodule_fini)(void *module_data);
} MmsBoxResolverFuncStruct;
extern MmsBoxResolverFuncStruct mmsbox_resolvefuncs; /* The module must expose this symbol. */
#endif

View File

@ -0,0 +1,70 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Resolving MSISDNs to local/remote MMSCs - calling shell scripts
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <stdio.h>
#include <stdlib.h>
#include "mmsbox_resolve.h"
#include "mms_util.h"
static Octstr *script = NULL;
static void *_shell_resolvermodule_init(char *settings)
{
script = octstr_imm(settings);
return NULL;
}
static int _shell_resolvermodule_fini(void *module_data)
{
octstr_destroy(script);
script = NULL;
return 0;
}
static Octstr *_shell_resolve(Octstr *pfrom, Octstr *pto, char *in_mmc, void *module_data, void *settings_p)
{
Octstr *s;
FILE *fp;
char buf[4096];
if (script == NULL || octstr_len(script) == 0)
return 0;
s = octstr_format("%s '%s' '%s' '%s'",
octstr_get_cstr(script), octstr_get_cstr(pfrom), octstr_get_cstr(pto),
in_mmc);
mms_info(0, "mmsbox", NULL, "Preparing to call resolver as: %s", octstr_get_cstr(s));
fp = popen(octstr_get_cstr(s), "r");
octstr_destroy(s);
fgets(buf, sizeof buf, fp);
s = octstr_create(buf);
octstr_strip_crlfs(s);
pclose(fp);
mms_info(0, "mmsbox", NULL, "Resolver returned: %s", octstr_get_cstr(s));
if (octstr_len(s) == 0) {
octstr_destroy(s);
return NULL;
}
return s;
}
/* The function struct itself. */
MmsBoxResolverFuncStruct mmsbox_resolvefuncs_shell = {
_shell_resolvermodule_init,
_shell_resolve,
_shell_resolvermodule_fini
};

View File

@ -0,0 +1,22 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Resolving MSISDNs to local/remote MMSCs - interface (shell)
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMSBOX_RESOLVE_SHELL_INCLUDED__
#define __MMSBOX_RESOLVE_SHELL_INCLUDED__
#include <time.h>
#include "gwlib/gwlib.h"
#include "mmsbox_resolve.h"
extern MmsBoxResolverFuncStruct mmsbox_resolvefuncs_shell;
#endif

View File

@ -1,19 +1,13 @@
libmms = $(top_builddir)/mmlib/libmms.la
libmmsc = libmmsc.la
libmmsc = libmmsc.a
noinst_LTLIBRARIES = libmmsc.la
libmmsc_la_SOURCES = mmsc_cfg.c mms_detokenize.c mms_resolve.c mms_billing.c
noinst_LIBRARIES = libmmsc.a
libmmsc_a_SOURCES = mmsc_cfg.c mms_detokenize.c mms_resolve.c mms_billing.c mms_detokenize_shell.c mms_resolve_shell.c mms_billing_shell.c mmsc_mm5.c
bin_PROGRAMS = mmsrelay mmsproxy mmsfromemail mmssend
mmsrelay_SOURCES = mmsglobalsender.c mmsmobilesender.c mmsrelay.c
mmsrelay_LDADD = $(libmmsc) $(libmms)
mmsproxy_LDADD = $(libmmsc) $(libmms)
bin_PROGRAMS = mmsc mmsfromemail mmssend
mmsc_SOURCES = mmsc.c mmsglobalsender.c mmsmobilesender.c mmsrelay.c mmsproxy.c
mmsc_LDADD = $(libmmsc) $(libmms)
mmsfromemail_LDADD = $(libmmsc) $(libmms)
mmssend_LDADD = $(libmmsc) $(libmms)
pkglib_LTLIBRARIES = libmmsc_billing_shell.la libmmsc_resolve_shell.la libmmsc_detokenize_shell.la
libmmsc_billing_shell_la_SOURCES = mms_billing_shell.c
libmmsc_resolve_shell_la_SOURCES = mms_resolve_shell.c
libmmsc_detokenize_shell_la_SOURCES = mms_detokenize_shell.c
EXTRA_DIST = mms_billing.h mmsc_cfg.h mms_detokenize.h mmsrelay.h mms_resolve.h
EXTRA_DIST = mmsc.h mms_billing.h mms_detokenize_shell.h mms_billing_shell.h mms_resolve_shell.h mmsc_cfg.h mms_detokenize.h mms_resolve.h mmsc_mm5.h

View File

@ -3,7 +3,7 @@
*
* Mbuni sample billing handler module
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -33,7 +33,7 @@ static int mms_billingmodule_fini(void *module_data)
return module_data ? fclose(module_data) : -1;
}
static int mms_billmsg(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, void *module_data)
static int mms_billmsg(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, Octstr *msgid, void *module_data)
{
return 0;
}
@ -46,8 +46,11 @@ static int mms_logcdr(MmsCdrStruct *cdr)
localtime_r(&cdr->sdate, &tm);
gw_strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &tm);
fprintf(cdr->module_data, "%s\t%.128s\t%.256s\t%.256s\t%ld\n",
buf, cdr->from, cdr->to, cdr->msgid, cdr->msg_size);
fprintf(cdr->module_data, "%s\t%.128s\t%.128s\t%.128s\t%.256s\t%.256s\t%ld\n",
buf,
cdr->src_interface[0] ? cdr->src_interface : "MM2",
cdr->dst_interface[0] ? cdr->dst_interface : "MM2",
cdr->from, cdr->to, cdr->msgid, cdr->msg_size);
fflush(cdr->module_data);
} else
return -1;
@ -55,6 +58,26 @@ static int mms_logcdr(MmsCdrStruct *cdr)
return 0;
}
MmsCdrStruct *make_cdr_struct(void *module_data, time_t sdate, char *from, char *to, char *msgid,
char *vaspid, char *src_int, char *dst_int, unsigned long msg_size)
{
MmsCdrStruct *cdr = gw_malloc(sizeof *cdr);
cdr->module_data = module_data;
cdr->sdate = sdate;
strncpy(cdr->from, from ? from : "", sizeof cdr->from);
strncpy(cdr->to, to ? to : "", sizeof cdr->to);
strncpy(cdr->msgid, msgid ? msgid : "", sizeof cdr->msgid);
strncpy(cdr->vaspid, vaspid ? vaspid : "", sizeof cdr->vaspid);
strncpy(cdr->src_interface, src_int ? src_int : "MM2", sizeof cdr->src_interface);
strncpy(cdr->dst_interface, dst_int ? dst_int : "MM2", sizeof cdr->dst_interface);
cdr->msg_size = msg_size;
return cdr;
}
/* The function itself. */
MmsBillingFuncStruct mms_billfuncs = {
mms_billingmodule_init,

View File

@ -3,7 +3,7 @@
*
* Mbuni billing integration interface
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -31,6 +31,8 @@ typedef struct MmsCdrStruct {
char to[CBUFSIZE];
char msgid[CBUFSIZE];
char vaspid[CBUFSIZE];
char src_interface[CBUFSIZE];
char dst_interface[CBUFSIZE];
unsigned long msg_size;
} MmsCdrStruct;
@ -47,11 +49,14 @@ typedef struct MmsBillingFuncStruct {
/* Bills a message. Returns >= 0 if billed ok, -1 if message should be rejected,
* -2 on internal (temporary) error.
*/
int (*mms_billmsg)(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, void *module_data);
int (*mms_billmsg)(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, Octstr *msgid, void *module_data);
int (*mms_billingmodule_fini)(void *module_data);
} MmsBillingFuncStruct;
extern MmsBillingFuncStruct mms_billfuncs; /* The module must expose this symbol. */
/* utility function. */
MmsCdrStruct *make_cdr_struct(void *module_data, time_t sdate, char *from, char *to, char *msgid,
char *vaspid, char *src_int, char *dst_int, unsigned long msg_size);
#endif

View File

@ -12,6 +12,13 @@
*/
#include <stdio.h>
#include <stdlib.h>
#ifndef DARWIN
#ifndef FREEBSD
#include <wait.h>
#endif
#endif
#include <sys/wait.h>
#include "mms_billing.h"
@ -33,15 +40,16 @@ static int mms_billingmodule_fini(void *module_data)
return 0;
}
static int mms_billmsg(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, void *module_data)
static int mms_billmsg(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, Octstr *msgid, void *module_data)
{
int i;
if (script == NULL || octstr_len(script) == 0)
return 0;
for (i=0;i<list_len(to);i++) {
for (i=0;i<gwlist_len(to);i++) {
Octstr *s;
s = octstr_format("%s '%s' '%s'", octstr_get_cstr(script), octstr_get_cstr(from), octstr_get_cstr(list_get(to, i)));
s = octstr_format("%s '%s' '%s' '%S'", octstr_get_cstr(script), octstr_get_cstr(from),
octstr_get_cstr(gwlist_get(to, i)), msgid);
if (s) {
int ret = system(octstr_get_cstr(s));
octstr_destroy(s);
@ -60,7 +68,7 @@ static int mms_logcdr(MmsCdrStruct *cdr)
}
/* The function itself. */
MmsBillingFuncStruct mms_billfuncs = {
MmsBillingFuncStruct mms_billfuncs_shell = {
mms_billingmodule_init,
mms_logcdr,
mms_billmsg,

View File

@ -0,0 +1,24 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Mbuni billing integration interface (shell)
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMS_BILLING_SHELL_INCLUDED__
#define __MMS_BILLING_SHELL_INCLUDED__
#include <time.h>
#include "gwlib/gwlib.h"
#include "mms_billing.h"
extern MmsBillingFuncStruct mms_billfuncs_shell;
#endif

View File

@ -3,7 +3,7 @@
*
* Mbuni MSISDN mapper sample
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*

View File

@ -3,7 +3,7 @@
*
* Mbuni MSISDN mapper interface
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -26,19 +26,19 @@ typedef struct MmsDetokenizerFuncStruct {
/* This function is called once to initialise the detokenizer module. Return 0 on succeful
* initialization.
*/
int (*mms_detokenizer_init)(char *settings);
int (*mms_detokenizer_init)(char *settings);
/* Looks up the token and returns the msisdn as a new Octstr.
* Return NULL on error, otherwise an Octstr
*/
Octstr *(*mms_detokenize)(Octstr * token, Octstr *request_ip);
Octstr *(*mms_detokenize)(Octstr * token, Octstr *request_ip);
/* Given an msisdn, returns the token associated
* Return NULL on error, otherwise an Octstr
*/
Octstr *(*mms_gettoken)(Octstr *msisdn);
int (*mms_detokenizer_fini)(void);
Octstr *(*mms_gettoken)(Octstr *msisdn);
int (*mms_detokenizer_fini)(void);
} MmsDetokenizerFuncStruct;
extern MmsDetokenizerFuncStruct mms_detokenizefuncs; /* The module must expose this symbol. */

View File

@ -21,7 +21,7 @@ Octstr *script;
static int mms_detokenizer_init(char *settings)
{
script = octstr_create(settings);
info(0, "Detokenizer script set to \"%s\"", settings);
mms_info(0, "mms_detokenizer", NULL, "Detokenizer script set to \"%s\"", settings);
return 0;
}
@ -35,17 +35,29 @@ static int mms_detokenizer_fini(void)
return 0;
}
static Octstr *mms_detokenize(Octstr * token, Octstr *request_ip)
static Octstr *mms_detokenize(Octstr *token, Octstr *request_ip)
{
Octstr *cmd = NULL, *msisdn = NULL;
Octstr *tmp1, *tmp2;
FILE *fp;
char buf[4096];
if (script == NULL || octstr_len(script) == 0)
return NULL;
cmd = octstr_format("%s '%s'", octstr_get_cstr(script), octstr_get_cstr(token));
info(0, "Calling \"%s\"", octstr_get_cstr(cmd));
tmp1 = octstr_duplicate(token ? token : octstr_imm("x"));
tmp2 = octstr_duplicate(request_ip ? request_ip : octstr_imm("x"));
escape_shell_chars(tmp1);
escape_shell_chars(tmp2);
cmd = octstr_format("%s %s %s",
octstr_get_cstr(script),
octstr_get_cstr(tmp1),
octstr_get_cstr(tmp2));
octstr_destroy(tmp1);
octstr_destroy(tmp2);
mms_info(0, "mms_detokenizer", NULL, "Calling \"%s\"", octstr_get_cstr(cmd));
if ((fp = popen(octstr_get_cstr(cmd), "r"))) {
if (fgets(buf, sizeof buf, fp) != NULL) {
msisdn = octstr_create(buf);
@ -53,7 +65,7 @@ static Octstr *mms_detokenize(Octstr * token, Octstr *request_ip)
}
pclose(fp);
}
info(0, "%s \"%s\", returned msisdn = %s",
mms_info(0, "mms_detokenizer", NULL, "%s \"%s\", returned msisdn = %s",
fp ? "Called" : "Failed to call",
octstr_get_cstr(cmd),
msisdn ? octstr_get_cstr(msisdn) : "null");
@ -68,7 +80,7 @@ static Octstr *mms_gettoken(Octstr *msisdn)
}
/* The function itself. */
MmsDetokenizerFuncStruct mms_detokenizefuncs = {
MmsDetokenizerFuncStruct mms_detokenizefuncs_shell = {
mms_detokenizer_init,
mms_detokenize,
mms_gettoken,

View File

@ -0,0 +1,22 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Mbuni MSISDN mapper interface (shell)
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMS_DETOKENIZE_SHELL_INCLUDED__
#define __MMS_DETOKENIZE_SHELL_INCLUDED__
#include <time.h>
#include "gwlib/gwlib.h"
#include "mms_detokenize.h"
extern MmsDetokenizerFuncStruct mms_detokenizefuncs_shell;
#endif

View File

@ -3,7 +3,7 @@
*
* Resolving MSISDNs to local/remote MMSCs
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -25,7 +25,8 @@ static int mms_resolvermodule_fini(void *module_data)
return 0;
}
static Octstr *mms_resolve(Octstr * phonenum, void *module_data, void *settings_p, void *proxyrelays_p)
static Octstr *mms_resolve(Octstr * phonenum, char *src_int, char *src_id,
void *module_data, void *settings_p, void *proxyrelays_p)
{
/* Most custom implementations of this library will probably just ignore the two last arguments,
* but this one needs them
@ -36,13 +37,13 @@ static Octstr *mms_resolve(Octstr * phonenum, void *module_data, void *settings_
int j, m;
if (does_prefix_match(settings->local_prefix, phonenum)) {
return settings->hostname;
} else if (proxyrelays && list_len(proxyrelays) > 0) /* Step through proxies. */
for (j = 0, m = list_len(proxyrelays); j < m; j++) {
MmsProxyRelay *mp = list_get(proxyrelays, j);
return settings->hostname ? octstr_duplicate(settings->hostname) : NULL;
} else if (proxyrelays && gwlist_len(proxyrelays) > 0) /* Step through proxies. */
for (j = 0, m = gwlist_len(proxyrelays); j < m; j++) {
MmsProxyRelay *mp = gwlist_get(proxyrelays, j);
if (does_prefix_match(mp->allowed_prefix, phonenum) &&
!does_prefix_match(mp->denied_prefix, phonenum)) {
return mp->host;
return octstr_duplicate(mp->host);
}
}

View File

@ -3,7 +3,7 @@
*
* Resolving MSISDNs to local/remote MMSCs - interface
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -33,9 +33,11 @@ typedef struct MmsResolverFuncStruct {
*
* Return NULL on error, otherwise an Octstr
*/
Octstr *(*mms_resolve)(Octstr * phonenum, void *module_data, void *settings, void *proxyrelays);
Octstr *(*mms_resolve)(Octstr *phonenum, char *src_int, char *src_id,
void *module_data, void *settings, void *proxyrelays);
int (*mms_resolvermodule_fini)(void *module_data);
} MmsResolverFuncStruct;
extern MmsResolverFuncStruct mms_resolvefuncs; /* The module must expose this symbol. */

View File

@ -3,7 +3,7 @@
*
* Resolving MSISDNs to local/remote MMSCs - calling shell scripts
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -28,7 +28,8 @@ static int mms_resolvermodule_fini(void *module_data)
return 0;
}
static Octstr *mms_resolve(Octstr * phonenum, void *module_data, void *settings_p, void *proxyrelays_p)
static Octstr *mms_resolve(Octstr *phonenum, char *src_int, char *src_id,
void *module_data, void *settings_p, void *proxyrelays_p)
{
Octstr *s;
FILE *fp;
@ -37,21 +38,28 @@ static Octstr *mms_resolve(Octstr * phonenum, void *module_data, void *settings_
if (script == NULL || octstr_len(script) == 0)
return 0;
s = octstr_format("%s '%s' ", octstr_get_cstr(phonenum));
s = octstr_format("%s '%s' '%s' '%s'",
octstr_get_cstr(script), octstr_get_cstr(phonenum) ,
src_int ? src_int : "", src_id ? src_id : "");
fp = popen(octstr_get_cstr(s), "r");
octstr_destroy(s);
fgets(buf, 4096, fp);
fgets(buf, sizeof buf, fp);
s = octstr_create(buf);
octstr_strip_crlfs(s);
pclose(fp);
if (octstr_len(s) == 0) {
octstr_destroy(s);
return NULL;
}
return s;
}
/* The function itself. */
MmsResolverFuncStruct mms_resolvefuncs = {
MmsResolverFuncStruct mms_resolvefuncs_shell = {
mms_resolvermodule_init,
mms_resolve,
mms_resolvermodule_fini

View File

@ -0,0 +1,22 @@
/*
* Mbuni - Open Source MMS Gateway
*
* Resolving MSISDNs to local/remote MMSCs - interface (shell)
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMS_RESOLVE_SHELL_INCLUDED__
#define __MMS_RESOLVE_SHELL_INCLUDED__
#include <time.h>
#include "gwlib/gwlib.h"
#include "mms_resolve.h"
extern MmsResolverFuncStruct mms_resolvefuncs_shell;
#endif

105
mbuni/mmsc/mmsc.c Normal file
View File

@ -0,0 +1,105 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSC: Full MMSC startup
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <signal.h>
#include "mmsc.h"
#include "mms_uaprof.h"
MmscSettings *settings;
List *proxyrelays;
static void quit_now(int notused)
{
stop_mmsrelay();
stop_mmsproxy();
}
/* manage the SIGHUP signal */
static void relog_now(int notused)
{
mms_warning(0, "mmsc", NULL, "SIGHUP received, catching and re-opening logs");
log_reopen();
alog_reopen();
}
int main(int argc, char *argv[])
{
int cfidx;
Octstr *fname;
long r_thread = 0;
mms_lib_init();
srandom(time(NULL));
cfidx = get_and_set_debugs(argc, argv, NULL);
if (argv[cfidx] == NULL)
fname = octstr_imm("mbuni.conf");
else
fname = octstr_create(argv[cfidx]);
mms_info(0, "mmsc", NULL, "----------------------------------------");
mms_info(0, "mmsc", NULL," " MM_NAME " MMSC version %s starting", MMSC_VERSION);
settings = mms_load_mmsc_settings(fname,&proxyrelays, 0);
octstr_destroy(fname);
if (!settings)
panic(0, "No MMSC configuration!");
#ifdef SA_RESTART
{
struct sigaction nact;
memset(&nact, 0, sizeof(nact));
nact.sa_handler = relog_now;
nact.sa_flags = SA_RESTART;
sigaction(SIGHUP, &nact, (struct sigaction *)0);
}
#else
signal(SIGHUP, relog_now);
#endif
signal(SIGTERM, quit_now);
signal(SIGINT, quit_now);
signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for no reason*/
mms_info(0, "mmsc", NULL," " MM_NAME " MMSC services:%s%s%s%s",
(settings->svc_list & SvcMM1) ? " MM1" : "",
(settings->svc_list & SvcMM7) ? " MM7" : "",
(settings->svc_list & SvcRelay) ? " Relay" : "",
(settings->svc_list & (SvcMM1 | SvcMM7 | SvcRelay)) ? "" : " None");
mms_info(0, "mmsc", NULL, "----------------------------------------");
if ((r_thread = gwthread_create((gwthread_func_t *)mmsrelay, NULL)) < 0)
panic(0, "Failed to start MMSC Relay component!");
if (mmsproxy() < 0)
panic(0, "Failed to start MMSC Relay component!");
/* We are done. Cleanup. */
gwthread_join(r_thread);
mms_info(0, "mmsc", NULL, "MMSC shutdown commenced.");
gwthread_sleep(2); /* Wait for them to die. */
mms_info(0, "mmsc", NULL, "Final cleanup...");
mms_cleanup_mmsc_settings(settings); /* Stop settings stuff and so on. */
mms_info(0, "mmsc", NULL,"Shutdown complete...");
mms_lib_shutdown();
return 0;
}

30
mbuni/mmsc/mmsc.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MMSC: Full MMSC startup
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MBUNI_MMSC_INCLUDED__
#define __MBUNI_MMSC_INCLUDED__
#include "mmsc_cfg.h"
int mmsproxy(void);
void stop_mmsproxy(void);
int mmsrelay(void);
int stop_mmsrelay(void);
extern void mbuni_global_queue_runner(volatile sig_atomic_t *stopflag);
extern void mbuni_mm1_queue_runner(volatile sig_atomic_t *stopflag);
extern MmscSettings *settings;
extern List *proxyrelays;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* MMSC CFG: MMC configuration and misc. functions
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -13,41 +13,68 @@
#ifndef __MMSC_CFG__
#define __MMSC_CFG__
#include "mms_util.h"
#include "mms_resolve.h"
#include "mms_billing.h"
#include "mms_detokenize.h"
#include "mms_resolve_shell.h"
#include "mms_billing_shell.h"
#include "mms_detokenize_shell.h"
#include "mms_queue.h"
#include "mmsc_mm5.h"
typedef struct MmsProxyRelay {
Octstr *host;
Octstr *name;
Octstr *allowed_prefix;
Octstr *denied_prefix;
Octstr *unified_prefix;
List *strip_prefixes;
int confirmed_mm4;
Octstr *sendmail;
} MmsProxyRelay;
typedef struct MmsVasp {
Octstr *id;
long short_code;
long *short_codes; /* array of short codes. */
int num_short_codes; /* number of short codes above. */
enum {SOAP_VASP, EAIF_VASP, NONE_VASP} type;
Octstr *vasp_username, *vasp_password;
Octstr *vasp_url;
Octstr *mmsc_username, *mmsc_password;
enum {UAProf_None, UAProf_URL, UAProf_UA} send_uaprof;
MM7Version_t ver;
double throughput;
time_t delete_after; /* Set, when thingie should be deleted. */
struct {
unsigned long mo_pdus, mt_pdus;
unsigned long mo_errors, mt_errors;
time_t start_time, last_pdu;
} stats;
} MmsVasp;
typedef struct MmscSettings {
Octstr *system_user;
Octstr *name, *hostname, *host_alias;
List *local_domains;
Octstr *unified_prefix, *local_prefix;
List *strip_prefixes;
Octstr *sendmail;
Octstr *global_queuedir, *mm1_queuedir, *mm4_queuedir;
Octstr *smtp_relay;
int smtp_port;
Octstr *global_queuedir, *mm1_queuedir;
Octstr *mmbox_rootdir;
MmsQueueHandlerFuncs *qfs;
Octstr *ua_profile_cache_dir;
long maxthreads;
long maxsendattempts;
long maxsendattempts, mm1_maxsendattempts;
long default_msgexpiry;
double queue_interval;
long max_msgexpiry;
double queue_interval, mm1_queue_interval;
long send_back_off;
long port, mm7port;
@ -77,7 +104,8 @@ typedef struct MmscSettings {
int optimize_notification_size;
int content_adaptation;
int dlr_on_fetch;
Octstr *prov_notify;
Octstr *prov_getstatus;
@ -88,27 +116,57 @@ typedef struct MmscSettings {
Octstr *mms_email_txt;
Octstr *mms_email_html;
Octstr *wap_gw_msisdn_header;
Octstr *wap_gw_ip_header;
Octstr *mms_email_subject;
List *wap_gw_msisdn_header;
List *wap_gw_ip_header;
List *vasp_list; /* of MmsVasp * */
MmsVasp *mms2email, *mms2mobile;
Dict *vasp_list; /* of MmsVasp *, indexed by ID */
List *vasp_del_list; /* stuff to be deleted! */
MmsVasp *mms2email, *mms2mobile;
MmscMM5FuncStruct *mm5; /* If we have loaded an mm5 module, this is it. */
/* Stuff for the admin interface. */
long admin_port;
Octstr *admin_allow_ip, *admin_deny_ip;
Octstr *admin_pass;
long admin_thread;
unsigned int svc_list; /* List of started services */
mCfg *cfg; /* have a pointer to it. */
} MmscSettings;
/* Returns mmsc settings. */
MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays);
enum {SvcMM1=1, SvcMM7=2, SvcRelay=4}; /* List of started services */
/* Returns mmsc settings. */
MmscSettings *mms_load_mmsc_settings(Octstr *fname, List **proxyrelays, int skip_admin_port);
MmsVasp *mmsc_load_vasp_from_conf(MmscSettings *m, mCfgGrp *grp,
List *errors, List *warnings);
int mmsc_unload_vasp(MmscSettings *m, Octstr *id);
/* do final cleanup. */
void mms_cleanup_mmsc_settings(MmscSettings *settings);
/* Returns list of MmsProxyRelay */
extern List *mms_proxy_relays(mCfg *cfg);
extern List *mms_proxy_relays(mCfg *cfg, Octstr *myhostname);
extern Octstr *mms_makefetchurl(char *qf, Octstr *token, int loc,
Octstr *to,
MmscSettings *settings);
Octstr *mms_find_sender_msisdn(Octstr *send_url, List *request_hdrs,
Octstr *msisdn_header,
Octstr *requestip_header,
Octstr *mms_find_sender_msisdn(Octstr *send_url,
Octstr *ip,
List *request_hdrs,
List *msisdn_header,
List *requestip_header,
MmsDetokenizerFuncStruct *detokenizerfuncs);
extern int mms_decodefetchurl(Octstr *fetch_url,
Octstr **qf, Octstr **token, int *loc);
Octstr *mms_find_sender_ip(List *request_hdrs, List *ip_header, Octstr *ip, int *isv6);
void notify_prov_server(char *cmd, char *from, char *event, char *arg, Octstr *msgid,
Octstr *ua, Octstr *uaprof);
int mms_ind_send(Octstr *prov_cmd, Octstr *to);
#endif

108
mbuni/mmsc/mmsc_mm5.c Normal file
View File

@ -0,0 +1,108 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MM5 interface, query/save mapping from msisdn to uaprof string/url
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <stdio.h>
#include <stdlib.h>
#include "mmsc_mm5.h"
#include "mms_util.h"
static char cmd[1024] = "true";
static int mm5_shell_init(char *shell_cmd)
{
strncpy(cmd, shell_cmd, sizeof cmd);
return 0;
}
static void mm5_shell_update(char *phonenum, char *uaprof_url, char *ua_string)
{
Octstr *x;
Octstr *y;
Octstr *z;
Octstr *s;
if (phonenum == NULL)
return;
x = uaprof_url ? octstr_create(uaprof_url) : octstr_imm("");
y = ua_string ? octstr_create(ua_string) : octstr_imm("");
z = octstr_create(phonenum);
escape_shell_chars(x);
escape_shell_chars(y);
escape_shell_chars(z);
s = octstr_format("%s '%S' '%S' '%S'", cmd, z, x, y);
system(octstr_get_cstr(s));
octstr_destroy(s);
octstr_destroy(x);
octstr_destroy(y);
octstr_destroy(z);
}
static int mm5_shell_query(char *phonenum, char uaprof_url[], char *ua_string,
int buflen)
{
FILE *fp;
char buf[4096], *p;
int ret;
Octstr *z;
Octstr *s;
if (phonenum == NULL)
return -1;
z = octstr_create(phonenum);
escape_shell_chars(z);
s = octstr_format("%s '%S'", cmd, z);
if ((fp = popen(octstr_get_cstr(s), "r")) != NULL) {
if (uaprof_url) {
uaprof_url[0] = 0;
p = fgets(buf, sizeof buf, fp);
if (p)
strncpy(uaprof_url, p, buflen);
}
if (ua_string) {
ua_string[0] = 0;
p = fgets(buf, sizeof buf, fp);
if (p)
strncpy(ua_string, p, buflen);
}
pclose(fp);
ret = 0;
} else
ret = -1;
octstr_destroy(s);
octstr_destroy(z);
return ret;
}
static void shell_cleanup(void)
{
}
MmscMM5FuncStruct _x = {
mm5_shell_init,
mm5_shell_update,
mm5_shell_query,
shell_cleanup
}, *shell_mm5 = &_x;

45
mbuni/mmsc/mmsc_mm5.h Normal file
View File

@ -0,0 +1,45 @@
/*
* Mbuni - Open Source MMS Gateway
*
* MM5 interface, query/save mapping from msisdn to uaprof string/url
*
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#ifndef __MMS_MM5_INCLUDED__
#define __MMS_MM5_INCLUDED__
#include <time.h>
#include "gwlib/gwlib.h"
/* mm5 module. This file provides prototypes for all mm5 interface functions.
*
*/
typedef struct MmscMM5FuncStruct {
/* This function is called once to initialise the mm5 interface module. Return a generic object,
* which is passed with each request.
*/
int (*init)(char *settings);
/* Save the UaProf URL and UserAgent string for given phone number. */
void (*update)(char *phonenum,
char *uaprof_url, char *ua_string);
/* Query for the uaprof and ua string. Return them in the buffers provided.
* return 0 on success, -1 on error.
*/
int (*query)(char *phonenum, char uaprof_url[], char *ua_string,
int buflen);
void (*cleanup)(void);
} MmscMM5FuncStruct;
/* Any module must export a symbol of the above type, with name 'mm5_funcs' */
extern MmscMM5FuncStruct *shell_mm5; /* Handler when using shell script. */
#endif

View File

@ -3,7 +3,7 @@
*
* Email2MMS and MM4 (incoming) interface
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -23,27 +23,36 @@ static Octstr *xproxy;
enum {TPLMN, TEMAIL, TOTHER} ttype;
/* above indexed by types! */
static int find_own(int i, int argc, char *argv[]);
static void fixup_recipient(void);
static void fixup_recipient(Octstr **host);
static void fixup_sender(void);
static void fixup_addresses(List *headers);
static void send_mm4_res(int mtype, Octstr *to, Octstr *sender,
Octstr *transid, char *status, Octstr *msgid,
Octstr *sendmail_cmd);
static mCfg *cfg;
static List *proxyrelays;
static int no_strip = 0, strip_type = 0;
int main(int argc, char *argv[])
{
int cfidx;
Octstr *fname;
MIMEEntity *mm;
MmsMsg *msg;
Octstr *email;
Octstr *home_mmsc = NULL;
mms_lib_init();
Octstr *email, *me, *rstatus, *fname;
Octstr *home_mmsc = NULL, *rhost = NULL;
List *headers, *h2;
Octstr *mm4_type = NULL, *transid, *ack, *msgid, *orig_sys;
Octstr *newmsgid = NULL;
srandom(time(NULL));
int mtype = -1, mm1_type = -1, cfidx, i;
char *err = NULL;
mms_lib_init();
cfidx = get_and_set_debugs(argc, argv, find_own);
@ -52,42 +61,36 @@ int main(int argc, char *argv[])
else
fname = octstr_create(argv[cfidx]);
cfg = mms_cfg_read(fname);
if (cfg == NULL)
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
mms_info(0, "mmsfromemail", NULL, "----------------------------------------");
mms_info(0, "mmsfromemail", NULL, " MMSC Email2MMS/MM4 Incoming Tool version %s starting", MMSC_VERSION);
octstr_destroy(fname);
info(0, "----------------------------------------");
info(0, " MMSC Email2MMS Tool version %s starting", MMSC_VERSION);
/* Load settings. */
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
mms_cfg_destroy(cfg);
settings = mms_load_mmsc_settings(fname, &proxyrelays,1);
if (!settings)
panic(0, "No global MMSC configuration!");
panic(0, "No global MMSC configuration, or failed to read conf from <%s>!", octstr_get_cstr(fname));
if (!xto || !xfrom)
panic(0, "usage: %s -f from -t to!", argv[0]);
octstr_destroy(fname);
if (!xto || !xfrom) {
mms_error(0, "mmsfromemail", NULL, "usage: %s -f from -t to!", argv[0]);
return -1;
}
/* normalize recipient address, then if phone number,
* check whether we are allowed to process.
*/
fixup_recipient();
fixup_recipient(&rhost);
fixup_sender();
if (xto && ttype == TPLMN) /* Get the home mmsc domain for this recipient. */
home_mmsc = settings->mms_resolvefuncs->mms_resolve(xto,
"MM4", xproxy ? octstr_get_cstr(xproxy) : NULL,
settings->mms_resolver_module_data,
settings, proxyrelays);
if (!xto ||
(ttype == TPLMN && (!home_mmsc ||
!is_allowed_host(home_mmsc,
settings->email2mmsrelay_hosts)))) {
error(0, " Not allowed to send to this recipient %s, resolved mmsc=%s!",
mms_error(0, "mmsfromemail", NULL, " Not allowed to send to this recipient %s, resolved mmsc=%s!",
xto ? octstr_get_cstr(xto) : "(null)",
home_mmsc ? octstr_get_cstr(home_mmsc) : "(null)");
mms_lib_shutdown();
@ -98,13 +101,13 @@ int main(int argc, char *argv[])
email = octstr_read_pipe(stdin);
if (!email || octstr_len(email) == 0) {
error(0, "Empty email message!");
mms_error(0, "mmsfromeail", NULL, "Empty email message!");
mms_lib_shutdown();
return -1;
}
if ((mm = mime_octstr_to_entity(email)) == NULL) {
error(0, "Unable to decode mime entity!");
mms_error(0, "mmsfromeail", NULL, "Unable to decode mime entity!");
mms_lib_shutdown();
return -1;
}
@ -115,37 +118,145 @@ int main(int argc, char *argv[])
unpack_mimeheaders(mm);
/* Delete some headers... */
http_header_remove_all(mm->headers, "Received");
http_header_remove_all(mm->headers, "X-MimeOLE");
http_header_remove_all(mm->headers, "X-Mailer");
headers = mime_entity_headers(mm);
http_header_remove_all(headers, "Received");
http_header_remove_all(headers, "X-MimeOLE");
http_header_remove_all(headers, "X-Mailer");
/* Now convert from mime to MMS message. */
msg = mms_frommime(mm);
mime_entity_destroy(mm);
if (!msg) {
error(0, "Unable to create MM!");
mms_lib_shutdown();
return -1;
/* rebuild headers, removing nasty looking ones. */
h2 = http_create_empty_headers();
for (i = 0; i<gwlist_len(headers); i++) {
Octstr *name = NULL, *value = NULL;
http_header_get(headers, i, &name, &value);
if (!name ||
octstr_case_search(name, octstr_imm("spam"), 0) >= 0 ||
octstr_case_search(name, octstr_imm("mailscanner"), 0) >= 0)
goto loop;
http_header_add(h2, octstr_get_cstr(name), octstr_get_cstr(value));
loop:
octstr_destroy(name);
octstr_destroy(value);
}
http_destroy_headers(headers);
headers = h2;
/* Look for MM4 headers... */
mm4_type = http_header_value(headers, octstr_imm("X-Mms-Message-Type"));
ack = http_header_value(headers, octstr_imm("X-Mms-Ack-Request"));
rstatus = http_header_value(headers, octstr_imm("X-Mms-Request-Status-Code"));
switch(mms_messagetype(msg)) {
case MMS_MSGTYPE_SEND_REQ:
if (ttype != TPLMN)
error(0, "Not allowed to send to non-phone recipient, to=%s!", octstr_get_cstr(xto));
else {
List *lto = list_create();
if ((transid = http_header_value(headers, octstr_imm("X-Mms-Transaction-ID"))) == NULL)
transid = octstr_create("001");
/* get originator system. */
if ((orig_sys = http_header_value(headers, octstr_imm("X-Mms-Originator-System"))) == NULL)
orig_sys = http_header_value(headers, octstr_imm("Sender"));
if (xproxy == NULL && orig_sys != NULL) { /* Copy proxy address from originator system. */
int i = octstr_search_char(orig_sys, '@', 0);
if (i >= 0)
xproxy = octstr_copy(orig_sys, i+1, octstr_len(orig_sys));
}
if ((msgid = http_header_value(headers, octstr_imm("X-Mms-Message-ID"))) == NULL)
msgid = http_header_value(headers, octstr_imm("Message-ID"));
strip_quoted_string(msgid);
strip_quoted_string(transid);
mms_info(0, "MM4", NULL, "Received [message type: %s] [transaction id: %s] [origin: %s] [msgid: %s]",
mm4_type ? octstr_get_cstr(mm4_type) : "",
transid ? octstr_get_cstr(transid) : "",
orig_sys ? octstr_get_cstr(orig_sys) : "",
msgid ? octstr_get_cstr(msgid) : "");
/* ... and remove non-essential ones */
http_header_remove_all(headers, "X-Mms-3GPP-MMS-Version");
http_header_remove_all(headers, "MIME-Version");
http_header_remove_all(headers, "X-Mms-Message-ID");
http_header_remove_all(headers, "Message-ID");
http_header_remove_all(headers, "X-Mms-Ack-Request");
http_header_remove_all(headers, "X-Mms-Originator-System");
http_header_remove_all(headers, "Sender");
/* msgid was there, put it back in proper form. */
if (msgid)
http_header_add(headers, "Message-ID", octstr_get_cstr(msgid));
fixup_addresses(headers);
if (mm4_type) {
unsigned char *x = NULL;
Octstr *y;
int i;
http_header_remove_all(headers, "X-Mms-Message-Type");
for (i = 0; mm4_types[i].mm4str; i++)
if (octstr_str_case_compare(mm4_type, mm4_types[i].mm4str) == 0) {
mtype = i;
mm1_type = mm4_types[i].mm1_type;
x = mms_message_type_to_cstr(mm1_type);
break;
}
if (x) {
http_header_add(headers, "X-Mms-Message-Type", (char *)x);
if (orig_sys == NULL) /* Make it up! */
orig_sys = octstr_format("system-user@%S",
xproxy ? xproxy : octstr_imm("unknown"));
} else {
octstr_destroy(mm4_type);
mm4_type = NULL; /* So that we assume normal message below. */
}
if ((y = http_header_value(headers, octstr_imm("X-Mms-MM-Status-Code"))) != NULL) {
/* This field is different on MM1. */
http_header_remove_all(headers, "X-Mms-MM-Status-Code");
http_header_add(headers, "X-Mms-Status", octstr_get_cstr(y));
octstr_destroy(y);
}
}
if (mm4_type == NULL && mtype < 0) { /* else assume a normal send message. */
http_header_add(headers, "X-Mms-Message-Type", "m-send-req");
mm1_type = MMS_MSGTYPE_SEND_REQ;
mtype = MM4_FORWARD_REQ;
}
mime_replace_headers(mm, headers);
http_destroy_headers(headers);
/* Now convert from mime to MMS message, if we should */
if (mm1_type >= 0) {
if ((msg = mms_frommime(mm)) == NULL) {
mms_error(0, "mmsfromeail", NULL, "Unable to create MM!");
mms_lib_shutdown();
return -1;
}
} else
msg = NULL;
mime_entity_destroy(mm);
me = octstr_format("system-user@%S", settings->hostname);
switch(mtype) {
case MM4_FORWARD_REQ:
if (ttype != TPLMN && settings->mms2email == NULL) {
err = "Error-service-denied";
mms_error(0, "MM4", NULL, "Not allowed to send to non-phone recipient, to=%s!", octstr_get_cstr(xto));
} else {
List *lto = gwlist_create();
Octstr *qf;
Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID"));
Octstr *dreport = mms_get_header_value(msg,
octstr_imm("X-Mms-Delivery-Report"));
char *err;
Octstr *rto;
Octstr *dreport = mms_get_header_value(msg, octstr_imm("X-Mms-Delivery-Report"));
int dlr;
octstr_format_append(xto, "/TYPE=PLMN");
list_append(lto, xto);
if (ttype == TPLMN)
octstr_format_append(xto, "/TYPE=PLMN");
else
octstr_format_append(xto, "@%S", rhost);
gwlist_append(lto, xto);
if (dreport &&
octstr_case_compare(dreport, octstr_imm("Yes")) == 0)
@ -153,16 +264,23 @@ int main(int argc, char *argv[])
else
dlr = 0;
qf = mms_queue_add(xfrom, lto, NULL, xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
dlr,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
if (qf) {
qf = settings->qfs->mms_queue_add(xfrom, lto, NULL, xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
NULL,
dlr,
octstr_get_cstr(settings->global_queuedir),
mm4_type ? "MM4" : "MM3",
settings->host_alias);
info(0, "Email2MMS Queued message to %s from %s (via %s) => %s",
newmsgid = msgid ? octstr_duplicate(msgid) :
qf ? mms_make_msgid(octstr_get_cstr(qf),
settings->host_alias) : NULL;
if (qf) {
mms_info(0, "mmsfromemail", NULL, "%s Queued message to %s from %s (via %s) => %s",
mm4_type ? "MM4 Incoming" : "Email2MMS",
octstr_get_cstr(xto), octstr_get_cstr(xfrom),
xproxy ? octstr_get_cstr(xproxy) : "(None)", octstr_get_cstr(qf));
octstr_destroy(qf);
@ -170,154 +288,210 @@ int main(int argc, char *argv[])
/* Queue our response to the chap. */
err = "Ok";
} else
err = "Error-transient-failure";
if (xproxy) {
MmsMsg *mresp;
List *xlto;
mresp = mms_sendconf(err, octstr_get_cstr(msgid),
transid ? octstr_get_cstr(transid) : "001",
0,MS_1_1);
rto = octstr_format("system-user@%S", xproxy);
xlto = list_create();
list_append(xlto, rto);
qf = mms_queue_add(settings->system_user, xlto, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry,
mresp, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
list_destroy(xlto, (list_item_destructor_t *)octstr_destroy);
mms_destroy(mresp);
octstr_destroy(qf);
}
err = "Error-network-problem";
mms_log("Received", xfrom, lto,
-1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL,NULL);
-1, msgid, NULL, xproxy, mm4_type ? "MM4" : "MM3", NULL,NULL);
list_destroy(lto,NULL);
octstr_destroy(transid);
octstr_destroy(msgid);
gwlist_destroy(lto,NULL);
if (dreport)
octstr_destroy(dreport);
}
break;
case MMS_MSGTYPE_SEND_CONF:
case MM4_DELIVERY_REPORT_REQ:
if (ttype != TPLMN && settings->mms2email == NULL) { /* We only send to phones from this interface */
mms_error(0, "MM4", NULL, "Not allowed to send to %s!", octstr_get_cstr(xto));
err = "Error-service-denied";
} else {
List *lto = gwlist_create();
Octstr *qf;
if (ttype == TPLMN)
octstr_format_append(xto, "/TYPE=PLMN");
else
octstr_format_append(xto, "@%S", rhost);
gwlist_append(lto, xto);
qf = settings->qfs->mms_queue_add(xfrom, lto, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
NULL,
0,
octstr_get_cstr(settings->global_queuedir),
"MM4",
settings->host_alias);
gwlist_destroy(lto, NULL);
if (qf) {
mms_info(0, "MM4", xproxy,"Queued DLR from proxy %s to %s from %s => %s",
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
octstr_get_cstr(qf));
octstr_destroy(qf);
err = "Ok";
} else
err = "Error-network-problem";
newmsgid = msgid ? octstr_duplicate(msgid) : NULL; /* report old msg id */
}
break;
case MM4_READ_REPLY_REPORT_REQ:
if (ttype != TPLMN && settings->mms2email == NULL) { /* We only send to phones from this interface */
mms_error(0, "MM4", NULL, "Not allowed to send to %s!", octstr_get_cstr(xto));
err = "Error-service-denied";
} else {
List *lto = gwlist_create();
Octstr *qf;
if (ttype == TPLMN)
octstr_format_append(xto, "/TYPE=PLMN");
else
octstr_format_append(xto, "@%S", rhost);
gwlist_append(lto, xto);
qf = settings->qfs->mms_queue_add(xfrom, lto, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
NULL,
0,
octstr_get_cstr(settings->global_queuedir),
"MM4",
settings->host_alias);
gwlist_destroy(lto, NULL);
if (qf) {
mms_info(0, "MM4", xproxy, "Queued read report from proxy %s to %s from %s => %s",
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
octstr_get_cstr(qf));
octstr_destroy(qf);
err = "Ok";
} else
err = "Error-network-problem";
}
break;
case MM4_FORWARD_RES:
case MM4_READ_REPLY_REPORT_RES:
case MM4_DELIVERY_REPORT_RES: /* remove corresponding queue entry. */
{
Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID"));
Octstr *qf = mms_getqf_fromtransid(transid);
Octstr *qf, *o_to;
int i;
octstr_destroy(transid);
/* Pull the number out of the fake transaction ID */
if ((i = octstr_search_char(transid, '-',0)) > 0) {
o_to = octstr_copy(transid, 0, i);
#if 0
_mms_fixup_address(o_to, settings->unified_prefix ? octstr_get_cstr(settings->unified_prefix) : NULL);
#else
mms_normalize_phonenum(&o_to,
octstr_get_cstr(settings->unified_prefix),
settings->strip_prefixes);
#endif
octstr_delete(transid, 0, i+1);
} else
o_to = NULL;
qf = mms_getqf_fromtransid(transid);
if (qf) {
MmsEnvelope *e = mms_queue_readenvelope(octstr_get_cstr(qf),
octstr_get_cstr(settings->mm4_queuedir),
MmsEnvelope *e;
octstr_strip_blanks(qf);
strip_quotes(qf);
octstr_strip_blanks(o_to);
strip_quotes(o_to);
e = settings->qfs->mms_queue_readenvelope(octstr_get_cstr(qf),
octstr_get_cstr(settings->global_queuedir),
1);
if (!e)
warning(0, "Received confirm MMS but cannot find message %s [%s] in queue!",
mms_warning(0, "MM4", xproxy, "MM4 Received %s from %s but cannot find queue entry for transaction %s [%s]!",
mm4_types[mtype].mm4str,
octstr_get_cstr(xproxy),
octstr_get_cstr(transid),
octstr_get_cstr(qf));
else {
MmsEnvelopeTo *t;
int i, n;
int processed = 0;
for (i = 0, n = list_len(e->to); i<n; i++)
if ((t = list_get(e->to, i)) != NULL)
for (i = 0, n = gwlist_len(e->to); i<n; i++)
if ((t = gwlist_get(e->to, i)) != NULL &&
(o_to == NULL || octstr_case_compare(o_to, t->rcpt) == 0)) {
t->process = 0; /* Should make it go away. */
mms_queue_update(e);
info(0, "Email2MMS received send conf from proxy %s to %s from %s => %s",
octstr_get_cstr(xproxy), octstr_get_cstr(xto),
processed = 1;
}
/* write CDR if it is a forward confirmation */
if (processed && mtype == MM4_FORWARD_RES &&
rstatus && octstr_str_case_compare(rstatus, "Ok") == 0) {
MmsCdrStruct *cdr = make_cdr_struct(settings->mms_bill_module_data,
e->created, octstr_get_cstr(e->from),
o_to ? octstr_get_cstr(o_to) : "",
e->msgId ? octstr_get_cstr(e->msgId) : "",
e->vaspid ? octstr_get_cstr(e->vaspid) : "",
e->src_interface,
"MM4", e->msize);
settings->mms_billfuncs->mms_logcdr(cdr);
gw_free(cdr);
}
mms_info(0, "MM4", xproxy, "Received %s from proxy %s to %s from %s => %s, status: [%s, %s]",
mm4_types[mtype].mm4str,
octstr_get_cstr(xproxy), o_to ? octstr_get_cstr(o_to) : octstr_get_cstr(xto),
octstr_get_cstr(xfrom),
octstr_get_cstr(qf));
octstr_get_cstr(qf),
rstatus ? octstr_get_cstr(rstatus) : "",
processed ? "Sender number matched in queue file" : "Sender number not matched in queue file");
if (settings->qfs->mms_queue_update(e) != 1)
settings->qfs->mms_queue_free_env(e);
}
} else
warning(0, "Received confirm MMS but cannot find message %s in queue!",
mms_warning(0, "MM4", xproxy, "Received %s but cannot find message %s in queue!",
mm4_types[mtype].mm4str,
octstr_get_cstr(transid));
octstr_destroy(o_to);
}
break;
case MMS_MSGTYPE_DELIVERY_IND:
if (ttype != TPLMN) /* We only send to phones from this interface */
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
else {
List *lto = list_create();
Octstr *qf;
octstr_format_append(xto, "/TYPE=PLMN");
list_append(lto, xto);
qf = mms_queue_add(xfrom, lto, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
list_destroy(lto, NULL);
if (qf) {
info(0, "Email2MMS Queued DLR from proxy %s to %s from %s => %s",
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
octstr_get_cstr(qf));
octstr_destroy(qf);
}
list_destroy(lto, NULL);
}
break;
case MMS_MSGTYPE_READ_REC_IND:
mms_convert_readrec2readorig(msg);
/* Fall through. */
case MMS_MSGTYPE_READ_ORIG_IND:
if (ttype != TPLMN) /* We only send to phones from this interface */
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
else {
List *lto = list_create();
Octstr *qf;
octstr_format_append(xto, "/TYPE=PLMN");
list_append(lto, xto);
qf = mms_queue_add(xfrom, lto, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
list_destroy(lto, NULL);
if (qf) {
info(0, "Email2MMS Queued read report from proxy %s to %s from %s => %s",
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
octstr_get_cstr(qf));
octstr_destroy(qf);
}
list_destroy(lto, NULL);
}
break;
default:
{
int x = mms_messagetype(msg);
warning(0, "Unexpected message type: %d=>%s",
x,
mms_message_type_to_cstr(x));
mms_warning(0, "MM4", xproxy, "Unexpected message type: %s",
mm4_type ? octstr_get_cstr(mm4_type) : "not given!");
break;
}
}
/* respond to the sender as necessary. */
if (mm4_type &&
err &&
ack && octstr_str_case_compare(ack, "Yes") == 0) {
int i, n;
Octstr *sendmail_cmd = settings->sendmail;
/* try and find proxy and it's send command. */
if (xproxy)
for (i = 0, n = gwlist_len(proxyrelays); i<n; i++) {
MmsProxyRelay *mp = gwlist_get(proxyrelays, i);
if (mp && octstr_case_compare(xproxy, mp->host) == 0 &&
mp->sendmail) {
sendmail_cmd = mp->sendmail;
break;
}
}
send_mm4_res(mtype+1, orig_sys, me, transid, err, newmsgid, sendmail_cmd);
}
octstr_destroy(mm4_type);
octstr_destroy(transid);
octstr_destroy(orig_sys);
octstr_destroy(msgid);
octstr_destroy(newmsgid);
octstr_destroy(rstatus);
octstr_destroy(xto);
octstr_destroy(xfrom);
octstr_destroy(xproxy);
octstr_destroy(me);
octstr_destroy(rhost);
mms_destroy(msg);
mms_cleanup_mmsc_settings(settings);
mms_lib_shutdown();
return 0;
@ -339,60 +513,139 @@ static int find_own(int i, int argc, char *argv[])
return 1;
} else
return -1;
else if (argv[i][1] == 'p') /* Proxy name if any. */
else if (argv[i][1] == 's') /* Proxy name if any. */
if (i + 1 < argc) {
xproxy = octstr_create(argv[i+1]);
return 1;
} else
return -1;
else
else if (argv[i][1] == 'n') {
no_strip = 1;
return 0;
} else if (argv[i][1] == 'x') {
strip_type = 1;
return 0;
} else
return -1;
}
static void fixup_recipient(void)
static void fixup_recipient(Octstr **host)
{
int i;
Octstr *typ = NULL;
if (!xto) xto = octstr_imm("");
i = octstr_search_char(xto, '@', 0);
if (i>0)
if (!xto) return;
i = octstr_search_char(xto, '@', 0); /* Remove '@' */
if (i>0) {
*host = octstr_copy(xto, i+1, octstr_len(xto));
octstr_delete(xto, i, octstr_len(xto));
} else
*host = octstr_create("localhost");
i = octstr_search(xto, octstr_imm("/TYPE="), 0);
if (i > 0) {
typ = octstr_copy(xto, i+1, octstr_len(xto));
octstr_delete(xto, i, octstr_len(xto));
}
/* XXX may be we should use fixup function in mmlib/mms_util.c ?? */
if (isphonenum(xto) &&
(!typ || octstr_str_compare(typ, "TYPE=PLMN") == 0)) { /* A phone number. */
#if 0
normalize_number(octstr_get_cstr(settings->unified_prefix), &xto);
#else
mms_normalize_phonenum(&xto,
octstr_get_cstr(settings->unified_prefix),
settings->strip_prefixes);
#endif
ttype = TPLMN;
} else { /* For now everything else is email. */
ttype = TEMAIL;
}
octstr_destroy(typ);
}
static void fixup_sender(void)
{
int i;
if (!xfrom) xfrom = octstr_imm("");
i = octstr_search_char(xfrom, '@', 0);
if (i>0)
return;
int i, isphone = 1;
i = octstr_search(xfrom, octstr_imm("/TYPE="), 0);
if (i > 0)
return;
/* Find the TYPE=xxx element. If it is there, it is a number. Strip the @ */
if (isphonenum(xfrom))
octstr_append(xfrom, octstr_imm("/TYPE=PLMN"));
else
octstr_append(xfrom, octstr_imm("@unknown"));
if (!xfrom) return;
i = octstr_case_search(xfrom, octstr_imm("/TYPE="), 0);
if (i>0) {
int j = octstr_search_char(xfrom, '@', 0);
if (j > i) { /* we have @, remove it */
if (xproxy == NULL)
xproxy = octstr_copy(xfrom, j+1, octstr_len(xfrom));
octstr_delete(xfrom, j, octstr_len(xfrom));
}
if (strip_type)
octstr_delete(xfrom, i, octstr_len(xfrom));
} else if (isphonenum(xfrom)) { /* Add the TYPE element if missing. */
if (!strip_type)
octstr_append(xfrom, octstr_imm("/TYPE=PLMN"));
} else {
i = octstr_search_char(xfrom, '@', 0);
if (i<0)
octstr_format_append(xfrom, "@unknown");
else if (xproxy == NULL)
xproxy = octstr_copy(xfrom, i+1, octstr_len(xfrom));
isphone = 0;
}
/* clean the number. */
_mms_fixup_address(&xfrom,
octstr_get_cstr(settings->unified_prefix),
settings->strip_prefixes, strip_type ? 0 : 1);
if (no_strip && isphone && xproxy)
octstr_format_append(xfrom, "@%S", xproxy);
}
static void fixup_addresses(List *headers)
{
fixup_address_type(headers, "To",
octstr_get_cstr(settings->unified_prefix), settings->strip_prefixes);
fixup_address_type(headers, "From",
octstr_get_cstr(settings->unified_prefix), settings->strip_prefixes);
}
static void send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid, char *status, Octstr *msgid,
Octstr *sendmail_cmd)
{
char tmp[32];
List *h = http_create_empty_headers();
MIMEEntity *m = mime_entity_create();
Octstr *err = NULL;
/* Make headers */
sprintf(tmp, "%d.%d.%d",
MAJOR_VERSION(MMS_3GPP_VERSION),
MINOR1_VERSION(MMS_3GPP_VERSION),
MINOR2_VERSION(MMS_3GPP_VERSION));
http_header_add(h, "X-Mms-3GPP-MMS-Version", tmp);
http_header_add(h, "X-Mms-Transaction-ID", octstr_get_cstr(transid));
http_header_add(h, "X-Mms-Message-Type", mm4_types[mtype].mm4str);
if (msgid)
http_header_add(h, "X-Mms-Message-ID", octstr_get_cstr(msgid));
http_header_add(h, "X-Mms-Request-Status-Code", status);
http_header_add(h, "Sender", octstr_get_cstr(sender));
http_header_add(h, "To", octstr_get_cstr(to));
mime_replace_headers(m, h);
http_destroy_headers(h);
mm_send_to_email(to, sender, octstr_imm(""), msgid, m, 0, &err, octstr_get_cstr(sendmail_cmd),
settings->hostname, settings->smtp_relay, settings->smtp_port);
if (err) {
mms_warning(0, "MM4", NULL, "send.RES reported: %s!", octstr_get_cstr(err));
octstr_destroy(err);
}
mime_entity_destroy(m);
}

View File

@ -3,27 +3,24 @@
*
* MMS Global Queue Runner, routes messages generally.
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include "mmsrelay.h"
#include <unistd.h>
#include "mmsc.h"
#define NMAX 256
static char mobile_qdir[NMAX];
static char mm4_qdir[NMAX];
static char sendmail_cmd[NMAX];
/* Set the queue directory for messages going to mobile. */
static int mms_setmobile_queuedir(char *mqdir);
/* Set the queue directory for messages going to remote proxies. */
static int mms_setmm4_queuedir(char *mqdir);
/* Send command for sending mail. It will be called as <sendmail> <to> with
* headers and message on stdin.
@ -47,17 +44,22 @@ static int mms_sendtomobile(Octstr *from, Octstr *to,
*/
static int mms_sendtoproxy(Octstr *from, Octstr *to,
Octstr *subject, Octstr *proxy,
Octstr *msgid, time_t expires, MmsMsg *m, int dlr, Octstr **error);
char *transid,
Octstr *msgid, time_t expires, MmsMsg *msg,
int dlr, Octstr *proxy_sendmail_cmd, List *extra_headers, Octstr **error);
static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
List *qh,
MmsMsg *m, Octstr **error);
static int _x_octstr_int_compare(int n, Octstr *s);
static int match_short_codes(Octstr *phonenum, long short_codes[], int num_codes);
#if 0
/* Send errors */
#define MMS_SEND_OK 0
#define MMS_SEND_ERROR_TRANSIENT -1
#define MMS_SEND_ERROR_FATAL -2
#endif
#define NMAX 256
static char qdir[NMAX];
@ -68,31 +70,37 @@ static int sendMsg(MmsEnvelope *e)
{
int i, n;
MmsMsg *msg = NULL;
time_t tstart = time(NULL);
if (e->msgtype == MMS_MSGTYPE_SEND_REQ &&
!e->bill.billed) { /* Attempt to bill if not already billed */
List *l = list_create();
List *l = gwlist_create();
double amt;
for (i = 0, n = list_len(e->to); i < n; i++) {
MmsEnvelopeTo *to = list_get(e->to, i);
list_append(l, to->rcpt);
for (i = 0, n = gwlist_len(e->to); i < n; i++) {
MmsEnvelopeTo *to = gwlist_get(e->to, i);
Octstr *s = octstr_duplicate(to->rcpt);
_mms_fixup_address(&s,
octstr_get_cstr(settings->unified_prefix),
settings->strip_prefixes, 1);
gwlist_append(l, s);
}
amt = settings->mms_billfuncs->mms_billmsg(e->from, l,
e->msize,
e->vaspid,
e->msgId,
settings->mms_bill_module_data);
list_destroy(l, NULL);
gwlist_destroy(l, (void *)octstr_destroy);
info(0, "Global Queue MMS Bill: From %s, to_count=%ld, msgid=%s, msgsize=%ld: returned=%.2f",
octstr_get_cstr(e->from), list_len(e->to), e->msgId ? octstr_get_cstr(e->msgId) : "",
mms_info(0, "MM2", NULL, "Global Queue MMS Bill: From %s, to_count=%ld, msgid=%s, msgsize=%ld: returned=%.2f",
octstr_get_cstr(e->from), gwlist_len(e->to), e->msgId ? octstr_get_cstr(e->msgId) : "",
e->msize, amt);
if (amt == -1) { /* Delete message. */
for (i = 0, n = list_len(e->to); i < n; i++) {
MmsEnvelopeTo *to = list_get(e->to, i);
for (i = 0, n = gwlist_len(e->to); i < n; i++) {
MmsEnvelopeTo *to = gwlist_get(e->to, i);
to->process = 0;
}
} else if (amt >= 0) {
@ -101,7 +109,7 @@ static int sendMsg(MmsEnvelope *e)
}
if (amt >= -1)
if (mms_queue_update(e) == 1) /* Write queue just in case we crash. */
if (settings->qfs->mms_queue_update(e) == 1) /* Write queue just in case we crash. */
e = NULL;
if (e == NULL ||
@ -111,18 +119,18 @@ static int sendMsg(MmsEnvelope *e)
msg = mms_queue_getdata(e);
msg = settings->qfs->mms_queue_getdata(e);
#if 0
if (msg) mms_msgdump(msg,1);
#endif
for (i = 0, n = list_len(e->to); i < n; i++) {
for (i = 0, n = gwlist_len(e->to); i < n; i++) {
Octstr *err = NULL;
int res = MMS_SEND_OK, m;
MmsEnvelopeTo *to = list_get(e->to, i);
MmsEnvelopeTo *to = gwlist_get(e->to, i);
time_t tnow = time(NULL);
char *dst_int = "NONE";
if (!to || !to->process) /* Already processed. */
continue;
@ -147,26 +155,53 @@ static int sendMsg(MmsEnvelope *e)
*/
if (octstr_search_char(to->rcpt, '@', 0) > 0) {
if (settings->mms2email)
int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0);
int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0);
int len = octstr_len(e->from);
Octstr *pfrom;
dst_int = "MM3";
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
pfrom = octstr_copy(e->from, 0, j);
else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
pfrom = octstr_copy(e->from, 0, k);
else
pfrom = octstr_duplicate(e->from);
if (octstr_search_char(e->from, '@', 0) < 0)
octstr_format_append(pfrom,"@%S", settings->hostname);
if (settings->mms2email && /* send, but don't loop back on it */
!(strcmp(e->src_interface, "MM7") == 0 &&
e->vaspid && settings->mms2email->id &&
octstr_compare(e->vaspid, settings->mms2email->id) == 0))
res = mms_sendtovasp(settings->mms2email,
e->from, to->rcpt,
e->msgId,
e->hdrs,
msg, &err);
else
res = mms_sendtoemail(e->from, to->rcpt,
e->subject,
e->msgId, msg, e->dlr, &err, sendmail_cmd,
else {
List *lto = gwlist_create_ex(to->rcpt);
res = mms_sendtoemail(pfrom, lto,
e->subject ? e->subject : settings->mms_email_subject,
e->msgId, msg, 0, &err, sendmail_cmd,
settings->hostname, 1, 1,
octstr_get_cstr(settings->mms_email_txt),
octstr_get_cstr(settings->mms_email_html), 1);
octstr_get_cstr(settings->mms_email_html), 0, e->xqfname,
e->hdrs, settings->smtp_relay, settings->smtp_port);
gwlist_destroy(lto, NULL);
}
if (res == MMS_SEND_QUEUED)
res = MMS_SEND_OK; /* queued to email treated same as sent.
* XXX - this means DLR requests for emailed messages not supported!
*/
if (res == MMS_SEND_OK)
mms_log2("Sent", e->from, to->rcpt,
-1, e->msgId, NULL, NULL, "MM3", NULL,NULL);
} else if (e->viaproxy && octstr_len(e->viaproxy) > 0)
res = mms_sendtoproxy(e->from,
to->rcpt, e->subject, e->viaproxy,
e->msgId, e->expiryt, msg, e->dlr, &err);
else {
if (pfrom != e->from)
octstr_destroy(pfrom);
} else {
int j = octstr_case_search(to->rcpt, octstr_imm("/TYPE=PLMN"), 0);
int k = octstr_case_search(to->rcpt, octstr_imm("/TYPE=IPv"), 0);
int len = octstr_len(to->rcpt);
@ -174,18 +209,20 @@ static int sendMsg(MmsEnvelope *e)
Octstr *mmsc;
int sent = 0;
MmsVasp *vasp;
List *vlist;
/* If it is an IP, send to mobile handler, else if number, look for recipient. */
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
phonenum = octstr_copy(to->rcpt, 0, j);
else if (k > 0 && k + sizeof "/TYPE=IPv" == len) {
if (settings->mms2mobile) { /* Send a copy to this VASP. */
if (settings->mms2mobile && e->msgtype == MMS_MSGTYPE_SEND_REQ) { /* Send a copy to this VASP. */
Octstr *xerr = NULL;
int res = mms_sendtovasp(settings->mms2mobile,
e->from, to->rcpt,
e->msgId,
e->hdrs,
msg, &err);
info(0, "%s Global Queue MMS Send: Local Msg copy to VASP (%s) - "
mms_info(0, "MM7", settings->mms2mobile->id, "%s Global Queue MMS Send: Local Msg copy to VASP (%s) - "
"From %s, to %s, msgsize=%ld: err=%s",
SEND_ERROR_STR(res),
octstr_get_cstr(settings->mms2mobile->id),
@ -197,6 +234,7 @@ static int sendMsg(MmsEnvelope *e)
res = mms_sendtomobile(e->from,
to->rcpt, e->subject, e->fromproxy,
e->msgId, e->expiryt, msg, e->dlr, &err);
dst_int = "MM1";
sent = 1;
goto done;
} else {
@ -207,52 +245,124 @@ static int sendMsg(MmsEnvelope *e)
goto done;
}
/* Normalise the number, then see if we can resolve home MMSC for this recipient. */
normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
if ((mmsc = settings->mms_resolvefuncs->mms_resolve(phonenum,
settings->mms_resolver_module_data,
settings, proxyrelays))) {
info(0, "mmsc for \"%s\" resolved to: \"%s\"",
octstr_get_cstr(phonenum), octstr_get_cstr(mmsc));
if (octstr_compare(mmsc, settings->hostname) == 0) {
res =
mms_sendtomobile(e->from, to->rcpt,
e->subject, e->fromproxy,
e->msgId, e->expiryt, msg, e->dlr,
&err);
/* Search VASP list, see what you can find... */
vlist = dict_keys(settings->vasp_list);
for (j = 0, m = gwlist_len(vlist); j < m; j++)
if ((vasp = dict_get(settings->vasp_list, gwlist_get(vlist, j))) != NULL &&
match_short_codes(phonenum, vasp->short_codes, vasp->num_short_codes)) {
res = mms_sendtovasp(vasp, e->from, to->rcpt,
e->msgId,
e->hdrs,
msg, &err);
dst_int = "MM7";
sent = 1;
} else if (proxyrelays && list_len(proxyrelays) > 0) /* Step through proxies. */
for (j = 0, m = list_len(proxyrelays); j<m; j++) {
MmsProxyRelay *mp = list_get(proxyrelays, j);
break;
}
gwlist_destroy(vlist, (void *)octstr_destroy);
if (sent != 1) { /* Not yet, sent, find the receiver MMSC. */
/* Normalise the number, then see if we can resolve home MMSC for this recipient. */
#if 0
normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
#else
mms_normalize_phonenum(&phonenum,
octstr_get_cstr(settings->unified_prefix),
settings->strip_prefixes);
#endif
if ((mmsc = settings->mms_resolvefuncs->mms_resolve(phonenum,
e->src_interface,
e->vaspid ? octstr_get_cstr(e->vaspid) : NULL,
settings->mms_resolver_module_data,
settings, proxyrelays))) {
mms_info(0, "MM2", NULL, "mmsc for \"%s\" resolved to: \"%s\"",
octstr_get_cstr(phonenum), octstr_get_cstr(mmsc));
/* If resolved to my hostname, then this is local. */
if (octstr_compare(mmsc, settings->hostname) == 0) {
if (settings->mms2mobile &&
e->msgtype == MMS_MSGTYPE_SEND_REQ) { /* Send a copy to this VASP. */
Octstr *xerr = NULL;
int res = mms_sendtovasp(settings->mms2mobile,
e->from, to->rcpt,
e->msgId,
e->hdrs,
msg, &err);
mms_info(0, "MM2", NULL, "%s Global Queue MMS Send: Local Msg copy to VASP (%s) - "
"From %s, to %s, msgsize=%ld: err=%s",
SEND_ERROR_STR(res),
octstr_get_cstr(settings->mms2mobile->id),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
xerr ? octstr_get_cstr(xerr) : "(null)");
if (xerr)
octstr_destroy(xerr);
}
if (!octstr_compare(mp->host, mmsc)) {
res = mms_sendtoproxy(e->from, to->rcpt,
e->subject, mp->host,
e->msgId, e->expiryt, msg,
e->dlr, &err);
sent = 1;
break;
res = mms_sendtomobile(e->from, to->rcpt,
e->subject, e->fromproxy,
e->msgId, e->expiryt, msg, e->dlr,
&err);
dst_int = "MM1";
sent = 1;
} else {
/* else, step through proxies, look for one that matches. */
for (j = 0, m = proxyrelays ? gwlist_len(proxyrelays) : 0; j<m; j++) {
MmsProxyRelay *mp = gwlist_get(proxyrelays, j);
if (octstr_compare(mp->host, mmsc) == 0) {
Octstr *xtransid = mms_maketransid(e->xqfname,
settings->host_alias);
Octstr *xfrom = e->from ? octstr_duplicate(e->from) : octstr_create("anon@anon");
Octstr *xto = octstr_duplicate(to->rcpt);
_mms_fixup_address(&xfrom,
mp->unified_prefix ? octstr_get_cstr(mp->unified_prefix) : NULL,
mp->strip_prefixes, 1);
_mms_fixup_address(&xto,
mp->unified_prefix ? octstr_get_cstr(mp->unified_prefix) : NULL,
mp->strip_prefixes, 1);
res = mms_sendtoproxy(xfrom, xto,
e->subject, mp->host,
octstr_get_cstr(xtransid),
e->msgId, e->expiryt, msg,
mp->confirmed_mm4, mp->sendmail, e->hdrs, &err);
dst_int = "MM4";
sent = 1;
octstr_destroy(xtransid);
octstr_destroy(xfrom);
octstr_destroy(xto);
break;
}
}
if (sent != 1) { /* try mm7 delivery. Again. */
List *vlist = dict_keys(settings->vasp_list);
Octstr *vid;
for (j = 0, m = gwlist_len(vlist); j < m; j++)
if ((vid = gwlist_get(vlist, j)) != NULL &&
(vasp = dict_get(settings->vasp_list, vid)) != NULL &&
vasp->id &&
octstr_compare(vasp->id, mmsc) == 0) {
res = mms_sendtovasp(vasp, e->from, to->rcpt,
e->msgId,
e->hdrs,
msg, &err);
dst_int = "MM7";
sent = 1;
break;
}
gwlist_destroy(vlist, (void *)octstr_destroy);
}
}
} else /* Search VASP list, see what you can find... */
for (j = 0, m = list_len(settings->vasp_list); j < m; j++)
if ((vasp = list_get(settings->vasp_list, j)) != NULL &&
_x_octstr_int_compare(vasp->short_code, phonenum) == 0) {
res = mms_sendtovasp(vasp, e->from, to->rcpt,
e->msgId,
msg, &err);
sent = 1;
break;
}
octstr_destroy(mmsc);
}
}
if (!sent) {
res = MMS_SEND_ERROR_FATAL;
err = octstr_format("MMSC error: Don't know how to deliver to %S !", to->rcpt);
}
if (phonenum) octstr_destroy(phonenum);
octstr_destroy(phonenum);
}
done:
@ -262,26 +372,35 @@ static int sendMsg(MmsEnvelope *e)
if (e->dlr) {
Octstr *qfs;
MmsMsg *m = mms_deliveryreport(e->msgId, to->rcpt, tnow,
(e->expiryt != 0 && e->expiryt < tnow) ?
octstr_imm("Expired") : octstr_imm("Rejected"));
char *mstatus;
MmsMsg *m;
List *l;
List *l = list_create();
if (res == MMS_SEND_QUEUED)
mstatus = "Forwarded";
else if (e->expiryt != 0 && e->expiryt < tnow)
mstatus = "Expired";
else
mstatus = "Rejected";
m = mms_deliveryreport(e->msgId, to->rcpt, e->from, tnow, octstr_imm(mstatus));
list_append(l, octstr_duplicate(e->from));
l = gwlist_create();
gwlist_append(l, octstr_duplicate(e->from));
/* Add to queue, switch via proxy to be from proxy. */
qfs = mms_queue_add(settings->system_user, l,
err, NULL, e->fromproxy,
tnow, tnow+settings->default_msgexpiry, m, NULL,
NULL, NULL,
NULL, NULL,
0,
qdir,
settings->host_alias);
qfs = settings->qfs->mms_queue_add(to->rcpt, l,
err, NULL, e->fromproxy,
tnow, tnow+settings->default_msgexpiry, m, NULL,
NULL, NULL,
NULL, NULL,
NULL,
0,
qdir,
"MM2",
settings->host_alias);
octstr_destroy(qfs);
list_destroy(l, NULL);
gwlist_destroy(l, NULL);
mms_destroy(m);
}
@ -290,45 +409,59 @@ static int sendMsg(MmsEnvelope *e)
}
/* Write to log */
info(0, "%s Global Queue MMS Send: From %s, to %s, msgsize=%ld: err=%s",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
err ? octstr_get_cstr(err) : "(null)");
if (res == MMS_SEND_OK) { /* Do CDR writing. */
MmsCdrStruct *cdr = gw_malloc(sizeof *cdr);
cdr->module_data = settings->mms_bill_module_data;
cdr->sdate = e->created;
strncpy(cdr->from, octstr_get_cstr(e->from), sizeof cdr->from);
strncpy(cdr->to, octstr_get_cstr(to->rcpt), sizeof cdr->to);
strncpy(cdr->msgid, e->msgId ? octstr_get_cstr(e->msgId) : "", sizeof cdr->msgid);
strncpy(cdr->vaspid, e->vaspid ? octstr_get_cstr(e->vaspid) : "", sizeof cdr->vaspid);
cdr->msg_size = e->msize;
list_produce(cdr_list, cdr); /* Put it on list so sending thread sends it. */
if (res == MMS_SEND_ERROR_FATAL ||
(res == MMS_SEND_ERROR_TRANSIENT && err != NULL))
mms_error(0, "MM2", NULL, "%s Global Queue MMS Send [%.128s]: From %s, to %s, msgsize=%ld: %s. ",
SEND_ERROR_STR(res),
e->xqfname,
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
err ? octstr_get_cstr(err) : "n/a");
else
mms_info(0, "MM2", NULL, "%s Global Queue MMS Send [%.128s]: From %s, to %s, msgsize=%ld: %s.",
SEND_ERROR_STR(res),
e->xqfname,
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
err ? octstr_get_cstr(err) : "n/a");
if (res == MMS_SEND_OK &&
(e->msgtype == MMS_MSGTYPE_SEND_REQ ||
e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF)) { /* Do CDR writing. */
MmsCdrStruct *cdr = make_cdr_struct(settings->mms_bill_module_data,
e->created,
octstr_get_cstr(e->from),
octstr_get_cstr(to->rcpt),
e->msgId ? octstr_get_cstr(e->msgId) : "",
e->vaspid ? octstr_get_cstr(e->vaspid) : "",
e->src_interface,
dst_int,
e->msize);
gwlist_produce(cdr_list, cdr); /* Put it on list so sending thread sends it. */
}
octstr_destroy(err);
/* Update queue entry so that we know which ones have been processed. */
e->lasttry = tnow;
if (mms_queue_update(e) == 1) {
if (settings->qfs->mms_queue_update(e) == 1) {
e = NULL;
break; /* Queue entry gone. */
}
}
done2:
if (msg)
mms_destroy(msg);
mms_destroy(msg);
if (e) { /* Update the queue if it is still valid (e.g. recipients not handled) XXX can this happen here??... */
e->lasttry = time(NULL);
e->attempts++; /* Update count of number of delivery attempts. */
e->sendt = e->lasttry + settings->send_back_off * e->attempts;
if (mms_queue_update(e) != 1)
mms_queue_free_env(e);
if (settings->qfs->mms_queue_update(e) != 1)
settings->qfs->mms_queue_free_env(e);
}
mms_info(0, "MMSC.global", NULL, "Processed in %d secs", (int)(time(NULL) - tstart)); /* report processing time. */
return 1; /* Always deletes the queue entry. */
}
@ -337,18 +470,17 @@ static void cdr_thread(void *unused)
{
MmsCdrStruct *cdr;
while ((cdr = list_consume(cdr_list)) != NULL) {
while ((cdr = gwlist_consume(cdr_list)) != NULL) {
settings->mms_billfuncs->mms_logcdr(cdr);
/* We should probably write to log here... */
gw_free(cdr);
}
}
void mbuni_global_queue_runner(int *rstop)
void mbuni_global_queue_runner(volatile sig_atomic_t *rstop)
{
long cdr_thid;
mms_setmobile_queuedir(octstr_get_cstr(settings->mm1_queuedir));
mms_setmm4_queuedir(octstr_get_cstr(settings->mm4_queuedir));
mms_setsendmail_cmd(octstr_get_cstr(settings->sendmail));
@ -356,16 +488,20 @@ void mbuni_global_queue_runner(int *rstop)
/* Start the thread for CDR */
cdr_list = list_create();
list_add_producer(cdr_list);
gwthread_create(cdr_thread, NULL);
cdr_list = gwlist_create();
gwlist_add_producer(cdr_list);
cdr_thid = gwthread_create(cdr_thread, NULL);
mms_queue_run(qdir, sendMsg, settings->queue_interval, settings->maxthreads, rstop);
settings->qfs->mms_queue_run(qdir, sendMsg, settings->queue_interval, settings->maxthreads, rstop);
/* When it ends, wait a little for other stuff to stop... */
sleep(2);
list_remove_producer(cdr_list); /* Stop CDR thread. */
gwlist_remove_producer(cdr_list); /* Stop CDR thread. */
if (cdr_thid >= 0)
gwthread_join(cdr_thid);
gwthread_sleep(2);
gwlist_destroy(cdr_list, NULL);
return;
}
@ -377,11 +513,6 @@ static int mms_setmobile_queuedir(char *mqdir)
return 0;
}
static int mms_setmm4_queuedir(char *mqdir)
{
strncpy(mm4_qdir, mqdir, sizeof mm4_qdir);
return 0;
}
static int mms_setsendmail_cmd(char *sendmail)
{
@ -399,11 +530,11 @@ int mms_sendtomobile(Octstr *from, Octstr *to,
Octstr *msgid, time_t expires, MmsMsg *m, int dlr, Octstr **error)
{
Octstr *ret, *x;
List *l = list_create();
Octstr *ret = NULL, *x;
List *l = gwlist_create();
char tokenstr[128];
list_append(l, to);
gwlist_append(l, to);
/* We generate a special token that will be added to message ID to make
* stealing messages a bit harder.
@ -413,18 +544,23 @@ int mms_sendtomobile(Octstr *from, Octstr *to,
random() % 100);
x = octstr_create(tokenstr);
if (m)
ret = settings->qfs->mms_queue_add(from, l, subject, fromproxy, NULL, 0, expires, m,
x, NULL, NULL,
NULL, NULL,
NULL,
dlr, mobile_qdir,
"MM2",
settings->host_alias);
else
*error = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to);
ret = mms_queue_add(from, l, subject, fromproxy, NULL, 0, expires, m,
x, NULL, NULL,
NULL, NULL,
dlr, mobile_qdir,
settings->host_alias);
octstr_destroy(x);
list_destroy(l, NULL);
gwlist_destroy(l, NULL);
octstr_destroy(ret);
if (ret == NULL)
return MMS_SEND_ERROR_TRANSIENT;
return (m) ? MMS_SEND_ERROR_TRANSIENT : MMS_SEND_ERROR_FATAL;
else
return MMS_SEND_OK;
}
@ -435,53 +571,54 @@ int mms_sendtomobile(Octstr *from, Octstr *to,
* so we can handle delivery receipts and such.
*/
static int mms_sendtoproxy(Octstr *from, Octstr *to,
Octstr *subject, Octstr *proxy,
Octstr *msgid, time_t expires, MmsMsg *msg, int dlr, Octstr **error)
Octstr *subject, Octstr *proxy,
char *transid,
Octstr *msgid, time_t expires, MmsMsg *msg,
int dlr, Octstr *proxy_sendmail_cmd, List *extra_headers, Octstr **error)
{
Octstr *pto;
Octstr *pto, *pfrom;
List *lto;
int x = MMS_SEND_ERROR_FATAL;
Octstr *xtransid; /* We make a fake transaction ID that includes 'to' field. */
int x;
if (!to ||
octstr_search_char(to, '@', 0) >= 0) {
*error = octstr_format("Bad recipient address sent to MM4 interface, addresss is %S!", to);
return MMS_SEND_ERROR_FATAL;
}
if (mms_messagetype(msg) == MMS_MSGTYPE_SEND_REQ) { /* Only queue these ones for future response. */
List *l = list_create();
Octstr *ret;
list_append(l, to);
ret = mms_queue_add(from, l, subject, NULL, proxy, 0, expires, msg,NULL,
NULL, NULL,
NULL, NULL,
dlr, mm4_qdir,
settings->host_alias);
list_destroy(l, NULL);
if (ret == NULL) {
*error = octstr_format("MM4: Failed to queue message to %S for future tracking. ", to);
return MMS_SEND_ERROR_TRANSIENT;
}
octstr_destroy(ret);
if (!msg) {
*error = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to);
return MMS_SEND_ERROR_FATAL;
}
pto = octstr_format("%S@%S", to, proxy);
x = mms_sendtoemail(from, pto, subject, msgid, msg, 0,
error, sendmail_cmd,
settings->hostname, 0, 0,NULL,NULL,0);
mms_log2("Sent", from, to,
-1, msgid, NULL, proxy, "MM4", NULL,NULL);
if (octstr_search_char(from, '@', 0) < 0)
pfrom = octstr_format("%S@%S", from, settings->hostname);
else
pfrom = from;
octstr_destroy(pto);
xtransid = octstr_format("%S-%s", to,transid);
lto = gwlist_create_ex(pto);
x = mms_sendtoemail(from, lto,
subject ? subject : settings->mms_email_subject,
msgid, msg, dlr,
error, proxy_sendmail_cmd ? octstr_get_cstr(proxy_sendmail_cmd) : sendmail_cmd,
settings->hostname, 0, 0,NULL,NULL,1, octstr_get_cstr(xtransid), extra_headers,
settings->smtp_relay, settings->smtp_port);
octstr_destroy(xtransid);
if (x == MMS_SEND_QUEUED && !dlr) /* No confirmed sending, and message was queued successfully... */
x = MMS_SEND_OK; /* we assume fully sent! */
if (x >= 0) /* no error. */
mms_log2(x == MMS_SEND_OK ? "Sent" : "Queued", from, pto,
-1, msgid, NULL, proxy, "MM4", NULL,NULL);
octstr_destroy(pto);
if (pfrom != from)
octstr_destroy(pfrom);
gwlist_destroy(lto, NULL);
return x;
}
@ -494,49 +631,54 @@ static int _x_octstr_int_compare(int n, Octstr *s)
}
static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
MmsMsg *m, Octstr **error)
List *qh,
MmsMsg *m, Octstr **error, int *got_conn_error)
{
int ret = MMS_SEND_ERROR_TRANSIENT;
int mtype = mms_messagetype(m);
int hstatus = HTTP_OK, tstatus;
List *xto = list_create();
List *xto = gwlist_create();
MSoapMsg_t *mreq = NULL, *mresp = NULL;
List *rh = NULL, *ph = NULL;
Octstr *body = NULL, *rbody = NULL, *url = NULL;
HTTPCaller *caller = http_caller_create();
void *xx;
Octstr *s;
Octstr *body = NULL, *rbody = NULL;
Octstr *uaprof = NULL, *s;
time_t tstamp;
info(0, "MMS Relay: Send[soap] to VASP[%s], msg type [%s], from %s, to %s",
mms_info(0, "MM7", vasp->id, "MMS Relay: Send[soap] to VASP[%s], msg_type=[%s], from=[%s], to=[%s]",
vasp ? octstr_get_cstr(vasp->id) : "",
mms_message_type_to_cstr(mtype), octstr_get_cstr(from), octstr_get_cstr(to));
list_append(xto, to);
gwlist_append(xto, to);
if (vasp->send_uaprof == UAProf_URL)
uaprof = http_header_value(qh, octstr_imm("X-Mbuni-Profile-Url"));
else if (vasp->send_uaprof == UAProf_UA)
uaprof = http_header_value(qh, octstr_imm("X-Mbuni-User-Agent"));
if ((s = http_header_value(qh, octstr_imm("X-Mbuni-Timestamp"))) != NULL) {
tstamp = strtoul(octstr_get_cstr(s), NULL, 10);
octstr_destroy(s);
} else
tstamp = 0;
if ((mreq = mm7_mmsmsg_to_soap(m, from, xto, msgId, settings->host_alias,
msgId,
0, NULL, NULL)) == NULL) {
0, NULL, NULL, uaprof, tstamp, NULL)) == NULL) {
*error = octstr_format("Failed to convert Msg[%s] 2 SOAP message!",
mms_message_type_to_cstr(mtype));
goto done1;
}
if (mm7_soapmsg_to_httpmsg(mreq, &rh, &body) < 0) {
if (mm7_soapmsg_to_httpmsg(mreq, &vasp->ver, &rh, &body) < 0) {
*error = octstr_format("Failed to convert SOAP message 2 HTTP Msg!");
goto done1;
}
if (vasp->mmsc_username)
http_add_basic_auth(rh, vasp->mmsc_username,
vasp->mmsc_password ? vasp->mmsc_password : octstr_imm(""));
http_start_request(caller, HTTP_METHOD_POST, vasp->vasp_url, rh, body, 1, NULL, NULL);
if ((xx = http_receive_result(caller, &hstatus, &url, &ph, &rbody)) == NULL ||
hstatus != HTTP_OK) {
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d, id=%s !",
octstr_get_cstr(vasp->vasp_url), hstatus, xx ? "Ok" : "not OK");
hstatus = mms_url_fetch_content(HTTP_METHOD_POST, vasp->vasp_url, rh, body, &ph, &rbody);
*got_conn_error = (hstatus < 0);
if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d!",
octstr_get_cstr(vasp->vasp_url), hstatus);
goto done1;
}
@ -557,7 +699,7 @@ static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
if (!MM7_SOAP_STATUS_OK(tstatus)) {
Octstr *detail = mm7_soap_header_value(mresp, octstr_imm("Details"));
ret = MMS_SEND_ERROR_FATAL;
info(0, "Send to VASP[%s], failed, code=[%d=>%s], detail=%s",
mms_info(0, "MM7", vasp->id, "Send to VASP[%s], failed, code=[%d=>%s], detail=%s",
vasp ? octstr_get_cstr(vasp->id) : "",
tstatus, mms_soap_status_to_cstr(tstatus),
detail ? octstr_get_cstr(detail) : "");
@ -572,44 +714,37 @@ static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
} else
ret = MMS_SEND_OK;
info(0, "Sent to VASP[%s], code=[%d=>%s]", octstr_get_cstr(vasp->id),
mms_info(0, "MM7", vasp->id, "Sent to VASP[%s], code=[%d=>%s]", octstr_get_cstr(vasp->id),
tstatus, mms_soap_status_to_cstr(tstatus));
done1:
if (mreq)
mm7_soap_destroy(mreq);
if (mresp)
mm7_soap_destroy(mresp);
if (rh)
http_destroy_headers(rh);
if (body)
octstr_destroy(body);
if (ph)
http_destroy_headers(ph);
if (rbody)
octstr_destroy(rbody);
if (url)
octstr_destroy(url);
http_caller_destroy(caller);
list_destroy(xto, NULL);
mm7_soap_destroy(mreq);
mm7_soap_destroy(mresp);
http_destroy_headers(rh);
octstr_destroy(body);
http_destroy_headers(ph);
octstr_destroy(rbody);
octstr_destroy(uaprof);
gwlist_destroy(xto, NULL);
return ret;
}
static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
MmsMsg *m, Octstr **error)
MmsMsg *m, Octstr **error, int *got_conn_error)
{
int ret = MMS_SEND_ERROR_TRANSIENT;
int mtype = mms_messagetype(m);
int hstatus = HTTP_OK;
List *rh = http_create_empty_headers(), *ph = NULL;
Octstr *body = NULL, *rbody = NULL, *url = NULL;
HTTPCaller *caller = http_caller_create();
void *xx;
Octstr *body = NULL, *rbody = NULL, *url = NULL, *xver;
char *msgtype;
info(0, "MMS Relay: Send [eaif] to VASP[%s], msg type [%s], from %s, to %s",
mms_info(0, "MM7", vasp->id, "MMS Relay: Send [eaif] to VASP[%s], msg_type=[%s], from=[%s], to=[%s]",
vasp ? octstr_get_cstr(vasp->id) : "",
mms_message_type_to_cstr(mtype), octstr_get_cstr(from), octstr_get_cstr(to));
@ -617,34 +752,37 @@ static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
http_header_add(rh, "X-NOKIA-MMSC-From", octstr_get_cstr(from));
if (msgid)
http_header_add(rh, "X-NOKIA-MMSC-Message-Id", octstr_get_cstr(msgid));
http_header_add(rh, "X-NOKIA-MMSC-Version", EAIF_VERSION);
if (mtype == MMS_MSGTYPE_SEND_REQ)
xver = octstr_format(EAIF_VERSION, vasp->ver.major, vasp->ver.minor1);
http_header_add(rh, "X-NOKIA-MMSC-Version", octstr_get_cstr(xver));
octstr_destroy(xver);
if (mtype == MMS_MSGTYPE_SEND_REQ ||
mtype == MMS_MSGTYPE_RETRIEVE_CONF) {
msgtype = "MultiMediaMessage";
else if (mtype == MMS_MSGTYPE_DELIVERY_IND)
mms_make_sendreq(m); /* ensure it is a sendreq. */
} else if (mtype == MMS_MSGTYPE_DELIVERY_IND)
msgtype = "DeliveryReport";
else
msgtype = "ReadReply";
http_header_add(rh, "X-NOKIA-MMSC-Message-Type", msgtype);
http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message");
if (vasp->mmsc_username)
http_add_basic_auth(rh, vasp->mmsc_username,
vasp->mmsc_password ? vasp->mmsc_password : octstr_imm(""));
body = mms_tobinary(m);
http_start_request(caller, HTTP_METHOD_POST, vasp->vasp_url, rh, body, 1, NULL, NULL);
if ((xx = http_receive_result(caller, &hstatus, &url, &ph, &rbody)) == NULL ||
http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d, id=%s !",
octstr_get_cstr(vasp->vasp_url), hstatus, xx ? "Ok" : "not OK");
hstatus = mms_url_fetch_content(HTTP_METHOD_POST, vasp->vasp_url, rh, body, &ph, &rbody);
if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d!",
octstr_get_cstr(vasp->vasp_url), hstatus);
} else
info(0, "Sent to VASP[%s], code=[%d]", octstr_get_cstr(vasp->id), hstatus);
mms_info(0, "MM7", vasp->id, "Sent to VASP[%s], code=[%d]", octstr_get_cstr(vasp->id), hstatus);
if (hstatus < 0)
if (hstatus < 0) {
ret = MMS_SEND_ERROR_TRANSIENT;
else {
*got_conn_error = (hstatus < 0);
} else {
hstatus = http_status_class(hstatus);
if (hstatus == HTTP_STATUS_CLIENT_ERROR)
ret = MMS_SEND_ERROR_TRANSIENT;
@ -654,31 +792,50 @@ static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
ret = MMS_SEND_OK;
}
if (rh)
http_destroy_headers(rh);
if (body)
octstr_destroy(body);
if (ph)
http_destroy_headers(ph);
if (rbody)
octstr_destroy(rbody);
if (url)
octstr_destroy(url);
http_caller_destroy(caller);
http_destroy_headers(rh);
octstr_destroy(body);
http_destroy_headers(ph);
octstr_destroy(rbody);
octstr_destroy(url);
return ret;
}
static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
List *qh,
MmsMsg *m, Octstr **err)
{
if (vasp->type == SOAP_VASP)
return mm7soap_send(vasp, from, to, msgid, m, err);
int ret, conn_err = 0;
if (m == NULL) {
*err = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to);
ret = MMS_SEND_ERROR_FATAL;
} else if (vasp->type == SOAP_VASP)
ret = mm7soap_send(vasp, from, to, msgid, qh, m, err, &conn_err);
else if (vasp->type == EAIF_VASP)
return mm7eaif_send(vasp, from, to, msgid, m, err);
ret = mm7eaif_send(vasp, from, to, msgid, m, err, &conn_err);
else {
error(0, "Vasp[%s] of unknown type, can't send!",
mms_error(0, "MM7", vasp->id, "Vasp[%s] of unknown type, can't send!",
vasp->id ? octstr_get_cstr(vasp->id) : "");
return MMS_SEND_ERROR_FATAL;
ret = MMS_SEND_ERROR_FATAL;
}
if (ret < 0) /* failed. */
vasp->stats.mt_errors++;
if (!conn_err) {
vasp->stats.mt_pdus++;
vasp->stats.last_pdu = time(NULL);
}
return ret;
}
static int match_short_codes(Octstr *phonenum, long short_codes[], int num_codes)
{
int i;
for (i = 0; i<num_codes;i++)
if (_x_octstr_int_compare(short_codes[i], phonenum) == 0)
return 1;
return 0;
}

View File

@ -4,76 +4,58 @@
* MMS client sender: notifications/reports to clients via WAP Push,
* manages out-going messages.
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include "mmsrelay.h"
#include "mmsc.h"
#include <errno.h>
#include <unistd.h>
#include <strings.h>
#define WAPPUSH_PORT 2948
static HTTPCaller *httpcaller;
static MmsEnvelope edummy;
static MmsEnvelope *update_env_success(MmsEnvelope *env, MmsEnvelopeTo *xto)
static MmsEnvelope *update_env(MmsEnvelope *e, MmsEnvelopeTo *xto, int success)
{
time_t tnow = time(NULL);
if (xto && !(env->msgtype == MMS_MSGTYPE_SEND_REQ ||
env->msgtype == MMS_MSGTYPE_RETRIEVE_CONF))
xto->process = 0; /* No more processing. */
else {
env->lasttry = tnow;
env->attempts++;
env->sendt = env->lasttry + settings->send_back_off * env->attempts;
}
if (success && xto &&
e->msgtype != MMS_MSGTYPE_SEND_REQ &&
e->msgtype != MMS_MSGTYPE_RETRIEVE_CONF)
xto->process = 0; /* No more processing, unless it is a SEND/RETRIEVE */
if (mms_queue_update(env) == 1)
env = NULL;
return env;
e->lasttry = tnow;
e->attempts++;
e->sendt = tnow + settings->send_back_off * e->attempts;
if (settings->qfs->mms_queue_update(e) == 1)
e = NULL;
return e;
}
static MmsEnvelope *update_env_failed(MmsEnvelope *env)
{
time_t tnow = time(NULL);
if (env && env != &edummy) {
env->sendt = tnow + settings->send_back_off;
env->lasttry = tnow;
if (mms_queue_update(env) == 1)
env = NULL;
}
return env;
}
static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *msg)
static void do_mm1_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *msg)
{
List *pheaders;
static unsigned char ct; /* Transaction counter -- do we need it? */
Octstr *to = NULL;
Octstr *pduhdr = octstr_create("");
Octstr *s = NULL;
info(0, "mms2mobile.startpush: notification to %s\n", octstr_get_cstr(rcpt_to));
Octstr *to = NULL;
Octstr *pduhdr = octstr_create("");
Octstr *s = NULL;
if (!rcpt_to) {
error(0, "mobilesender: Queue entry %s has no recipient address!", e->xqfname);
mms_error(0, "MM1", NULL, "mobilesender: Queue entry %s has no recipient address!", e->xqfname);
goto done;
} else
to = octstr_duplicate(rcpt_to);
ct++;
octstr_append_char(pduhdr, ct);
octstr_append_char(pduhdr, 0x06); /* Pushd id */
octstr_append_char(pduhdr, ct); /* Pushd id */
octstr_append_char(pduhdr, 0x06); /* PUSH */
#if 1
@ -81,44 +63,50 @@ static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *
octstr_append_char(pduhdr, 0xbe); /* content type. */
#else
octstr_append_char(pduhdr,
1 + 1 + sizeof "application/vnd.wap.mms-message"); /*header length. */
1 + 1 + strlen("application/vnd.wap.mms-message") + 1); /*header length. */
octstr_append_cstr(pduhdr, "application/vnd.wap.mms-message");
octstr_append_char(pduhdr, 0x0); /* string terminator. */
#endif
octstr_append_char(pduhdr, 0xaf); /* charset. */
octstr_append_char(pduhdr, 0xaf); /* push application ID header and value follows. */
octstr_append_char(pduhdr, 0x84); /* ... */
s = mms_tobinary(msg);
if (isphonenum) {
Octstr *url;
octstr_url_encode(to);
octstr_url_encode(s);
#if 0
octstr_dump(pduhdr, 0);
#endif
octstr_url_encode(pduhdr);
url = octstr_format("%S&text=%S%S&to=%S&udh=%%06%%05%%04%%0B%%84%%23%%F0",
settings->sendsms_url, pduhdr, s, to);
Octstr *url = octstr_format("%S&text=%E%E&to=%E&udh=%%06%%05%%04%%0B%%84%%23%%F0",
settings->sendsms_url, pduhdr, s, to);
int status;
List *rph = NULL;
Octstr *rbody = NULL;
MmsEnvelopeTo *xto = gwlist_get(e->to, 0);
pheaders = http_create_empty_headers();
http_header_add(pheaders, "Connection", "close");
http_header_add(pheaders, "User-Agent", MM_NAME "/" MMSC_VERSION);
http_start_request(httpcaller, HTTP_METHOD_GET, url,
pheaders, NULL, 0, e, NULL);
if ((status = mms_url_fetch_content(HTTP_METHOD_GET, url, pheaders, NULL, &rph, &rbody)) < 0 ||
http_status_class(status) != HTTP_STATUS_SUCCESSFUL) {
mms_error(0, "MM1", NULL, " Push[%s] from %s, to %s, failed, HTTP code => %d", e->xqfname,
octstr_get_cstr(e->from), octstr_get_cstr(to), status);
e = update_env(e,xto,0);
} else { /* Successful push. */
mms_log2("Notify", octstr_imm("system"), to,
-1, e ? e->msgId : NULL, NULL, NULL, "MM1", NULL,NULL);
e = update_env(e, xto, 1);
}
http_destroy_headers(pheaders);
http_destroy_headers(rph);
octstr_destroy(rbody);
octstr_destroy(url);
} else { /* An IP Address: Send packet, forget. */
Octstr *addr = udp_create_address(to, WAPPUSH_PORT);
int sock = udp_client_socket();
MmsEnvelopeTo *xto = gwlist_get(e->to,0);
if (sock > 0) {
MmsEnvelopeTo *xto = list_get(e->to,0);
octstr_append(pduhdr, s);
#if 0
octstr_dump(pduhdr, 0);
@ -128,100 +116,28 @@ static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *
mms_log2("Notify", octstr_imm("system"), to,
-1, e ? e->msgId : NULL,
NULL, NULL, "MM1", NULL,NULL);
e = update_env_success(e, xto);
e = update_env(e, xto, 1);
} else {
e = update_env_failed(e);
error(0, "push to %s:%d failed, no reason found", octstr_get_cstr(to), WAPPUSH_PORT);
e = update_env(e, xto, 0);
mms_error(0, "MM1", NULL, "push to %s:%d failed: %s",
octstr_get_cstr(to), WAPPUSH_PORT, strerror(errno));
}
octstr_destroy(addr);
if (e)
mms_queue_free_env(e);
}
done:
if (to) octstr_destroy(to);
if (pduhdr) octstr_destroy(pduhdr);
if (s) octstr_destroy(s);
}
static int receive_push_reply(HTTPCaller *caller)
{
int http_status;
List *reply_headers;
Octstr *final_url, *reply_body;
MmsEnvelope *env;
octstr_destroy(to);
octstr_destroy(pduhdr);
octstr_destroy(s);
http_status = HTTP_UNAUTHORIZED;
while ((env = http_receive_result(caller, &http_status, &final_url, &reply_headers,
&reply_body)) != NULL) {
MmsEnvelopeTo *xto = NULL;
Octstr *to = NULL;
if (http_status == -1 || final_url == NULL) {
error(0, "push failed, no reason found");
goto push_failed;
}
if (env == &edummy) /* Skip this one it is a dummy. */
goto push_free_env;
xto = list_get(env->to, 0);
if (xto)
to = xto->rcpt;
else {
error(0, "mobilesender: Queue entry %s has no recipient address!", env->xqfname);
goto push_failed;
}
info(0, "send2mobile.push_reply[%s]: From %s, to %s => %d",
env->xqfname,
octstr_get_cstr(env->from), octstr_get_cstr(to), http_status);
if (http_status == HTTP_UNAUTHORIZED ||
http_status == HTTP_NOT_FOUND ||
http_status == HTTP_FORBIDDEN) { /* This is a temporary system error
* do not increase attempts, count,
* merely reschedule
* for a minute or so later.
*/
error(0, "Deffered notification, WAP Push failed for "
"msgid %s to %s, http error: %d!", octstr_get_cstr(env->msgId),
octstr_get_cstr(to), http_status);
goto push_failed;
}
debug("mobilesender.push", 0, "Push reply headers were");
http_header_dump(reply_headers);
mms_log2("Notify", octstr_imm("system"), to,
-1, env ? env->msgId : NULL, NULL, NULL, "MM1", NULL,NULL);
if ((env = update_env_success(env, xto)) != NULL)
goto push_free_env;
/* Fall through. */
push_failed:
octstr_destroy(final_url);
octstr_destroy(reply_body);
http_destroy_headers(reply_headers);
env = update_env_failed(env);
push_free_env:
if (env && env != &edummy)
mms_queue_free_env(env);
}
return 0;
if (e)
settings->qfs->mms_queue_free_env(e);
}
static int sendNotify(MmsEnvelope *e)
{
Octstr *to;
MmsMsg *msg, *smsg = NULL;
MmsEnvelopeTo *xto = list_get(e->to, 0);
MmsMsg *smsg = NULL;
MmsEnvelopeTo *xto = gwlist_get(e->to, 0);
Octstr *err = NULL;
time_t tnow = time(NULL);
int j, k, len;
@ -231,20 +147,23 @@ static int sendNotify(MmsEnvelope *e)
time_t expiryt;
char *prov_notify_event = NULL;
char *rtype = NULL;
#if 0 /* ... because we don't want fetched messages sticking around in queue forever */
if (e->lastaccess != 0) { /* This message has been fetched at least once, no more signals. */
if (e->lastaccess != 0) { /* This message has been fetched at least once, no more signals. */
e->sendt = e->expiryt + 3600*24*30*12;
return mms_queue_update(e);
mms_info(0, "MM1", NULL, "Message [ID: %s] fetched/touched at least once. Skipping",
e->xqfname);
return settings->qfs->mms_queue_update(e);
}
#endif
if (!xto) {
error(0, "mobilesender: Queue entry %s with no recipients!",
mms_error(0, "MM1", NULL, "mobilesender: Queue entry %s with no recipients!",
e->xqfname);
return 0;
}
msg = mms_queue_getdata(e);
to = octstr_duplicate(xto->rcpt);
expiryt = e->expiryt;
msgId = e->msgId ? octstr_duplicate(e->msgId) : NULL;
@ -252,32 +171,51 @@ static int sendNotify(MmsEnvelope *e)
fromproxy = e->fromproxy ? octstr_duplicate(e->fromproxy) : NULL;
msize = e->msize;
dlr = e->dlr;
mtype = e->msgtype;
if (e->expiryt != 0 && /* Handle message expiry. */
e->expiryt < tnow) {
err = octstr_format("MMSC error: Message expired while sending to %S!", to);
err = octstr_format("MM1 error: Message expired while sending to %S!", to);
res = MMS_SEND_ERROR_FATAL;
prov_notify_event = "failedfetch";
rtype = "Expired";
goto done;
} else if (e->attempts >= settings->maxsendattempts) {
err = octstr_format("MMSC error: Failed to deliver to %S after %ld attempts!",
to, e->attempts);
res = MMS_SEND_ERROR_FATAL;
} else if (e->attempts >= settings->mm1_maxsendattempts) {
err = octstr_format("MM1: Maximum delivery attempts [%d] to %S reached. Delivery suspended!",
e->attempts, to);
res = MMS_SEND_OK;
e->sendt = e->expiryt + 1; /* no retry until expiry */
if (settings->qfs->mms_queue_update(e) != 1)
settings->qfs->mms_queue_free_env(e);
e = NULL;
goto done;
} else if (e->lastaccess != 0) {
e->sendt = e->expiryt + 1;
res = MMS_SEND_OK;
err = octstr_create("Skipped");
mms_info(0, "MM1", NULL, "Message [ID: %s] fetched/touched at least once. Skipping",
e->xqfname);
if (settings->qfs->mms_queue_update(e) != 1)
settings->qfs->mms_queue_free_env(e);
e = NULL;
prov_notify_event = "failedfetch";
rtype = "Expired";
goto done;
}
j = octstr_case_search(to, octstr_imm("/TYPE=PLMN"), 0);
k = octstr_case_search(to, octstr_imm("/TYPE=IPv"), 0);
len = octstr_len(to);
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len) { /* A proper number. */
phonenum = octstr_copy(to, 0, j);
normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
} else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
mms_normalize_phonenum(&phonenum,
octstr_get_cstr(settings->unified_prefix),
settings->strip_prefixes);
} else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
rcpt_ip = octstr_copy(to, 0, k);
else {
/* We only handle phone numbers here. */
@ -286,7 +224,6 @@ static int sendNotify(MmsEnvelope *e)
goto done;
}
mtype = mms_messagetype(msg);
/* For phone, getting here means the message can be delivered. So:
* - Check whether the recipient is provisioned, if not, wait (script called will queue creation req)
@ -317,41 +254,45 @@ static int sendNotify(MmsEnvelope *e)
e->lasttry = tnow;
e->sendt = e->lasttry + settings->send_back_off * (1 + e->attempts);
if (mms_queue_update(e) == 1)
if (settings->qfs->mms_queue_update(e) == 1)
e = NULL; /* Queue entry gone. */
else
mms_queue_free_env(e);
settings->qfs->mms_queue_free_env(e);
goto done;
} else if (send_ind == 0) { /* provisioned but does not support */
Octstr *s = octstr_format(octstr_get_cstr(settings->mms_notify_txt),
from);
if (s && octstr_len(s) > 0) { /* Only send if the string was set. */
List *pheaders;
Octstr *sto = octstr_duplicate(phonenum);
if (settings->notify_unprovisioned && s && octstr_len(s) > 0) { /* Only send if the string was set. */
List *pheaders = http_create_empty_headers(), *rph = NULL;
Octstr *rbody = NULL;
int status;
octstr_url_encode(s);
octstr_url_encode(sto);
url = octstr_format("%S&text=%S&to=%S",settings->sendsms_url,s, sto);
pheaders = http_create_empty_headers();
url = octstr_format("%S&text=%E&to=%E",settings->sendsms_url,s, phonenum);
http_header_add(pheaders, "Connection", "close");
http_header_add(pheaders, "User-Agent", MM_NAME "/" VERSION);
http_start_request(httpcaller, HTTP_METHOD_GET, url,
pheaders, NULL, 0, &edummy, NULL);
if ((status = mms_url_fetch_content(HTTP_METHOD_GET, url,
pheaders, NULL, &rph, &rbody)) <0 ||
http_status_class(status) != HTTP_STATUS_SUCCESSFUL)
mms_error(0, "MM1", NULL, "Notify unprovisioned url fetch failed => %d", status);
http_destroy_headers(pheaders);
http_destroy_headers(rph);
octstr_destroy(url);
octstr_destroy(sto);
} else if (s)
octstr_destroy(s);
octstr_destroy(rbody);
}
octstr_destroy(s);
res = MMS_SEND_OK;
err = octstr_imm("No MMS Ind support, sent SMS instead");
xto->process = 0; /* No more processing. */
if (mms_queue_update(e) == 1)
if (settings->qfs->mms_queue_update(e) == 1)
e = NULL;
else
mms_queue_free_env(e);
settings->qfs->mms_queue_free_env(e);
goto done;
}
@ -359,11 +300,13 @@ static int sendNotify(MmsEnvelope *e)
/* To get here means we can send Ind. */
url = mms_makefetchurl(e->xqfname, e->token, MMS_LOC_MQUEUE,
to,
phonenum ? phonenum : to,
settings);
mms_info(0, "MM1", NULL, "Preparing to notify client to fetch message at URL: %s",
octstr_get_cstr(url));
transid = mms_maketransid(e->xqfname, settings->host_alias);
smsg = mms_notification(msg, e->msize, url, transid,
smsg = mms_notification(e->from, e->subject, e->mclass, e->msize, url, transid,
e->expiryt ? e->expiryt :
tnow + settings->default_msgexpiry,
settings->optimize_notification_size);
@ -371,69 +314,69 @@ static int sendNotify(MmsEnvelope *e)
octstr_destroy(url);
} else if (mtype == MMS_MSGTYPE_DELIVERY_IND ||
mtype == MMS_MSGTYPE_READ_ORIG_IND)
smsg = msg;
smsg = settings->qfs->mms_queue_getdata(e);
else {
error(0, "Unexpected message type %s for %s found in MT queue!",
mms_error(0, "MM1", NULL, "Unexpected message type [%s] for [%s] found in MT queue!",
mms_message_type_to_cstr(mtype), octstr_get_cstr(to));
res = MMS_SEND_ERROR_FATAL;
goto done;
}
if (smsg)
start_push(phonenum ? phonenum : rcpt_ip,
phonenum ? 1 : 0,
e, smsg); /* Send the message.
* Don't touch 'e' after this point!
* It may be freed by receive thread.
*/
if (smsg) {
do_mm1_push(phonenum ? phonenum : rcpt_ip,
phonenum ? 1 : 0,
e, smsg); /* Don't touch 'e' after this point. It is gone */
e = NULL;
}
if (smsg != msg && smsg)
if (smsg)
mms_destroy(smsg);
done:
if (err != NULL &&
res != MMS_SEND_ERROR_TRANSIENT) { /* If there was a report request and this is a legit error
* queue it.
*/
if (dlr) {
MmsMsg *m = mms_deliveryreport(msgId, to, tnow,
if (e != NULL &&
err != NULL &&
res != MMS_SEND_ERROR_TRANSIENT && dlr) { /* If there was a report request and this is a legit error
* queue it.
*/
MmsMsg *m = mms_deliveryreport(msgId, to, e->from, tnow,
rtype ? octstr_imm(rtype) :
octstr_imm("Indeterminate"));
List *l = list_create();
List *l = gwlist_create();
Octstr *res;
list_append(l, from);
gwlist_append(l, from);
/* Add to queue, switch via proxy to be from proxy. */
res = mms_queue_add(settings->system_user, l, err,
NULL, fromproxy,
tnow, tnow+settings->default_msgexpiry, m, NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->mm1_queuedir),
settings->host_alias);
list_destroy(l, NULL);
res = settings->qfs->mms_queue_add(to ? to : settings->system_user, l, err,
NULL, fromproxy,
tnow, tnow+settings->default_msgexpiry, m, NULL,
NULL, NULL,
NULL, NULL,
NULL,
0,
octstr_get_cstr(settings->global_queuedir),
"MM2",
settings->host_alias);
gwlist_destroy(l, NULL);
mms_destroy(m);
octstr_destroy(res);
}
octstr_destroy(res);
}
/* Write to log */
info(0, "%s Mobile Queue MMS Send Notify: From=%s, to=%s, msgsize=%d, reason=%s",
SEND_ERROR_STR(res),
octstr_get_cstr(from), octstr_get_cstr(to), msize,
err ? octstr_get_cstr(err) : "");
mms_info(0, "MM1", NULL, "%s Mobile Queue MMS Send Notify: From=%s, to=%s, msgsize=%d, reason=%s. Processed in %d secs",
SEND_ERROR_STR(res),
octstr_get_cstr(from), octstr_get_cstr(to), msize,
err ? octstr_get_cstr(err) : "",
(int)(time(NULL) - tnow));
if (res == MMS_SEND_ERROR_FATAL) {
xto->process = 0; /* No more attempts to deliver, delete this. */
if (mms_queue_update(e) == 1)
if (xto && e) {
if (res == MMS_SEND_ERROR_FATAL)
xto->process = 0; /* No more attempts to deliver, delete this. */
if (settings->qfs->mms_queue_update(e) == 1)
e = NULL; /* Queue entry gone. */
else
mms_queue_free_env(e);
settings->qfs->mms_queue_free_env(e);
} /* Else queue will be updated/freed elsewhere. */
@ -441,37 +384,26 @@ static int sendNotify(MmsEnvelope *e)
notify_prov_server(octstr_get_cstr(settings->prov_notify),
to ? octstr_get_cstr(to) : "unknown",
prov_notify_event,
rtype ? rtype : "");
if (msg) mms_destroy(msg);
if (phonenum)
octstr_destroy(phonenum);
if (rcpt_ip)
octstr_destroy(rcpt_ip);
rtype ? rtype : "",
e ? e->msgId : NULL, NULL, NULL);
octstr_destroy(phonenum);
octstr_destroy(rcpt_ip);
octstr_destroy(to);
if (msgId) octstr_destroy(msgId);
if (fromproxy) octstr_destroy(fromproxy);
octstr_destroy(msgId);
octstr_destroy(fromproxy);
octstr_destroy(from);
if (err) octstr_destroy(err);
octstr_destroy(err);
return 1;
return 1; /* Tell caller we dealt with envelope */
}
void mbuni_mm1_queue_runner(int *rstop)
void mbuni_mm1_queue_runner(volatile sig_atomic_t *rstop)
{
httpcaller = http_caller_create();
if (gwthread_create((gwthread_func_t *)receive_push_reply, httpcaller) < 0) { /* Listener thread. */
error(0, "Mobile sender: Failed to create push reply thread: %d: %s!",
errno, strerror(errno));
return;
}
mms_queue_run(octstr_get_cstr(settings->mm1_queuedir),
sendNotify, settings->queue_interval, settings->maxthreads, rstop);
sleep(2); /* Wait for it to die. */
http_caller_signal_shutdown(httpcaller);
sleep(2);
http_caller_destroy(httpcaller);
settings->qfs->mms_queue_run(octstr_get_cstr(settings->mm1_queuedir),
sendNotify, settings->mm1_queue_interval, settings->maxthreads, rstop);
gwthread_sleep(2); /* Wait for it to die. */
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -10,85 +10,45 @@
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include "mmsrelay.h"
static mCfg *cfg;
MmscSettings *settings;
List *proxyrelays;
#include "mmsc.h"
static int rstop = 0; /* Set to 1 to stop relay. */
static void quit_now(int notused)
static long qthread = -1;
static volatile sig_atomic_t rstop = 0; /* Set to 1 to stop relay. */
int mmsrelay()
{
rstop = 1;
if (!(settings->svc_list & (SvcMM1 | SvcRelay))) {
mms_info(0, "mmsrelay", NULL, " " MM_NAME " MMSC Relay version %s, no services to be started.", MMSC_VERSION);
return 0;
} else
mms_info(0, "mmsrelay", NULL, " " MM_NAME " MMSC Relay version %s starting", MMSC_VERSION);
/* Start global queue runner. */
if (settings->svc_list & SvcRelay) {
mms_info(0, "mmsrelay", NULL, "Starting Global Queue Runner...");
qthread = gwthread_create((gwthread_func_t *)mbuni_global_queue_runner, (void *)&rstop);
}
if (settings->svc_list & SvcMM1) {
/* Start the local queue runner. */
mms_info(0, "mmsrelay", NULL,"Starting Local Queue Runner...");
mbuni_mm1_queue_runner(&rstop);
}
if (qthread >= 0)
gwthread_join(qthread); /* Wait for it to die... */
mms_info(0, "mmsrelay", NULL, "MMSC Relay MM1 queue runner terminates...");
return 0;
}
int main(int argc, char *argv[])
int stop_mmsrelay(void)
{
int cfidx;
Octstr *fname;
long qthread = 0;
mms_lib_init();
srandom(time(NULL));
cfidx = get_and_set_debugs(argc, argv, NULL);
if (argv[cfidx] == NULL)
fname = octstr_imm("mbuni.conf");
else
fname = octstr_create(argv[cfidx]);
cfg = mms_cfg_read(fname);
if (cfg == NULL)
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
octstr_destroy(fname);
info(0, "----------------------------------------");
info(0, " " MM_NAME " MMSC Relay version %s starting", MMSC_VERSION);
settings = mms_load_mmsc_settings(cfg,&proxyrelays);
mms_cfg_destroy(cfg);
if (!settings)
panic(0, "No global MMSC configuration!");
#if 0
mms_start_profile_engine(octstr_get_cstr(settings->ua_profile_cache_dir));
#endif
signal(SIGHUP, quit_now);
signal(SIGTERM, quit_now);
signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for nothing*/
/* Start global queue runner. */
info(0, "Starting Global Queue Runner...");
qthread = gwthread_create((gwthread_func_t *)mbuni_global_queue_runner, &rstop);
/* Start the local queue runner. */
info(0, "Starting Local Queue Runner...");
mbuni_mm1_queue_runner(&rstop);
gwthread_join(qthread); /* Wait for it to die... */
sleep(2);
/* It terminates, so start dying... */
mms_stop_profile_engine(); /* Stop profile stuff. */
sleep(2); /* Wait for them to die. */
mms_lib_shutdown();
rstop = 1;
mms_info(0, "mmsrelay", NULL, "Mmsrelay: Queue runners shutdown, cleanup commenced...");
return 0;
};

View File

@ -1,28 +0,0 @@
#ifndef __MMSRELAY_INCLUDED__
#define __MMSRELAY_INCLUDED__
/*
* Mbuni - Open Source MMS Gateway
*
* MMS Relay, implements message routing
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <signal.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include "mms_queue.h"
#include "mms_uaprof.h"
#include "mmsc_cfg.h"
#include "mms_mm7soap.h"
extern void mbuni_global_queue_runner(int *stopflag);
extern void mbuni_mm1_queue_runner(int *stopflag);
extern MmscSettings *settings;
extern List *proxyrelays;
#endif

View File

@ -3,7 +3,7 @@
*
* MMS send: Inject message into queue for delivery.
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
@ -20,21 +20,17 @@
static Octstr *from;
static Octstr *binfo;
static List *to;
static Octstr *data;
static MmsMsg *m;
static int savetommbox;
Octstr *mmbox;
static MmscSettings *settings;
static int dlr;
static int find_own(int i, int argc, char *argv[])
{
if (argv[i][1] == 'f')
if (i + 1 < argc) {
from = octstr_create(argv[i+1]);
_mms_fixup_address(from);
return 1;
} else
return -1;
@ -42,17 +38,11 @@ static int find_own(int i, int argc, char *argv[])
savetommbox = 1;
return 0;
} else if (argv[i][1] == 't')
if (i + 1 < argc) {
int j, m;
List *l = octstr_split(octstr_create(argv[i+1]),
octstr_imm(":"));
for (j = 0, m = list_len(l); j < m; j++) {
Octstr *x = list_get(l, j);
_mms_fixup_address(x);
list_append(to, x);
}
list_destroy(l, NULL);
return 1;
if (i + 1 < argc) {
Octstr *x = octstr_create(argv[i+1]);
to = octstr_split(x, octstr_imm(":"));
octstr_destroy(x);
return 1;
} else
return -1;
else if (argv[i][1] == 'm')
@ -61,14 +51,23 @@ static int find_own(int i, int argc, char *argv[])
return 1;
} else
return -1;
else if (argv[i][1] == 'r') {
dlr = 1;
return 0;
} else if (argv[i][1] == 'B')
if (i + 1 < argc) {
binfo = octstr_create(argv[i+1]);
return 1;
} else
return -1;
else
return -1;
}
static mCfg *cfg;
static MmscSettings *settings;
static List *proxyrelays;
static MmsMsg *m;
Octstr *mmbox;
int main(int argc, char *argv[])
{
@ -76,14 +75,14 @@ int main(int argc, char *argv[])
int cfidx;
int msize;
List *h = NULL;
if (argc < 2)
return -1;
mms_lib_init();
to = list_create();
srandom(time(NULL));
cfidx = get_and_set_debugs(argc, argv, find_own);
if (argv[cfidx] == NULL)
@ -91,31 +90,40 @@ int main(int argc, char *argv[])
else
fname = octstr_create(argv[cfidx]);
cfg = mms_cfg_read(fname);
if (cfg == NULL)
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
octstr_destroy(fname);
info(0, "----------------------------------------");
info(0, " MMSC Message sender runner version %s starting", MMSC_VERSION);
mms_info(0, "mmssend", NULL, "----------------------------------------");
mms_info(0, "mmssend", NULL, " MMSC Message sender runner version %s starting", MMSC_VERSION);
/* Load settings. */
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
mms_cfg_destroy(cfg);
settings = mms_load_mmsc_settings(fname, &proxyrelays,1);
if (!settings)
panic(0, "No global MMSC configuration!");
panic(0, "No global MMSC configuration, or failed to read conf from <%s>!", octstr_get_cstr(fname));
octstr_destroy(fname);
if (from == NULL ||
to == NULL) {
error(0, "Sender and recipient addresses required!\n");
mms_error(0, "mmssend", NULL, "Sender and recipient addresses required!\n");
exit(-1);
} else { /* fix up 'to' list */
List *l = gwlist_create();
Octstr *x;
while ((x = gwlist_extract_first(to)) != NULL) {
octstr_strip_blanks(x);
_mms_fixup_address(&x,
settings->unified_prefix ? octstr_get_cstr(settings->unified_prefix) : NULL,
settings->strip_prefixes, 1);
gwlist_append(l, x);
}
gwlist_destroy(to, NULL);
to = l;
}
/* fix from address. */
_mms_fixup_address(&from,
settings->unified_prefix ? octstr_get_cstr(settings->unified_prefix) : NULL,
settings->strip_prefixes, 1);
#if 0
mms_start_profile_engine(octstr_get_cstr(settings->ua_profile_cache_dir));
#endif
@ -130,7 +138,9 @@ int main(int argc, char *argv[])
mime_entity_destroy(mime);
}
} else
m = mms_frombinary(data, from ? from : octstr_imm("anon@anon"));
m = mms_frombinary_ex(data, from ? from : octstr_imm("anon@anon"),
octstr_get_cstr(settings->unified_prefix),
settings->strip_prefixes);
if (m)
mms_msgdump(m,1);
msize = octstr_len(data);
@ -140,24 +150,38 @@ int main(int argc, char *argv[])
if (!m)
panic(0, "No Message supplied, or failed to decode binary data!");
s = mms_queue_add(from, to, NULL, NULL, NULL, time(NULL),
time(NULL) + settings->default_msgexpiry, m,
NULL,
NULL, NULL,
NULL, NULL,
0,
octstr_get_cstr(settings->global_queuedir),
settings->host_alias);
h = http_create_empty_headers();
http_header_add(h, "X-Mbuni-Tool", "mmssend");
http_header_add(h, "X-Mbuni-CalledFrom", "Terminal");
if (binfo) {
mms_info(0, "add.info", NULL, "Adding extra headers billing info `X-Mms-Binfo' :");
http_header_add(h, "X-Mms-Binfo", octstr_get_cstr(binfo));
}
s = settings->qfs->mms_queue_add(from, to, NULL, NULL, NULL, time(NULL),
time(NULL) + settings->default_msgexpiry, m,
NULL,
NULL, NULL,
NULL, NULL,
h,
dlr,
octstr_get_cstr(settings->global_queuedir),
"MM3",
settings->host_alias);
if (savetommbox)
mmbox = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir),
octstr_get_cstr(from), m, NULL, octstr_imm("Sent"));
mms_log("Received", from, to, msize, s, NULL, NULL, "mmssend",NULL,NULL);
mms_log("Received", from, to, msize, s, NULL, NULL, "MM3",NULL,NULL);
printf("Queued: %s, mmbox=%s\n",
octstr_get_cstr(s), mmbox ? octstr_get_cstr(mmbox) : "");
octstr_destroy(s);
http_destroy_headers(h);
mms_cleanup_mmsc_settings(settings);
mms_lib_shutdown();
return 0;
}

View File

@ -3,6 +3,4 @@
- Need to parameterise some values: response messages (say on failed content adaptation)
- Test suite
- Correct handling of unrecognised mms headers. spec says pass them un-changed.
- Queue module needs to be de-coupled slightly from storage, so that mmsproxy can run on a separate box
but be able to initiate queue writes/reads over network. Hence pieces can run on separate boxes
(with mmsrelay providing network service for queue functions)
- Generalise billing interface