00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #include <ctype.h>
00081 #include <time.h>
00082 #include <errno.h>
00083 #include <limits.h>
00084 #include <string.h>
00085
00086 #include <unistd.h>
00087
00088 #include "gwlib/gwlib.h"
00089 #include "sms.h"
00090 #include "dlr.h"
00091 #include "dlr_p.h"
00092
00093
00094 static struct dlr_storage *handles = NULL;
00095
00096
00097
00098
00099
00100 struct dlr_entry *dlr_entry_create(void)
00101 {
00102 struct dlr_entry *dlr;
00103
00104 dlr = gw_malloc(sizeof(*dlr));
00105 gw_assert(dlr != NULL);
00106
00107
00108 memset(dlr, 0, sizeof(*dlr));
00109
00110 return dlr;
00111 }
00112
00113
00114
00115
00116 struct dlr_entry *dlr_entry_duplicate(const struct dlr_entry *dlr)
00117 {
00118 struct dlr_entry *ret;
00119
00120 if (dlr == NULL)
00121 return NULL;
00122
00123 ret = dlr_entry_create();
00124 ret->smsc = octstr_duplicate(dlr->smsc);
00125 ret->timestamp = octstr_duplicate(dlr->timestamp);
00126 ret->source = octstr_duplicate(dlr->source);
00127 ret->destination = octstr_duplicate(dlr->destination);
00128 ret->service = octstr_duplicate(dlr->service);
00129 ret->url = octstr_duplicate(dlr->url);
00130 ret->boxc_id = octstr_duplicate(dlr->boxc_id);
00131 ret->mask = dlr->mask;
00132
00133 return ret;
00134 }
00135
00136
00137
00138
00139 void dlr_entry_destroy(struct dlr_entry *dlr)
00140 {
00141
00142 if (dlr == NULL)
00143 return;
00144
00145 #define O_DELETE(a) { if (a) octstr_destroy(a); a = NULL; }
00146
00147 O_DELETE(dlr->smsc);
00148 O_DELETE(dlr->timestamp);
00149 O_DELETE(dlr->source);
00150 O_DELETE(dlr->destination);
00151 O_DELETE(dlr->service);
00152 O_DELETE(dlr->url);
00153 O_DELETE(dlr->boxc_id);
00154
00155 #undef O_DELETE
00156
00157 dlr->mask = 0;
00158 gw_free(dlr);
00159 }
00160
00161
00162
00163
00164
00165
00166 struct dlr_db_fields *dlr_db_fields_create(CfgGroup *grp)
00167 {
00168 struct dlr_db_fields *ret = NULL;
00169
00170 ret = gw_malloc(sizeof(*ret));
00171 gw_assert(ret != NULL);
00172 memset(ret, 0, sizeof(*ret));
00173
00174 if (!(ret->table = cfg_get(grp, octstr_imm("table"))))
00175 panic(0, "DLR: DB: directive 'table' is not specified!");
00176 if (!(ret->field_smsc = cfg_get(grp, octstr_imm("field-smsc"))))
00177 panic(0, "DLR: DB: directive 'field-smsc' is not specified!");
00178 if (!(ret->field_ts = cfg_get(grp, octstr_imm("field-timestamp"))))
00179 panic(0, "DLR: DB: directive 'field-timestamp' is not specified!");
00180 if (!(ret->field_src = cfg_get(grp, octstr_imm("field-source"))))
00181 panic(0, "DLR: DB: directive 'field-source' is not specified!");
00182 if (!(ret->field_dst = cfg_get(grp, octstr_imm("field-destination"))))
00183 panic(0, "DLR: DB: directive 'field-destination' is not specified!");
00184 if (!(ret->field_serv = cfg_get(grp, octstr_imm("field-service"))))
00185 panic(0, "DLR: DB: directive 'field-service' is not specified!");
00186 if (!(ret->field_url = cfg_get(grp, octstr_imm("field-url"))))
00187 panic(0, "DLR: DB: directive 'field-url' is not specified!");
00188 if (!(ret->field_mask = cfg_get(grp, octstr_imm("field-mask"))))
00189 panic(0, "DLR: DB: directive 'field-mask' is not specified!");
00190 if (!(ret->field_status = cfg_get(grp, octstr_imm("field-status"))))
00191 panic(0, "DLR: DB: directive 'field-status' is not specified!");
00192 if (!(ret->field_boxc = cfg_get(grp, octstr_imm("field-boxc-id"))))
00193 panic(0, "DLR: DB: directive 'field-boxc-id' is not specified!");
00194
00195 return ret;
00196 }
00197
00198 void dlr_db_fields_destroy(struct dlr_db_fields *fields)
00199 {
00200
00201 if (fields == NULL)
00202 return;
00203
00204 #define O_DELETE(a) { if (a) octstr_destroy(a); a = NULL; }
00205
00206 O_DELETE(fields->table);
00207 O_DELETE(fields->field_smsc);
00208 O_DELETE(fields->field_ts);
00209 O_DELETE(fields->field_src);
00210 O_DELETE(fields->field_dst);
00211 O_DELETE(fields->field_serv);
00212 O_DELETE(fields->field_url);
00213 O_DELETE(fields->field_mask);
00214 O_DELETE(fields->field_status);
00215 O_DELETE(fields->field_boxc);
00216
00217 #undef O_DELETE
00218
00219 gw_free(fields);
00220 }
00221
00222
00223
00224
00225
00226
00227 void dlr_init(Cfg* cfg)
00228 {
00229 CfgGroup *grp;
00230 Octstr *dlr_type;
00231
00232
00233 grp = cfg_get_single_group(cfg, octstr_imm("core"));
00234 if(grp == NULL)
00235 panic(0, "DLR: can't find group core");
00236
00237 dlr_type = cfg_get(grp, octstr_imm("dlr-storage"));
00238
00239
00240
00241
00242
00243 if (dlr_type == NULL) {
00244 dlr_type = octstr_imm("internal");
00245 warning(0, "DLR: using default 'internal' for storage type.");
00246 }
00247
00248
00249 if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) {
00250 handles = dlr_init_mysql(cfg);
00251 } else if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) {
00252 handles = dlr_init_sdb(cfg);
00253 } else if (octstr_compare(dlr_type, octstr_imm("oracle")) == 0) {
00254 handles = dlr_init_oracle(cfg);
00255 } else if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) {
00256 handles = dlr_init_mem(cfg);
00257 } else if (octstr_compare(dlr_type, octstr_imm("pgsql")) == 0) {
00258 handles = dlr_init_pgsql(cfg);
00259 }
00260
00261
00262
00263
00264
00265 if (handles == NULL) {
00266 panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
00267 }
00268
00269
00270 if (handles->dlr_add == NULL || handles->dlr_get == NULL || handles->dlr_remove == NULL)
00271 panic(0, "DLR: storage type '%s' don't implement needed functions", octstr_get_cstr(dlr_type));
00272
00273
00274 info(0, "DLR using storage type: %s", handles->type);
00275
00276
00277 octstr_destroy(dlr_type);
00278 }
00279
00280
00281
00282
00283 void dlr_shutdown()
00284 {
00285 if (handles != NULL && handles->dlr_shutdown != NULL)
00286 handles->dlr_shutdown();
00287 }
00288
00289
00290
00291
00292 long dlr_messages(void)
00293 {
00294 if (handles != NULL && handles->dlr_messages != NULL)
00295 return handles->dlr_messages();
00296
00297 return -1;
00298 }
00299
00300
00301
00302
00303 const char* dlr_type(void)
00304 {
00305 if (handles != NULL && handles->type != NULL)
00306 return handles->type;
00307
00308 return "unknown";
00309 }
00310
00311
00312
00313
00314 void dlr_add(const Octstr *smsc, const Octstr *ts, const Msg *msg)
00315 {
00316 struct dlr_entry *dlr = NULL;
00317
00318 if(octstr_len(smsc) == 0) {
00319 warning(0, "DLR[%s]: Can't add a dlr without smsc-id", dlr_type());
00320 return;
00321 }
00322
00323
00324 if (handles == NULL || handles->dlr_add == NULL || msg == NULL)
00325 return;
00326
00327
00328 if (!DLR_IS_ENABLED(msg->sms.dlr_mask))
00329 return;
00330
00331
00332 dlr = dlr_entry_create();
00333 gw_assert(dlr != NULL);
00334
00335
00336 dlr->smsc = (smsc ? octstr_duplicate(smsc) : octstr_create(""));
00337 dlr->timestamp = (ts ? octstr_duplicate(ts) : octstr_create(""));
00338 dlr->source = (msg->sms.sender ? octstr_duplicate(msg->sms.sender) : octstr_create(""));
00339 dlr->destination = (msg->sms.receiver ? octstr_duplicate(msg->sms.receiver) : octstr_create(""));
00340 dlr->service = (msg->sms.service ? octstr_duplicate(msg->sms.service) : octstr_create(""));
00341 dlr->url = (msg->sms.dlr_url ? octstr_duplicate(msg->sms.dlr_url) : octstr_create(""));
00342 dlr->boxc_id = (msg->sms.boxc_id ? octstr_duplicate(msg->sms.boxc_id) : octstr_create(""));
00343 dlr->mask = msg->sms.dlr_mask;
00344
00345 debug("dlr.dlr", 0, "DLR[%s]: Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, mask=%d, boxc=%s",
00346 dlr_type(), octstr_get_cstr(dlr->smsc), octstr_get_cstr(dlr->timestamp),
00347 octstr_get_cstr(dlr->source), octstr_get_cstr(dlr->destination), dlr->mask, octstr_get_cstr(dlr->boxc_id));
00348
00349
00350 handles->dlr_add(dlr);
00351 }
00352
00353
00354
00355
00356
00357
00358 Msg *dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ)
00359 {
00360 Msg *msg = NULL;
00361 struct dlr_entry *dlr = NULL;
00362
00363 if(octstr_len(smsc) == 0) {
00364 warning(0, "DLR[%s]: Can't find a dlr without smsc-id", dlr_type());
00365 return NULL;
00366 }
00367
00368
00369 if (handles == NULL || handles->dlr_get == NULL)
00370 return NULL;
00371
00372 debug("dlr.dlr", 0, "DLR[%s]: Looking for DLR smsc=%s, ts=%s, dst=%s, type=%d",
00373 dlr_type(), octstr_get_cstr(smsc), octstr_get_cstr(ts), octstr_get_cstr(dst), typ);
00374
00375 dlr = handles->dlr_get(smsc, ts, dst);
00376 if (dlr == NULL) {
00377 warning(0, "DLR[%s]: DLR from SMSC<%s> for DST<%s> not found.",
00378 dlr_type(), octstr_get_cstr(smsc), octstr_get_cstr(dst));
00379 return NULL;
00380 }
00381
00382 #define O_SET(x, val) if (octstr_len(val) > 0) { x = val; val = NULL; }
00383
00384 if ((typ & dlr->mask) > 0) {
00385
00386 msg = msg_create(sms);
00387 msg->sms.sms_type = report_mo;
00388 msg->sms.dlr_mask = typ;
00389 O_SET(msg->sms.service, dlr->service);
00390 O_SET(msg->sms.smsc_id, dlr->smsc);
00391 O_SET(msg->sms.receiver, dlr->destination);
00392 O_SET(msg->sms.sender, dlr->source);
00393
00394 O_SET(msg->sms.dlr_url, dlr->url);
00395
00396
00397
00398
00399 msg->sms.msgdata = NULL;
00400
00401
00402
00403
00404 O_SET(msg->sms.boxc_id, dlr->boxc_id);
00405
00406 time(&msg->sms.time);
00407 debug("dlr.dlr", 0, "DLR[%s]: created DLR message for URL <%s>",
00408 dlr_type(), (msg->sms.dlr_url?octstr_get_cstr(msg->sms.dlr_url):""));
00409 } else {
00410 debug("dlr.dlr", 0, "DLR[%s]: Ignoring DLR message because of mask type=%d dlr->mask=%d", dlr_type(), typ, dlr->mask);
00411
00412 msg = NULL;
00413 }
00414
00415 #undef O_SET
00416
00417
00418 if ((typ & DLR_BUFFERED) && ((dlr->mask & DLR_SUCCESS) || (dlr->mask & DLR_FAIL))) {
00419 debug("dlr.dlr", 0, "DLR[%s]: DLR not destroyed, still waiting for other delivery report", dlr_type());
00420
00421 if (handles != NULL && handles->dlr_update != NULL)
00422 handles->dlr_update(smsc, ts, dst, typ);
00423 } else {
00424 if (handles != NULL && handles->dlr_remove != NULL) {
00425
00426 handles->dlr_remove(smsc, ts, dst);
00427 } else {
00428 warning(0, "DLR[%s]: Storage don't have remove operation defined", dlr_type());
00429 }
00430 }
00431
00432
00433 dlr_entry_destroy(dlr);
00434
00435 return msg;
00436 }
00437
00438 void dlr_flush(void)
00439 {
00440 info(0, "Flushing all %ld queued DLR messages in %s storage", dlr_messages(),
00441 dlr_type());
00442
00443 if (handles != NULL && handles->dlr_flush != NULL)
00444 handles->dlr_flush();
00445 }
00446
00447
00448 Msg* create_dlr_from_msg(const Octstr *smsc, const Msg *msg, const Octstr *reply, long stat)
00449 {
00450 Msg *dlrmsg;
00451
00452 if (msg == NULL)
00453 return NULL;
00454
00455
00456 debug("dlr.dlr", 0,"SMSC[%s]: creating DLR message",
00457 (smsc ? octstr_get_cstr(smsc) : "UNKNOWN"));
00458
00459 dlrmsg = msg_create(sms);
00460 gw_assert(dlrmsg != NULL);
00461
00462 dlrmsg->sms.service = octstr_duplicate(msg->sms.service);
00463 dlrmsg->sms.dlr_mask = stat;
00464 dlrmsg->sms.sms_type = report_mo;
00465 dlrmsg->sms.smsc_id = octstr_duplicate(smsc ? smsc : msg->sms.smsc_id);
00466 dlrmsg->sms.sender = octstr_duplicate(msg->sms.sender);
00467 dlrmsg->sms.receiver = octstr_duplicate(msg->sms.receiver);
00468 dlrmsg->sms.dlr_url = octstr_duplicate(msg->sms.dlr_url);
00469 dlrmsg->sms.msgdata = octstr_duplicate(reply);
00470 dlrmsg->sms.boxc_id = octstr_duplicate(msg->sms.boxc_id);
00471 time(&dlrmsg->sms.time);
00472
00473 debug("dlr.dlr", 0,"SMSC[%s]: DLR = %s",
00474 (smsc ? octstr_get_cstr(smsc) : "UNKNOWN"),
00475 (dlrmsg->sms.dlr_url ? octstr_get_cstr(dlrmsg->sms.dlr_url) : ""));
00476
00477 return dlrmsg;
00478 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.