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, "&nbsp;&nbsp;&nbsp;&nbsp;<b>");            octstr_append(tmp, conn_id);            octstr_append_cstr(tmp, "</b>&nbsp;&nbsp;&nbsp;&nbsp;");        } 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 + -
显示快捷键?