\n\t");
}
else
tmp = octstr_format("%sBox connections:%s", para ? "" : "", lb);
boxes = 0;
if (wapbox_list) {
gwlist_lock(wapbox_list);
for(i=0; i < gwlist_len(wapbox_list); i++) {
bi = gwlist_get(wapbox_list, i);
if (bi->alive == 0)
continue;
t = orig - bi->connect_time;
if (status_type == BBSTATUS_XML)
octstr_format_append(tmp,
"\n\t\twapbox\n\t\t%s\n"
"\t\ton-line %ldd %ldh %ldm %lds\n"
"\t\t%s\n\t\n",
octstr_get_cstr(bi->client_ip),
t/3600/24, t/3600%24, t/60%60, t%60,
#ifdef HAVE_LIBSSL
conn_get_ssl(bi->conn) != NULL ? "yes" : "no"
#else
"not installed"
#endif
);
else
octstr_format_append(tmp,
"%swapbox, IP %s (on-line %ldd %ldh %ldm %lds) %s %s",
ws, octstr_get_cstr(bi->client_ip),
t/3600/24, t/3600%24, t/60%60, t%60,
#ifdef HAVE_LIBSSL
conn_get_ssl(bi->conn) != NULL ? "using SSL" : "",
#else
"",
#endif
lb);
boxes++;
}
gwlist_unlock(wapbox_list);
}
if (smsbox_list) {
gw_rwlock_rdlock(smsbox_list_rwlock);
for(i=0; i < gwlist_len(smsbox_list); i++) {
bi = gwlist_get(smsbox_list, i);
if (bi->alive == 0)
continue;
t = orig - bi->connect_time;
if (status_type == BBSTATUS_XML)
octstr_format_append(tmp, "\n\t\tsmsbox\n"
"\t\t%s\n\t\t%s\n"
"\t\t%ld\n"
"\t\ton-line %ldd %ldh %ldm %lds\n"
"\t\t%s\n\t",
(bi->boxc_id ? octstr_get_cstr(bi->boxc_id) : ""),
octstr_get_cstr(bi->client_ip),
gwlist_len(bi->incoming) + dict_key_count(bi->sent),
t/3600/24, t/3600%24, t/60%60, t%60,
#ifdef HAVE_LIBSSL
conn_get_ssl(bi->conn) != NULL ? "yes" : "no"
#else
"not installed"
#endif
);
else
octstr_format_append(tmp, "%ssmsbox:%s, IP %s (%ld queued), (on-line %ldd %ldh %ldm %lds) %s %s",
ws, (bi->boxc_id ? octstr_get_cstr(bi->boxc_id) : "(none)"),
octstr_get_cstr(bi->client_ip), gwlist_len(bi->incoming) + dict_key_count(bi->sent),
t/3600/24, t/3600%24, t/60%60, t%60,
#ifdef HAVE_LIBSSL
conn_get_ssl(bi->conn) != NULL ? "using SSL" : "",
#else
"",
#endif
lb);
boxes++;
}
gw_rwlock_unlock(smsbox_list_rwlock);
}
if (boxes == 0 && status_type != BBSTATUS_XML) {
octstr_destroy(tmp);
tmp = octstr_format("%sNo boxes connected", para ? "
" : "");
}
if (para)
octstr_append_cstr(tmp, "
");
if (status_type == BBSTATUS_XML)
octstr_append_cstr(tmp, "\n");
else
octstr_append_cstr(tmp, "\n\n");
return tmp;
}
int boxc_incoming_wdp_queue(void)
{
int i, q = 0;
Boxc *boxc;
if (wapbox_list) {
gwlist_lock(wapbox_list);
for(i=0; i < gwlist_len(wapbox_list); i++) {
boxc = gwlist_get(wapbox_list, i);
q += gwlist_len(boxc->incoming);
}
gwlist_unlock(wapbox_list);
}
return q;
}
void boxc_cleanup(void)
{
octstr_destroy(box_allow_ip);
octstr_destroy(box_deny_ip);
box_allow_ip = NULL;
box_deny_ip = NULL;
counter_destroy(boxid);
boxid = NULL;
}
/*
* Route the incoming message to one of the following input queues:
* a specific smsbox conn
* a random smsbox conn if no shortcut routing and msg->sms.boxc_id match
*
* BEWARE: All logic inside here should be fast, hence speed processing
* optimized, because every single MO message passes this function and we
* have to ensure that no unncessary overhead is done.
*/
int route_incoming_to_boxc(Msg *msg)
{
Boxc *bc = NULL, *best = NULL;
Octstr *s, *r;
long len, b, i;
int full_found = 0;
s = r = NULL;
gw_assert(msg_type(msg) == sms);
/* msg_dump(msg, 0); */
/*
* We have a specific route to pass this msg to smsbox-id
* Lookup the connection in the dictionary.
*/
gw_rwlock_rdlock(smsbox_list_rwlock);
if (gwlist_len(smsbox_list) == 0) {
gw_rwlock_unlock(smsbox_list_rwlock);
warning(0, "smsbox_list empty!");
if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) {
gwlist_produce(incoming_sms, msg);
return 0;
}
else
return -1;
}
if (octstr_len(msg->sms.boxc_id) > 0) {
bc = dict_get(smsbox_by_id, msg->sms.boxc_id);
if (bc == NULL) {
/*
* something is wrong, this was the smsbox connection we used
* for sending, so it seems this smsbox is gone
*/
warning(0,"Could not route message to smsbox id <%s>, smsbox is gone!",
octstr_get_cstr(msg->sms.boxc_id));
}
}
else {
/*
* Check if we have a "smsbox-route" for this msg.
* Where the shortcut route has a higher priority then the smsc-id rule.
*/
s = (msg->sms.smsc_id ? dict_get(smsbox_by_smsc, msg->sms.smsc_id) : NULL);
r = (msg->sms.receiver ? dict_get(smsbox_by_receiver, msg->sms.receiver) : NULL);
bc = r ? dict_get(smsbox_by_id, r) : (s ? dict_get(smsbox_by_id, s) : NULL);
}
/* check if we found our routing */
if (bc != NULL) {
if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(bc->incoming)) {
gwlist_produce(bc->incoming, msg);
gw_rwlock_unlock(smsbox_list_rwlock);
return 1; /* we are done */
}
else {
gw_rwlock_unlock(smsbox_list_rwlock);
return -1;
}
}
else if (s != NULL || r != NULL || octstr_len(msg->sms.boxc_id) > 0) {
gw_rwlock_unlock(smsbox_list_rwlock);
/*
* we have routing defined, but no smsbox connected at the moment.
* put msg into global incoming queue and wait until smsbox with
* such boxc_id connected.
*/
if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) {
gwlist_produce(incoming_sms, msg);
return 0;
}
else
return -1;
}
/*
* ok, none of the routing things applied previously, so route it to
* a random smsbox.
*/
/* take random smsbox from list, and then check all smsboxes
* and select the one with lowest load level - if tied, the first
* one
*/
len = gwlist_len(smsbox_list);
b = gw_rand() % len;
for(i = 0; i < gwlist_len(smsbox_list); i++) {
bc = gwlist_get(smsbox_list, (i+b) % len);
if (bc->boxc_id != NULL || bc->routable == 0)
bc = NULL;
if (bc != NULL && max_incoming_sms_qlength > 0 &&
gwlist_len(bc->incoming) > max_incoming_sms_qlength) {
full_found = 1;
bc = NULL;
}
if ((bc != NULL && best != NULL && bc->load < best->load) ||
(bc != NULL && best == NULL)) {
best = bc;
}
}
if (best != NULL) {
best->load++;
gwlist_produce(best->incoming, msg);
}
gw_rwlock_unlock(smsbox_list_rwlock);
if (best == NULL && full_found == 0) {
warning(0, "smsbox_list empty!");
if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) {
gwlist_produce(incoming_sms, msg);
return 0;
}
else
return -1;
}
else if (best == NULL && full_found == 1)
return -1;
return 1;
}
static void sms_to_smsboxes(void *arg)
{
Msg *newmsg, *startmsg, *msg;
long i, len;
int ret = -1;
Boxc *boxc;
gwlist_add_producer(flow_threads);
newmsg = startmsg = msg = NULL;
while(bb_status != BB_DEAD) {
if (newmsg == startmsg) {
/* check if we are in shutdown phase */
if (gwlist_producer_count(smsbox_list) == 0)
break;
if (ret == 0 || ret == -1) {
/* debug("", 0, "time to sleep"); */
gwthread_sleep(60.0);
/* debug("", 0, "wake up list len %ld", gwlist_len(incoming_sms)); */
/* shutdown ? */
if (gwlist_producer_count(smsbox_list) == 0 && gwlist_len(smsbox_list) == 0)
break;
}
startmsg = msg = gwlist_consume(incoming_sms);
/* debug("", 0, "gwlist_consume done 1"); */
newmsg = NULL;
}
else {
newmsg = msg = gwlist_consume(incoming_sms);
}
if (msg == NULL)
break;
gw_assert(msg_type(msg) == sms);
/* debug("bb.sms", 0, "sms_boxc_router: handling message (%p vs %p)",
msg, startmsg); */
ret = route_incoming_to_boxc(msg);
if (ret == 1)
startmsg = newmsg = NULL;
else if (ret == -1) {
gwlist_produce(incoming_sms, msg);
}
}
gw_rwlock_rdlock(smsbox_list_rwlock);
len = gwlist_len(smsbox_list);
for (i=0; i < len; i++) {
boxc = gwlist_get(smsbox_list, i);
gwlist_remove_producer(boxc->incoming);
}
gw_rwlock_unlock(smsbox_list_rwlock);
gwlist_remove_producer(flow_threads);
}