Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

dlr.c File Reference

#include <ctype.h>
#include <time.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include "gwlib/gwlib.h"
#include "sms.h"
#include "dlr.h"
#include "dlr_p.h"

Include dependency graph for dlr.c:

Include dependency graph

Go to the source code of this file.

Defines

#define O_DELETE(a)   { if (a) octstr_destroy(a); a = NULL; }
#define O_DELETE(a)   { if (a) octstr_destroy(a); a = NULL; }
#define O_SET(x, val)   if (octstr_len(val) > 0) { x = val; val = NULL; }

Functions

dlr_entrydlr_entry_create (void)
dlr_entrydlr_entry_duplicate (const struct dlr_entry *dlr)
void dlr_entry_destroy (struct dlr_entry *dlr)
dlr_db_fieldsdlr_db_fields_create (CfgGroup *grp)
void dlr_db_fields_destroy (struct dlr_db_fields *fields)
void dlr_init (Cfg *cfg)
void dlr_shutdown ()
long dlr_messages (void)
const char * dlr_type (void)
void dlr_add (const Octstr *smsc, const Octstr *ts, const Msg *msg)
Msgdlr_find (const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ)
void dlr_flush (void)
Msgcreate_dlr_from_msg (const Octstr *smsc, const Msg *msg, const Octstr *reply, long stat)

Variables

dlr_storagehandles = NULL


Define Documentation

#define O_DELETE  )     { if (a) octstr_destroy(a); a = NULL; }
 

#define O_DELETE  )     { if (a) octstr_destroy(a); a = NULL; }
 

Referenced by dlr_db_fields_destroy(), and dlr_entry_destroy().

#define O_SET x,
val   )     if (octstr_len(val) > 0) { x = val; val = NULL; }
 

Referenced by dlr_find().


Function Documentation

Msg* create_dlr_from_msg const Octstr smsc,
const Msg msg,
const Octstr reply,
long  stat
 

Definition at line 448 of file dlr.c.

References debug(), gw_assert, msg_create, octstr_duplicate, octstr_get_cstr, and sms.

Referenced by bb_smscconn_send_failed(), and bb_smscconn_sent().

00449 {
00450     Msg *dlrmsg;
00451 
00452     if (msg == NULL)
00453         return NULL;
00454 
00455     /* generate DLR */
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 }

Here is the call graph for this function:

void dlr_add const Octstr smsc,
const Octstr ts,
const Msg msg
 

Definition at line 314 of file dlr.c.

References dlr_entry::boxc_id, debug(), dlr_entry::destination, dlr_storage::dlr_add, dlr_entry_create(), DLR_IS_ENABLED, dlr_type(), gw_assert, handles, dlr_entry::mask, octstr_create, octstr_duplicate, octstr_get_cstr, octstr_len(), dlr_entry::service, dlr_entry::smsc, dlr_entry::source, dlr_entry::timestamp, dlr_entry::url, and warning().

Referenced by add_msg_cb(), at2_send_one_message(), cgw_handle_op(), cimd2_submit_msg(), clickatell_parse_reply(), emi2_handle_smscreq(), handle_pdu(), kannel_parse_reply(), oisd_submit_msg(), soap_read_response(), and xidris_parse_reply().

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     /* sanity check */
00324     if (handles == NULL || handles->dlr_add == NULL || msg == NULL)
00325         return;
00326 
00327     /* check if delivery receipt requested */
00328     if (!DLR_IS_ENABLED(msg->sms.dlr_mask))
00329         return;
00330 
00331      /* allocate new struct dlr_entry struct */
00332     dlr = dlr_entry_create();
00333     gw_assert(dlr != NULL);
00334 
00335     /* now copy all values, we are interested in */
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     /* call registered function */
00350     handles->dlr_add(dlr);
00351 }

Here is the call graph for this function:

struct dlr_db_fields* dlr_db_fields_create CfgGroup grp  ) 
 

Definition at line 166 of file dlr.c.

References cfg_get, gw_assert, octstr_imm(), and panic.

Referenced by dlr_init_mysql(), and dlr_init_pgsql().

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 }

Here is the call graph for this function:

void dlr_db_fields_destroy struct dlr_db_fields fields  ) 
 

Definition at line 198 of file dlr.c.

References dlr_db_fields::field_boxc, dlr_db_fields::field_dst, dlr_db_fields::field_mask, dlr_db_fields::field_serv, dlr_db_fields::field_smsc, dlr_db_fields::field_src, dlr_db_fields::field_status, dlr_db_fields::field_ts, dlr_db_fields::field_url, fields, O_DELETE, and dlr_db_fields::table.

Referenced by dlr_mysql_shutdown(), and dlr_pgsql_shutdown().

00199 {
00200     /* sanity check */
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 }

struct dlr_entry* dlr_entry_create void   ) 
 

Definition at line 100 of file dlr.c.

References gw_assert.

Referenced by dlr_add(), dlr_entry_duplicate(), dlr_mysql_get(), and dlr_pgsql_get().

00101 {
00102     struct dlr_entry *dlr;
00103 
00104     dlr = gw_malloc(sizeof(*dlr));
00105     gw_assert(dlr != NULL);
00106 
00107     /* set all values to NULL */
00108     memset(dlr, 0, sizeof(*dlr));
00109 
00110     return dlr;
00111 }

void dlr_entry_destroy struct dlr_entry dlr  ) 
 

Definition at line 139 of file dlr.c.

References dlr_entry::boxc_id, dlr_entry::destination, dlr_entry::mask, O_DELETE, dlr_entry::service, dlr_entry::smsc, dlr_entry::source, dlr_entry::timestamp, and dlr_entry::url.

Referenced by dlr_find(), dlr_mem_remove(), dlr_mem_shutdown(), dlr_mysql_add(), and dlr_pgsql_add().

00140 {
00141     /* sanity check */
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 }

struct dlr_entry* dlr_entry_duplicate const struct dlr_entry dlr  ) 
 

Definition at line 116 of file dlr.c.

References dlr_entry::boxc_id, dlr_entry::destination, dlr_entry_create(), dlr_entry::mask, octstr_duplicate, dlr_entry::service, dlr_entry::smsc, dlr_entry::source, dlr_entry::timestamp, and dlr_entry::url.

Referenced by dlr_mem_get().

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 }

Here is the call graph for this function:

Msg* dlr_find const Octstr smsc,
const Octstr ts,
const Octstr dst,
int  typ
 

Definition at line 358 of file dlr.c.

References dlr_entry::boxc_id, debug(), dlr_entry::destination, dlr_entry_destroy(), dlr_storage::dlr_get, dlr_storage::dlr_remove, dlr_type(), dlr_storage::dlr_update, handles, dlr_entry::mask, msg_create, O_SET, octstr_get_cstr, octstr_len(), dlr_entry::service, sms, dlr_entry::smsc, dlr_entry::source, dlr_entry::url, and warning().

Referenced by at2_pdu_decode_report_sm(), cgw_handle_op(), cimd2_accept_delivery_report_message(), clickatell_receive_sms(), handle_dlr(), handle_operation(), kannel_receive_sms(), main_connection_loop(), oisd_accept_delivery_report_message(), soap_parse_dlr(), and xidris_receive_sms().

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     /* check if we have handler registered */
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         /* its an entry we are interested in */
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         /* if dlr_url was present, recode it here again */
00394         O_SET(msg->sms.dlr_url, dlr->url);
00395         /* 
00396          * insert original message to the data segment 
00397          * later in the smsc module 
00398          */
00399         msg->sms.msgdata = NULL;
00400         /* 
00401          * If a boxc_id is available, then instruct bearerbox to 
00402          * route this msg back to originating smsbox
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         /* ok that was a status report but we where not interested in having it */
00412         msg = NULL;
00413     }
00414 
00415 #undef O_SET
00416  
00417     /* check for end status and if so remove from storage */
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         /* update dlr entry status if function defined */
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             /* it's not good for internal storage, but better for all others */
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     /* destroy struct dlr_entry */
00433     dlr_entry_destroy(dlr);
00434 
00435     return msg;
00436 }

Here is the call graph for this function:

void dlr_flush void   ) 
 

Definition at line 438 of file dlr.c.

References dlr_storage::dlr_flush, dlr_messages(), dlr_type(), handles, and info().

Referenced by bb_flush_dlr().

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 }

Here is the call graph for this function:

void dlr_init Cfg cfg  ) 
 

Definition at line 227 of file dlr.c.

References cfg_get, cfg_get_single_group(), dlr_storage::dlr_add, dlr_storage::dlr_get, dlr_init_mem(), dlr_init_mysql(), dlr_init_oracle(), dlr_init_pgsql(), dlr_init_sdb(), dlr_storage::dlr_remove, dlr_type(), handles, info(), octstr_compare(), octstr_destroy(), octstr_get_cstr, octstr_imm(), panic, dlr_storage::type, and warning().

Referenced by main().

00228 {
00229     CfgGroup *grp;
00230     Octstr *dlr_type;
00231 
00232     /* check which DLR storage type we are using */
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      * assume we are using internal memory in case no directive
00241      * has been specified, warn the user anyway
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     /* call the sub-init routine */
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      * add aditional types here
00263      */
00264 
00265      if (handles == NULL) {
00266         panic(0, "DLR: storage type '%s' is not supported!", octstr_get_cstr(dlr_type));
00267     }
00268 
00269     /* check needed function pointers */
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     /* get info from storage */
00274     info(0, "DLR using storage type: %s", handles->type);
00275 
00276     /* cleanup */
00277     octstr_destroy(dlr_type);
00278 }

Here is the call graph for this function:

long dlr_messages void   ) 
 

Definition at line 292 of file dlr.c.

References dlr_storage::dlr_messages, and handles.

Referenced by bb_print_status(), and dlr_flush().

00293 {
00294     if (handles != NULL && handles->dlr_messages != NULL)
00295         return handles->dlr_messages();
00296 
00297     return -1;
00298 }

void dlr_shutdown void   ) 
 

Definition at line 283 of file dlr.c.

References dlr_storage::dlr_shutdown, and handles.

Referenced by main().

00284 {
00285     if (handles != NULL && handles->dlr_shutdown != NULL)
00286         handles->dlr_shutdown();
00287 }

const char* dlr_type void   ) 
 

Definition at line 303 of file dlr.c.

References handles, and dlr_storage::type.

Referenced by bb_print_status(), dlr_add(), dlr_find(), dlr_flush(), and dlr_init().

00304 {
00305     if (handles != NULL && handles->type != NULL)
00306         return handles->type;
00307 
00308     return "unknown";
00309 }


Variable Documentation

struct dlr_storage* handles = NULL [static]
 

Definition at line 94 of file dlr.c.

Referenced by dlr_add(), dlr_find(), dlr_flush(), dlr_init(), dlr_messages(), dlr_shutdown(), and dlr_type().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.