⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smsc_at.c

📁 主要包括sms网关和wap网关实现说明和源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    * 3 seconds (default timeout of send_modem_command()) is not enough with some    * modems if the message is large, so we'll give it 7 seconds     */    if (at2_send_modem_command(privdata, cmd, 7, 0) != 0) {          /*          * failed to delete the message, we'll just ignore it for now,          * this is bad, since if the message really didn't get deleted         * we'll see it next time around.          */                        error(2, "AT2[%s]: failed to delete message %d.",              octstr_get_cstr(privdata->name), message_number);    }    return 1;}/* * This function loops through the pending_incoming_messages queue for CMTI * notifications. * Every notification is parsed and the messages are read (and deleted) * accordingly.*/static void at2_read_pending_incoming_messages(PrivAT2data *privdata){    Octstr *current_storage = NULL;    if (privdata->modem->message_storage) {	    current_storage = octstr_duplicate(privdata->modem->message_storage);    }    while (gwlist_len(privdata->pending_incoming_messages) > 0) {        int pos;        long location;        Octstr *cmti_storage = NULL, *line = NULL;                line = gwlist_extract_first(privdata->pending_incoming_messages);        /* message memory starts after the first quote in the string */        if ((pos = octstr_search_char(line, '"', 0)) != -1) {            /* grab memory storage name */            int next_quote = octstr_search_char(line, '"', ++pos);            if (next_quote == -1) { /* no second qoute - this line must be broken somehow */                O_DESTROY(line);                continue;            }            /* store notification storage location for reference */            cmti_storage = octstr_copy(line, pos, next_quote - pos);        } else            /* reset pos for the next lookup which would start from the beginning if no memory             * location was found */            pos = 0;         /* if no message storage is set in configuration - set now */        if (!privdata->modem->message_storage && cmti_storage) {             info(2, "AT2[%s]: CMTI received, but no message-storage is set in confiuration."                 "setting now to <%s>", octstr_get_cstr(privdata->name), octstr_get_cstr(cmti_storage));            privdata->modem->message_storage = octstr_duplicate(cmti_storage);            current_storage = octstr_duplicate(cmti_storage);            at2_set_message_storage(privdata, cmti_storage);        }        /* find the message id from the line, which should appear after the first comma */        if ((pos = octstr_search_char(line, ',', pos)) == -1) { /* this CMTI notification is probably broken */            error(2, "AT2[%s]: failed to find memory location in CMTI notification",                  octstr_get_cstr(privdata->name));            O_DESTROY(line);            octstr_destroy(cmti_storage);            continue;        }        if ((pos = octstr_parse_long(&location, line, ++pos, 10)) == -1) {            /* there was an error parsing the message id. next! */            error(2, "AT2[%s]: error parsing memory location in CMTI notification",                  octstr_get_cstr(privdata->name));            O_DESTROY(line);            octstr_destroy(cmti_storage);            continue;        }        /* check if we need to change storage location before issuing the read command */        if (!current_storage || (octstr_compare(current_storage, cmti_storage) != 0)) {            octstr_destroy(current_storage);            current_storage = octstr_duplicate(cmti_storage);            at2_set_message_storage(privdata, cmti_storage);        }                if (!at2_read_delete_message(privdata, location)) {            error(1, "AT2[%s]: CMTI notification received, but no message found in memory!",                  octstr_get_cstr(privdata->name));        }                octstr_destroy(line);        octstr_destroy(cmti_storage);    }        /* set prefered message storage back to what configured */    if (current_storage && privdata->modem->message_storage         && (octstr_compare(privdata->modem->message_storage, current_storage) != 0))        at2_set_message_storage(privdata, privdata->modem->message_storage);    octstr_destroy(current_storage);}static int at2_read_sms_memory(PrivAT2data* privdata){    /* get memory status */    if (at2_check_sms_memory(privdata) == -1) {        debug("bb.smsc.at2", 0, "AT2[%s]: memory check error", octstr_get_cstr(privdata->name));        return -1;    }    if (privdata->sms_memory_usage) {        /*         * that is - greater then 0, meaning there are some messages to fetch         * now - I used to just loop over the first input_mem_sms_used locations,          * but it doesn't hold, since under load, messages may be received while          * we're in the loop, and get stored in locations towards the end of the list,          * thus creating 'holes' in the memory.          *          * There are two ways we can fix this :          *   (a) Just read the last message location, delete it and return.         *       It's not a complete solution since holes can still be created if messages          *       are received between the memory check and the delete command,          *       and anyway - it will slow us down and won't hold well under pressure         *   (b) Just scan the entire memory each call, bottom to top.          *       This will be slow too, but it'll be reliable.         *         * We can massivly improve performance by stopping after input_mem_sms_used messages         * have been read, but send_modem_command returns 0 for no message as well as for a          * message read, and the only other way to implement it is by doing memory_check          * after each read and stoping when input_mem_sms_used get to 0. This is slow          * (modem commands take time) so we improve speed only if there are less then 10          * messages in memory.         *         * I implemented the alternative - changed at2_wait_modem_command to return the          * number of messages it collected.         */        int i;        int message_count = 0; /* cound number of messages collected */        debug("bb.smsc.at2", 0, "AT2[%s]: %d messages waiting in memory",               octstr_get_cstr(privdata->name), privdata->sms_memory_usage);        /*         * loop till end of memory or collected enouch messages         */        for (i = 1; i <= privdata->sms_memory_capacity &&             message_count < privdata->sms_memory_usage; ++i) {             /* if (meanwhile) there are pending CMTI notifications, process these first             * to not let CMTI and sim buffering sit in each others way */            while (gwlist_len(privdata->pending_incoming_messages) > 0) {                at2_read_pending_incoming_messages(privdata);            }            /* read the message and delete it */            message_count += at2_read_delete_message(privdata, i);        }    }        /*    at2_send_modem_command(privdata, ModemTypes[privdata->modemid].init1, 0, 0);    */    return 0;}static int at2_check_sms_memory(PrivAT2data *privdata){    long values[4]; /* array to put response data in */    int pos; /* position of parser in data stream */    int ret;    Octstr *search_cpms = NULL;    /* select memory type and get report */    if ((ret = at2_send_modem_command(privdata, "AT+CPMS?", 0, 0)) != 0) {         debug("bb.smsc.at2.memory_check", 0, "failed to send mem select command to modem %d", ret);        return -1;    }    search_cpms = octstr_create("+CPMS:");    if ((pos = octstr_search(privdata->lines, search_cpms, 0)) != -1) {        /* got back a +CPMS response */        int index = 0; /* index in values array */        pos += 6; /* position of parser in the stream - start after header */        /* skip memory indication */        pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1;         /* find all the values */        while (index < 4 && pos < octstr_len(privdata->lines) &&               (pos = octstr_parse_long(&values[index], privdata->lines, pos, 10)) != -1) {             ++pos; /* skip number seperator */            ++index; /* increment array index */            if (index == 2)                /* skip second memory indication */                pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1;         }        if (index < 4) {             /* didn't get all memory data - I don't why, so I'll bail */            debug("bb.smsc.at2", 0, "AT2[%s]: couldn't parse all memory locations : %d:'%s'.",                  octstr_get_cstr(privdata->name), index,                   &(octstr_get_cstr(privdata->lines)[pos]));            O_DESTROY(search_cpms);            return -1;        }        privdata->sms_memory_usage = values[0];        privdata->sms_memory_capacity = values[1];        /*        privdata->output_mem_sms_used = values[2];        privdata->output_mem_sms_capacity = values[3];        */        /* everything's cool */        ret = 0;         /*  clear the buffer */        O_DESTROY(privdata->lines);    } else {        debug("bb.smsc.at2", 0, "AT2[%s]: no correct header for CPMS response.",               octstr_get_cstr(privdata->name));        /* didn't get a +CPMS response - this is clearly an error */        ret = -1;     }    O_DESTROY(search_cpms);    return ret;}static void at2_set_speed(PrivAT2data *privdata, int bps){    struct termios tios;    int ret;    int	speed;    if (!privdata->is_serial)        return;    tcgetattr(privdata->fd, &tios);    switch (bps) {        case 300:            speed = B300;            break;        case 1200:            speed = B1200;            break;        case 2400:            speed = B2400;            break;        case 4800:            speed = B4800;            break;        case 9600:            speed = B9600;            break;        case 19200:            speed = B19200;            break;        case 38400:            speed = B38400;            break;#ifdef B57600        case 57600:            speed = B57600;            break;#endif#ifdef B115200        case 115200:            speed = B115200;            break;#endif        default:            speed = B9600;    }        cfsetospeed(&tios, speed);    cfsetispeed(&tios, speed);    ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */    if (ret == -1) {        error(errno, "AT2[%s]: at_data_link: fail to set termios attribute",              octstr_get_cstr(privdata->name));    }    tcflush(privdata->fd, TCIOFLUSH);    info(0, "AT2[%s]: speed set to %d", octstr_get_cstr(privdata->name), bps);}static void at2_device_thread(void *arg){    SMSCConn *conn = arg;    PrivAT2data	*privdata = conn->data;    int l, reconnecting = 0, error_count = 0;    long idle_timeout, memory_poll_timeout = 0;    conn->status = SMSCCONN_CONNECTING;    /* Make sure we log into our own log-file if defined */    log_thread_to(conn->log_idx);reconnect:    do {        if (reconnecting) {            if (conn->status == SMSCCONN_ACTIVE) {                mutex_lock(conn->flow_mutex);                conn->status = SMSCCONN_RECONNECTING;                mutex_unlock(conn->flow_mutex);            }            error(0, "AT2[%s]: Couldn't connect (retrying in %ld seconds).",                     octstr_get_cstr(privdata->name), conn->reconnect_delay);            gwthread_sleep(conn->reconnect_delay);        }        /* If modems->speed is defined, try to use it, else autodetect */        if (privdata->speed == 0 && privdata->modem != NULL && privdata->modem->speed != 0) {            info(0, "AT2[%s]: trying to use speed <%ld> from modem definition",                 octstr_get_cstr(privdata->name), privdata->modem->speed);            if (at2_test_speed(privdata, privdata->modem->speed) == 0) {                 privdata->speed = privdata->modem->speed;            	info(0, "AT2[%s]: speed is %ld",                      octstr_get_cstr(privdata->name), privdata->speed);            } else {                info(0, "AT2[%s]: speed in modem definition don't work, will autodetect",                      octstr_get_cstr(privdata->name));            }        }        if (privdata->speed == 0 && at2_detect_speed(privdata) == -1) {            continue;        }        if (privdata->modem == NULL && at2_detect_modem_type(privdata) == -1) {            continue;        }        if (at2_open_device(privdata)) {            error(errno, "AT2[%s]: at2_device_thread: open_at2_device failed. Terminating",                   octstr_get_cstr(privdata->name));            continue;        }        if (privdata->max_error_count > 0 && error_count > privdata->max_error_count             && privdata->modem != NULL && privdata->modem->reset_string != NULL) {            error_count = 0;            if (at2_send_modem_command(privdata,                 octstr_get_cstr(privdata->modem->reset_string), 0, 0) != 0) {                error(0, "AT2[%s]: Reset of modem failed.", octstr_get_cstr(privdata->name));                at2_close_device(privdata);                continue;            } else {                info(0, "AT2[%s]: Modem reseted.", octstr_get_cstr(privdata->name));            }        }        if (at2_init_device(privdata) != 0) {            error(0, "AT2[%s]: Opening failed. Terminating", octstr_get_cstr(privdata->name));            at2_close_device(privdata);            error_count++;            continue;        } else            error_count = 0;        /* If we got here, then the device is opened */        break;    } while (!privdata->shutdown);    mutex_lock(conn->flow_mutex);    conn->status = SMSCCONN_ACTIVE;    conn->connect_time = time(NULL);    mutex_unlock(conn->flow_mutex);    bb_smscconn_connected(conn);    idle_timeout = 0;    while (!privdata->shutdown) {        l = gw_prioqueue_len(privdata->outgoing_queue);        if (l > 0) {            at2_send_messages(privdata);            idle_timeout = time(NULL);        } else            at2_wait_modem_command(privdata, 1, 0, NULL);        while (gwlist_len(privdata->pending_incoming_messages) > 0) {            at2_read_pending_incoming_messages(privdata);        }        if (privdata->keepalive &&            idle_timeout + privdata->keepalive < time(NULL)) {            if (at2_send_modem_command(privdata,                 octstr_get_cstr(privdata->modem->keepalive_cmd), 5, 0) < 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -