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

📄 smsc_oisd.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 4 页
字号:
     *             the recipient in interpreting the SM.     *                   z = reply path     *                   y = user data header indicator     *                   x = reserved     */    /*     * Destination addr. and Originating addr. w/o TOA     */    /* Destination addr. length */    dest_len = octstr_get_char(request->data, 10);    /* Destination addr. */    msg->sms.receiver = octstr_copy(request->data, 11+2, dest_len-2);    /* Originating addr. length */    origin_len = octstr_get_char(request->data, 11+dest_len+4);    /* Originating addr. */    msg->sms.sender = octstr_copy(request->data, 11+dest_len+5+2, origin_len-2);    DCS = octstr_get_char(request->data, 11+dest_len+5+origin_len);    if (!dcs_to_fields(&msg, DCS)) {        /* XXX: Should reject this message ? */        debug("bb.sms.oisd", 0, "OISD[%s]: Invalid DCS",              octstr_get_cstr(conn->id));        dcs_to_fields(&msg, 0);    }    add_info = octstr_get_char(request->data,11+dest_len+5+origin_len+2);    msglen7 = octstr_get_char(request->data, 11+dest_len+5+origin_len+3);    msglen8 = octstr_get_char(request->data, 11+dest_len+5+origin_len+4);    msg->sms.rpi = add_info & 0x01;    debug("bb.sms.oisd", 0,          "OISD[%s]: received DCS=%02X, add_info=%d, msglen7=%d, msglen8=%d, rpi=%ld",          octstr_get_cstr(conn->id),          DCS, add_info, msglen7, msglen8, msg->sms.rpi);    if (msg->sms.coding == DC_7BIT) {        msg->sms.msgdata =            oisd_expand_gsm7(octstr_copy(request->data,                                         11+dest_len+5+origin_len+5,                                         msglen7));            debug("bb.sms.oisd", 0, "OISD[%s]: received raw8=%s ",                  octstr_get_cstr(conn->id),                  octstr_get_cstr(msg->sms.msgdata));        if (add_info & 0x02) {            warning(0, "OISD[%s]: 7-bit UDH ?",                    octstr_get_cstr(conn->id));        } else {            charset_gsm_to_latin1(msg->sms.msgdata);            debug("bb.sms.oisd", 0, "OISD[%s]: received latin1=%s",                  octstr_get_cstr(conn->id),                  octstr_get_cstr(msg->sms.msgdata));        }    } else {        /* 0xf4, 0xf5, 0xf6, 0xf7; 8bit to disp, mem, sim or term */        if (add_info & 0x02) {            udh_len = octstr_get_char(request->data,                                      11+dest_len+5+origin_len+5)+1;            msg->sms.msgdata =                octstr_copy(request->data,                            11+dest_len+5+origin_len+5+udh_len,                            msglen8);            msg->sms.udhdata =                octstr_copy(request->data,                            11+dest_len+5+origin_len+5,                            udh_len);        } else {            msg->sms.msgdata =                octstr_copy(request->data,                            11+dest_len+5+origin_len+5,                            msglen8);        }    }    /* 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 (!(msg->sms.receiver) || octstr_len(msg->sms.receiver) == 0) {        info(0, "OISD[%s]: Got SMS without receiver, discarding.",             octstr_get_cstr(conn->id));        goto error;    }    if (!(msg->sms.sender) || octstr_len(msg->sms.sender) == 0) {        info(0, "OISD[%s]: Got SMS without sender, discarding.",              octstr_get_cstr(conn->id));        goto error;    }    if ((!(msg->sms.msgdata) || octstr_len(msg->sms.msgdata) == 0)        && (!(msg->sms.udhdata) || octstr_len(msg->sms.udhdata) == 0)) {        info(0, "OISD[%s]: Got empty SMS, ignoring.",              octstr_get_cstr(conn->id));        goto error;    }    return msg;error:    msg_destroy(msg);    return NULL;}/* Deal with a request from the OISD server, and acknowledge it. */static void oisd_handle_request(struct packet *request, SMSCConn *conn){    PrivData *pdata = conn->data;    Msg *msg = NULL;    if (request->operation == STATUS_REPORT) {        msg = oisd_accept_delivery_report_message(request, conn);        if (msg)            list_append(pdata->received, msg);    } else if (request->operation == DELIVER_SM) {        msg = oisd_accept_message(request, conn);        if (msg)            list_append(pdata->received, msg);    }    oisd_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. */static int oisd_request(struct packet *request, SMSCConn *conn, Octstr **ts){    PrivData *pdata = conn->data;    int ret;    struct packet *reply = NULL;    int errorcode;    int tries = 0;    Octstr *request_name;    gw_assert(pdata != NULL);    gw_assert(request != NULL);    gw_assert(operation_can_send(request->operation));    if (pdata->socket < 0) {        warning(0, "OISD[%s]: oisd_request: socket not open.",                octstr_get_cstr(conn->id));        return -2;    }    packet_set_data_size(request);retransmit:    packet_set_send_sequence(request, pdata);    request_name = operation_name(request->operation);    debug("bb.sms.oisd", 0, "OISD[%s]: sending %s request",          octstr_get_cstr(conn->id),          octstr_get_cstr(request_name));    octstr_destroy(request_name);    if (request->operation != RETRIEVE_REQUEST)        octstr_dump(request->data, 0);    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 = oisd_get_packet(pdata, ts);    if (!reply)        goto io_error;    /* The server sent us a request.  Handle it, then wait for     * a new reply. */    if (reply->operation < RESPONSE) {        oisd_handle_request(reply, conn);        goto next_reply;    }    if (reply->opref != request->opref) {        /* We got a response to a different request number than         * what we send.  Strange. */        warning(0, "OISD[%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, "OISD[%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;    }    errorcode = octstr_get_char(reply->data, 10); /* Result */    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, "OISD[%s]: Retransmitting (take %d)",                octstr_get_cstr(conn->id),                tries);        goto retransmit;    }    warning(0, "OISD[%s]: Giving up.",            octstr_get_cstr(conn->id));    goto io_error;}/* Close the SMSC socket without fanfare. */static void oisd_close_socket(PrivData *pdata){    gw_assert(pdata != NULL);    if (pdata->socket < 0)        return;    if (close(pdata->socket) < 0)        warning(errno, "OISD[%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 oisd_login(SMSCConn *conn){    PrivData *pdata = conn->data;    struct packet *packet = NULL;    gw_assert(pdata != NULL);    if (pdata->socket >= 0) {        warning(0, "OISD[%s]: login: socket was already open; closing",                octstr_get_cstr(conn->id));        oisd_close_socket(pdata);    }    pdata->socket = tcpip_connect_to_server(                        octstr_get_cstr(pdata->host),                        pdata->port,                        (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL));    if (pdata->socket != -1) {        info(0, "OISD[%s] logged in.",             octstr_get_cstr(conn->id));        return 0;    }    error(0, "OISD[%s] login failed.",          octstr_get_cstr(conn->id));    oisd_close_socket(pdata);    packet_destroy(packet);    return -1;}static int oisd_send_delivery_request(SMSCConn *conn){    PrivData *pdata = conn->data;    struct packet *packet = NULL;    int ret;    gw_assert(conn != NULL);    packet = packet_create(RETRIEVE_REQUEST, BOGUS_SEQUENCE);    gw_assert(octstr_check_range(pdata->my_number, 0,                                 octstr_len(pdata->my_number),                                 isphonedigit));    /* Originating address length */    octstr_append_char(packet->data,                       (char) (octstr_len(pdata->my_number) + 2));    /* TON */    octstr_append_char(packet->data, 0x42);    /* NPI */    octstr_append_char(packet->data, 0x44);    /* Originating address */    octstr_append(packet->data, pdata->my_number);    /* Receive ready flag */    octstr_append_char(packet->data, 1);    /* Retrieve order */    octstr_append_char(packet->data, 0);    ret = oisd_request(packet, conn, NULL);    packet_destroy(packet);    if (ret < 0)        warning(0, "OISD[%s]: Sending delivery request failed.\n",                octstr_get_cstr(conn->id));    return ret;}static void oisd_destroy(PrivData *pdata){    int discarded;    if (pdata == NULL)        return;    octstr_destroy(pdata->host);    octstr_destroy(pdata->inbuffer);    octstr_destroy(pdata->my_number);    discarded = list_len(pdata->received);    if (discarded > 0)        warning(0, "OISD[%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 oisd_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.oisd", 0, "OISD[%s]: sending message",          octstr_get_cstr(conn->id));    packet = packet_encode_message(msg, conn);    if (!packet) {        /* This is a protocol error. Does this help? I doubt..         * But nevermind that.         */        bb_smscconn_send_failed(conn, msg,                SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED"));        return -1;    }    ret = oisd_request(packet, conn, &ts);    if((ret == 0) && (ts) && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask) && !pdata->no_dlr) {        dlr_add(conn->name, ts, msg);    }    octstr_destroy(ts);    packet_destroy(packet);    if (ret == -1) {        bb_smscconn_send_failed(conn, msg,                SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED"));    }    else if (ret == -2) {        oisd_close_socket(pdata);        bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL);        mutex_lock(conn->flow_mutex);        conn->status = SMSCCONN_DISCONNECTED;        mutex_unlock(conn->flow_mutex);    }    else {        bb_smscconn_sent(conn, msg, NULL);    }    return ret;}static int oisd_receive_msg(SMSCConn *conn, Msg **msg)

⌨️ 快捷键说明

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