Esempio n. 1
0
static int add_msg_cb(SMSCConn *conn, Msg *sms)
{
    PrivData *privdata = conn->data;
    Msg *copy;

    copy = msg_duplicate(sms);
  
    /*  
     * Send DLR if desired, which means first add the DLR entry 
     * and then later find it and remove it. We need to ensure
     * that we put the DLR in first before producing the copy
     * to the list.
     */
    if (DLR_IS_ENABLED_DEVICE(sms->sms.dlr_mask)) {
        Octstr *tmp;
        char id[UUID_STR_LEN + 1];
        uuid_unparse(sms->sms.id, id);
        tmp = octstr_format("%s", id);
        dlr_add(conn->id, tmp, sms, 0);
        octstr_destroy(tmp);
    }
    gwlist_produce(privdata->outgoing_queue, copy);

    gwthread_wakeup(privdata->connection_thread);

    return 0;
}
Esempio n. 2
0
static int wrapper_add_msg(SMSCConn *conn, Msg *sms)
{
    SmscWrapper *wrap = conn->data;
    Msg *copy;

    copy = msg_duplicate(sms);
    gwlist_produce(wrap->outgoing_queue, copy);

    return 0;
}
Esempio n. 3
0
static void bearerbox_to_smsbox(void *arg)
{
    Msg *msg, *msg_escaped;
    Boxc *conn = arg;

    while (sqlbox_status == SQL_RUNNING && conn->alive) {

        msg = read_from_box(conn->bearerbox_connection, conn);

        if (msg == NULL) {
            /* tell sqlbox to die */
            conn->alive = 0;
            debug("sqlbox", 0, "bearerbox_to_smsbox: connection to bearerbox died.");
            break;
        }
        if (msg_type(msg) == admin) {
            if (msg->admin.command == cmd_shutdown || msg->admin.command == cmd_restart) {
                /* tell sqlbox to die */
                conn->alive = 0;
                debug("sqlbox", 0, "bearerbox_to_smsbox: Bearerbox told us to shutdown.");
                break;
            }
        }

        if (msg_type(msg) == heartbeat) {
        // todo
            debug("sqlbox", 0, "bearerbox_to_smsbox: catch an heartbeat - we are alive");
            msg_destroy(msg);
            continue;
        }
        if (!conn->alive) {
            msg_destroy(msg);
            break;
        }
        if (msg_type(msg) == sms) {
            msg_escaped = msg_duplicate(msg);
            if (msg->sms.sms_type != report_mo) {
                if (save_mo) {
                    gw_sql_save_msg(msg_escaped, octstr_imm("MO"));
                }
            }
            else {
                if (save_dlr) {
                    gw_sql_save_msg(msg_escaped, octstr_imm("DLR"));
                }
            }
            msg_destroy(msg_escaped);
        }
        send_msg(conn->smsbox_connection, conn, msg);
        msg_destroy(msg);
    }
    /* the client closes the connection, after that die in receiver */
    conn->alive = 0;
}
Esempio n. 4
0
static void smsbox_to_bearerbox(void *arg)
{
    Boxc *conn = arg;
    Msg *msg, *msg_escaped;

    /* remove messages from socket until it is closed */
    while (sqlbox_status == SQL_RUNNING && conn->alive) {

        //list_consume(suspended);    /* block here if suspended */

        msg = read_from_box(conn->smsbox_connection, conn);

        if (msg == NULL) {    /* garbage/connection lost */
            conn->alive = 0;
            break;
        }

        if (msg_type(msg) == sms) {
            debug("sqlbox", 0, "smsbox_to_bearerbox: sms received");
            if (save_mt) {
                msg_escaped = msg_duplicate(msg);
                /* convert validity & deferred to minutes */
                if (msg_escaped->sms.validity != SMS_PARAM_UNDEFINED)
                    msg_escaped->sms.validity = (msg_escaped->sms.validity - time(NULL))/60;
                if (msg_escaped->sms.deferred != SMS_PARAM_UNDEFINED)
                    msg_escaped->sms.deferred = (msg_escaped->sms.deferred - time(NULL))/60;
                gw_sql_save_msg(msg_escaped, octstr_imm("MT"));
                msg_destroy(msg_escaped);
            }
        }

        send_msg(conn->bearerbox_connection, conn, msg);

        /* if this is an identification message from an smsbox instance */
        if (msg_type(msg) == admin && msg->admin.command == cmd_identify) {
            /*
             * any smsbox sends this command even if boxc_id is NULL,
             * but we will only consider real identified boxes
             */
            if (msg->admin.boxc_id != NULL) {

                /* and add the boxc_id into conn for boxc_status() output */
                conn->boxc_id = msg->admin.boxc_id;
                msg->admin.boxc_id = NULL;

                debug("sqlbox", 0, "smsbox_to_bearerbox: got boxc_id <%s> from <%s>",
                      octstr_get_cstr(conn->boxc_id),
                      octstr_get_cstr(conn->client_ip));
            }
        }
        msg_destroy(msg);
    }
    conn->alive = 0;
}
Esempio n. 5
0
static int cgw_add_msg_cb(SMSCConn *conn, Msg *sms)
{
    PrivData *privdata = conn->data;
    Msg *copy;

    copy = msg_duplicate(sms);
    gwlist_produce(privdata->outgoing_queue, copy);
    gwthread_wakeup(privdata->sender_thread);

    return 0;
}
Esempio n. 6
0
static void boxc_sent_push(Boxc *conn, Msg *m)
{
    Octstr *os;
    char id[UUID_STR_LEN + 1];
    
    if (conn->is_wap || !conn->sent || !m || msg_type(m) != sms)
        return;
    
    uuid_unparse(m->sms.id, id);
    os = octstr_create(id);
    dict_put(conn->sent, os, msg_duplicate(m));
    semaphore_down(conn->pending);
    octstr_destroy(os);
}
Esempio n. 7
0
static int store_to_dict(Msg *msg)
{
    Msg *copy;
    Octstr *uuid_os;
    char id[UUID_STR_LEN + 1];
	
    /* always set msg id and timestamp */
    if (msg_type(msg) == sms && uuid_is_null(msg->sms.id))
        uuid_generate(msg->sms.id);

    if (msg_type(msg) == sms && msg->sms.time == MSG_PARAM_UNDEFINED)
        time(&msg->sms.time);

    if (msg_type(msg) == sms) {
        copy = msg_duplicate(msg);
        
        uuid_unparse(copy->sms.id, id);
        uuid_os = octstr_create(id);
        
        dict_put(sms_dict, uuid_os, copy);
        octstr_destroy(uuid_os);
        last_dict_mod = time(NULL);
    } else if (msg_type(msg) == ack) {
        uuid_unparse(msg->ack.id, id);
        uuid_os = octstr_create(id);
        copy = dict_remove(sms_dict, uuid_os);
        octstr_destroy(uuid_os);
        if (copy == NULL) {
            warning(0, "bb_store: get ACK of message not found "
        	       "from store, strange?");
        } else {
            msg_destroy(copy);
            last_dict_mod = time(NULL);
        }
    } else
        return -1;
    return 0;
}
Esempio n. 8
0
static int httpsmsc_send(SMSCConn *conn, Msg *msg)
{
    ConnData *conndata = conn->data;
    Msg *sms;


    /* don't crash if no send_sms handle defined */
    if (!conndata || !conndata->callbacks->send_sms)
        return -1;

    sms = msg_duplicate(msg);
    /* convert character encoding if required */
    if (msg->sms.coding == DC_7BIT && conndata->alt_charset &&
        charset_convert(sms->sms.msgdata, DEFAULT_CHARSET,
                        octstr_get_cstr(conndata->alt_charset)) != 0) {
        error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.",
              DEFAULT_CHARSET, octstr_get_cstr(conndata->alt_charset));
    }

    gwlist_produce(conndata->msg_to_send, sms);

    return 0;
}
Esempio n. 9
0
int smscconn_send(SMSCConn *conn, Msg *msg)
{
    int ret = -1;
    List *parts = NULL;
    
    gw_assert(conn != NULL);
    mutex_lock(conn->flow_mutex);
    if (conn->status == SMSCCONN_DEAD || conn->why_killed != SMSCCONN_ALIVE) {
        mutex_unlock(conn->flow_mutex);
        return -1;
    }

    /* if this a retry of splitted message, don't unify prefix and don't try to split */
    if (msg->sms.split_parts == NULL) {    
        /* normalize the destination number for this smsc */
        char *uf = conn->unified_prefix ? octstr_get_cstr(conn->unified_prefix) : NULL;
        normalize_number(uf, &(msg->sms.receiver));

        /* split msg */
        parts = sms_split(msg, NULL, NULL, NULL, NULL, 1, 
            counter_increase(split_msg_counter) & 0xff, 0xff, conn->max_sms_octets);
        if (gwlist_len(parts) == 1) {
            /* don't create split_parts of sms fit into one */
            gwlist_destroy(parts, msg_destroy_item);
            parts = NULL;
        }
    }
    
    if (parts == NULL)
        ret = conn->send_msg(conn, msg);
    else {
        long i, parts_len = gwlist_len(parts);
        struct split_parts *split = gw_malloc(sizeof(*split));
         /* must duplicate, because smsc2_route will destroy this msg */
        split->orig = msg_duplicate(msg);
        split->parts_left = counter_create();
        split->status = SMSCCONN_SUCCESS;
        counter_set(split->parts_left, parts_len);
        split->smsc_conn = conn;
        debug("bb.sms.splits", 0, "new split_parts created %p", split);
        for (i = 0; i < parts_len; i++) {
            msg = gwlist_get(parts, i);
            msg->sms.split_parts = split;
            ret = conn->send_msg(conn, msg);
            if (ret < 0) {
                if (i == 0) {
                    counter_destroy(split->parts_left);
                    gwlist_destroy(parts, msg_destroy_item);
                    gw_free(split);
                    mutex_unlock(conn->flow_mutex);
                    return ret;
                }
                /*
                 * Some parts were sent. So handle this within
                 * bb_smscconn_XXX().
                 */
                split->status = SMSCCONN_FAILED_REJECTED;
                counter_increase_with(split->parts_left, -(parts_len - i));
                warning(0, "Could not send all parts of a split message");
                break;
            }
        }
        gwlist_destroy(parts, msg_destroy_item);
    }
    mutex_unlock(conn->flow_mutex);
    return ret;
}
Esempio n. 10
0
static void wrapper_sender(void *arg)
{
    Msg 	*msg;
    SMSCConn 	*conn = arg;
    SmscWrapper *wrap = conn->data;

    /* Make sure we log into our own log-file if defined */
    log_thread_to(conn->log_idx);

    /* send messages to SMSC until our outgoing_list is empty and
     * no producer anymore (we are set to shutdown) */
    while(conn->status != SMSCCONN_DEAD) {

	if ((msg = gwlist_consume(wrap->outgoing_queue)) == NULL)
            break;

        if (octstr_search_char(msg->sms.receiver, ' ', 0) != -1) {
            /*
             * multi-send: this should be implemented in corresponding
             *  SMSC protocol, but while we are waiting for that...
             */
            int i;
	    Msg *newmsg;
            /* split from spaces: in future, split with something more sensible,
             * this is dangerous... (as space is url-encoded as '+')
             */
            List *nlist = octstr_split_words(msg->sms.receiver);

	    debug("bb.sms", 0, "Handling multi-receiver message");

            for(i=0; i < gwlist_len(nlist); i++) {

		newmsg = msg_duplicate(msg);
                octstr_destroy(newmsg->sms.receiver);

                newmsg->sms.receiver = gwlist_get(nlist, i);
                sms_send(conn, newmsg);
            }
            gwlist_destroy(nlist, NULL);
            msg_destroy(msg);
        }
        else
	    sms_send(conn,msg);

    }
    /* cleanup, we are now dying */

    debug("bb.sms", 0, "SMSCConn %s sender died, waiting for receiver",
	  octstr_get_cstr(conn->name));
    
    conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;

    if (conn->is_stopped) {
	gwlist_remove_producer(wrap->stopped);
	conn->is_stopped = 0;
    }

    gwthread_wakeup(wrap->receiver_thread);
    gwthread_join(wrap->receiver_thread);

    /* call 'failed' to all messages still in queue */
    
    mutex_lock(conn->flow_mutex);

    conn->status = SMSCCONN_DEAD;

    while((msg = gwlist_extract_first(wrap->outgoing_queue))!=NULL) {
	bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
    }
    smscwrapper_destroy(wrap);
    conn->data = NULL;
    
    mutex_unlock(conn->flow_mutex);

    bb_smscconn_killed();
}
Esempio n. 11
0
enum fsm_event e2e_event(struct port *p, int fd_index)
{
	int cnt, fd = p->fda.fd[fd_index];
	enum fsm_event event = EV_NONE;
	struct ptp_message *msg, *dup;

	switch (fd_index) {
	case FD_ANNOUNCE_TIMER:
	case FD_SYNC_RX_TIMER:
		pr_debug("port %hu: %s timeout", portnum(p),
			 fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce");
		if (p->best) {
			fc_clear(p->best);
		}
		port_set_announce_tmo(p);
		return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;

	case FD_DELAY_TIMER:
		pr_debug("port %hu: delay timeout", portnum(p));
		port_set_delay_tmo(p);
		delay_req_prune(p);
		tc_prune(p);
		if (!clock_free_running(p->clock)) {
			switch (p->state) {
			case PS_UNCALIBRATED:
			case PS_SLAVE:
				if (port_delay_request(p)) {
					event = EV_FAULT_DETECTED;
				}
				break;
			default:
				break;
			};
		}
		return event;

	case FD_QUALIFICATION_TIMER:
		pr_debug("port %hu: qualification timeout", portnum(p));
		return EV_QUALIFICATION_TIMEOUT_EXPIRES;

	case FD_MANNO_TIMER:
	case FD_SYNC_TX_TIMER:
	case FD_UNICAST_REQ_TIMER:
	case FD_UNICAST_SRV_TIMER:
		pr_err("unexpected timer expiration");
		return EV_NONE;

	case FD_RTNL:
		pr_debug("port %hu: received link status notification", portnum(p));
		rtnl_link_status(fd, p->name, port_link_status, p);
		if (p->link_status == (LINK_UP|LINK_STATE_CHANGED)) {
			return EV_FAULT_CLEARED;
		} else if ((p->link_status == (LINK_DOWN|LINK_STATE_CHANGED)) ||
			   (p->link_status & TS_LABEL_CHANGED)) {
			return EV_FAULT_DETECTED;
		} else {
			return EV_NONE;
		}
	}

	msg = msg_allocate();
	if (!msg) {
		return EV_FAULT_DETECTED;
	}
	msg->hwts.type = p->timestamping;

	cnt = transport_recv(p->trp, fd, msg);
	if (cnt <= 0) {
		pr_err("port %hu: recv message failed", portnum(p));
		msg_put(msg);
		return EV_FAULT_DETECTED;
	}
	if (msg_sots_valid(msg)) {
		ts_add(&msg->hwts.ts, -p->rx_timestamp_offset);
	}
	if (msg_unicast(msg)) {
		pl_warning(600, "cannot handle unicast messages!");
		msg_put(msg);
		return EV_NONE;
	}

	dup = msg_duplicate(msg, cnt);
	if (!dup) {
		msg_put(msg);
		return EV_NONE;
	}
	if (tc_ignore(p, dup)) {
		msg_put(dup);
		dup = NULL;
	}

	switch (msg_type(msg)) {
	case SYNC:
		if (tc_fwd_sync(p, msg)) {
			event = EV_FAULT_DETECTED;
			break;
		}
		if (dup) {
			process_sync(p, dup);
		}
		break;
	case DELAY_REQ:
		if (tc_fwd_request(p, msg)) {
			event = EV_FAULT_DETECTED;
		}
		break;
	case PDELAY_REQ:
		break;
	case PDELAY_RESP:
		break;
	case FOLLOW_UP:
		if (tc_fwd_folup(p, msg)) {
			event = EV_FAULT_DETECTED;
			break;
		}
		if (dup) {
			process_follow_up(p, dup);
		}
		break;
	case DELAY_RESP:
		if (tc_fwd_response(p, msg)) {
			event = EV_FAULT_DETECTED;
		}
		if (dup) {
			process_delay_resp(p, dup);
		}
		break;
	case PDELAY_RESP_FOLLOW_UP:
		break;
	case ANNOUNCE:
		if (tc_forward(p, msg)) {
			event = EV_FAULT_DETECTED;
			break;
		}
		if (dup && process_announce(p, dup)) {
			event = EV_STATE_DECISION_EVENT;
		}
		break;
	case SIGNALING:
	case MANAGEMENT:
		if (tc_forward(p, msg)) {
			event = EV_FAULT_DETECTED;
		}
		break;
	}

	msg_put(msg);
	if (dup) {
		msg_put(dup);
	}
	return event;
}
Esempio n. 12
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;
}