/* * Find matching entry in our spool and return the dlr_entry. */ static struct dlr_entry *dlr_spool_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { struct dlr_entry *ret = NULL; Octstr *os, *hash, *dir, *filename = NULL; Msg *msg; /* determine target dir and filename via hash */ os = octstr_duplicate(smsc); octstr_append(os, ts); hash = our_hash_func(os); octstr_destroy(os); /* determine target dir */ dir = octstr_format("%S/%ld", spool_dir, octstr_hash_key(hash) % MAX_DIRS); /* get content of msg surrogate */ os = get_msg_surrogate(dir, hash, dst, &filename); octstr_destroy(dir); octstr_destroy(hash); /* if there was no content */ if (os == NULL) { octstr_destroy(filename); return NULL; } /* unpack */ if ((msg = store_msg_unpack(os)) == NULL) { octstr_destroy(os); error(0, "Could not unpack DLR message `%s'", octstr_get_cstr(filename)); octstr_destroy(filename); return ret; } octstr_destroy(os); octstr_destroy(filename); #define MAP(to, from) \ to = from; \ from = NULL; /* map values to a struct dlr_entry */ ret = dlr_entry_create(); MAP(ret->smsc, msg->sms.smsc_id); MAP(ret->timestamp, msg->sms.foreign_id); MAP(ret->source, msg->sms.sender); MAP(ret->destination, msg->sms.receiver); MAP(ret->service, msg->sms.service); MAP(ret->url, msg->sms.dlr_url); MAP(ret->boxc_id, msg->sms.boxc_id); ret->mask = msg->sms.dlr_mask; msg_destroy(msg); return ret; }
static struct dlr_entry* dlr_get_oracle(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { Octstr *sql; DBPoolConn *pconn; List *result = NULL, *row; struct dlr_entry *res = NULL; List *binds = gwlist_create(); pconn = dbpool_conn_consume(pool); if (pconn == NULL) /* should not happens, but sure is sure */ return NULL; sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S=:1 AND %S=:2 AND %S=:3 AND ROWNUM < 2", fields->field_mask, fields->field_serv, fields->field_url, fields->field_src, fields->field_dst, fields->field_boxc, fields->table, fields->field_smsc, fields->field_ts, fields->field_dst); gwlist_append(binds, (Octstr *)smsc); /* :1 */ gwlist_append(binds, (Octstr *)ts); /* :2 */ gwlist_append(binds, (Octstr *)dst); /* :3 */ #if defined(DLR_TRACE) debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql)); #endif if (dbpool_conn_select(pconn, sql, binds, &result) != 0) { octstr_destroy(sql); dbpool_conn_produce(pconn); return NULL; } octstr_destroy(sql); gwlist_destroy(binds, NULL); dbpool_conn_produce(pconn); #define LO2CSTR(r, i) octstr_get_cstr(gwlist_get(r, i)) if (gwlist_len(result) > 0) { row = gwlist_extract_first(result); res = dlr_entry_create(); gw_assert(res != NULL); res->mask = atoi(LO2CSTR(row,0)); res->service = octstr_create(LO2CSTR(row, 1)); res->url = octstr_create(LO2CSTR(row,2)); res->source = octstr_create(LO2CSTR(row, 3)); res->destination = octstr_create(LO2CSTR(row, 4)); res->boxc_id = octstr_create(LO2CSTR(row, 5)); gwlist_destroy(row, octstr_destroy_item); res->smsc = octstr_duplicate(smsc); } gwlist_destroy(result, NULL); #undef LO2CSTR return res; }
static struct dlr_entry* dlr_get_mssql(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { Octstr *sql, *like; DBPoolConn *pconn; List *result = NULL, *row; struct dlr_entry *res = NULL; pconn = dbpool_conn_consume(pool); if (pconn == NULL) /* should not happens, but sure is sure */ return NULL; if (dst) like = octstr_format("AND %S LIKE '%%%S'", fields->field_dst, dst); else like = octstr_imm(""); sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S='%S'" " AND %S='%S' %S", fields->field_mask, fields->field_serv, fields->field_url, fields->field_src, fields->field_dst, fields->field_boxc, fields->table, fields->field_smsc, smsc, fields->field_ts, ts, like); #if defined(DLR_TRACE) debug("dlr.mssql", 0, "sql: %s", octstr_get_cstr(sql)); #endif if (dbpool_conn_select(pconn, sql, NULL, &result) != 0) { octstr_destroy(sql); dbpool_conn_produce(pconn); return NULL; } octstr_destroy(sql); octstr_destroy(like); dbpool_conn_produce(pconn); #define LO2CSTR(r, i) octstr_get_cstr(gwlist_get(r, i)) if (gwlist_len(result) > 0) { row = gwlist_extract_first(result); res = dlr_entry_create(); gw_assert(res != NULL); res->mask = atoi(LO2CSTR(row,0)); res->service = octstr_create(LO2CSTR(row, 1)); res->url = octstr_create(LO2CSTR(row,2)); res->source = octstr_create(LO2CSTR(row, 3)); res->destination = octstr_create(LO2CSTR(row, 4)); res->boxc_id = octstr_create(LO2CSTR(row, 5)); gwlist_destroy(row, octstr_destroy_item); res->smsc = octstr_duplicate(smsc); } gwlist_destroy(result, NULL); #undef LO2CSTR return res; }
static struct dlr_entry *dlr_pgsql_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { struct dlr_entry *res = NULL; Octstr *sql, *like; List *result, *row; if (dst) like = octstr_format("AND \"%S\" LIKE '%%%S'", fields->field_dst, dst); else like = octstr_imm(""); sql = octstr_format("SELECT \"%S\", \"%S\", \"%S\", \"%S\", \"%S\", " "\"%S\" FROM \"%S\" WHERE \"%S\"='%S' AND \"%S\"='%S' %S LIMIT 1;", fields->field_mask, fields->field_serv, fields->field_url, fields->field_src, fields->field_dst, fields->field_boxc, fields->table, fields->field_smsc, smsc, fields->field_ts, ts, like); result = pgsql_select(sql); octstr_destroy(sql); octstr_destroy(like); if (result == NULL || gwlist_len(result) < 1) { debug("dlr.pgsql", 0, "no rows found"); gwlist_destroy(result, NULL); return NULL; } row = gwlist_get(result, 0); debug("dlr.pgsql", 0, "Found entry, col1=%s, col2=%s, col3=%s, col4=%s, col5=%s col6=%s", octstr_get_cstr(gwlist_get(row, 0)), octstr_get_cstr(gwlist_get(row, 1)), octstr_get_cstr(gwlist_get(row, 2)), octstr_get_cstr(gwlist_get(row, 3)), octstr_get_cstr(gwlist_get(row, 4)), octstr_get_cstr(gwlist_get(row, 5)) ); res = dlr_entry_create(); gw_assert(res != NULL); res->mask = atoi(octstr_get_cstr(gwlist_get(row, 0))); res->service = octstr_duplicate(gwlist_get(row, 1)); res->url = octstr_duplicate(gwlist_get(row, 2)); res->source = octstr_duplicate(gwlist_get(row, 3)); res->destination = octstr_duplicate(gwlist_get(row, 4)); res->boxc_id = octstr_duplicate(gwlist_get(row, 5)); res->smsc = octstr_duplicate(smsc); while((row = gwlist_extract_first(result))) gwlist_destroy(row, octstr_destroy_item); gwlist_destroy(result, NULL); return res; }
static struct dlr_entry *dlr_pgsql_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { struct dlr_entry *res = NULL; Octstr *sql; List *result, *row; sql = octstr_format("SELECT %s, %s, %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1;", octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_serv), octstr_get_cstr(fields->field_url), octstr_get_cstr(fields->field_src), octstr_get_cstr(fields->field_dst), octstr_get_cstr(fields->field_boxc), octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts)); result = pgsql_select(sql); octstr_destroy(sql); if (result == NULL || gwlist_len(result) < 1) { debug("dlr.pgsql", 0, "no rows found"); while((row = gwlist_extract_first(result))) gwlist_destroy(row, octstr_destroy_item); gwlist_destroy(result, NULL); return NULL; } row = gwlist_get(result, 0); debug("dlr.pgsql", 0, "Found entry, col1=%s, col2=%s, col3=%s, col4=%s, col5=%s col6=%s", octstr_get_cstr(gwlist_get(row, 0)), octstr_get_cstr(gwlist_get(row, 1)), octstr_get_cstr(gwlist_get(row, 2)), octstr_get_cstr(gwlist_get(row, 3)), octstr_get_cstr(gwlist_get(row, 4)), octstr_get_cstr(gwlist_get(row, 5)) ); res = dlr_entry_create(); gw_assert(res != NULL); res->mask = atoi(octstr_get_cstr(gwlist_get(row, 0))); res->service = octstr_duplicate(gwlist_get(row, 1)); res->url = octstr_duplicate(gwlist_get(row, 2)); res->source = octstr_duplicate(gwlist_get(row, 3)); res->destination = octstr_duplicate(gwlist_get(row, 4)); res->boxc_id = octstr_duplicate(gwlist_get(row, 5)); res->smsc = octstr_duplicate(smsc); while((row = gwlist_extract_first(result))) gwlist_destroy(row, octstr_destroy_item); gwlist_destroy(result, NULL); return res; }
/* * Add new dlr entry into dlr storage */ void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg) { struct dlr_entry *dlr = NULL; /* Add the foreign_id so all SMSC modules can use it. * Obey also the original message in the split_parts list. */ if (msg->sms.foreign_id != NULL) octstr_destroy(msg->sms.foreign_id); msg->sms.foreign_id = octstr_duplicate(ts); if (msg->sms.split_parts != NULL) { struct split_parts *split = msg->sms.split_parts; if (split->orig->sms.foreign_id != NULL) octstr_destroy(split->orig->sms.foreign_id); split->orig->sms.foreign_id = octstr_duplicate(ts); } if(octstr_len(smsc) == 0) { warning(0, "DLR[%s]: Can't add a dlr without smsc-id", dlr_type()); return; } /* sanity check */ if (handles == NULL || handles->dlr_add == NULL || msg == NULL) return; /* check if delivery receipt requested */ if (!DLR_IS_ENABLED(msg->sms.dlr_mask)) return; /* allocate new struct dlr_entry struct */ dlr = dlr_entry_create(); gw_assert(dlr != NULL); /* now copy all values, we are interested in */ dlr->smsc = (smsc ? octstr_duplicate(smsc) : octstr_create("")); dlr->timestamp = (ts ? octstr_duplicate(ts) : octstr_create("")); dlr->source = (msg->sms.sender ? octstr_duplicate(msg->sms.sender) : octstr_create("")); dlr->destination = (msg->sms.receiver ? octstr_duplicate(msg->sms.receiver) : octstr_create("")); dlr->service = (msg->sms.service ? octstr_duplicate(msg->sms.service) : octstr_create("")); dlr->url = (msg->sms.dlr_url ? octstr_duplicate(msg->sms.dlr_url) : octstr_create("")); dlr->boxc_id = (msg->sms.boxc_id ? octstr_duplicate(msg->sms.boxc_id) : octstr_create("")); dlr->mask = msg->sms.dlr_mask; debug("dlr.dlr", 0, "DLR[%s]: Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, mask=%d, boxc=%s", dlr_type(), octstr_get_cstr(dlr->smsc), octstr_get_cstr(dlr->timestamp), octstr_get_cstr(dlr->source), octstr_get_cstr(dlr->destination), dlr->mask, octstr_get_cstr(dlr->boxc_id)); /* call registered function */ handles->dlr_add(dlr); }
/* * Duplicate dlr entry */ struct dlr_entry *dlr_entry_duplicate(const struct dlr_entry *dlr) { struct dlr_entry *ret; if (dlr == NULL) return NULL; ret = dlr_entry_create(); ret->smsc = octstr_duplicate(dlr->smsc); ret->timestamp = octstr_duplicate(dlr->timestamp); ret->source = octstr_duplicate(dlr->source); ret->destination = octstr_duplicate(dlr->destination); ret->service = octstr_duplicate(dlr->service); ret->url = octstr_duplicate(dlr->url); ret->boxc_id = octstr_duplicate(dlr->boxc_id); ret->mask = dlr->mask; return ret; }
static struct dlr_entry* dlr_sdb_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { Octstr *sql, *like; int state; struct dlr_entry *res = dlr_entry_create(); gw_assert(res != NULL); if (dst) like = octstr_format("AND %S LIKE '%%%S'", fields->field_dst, dst); else like = octstr_imm(""); sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S='%S' " "AND %S='%S' %S %s", fields->field_mask, fields->field_serv, fields->field_url, fields->field_src, fields->field_dst, fields->field_boxc, fields->table, fields->field_smsc, smsc, fields->field_ts, ts, like, sdb_get_limit_str()); #if defined(DLR_TRACE) debug("dlr.sdb", 0, "SDB: sql: %s", octstr_get_cstr(sql)); #endif state = gw_sdb_query(octstr_get_cstr(sql), sdb_callback_add, res); octstr_destroy(sql); octstr_destroy(like); if (state == -1) { error(0, "SDB: error in finding DLR"); goto notfound; } else if (state == 0) { debug("dlr.sdb", 0, "SDB: no entry found for DST <%s>.", octstr_get_cstr(dst)); goto notfound; } res->smsc = octstr_duplicate(smsc); return res; notfound: dlr_entry_destroy(res); return NULL; }
static struct dlr_entry* dlr_sdb_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { Octstr *sql; int state; struct dlr_entry *res = dlr_entry_create(); gw_assert(res != NULL); sql = octstr_format("SELECT %s, %s, %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s' %s", octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_serv), octstr_get_cstr(fields->field_url), octstr_get_cstr(fields->field_src), octstr_get_cstr(fields->field_dst), octstr_get_cstr(fields->field_boxc), octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts), sdb_get_limit_str()); #if defined(DLR_TRACE) debug("dlr.sdb", 0, "SDB: sql: %s", octstr_get_cstr(sql)); #endif state = gw_sdb_query(octstr_get_cstr(sql), sdb_callback_add, res); octstr_destroy(sql); if (state == -1) { error(0, "SDB: error in finding DLR"); goto notfound; } else if (state == 0) { debug("dlr.sdb", 0, "SDB: no entry found for DST <%s>.", octstr_get_cstr(dst)); goto notfound; } res->smsc = octstr_duplicate(smsc); return res; notfound: dlr_entry_destroy(res); return NULL; }
static struct dlr_entry *dlr_redis_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { Octstr *key, *sql; DBPoolConn *pconn; List *binds = gwlist_create(); List *result = NULL, *row; struct dlr_entry *res = NULL; pconn = dbpool_conn_consume(pool); if (pconn == NULL) { error(0, "DLR: REDIS: No connection available"); gwlist_destroy(binds, NULL); dbpool_conn_produce(pconn); return NULL; } /* If the destination address is not NULL, then * it has been shortened by the abstractive layer. */ key = octstr_format((dst ? "%S:?:?:?" : "%S:?:?"), fields->table); sql = octstr_format("HMGET %S ? ? ? ? ? ?", key); gwlist_append(binds, (Octstr *)smsc); /* key */ gwlist_append(binds, (Octstr *)ts); /* key */ if (dst) gwlist_append(binds, (Octstr *)dst); /* key */ gwlist_append(binds, fields->field_mask); gwlist_append(binds, fields->field_serv); gwlist_append(binds, fields->field_url); gwlist_append(binds, fields->field_src); gwlist_append(binds, fields->field_dst); gwlist_append(binds, fields->field_boxc); if (dbpool_conn_select(pconn, sql, binds, &result) != 0) { error(0, "DLR: REDIS: Failed to fetch DLR for %s", octstr_get_cstr(key)); octstr_destroy(sql); octstr_destroy(key); gwlist_destroy(binds, NULL); dbpool_conn_produce(pconn); return NULL; } dbpool_conn_produce(pconn); octstr_destroy(sql); octstr_destroy(key); gwlist_destroy(binds, NULL); #define LO2CSTR(r, i) octstr_get_cstr(gwlist_get(r, i)) if (gwlist_len(result) > 0) { row = gwlist_extract_first(result); /* * If we get an empty set back from redis, this is * still an array with "" values, representing (nil). * If the mask is empty then this can't be a valid * set, therefore bail out. */ if (octstr_len(gwlist_get(row, 0)) > 0) { res = dlr_entry_create(); gw_assert(res != NULL); res->mask = atoi(octstr_get_cstr(gwlist_get(row, 0))); get_octstr_value(&res->service, row, 1); get_octstr_value(&res->url, row, 2); octstr_url_decode(res->url); get_octstr_value(&res->source, row, 3); get_octstr_value(&res->destination, row, 4); get_octstr_value(&res->boxc_id, row, 5); res->smsc = octstr_duplicate(smsc); octstr_replace(res->source, octstr_imm("__space__"), octstr_imm(" ")); octstr_replace(res->destination, octstr_imm("__space__"), octstr_imm(" ")); } gwlist_destroy(row, octstr_destroy_item); } gwlist_destroy(result, NULL); #undef LO2CSTR return res; }
static struct dlr_entry* dlr_mongodb_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst) { DBPoolConn *pconn; bson cond, obj; bson_buffer cond_buf; bson_iterator it; struct dlr_entry *res = NULL; bson_bool_t found = 0; mongo_connection *conn = NULL; pconn = dbpool_conn_consume(pool); if (pconn == NULL) { return NULL; } conn = (mongo_connection*)pconn->conn; bson_buffer_init(&cond_buf); bson_append_string(&cond_buf, octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc)); bson_append_string(&cond_buf, octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts)); if (dst) { bson_append_string(&cond_buf, octstr_get_cstr(fields->field_dst), octstr_get_cstr(dst)); } bson_from_buffer(&cond, &cond_buf); memset(&obj, 0, sizeof(bson)); MONGO_TRY { found = mongo_find_one(conn, mongodb_namespace, &cond, NULL, &obj); } MONGO_CATCH { mongodb_error("dlr_mongodb_get", conn->exception.type); found = 0; } if (found) { res = dlr_entry_create(); gw_assert(res != NULL); bson_find(&it, &obj, octstr_get_cstr(fields->field_mask)); res->mask = bson_iterator_int(&it); bson_find(&it, &obj, octstr_get_cstr(fields->field_serv)); res->service = octstr_create(bson_iterator_string(&it)); bson_find(&it, &obj, octstr_get_cstr(fields->field_url)); res->url = octstr_create(bson_iterator_string(&it)); bson_find(&it, &obj, octstr_get_cstr(fields->field_src)); res->source = octstr_create(bson_iterator_string(&it)); bson_find(&it, &obj, octstr_get_cstr(fields->field_dst)); res->destination = octstr_create(bson_iterator_string(&it)); bson_find(&it, &obj, octstr_get_cstr(fields->field_boxc)); res->boxc_id = octstr_create(bson_iterator_string(&it)); bson_find(&it, &obj, octstr_get_cstr(fields->field_smsc)); res->smsc = octstr_create(bson_iterator_string(&it)); } dbpool_conn_produce(pconn); bson_destroy(&cond); bson_destroy(&obj); return res; }