bb_smscconn.c
来自「The Kannel Open Source WAP and SMS gatew」· C语言 代码 · 共 1,018 行 · 第 1/2 页
C
1,018 行
panic(0, "Cannot start with SMSC connection failing"); list_append(smsc_list, conn); } */ list_add_producer(smsc_list); for (i = 0; i < list_len(smsc_groups) && (grp = list_get(smsc_groups, i)) != NULL; i++) { conn = smscconn_create(grp, 1); if (conn == NULL) panic(0, "Cannot start with SMSC connection failing"); list_append(smsc_list, conn); } list_remove_producer(smsc_list); if ((router_thread = gwthread_create(sms_router, NULL)) == -1) panic(0, "Failed to start a new thread for SMS routing"); list_add_producer(incoming_sms); smsc_running = 1; return 0;}/* * Find a matching smsc-id in the smsc list starting at position start. * NOTE: Caller must ensure that smsc_list is properly locked! */static long smsc2_find(Octstr *id, long start){ SMSCConn *conn = NULL; long i; if (start > list_len(smsc_list) || start < 0) return -1; for (i = start; i < list_len(smsc_list); i++) { conn = list_get(smsc_list, i); if (conn != NULL && octstr_compare(conn->id, id) == 0) { break; } } if (i >= list_len(smsc_list)) i = -1; return i;}int smsc2_stop_smsc(Octstr *id){ SMSCConn *conn; long i = -1; if (!smsc_running) return -1; gw_rwlock_rdlock(&smsc_list_lock); /* find the specific smsc via id */ while((i = smsc2_find(id, ++i)) != -1) { conn = list_get(smsc_list, i); if (conn != NULL && smscconn_status(conn) == SMSCCONN_DEAD) { info(0, "HTTP: Could not shutdown already dead smsc-id `%s'", octstr_get_cstr(id)); } else { info(0,"HTTP: Shutting down smsc-id `%s'", octstr_get_cstr(id)); smscconn_shutdown(conn, 1); /* shutdown the smsc */ } } gw_rwlock_unlock(&smsc_list_lock); return 0;}int smsc2_restart_smsc(Octstr *id){ CfgGroup *grp; SMSCConn *conn, *new_conn; Octstr *smscid = NULL; long i = -1; int num = 0; if (!smsc_running) return -1; gw_rwlock_wrlock(&smsc_list_lock); /* find the specific smsc via id */ while((i = smsc2_find(id, ++i)) != -1) { int hit; long group_index; /* check if smsc has online status already */ conn = list_get(smsc_list, i); if (conn != NULL && smscconn_status(conn) != SMSCCONN_DEAD) { warning(0, "HTTP: Could not re-start already running smsc-id `%s'", octstr_get_cstr(id)); continue; } /* find the group with equal smsc id */ hit = 0; grp = NULL; for (group_index = 0; group_index < list_len(smsc_groups) && (grp = list_get(smsc_groups, group_index)) != NULL; group_index++) { smscid = cfg_get(grp, octstr_imm("smsc-id")); if (smscid != NULL && octstr_compare(smscid, id) == 0) { if (hit == num) break; else hit++; } octstr_destroy(smscid); smscid = NULL; } octstr_destroy(smscid); if (hit != num) { /* config group not found */ error(0, "HTTP: Could not find config for smsc-id `%s'", octstr_get_cstr(id)); break; } info(0,"HTTP: Re-starting smsc-id `%s'", octstr_get_cstr(id)); new_conn = smscconn_create(grp, 1); if (new_conn == NULL) { error(0, "Start of SMSC connection failed, smsc-id `%s'", octstr_get_cstr(id)); continue; /* keep old connection on the list */ } /* drop old connection from the active smsc list */ list_delete(smsc_list, i, 1); /* destroy the connection */ smscconn_destroy(conn); list_insert(smsc_list, i, new_conn); smscconn_start(new_conn); num++; } gw_rwlock_unlock(&smsc_list_lock); /* wake-up the router */ if (router_thread >= 0) gwthread_wakeup(router_thread); return 0;}void smsc2_resume(void){ SMSCConn *conn; long i; if (!smsc_running) return; gw_rwlock_rdlock(&smsc_list_lock); for (i = 0; i < list_len(smsc_list); i++) { conn = list_get(smsc_list, i); smscconn_start(conn); } gw_rwlock_unlock(&smsc_list_lock); if (router_thread >= 0) gwthread_wakeup(router_thread);}void smsc2_suspend(void){ SMSCConn *conn; long i; if (!smsc_running) return; gw_rwlock_rdlock(&smsc_list_lock); for (i = 0; i < list_len(smsc_list); i++) { conn = list_get(smsc_list, i); smscconn_stop(conn); } gw_rwlock_unlock(&smsc_list_lock);}int smsc2_shutdown(void){ SMSCConn *conn; long i; if (!smsc_running) return -1; /* Call shutdown for all SMSC Connections; they should * handle that they quit, by emptying queues and then dying off */ gw_rwlock_rdlock(&smsc_list_lock); for(i=0; i < list_len(smsc_list); i++) { conn = list_get(smsc_list, i); smscconn_shutdown(conn, 1); } gw_rwlock_unlock(&smsc_list_lock); if (router_thread >= 0) gwthread_wakeup(router_thread); /* start avalanche by calling shutdown */ /* XXX shouldn'w we be sure that all smsces have closed their * receive thingies? Is this guaranteed by setting bb_status * to shutdown before calling these? */ list_remove_producer(incoming_sms); return 0;}void smsc2_cleanup(void){ SMSCConn *conn; long i; if (!smsc_running) return; debug("smscconn", 0, "final clean-up for SMSCConn"); gw_rwlock_wrlock(&smsc_list_lock); for (i = 0; i < list_len(smsc_list); i++) { conn = list_get(smsc_list, i); smscconn_destroy(conn); } list_destroy(smsc_list, NULL); smsc_list = NULL; gw_rwlock_unlock(&smsc_list_lock); list_destroy(smsc_groups, NULL); octstr_destroy(unified_prefix); numhash_destroy(white_list); numhash_destroy(black_list); if (white_list_regex != NULL) gw_regex_destroy(white_list_regex); if (black_list_regex != NULL) gw_regex_destroy(black_list_regex); /* destroy msg split counter */ counter_destroy(split_msg_counter); gw_rwlock_destroy(&smsc_list_lock);}Octstr *smsc2_status(int status_type){ Octstr *tmp; char tmp3[64]; char *lb; long i; int para = 0; SMSCConn *conn; StatusInfo info; const Octstr *conn_id = NULL; const Octstr *conn_name = NULL; if ((lb = bb_status_linebreak(status_type)) == NULL) return octstr_create("Un-supported format"); if (status_type == BBSTATUS_HTML || status_type == BBSTATUS_WML) para = 1; if (!smsc_running) { if (status_type == BBSTATUS_XML) return octstr_create ("<smscs>\n\t<count>0</count>\n</smscs>"); else return octstr_format("%sNo SMSC connections%s\n\n", para ? "<p>" : "", para ? "</p>" : ""); } if (status_type != BBSTATUS_XML) tmp = octstr_format("%sSMSC connections:%s", para ? "<p>" : "", lb); else tmp = octstr_format("<smscs><count>%d</count>\n\t", list_len(smsc_list)); gw_rwlock_rdlock(&smsc_list_lock); for (i = 0; i < list_len(smsc_list); i++) { conn = list_get(smsc_list, i); if ((smscconn_info(conn, &info) == -1)) { /* * we do not delete SMSCs from the list * this way we can show in the status which links are dead */ continue; } conn_id = conn ? smscconn_id(conn) : octstr_imm("unknown"); conn_id = conn_id ? conn_id : octstr_imm("unknown"); conn_name = conn ? smscconn_name(conn) : octstr_imm("unknown"); if (status_type == BBSTATUS_HTML) { octstr_append_cstr(tmp, " <b>"); octstr_append(tmp, conn_id); octstr_append_cstr(tmp, "</b> "); } else if (status_type == BBSTATUS_TEXT) { octstr_append_cstr(tmp, " "); octstr_append(tmp, conn_id); octstr_append_cstr(tmp, " "); } if (status_type == BBSTATUS_XML) { octstr_append_cstr(tmp, "<smsc>\n\t\t<name>"); octstr_append(tmp, conn_name); octstr_append_cstr(tmp, "</name>\n\t\t"); octstr_append_cstr(tmp, "<id>"); octstr_append(tmp, conn_id); octstr_append_cstr(tmp, "</id>\n\t\t"); } else octstr_append(tmp, conn_name); switch (info.status) { case SMSCCONN_ACTIVE: case SMSCCONN_ACTIVE_RECV: sprintf(tmp3, "online %lds", info.online); break; case SMSCCONN_DISCONNECTED: sprintf(tmp3, "disconnected"); break; case SMSCCONN_CONNECTING: sprintf(tmp3, "connecting"); break; case SMSCCONN_RECONNECTING: sprintf(tmp3, "re-connecting"); break; case SMSCCONN_DEAD: sprintf(tmp3, "dead"); break; default: sprintf(tmp3, "unknown"); } if (status_type == BBSTATUS_XML) octstr_format_append(tmp, "<status>%s</status>\n\t\t<received>%ld</received>" "\n\t\t<sent>%ld</sent>\n\t\t<failed>%ld</failed>\n\t\t" "<queued>%ld</queued>\n\t</smsc>\n", tmp3, info.received, info.sent, info.failed, info.queued); else octstr_format_append(tmp, " (%s, rcvd %ld, sent %ld, failed %ld, " "queued %ld msgs)%s", tmp3, info.received, info.sent, info.failed, info.queued, lb); } gw_rwlock_unlock(&smsc_list_lock); if (para) octstr_append_cstr(tmp, "</p>"); if (status_type == BBSTATUS_XML) octstr_append_cstr(tmp, "</smscs>\n"); else octstr_append_cstr(tmp, "\n\n"); return tmp;}/* function to route outgoing SMS'es * * If finds a good one, puts into it and returns 1 * If finds only bad ones, but acceptable, queues and * returns 0 (like all acceptable currently disconnected) * If cannot find nothing at all, returns -1 and * message is NOT destroyed (otherwise it is) */int smsc2_rout(Msg *msg){ StatusInfo info; SMSCConn *conn, *best_preferred, *best_ok; long bp_load, bo_load; int i, s, ret, bad_found; char *uf; bp_load = bo_load = 0; /* XXX handle ack here? */ if (msg_type(msg) != sms) return -1; /* unify prefix of receiver, in case of it has not been * already done */ uf = unified_prefix ? octstr_get_cstr(unified_prefix) : NULL; normalize_number(uf, &(msg->sms.receiver)); /* select in which list to add this * start - from random SMSCConn, as they are all 'equal' */ gw_rwlock_rdlock(&smsc_list_lock); if (list_len(smsc_list) == 0) { warning(0, "No SMSCes to receive message"); gw_rwlock_unlock(&smsc_list_lock); return SMSCCONN_FAILED_DISCARDED; } s = gw_rand() % list_len(smsc_list); best_preferred = best_ok = NULL; bad_found = 0; conn = NULL; for (i=0; i < list_len(smsc_list); i++) { conn = list_get(smsc_list, (i+s) % list_len(smsc_list)); ret = smscconn_usable(conn,msg); if (ret == -1) continue; /* if we already have a preferred one, skip non-preferred */ if (ret != 1 && best_preferred) continue; smscconn_info(conn, &info); /* If connection is not currently answering... */ if (info.status != SMSCCONN_ACTIVE) { bad_found = 1; continue; } if (ret == 1) { /* preferred */ if (best_preferred == NULL || info.load < bp_load) { best_preferred = conn; bp_load = info.load; continue; } } if (best_ok == NULL || info.load < bo_load) { best_ok = conn; bo_load = info.load; } } if (best_preferred) ret = smscconn_send(best_preferred, msg); else if (best_ok) ret = smscconn_send(best_ok, msg); else if (bad_found) { if (bb_status != BB_SHUTDOWN) list_produce(outgoing_sms, msg); gw_rwlock_unlock(&smsc_list_lock); return 0; } else { gw_rwlock_unlock(&smsc_list_lock); if (bb_status == BB_SHUTDOWN) return 0; warning(0, "Cannot find SMSCConn for message to <%s>, rejected.", octstr_get_cstr(msg->sms.receiver)); return -1; } gw_rwlock_unlock(&smsc_list_lock); /* check the status of sending operation */ if (ret == -1) return (smsc2_rout(msg)); /* re-try */ msg_destroy(msg); return 1;}/* * Try to reroute to another smsc. * @return -1 if no rerouting info available; otherwise return code from smsc2_route. */static long route_incoming_to_smsc(SMSCConn *conn, Msg *msg){ Octstr *smsc; /* sanity check */ if (!conn || !msg) return -1; /* check for dlr rerouting */ if (!conn->reroute_dlr && (msg->sms.sms_type == report_mo || msg->sms.sms_type == report_mt)) return -1; /* * Check if we have any "reroute" rules to obey. Which means msg gets * transported internally from MO to MT msg. */ if (conn->reroute) { /* change message direction */ store_save_ack(msg, ack_success); msg->sms.sms_type = mt_push; store_save(msg); /* drop into outbound queue again for routing */ return smsc2_rout(msg); } if (conn->reroute_to_smsc) { /* change message direction */ store_save_ack(msg, ack_success); msg->sms.sms_type = mt_push; store_save(msg); /* apply directly to the given smsc-id for MT traffic */ octstr_destroy(msg->sms.smsc_id); msg->sms.smsc_id = octstr_duplicate(conn->reroute_to_smsc); return smsc2_rout(msg); } if (conn->reroute_by_receiver && msg->sms.receiver && (smsc = dict_get(conn->reroute_by_receiver, msg->sms.receiver))) { /* change message direction */ store_save_ack(msg, ack_success); msg->sms.sms_type = mt_push; store_save(msg); /* route by receiver number */ /* XXX implement wildcard matching too! */ octstr_destroy(msg->sms.smsc_id); msg->sms.smsc_id = octstr_duplicate(smsc); return smsc2_rout(msg); } return -1; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?