Exemplo n.º 1
0
/* restore callbacks */
void acc_loaded_callback(struct dlg_cell *dlg, int type,
			struct dlg_cb_params *_params) {
		str flags_s;
		unsigned int flags_l;

		if (!dlg) {
			LM_ERR("null dialog - cannot fetch message flags\n");
			return;
		}

		if (dlg_api.fetch_dlg_value(dlg, &flags_str, &flags_s, 0) < 0) {
			LM_DBG("flags were not saved in dialog\n");
			return;
		}
		flags_l = flag_list_to_bitmask(&flags_s, FLAG_TYPE_MSG, FLAG_DELIM);

		/* register database callbacks */
		if (dlg_api.register_dlgcb(dlg, DLGCB_TERMINATED |
				DLGCB_EXPIRED, acc_dlg_callback, (void*)(long)flags_l, 0)){
			LM_ERR("cannot register callback for database accounting\n");
			return;
		}
}
Exemplo n.º 2
0
static int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
                                unsigned int part_idx, unsigned int part_max)
{
	static char query_buf[512];
	static str query_str;
	static struct sip_uri puri;

	struct socket_info *sock;
	struct proxy_l next_hop;
	db_res_t *res = NULL;
	db_row_t *row;
	db_val_t *val;
	dlist_t *dom;
	str uri, host, flag_list;
	int i, no_rows = 10;
	int now_len;
	char now_s[25];
	char *p, *p1;
	int port, proto, p_len, p1_len;
	unsigned int dbflags;
	int needed;
	int shortage = 0;

	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof p_len;

	/* get the current time in DB format */
	now_len = 25;
	if (db_time2str(time(NULL), now_s, &now_len) != 0) {
		LM_ERR("failed to print now time\n");
		return -1;
	}

	LM_DBG("buf: %p. flags: %d\n", buf, flags);

	/* for each table */
	for (dom = root; dom; dom = dom->next) {
		if (db_check_table_version(&ul_dbf, ul_dbh, dom->d->name, UL_TABLE_VERSION))
			goto error;

		/* read the destinations */
		if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) {
			LM_ERR("cannot select table \"%.*s\"\n", dom->d->name->len,
			       dom->d->name->s);
			goto error;
		}

		i = snprintf(query_buf, sizeof query_buf, "select %.*s, %.*s, %.*s,"
#ifdef ORACLE_USRLOC
		" %.*s, %.*s from %s where %.*s > %.*s and mod(id, %u) = %u",
#else
		" %.*s, %.*s from %s where %.*s > %.*s and id %% %u = %u",
#endif
			received_col.len, received_col.s,
			contact_col.len, contact_col.s,
			sock_col.len, sock_col.s,
			cflags_col.len, cflags_col.s,
			path_col.len, path_col.s,
			dom->d->name->s,
			expires_col.len, expires_col.s,
			now_len, now_s,
			part_max, part_idx);

		LM_DBG("query: %.*s\n", (int)(sizeof query_buf), query_buf);
		if (i >= sizeof query_buf) {
			LM_ERR("DB query too long\n");
			goto error;
		}

		query_str.s = query_buf;
		query_str.len = i;

		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
			if (ul_dbf.raw_query(ul_dbh, &query_str, 0) < 0) {
				LM_ERR("raw_query failed\n");
				goto error;
			}

			no_rows = estimate_available_rows(20+128+20+128+64, 5);
			if (no_rows == 0)
				no_rows = 10;

			LM_DBG("fetching %d rows\n", no_rows);

			if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) {
				LM_ERR("Error fetching rows\n");
				goto error;
			}
		} else if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) {
			LM_ERR("raw_query failed\n");
			goto error;
		}

		do {
			for (i = 0; i < RES_ROW_N(res); i++) {
				row = RES_ROWS(res) + i;
				val = ROW_VALUES(row) + 3; /* cflags */
				flag_list.s   = (char *)VAL_STRING(val);
				flag_list.len = strlen(flag_list.s);

				LM_DBG("contact cflags: '%.*s'\n", flag_list.len, flag_list.s);

				/* contact is not flagged at all */
				if (flags && (val->nul || !flag_list.s))
					continue;

				dbflags = flag_list_to_bitmask(&flag_list,
				                FLAG_TYPE_BRANCH, FLAG_DELIM);

				LM_DBG("masks: param: %d --- %d :db\n", flags, dbflags);

				/* check if contact flags match the given bitmask */
				if ((dbflags & flags) != flags)
					continue;

				/* received */
				p = (char*)VAL_STRING(ROW_VALUES(row));
				if (VAL_NULL(ROW_VALUES(row)) || !p || !p[0]) {
					/* contact */
					p = (char*)VAL_STRING(ROW_VALUES(row) + 1);
					if (VAL_NULL(ROW_VALUES(row) + 1) || !p || *p == '\0') {
						LM_ERR("empty contact -> skipping\n");
						continue;
					}
				}
				p_len = strlen(p);

				/* path */
				p1 = (char*)VAL_STRING(ROW_VALUES(row) + 4);
				if (VAL_NULL(ROW_VALUES(row) + 4) || !p1 || *p1 == '\0') {
					p1 = NULL;
					p1_len = 0;
				} else
					p1_len = strlen(p1);

				needed = (int)(p_len + sizeof p_len + p1_len + sizeof p1_len +
				               sizeof sock + sizeof dbflags + sizeof next_hop);

				LM_DBG("len: %d, needed: %d\n", len, needed);

				if (len < needed) {
					shortage += needed;
					continue;
				}

				/* determine and parse the URI of this contact's next hop */
				if (p1_len > 0) {
					/* send to first URI in path */
					host.s   = p1;
					host.len = p1_len;
					if (get_path_dst_uri(&host, &uri) < 0) {
						LM_ERR("failed to get dst_uri for Path\n");
						continue;
					}
					if (parse_uri(uri.s, uri.len, &puri) < 0) {
						LM_ERR("failed to parse path URI of next hop: '%*.s'\n",
						        p1_len, p1);
						return -1;
					}
				} else {
					if (parse_uri(p, p_len, &puri) < 0) {
						LM_ERR("failed to parse contact of next hop: '%*.s'\n",
						        p_len, p);
						return -1;
					}
				}

				/* write received/contact */
				memcpy(buf, &p_len, sizeof p_len);
				buf += sizeof p_len;
				memcpy(buf, p, p_len);
				buf += p_len;

				/* write path */
				memcpy(buf, &p1_len, sizeof p1_len);
				buf += sizeof p1_len;
				memcpy(buf, p1, p1_len);
				buf += p1_len;

				/* sock */
				p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
				if (VAL_NULL(ROW_VALUES(row)+2) || !p || *p == '\0') {
					sock = NULL;
				} else {
					if (parse_phostport(p, strlen(p), &host.s, &host.len,
					    &port, &proto) != 0) {
						LM_ERR("bad socket <%s>...ignoring\n", p);
						sock = NULL;
					} else {
						sock = grep_sock_info(&host, (unsigned short)port, proto);
						if (!sock)
							LM_DBG("non-local socket <%s>...ignoring\n", p);
					}
				}

				/* write sock and flags */
				memcpy(buf, &sock, sizeof sock);
				buf += sizeof sock;
				memcpy(buf, &dbflags, sizeof dbflags);
				buf += sizeof dbflags;

				memset(&next_hop, 0, sizeof next_hop);
				next_hop.port  = puri.port_no;
				next_hop.proto = puri.proto;
				next_hop.name  = puri.host;

				/* write the next hop */
				memcpy(buf, &next_hop, sizeof next_hop);
				buf += sizeof next_hop;

				len -= needed;
			}

			if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
				if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) {
					LM_ERR("fetching rows (1)\n");
					goto error;
				}
			} else
				break;

		} while (RES_ROW_N(res) > 0);

		ul_dbf.free_result(ul_dbh, res);
	}

	/* len < 0 is possible, if size of the buffer < sizeof c->c.len */
	if (len >= 0)
		memset(buf, 0, sizeof p_len);

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage)
		abort();

	shortage -= len;

	return shortage > 0 ? shortage : 0;

error:
	if (res)
		ul_dbf.free_result(ul_dbh, res);
	return -1;
}