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

📄 smsc_at2.c

📁 gnu的专业网关smpp协议支持源代码。
💻 C
📖 第 1 页 / 共 5 页
字号:
	    break;            /* Add other message types here: */    }    return msg;}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);    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));    }    /* 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)) ;    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 */    len = octstr_get_char(pdu, pos);    pos++;    /* if there is a UDH */    udhlen = 0;    if (udhi) {        udhlen = octstr_get_char(pdu, pos);        pos++;        udh = octstr_copy(pdu, pos, udhlen);        pos += udhlen;        len -= udhlen + 1;    }    /* 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 *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(octstr_get_cstr(privdata->conn->id),	    octstr_get_cstr(msg_id), octstr_get_cstr(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;}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;}int at2_rmask[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };int at2_lmask[8] = { 0, 128, 192, 224, 240, 248, 252, 254 };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);}void at2_send_messages(PrivAT2data *privdata){    Msg *msg;    do {        if (privdata->modem->enable_mms && 			list_len(privdata->outgoing_queue) > 1)            at2_send_modem_command(privdata, "AT+CMMS=2", 0, 0);        if ((msg = list_extract_first(privdata->outgoing_queue)))            at2_send_one_message(privdata, msg);    } while (msg);}void at2_send_one_message(PrivAT2data *privdata, Msg *msg){    unsigned char command[500];    int ret = -1;    char sc[3];    int retries = RETRY_SEND;    if (octstr_len(privdata->my_number)) {        octstr_destroy(msg->sms.sender);        msg->sms.sender = octstr_duplicate(privdata->my_number);    }    /*      * The standard says you should be prepending the PDU with 00 to indicate      * to use the default SC. Some older modems dont expect this so it can be      * disabled      * NB: This extra padding is not counted in the CMGS byte count      */    sc[0] = '\0';    if (!privdata->modem->no_smsc)        strcpy(sc, "00");    if (msg_type(msg) == sms) {	Octstr* pdu;	if ((pdu = at2_pdu_encode(msg, privdata)) == NULL) {	    error(2, "AT2[%s]: Error encoding PDU!",octstr_get_cstr(privdata->name));	    return;	}	        ret = -99;        retries = RETRY_SEND;        while ((ret != 0) && (retries-- > 0)) {	    int msg_id = -1;            /*              * send the initial command and then wait for >              */            sprintf(command, "AT+CMGS=%ld", octstr_len(pdu) / 2);                        ret = at2_send_modem_command(privdata, command, 5, 1);            debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",                  octstr_get_cstr(privdata->name), ret);            if (ret != 1) /* > only! */                continue;            /*              * ok the > has been see now so we can send the PDU now and a              * control Z but no CR or LF              */            sprintf(command, "%s%s", sc, octstr_get_cstr(pdu));            at2_write(privdata, command);            at2_write_ctrlz(privdata);

⌨️ 快捷键说明

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