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

📄 smsc_at.c

📁 主要包括sms网关和wap网关实现说明和源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    type = octstr_get_char(data, 1) & 3;    switch (type) {        case AT_DELIVER_SM:            msg = at2_pdu_decode_deliver_sm(data, privdata);            break;        case AT_STATUS_REPORT_SM:            msg = at2_pdu_decode_report_sm(data, privdata);            break;            /* Add other message types here: */    }    return msg;}static Msg *at2_pdu_decode_deliver_sm(Octstr *data, PrivAT2data *privdata){    int len, pos, i, ntype;    int udhi, dcs, udhlen, pid;    Octstr *origin = NULL;    Octstr *udh = NULL;    Octstr *text = NULL, *tmpstr;    Octstr *pdu = NULL;    Msg *message = NULL;    struct universaltime mtime; /* time structure */    long stime; /* time in seconds */    int timezone; /* timezone in 15 minutes jumps from GMT */    /*      * Note: some parts of the PDU are not decoded because they are     * not needed for the Msg type.      */    /* convert the pdu to binary format for ease of processing */    pdu = at2_convertpdu(data);    /* UDH Indicator */    udhi = (octstr_get_char(pdu, 0) & 64) >> 6;    /* originating address */    len = octstr_get_char(pdu, 1);    if (len > 20) /* maximum valid number of semi-octets in Address-Value field */        goto msg_error;    ntype = octstr_get_char(pdu, 2);    pos = 3;    if ((ntype & 0xD0) == 0xD0) {        /* Alphanumeric sender */        origin = octstr_create("");        tmpstr = octstr_copy(pdu, 3, len);        at2_decode7bituncompressed(tmpstr, (((len - 1) * 4 - 3) / 7) + 1, origin, 0);        octstr_destroy(tmpstr);        debug("bb.smsc.at2", 0, "AT2[%s]: Alphanumeric sender <%s>",               octstr_get_cstr(privdata->name), octstr_get_cstr(origin));        pos += (len + 1) / 2;    } else {        origin = octstr_create("");        if ((ntype & 0x90) == 0x90) {            /* International number */            octstr_append_char(origin, '+');        }        for (i = 0; i < len; i += 2, pos++) {            octstr_append_char(origin, (octstr_get_char(pdu, pos) & 15) + 48);            if (i + 1 < len)                octstr_append_char(origin, (octstr_get_char(pdu, pos) >> 4) + 48);        }        debug("bb.smsc.at2", 0, "AT2[%s]: Numeric sender %s <%s>",               octstr_get_cstr(privdata->name), ((ntype & 0x90) == 0x90 ? "(international)" : ""),               octstr_get_cstr(origin));    }    if (pos > octstr_len(pdu))        goto msg_error;    /* PID */    pid = octstr_get_char(pdu, pos);    pos++;    /* DCS */    dcs = octstr_get_char(pdu, pos);    pos++;    /* get the timestamp */    mtime.year = swap_nibbles(octstr_get_char(pdu, pos));    pos++;    mtime.year += (mtime.year < 70 ? 2000 : 1900);    mtime.month = swap_nibbles(octstr_get_char(pdu, pos));    mtime.month--;        pos++;    mtime.day = swap_nibbles(octstr_get_char(pdu, pos));    pos++;    mtime.hour = swap_nibbles(octstr_get_char(pdu, pos));    pos++;    mtime.minute = swap_nibbles(octstr_get_char(pdu, pos));    pos++;    mtime.second = swap_nibbles(octstr_get_char(pdu, pos));    pos++;    /*      * time zone:      *     * time zone is "swapped nibble", with the MSB as the sign (1 is negative).       */    timezone = swap_nibbles(octstr_get_char(pdu, pos));    pos++;    timezone = ((timezone >> 7) ? -1 : 1) * (timezone & 127);    /*      * Ok, that was the time zone as read from the PDU. Now how to interpert it?      * All the handsets I tested send the timestamp of their local time and the      * timezone as GMT+0. I assume that the timestamp is the handset's local time,      * so we need to apply the timezone in reverse to get GM time:      */    /*      * time in PDU is handset's local time and timezone is handset's time zone      * difference from GMT      */    mtime.hour -= timezone / 4;    mtime.minute -= 15 * (timezone % 4);    stime = date_convert_universal(&mtime);    /* get data length     * XXX: Is it allowed to have length = 0 ??? (alex)     */    len = octstr_get_char(pdu, pos);    pos++;    debug("bb.smsc.at2", 0, "AT2[%s]: User data length read as (%d)",           octstr_get_cstr(privdata->name), len);    /* if there is a UDH */    udhlen = 0;    if (udhi && len > 0) {        udhlen = octstr_get_char(pdu, pos);        pos++;        if (udhlen + 1 > len)            goto msg_error;        udh = octstr_copy(pdu, pos, udhlen);        pos += udhlen;        len -= udhlen + 1;    } else if (len <= 0) /* len < 0 is impossible, but sure is sure */        udhi = 0;    debug("bb.smsc.at2", 0, "AT2[%s]: Udh decoding done len=%d udhi=%d udhlen=%d udh='%s'",          octstr_get_cstr(privdata->name), len, udhi, udhlen, (udh ? octstr_get_cstr(udh) : ""));    if (pos > octstr_len(pdu) || len < 0)        goto msg_error;    /* build the message */    message = msg_create(sms);    if (!dcs_to_fields(&message, dcs)) {        /* XXX Should reject this message? */        debug("bb.smsc.at2", 0, "AT2[%s]: Invalid DCS", octstr_get_cstr(privdata->name));        dcs_to_fields(&message, 0);    }    message->sms.pid = pid;    /* deal with the user data -- 7 or 8 bit encoded */    tmpstr = octstr_copy(pdu, pos, len);    if (message->sms.coding == DC_8BIT || message->sms.coding == DC_UCS2) {        text = octstr_duplicate(tmpstr);    } else {        int offset = 0;        text = octstr_create("");        if (udhi && message->sms.coding == DC_7BIT) {            int nbits;            nbits = (udhlen + 1) * 8;            /* fill bits for UDH to septet boundary */            offset = (((nbits / 7) + 1) * 7 - nbits) % 7;             }        at2_decode7bituncompressed(tmpstr, len, text, offset);    }    message->sms.sender = origin;    if (octstr_len(privdata->my_number)) {        message->sms.receiver = octstr_duplicate(privdata->my_number);    } else {        /* Put a dummy address in the receiver for now (SMSC requires one) */        message->sms.receiver = octstr_create_from_data("1234", 4);    }    if (udhi) {        message->sms.udhdata = udh;    }    message->sms.msgdata = text;    message->sms.time = stime;    /* cleanup */    octstr_destroy(pdu);    octstr_destroy(tmpstr);    return message;    msg_error:    error(1, "AT2[%s]: Invalid DELIVER-SMS pdu!", octstr_get_cstr(privdata->name));    O_DESTROY(udh);    O_DESTROY(origin);    O_DESTROY(text);    O_DESTROY(pdu);    return NULL;}static Msg *at2_pdu_decode_report_sm(Octstr *data, PrivAT2data *privdata){    Msg *dlrmsg = NULL;    Octstr *pdu, *msg_id, *tmpstr = NULL, *receiver = NULL;    int type, tp_mr, len, ntype, pos;    /*     * parse the PDU.     */    /* convert the pdu to binary format for ease of processing */    pdu = at2_convertpdu(data);    /* Message reference */    tp_mr = octstr_get_char(pdu, 1);    msg_id = octstr_format("%d", tp_mr);    debug("bb.smsc.at2", 0, "AT2[%s]: got STATUS-REPORT for message <%d>:",           octstr_get_cstr(privdata->name), tp_mr);        /* reciver address */    len = octstr_get_char(pdu, 2);    ntype = octstr_get_char(pdu, 3);    pos = 4;    if ((ntype & 0xD0) == 0xD0) {        /* Alphanumeric sender */        receiver = octstr_create("");        tmpstr = octstr_copy(pdu, pos, (len + 1) / 2);        at2_decode7bituncompressed(tmpstr, (((len - 1) * 4 - 3) / 7) + 1, receiver, 0);        octstr_destroy(tmpstr);        debug("bb.smsc.at2", 0, "AT2[%s]: Alphanumeric receiver <%s>",              octstr_get_cstr(privdata->name), octstr_get_cstr(receiver));        pos += (len + 1) / 2;    } else {        int i;        receiver = octstr_create("");        if ((ntype & 0x90) == 0x90) {            /* International number */            octstr_append_char(receiver, '+');        }        for (i = 0; i < len; i += 2, pos++) {            octstr_append_char(receiver, (octstr_get_char(pdu, pos) & 15) + 48);            if (i + 1 < len)                octstr_append_char(receiver, (octstr_get_char(pdu, pos) >> 4) + 48);        }        debug("bb.smsc.at2", 0, "AT2[%s]: Numeric receiver %s <%s>",              octstr_get_cstr(privdata->name), ((ntype & 0x90) == 0x90 ? "(international)" : ""),              octstr_get_cstr(receiver));    }    pos += 14; /* skip time stamps for now */    if ((type = octstr_get_char(pdu, pos)) == -1 ) {        error(1, "AT2[%s]: STATUS-REPORT pdu too short to have TP-Status field !",              octstr_get_cstr(privdata->name));        goto error;    }	/* Check DLR type:	 * 3GPP TS 23.040 defines this a bit mapped field with lots of options	 * most of which are not really intersting to us, as we are only interested	 * in one of three conditions : failed, held in SC for delivery later, or delivered successfuly	 * and here's how I suggest to test it (read the 3GPP reference for further detailes) -	 * we'll test the 6th and 5th bits (7th bit when set making all other values 'reseved' so I want to test it).	 */    type = type & 0xE0; /* filter out everything but the 7th, 6th and 5th bits */    switch (type) {        case 0x00:            /* 0 0 : success class */            type = DLR_SUCCESS;            tmpstr = octstr_create("Success");            break;        case 0x20:            /* 0 1 : buffered class (temporary error) */            type = DLR_BUFFERED;            tmpstr = octstr_create("Buffered");            break;        case 0x40:        case 0x60:        default:            /* 1 0 : failed class */            /* 1 1 : failed class (actually, temporary error but timed out) */            /* and any other value (can't think of any) is considered failure */            type = DLR_FAIL;            tmpstr = octstr_create("Failed");            break;    }    /* Actually, the above implementation is not correct, as the reference      * says that implementations should consider any "reserved" values to be      * "failure", but most reserved values fall into one of the three      * categories. It will catch "reserved" values where the first 3 MSBits      * are not set as "Success" which may not be correct. */    if ((dlrmsg = dlr_find(privdata->conn->id, msg_id, receiver, type)) == NULL) {        debug("bb.smsc.at2", 1, "AT2[%s]: Received delivery notification but can't find that ID in the DLR storage",              octstr_get_cstr(privdata->name));	    goto error;    }    /* Beware DLR URL is now in msg->sms.dlr_url given by dlr_find() */    dlrmsg->sms.msgdata = octstr_duplicate(tmpstr);	error:    O_DESTROY(tmpstr);    O_DESTROY(pdu);    O_DESTROY(receiver);    O_DESTROY(msg_id);    return dlrmsg;}static Octstr *at2_convertpdu(Octstr *pdutext){    Octstr *pdu;    int i;    int len = octstr_len(pdutext);    pdu = octstr_create("");    for (i = 0; i < len; i += 2) {        octstr_append_char(pdu, at2_hexchar(octstr_get_char(pdutext, i)) * 16                           + at2_hexchar(octstr_get_char(pdutext, i + 1)));    }    return pdu;}static int at2_rmask[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };static int at2_lmask[8] = { 0, 128, 192, 224, 240, 248, 252, 254 };static void at2_decode7bituncompressed(Octstr *input, int len, Octstr *decoded, int offset){    unsigned char septet, octet, prevoctet;    int i;    int r = 1;    int c = 7;    int pos = 0;    /* Shift the buffer offset bits to the left */    if (offset > 0) {        unsigned char *ip;        for (i = 0, ip = octstr_get_cstr(input); i < octstr_len(input); i++) {            if (i == octstr_len(input) - 1)                *ip = *ip >> offset;            else                *ip = (*ip >> offset) | (*(ip + 1) << (8 - offset));            ip++;        }    }    octet = octstr_get_char(input, pos);    prevoctet = 0;    for (i = 0; i < len; i++) {        septet = ((octet & at2_rmask[c]) << (r - 1)) + prevoctet;        octstr_append_char(decoded, septet);        prevoctet = (octet & at2_lmask[r]) >> c;        /* When r=7 we have a full character in prevoctet */        if ((r == 7) && (i < len - 1)) {            i++;            octstr_append_char(decoded, prevoctet);            prevoctet = 0;        }        r = (r > 6) ? 1 : r + 1;        c = (c < 2) ? 7 : c - 1;        pos++;        octet = octstr_get_char(input, pos);    }    charset_gsm_to_latin1(decoded);}static void at2_send_messages(PrivAT2data *privdata){    Msg *msg;    do {        if (privdata->modem->enable_mms &&             gw_prioqueue_len(privdata->outgoing_queue) > 1)            at2_send_modem_command(privdata, "AT+CMMS=2", 0, 0);        if ((msg = gw_prioqueue_remove(privdata->outgoing_queue)))            at2_send_one_message(privdata, msg);    } while (msg);}static void at2_send_one_message(PrivAT2data *p

⌨️ 快捷键说明

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