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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
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(); }
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; }
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; }