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

📄 smsc_cgw.c

📁 gnu的专业网关smpp协议支持源代码。
💻 C
📖 第 1 页 / 共 3 页
字号:
}/****************************************************************************** * cgw_read_op - read an operation, and return it as a *cgwop structure * * This function will not lock and wait for data if none is available. It will * however lock until a whole op has been read. Timeout not implemented yet. */struct cgwop *cgw_read_op(PrivData *privdata, SMSCConn *conn, Connection *server, time_t timeout){    Octstr *line, *name, *value;    int finished = 0;    int c = 0;    struct cgwop *cgwop = NULL;    int op = CGW_OP_NOP;    if ((line = conn_read_line(server)) == NULL)         return NULL;     /* don't block */    do    {        while (line == NULL)            line = conn_read_line(server);     /* wait for more data */        c = octstr_search_char(line, ':', 0);        if (c != -1) {            name = octstr_copy(line, 0, c);            value = octstr_copy(line, c + 1, octstr_len(line) - (c + 1));            if (octstr_compare(name, octstr_imm("hello")) == 0) {                /* A connection is started by CGW by sending a 		 * "hello: Provider Server..." line. */                cgwop = cgwop_create(CGW_OP_HELLO, 0);                cgwop_add(cgwop, octstr_imm("hello"), value);                octstr_destroy(name);                octstr_destroy(value);                octstr_destroy(line);                return cgwop;            }            if (octstr_compare(name, octstr_imm("op")) == 0) {                /* check different ops */                if (octstr_compare(value, octstr_imm("msg")) == 0)                    op = CGW_OP_MSG;                else                    if (octstr_compare(value, octstr_imm("ok")) == 0)                        op = CGW_OP_OK;                    else                        if (octstr_compare(value, octstr_imm("delivery")) == 0)                            op = CGW_OP_DELIVERY;                        else                            if (octstr_compare(value, octstr_imm("err")) == 0)                                op = CGW_OP_ERR;                            else                                if (octstr_compare(value, octstr_imm("status")) == 0)                                    op = CGW_OP_STATUS;                                else                                    info(0, "CGW: Received unknown op: %s", octstr_get_cstr(value));                if (cgwop == NULL)                    cgwop = cgwop_create(op, 0);                else                    info(0, "cgw: cgwop != null");            }            if (op != CGW_OP_NOP) {                /* All commands have to be inside an op:xx ... end:xx statement */                if (octstr_compare(name, octstr_imm("end")) == 0) { // found end of op                    finished = 1;                } else {                    // store in name/value fields in cgwop                    if (cgwop != NULL) {                        cgwop_add(cgwop, name, value);                    }                }            }            octstr_destroy(name);            octstr_destroy(value);            octstr_destroy(line);            if (!finished) line = conn_read_line(server);        } else {            info(0, "cgw: Received invalid input: %s", octstr_get_cstr(line));            octstr_destroy(line);            finished = 1;        }    } while (!finished);    return cgwop;}static int cgw_open_listening_socket(PrivData *privdata){    int s;    if ((s = make_server_socket(privdata->rport, NULL)) == -1) {        /* XXX add interface_name if required */        error(0, "smsc_cgw: could not create listening socket in port %d", privdata->rport);        return -1;    }    if (socket_set_blocking(s, 0) == -1) {        error(0, "smsc_cgw: couldn't make listening socket port %d non-blocking", privdata->rport);        close(s);        return -1;    }    privdata->listening_socket = s;    return 0;}/****************************************************************************** * This is the entry point for our receiver thread. Listens for incoming  * connections and handles operations. */static void cgw_listener(void *arg){    SMSCConn	*conn = arg;    PrivData	*privdata = conn->data;    struct sockaddr_in server_addr;    socklen_t	server_addr_len;    Octstr	*ip;    Connection	*server;    int s, ret;    while (!privdata->shutdown) {        server_addr_len = sizeof(server_addr);	        ret = gwthread_pollfd(privdata->listening_socket, POLLIN, -1);        if (ret == -1) {            if (errno == EINTR)                continue;            error(0, "Poll for cgw smsc connections failed, shutting down");            break;        }        if (privdata->shutdown)            break;        if (ret == 0) /* This thread was woken up from elsewhere, but                       * if we're not shutting down nothing to do here. */            continue;        s = accept(privdata->listening_socket, (struct sockaddr *) & server_addr,                   &server_addr_len);        if (s == -1) {            warning(errno, "cgw_listener: accept() failed, retrying...");            continue;        }        ip = host_ip(server_addr);        if (!is_allowed_ip(privdata->allow_ip, privdata->deny_ip, ip)) {            info(0, "CGW smsc connection tried from denied host <%s>, disconnected", octstr_get_cstr(ip));            octstr_destroy(ip);            close(s);            continue;        }        server = conn_wrap_fd(s, 0);        if (server == NULL) {            error(0, "cgw_listener: conn_wrap_fd failed on accept()ed fd");            octstr_destroy(ip);            close(s);            continue;        }        conn_claim(server);        info(0, "cgw: smsc connected from %s", octstr_get_cstr(ip));        octstr_destroy(ip);        cgw_receiver(conn, server);        conn_destroy(server);    }    if (close(privdata->listening_socket) == -1)        warning(errno, "smsc_cgw: couldn't close listening socket at shutdown");    gwthread_wakeup(privdata->sender_thread);}static void cgw_receiver(SMSCConn *conn, Connection *server){    PrivData *privdata = conn->data;    Octstr *str = NULL;    struct cgwop *cgwop;    while (1) {        if (conn_eof(server)) {            info(0, "cgw: receive connection closed by SMSC");            return ;        }        if (conn_read_error(server)) {            error(0, "cgw: receive connection broken");            return ;        }        if (conn->is_stopped)	    str = NULL;        cgwop = cgw_read_op(conn->data, conn, server, 0);        if (cgwop != NULL) {            cgw_handle_op(conn, server, cgwop);            cgwop_destroy(cgwop);        } else            conn_wait(server, -1);        if (privdata->shutdown)            break;    }    return ;}/****************************************************************************** * This function handles incoming operations. Used by both receiver and sender * threads (i.e. sender thread uses this function for delivery and ack * operations). * Returns 1 if successfull, otherwise 0 */static int cgw_handle_op(SMSCConn *conn, Connection *server, struct cgwop *cgwop){    PrivData *privdata = conn->data;    Msg *msg = NULL;    Octstr *from, *app, *sid, *to, *msgtype, *msgdata; /* for messages */    Octstr *msid, *status, *txt;    		       /* delivery reports */    Octstr *clid;    		       		       /* for acks */    struct cgwop *reply = NULL;    long trn, stat;                          /* transaction number for ack */    Msg *dlrmsg = NULL, *origmsg = NULL;    Octstr *ts;    if (cgwop == NULL) return 0;    from = cgwop_get(cgwop, octstr_imm("from"));    app = cgwop_get(cgwop, octstr_imm("app"));    sid = cgwop_get(cgwop, octstr_imm("session-id"));    to = cgwop_get(cgwop, octstr_imm("to"));    msgtype = cgwop_get(cgwop, octstr_imm("type"));    msgdata = cgwop_get(cgwop, octstr_imm("msg"));    txt = cgwop_get(cgwop, octstr_imm("txt"));    msid = cgwop_get(cgwop, octstr_imm("msid"));    status = cgwop_get(cgwop, octstr_imm("status"));    clid = cgwop_get(cgwop, octstr_imm("client-id"));    if (clid != NULL)    {        octstr_parse_long(&trn, clid, 0, 10);        if ((trn < 0) || (trn >= CGW_TRN_MAX)) { /* invalid transaction number */	    info(0, "cgw: Invalid transaction number: %d", (int) trn);            trn = -1;            	    return 0;        }    }    switch (cgwop->op)    {    case CGW_OP_MSG:        msg = msg_create(sms);        time(&msg->sms.time);        msg->sms.msgdata = cgw_decode_msg(octstr_duplicate(msgdata));        msg->sms.sender = octstr_duplicate(from);        msg->sms.receiver = octstr_duplicate(to);        msg->sms.smsc_id = octstr_duplicate(conn->id);        bb_smscconn_receive(conn, msg);        reply = cgwop_create(CGW_OP_OK, -1);        cgwop_add(reply, octstr_imm("session-id"), sid);        cgwop_send(server, reply);     // send reply        cgwop_destroy(reply);        break;    case CGW_OP_DELIVERY:        if (privdata->dlr[trn]) {            octstr_parse_long(&stat, status, 0, 10);            origmsg = privdata->sendmsg[trn];            if (origmsg == NULL) break;            ts = octstr_create("");            octstr_append(ts, conn->id);            octstr_append_char(ts, '-');            octstr_append_decimal(ts, trn);            switch (stat) {            case 0:     /* delivered */                dlrmsg = dlr_find(octstr_get_cstr(conn->id),                                  octstr_get_cstr(ts),     /* timestamp */                                  octstr_get_cstr(msid),   /* destination */                                  DLR_SUCCESS);                break;            case 1:     /* buffered */                dlrmsg = dlr_find(octstr_get_cstr(conn->id),                                  octstr_get_cstr(ts),     /* timestamp */                                  octstr_get_cstr(msid),   /* destination */                                  DLR_BUFFERED);                break;            case 2:     /* not delivered */                dlrmsg = dlr_find(octstr_get_cstr(conn->id),                                  octstr_get_cstr(ts),     /* timestamp */                                  octstr_get_cstr(msid),   /* destination */                                  DLR_FAIL);                break;            }            octstr_destroy(ts);            if (dlrmsg != NULL) {                dlrmsg->sms.msgdata = octstr_duplicate(txt);                bb_smscconn_receive(conn, dlrmsg);            }        }        break;    case CGW_OP_OK:        if (trn == -1) break;     /* invalid transaction number */        /* info(0, "cgw: Got ACK: %s", octstr_get_cstr(clid)); */        privdata->sendtime[trn] = 0;        privdata->unacked--;        /* add delivery notification request if wanted */        msg = privdata->sendmsg[trn];        if (msg && msg->sms.dlr_url && (msg->sms.dlr_mask & 0x07)) {            Octstr *ts;            ts = octstr_create("");            octstr_append(ts, conn->id);            octstr_append_char(ts, '-');            octstr_append_decimal(ts, trn);            dlr_add(octstr_get_cstr(conn->id),                    octstr_get_cstr(ts),                    octstr_get_cstr(msg->sms.sender),                    octstr_get_cstr(msg->sms.receiver),                    octstr_get_cstr(msg->sms.service),                    octstr_get_cstr(msg->sms.dlr_url),                    msg->sms.dlr_mask);            octstr_destroy(ts);            privdata->dlr[trn] = 1;        } else {            privdata->dlr[trn] = 0;        }        bb_smscconn_sent(conn, msg);     /* mark as successfully sent */        break;    case CGW_OP_STATUS:        info(0, "CGW: Warning: Got session status");        /* op:status messages are sent by ProviderServer to tell if there are problems with           the session status. These are not wanted, and should never occur, as the delivery is           cancelled, and no end-user billing is done. */        break;    case CGW_OP_HELLO:        info(0, "CGW: Server said: %s", octstr_get_cstr(cgwop_get(cgwop, octstr_imm("hello"))));        break;    case CGW_OP_ERR:        if (trn == -1) break;     /* invalid transaction number */        info(0, "CGW: Received error: %s", octstr_get_cstr(txt));        privdata->sendtime[trn] = 0;        privdata->unacked--;        bb_smscconn_send_failed(conn, privdata->sendmsg[trn],                                SMSCCONN_FAILED_REJECTED);        break;    default:        info(0, "cgw: Unknown operation: %d", cgwop->op);        return 0;    }    return 1;}

⌨️ 快捷键说明

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