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

📄 smsc_cimd2.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 5 页
字号:
                                dlen - negative, gw_isdigit)) {            warning(0, "CIMD2[%s]: packet has '%s' parameter with non-integer contents",                     octstr_get_cstr(conn->id),                    parameters[i].name);            errors++;        }        if (octstr_parse_long(&value, data, dpos, 10) >= 0 &&            (value < parameters[i].minval || value > parameters[i].maxval)) {            warning(0, "CIMD2[%s]: packet has '%s' parameter out of range (value %ld, min %d, max %d)",                    octstr_get_cstr(conn->id),                    parameters[i].name, value,                    parameters[i].minval, parameters[i].maxval);            errors++;        }        break;    case P_TIME:        if (!octstr_check_range(data, dpos, dlen, gw_isdigit)) {            warning(0, "CIMD2[%s]: packet has '%s' parameter with non-digit contents",                     octstr_get_cstr(conn->id),                    parameters[i].name);            errors++;        }        break;    case P_ADDRESS:        if (!octstr_check_range(data, dpos, dlen, isphonedigit)) {            warning(0, "CIMD2[%s]: packet has '%s' parameter with non phone number contents",                     octstr_get_cstr(conn->id),                    parameters[i].name);            errors++;        }        break;    case P_HEX:        if (!octstr_check_range(data, dpos, dlen, gw_isxdigit)) {            warning(0, "CIMD2[%s]: packet has '%s' parameter with non-hex contents",                     octstr_get_cstr(conn->id),                    parameters[i].name);            errors++;        }        if (dlen % 2 != 0) {            warning(0, "CIMD2[%s]: packet has odd-length '%s' parameter",                     octstr_get_cstr(conn->id),                    parameters[i].name);            errors++;        }        break;    case P_SMS:    case P_STRING:  /* nothing to check */        break;    }    if (errors > 0)        return -1;    return 0;}/* Check the packet against the CIMD 2 spec, generating log entries as * necessary. Return -1 if anything was wrong, otherwise 0. *//* TODO: Check if parameters found actually belong in the packet type */static int packet_check(struct packet *packet, SMSCConn *conn){    int errors = 0;    long pos, len, next;    Octstr *data;    gw_assert(packet != NULL);    data = packet->data;    if (octstr_search_char(data, 0, 0) >= 0) {        /* CIMD2 spec does not allow NUL bytes in a packet */        warning(0, "CIMD2[%s]: packet contains NULs",                octstr_get_cstr(conn->id));        errors++;    }    /* Assume the packet starts with STX and ends with ETX,     * because we parsed it that way in the first place. */    errors += (packet_check_header(packet,conn) < 0);    /* Parameters are separated by tabs.  After the last parameter     * there is a tab, an optional two-digit checksum, and the ETX.     * Check each parameter in turn, by skipping from tab to tab.     */    len = octstr_len(data);    /* Start at the first tab, wherever it is, so that we can still     * check parameters if the header was weird. */    pos = octstr_search_char(data, TAB, 0);    for ( ; pos >= 0; pos = next) {        next = octstr_search_char(data, TAB, pos + 1);        if (next >= 0) {            errors += (packet_check_parameter(packet, pos, next - pos, conn) < 0);        } else {            /* Check if the checksum has the right format.  Don't             * check the sum itself here, that will be done in a             * separate call later. */            /* There are two valid formats: TAB ETX (no checksum)             * and TAB digit digit ETX.  We already know the TAB             * and the ETX are there. */            if (!(octstr_len(data) - pos == 2 ||                  (octstr_len(data) - pos == 4 &&                   octstr_check_range(data, pos + 1, 2, gw_isxdigit)))) {                warning(0, "CIMD2[%s]: packet checksum in wrong format",                        octstr_get_cstr(conn->id));                errors++;            }        }    }    if (errors > 0) {        octstr_dump(packet->data, 0);        return -1;    }    return 0;}static void packet_check_can_receive(struct packet *packet, SMSCConn *conn){    gw_assert(packet != NULL);    if (!operation_can_receive(packet->operation)) {        Octstr *name = operation_name(packet->operation);        warning(0, "CIMD2[%s]: SMSC sent us %s request",                octstr_get_cstr(conn->id),                octstr_get_cstr(name));        octstr_destroy(name);    }}/* Table of known error codes */static struct{    int code;    unsigned char *text;}cimd2_errors[] = {    { 0, "No error" },    { 1, "Unexpected operation" },    { 2, "Syntax error" },    { 3, "Unsupported parameter error" },    { 4, "Connection to message center lost" },    { 5, "No response from message center" },    { 6, "General system error" },    { 7, "Cannot find information" },    { 8, "Parameter formatting error" },    { 9, "Requested operation failed" },    /* LOGIN error codes */    { 100, "Invalid login" },    { 101, "Incorrect access type" },    { 102, "Too many users with this login id" },    { 103, "Login refused by message center" },    /* SUBMIT MESSAGE error codes */    { 300, "Incorrect destination address" },    { 301, "Incorrect number of destination addresses" },    { 302, "Syntax error in user data parameter" },    { 303, "Incorrect bin/head/normal user data parameter combination" },    { 304, "Incorrect data coding scheme parameter usage" },    { 305, "Incorrect validity period parameters usage" },    { 306, "Incorrect originator address usage" },    { 307, "Incorrect pid paramterer usage" },    { 308, "Incorrect first delivery parameter usage" },    { 309, "Incorrect reply path usage" },    { 310, "Incorrect status report request parameter usage" },    { 311, "Incorrect cancel enabled parameter usage" },    { 312, "Incorrect priority parameter usage" },    { 313, "Incorrect tariff class parameter usage" },    { 314, "Incorrect service description parameter usage" },    { 315, "Incorrect transport type parameter usage" },    { 316, "Incorrect message type parameter usage" },    { 318, "Incorrect mms parameter usage" },    { 319, "Incorrect operation timer parameter usage" },    /* ENQUIRE MESSAGE STATUS error codes */    { 400, "Incorrect address parameter usage" },    { 401, "Incorrect scts parameter usage" },    /* DELIVERY REQUEST error codes */    { 500, "Incorrect scts parameter usage" },    { 501, "Incorrect mode parameter usage" },    { 502, "Incorrect parameter combination" },    /* CANCEL MESSAGE error codes */    { 600, "Incorrect scts parameter usage" },    { 601, "Incorrect address parameter usage" },    { 602, "Incorrect mode parameter usage" },    { 603, "Incorrect parameter combination" },    /* SET error codes */    { 800, "Changing password failed" },    { 801, "Changing password not allowed" },    /* GET error codes */    { 900, "Unsupported item requested" },    { -1, NULL }};static int packet_display_error(struct packet *packet, SMSCConn *conn){    int code;    Octstr *text = NULL;    Octstr *opname = NULL;    code = packet_get_int_parm(packet, P_ERROR_CODE);    text = packet_get_string_parm(packet, P_ERROR_TEXT);    if (code <= 0) {        octstr_destroy(text);        return 0;    }    if (text == NULL) {        /* No error text.  Try to find it in the table. */        int i;        for (i = 0; cimd2_errors[i].text != NULL; i++) {            if (cimd2_errors[i].code == code) {                text = octstr_create(cimd2_errors[i].text);                break;            }        }    }    if (text == NULL) {        /* Still no error text.  Make one up. */        text = octstr_create("Unknown error");    }    opname = operation_name(packet->operation);    error(0, "CIMD2[%s]: %s contained error message:",          octstr_get_cstr(conn->id),          octstr_get_cstr(opname));    error(0, "code %03d: %s", code, octstr_get_cstr(text));    octstr_destroy(opname);    octstr_destroy(text);    return code;}/* Table of special combinations, for convert_gsm_to_latin1. *//* Each cimd1, cimd2 pair is mapped to a character in the GSM default * character set. */static const struct{    unsigned char cimd1, cimd2;    unsigned char gsm;}cimd_combinations[] = {    { 'O', 'a', 0 },     /* @ */    { 'L', '-', 1 },     /* Pounds sterling */    { 'Y', '-', 3 },     /* Yen */    { 'e', '`', 4 },     /* egrave */    { 'e', '\'', 5 },    /* eacute */    { 'u', '`', 6 },     /* ugrave */    { 'i', '`', 7 },     /* igrave */    { 'o', '`', 8 },     /* ograve */    { 'C', ',', 9 },     /* C cedilla */    { 'O', '/', 11 },    /* Oslash */    { 'o', '/', 12 },    /* oslash */    { 'A', '*', 14 },    /* Aring */    { 'a', '*', 15 },    /* aring */    { 'g', 'd', 16 },    /* greek delta */    { '-', '-', 17 },    /* underscore */    { 'g', 'f', 18 },    /* greek phi */    { 'g', 'g', 19 },    /* greek gamma */    { 'g', 'l', 20 },    /* greek lambda */    { 'g', 'o', 21 },    /* greek omega */    { 'g', 'p', 22 },    /* greek pi */    { 'g', 'i', 23 },    /* greek psi */    { 'g', 's', 24 },    /* greek sigma */    { 'g', 't', 25 },    /* greek theta */    { 'g', 'x', 26 },    /* greek xi */    { 'X', 'X', 27 },    /* escape */    { 'A', 'E', 28 },    /* AE ligature */    { 'a', 'e', 29 },    /* ae ligature */    { 's', 's', 30 },    /* german double s */    { 'E', '\'', 31 },   /* Eacute */    { 'q', 'q', '"' },    { 'o', 'x', 36 },    /* international currency symbol */    { '!', '!', 64 },    /* inverted ! */    { 'A', '"', 91 },    /* Adieresis */    { 'O', '"', 92 },    /* Odieresis */    { 'N', '~', 93 },    /* N tilde */    { 'U', '"', 94 },    /* Udieresis */    { 's', 'o', 95 },    /* section mark */    { '?', '?', 96 },    /* inverted ? */    { 'a', '"', 123 },   /* adieresis */    { 'o', '"', 124 },   /* odieresis */    { 'n', '~', 125 },   /* n tilde */    { 'u', '"', 126 },   /* udieresis */    { 'a', '`', 127 },   /* agrave */    { 0, 0, 0 }};/* Convert text in the CIMD2 User Data format to the GSM default * character set. * CIMD2 allows 8-bit characters in this format; they map directly * to the corresponding ISO-8859-1 characters.  Since we are heading * toward that character set in the end, we don't bother converting * those to GSM. */static void convert_cimd2_to_gsm(Octstr *text, SMSCConn *conn){    long pos, len;    int cimd1, cimd2;    int c;    int i;    /* CIMD2 uses four single-character mappings that do not map     * to themselves:     * '@' from 64 to 0, '$' from 36 to 2, ']' from 93 to 14 (A-ring),     * and '}' from 125 to 15 (a-ring).     * Other than those, we only have to worry about the escape     * sequences introduced by _ (underscore).     */    len = octstr_len(text);    for (pos = 0; pos < len; pos++) {        c = octstr_get_char(text, pos);        if (c == '@')            octstr_set_char(text, pos, 0);        else if (c == '$')            octstr_set_char(text, pos, 2);        else if (c == ']')            octstr_set_char(text, pos, 14);        else if (c == '}')            octstr_set_char(text, pos, 15);        else if (c == '_' && pos + 2 < len) {            cimd1 = octstr_get_char(text, pos + 1);            cimd2 = octstr_get_char(text, pos + 2);            for (i = 0; cimd_combinations[i].cimd1 != 0; i++) {                if (cimd_combinations[i].cimd1 == cimd1 &&                    cimd_combinations[i].cimd2 == cimd2)                    break;            }            if (cimd_combinations[i].cimd1 == 0)                warning(0, "CIMD2[%s]: Encountered unknown "                        "escape code _%c%c, ignoring.",                        octstr_get_cstr(conn->id),                        cimd1, cimd2);            else {                octstr_delete(text, pos, 2);                octstr_set_char(text, pos, cimd_combinations[i].gsm);                len = octstr_len(text);            }        }    }}/* Convert text in the GSM default character set to the CIMD2 User Data * format, which is a representation of the GSM default character set * in the lower 7 bits of ISO-8859-1.  (8-bit characters are also * allowed, but it's just as easy not to use them.) */static void convert_gsm_to_cimd2(Octstr *text){    long pos, len;    len = octstr_len(text);    for (pos = 0; pos < len; pos++) {        int c, i;        c = octstr_get_char(text, pos);        /* If c is not in the GSM alphabet at this point,         * the caller did something badly wrong. */        gw_assert(c >= 0);        gw_assert(c < 128);        for (i = 0; cimd_combinations[i].cimd1 != 0; i++) {            if (cimd_combinations[i].gsm == c)                break;        }        if (cimd_combinations[i].gsm == c) {            /* Escape sequence */            octstr_insert_data(text, pos, "_ ", 2);            pos += 2;            len += 2;            octstr_set_char(text, pos - 1, cimd_combinations[i].cimd1);            octstr_set_char(text, pos, cimd_combinations[i].cimd2);        } else if (c == 2) {            /* The dollar sign is the only GSM character that            	 * does not have a CIMD escape sequence and does not             * map to itself. */            octstr_set_char(text, pos, '$');        }    }}/***************************************************************************//* Packet encoding functions.  They do not allow the creation of invalid   *//* CIMD 2 packets.                                                         *//***************************************************************************//* Build a new packet struct with this operation code and sequence number. */static struct packet *packet_create(int operation, int seq){    struct packet *packet;

⌨️ 快捷键说明

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