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

📄 smsc_cimd2.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 5 页
字号:
        if (i >= 0) {            Octstr *name = octstr_create(operations[i].name);            octstr_append_cstr(name, " response");            return name;        }    }    /* Put the operation number here when we have octstr_format */    return octstr_create("(unknown)");}/* Return true if a CIMD2 client may send this operation */static const int operation_can_send(int operation){    int i = operation_find(operation);    if (i >= 0)        return operations[i].can_send;    /* If we can receive the request, then we can send the response. */    if (operation >= RESPONSE)        return operation_can_receive(operation - RESPONSE);    return 0;}/* Return true if a CIMD2 server may send this operation */static const int operation_can_receive(int operation){    int i = operation_find(operation);    if (i >= 0)        return operations[i].can_receive;    /* If we can send the request, then we can receive the response. */    if (operation >= RESPONSE)        return operation_can_send(operation - RESPONSE);    return 0;}/***************************************************************************//* Packet encoding/decoding functions.  They handle packets at the octet   *//* level, and know nothing of the network.                                 *//***************************************************************************/struct packet{    /* operation and seq are -1 if their value could not be parsed */    int operation;    int seq;   /* Sequence number */    Octstr *data;   /* Encoded packet */    /* CIMD 2 packet structure is so simple that packet information is     * stored as a valid encoded packet, and decoded as necessary.     * Exceptions: operation code and sequence number are also stored     * as ints for speed, and the checksum is not added until the packet     * is about to be sent.  Since checksums are optional, the packet     * is still valid without a checksum.     *     * The sequence number is kept at 0 until it's time to actually     * send the packet, so that the send functions have control over     * the sequence numbers.     */};/* These are the separators defined by the CIMD 2 spec */#define STX 2   /* Start of packet */#define ETX 3   /* End of packet */#define TAB 9   /* End of parameter *//* The same separators, in string form */#define STX_str "\02"#define ETX_str "\03"#define TAB_str "\011"/* A reminder that packets are created without a valid sequence number */#define BOGUS_SEQUENCE 0static Msg *cimd2_accept_delivery_report_message(struct packet *request,						 SMSCConn *conn);/* Look for the STX OO:SSS TAB header defined by CIMD 2, where OO is the * operation code in two decimals and SSS is the sequence number in three * decimals.  Leave the results in the proper fields of the packet. * Try to make sense of headers that don't fit this pattern; validating * the packet format is not our job. */static void packet_parse_header(struct packet *packet){    int pos;    long number;    /* Set default values, in case we can't parse the fields */    packet->operation = -1;    packet->seq = -1;    pos = octstr_parse_long(&number, packet->data, 1, 10);    if (pos < 0)        return;    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, SMSCConn *conn){    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[%s]: packet without end marker",                octstr_get_cstr(conn->id));        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, SMSCConn *conn){    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[%s]: packet header in wrong format",                octstr_get_cstr(conn->id));        return -1;    }    return 0;}static int packet_check_parameter(struct packet *packet, long pos, long len, SMSCConn *conn){    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[%s]: parameter at offset %ld in wrong format",                octstr_get_cstr(conn->id),                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[%s]: packet contains unknown parameter %ld",                 octstr_get_cstr(conn->id),                parm);        return -1;    }    if (dlen > parameters[i].maxlen) {        warning(0, "CIMD2[%s]: packet has '%s' parameter with length %ld, spec says max %d",                octstr_get_cstr(conn->id),                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,

⌨️ 快捷键说明

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