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

📄 smsc_cimd2.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 5 页
字号:
    response = packet_create(request->operation + RESPONSE, request->seq);    packet_set_checksum(response);    debug("bb.sms.cimd2", 0, "CIMD2[%s]: sending <%s>",          octstr_get_cstr(pdata->conn->id),          octstr_get_cstr(response->data));    /* Don't check errors here because if there is something     * wrong with the socket, the main loop will detect it. */    octstr_write_to_socket(pdata->socket, response->data);    packet_destroy(response);}static Msg *cimd2_accept_message(struct packet *request, SMSCConn *conn){    Msg *message = NULL;    Octstr *destination = NULL;    Octstr *origin = NULL;    Octstr *UDH = NULL;    Octstr *text = NULL;    int DCS;    /* See GSM 03.38.  The bit patterns we can handle are:     *   000xyyxx  Uncompressed text, yy indicates alphabet.     *                   yy = 00, default alphabet     *                   yy = 01, 8-bit data     *                   yy = 10, UCS2     *                   yy = 11, reserved     *   1111xyxx  Data, y indicates alphabet.     *                   y = 0, default alphabet     *                   y = 1, 8-bit data     */    DCS = packet_get_int_parm(request, P_DATA_CODING_SCHEME);    destination = packet_get_address_parm(request, P_DESTINATION_ADDRESS);    origin = packet_get_address_parm(request, P_ORIGINATING_ADDRESS);    UDH = packet_get_hex_parm(request, P_USER_DATA_HEADER);    /* Text is either in User Data or User Data Binary field. */    text = packet_get_sms_parm(request, P_USER_DATA);    if (text != NULL) {        convert_cimd2_to_gsm(text,conn);        charset_gsm_to_latin1(text);    } else {        /*         * FIXME: If DCS indicates GSM charset, and we get it in binary,         * then it's probably bit-packed.  We'll have to undo it because         * our "charset_gsm" means one gsm character per octet.  This is         * not currently supported. -- RB         */        text = packet_get_hex_parm(request, P_USER_DATA_BINARY);    }    /* Code elsewhere in the gateway always expects the sender and     * receiver fields to be filled, so we discard messages that     * lack them.  If they should not be discarded, then the code     * handling sms messages should be reviewed.  -- RB */    if (!destination || octstr_len(destination) == 0) {        info(0, "CIMD2[%s]: Got SMS without receiver, discarding.",              octstr_get_cstr(conn->id));        goto error;    }    if (!origin || octstr_len(origin) == 0) {        info(0, "CIMD2[%s]: Got SMS without sender, discarding.",              octstr_get_cstr(conn->id));        goto error;    }    if (!text && (!UDH || octstr_len(UDH) == 0)) {        info(0, "CIMD2[%s]: Got empty SMS, ignoring.",              octstr_get_cstr(conn->id));        goto error;    }        message = msg_create(sms);    if (! dcs_to_fields(&message, DCS)) {	/* XXX Should reject this message ? */        debug("bb.sms.cimd2", 0, "CIMD2[%s]: Invalid DCS",              octstr_get_cstr(conn->id));	dcs_to_fields(&message, 0);    }    time(&message->sms.time);    message->sms.sender = origin;    message->sms.receiver = destination;    if (UDH) {        message->sms.udhdata = UDH;    }    message->sms.msgdata = text;    return message;error:    msg_destroy(message);    octstr_destroy(destination);    octstr_destroy(origin);    octstr_destroy(UDH);    octstr_destroy(text);    return NULL;}/* Deal with a request from the CIMD2 server, and acknowledge it. */static void cimd2_handle_request(struct packet *request, SMSCConn *conn){    PrivData *pdata = conn->data;    Msg *message = NULL;    if ((request->seq == 254 && pdata->receive_seq == 0) ||            request->seq == pdata->receive_seq - 2) {        warning(0, "CIMD2[%s]: request had same sequence number as previous.",                octstr_get_cstr(conn->id));    }    else {        pdata->receive_seq = request->seq + 2;        if (pdata->receive_seq > 254)            pdata->receive_seq = 0;        if (request->operation == DELIVER_STATUS_REPORT) {            message = cimd2_accept_delivery_report_message(request, conn);            if (message)                list_append(pdata->received, message);        }        else if (request->operation == DELIVER_MESSAGE) {            message = cimd2_accept_message(request,conn);            if (message)                list_append(pdata->received, message);        }    }    cimd2_send_response(request, pdata);}/* Send a request and wait for the ack.  If the other side responds with * an error code, attempt to correct and retry. * If other packets arrive while we wait for the ack, handle them. * * Return -1 if the SMSC refused the request.  Return -2 for other * errors, such as being unable to send the request at all.  If the * function returns -2, the caller would do well to try to reopen the * connection. * * The SMSCenter must be already open. * * TODO: This function has grown large and complex.  Break it up * into smaller pieces. */static int cimd2_request(struct packet *request, SMSCConn *conn, Octstr **ts){    PrivData *pdata = conn->data;    int ret;    struct packet *reply = NULL;    int errorcode;    int tries = 0;    gw_assert(pdata != NULL);    gw_assert(request != NULL);    gw_assert(operation_can_send(request->operation));    if (pdata->socket < 0) {        warning(0, "CIMD2[%s]: cimd2_request: socket not open.",                octstr_get_cstr(conn->id));        return -2;            }    retransmit:    packet_set_send_sequence(request, pdata);    packet_set_checksum(request);    debug("bb.sms.cimd2", 0, "CIMD2[%s]: sending <%s>",          octstr_get_cstr(conn->id),          octstr_get_cstr(request->data));    ret = octstr_write_to_socket(pdata->socket, request->data);    if (ret < 0)        goto io_error;next_reply:    packet_destroy(reply);  /* destroy old, if any */    reply = cimd2_get_packet(pdata, ts);    if (!reply)        goto io_error;    errorcode = packet_display_error(reply,conn);    if (reply->operation == NACK) {        warning(0, "CIMD2[%s]: received NACK",                octstr_get_cstr(conn->id));        octstr_dump(reply->data, 0);        /* Correct sequence number if server says it was wrong,         * but only if server's number is sane. */        if (reply->seq != request->seq && (reply->seq % 2) == 1) {            warning(0, "CIMD2[%s]: correcting sequence number from %ld to %ld.",                    octstr_get_cstr(conn->id),                    (long) pdata->send_seq,                     (long) reply->seq);            pdata->send_seq = reply->seq;        }        goto retry;    }    if (reply->operation == GENERAL_ERROR_RESPONSE) {        error(0, "CIMD2[%s]: received general error response",              octstr_get_cstr(conn->id));        goto io_error;    }    /* The server sent us a request.  Handle it, then wait for     * a new reply. */    if (reply->operation < RESPONSE) {        cimd2_handle_request(reply, conn);        goto next_reply;    }    if (reply->seq != request->seq) {        /* We got a response to a different request number than         * what we send.  Strange. */        warning(0, "CIMD2[%s]: response had unexpected sequence number; ignoring.",                octstr_get_cstr(conn->id));        goto next_reply;    }    if (reply->operation != request->operation + RESPONSE) {        /* We got a response that didn't match our request */        Octstr *request_name = operation_name(request->operation);        Octstr *reply_name = operation_name(reply->operation);        warning(0, "CIMD2[%s]: %s request got a %s",                octstr_get_cstr(conn->id),                octstr_get_cstr(request_name),                octstr_get_cstr(reply_name));        octstr_destroy(request_name);        octstr_destroy(reply_name);        octstr_dump(reply->data, 0);        goto retry;    }    if (errorcode > 0)        goto error;    /* The reply passed all the checks... looks like the SMSC accepted     * our request! */    packet_destroy(reply);    return 0;io_error:    packet_destroy(reply);    return -2;error:    packet_destroy(reply);    return -1;retry:    if (++tries < 3) {        warning(0, "CIMD2[%s]: Retransmitting (take %d)",                 octstr_get_cstr(conn->id),                tries);        goto retransmit;    }    warning(0, "CIMD2[%s]: Giving up.",            octstr_get_cstr(conn->id));    goto io_error;}/* Close the SMSC socket without fanfare. */static void cimd2_close_socket(PrivData *pdata){    gw_assert(pdata != NULL);    if (pdata->socket < 0)        return;    if (close(pdata->socket) < 0)        warning(errno, "CIMD2[%s]: error closing socket",                octstr_get_cstr(pdata->conn->id));    pdata->socket = -1;}/* Open a socket to the SMSC, send a login packet, and wait for ack. * This may block.  Return 0 for success, or -1 for failure. *//* Make sure the socket is closed before calling this function, otherwise * we will leak fd's. */static int cimd2_login(SMSCConn *conn){    PrivData *pdata = conn->data;    int ret;    struct packet *packet = NULL;    gw_assert(pdata != NULL);    if (pdata->socket >= 0) {        warning(0, "CIMD2[%s]: login: socket was already open; closing",                octstr_get_cstr(conn->id));        cimd2_close_socket(pdata);    }        pdata->socket = tcpip_connect_to_server_with_port(                                            octstr_get_cstr(pdata->host),                                            pdata->port,                                            pdata->our_port,                                            (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL));     if (pdata->socket != -1) {            packet = packet_create(LOGIN, BOGUS_SEQUENCE);        packet_add_string_parm(packet, P_USER_IDENTITY, pdata->username, conn);        packet_add_string_parm(packet, P_PASSWORD, pdata->password, conn);                ret = cimd2_request(packet, conn, NULL);                if (ret >= 0) {            packet_destroy(packet);            info(0, "CIMD2[%s] logged in.",                 octstr_get_cstr(conn->id));            return 0;        }    }    error(0, "CIMD2[%s] login failed.",          octstr_get_cstr(conn->id));    cimd2_close_socket(pdata);    packet_destroy(packet);    return -1;}static void cimd2_logout(SMSCConn *conn){    struct packet *packet = NULL;    int ret;    packet = packet_create(LOGOUT, BOGUS_SEQUENCE);    /* TODO: Don't wait very long for a response in this case. */    ret = cimd2_request(packet, conn, NULL);    if (ret == 0) {        info(0, "CIMD2[%s] logged out.",             octstr_get_cstr(conn->id));    }    packet_destroy(packet);}static int cimd2_send_alive(SMSCConn *conn){    struct packet *packet = NULL;    int ret;    packet = packet_create(ALIVE, BOGUS_SEQUENCE);    ret = cimd2_request(packet, conn, NULL);    packet_destroy(packet);    if (ret < 0)        warning(0, "CIMD2[%s]: SMSC not alive.",                octstr_get_cstr(conn->id));    return ret;}static void cimd2_destroy(PrivData *pdata){    int discarded;    if (pdata == NULL)         return;            octstr_destroy(pdata->host);    octstr_destroy(pdata->username);    octstr_destroy(pdata->password);    octstr_destroy(pdata->inbuffer);    octstr_destroy(pdata->my_number);    discarded = list_len(pdata->received);    if (discarded > 0)        warning(0, "CIMD2[%s]: discarded %d received messages",                octstr_get_cstr(pdata->conn->id),                 discarded);    list_destroy(pdata->received, msg_destroy_item);    list_destroy(pdata->outgoing_queue, NULL);    list_destroy(pdata->stopped, NULL);    gw_free(pdata);}static int cimd2_submit_msg(SMSCConn *conn, Msg *msg){    PrivData *pdata = conn->data;    struct packet *packet;    Octstr *ts = NULL;    int ret;    gw_assert(pdata != NULL);    debug("bb.sms.cimd2", 0, "CIMD2[%s]: sending message",      

⌨️ 快捷键说明

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