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

📄 smsc_cimd2.c

📁 gnu的专业网关smpp协议支持源代码。
💻 C
📖 第 1 页 / 共 5 页
字号:
    packet->operation = number;    if (octstr_get_char(packet->data, pos++) != ':')        return;    pos = octstr_parse_long(&number, packet->data, pos, 10);    if (pos < 0)        return;    packet->seq = number;}/* Accept an Octstr containing one packet, build a struct packet around * it, and return that struct.  The Octstr is stored in the struct. * No error checking is done here yet. */static struct packet *packet_parse(Octstr *packet_data){    struct packet *packet;    packet = gw_malloc(sizeof(*packet));    packet->data = packet_data;    /* Fill in packet->operation and packet->seq */    packet_parse_header(packet);    return packet;}/* Deallocate this packet */static void packet_destroy(struct packet *packet){    if (packet != NULL) {        octstr_destroy(packet->data);        gw_free(packet);    }}/* Find the first packet in "in", delete it from "in", and return it as * a struct.  Return NULL if "in" contains no packet.  Always delete * leading non-packet data from "in".  (The CIMD 2 spec says we should * ignore any data between the packet markers). */static struct packet *packet_extract(Octstr *in){    int stx, etx;    Octstr *packet;    /* Find STX, and delete everything up to it */    stx = octstr_search_char(in, STX, 0);    if (stx < 0) {        octstr_delete(in, 0, octstr_len(in));        return NULL;    } else {        octstr_delete(in, 0, stx);    }    /* STX is now in position 0.  Find ETX. */    etx = octstr_search_char(in, ETX, 1);    if (etx < 0)        return NULL;    /* What shall we do with STX data... STX data... ETX?     * Either skip to the second STX, or assume an ETX marker before     * the STX.  Doing the latter has a chance of succeeding, and     * will at least allow good logging of the error. */    stx = octstr_search_char(in, STX, 1);    if (stx >= 0 && stx < etx) {        warning(0, "CIMD2: packet without end marker");        packet = octstr_copy(in, 0, stx);        octstr_delete(in, 0, stx);        octstr_append_cstr(packet, ETX_str);    } else {        /* Normal case. Copy packet, and cut it from the source. */        packet = octstr_copy(in, 0, etx + 1);        octstr_delete(in, 0, etx + 1);    }    return packet_parse(packet);}/* The get_parm functions always return the first parameter with the * correct id.  There is only one case where the spec allows multiple * parameters with the same id, and that is when an SMS has multiple * destination addresses.  We only support one destination address anyway. *//* Look for the first parameter with id 'parmno' and return its value. * Return NULL if the parameter was not found. */static Octstr *packet_get_parm(struct packet *packet, int parmno){    long pos, next;    long valuepos;    long number;    gw_assert(packet != NULL);    pos = octstr_search_char(packet->data, TAB, 0);    if (pos < 0)        return NULL;  /* Bad packet, nothing we can do */    /* Parameters have a tab on each end.  If we don't find the     * closing tab, we're at the checksum, so we stop. */    for ( ;          (next = octstr_search_char(packet->data, TAB, pos + 1)) >= 0;          pos = next) {        if (octstr_parse_long(&number, packet->data, pos + 1, 10) < 0)            continue;        if (number != parmno)            continue;        valuepos = octstr_search_char(packet->data, ':', pos + 1);        if (valuepos < 0)            continue;  /* badly formatted parm */        valuepos++;  /* skip the ':' */        /* Found the right parameter */        return octstr_copy(packet->data, valuepos, next - valuepos);    }    return NULL;}/* Look for an Integer parameter with id 'parmno' in the packet and * return its value.  Return INT_MIN if the parameter was not found. * (Unfortunately, -1 is a valid parameter value for at least one * parameter.) */static long packet_get_int_parm(struct packet *packet, int parmno){    Octstr *valuestr = NULL;    long value;    /* Our code should never even try a bad parameter access. */    gw_assert(parm_type(parmno) == P_INT);    valuestr = packet_get_parm(packet, parmno);    if (!valuestr)        goto error;    if (octstr_parse_long(&value, valuestr, 0, 10) < 0)        goto error;    octstr_destroy(valuestr);    return value;error:    octstr_destroy(valuestr);    return INT_MIN;}/* Look for a String parameter with id 'parmno' in the packet and * return its value.  Return NULL if the parameter was not found. * No translations are done on the value. */static Octstr *packet_get_string_parm(struct packet *packet, int parmno){    /* Our code should never even try a bad parameter access. */    gw_assert(parm_type(parmno) == P_STRING);    return packet_get_parm(packet, parmno);}/* Look for an Address parameter with id 'parmno' in the packet and * return its value.  Return NULL if the parameter was not found. * No translations are done on the value. */static Octstr *packet_get_address_parm(struct packet *packet, int parmno){    /* Our code should never even try a bad parameter access. */    gw_assert(parm_type(parmno) == P_ADDRESS);    return packet_get_parm(packet, parmno);}/* Look for an SMS parameter with id 'parmno' in the packet and return its * value.  Return NULL if the parameter was not found.  No translations * are done on the value, so it will be in the ISO-Latin-1 character set * with CIMD2-specific escapes. */static Octstr *packet_get_sms_parm(struct packet *packet, int parmno){    /* Our code should never even try a bad parameter access. */    gw_assert(parm_type(parmno) == P_SMS);    return packet_get_parm(packet, parmno);}/* There is no packet_get_time_parm because the CIMD 2 timestamp * format is useless.  It's in the local time of the MC, with * a 2-digit year and no DST information.  We can do without. *//* Look for a Hex parameter with id 'parmno' in the packet and return * its value.  Return NULL if the parameter was not found.  The value * is de-hexed. */static Octstr *packet_get_hex_parm(struct packet *packet, int parmno){    Octstr *value = NULL;    /* Our code should never even try a bad parameter access. */    gw_assert(parm_type(parmno) == P_HEX);    value = packet_get_parm(packet, parmno);    if (!value)        goto error;    if (octstr_hex_to_binary(value) < 0)        goto error;    return value;error:    octstr_destroy(value);    return NULL;}/* Check if the header is according to CIMD 2 spec, generating log * entries as necessary.  Return -1 if anything was wrong, otherwise 0. */static int packet_check_header(struct packet *packet){    Octstr *data;    gw_assert(packet != NULL);    data = packet->data;    /* The header must have a two-digit operation code, a colon,     * and a three-digit sequence number, followed by a tab.     * (CIMD2, 3.1) */    if (octstr_len(data) < 8 ||        !octstr_check_range(data, 1, 2, gw_isdigit) ||        octstr_get_char(data, 3) != ':' ||        !octstr_check_range(data, 4, 3, gw_isdigit) ||        octstr_get_char(data, 7) != TAB) {        warning(0, "CIMD2 packet header in wrong format");        return -1;    }    return 0;}static int packet_check_parameter(struct packet *packet, long pos, long len){    Octstr *data;    long parm;    long dpos, dlen;    int negative;    long value;    int i;    int errors = 0;    gw_assert(packet != NULL);    data = packet->data;    /* The parameter header should be TAB, followed by a three-digit     * parameter number, a colon, and the data.  We already know about     * the tab. */    if (len < 5 ||        !octstr_check_range(data, pos + 1, 3, gw_isdigit) ||        octstr_get_char(data, pos + 4) != ':') {        warning(0, "CIMD2 parameter at offset %ld in wrong format",                pos);        errors++;    }    /* If we can't parse a parameter number, there's nothing more     * that we can check. */    dpos = octstr_parse_long(&parm, data, pos + 1, 10);    if (dpos < 0)        return -1;    if (octstr_get_char(data, dpos) == ':')        dpos++;    dlen = len - (dpos - pos);    /* dlen can not go negative because octstr_parse_long must have     * been stopped by the TAB at the end of the parameter data. */    gw_assert(dlen >= 0);    i = parm_index(parm);    if (i < 0) {        warning(0, "CIMD2 packet contains unknown parameter %ld", parm);        return -1;    }    if (dlen > parameters[i].maxlen) {        warning(0, "CIMD2 packet has '%s' parameter with length %ld, spec says max %d",                parameters[i].name, len, parameters[i].maxlen);        errors++;    }    switch (parameters[i].type) {    case P_INT:        /* Allow a leading - */        negative = (octstr_get_char(data, dpos) == '-');        if (!octstr_check_range(data, dpos + negative,                                dlen - negative, gw_isdigit)) {            warning(0, "CIMD2 packet has '%s' parameter with non-integer contents", parameters[i].name);            errors++;        }        if (octstr_parse_long(&value, data, dpos, 10) >= 0 &&            (value < parameters[i].minval || value > parameters[i].maxval)) {            warning(0, "CIMD2 packet has '%s' parameter out of range (value %ld, min %d, max %d)",                    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 packet has '%s' parameter with non-digit contents", parameters[i].name);            errors++;        }        break;    case P_ADDRESS:        if (!octstr_check_range(data, dpos, dlen, isphonedigit)) {            warning(0, "CIMD2 packet has '%s' parameter with non phone number contents", parameters[i].name);            errors++;        }        break;    case P_HEX:        if (!octstr_check_range(data, dpos, dlen, gw_isxdigit)) {            warning(0, "CIMD2 packet has '%s' parameter with non-hex contents", parameters[i].name);            errors++;        }        if (dlen % 2 != 0) {            warning(0, "CIMD2 packet has odd-length '%s' parameter", 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){    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 packet contains NULs");        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) < 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) < 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 packet checksum in wrong format");                errors++;            }        }    }    if (errors > 0) {        octstr_dump(packet->data, 0);        return -1;    }    return 0;}static void packet_check_can_receive(struct packet *packet){    gw_assert(packet != NULL);    if (!operation_can_receive(packet->operation)) {

⌨️ 快捷键说明

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