static void smsbox_thread(void *arg) { Connection *conn; Msg *msg; Octstr *os; Octstr *reply_msg; unsigned long count; msg = msg_create(sms); msg->sms.sender = octstr_create("123"); msg->sms.receiver = octstr_create("456"); msg->sms.msgdata = octstr_create("hello world"); reply_msg = msg_pack(msg); msg_destroy(msg); gwthread_sleep(1.0); conn = conn_open_tcp(bearerbox_host, port_for_smsbox, NULL); if (conn == NULL) { gwthread_sleep(2.0); conn = conn_open_tcp(bearerbox_host, port_for_smsbox, NULL); if (conn == NULL) panic(0, "Couldn't connect to bearerbox as smsbox"); } while (!quitting && conn_wait(conn, -1.0) != -1) { for (;;) { os = conn_read_withlen(conn); if (os == NULL) { if (conn_eof(conn) || conn_error(conn)) goto error; break; } msg = msg_unpack(os); if (msg == NULL || msg->type == wdp_datagram) error(0, "Bearerbox sent garbage to smsbox"); if (msg->type == sms) { if (first_from_bb == (time_t) -1) time(&first_from_bb); count = counter_increase(num_from_bearerbox) + 1; debug("test.smpp", 0, "Bearerbox sent sms #%ld <%s> to smsbox, sending reply.", count, octstr_get_cstr(msg->sms.msgdata)); if (count == max_to_esme) info(0, "Bearerbox has sent all messages to smsbox."); conn_write_withlen(conn, reply_msg); counter_increase(num_to_bearerbox); } msg_destroy(msg); octstr_destroy(os); time(&last_to_bb); } } error: conn_destroy(conn); octstr_destroy(reply_msg); debug("test.smpp", 0, "%s terminates.", __func__); }
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_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 ; }
static void receive_smpp_thread(void *arg) { ESME *esme; Octstr *os; long len; long sender_id; SMPP_PDU *pdu; esme = arg; sender_id = -1; len = 0; while (!quitting && conn_wait(esme->conn, -1.0) != -1) { for (;;) { if (len == 0) { len = smpp_pdu_read_len(esme->conn); if (len == -1) { error(0, "Client sent garbage, closing connection."); goto error; } else if (len == 0) { if (conn_eof(esme->conn) || conn_error(esme->conn)) goto error; break; } } gw_assert(len > 0); os = smpp_pdu_read_data(esme->conn, len); if (os != NULL) { len = 0; pdu = smpp_pdu_unpack(NULL, os); if (pdu == NULL) { error(0, "PDU unpacking failed!"); octstr_dump(os, 0); } else { handle_pdu(esme, pdu); smpp_pdu_destroy(pdu); } octstr_destroy(os); } else if (conn_eof(esme->conn) || conn_error(esme->conn)) goto error; else break; } if (!quitting && esme->receiver && sender_id == -1) sender_id = gwthread_create(send_smpp_thread, esme); } error: if (sender_id != -1) { quit(); gwthread_join(sender_id); } esme_destroy(esme); quit(); debug("test.smpp", 0, "%s terminates.", __func__); }
int read_from_bearerbox_real(Connection *conn, Msg **msg, double seconds) { int ret; Octstr *pack; pack = NULL; *msg = NULL; while (program_status != shutting_down) { pack = conn_read_withlen(conn); gw_claim_area(pack); if (pack != NULL) break; if (conn_error(conn)) { error(0, "Error reading from bearerbox, disconnecting."); return -1; } if (conn_eof(conn)) { error(0, "Connection closed by the bearerbox."); return -1; } ret = conn_wait(conn, seconds); if (ret < 0) { error(0, "Connection to bearerbox broke."); return -1; } else if (ret == 1) { /* debug("gwlib.gwlib", 0, "Connection to bearerbox timed out after %.2f seconds.", seconds); */ return 1; } } if (pack == NULL) return -1; *msg = msg_unpack(pack); octstr_destroy(pack); if (*msg == NULL) { error(0, "Failed to unpack data!"); return -1; } return 0; }
static Msg *read_from_box(Boxc *boxconn) { int ret; Octstr *pack; Msg *msg; pack = NULL; while (bb_status != BB_DEAD && boxconn->alive) { /* XXX: if box doesn't send (just keep conn open) we block here while shutdown */ pack = conn_read_withlen(boxconn->conn); gw_claim_area(pack); if (pack != NULL) break; if (conn_error(boxconn->conn)) { info(0, "Read error when reading from box <%s>, disconnecting", octstr_get_cstr(boxconn->client_ip)); return NULL; } if (conn_eof(boxconn->conn)) { info(0, "Connection closed by the box <%s>", octstr_get_cstr(boxconn->client_ip)); return NULL; } ret = conn_wait(boxconn->conn, -1.0); if (ret < 0) { error(0, "Connection to box <%s> broke.", octstr_get_cstr(boxconn->client_ip)); return NULL; } } if (pack == NULL) return NULL; msg = msg_unpack(pack); octstr_destroy(pack); if (msg == NULL) error(0, "Failed to unpack data!"); return msg; }
int cgw_wait_command(PrivData *privdata, SMSCConn *conn, Connection *server, int timeout) { int ret; struct cgwop *cgwop; /* is there data to be read? */ ret = gwthread_pollfd(privdata->send_socket, POLLIN, 0.2); if (ret != -1) { /* read all waiting ops */ cgwop = cgw_read_op(privdata, conn, server, timeout); if (cgwop != NULL) { do { if (conn_eof(server)) { info(0, "cgw: Connection closed by SMSC"); conn->status = SMSCCONN_DISCONNECTED; if (cgwop != NULL) cgwop_destroy(cgwop); return -1; } if (conn_error(server)) { error(0, "cgw: Error trying to read ACKs from SMSC"); if (cgwop != NULL) cgwop_destroy(cgwop); return -1; } cgw_handle_op(conn, server, cgwop); cgwop_destroy(cgwop); } while ((cgwop = cgw_read_op(privdata, conn, server, timeout)) != NULL); } else conn_wait(server, 1); /* added because gwthread_pollfd seems to always return 1. This will keep the load on a reasonable level */ } return 0; }
/* The main program. */ int main(int argc, char **argv) { Connection *server; Octstr *line; Octstr **msgs; int i; int mptr, num_msgs; long num_received, num_sent; double first_received_at, last_received_at; double first_sent_at, last_sent_at; double start_time, end_time; double delta; int interactive, maxfd; char *cptr; char buffer[IN_BUFSIZE]; fd_set rset; struct timeval alarm; FILE *fp; gwlib_init(); setup_signal_handlers(); host = octstr_create("localhost"); start_time = get_current_time(); mptr = get_and_set_debugs(argc, argv, check_args); num_msgs = argc - mptr; interactive = 0; msgs = NULL; fp = NULL; if (num_msgs <= 0) { interactive = 1; num_msgs = 0; info(0, "Entering interactive mode. Type your message on the command line"); /* set up file pointer to stdin */ fp = stdin; /* initialize set for select */ FD_ZERO(&rset); } else { msgs = gw_malloc(sizeof(Octstr *) * num_msgs); for (i = 0; i < num_msgs; i ++) { msgs[i] = octstr_create(argv[mptr + i]); octstr_append_char(msgs[i], 10); /* End of line */ } info(0, "Host %s Port %d interval %.3f max-messages %ld", octstr_get_cstr(host), port, interval, max_send); srand((unsigned int) time(NULL)); } info(0, "fakesmsc starting"); server = conn_open_tcp(host, port, NULL); if (server == NULL) panic(0, "Failed to open connection"); num_sent = 0; num_received = 0; first_received_at = 0; first_sent_at = 0; last_received_at = 0; last_sent_at = 0; /* infinitely loop */ while (1) { /* Are we on interactive mode? */ if (interactive == 1) { /* Check if we need to clean things up beforehand */ if ( num_msgs > 0 ) { for (i = 0; i < num_msgs; i ++) octstr_destroy(msgs[i]); gw_free(msgs); num_msgs = 0; } /* we want either the file pointer or timer */ FD_SET(fileno(fp), &rset); /* get the largest file descriptor */ maxfd = fileno(fp) + 1; /* set timer to go off in 3 seconds */ alarm.tv_sec = IN_TIMEOUT; alarm.tv_usec = 0; if (select(maxfd, &rset, NULL, NULL, &alarm) == -1) goto over; /* something went off, let's see if it's stdin */ if (FD_ISSET(fileno(fp), &rset)) { /* stdin is readable */ cptr = fgets(buffer, IN_BUFSIZE, stdin); if( strlen( cptr ) < 2 ) goto rcv; } else { /* timer kicked in */ goto rcv; } num_msgs = 1; msgs = gw_malloc(sizeof(Octstr*)); msgs[0] = octstr_create(cptr); } /* if we still have something to send as MO message */ if (num_sent < max_send) { Octstr *os = choose_message(msgs, num_msgs); Octstr *msg = rnd > 0 ? randomize(os) : os; if (conn_write(server, msg) == -1) panic(0, "write failed"); ++num_sent; if (num_sent == max_send) info(0, "fakesmsc: sent message %ld", num_sent); else debug("send", 0, "fakesmsc: sent message %ld", num_sent); if (rnd > 0) octstr_destroy(msg); last_sent_at = get_current_time(); if (first_sent_at == 0) first_sent_at = last_sent_at; } rcv: do { delta = interval * num_sent - (get_current_time() - first_sent_at); if (delta < 0) delta = 0; if (num_sent >= max_send) delta = -1; conn_wait(server, delta); if (conn_error(server) || conn_eof(server) || sigint_received) goto over; /* read as much as the smsc module provides us */ while ((line = conn_read_line(server))) { last_received_at = get_current_time(); if (first_received_at == 0) first_received_at = last_received_at; ++num_received; if (num_received == max_send) { info(0, "Got message %ld: <%s>", num_received, octstr_get_cstr(line)); } else { debug("receive", 0, "Got message %ld: <%s>", num_received, octstr_get_cstr(line)); } octstr_destroy(line); } } while (delta > 0 || num_sent >= max_send); } over: conn_destroy(server); /* destroy the MO messages */ for (i = 0; i < num_msgs; i ++) octstr_destroy(msgs[i]); gw_free(msgs); end_time = get_current_time(); info(0, "fakesmsc: %ld messages sent and %ld received", num_sent, num_received); info(0, "fakesmsc: total running time %.1f seconds", end_time - start_time); delta = last_sent_at - first_sent_at; if (delta == 0) delta = .01; if (num_sent > 1) info(0, "fakesmsc: from first to last sent message %.1f s, " "%.1f msgs/s", delta, (num_sent - 1) / delta); delta = last_received_at - first_received_at; if (delta == 0) delta = .01; if (num_received > 1) info(0, "fakesmsc: from first to last received message %.1f s, " "%.1f msgs/s", delta, (num_received - 1) / delta); info(0, "fakesmsc: terminating"); return 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; }