Ejemplo n.º 1
0
/******************************************************************************
 * 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(conn->id,
                                            ts,     /* timestamp */
                                            msid,   /* destination */
                                  DLR_SUCCESS);
                break;
            case 1:     /* buffered */
                dlrmsg = dlr_find(conn->id,
                                            ts,     /* timestamp */
                                            msid,   /* destination */
                                  DLR_BUFFERED);
                break;
            case 2:     /* not delivered */
                dlrmsg = dlr_find(conn->id,
                                            ts,     /* timestamp */
                                            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 && DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
            Octstr *ts;

            ts = octstr_create("");
            octstr_append(ts, conn->id);
            octstr_append_char(ts, '-');
            octstr_append_decimal(ts, trn);

            dlr_add(conn->id, ts, msg);

            octstr_destroy(ts);
            privdata->dlr[trn] = 1;
        } else {
            privdata->dlr[trn] = 0;
        }

	/* mark as successfully sent */
        bb_smscconn_sent(conn, msg, NULL);

        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, octstr_create("REJECTED"));

        break;

    default:
        info(0, "cgw: Unknown operation: %d", cgwop->op);
        return 0;
    }

    return 1;
}
Ejemplo n.º 2
0
static void kannel_receive_sms(SMSCConn *conn, HTTPClient *client,
                               List *headers, Octstr *body, List *cgivars)
{
    ConnData *conndata = conn->data;
    Octstr *user, *pass, *from, *to, *text, *udh, *account, *binfo, *charset;
    Octstr *dlrmid, *dlrerr;
    Octstr *tmp_string, *retmsg;
    int	mclass, mwi, coding, validity, deferred, dlrmask;
    List *reply_headers;
    int ret;
	
    mclass = mwi = coding = validity = 
        deferred = dlrmask = SMS_PARAM_UNDEFINED;

    user = http_cgi_variable(cgivars, "username");
    pass = http_cgi_variable(cgivars, "password");
    from = http_cgi_variable(cgivars, "from");
    to = http_cgi_variable(cgivars, "to");
    text = http_cgi_variable(cgivars, "text");
    udh = http_cgi_variable(cgivars, "udh");
    charset = http_cgi_variable(cgivars, "charset");
    account = http_cgi_variable(cgivars, "account");
    binfo = http_cgi_variable(cgivars, "binfo");
    dlrmid = http_cgi_variable(cgivars, "dlr-mid");
    tmp_string = http_cgi_variable(cgivars, "flash");
    if (tmp_string) {
        sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
    }
    tmp_string = http_cgi_variable(cgivars, "mclass");
    if (tmp_string) {
        sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
    }
    tmp_string = http_cgi_variable(cgivars, "mwi");
    if (tmp_string) {
        sscanf(octstr_get_cstr(tmp_string),"%d", &mwi);
    }
    tmp_string = http_cgi_variable(cgivars, "coding");
    if (tmp_string) {
        sscanf(octstr_get_cstr(tmp_string),"%d", &coding);
    }
    tmp_string = http_cgi_variable(cgivars, "validity");
    if (tmp_string) {
        sscanf(octstr_get_cstr(tmp_string),"%d", &validity);
    }
    tmp_string = http_cgi_variable(cgivars, "deferred");
    if (tmp_string) {
        sscanf(octstr_get_cstr(tmp_string),"%d", &deferred);
    }
    tmp_string = http_cgi_variable(cgivars, "dlr-mask");
    if (tmp_string) {
        sscanf(octstr_get_cstr(tmp_string),"%d", &dlrmask);
    }
    dlrerr = http_cgi_variable(cgivars, "dlr-err");

    debug("smsc.http.kannel", 0, "HTTP[%s]: Received an HTTP request",
          octstr_get_cstr(conn->id));
    
    if (user == NULL || pass == NULL ||
	    octstr_compare(user, conndata->username) != 0 ||
	    octstr_compare(pass, conndata->password) != 0) {

        error(0, "HTTP[%s]: Authorization failure",
              octstr_get_cstr(conn->id));
        retmsg = octstr_create("Authorization failed for sendsms");
    } else if (dlrmask != 0 && dlrmid != NULL) {
        /* we got a DLR, and we don't require additional values */
        Msg *dlrmsg;
        
        dlrmsg = dlr_find(conn->id,
            dlrmid, /* message id */
            to, /* destination */
            dlrmask, 0);

        if (dlrmsg != NULL) {
            dlrmsg->sms.sms_type = report_mo;
            dlrmsg->sms.msgdata = octstr_duplicate(text);
            dlrmsg->sms.account = octstr_duplicate(conndata->username);

            debug("smsc.http.kannel", 0, "HTTP[%s]: Received DLR for DLR-URL <%s>",
                  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmsg->sms.dlr_url));

            if (dlrerr != NULL) {
                /* pass errorcode as is */
            	if (dlrmsg->sms.meta_data == NULL)
            		dlrmsg->sms.meta_data = octstr_create("");

                meta_data_set_value(dlrmsg->sms.meta_data, METADATA_DLR_GROUP,
                                    octstr_imm(METADATA_DLR_GROUP_ERRORCODE), dlrerr, 1);
            }
            
            ret = bb_smscconn_receive(conn, dlrmsg);
            if (ret == -1)
                retmsg = octstr_create("Not accepted");
            else
                retmsg = octstr_create("Sent.");
        } else {
            error(0,"HTTP[%s]: Got DLR but could not find message or was not interested "
                  "in it id<%s> dst<%s>, type<%d>",
                  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmid),
                  octstr_get_cstr(to), dlrmask);
            retmsg = octstr_create("Unknown DLR, not accepted");
        }                    
    }
    else if (from == NULL || to == NULL || text == NULL) {
	
        error(0, "HTTP[%s]: Insufficient args",
              octstr_get_cstr(conn->id));
        retmsg = octstr_create("Insufficient args, rejected");
    }
    else if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
        error(0, "HTTP[%s]: UDH field misformed, rejected",
              octstr_get_cstr(conn->id));
        retmsg = octstr_create("UDH field misformed, rejected");
    }
    else if (udh != NULL && octstr_len(udh) > MAX_SMS_OCTETS) {
        error(0, "HTTP[%s]: UDH field is too long, rejected",
              octstr_get_cstr(conn->id));
        retmsg = octstr_create("UDH field is too long, rejected");
    }
    else {
        /* we got a normal MO SMS */
        Msg *msg;
        msg = msg_create(sms);

        debug("smsc.http.kannel", 0, "HTTP[%s]: Constructing new SMS",
              octstr_get_cstr(conn->id));
	
        msg->sms.service = octstr_duplicate(user);
        msg->sms.sender = octstr_duplicate(from);
        msg->sms.receiver = octstr_duplicate(to);
        msg->sms.msgdata = octstr_duplicate(text);
        msg->sms.udhdata = octstr_duplicate(udh);

        msg->sms.smsc_id = octstr_duplicate(conn->id);
        msg->sms.time = time(NULL);
        msg->sms.mclass = mclass;
        msg->sms.mwi = mwi;
        msg->sms.coding = coding;
        msg->sms.validity = (validity == SMS_PARAM_UNDEFINED ? validity : time(NULL) + validity * 60);
        msg->sms.deferred = (deferred == SMS_PARAM_UNDEFINED ? deferred : time(NULL) + deferred * 60);
        msg->sms.account = octstr_duplicate(account);
        msg->sms.binfo = octstr_duplicate(binfo);

        /* re-encode content if necessary */
        if (sms_charset_processing(charset, msg->sms.msgdata, msg->sms.coding) == -1) {
            error(0, "HTTP[%s]: Charset or body misformed, rejected",
                  octstr_get_cstr(conn->id));
            retmsg = octstr_create("Charset or body misformed, rejected");
        }
        else {

            ret = bb_smscconn_receive(conn, msg);
            if (ret == -1)
                retmsg = octstr_create("Not accepted");
            else
                retmsg = octstr_create("Sent.");
        }
    }

    reply_headers = gwlist_create();
    http_header_add(reply_headers, "Content-Type", "text/plain");
    debug("smsc.http.kannel", 0, "HTTP[%s]: Sending reply",
          octstr_get_cstr(conn->id));
    http_send_reply(client, HTTP_ACCEPTED, reply_headers, retmsg);

    octstr_destroy(retmsg);
    http_destroy_headers(reply_headers);
}
Ejemplo n.º 3
0
static void main_connection_loop(SMSCConn *conn, Connection *client)
{
    PrivData *privdata = conn->data;
    Octstr *line;
    Msg	*msg;
    double delay = 0;

    if (conn->throughput > 0) {
        delay = 1.0 / conn->throughput;
    }

    while (1) {
        while (!conn->is_stopped && !privdata->shutdown &&
                (line = conn_read_line(client)))
            msg_to_bb(conn, line);
        if (conn_error(client))
            goto error;
        if (conn_eof(client))
            goto eof;

        /* 
         * We won't get DLRs from fakesmsc itself, due that we don't have
         * corresponding message IDs etc. We threat the DLR receiving here. So
         * DLR "originate" from the protocol layer towards abstraction layer.
         * This is all for pure debugging and testing.
         */

        while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {

            /* pass msg to fakesmsc daemon */            
            if (sms_to_client(client, msg) == 1) {
                Msg *copy = msg_duplicate(msg);
                
                /* 
                 * Actually no guarantee of it having been really sent,
                 * but I suppose that doesn't matter since this interface
                 * is just for debugging anyway. The upper layer will send
                 * a SMSC success DLR if mask is set. Be aware that msg is
                 * destroyed in abstraction layer, that's why we use a copy
                 * afterwards to handle the final DLR. 
                 */
                bb_smscconn_sent(conn, msg, NULL);

                /* and now the final DLR */
                if (DLR_IS_SUCCESS_OR_FAIL(copy->sms.dlr_mask)) {
                    Msg *dlrmsg;
                    Octstr *tmp;
                    int dlrstat = DLR_SUCCESS;
                    char id[UUID_STR_LEN + 1];

                    uuid_unparse(copy->sms.id, id);
                    tmp = octstr_create(id);
                    dlrmsg = dlr_find(conn->id,
                                      tmp, /* smsc message id */
                                      copy->sms.receiver, /* destination */
                                      dlrstat, 0);
                    if (dlrmsg != NULL) {
                        /* XXX TODO: Provide a SMPP DLR text in msgdata */
                        bb_smscconn_receive(conn, dlrmsg);
                    } else {
                        error(0,"smsc_fale: got DLR but could not find message or "
                        		"was not interested in it");
                    }
                    octstr_destroy(tmp);
                }
                msg_destroy(copy);

            } else {
                bb_smscconn_send_failed(conn, msg,
		            SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED"));
                goto error;
            }

            /* obey throughput speed limit, if any */
            if (conn->throughput > 0) {
                gwthread_sleep(delay);
            }
        }
        if (privdata->shutdown) {
            debug("bb.sms", 0, "smsc_fake shutting down, closing client socket");
            conn_destroy(client);
            return;
        }
        conn_wait(client, -1);
        if (conn_error(client))
            goto error;
        if (conn_eof(client))
            goto eof;
    }
error:
    info(0, "IO error to fakesmsc client. Closing connection.");
    conn_destroy(client);
    return;
eof:
    info(0, "EOF from fakesmsc client. Closing connection.");
    conn_destroy(client);
    return;
}