#include <sys/types.h>#include <sys/socket.h>#include <unistd.h>#include <errno.h>#include <time.h>#include <limits.h>#include <float.h>#include "gwlib/gwlib.h"#include "smscconn.h"#include "smscconn_p.h"#include "bb_smscconn_cb.h"#include "msg.h"#include "sms.h"#include "emimsg.h"#include "dlr.h"#include "alt_charsets.h"Include dependency graph for smsc_emi.c:

Go to the source code of this file.
|
|
Value: ((PRIVDATA(conn)->unacked == 0) && \ (PRIVDATA(conn)->idle_timeout ? \ (PRIVDATA(conn)->last_activity_time + PRIVDATA(conn)->idle_timeout) <= time(0):0)) Definition at line 148 of file smsc_emi.c. Referenced by emi2_idletimeout_handling(). |
|
|
Value: ((PRIVDATA(conn)->can_write || !PRIVDATA(conn)->flowcontrol) && \ (PRIVDATA(conn)->unacked < PRIVDATA(conn)->window) && \ (!PRIVDATA(conn)->shutdown)) Definition at line 153 of file smsc_emi.c. Referenced by emi2_do_send(), and emi2_wait(). |
|
|
Definition at line 93 of file smsc_emi.c. Referenced by smsc_emi2_create(). |
|
|
Value: (emi2_can_send(conn) && \ (PRIVDATA(conn)->keepalive > 0) && \ (time(NULL) > (PRIVDATA(conn)->last_activity_time + PRIVDATA(conn)->keepalive))) Definition at line 158 of file smsc_emi.c. Referenced by emi2_send_loop(). |
|
|
Referenced by emi2_next_trn(). |
|
|
Definition at line 144 of file smsc_emi.c. Referenced by emi2_do_send(), emi2_emimsg_send(), emi2_get_timeouttime(), emi2_handle_smscreq(), emi2_idleprocessing(), emi2_keepalive_handling(), emi2_next_trn(), emi2_send_loop(), emi2_wait(), and handle_operation(). |
|
|
Definition at line 146 of file smsc_emi.c. Referenced by emi2_handle_smscreq(), emi2_idleprocessing(), and emi2_next_trn(). |
|
|
|
|
|
Definition at line 137 of file smsc_emi.c. Referenced by emi2_send_loop(), and emi2_wait(). 00137 {
00138 EMI2_SENDREQ, /* somebody asked this driver to send a SMS message */
00139 EMI2_SMSCREQ, /* the SMSC wants something from us */
00140 EMI2_CONNERR, /* an error condition in the SMSC main connection */
00141 EMI2_TIMEOUT, /* timeout on the SMSC main connection */
00142 } EMI2Event;
|
|
||||||||||||
|
Definition at line 1546 of file smsc_emi.c. References smscconn::data, gw_prioqueue_produce, gwthread_wakeup(), msg_duplicate(), privdata::outgoing_queue, PrivData, privdata::sender_thread, sms, and SMSCConn. 01547 {
01548 PrivData *privdata = conn->data;
01549 Msg *copy;
01550
01551 copy = msg_duplicate(sms);
01552 gw_prioqueue_produce(privdata->outgoing_queue, copy);
01553 gwthread_wakeup(privdata->sender_thread);
01554
01555 return 0;
01556 }
|
Here is the call graph for this function:

|
|
Definition at line 921 of file smsc_emi.c. References debug(), gw_prioqueue_produce, privdata::name, octstr_get_cstr, privdata::outgoing_queue, PrivData, privdata::sendmsg, privdata::sendtime, privdata::sendtype, privdata::slots, and privdata::unacked. Referenced by emi2_sender(). 00922 {
00923 int i;
00924 debug("smsc.emi2", 0, "EMI2[%s]: clear_sent called",
00925 octstr_get_cstr(privdata->name));
00926 for (i = 0; i < EMI2_MAX_TRN; i++) {
00927 if (privdata->slots[i].sendtime && privdata->slots[i].sendtype == 51)
00928 gw_prioqueue_produce(privdata->outgoing_queue, privdata->slots[i].sendmsg);
00929 privdata->slots[i].sendtime = 0;
00930 }
00931 privdata->unacked = 0;
00932 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1005 of file smsc_emi.c. References emi2_can_send, emi2_emimsg_send(), emi2_next_trn(), emimsg_destroy(), gw_prioqueue_remove(), gwthread_sleep(), msg_to_emimsg(), PRIVDATA, SMSCConn, and smscconn::throughput. Referenced by emi2_send_loop(). 01006 {
01007 struct emimsg *emimsg;
01008 Msg *msg;
01009 double delay = 0;
01010
01011 if (conn->throughput > 0) {
01012 delay = 1.0 / conn->throughput;
01013 }
01014
01015 /* Send messages if there's room in the sending window */
01016 while (emi2_can_send(conn) &&
01017 (msg = gw_prioqueue_remove(PRIVDATA(conn)->outgoing_queue)) != NULL) {
01018 int nexttrn = emi2_next_trn(conn);
01019
01020 if (conn->throughput > 0)
01021 gwthread_sleep(delay);
01022
01023 /* convert the generic Kannel message into an EMI type message */
01024 emimsg = msg_to_emimsg(msg, nexttrn, PRIVDATA(conn));
01025
01026 /* remember the message for retransmission or DLR */
01027 PRIVDATA(conn)->slots[nexttrn].sendmsg = msg;
01028 PRIVDATA(conn)->slots[nexttrn].sendtype = 51;
01029 PRIVDATA(conn)->slots[nexttrn].sendtime = time(NULL);
01030
01031 /* send the message */
01032 if (emi2_emimsg_send(conn, server, emimsg) == -1) {
01033 emimsg_destroy(emimsg);
01034 return -1;
01035 }
01036
01037 /* we just sent a message */
01038 PRIVDATA(conn)->unacked++;
01039
01040 emimsg_destroy(emimsg);
01041
01042 /*
01043 * remember that there is an open request for stop-wait flow control
01044 * FIXME: couldn't this be done with the unacked field as well? After
01045 * all stop-wait is just a window of size 1.
01046 */
01047 PRIVDATA(conn)->can_write = 0;
01048 }
01049
01050 return 0;
01051 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 166 of file smsc_emi.c. References emimsg_send(), name, emimsg::or, emimsg::ot, PRIVDATA, result, and SMSCConn. Referenced by emi2_do_send(), emi2_keepalive_handling(), handle_operation(), and open_send_connection(). 00167 {
00168 int result = emimsg_send(server, emimsg, PRIVDATA(conn)->name);
00169
00170 if (result >= 0 && emimsg->or == 'O' && ( emimsg->ot == 31 || emimsg->ot == 51)) {
00171 PRIVDATA(conn)->last_activity_time = time (NULL);
00172 }
00173
00174 return result;
00175 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1270 of file smsc_emi.c. References PRIVDATA, result, and SMSCConn. Referenced by emi2_send_loop(). 01271 {
01272 double ka_timeouttime = PRIVDATA(conn)->keepalive ? PRIVDATA(conn)->keepalive + 1 : DBL_MAX;
01273 double idle_timeouttime = (PRIVDATA(conn)->idle_timeout && server) ? PRIVDATA(conn)->idle_timeout : DBL_MAX;
01274 double result = ka_timeouttime < idle_timeouttime ? ka_timeouttime : idle_timeouttime;
01275
01276 if (result == DBL_MAX)
01277 result = 30;
01278
01279 return result;
01280 }
|
|
||||||||||||
|
Definition at line 1053 of file smsc_emi.c. References bb_smscconn_send_failed(), bb_smscconn_sent(), conn_eof(), conn_error(), conn_read_packet(), smscconn::data, debug(), dlr_add(), DLR_IS_ENABLED_DEVICE, emimsg_destroy(), error(), emimsg::fields, get_fields(), handle_operation(), smscconn::id, info(), smscconn::is_stopped, m, privdata::name, octstr_append(), octstr_append_char(), octstr_create, octstr_delete(), octstr_destroy(), octstr_duplicate, octstr_get_char(), octstr_get_cstr, octstr_len(), octstr_search_char(), octstr_truncate(), emimsg::or, emimsg::ot, panic, PRIVDATA, PrivData, SLOTBUSY, SMSCConn, SMSCCONN_FAILED_REJECTED, and emimsg::trn. Referenced by emi2_send_loop(). 01054 {
01055 Octstr *str;
01056 struct emimsg *emimsg;
01057 PrivData *privdata = conn->data;
01058
01059 /* Read acks/nacks/ops from the server */
01060 while ((str = conn_read_packet(server, 2, 3))) {
01061 debug("smsc.emi2", 0, "EMI2[%s]: Got packet from the main socket",
01062 octstr_get_cstr(privdata->name));
01063
01064 /* parse the msg */
01065 emimsg = get_fields(str, privdata->name);
01066 octstr_destroy(str);
01067
01068 if (emimsg == NULL) {
01069 continue; /* The parse functions logged errors */
01070 }
01071
01072 if (emimsg->or == 'O') {
01073 /* If the SMSC wants to send operations through this
01074 * socket, we'll have to read them because there
01075 * might be ACKs too. We just drop them while stopped,
01076 * hopefully the SMSC will resend them later. */
01077 if (!conn->is_stopped) {
01078 if (handle_operation(conn, server, emimsg) < 0)
01079 return -1; /* Connection broke */
01080 } else {
01081 info(0, "EMI2[%s]: Ignoring operation from main socket "
01082 "because the connection is stopped.",
01083 octstr_get_cstr(privdata->name));
01084 }
01085 } else { /* Already checked to be 'O' or 'R' */
01086 if (!SLOTBUSY(conn,emimsg->trn) ||
01087 emimsg->ot != PRIVDATA(conn)->slots[emimsg->trn].sendtype) {
01088 error(0, "EMI2[%s]: Got ack for TRN %d, don't remember sending O?",
01089 octstr_get_cstr(privdata->name), emimsg->trn);
01090 } else {
01091 PRIVDATA(conn)->can_write = 1;
01092 PRIVDATA(conn)->slots[emimsg->trn].sendtime = 0;
01093 PRIVDATA(conn)->unacked--;
01094
01095 if (emimsg->ot == 51) {
01096 if (octstr_get_char(emimsg->fields[0], 0) == 'A') {
01097 /* we got an ack back. We might have to store the */
01098 /* timestamp for delivery notifications now */
01099 Octstr *ts, *adc;
01100 int i;
01101 Msg *m;
01102
01103 ts = octstr_duplicate(emimsg->fields[2]);
01104 if (octstr_len(ts)) {
01105 i = octstr_search_char(ts,':',0);
01106 if (i>0) {
01107 octstr_delete(ts,0,i+1);
01108 adc = octstr_duplicate(emimsg->fields[2]);
01109 octstr_truncate(adc,i);
01110
01111 m = PRIVDATA(conn)->slots[emimsg->trn].sendmsg;
01112 if(m == NULL) {
01113 info(0,"EMI2[%s]: uhhh m is NULL, very bad",
01114 octstr_get_cstr(privdata->name));
01115 } else if (DLR_IS_ENABLED_DEVICE(m->sms.dlr_mask)) {
01116 dlr_add((conn->id ? conn->id : privdata->name), ts, m);
01117 }
01118 octstr_destroy(ts);
01119 octstr_destroy(adc);
01120 } else {
01121 octstr_destroy(ts);
01122 }
01123 }
01124 /*
01125 * report the successful transmission to the generic bb code.
01126 */
01127 bb_smscconn_sent(conn,
01128 PRIVDATA(conn)->slots[emimsg->trn].sendmsg,
01129 NULL);
01130 } else {
01131 Octstr *reply;
01132
01133 /* create reply message */
01134 reply = octstr_create("");
01135 octstr_append(reply, emimsg->fields[1]);
01136 octstr_append_char(reply, '-');
01137 /* system message is optional */
01138 if (emimsg->fields[2] != NULL)
01139 octstr_append(reply, emimsg->fields[2]);
01140
01141 /* XXX Process error code here
01142 long errorcode;
01143 octstr_parse_long(&errorcode, emimsg->fields[1], 0, 10);
01144 ... switch(errorcode) ...
01145 }
01146
01147 else { */
01148 bb_smscconn_send_failed(conn,
01149 PRIVDATA(conn)->slots[emimsg->trn].sendmsg,
01150 SMSCCONN_FAILED_REJECTED, reply);
01151 /* } */
01152 }
01153 } else if (emimsg->ot == 31) {
01154 /* XXX Process error codes here
01155 if (octstr_get_char(emimsg->fields[0], 0) == 'N') {
01156 long errorcode;
01157 octstr_parse_long(&errorcode, emimsg->fields[1], 0, 10);
01158 ... switch errorcode ...
01159 }
01160
01161 else { */
01162 ;
01163 /* } */
01164 } else {
01165 panic(0, "EMI2[%s]: Bug, ACK handler missing for sent packet",
01166 octstr_get_cstr(privdata->name));
01167 }
01168 }
01169 }
01170 emimsg_destroy(emimsg);
01171 }
01172
01173 if (conn_error(server)) {
01174 error(0, "EMI2[%s]: Error trying to read ACKs from SMSC",
01175 octstr_get_cstr(privdata->name));
01176 return -1;
01177 }
01178
01179 if (conn_eof(server)) {
01180 info(0, "EMI2[%s]: Main connection closed by SMSC",
01181 octstr_get_cstr(privdata->name));
01182 return -1;
01183 }
01184
01185 return 0;
01186 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1188 of file smsc_emi.c. References conn_destroy(), smscconn::data, gw_prioqueue_produce, gwthread_wakeup(), info(), privdata::name, octstr_get_cstr, panic, PRIVDATA, PrivData, SLOTBUSY, SMSCConn, and warning(). Referenced by emi2_send_loop(). 01189 {
01190 time_t current_time;
01191 int i;
01192 PrivData *privdata = conn->data;
01193
01194 /*
01195 * Check whether there are messages the server hasn't acked in a
01196 * reasonable time
01197 */
01198 current_time = time(NULL);
01199
01200 if (PRIVDATA(conn)->unacked && (current_time > (PRIVDATA(conn)->check_time + 30))) {
01201 PRIVDATA(conn)->check_time = current_time;
01202 for (i = 0; i < PRIVDATA(conn)->window; i++) {
01203 if (SLOTBUSY(conn,i)
01204 && PRIVDATA(conn)->slots[i].sendtime < (current_time - PRIVDATA(conn)->waitack)) {
01205
01206 if (PRIVDATA(conn)->slots[i].sendtype == 51) {
01207 if (PRIVDATA(conn)->waitack_expire == 0x00) {
01208 /* 0x00 - disconnect/reconnect */
01209 warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
01210 "in %d seconds, disconnecting and reconnection",
01211 octstr_get_cstr(privdata->name), i, PRIVDATA(conn)->waitack);
01212 PRIVDATA(conn)->slots[i].sendtime = 0;
01213 PRIVDATA(conn)->unacked--;
01214 info(0, "EMI2[%s]: closing connection.",
01215 octstr_get_cstr(privdata->name));
01216 conn_destroy(*server);
01217 *server = NULL;
01218 break;
01219 } else if (PRIVDATA(conn)->waitack_expire == 0x01) {
01220 /* 0x01 - resend */
01221 warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
01222 "in %d seconds, resending message", octstr_get_cstr(privdata->name),
01223 i, PRIVDATA(conn)->waitack);
01224 gw_prioqueue_produce(PRIVDATA(conn)->outgoing_queue,
01225 PRIVDATA(conn)->slots[i].sendmsg);
01226 PRIVDATA(conn)->slots[i].sendtime = 0;
01227 PRIVDATA(conn)->unacked--;
01228 if (PRIVDATA(conn)->flowcontrol) PRIVDATA(conn)->can_write=1;
01229 /* Wake up this same thread to send again
01230 * (simpler than avoiding sleep) */
01231 gwthread_wakeup(PRIVDATA(conn)->sender_thread);
01232 } else if (PRIVDATA(conn)->waitack_expire == 0x02) {
01233 /* 0x02 - carry on waiting */
01234 warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
01235 "in %d seconds, carrying on waiting", octstr_get_cstr(privdata->name),
01236 i, PRIVDATA(conn)->waitack);
01237 }
01238 } else if (PRIVDATA(conn)->slots[i].sendtype == 31) {
01239 warning(0, "EMI2[%s]: Alert (operation 31) was not "
01240 "ACKed within %d seconds", octstr_get_cstr(privdata->name),
01241 PRIVDATA(conn)->waitack);
01242 if (PRIVDATA(conn)->flowcontrol) PRIVDATA(conn)->can_write=1;
01243 } else {
01244 panic(0, "EMI2[%s]: Bug, no timeout handler for sent packet",
01245 octstr_get_cstr(privdata->name));
01246 }
01247 }
01248 }
01249 }
01250 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1252 of file smsc_emi.c. References conn_destroy(), CONNECTIONIDLE, smscconn::data, info(), privdata::name, octstr_get_cstr, PrivData, and SMSCConn. Referenced by emi2_send_loop(). 01253 {
01254 PrivData *privdata = conn->data;
01255
01256 /*
01257 * close the connection if there was no activity.
01258 */
01259 if ((*server != NULL) && CONNECTIONIDLE(conn)) {
01260 info(0, "EMI2[%s]: closing idle connection.",
01261 octstr_get_cstr(privdata->name));
01262 conn_destroy(*server);
01263 *server = NULL;
01264 }
01265 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 978 of file smsc_emi.c. References emi2_emimsg_send(), emi2_next_trn(), emimsg_destroy(), make_emi31(), PRIVDATA, and SMSCConn. Referenced by emi2_send_loop(). 00979 {
00980 struct emimsg *emimsg;
00981 int nexttrn = emi2_next_trn (conn);
00982
00983 emimsg = make_emi31(PRIVDATA(conn), nexttrn);
00984 if(emimsg) {
00985 PRIVDATA(conn)->slots[nexttrn].sendtype= 31;
00986 PRIVDATA(conn)->slots[nexttrn].sendtime = time(NULL);
00987 PRIVDATA(conn)->unacked++;
00988
00989 if (emi2_emimsg_send(conn, server, emimsg) == -1) {
00990 emimsg_destroy(emimsg);
00991 return -1;
00992 }
00993 emimsg_destroy(emimsg);
00994 }
00995
00996 PRIVDATA(conn)->can_write = 0;
00997
00998 return 0;
00999 }
|
Here is the call graph for this function:

|
|
Definition at line 1479 of file smsc_emi.c. References privdata::allow_ip, conn_claim(), conn_destroy(), conn_wrap_fd(), smscconn::data, privdata::deny_ip, emi2_receiver(), error(), gwthread_pollfd(), gwthread_wakeup(), host_ip(), info(), is_allowed_ip(), privdata::listening_socket, smscconn::log_idx, log_thread_to(), privdata::name, octstr_destroy(), octstr_get_cstr, POLLIN, PrivData, privdata::sender_thread, privdata::shutdown, SMSCConn, and warning(). Referenced by smsc_emi2_create(). 01480 {
01481 SMSCConn *conn = arg;
01482 PrivData *privdata = conn->data;
01483 struct sockaddr_in server_addr;
01484 socklen_t server_addr_len;
01485 Octstr *ip;
01486 Connection *server;
01487 int s, ret;
01488
01489 /* Make sure we log into our own log-file if defined */
01490 log_thread_to(conn->log_idx);
01491
01492 while (!privdata->shutdown) {
01493 server_addr_len = sizeof(server_addr);
01494 ret = gwthread_pollfd(privdata->listening_socket, POLLIN, -1);
01495 if (ret == -1) {
01496 if (errno == EINTR)
01497 continue;
01498 error(0, "EMI2[%s]: Poll for emi2 smsc connections failed, shutting down",
01499 octstr_get_cstr(privdata->name));
01500 break;
01501 }
01502 if (privdata->shutdown)
01503 break;
01504 if (ret == 0) /* This thread was woken up from elsewhere, but
01505 if we're not shutting down nothing to do here. */
01506 continue;
01507 s = accept(privdata->listening_socket, (struct sockaddr *)&server_addr,
01508 &server_addr_len);
01509 if (s == -1) {
01510 warning(errno, "EMI2[%s]: emi2_listener: accept() failed, retrying...",
01511 octstr_get_cstr(privdata->name));
01512 continue;
01513 }
01514 ip = host_ip(server_addr);
01515 if (!is_allowed_ip(privdata->allow_ip, privdata->deny_ip, ip)) {
01516 info(0, "EMI2[%s]: smsc connection tried from denied host <%s>,"
01517 " disconnected", octstr_get_cstr(privdata->name),
01518 octstr_get_cstr(ip));
01519 octstr_destroy(ip);
01520 close(s);
01521 continue;
01522 }
01523 server = conn_wrap_fd(s, 0);
01524 if (server == NULL) {
01525 error(0, "EMI2[%s]: emi2_listener: conn_wrap_fd failed on accept()ed fd",
01526 octstr_get_cstr(privdata->name));
01527 octstr_destroy(ip);
01528 close(s);
01529 continue;
01530 }
01531 conn_claim(server);
01532 info(0, "EMI2[%s]: smsc connected from %s",
01533 octstr_get_cstr(privdata->name), octstr_get_cstr(ip));
01534 octstr_destroy(ip);
01535
01536 emi2_receiver(conn, server);
01537 conn_destroy(server);
01538 }
01539 if (close(privdata->listening_socket) == -1)
01540 warning(errno, "EMI2[%s]: couldn't close listening socket "
01541 "at shutdown", octstr_get_cstr(privdata->name));
01542 gwthread_wakeup(privdata->sender_thread);
01543 }
|
Here is the call graph for this function:

|
|
Definition at line 960 of file smsc_emi.c. References INC_TRN, privdata::priv_nexttrn, PRIVDATA, result, SLOTBUSY, and SMSCConn. Referenced by emi2_do_send(), and emi2_keepalive_handling(). 00961 {
00962 #define INC_TRN(x) ((x)=((x) + 1) % EMI2_MAX_TRN)
00963 int result;
00964
00965 while (SLOTBUSY(conn,PRIVDATA(conn)->priv_nexttrn))
00966 INC_TRN(PRIVDATA(conn)->priv_nexttrn); /* pick unused TRN */
00967
00968 result = PRIVDATA(conn)->priv_nexttrn;
00969 INC_TRN(PRIVDATA(conn)->priv_nexttrn);
00970
00971 return result;
00972 #undef INC_TRN
00973 }
|
|
||||||||||||
|
Definition at line 1459 of file smsc_emi.c. References error(), privdata::listening_socket, make_server_socket(), privdata::name, octstr_get_cstr, smscconn::our_host, PrivData, privdata::rport, SMSCConn, and socket_set_blocking(). Referenced by smsc_emi2_create(). 01460 {
01461 int s;
01462
01463 if ( (s = make_server_socket(privdata->rport, (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL))) == -1) {
01464 error(0, "EMI2[%s]: could not create listening socket in port %d",
01465 octstr_get_cstr(privdata->name), privdata->rport);
01466 return -1;
01467 }
01468 if (socket_set_blocking(s, 0) == -1) {
01469 error(0, "EMI2[%s]: couldn't make listening socket port %d "
01470 "non-blocking", octstr_get_cstr(privdata->name), privdata->rport);
01471 close(s);
01472 return -1;
01473 }
01474 privdata->listening_socket = s;
01475 return 0;
01476 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1412 of file smsc_emi.c. References conn_eof(), conn_error(), conn_read_packet(), conn_wait(), smscconn::data, debug(), emimsg_destroy(), error(), get_fields(), handle_operation(), info(), smscconn::is_stopped, privdata::name, octstr_destroy(), octstr_get_cstr, emimsg::or, PrivData, privdata::shutdown, and SMSCConn. Referenced by emi2_listener(). 01413 {
01414 PrivData *privdata = conn->data;
01415 Octstr *str;
01416 struct emimsg *emimsg;
01417
01418 while (1) {
01419 if (conn_eof(server)) {
01420 info(0, "EMI2[%s]: receive connection closed by SMSC",
01421 octstr_get_cstr(privdata->name));
01422 return;
01423 }
01424 if (conn_error(server)) {
01425 error(0, "EMI2[%s]: receive connection broken",
01426 octstr_get_cstr(privdata->name));
01427 return;
01428 }
01429 if (conn->is_stopped)
01430 str = NULL;
01431 else
01432 str = conn_read_packet(server, 2, 3);
01433 if (str) {
01434 debug("smsc.emi2", 0, "EMI2[%s]: Got packet from the receive connection.",
01435 octstr_get_cstr(privdata->name));
01436 if ( (emimsg = get_fields(str, privdata->name)) ) {
01437 if (emimsg->or == 'O') {
01438 if (handle_operation(conn, server, emimsg) < 0) {
01439 emimsg_destroy(emimsg);
01440 return;
01441 }
01442 }
01443 else
01444 error(0, "EMI2[%s]: No ACKs expected on receive connection!",
01445 octstr_get_cstr(privdata->name));
01446 emimsg_destroy(emimsg);
01447 }
01448 octstr_destroy(str);
01449 }
01450 else
01451 conn_wait(server, -1);
01452 if (privdata->shutdown)
01453 break;
01454 }
01455 return;
01456 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1285 of file smsc_emi.c. References conn_eof(), conn_error(), smscconn::data, EMI2_CONNERR, emi2_do_send(), emi2_get_timeouttime(), emi2_handle_smscreq(), emi2_idleprocessing(), emi2_idletimeout_handling(), emi2_keepalive_handling(), emi2_needs_keepalive, EMI2_SENDREQ, EMI2_SMSCREQ, EMI2_TIMEOUT, emi2_wait(), EMI2Event, event, info(), privdata::name, octstr_get_cstr, PRIVDATA, PrivData, SMSCConn, and warning(). Referenced by emi2_sender(). 01286 {
01287 PrivData *privdata = conn->data;
01288
01289 for (;;) {
01290 double timeouttime;
01291 EMI2Event event;
01292
01293 if (emi2_needs_keepalive (conn)) {
01294 if (*server == NULL) {
01295 return; /* reopen the connection */
01296 }
01297
01298 emi2_keepalive_handling (conn, *server);
01299 }
01300
01301 timeouttime = emi2_get_timeouttime (conn, *server);
01302
01303 event = emi2_wait (conn, *server, timeouttime);
01304
01305 switch (event) {
01306 case EMI2_CONNERR:
01307 return;
01308
01309 case EMI2_SENDREQ:
01310 if (*server == NULL) {
01311 return; /* reopen the connection */
01312 }
01313
01314 if (emi2_do_send (conn, *server) < 0) {
01315 return; /* reopen the connection */
01316 }
01317 break;
01318
01319 case EMI2_SMSCREQ:
01320 if (emi2_handle_smscreq (conn, *server) < 0) {
01321 return; /* reopen the connection */
01322 }
01323 break;
01324
01325 case EMI2_TIMEOUT:
01326 break;
01327 }
01328
01329 if ((*server !=NULL) && (emi2_handle_smscreq (conn, *server) < 0)) {
01330 return; /* reopen the connection */
01331 }
01332
01333 emi2_idleprocessing (conn, server);
01334 emi2_idletimeout_handling (conn, server);
01335
01336 if (PRIVDATA(conn)->shutdown && (PRIVDATA(conn)->unacked == 0)) {
01337 /* shutdown and no open messages */
01338 break;
01339 }
01340
01341 if (*server != NULL) {
01342 if (conn_error(*server)) {
01343 warning(0, "EMI2[%s]: Error reading from the main connection",
01344 octstr_get_cstr(privdata->name));
01345 break;
01346 }
01347
01348 if (conn_eof(*server)) {
01349 info(0, "EMI2[%s]: Main connection closed by SMSC",
01350 octstr_get_cstr(privdata->name));
01351 break;
01352 }
01353 }
01354 }
01355 }
|
Here is the call graph for this function:

|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 939 of file smsc_emi.c. References conn_wait(), emi2_can_send, EMI2_SENDREQ, EMI2Event, gw_prioqueue_len(), gwthread_sleep(), PRIVDATA, and SMSCConn. Referenced by emi2_send_loop(). 00940 {
00941 if (emi2_can_send(conn) && gw_prioqueue_len(PRIVDATA(conn)->outgoing_queue)) {
00942 return EMI2_SENDREQ;
00943 }
00944
00945 if (server != NULL) {
00946 switch (conn_wait(server, seconds)) {
00947 case 1: return gw_prioqueue_len(PRIVDATA(conn)->outgoing_queue) ? EMI2_SENDREQ : EMI2_TIMEOUT;
00948 case 0: return EMI2_SMSCREQ;
00949 default: return EMI2_CONNERR;
00950 }
00951 } else {
00952 gwthread_sleep(seconds);
00953 return gw_prioqueue_len(PRIVDATA(conn)->outgoing_queue) ? EMI2_SENDREQ : EMI2_TIMEOUT;
00954 }
00955 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 578 of file smsc_emi.c. References privdata::alt_charset, bb_smscconn_receive(), charset_gsm_to_utf8(), charset_nrc_iso_21_german_to_gsm(), smscconn::data, date_convert_universal(), universaltime::day, dcs_to_fields(), DLR_BUFFERED, DLR_FAIL, dlr_find(), DLR_SUCCESS, E01_ADC, E01_AMSG, E01_MT, E01_OADC, E50_ADC, E50_AMSG, E50_DST, E50_MT, E50_OADC, E50_SCTS, emi2_emimsg_send(), emimsg_create_reply(), emimsg_destroy(), error(), emimsg::fields, universaltime::hour, smscconn::id, info(), universaltime::minute, universaltime::month, msg_create, privdata::name, octstr_copy, octstr_create, octstr_delete(), octstr_destroy(), octstr_duplicate, octstr_get_char(), octstr_get_cstr, octstr_hex_to_binary(), octstr_len(), octstr_parse_long(), emimsg::ot, PRIVDATA, PrivData, universaltime::second, sms, SMSCConn, emimsg::trn, type, warning(), and universaltime::year. Referenced by emi2_handle_smscreq(), and emi2_receiver(). 00580 {
00581 struct emimsg *reply;
00582 Octstr *tempstr, *xser;
00583 int type, len;
00584 Msg *msg = NULL;
00585 struct universaltime unitime;
00586 int st_code;
00587 PrivData *privdata = conn->data;
00588
00589
00590 switch(emimsg->ot) {
00591
00592 /*
00593 * Handle OP/01 call input operation. This operation delivery MO messages
00594 * from SMSC to SMT according to [1], section 4.2, p. 9.
00595 */
00596 case 01:
00597 msg = msg_create(sms);
00598 if (emimsg->fields[E01_AMSG] == NULL)
00599 emimsg->fields[E01_AMSG] = octstr_create("");
00600 else if (octstr_hex_to_binary(emimsg->fields[E01_AMSG]) == -1)
00601 warning(0, "EMI2[%s]: Couldn't decode message text",
00602 octstr_get_cstr(privdata->name));
00603
00604 if (emimsg->fields[E01_MT] == NULL) {
00605 warning(0, "EMI2[%s]: required field MT missing",
00606 octstr_get_cstr(privdata->name));
00607 /* This guess could be incorrect, maybe the message should just
00608 be dropped */
00609 emimsg->fields[E01_MT] = octstr_create("3");
00610 }
00611
00612 if (octstr_get_char(emimsg->fields[E01_MT], 0) == '3') {
00613 msg->sms.msgdata = emimsg->fields[E01_AMSG];
00614 emimsg->fields[E01_AMSG] = NULL; /* So it's not freed */
00615
00616 /* obey the NRC (national replacement codes) */
00617 if (privdata->alt_charset == EMI_NRC_ISO_21)
00618 charset_nrc_iso_21_german_to_gsm(msg->sms.msgdata);
00619
00620 charset_gsm_to_utf8(msg->sms.msgdata);
00621 }
00622 else {
00623 error(0, "EMI2[%s]: MT == %s isn't supported for operation type 01",
00624 octstr_get_cstr(privdata->name),
00625 octstr_get_cstr(emimsg->fields[E01_MT]));
00626 msg->sms.msgdata = octstr_create("");
00627 }
00628
00629 msg->sms.sender = octstr_duplicate(emimsg->fields[E01_OADC]);
00630 if (msg->sms.sender == NULL) {
00631 warning(0, "EMI2[%s]: Empty sender field in received message",
00632 octstr_get_cstr(privdata->name));
00633 msg->sms.sender = octstr_create("");
00634 }
00635
00636 if(octstr_len(PRIVDATA(conn)->my_number)) {
00637 msg->sms.receiver = octstr_duplicate(PRIVDATA(conn)->my_number);
00638 }
00639 else {
00640 msg->sms.receiver = octstr_duplicate(emimsg->fields[E01_ADC]);
00641 }
00642 if (msg->sms.receiver == NULL) {
00643 warning(0, "EMI2[%s]: Empty receiver field in received message",
00644 octstr_get_cstr(privdata->name));
00645 msg->sms.receiver = octstr_create("");
00646 }
00647
00648 /* Operation type 01 doesn't have a time stamp field */
00649 time(&msg->sms.time);
00650
00651 msg->sms.smsc_id = octstr_duplicate(conn->id);
00652 bb_smscconn_receive(conn, msg);
00653 reply = emimsg_create_reply(01, emimsg->trn, 1, privdata->name);
00654 if (emi2_emimsg_send(conn, server, reply) < 0) {
00655 emimsg_destroy(reply);
00656 return -1;
00657 }
00658 emimsg_destroy(reply);
00659 return 1;
00660
00661 /*
00662 * Handle OP/52 delivery short message. This is the MO side of the protocol
00663 * implementation. See [1], section 5.4, p. 40.
00664 */
00665 case 52:
00666 msg = msg_create(sms);
00667 /* AMSG is the same field as TMSG */
00668 if (emimsg->fields[E50_AMSG] == NULL)
00669 emimsg->fields[E50_AMSG] = octstr_create("");
00670 else if (octstr_hex_to_binary(emimsg->fields[E50_AMSG]) == -1)
00671 warning(0, "EMI2[%s]: Couldn't decode message text",
00672 octstr_get_cstr(privdata->name));
00673
00674 /* Process XSer fields */
00675 xser = emimsg->fields[E50_XSER];
00676 while (octstr_len(xser) > 0) {
00677 int tempint;
00678 tempstr = octstr_copy(xser, 0, 4);
00679 if (octstr_hex_to_binary(tempstr) == -1)
00680 error(0, "EMI2[%s]: Invalid XSer",
00681 octstr_get_cstr(privdata->name));
00682 type = octstr_get_char(tempstr, 0);
00683 len = octstr_get_char(tempstr, 1);
00684 octstr_destroy(tempstr);
00685 if (len < 0) {
00686 error(0, "EMI2[%s]: Malformed emi XSer field",
00687 octstr_get_cstr(privdata->name));
00688 break;
00689 }
00690
00691 /* Handle supported XSer fields */
00692 switch (type) {
00693
00694 case 0x01: /* XSer 01, GSM UDH information */
00695 tempstr = octstr_copy(xser, 4, len * 2);
00696 if (octstr_hex_to_binary(tempstr) == -1)
00697 error(0, "EMI2[%s]: Invalid UDH contents",
00698 octstr_get_cstr(privdata->name));
00699 msg->sms.udhdata = tempstr;
00700 break;
00701
00702 case 0x02: /* XSer 02, GSM DCS information */
00703 tempstr = octstr_copy(xser, 4, 2);
00704 octstr_hex_to_binary(tempstr);
00705 tempint = octstr_get_char(tempstr, 0);
00706 octstr_destroy(tempstr);
00707 if (!dcs_to_fields(&msg, tempint)) {
00708 error(0, "EMI2[%s]: Invalid DCS received",
00709 octstr_get_cstr(privdata->name));
00710 /* XXX Should we discard message ? */
00711 dcs_to_fields(&msg, 0);
00712 }
00713 break;
00714
00715 /*
00716 * XSer 03-0b are for CDMA/TDMA information exchange and are currently
00717 * not implemented in this EMI interface. See CMG EMI/UCP spec 4.6,
00718 * section 5.1.2.4 for more information.
00719 */
00720
00721 case 0x0c: /* XSer 0c, billing identifier */
00722 tempstr = octstr_copy(xser, 4, len * 2);
00723 if (octstr_hex_to_binary(tempstr) == -1) {
00724 error(0, "EMI2[%s] Invalid XSer 0c billing identifier <%s>",
00725 octstr_get_cstr(privdata->name),
00726 octstr_get_cstr(tempstr));
00727 } else {
00728 msg->sms.binfo = tempstr;
00729 }
00730 break;
00731
00732 case 0x0d: /* XSer 0d, single shot indicator */
00733 tempstr = octstr_copy(xser, 4, 2);
00734 octstr_hex_to_binary(tempstr);
00735 tempint = octstr_get_char(tempstr, 0);
00736 octstr_destroy(tempstr);
00737 if (tempint)
00738 info(0, "EMI2[%s]: Single shot indicator set.",
00739 octstr_get_cstr(privdata->name));
00740 break;
00741
00742 /* XSer fields 0e-ff are reserved for future use and should not be used. */
00743
00744 default:
00745 warning(0, "EMI2[%s]: Unsupported EMI XSer field %d",
00746 octstr_get_cstr(privdata->name), type);
00747 break;
00748 }
00749
00750 octstr_delete(xser, 0, 2 * len + 4);
00751 }
00752
00753 if (emimsg->fields[E50_MT] == NULL) {
00754 warning(0, "EMI2[%s]: required field MT missing",
00755 octstr_get_cstr(privdata->name));
00756 /* This guess could be incorrect, maybe the message should just
00757 be dropped */
00758 emimsg->fields[E50_MT] = octstr_create("3");
00759 }
00760 if (octstr_get_char(emimsg->fields[E50_MT], 0) == '3') {
00761 msg->sms.msgdata = emimsg->fields[E50_AMSG];
00762 emimsg->fields[E50_AMSG] = NULL; /* So it's not freed */
00763
00764 /* obey the NRC (national replacement codes) */
00765 if (privdata->alt_charset == EMI_NRC_ISO_21)
00766 charset_nrc_iso_21_german_to_gsm(msg->sms.msgdata);
00767
00768 charset_gsm_to_utf8(msg->sms.msgdata);
00769 }
00770 else if (octstr_get_char(emimsg->fields[E50_MT], 0) == '4') {
00771 msg->sms.msgdata = emimsg->fields[E50_TMSG];
00772 emimsg->fields[E50_TMSG] = NULL;
00773 }
00774 else {
00775 error(0, "EMI2[%s]: MT == %s isn't supported yet",
00776 octstr_get_cstr(privdata->name),
00777 octstr_get_cstr(emimsg->fields[E50_MT]));
00778 msg->sms.msgdata = octstr_create("");
00779 }
00780
00781 msg->sms.sender = octstr_duplicate(emimsg->fields[E50_OADC]);
00782 if (msg->sms.sender == NULL) {
00783 warning(0, "EMI2[%s]: Empty sender field in received message",
00784 octstr_get_cstr(privdata->name));
00785 msg->sms.sender = octstr_create("");
00786 }
00787
00788 if(octstr_len(PRIVDATA(conn)->my_number)) {
00789 msg->sms.receiver = octstr_duplicate(PRIVDATA(conn)->my_number);
00790 }
00791 else {
00792 msg->sms.receiver = octstr_duplicate(emimsg->fields[E50_ADC]);
00793 }
00794 if (msg->sms.receiver == NULL) {
00795 warning(0, "EMI2[%s]: Empty receiver field in received message",
00796 octstr_get_cstr(privdata->name));
00797 msg->sms.receiver = octstr_create("");
00798 }
00799
00800 tempstr = emimsg->fields[E50_SCTS]; /* Just a shorter name */
00801 if (tempstr == NULL) {
00802 warning(0, "EMI2[%s]: Received EMI message doesn't have required timestamp",
00803 octstr_get_cstr(privdata->name));
00804 goto notime;
00805 }
00806 if (octstr_len(tempstr) != 12) {
00807 warning(0, "EMI2[%s]: EMI SCTS field must have length 12, now %ld",
00808 octstr_get_cstr(privdata->name), octstr_len(tempstr));
00809 goto notime;
00810 }
00811 if (octstr_parse_long(&unitime.second, tempstr, 10, 10) != 12 ||
00812 (octstr_delete(tempstr, 10, 2),
00813 octstr_parse_long(&unitime.minute, tempstr, 8, 10) != 10) ||
00814 (octstr_delete(tempstr, 8, 2),
00815 octstr_parse_long(&unitime.hour, tempstr, 6, 10) != 8) ||
00816 (octstr_delete(tempstr, 6, 2),
00817 octstr_parse_long(&unitime.year, tempstr, 4, 10) != 6) ||
00818 (octstr_delete(tempstr, 4, 2),
00819 octstr_parse_long(&unitime.month, tempstr, 2, 10) != 4) ||
00820 (octstr_delete(tempstr, 2, 2),
00821 octstr_parse_long(&unitime.day, tempstr, 0, 10) != 2)) {
00822 error(0, "EMI2[%s]: EMI delivery time stamp looks malformed",
00823 octstr_get_cstr(privdata->name));
00824 notime:
00825 time(&msg->sms.time);
00826 }
00827 else {
00828 unitime.year += 2000; /* Conversion function expects full year */
00829 unitime.month -= 1; /* conversion function expects 0-based months */
00830 msg->sms.time = date_convert_universal(&unitime);
00831 }
00832
00833 msg->sms.smsc_id = octstr_duplicate(conn->id);
00834 bb_smscconn_receive(conn, msg);
00835 reply = emimsg_create_reply(52, emimsg->trn, 1, privdata->name);
00836 if (emi2_emimsg_send(conn, server, reply) < 0) {
00837 emimsg_destroy(reply);
00838 return -1;
00839 }
00840 emimsg_destroy(reply);
00841 return 1;
00842
00843 /*
00844 * Handle OP/53 delivery notification. See [1], section 5.5, p. 43.
00845 */
00846 case 53:
00847 st_code = atoi(octstr_get_cstr(emimsg->fields[E50_DST]));
00848 switch(st_code)
00849 {
00850 case 0: /* delivered */
00851 msg = dlr_find((conn->id ? conn->id : privdata->name),
00852 emimsg->fields[E50_SCTS], /* timestamp */
00853 emimsg->fields[E50_OADC], /* destination */
00854 DLR_SUCCESS);
00855 break;
00856 case 1: /* buffered */
00857 msg = dlr_find((conn->id ? conn->id : privdata->name),
00858 emimsg->fields[E50_SCTS], /* timestamp */
00859 emimsg->fields[E50_OADC], /* destination */
00860 DLR_BUFFERED);
00861 break;
00862 case 2: /* not delivered */
00863 msg = dlr_find((conn->id ? conn->id : privdata->name),
00864 emimsg->fields[E50_SCTS], /* timestamp */
00865 emimsg->fields[E50_OADC], /* destination */
00866 DLR_FAIL);
00867 break;
00868 }
00869 if (msg != NULL) {
00870 /*
00871 * Recode the msg structure with the given msgdata.
00872 * Note: the DLR URL is delivered in msg->sms.dlr_url already.
00873 */
00874 if ((emimsg->fields[E50_AMSG]) == NULL)
00875 msg->sms.msgdata = octstr_create("Delivery Report without text");
00876 else
00877 msg->sms.msgdata = octstr_duplicate(emimsg->fields[E50_AMSG]);
00878 octstr_hex_to_binary(msg->sms.msgdata);
00879 if (octstr_get_char(emimsg->fields[E50_MT], 0) == '3') {
00880 /* obey the NRC (national replacement codes) */
00881 if (privdata->alt_charset == EMI_NRC_ISO_21)
00882 charset_nrc_iso_21_german_to_gsm(msg->sms.msgdata);
00883 charset_gsm_to_utf8(msg->sms.msgdata);
00884 }
00885 bb_smscconn_receive(conn, msg);
00886 }
00887 reply = emimsg_create_reply(53, emimsg->trn, 1, privdata->name);
00888 if (emi2_emimsg_send(conn, server, reply) < 0) {
00889 emimsg_destroy(reply);
00890 return -1;
00891 }
00892 emimsg_destroy(reply);
00893 return 1;
00894
00895 /*
00896 * Handle OP/31 from SMSC side. This is not "purely" spec conform since,
00897 * the protocol says "This operation can be used by a SMT to alert the SC.",
00898 * which implies semantically only the opposite way. For the sake of EMI/UCP
00899 * server implementations that send alert messages to SMTs we handle this
00900 * without breaking any core protocol concept.
00901 *
00902 * See [1], section 4.6, p. 19.
00903 */
00904 case 31:
00905 reply = emimsg_create_reply(31, emimsg->trn, 1, privdata->name);
00906 st_code = emi2_emimsg_send(conn, server, reply);
00907 emimsg_destroy(reply);
00908 return (st_code < 0 ? -1 : 1);
00909
00910 default:
00911 error(0, "EMI2[%s]: I don't know how to handle operation type %d",
00912 octstr_get_cstr(privdata->name), emimsg->ot);
00913 return 0;
00914 }
00915 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 232 of file smsc_emi.c. References emimsg_create_op(), emimsg::fields, privdata::my_number, privdata::name, octstr_create, octstr_duplicate, octstr_len(), PrivData, and privdata::username. Referenced by emi2_keepalive_handling(). 00233 {
00234 struct emimsg *emimsg;
00235
00236 if(octstr_len(privdata->username) || octstr_len(privdata->my_number)) {
00237 emimsg = emimsg_create_op(31, trn, privdata->name);
00238 if(octstr_len(privdata->username)) {
00239 emimsg->fields[0] = octstr_duplicate(privdata->username);
00240 } else {
00241 emimsg->fields[0] = octstr_duplicate(privdata->my_number);
00242 }
00243 emimsg->fields[1] = octstr_create("0539");
00244 return emimsg;
00245 } else {
00246 return NULL;
00247 }
00248 }
|
Here is the call graph for this function:

|
|
Definition at line 251 of file smsc_emi.c. References E60_PWD, emimsg_create_op(), emimsg::fields, privdata::name, octstr_binary_to_hex(), octstr_create, octstr_duplicate, privdata::password, PrivData, and privdata::username. Referenced by open_send_connection(). 00252 {
00253 struct emimsg *emimsg;
00254
00255 emimsg = emimsg_create_op(60, 0, privdata->name);
00256 emimsg->fields[E60_OADC] = octstr_duplicate(privdata->username);
00257 emimsg->fields[E60_OTON] = octstr_create("6");
00258 emimsg->fields[E60_ONPI] = octstr_create("5");
00259 emimsg->fields[E60_STYP] = octstr_create("1");
00260 emimsg->fields[E60_PWD] = octstr_duplicate(privdata->password);
00261 octstr_binary_to_hex(emimsg->fields[E60_PWD], 1);
00262 emimsg->fields[E60_VERS] = octstr_create("0100");
00263 return emimsg;
00264 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 413 of file smsc_emi.c. References privdata::alt_charset, charset_gsm_to_nrc_iso_21_german(), charset_gsm_truncate(), charset_utf8_to_gsm(), DC_8BIT, DLR_IS_BUFFERED, DLR_IS_ENABLED_DEVICE, E50_NT, E50_XSER, emimsg_create_op(), error(), emimsg::fields, fields_to_dcs(), gw_isdigit(), gw_localtime(), privdata::nadc, privdata::name, privdata::npid, octstr_append(), octstr_append_char(), octstr_append_decimal(), octstr_binary_to_hex(), octstr_check_range(), octstr_create, octstr_delete(), octstr_destroy(), octstr_duplicate, octstr_format(), octstr_get_char(), octstr_get_cstr, octstr_insert_data(), octstr_len(), octstr_truncate(), pack_7bit(), and PrivData. Referenced by emi2_do_send(). 00414 {
00415 Octstr *str;
00416 struct emimsg *emimsg;
00417 int dcs;
00418 struct tm tm;
00419 char p[20];
00420
00421 emimsg = emimsg_create_op(51, trn, privdata->name);
00422 str = octstr_duplicate(msg->sms.sender);
00423 if(octstr_get_char(str,0) == '+') {
00424 /* either alphanum or international */
00425 if (!octstr_check_range(str, 1, 256, gw_isdigit)) {
00426 /* alphanumeric sender address with + in front*/
00427 charset_utf8_to_gsm(str);
00428 octstr_truncate(str, 11); /* max length of alphanumeric OaDC */
00429 emimsg->fields[E50_OTOA] = octstr_create("5039");
00430 pack_7bit(str);
00431 }
00432 else {
00433 /* international number. Set format and remove + */
00434 emimsg->fields[E50_OTOA] = octstr_create("1139");
00435 octstr_delete(str, 0, 1);
00436 octstr_truncate(str, 22); /* max length of numeric OaDC */
00437 }
00438 }
00439 else {
00440 if (!octstr_check_range(str, 0, 256, gw_isdigit)) {
00441 /* alphanumeric sender address */
00442 charset_utf8_to_gsm(str);
00443 octstr_truncate(str, 11); /* max length of alphanumeric OaDC */
00444 emimsg->fields[E50_OTOA] = octstr_create("5039");
00445 pack_7bit(str);
00446 }
00447 }
00448
00449 emimsg->fields[E50_OADC] = str;
00450
00451 /* set protocol id */
00452 if (msg->sms.pid >= 0) {
00453 emimsg->fields[E50_RPID] = octstr_format("%04d", msg->sms.pid);
00454 }
00455
00456 /* set reply path indicator */
00457 if (msg->sms.rpi == 2)
00458 emimsg->fields[E50_RPI] = octstr_create("2");
00459 else if (msg->sms.rpi > 0)
00460 emimsg->fields[E50_RPI] = octstr_create("1");
00461
00462 str = octstr_duplicate(msg->sms.receiver);
00463 if(octstr_get_char(str,0) == '+') {
00464 /* international number format */
00465 /* EMI doesnt understand + so we have to replace it with something useful */
00466 /* we try 00 here. Should really be done in the config instead so this */
00467 /* is only a workaround to make wrong configs work */
00468 octstr_delete(str, 0, 1);
00469 octstr_insert_data(str, 0, "00",2);
00470 }
00471 octstr_truncate(str, 16); /* max length of ADC */
00472 emimsg->fields[E50_ADC] = str;
00473
00474 emimsg->fields[E50_XSER] = octstr_create("");
00475
00476 /* XSer 01: UDH */
00477 if (octstr_len(msg->sms.udhdata)) {
00478 str = octstr_create("");
00479 octstr_append_char(str, 0x01);
00480 octstr_append_char(str, octstr_len(msg->sms.udhdata));
00481 octstr_append(str, msg->sms.udhdata);
00482 octstr_binary_to_hex(str, 1);
00483 octstr_append(emimsg->fields[E50_XSER], str);
00484 octstr_destroy(str);
00485 }
00486
00487 /* XSer 02: DCS */
00488 dcs = fields_to_dcs(msg, msg->sms.alt_dcs);
00489 if (dcs != 0 && dcs != 4) {
00490 str = octstr_create("");
00491 octstr_append_char(str, 0x02);
00492 octstr_append_char(str, 1); /* len 01 */
00493 octstr_append_char(str, dcs);
00494 octstr_binary_to_hex(str, 1);
00495 octstr_append(emimsg->fields[E50_XSER], str);
00496 octstr_destroy(str);
00497 }
00498
00499 /* XSer 0c: billing identifier */
00500 if (octstr_len(msg->sms.binfo)) {
00501 str = octstr_create("");
00502 octstr_append_char(str, 0x0c);
00503 octstr_append_char(str, octstr_len(msg->sms.binfo));
00504 octstr_append(str, msg->sms.binfo);
00505 octstr_binary_to_hex(str, 1);
00506 octstr_append(emimsg->fields[E50_XSER], str);
00507 octstr_destroy(str);
00508 }
00509
00510 if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
00511 emimsg->fields[E50_MT] = octstr_create("4");
00512 emimsg->fields[E50_MCLS] = octstr_create("1");
00513 str = octstr_duplicate(msg->sms.msgdata);
00514 emimsg->fields[E50_NB] =
00515 octstr_format("%04d", 8 * octstr_len(str));
00516 octstr_binary_to_hex(str, 1);
00517 emimsg->fields[E50_TMSG] = str;
00518 }
00519 else {
00520 emimsg->fields[E50_MT] = octstr_create("3");
00521 str = octstr_duplicate(msg->sms.msgdata);
00522 charset_utf8_to_gsm(str);
00523
00524 /*
00525 * Check if we have to apply some after GSM transcoding kludges
00526 */
00527 if (privdata->alt_charset == EMI_NRC_ISO_21)
00528 charset_gsm_to_nrc_iso_21_german(str);
00529
00530 /* Could still be too long after truncation if there's an UDH part,
00531 * but this is only to notice errors elsewhere (should never happen).*/
00532 if (charset_gsm_truncate(str, 160))
00533 error(0, "EMI2[%s]: Message to send is longer "
00534 "than 160 gsm characters",
00535 octstr_get_cstr(privdata->name));
00536 octstr_binary_to_hex(str, 1);
00537 emimsg->fields[E50_AMSG] = str;
00538 }
00539
00540 if (msg->sms.validity >= 0) {
00541 tm = gw_localtime(time(NULL) + msg->sms.validity * 60);
00542 sprintf(p, "%02d%02d%02d%02d%02d",
00543 tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100,
00544 tm.tm_hour, tm.tm_min);
00545 str = octstr_create(p);
00546 emimsg->fields[E50_VP] = str;
00547 }
00548 if (msg->sms.deferred >= 0) {
00549 str = octstr_create("1");
00550 emimsg->fields[E50_DD] = str;
00551 tm = gw_localtime(time(NULL) + msg->sms.deferred * 60);
00552 sprintf(p, "%02d%02d%02d%02d%02d",
00553 tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100,
00554 tm.tm_hour, tm.tm_min);
00555 str = octstr_create(p);
00556 emimsg->fields[E50_DDT] = str;
00557 }
00558
00559 /* if delivery reports are asked, lets ask for them too */
00560 /* even the sender might not be interested in delivery or non delivery */
00561 /* we still need them back to clear out the memory after the message */
00562 /* has been delivered or non delivery has been confirmed */
00563 if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
00564 emimsg->fields[E50_NRQ] = octstr_create("1");
00565 emimsg->fields[E50_NT] = octstr_create("");
00566 octstr_append_decimal(emimsg->fields[E50_NT], 3 + (DLR_IS_BUFFERED(msg->sms.dlr_mask) ? 4 : 0));
00567 if (privdata->npid)
00568 emimsg->fields[E50_NPID] = octstr_duplicate(privdata->npid);
00569 if (privdata->nadc)
00570 emimsg->fields[E50_NADC] = octstr_duplicate(privdata->nadc);
00571 }
00572 return emimsg;
00573 }
|
Here is the call graph for this function:

|
|
Definition at line 267 of file smsc_emi.c. References privdata::alt_host, privdata::alt_port, bb_smscconn_connected(), bb_smscconn_send_failed(), privdata::can_write, conn_destroy(), conn_open_tcp_with_port(), smscconn::connect_time, smscconn::data, emi2_emimsg_send(), emimsg_destroy(), error(), smscconn::flow_mutex, gw_prioqueue_remove(), gwthread_sleep(), privdata::host, info(), privdata::last_activity_time, make_emi60(), mutex_lock, mutex_unlock, smscconn::name, privdata::name, octstr_destroy(), octstr_format(), octstr_get_cstr, octstr_imm(), octstr_len(), smscconn::our_host, privdata::our_port, privdata::outgoing_queue, privdata::password, privdata::port, PrivData, smscconn::reconnect_delay, result, privdata::shutdown, SMSCConn, SMSCCONN_FAILED_TEMPORARILY, smscconn::status, privdata::username, wait_for_ack(), and privdata::waitack. Referenced by emi2_sender(). 00268 {
00269 PrivData *privdata = conn->data;
00270 int result, alt_host, do_alt_host;
00271 struct emimsg *emimsg;
00272 Connection *server;
00273 Msg *msg;
00274 int connect_error = 0;
00275 int wait_ack = 0;
00276
00277 do_alt_host = octstr_len(privdata->alt_host) != 0 || privdata->alt_port != 0;
00278
00279 alt_host = 0;
00280
00281 mutex_lock(conn->flow_mutex);
00282 conn->status = SMSCCONN_RECONNECTING;
00283 mutex_unlock(conn->flow_mutex);
00284
00285 while (!privdata->shutdown) {
00286
00287 while ((msg = gw_prioqueue_remove(privdata->outgoing_queue))) {
00288 bb_smscconn_send_failed(conn, msg,
00289 SMSCCONN_FAILED_TEMPORARILY, NULL);
00290 }
00291
00292 /* if there is no alternative host, sleep and try to re-connect */
00293 if (alt_host == 0 && connect_error) {
00294 error(0, "EMI2[%s]: Couldn't connect to SMS center (retrying in %ld seconds).",
00295 octstr_get_cstr(privdata->name), conn->reconnect_delay);
00296 gwthread_sleep(conn->reconnect_delay);
00297 }
00298
00299 if (alt_host != 1) {
00300 info(0, "EMI2[%s]: connecting to Primary SMSC",
00301 octstr_get_cstr(privdata->name));
00302 mutex_lock(conn->flow_mutex);
00303 octstr_destroy(conn->name);
00304 conn->name = octstr_format("EMI2:%S:%d:%S", privdata->host, privdata->port, privdata->username ? privdata->username : octstr_imm("null"));
00305 mutex_unlock(conn->flow_mutex);
00306 server = conn_open_tcp_with_port(privdata->host, privdata->port,
00307 privdata->our_port,
00308 conn->our_host);
00309 if(do_alt_host)
00310 alt_host=1;
00311 else
00312 alt_host=0;
00313 } else {
00314 info(0, "EMI2[%s]: connecting to Alternate SMSC",
00315 octstr_get_cstr(privdata->name));
00316 /* use alt_host or/and alt_port if defined */
00317 mutex_lock(conn->flow_mutex);
00318 octstr_destroy(conn->name);
00319 conn->name = octstr_format("EMI2:%S:%d:%S", octstr_len(privdata->alt_host) ? privdata->alt_host : privdata->host,
00320 privdata->alt_port ? privdata->alt_port : privdata->port,
00321 privdata->username ? privdata->username : octstr_imm("null"));
00322 mutex_unlock(conn->flow_mutex);
00323 server = conn_open_tcp_with_port(
00324 (octstr_len(privdata->alt_host) ? privdata->alt_host : privdata->host),
00325 (privdata->alt_port ? privdata->alt_port : privdata->port),
00326 privdata->our_port, conn->our_host);
00327 alt_host=0;
00328 }
00329 if (privdata->shutdown) {
00330 conn_destroy(server);
00331 return NULL;
00332 }
00333 if (server == NULL) {
00334 error(0, "EMI2[%s]: opening TCP connection to %s failed",
00335 octstr_get_cstr(privdata->name),
00336 octstr_get_cstr(privdata->host));
00337 connect_error = 1;
00338 continue;
00339 }
00340
00341 if (privdata->username && privdata->password) {
00342 emimsg = make_emi60(privdata);
00343 emi2_emimsg_send(conn, server, emimsg);
00344 emimsg_destroy(emimsg);
00345 wait_ack = privdata->waitack > 30 ? privdata->waitack : 30;
00346 result = wait_for_ack(privdata, server, 60, wait_ack);
00347 if (result == -2) {
00348 /*
00349 * Are SMSCs going to return any temporary errors? If so,
00350 * testing for those error codes should be added here.
00351 */
00352 error(0, "EMI2[%s]: Server rejected our login",
00353 octstr_get_cstr(privdata->name));
00354 conn_destroy(server);
00355 connect_error = 1;
00356 continue;
00357 } else if (result == 0) {
00358 error(0, "EMI2[%s]: Got no reply to login attempt "
00359 "within %d seconds", octstr_get_cstr(privdata->name),
00360 wait_ack);
00361 conn_destroy(server);
00362 connect_error = 1;
00363 continue;
00364 } else if (result == -1) { /* Broken connection, already logged */
00365 conn_destroy(server);
00366 connect_error = 1;
00367 continue;
00368 }
00369 privdata->last_activity_time = 0; /* to force keepalive after login */
00370 privdata->can_write = 1;
00371 }
00372
00373 mutex_lock(conn->flow_mutex);
00374 conn->status = SMSCCONN_ACTIVE;
00375 conn->connect_time = time(NULL);
00376 mutex_unlock(conn->flow_mutex);
00377 bb_smscconn_connected(conn);
00378 return server;
00379 }
00380 return NULL;
00381 }
|
Here is the call graph for this function:

|
|
Definition at line 384 of file smsc_emi.c. References octstr_append(), octstr_append_char(), octstr_binary_to_hex(), octstr_create, octstr_delete(), octstr_destroy(), octstr_get_char(), octstr_len(), octstr_set_char(), and result. Referenced by msg_to_emimsg(). 00385 {
00386 Octstr *result;
00387 int len, i;
00388 int numbits, value;
00389
00390 result = octstr_create("0");
00391 len = octstr_len(str);
00392 value = 0;
00393 numbits = 0;
00394 for (i = 0; i < len; i++) {
00395 value += octstr_get_char(str, i) << numbits;
00396 numbits += 7;
00397 if (numbits >= 8) {
00398 octstr_append_char(result, value & 0xff);
00399 value >>= 8;
00400 numbits -= 8;
00401 }
00402 }
00403 if (numbits > 0)
00404 octstr_append_char(result, value);
00405 octstr_set_char(result, 0, (len * 7 + 3) / 4);
00406 octstr_delete(str, 0, LONG_MAX);
00407 octstr_append(str, result);
00408 octstr_binary_to_hex(str, 1);
00409 octstr_destroy(result);
00410 }
|
Here is the call graph for this function:

|
|
Definition at line 1598 of file smsc_emi.c. References smscconn::data, gw_prioqueue_len(), smscconn::load, privdata::outgoing_queue, PrivData, and SMSCConn. 01599 {
01600 PrivData *privdata = conn->data;
01601 long ret;
01602
01603 ret = (privdata ? gw_prioqueue_len(privdata->outgoing_queue) : 0);
01604
01605 /* use internal queue as load, maybe something else later */
01606
01607 conn->load = ret;
01608 return ret;
01609 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1559 of file smsc_emi.c. References bb_smscconn_send_failed(), smscconn::data, debug(), gw_prioqueue_remove(), gwthread_wakeup(), privdata::name, octstr_get_cstr, privdata::outgoing_queue, PrivData, privdata::receiver_thread, privdata::rport, privdata::shutdown, SMSCConn, SMSCCONN_FAILED_SHUTDOWN, and smscconn::why_killed. 01560 {
01561 PrivData *privdata = conn->data;
01562
01563 debug("bb.sms", 0, "EMI2[%s]: Shutting down SMSCConn EMI2, %s",
01564 octstr_get_cstr(privdata->name),
01565 finish_sending ? "slow" : "instant");
01566
01567 /* Documentation claims this would have been done by smscconn.c,
01568 but isn't when this code is being written. */
01569 conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
01570 privdata->shutdown = 1; /* Separate from why_killed to avoid locking, as
01571 why_killed may be changed from outside? */
01572
01573 if (finish_sending == 0) {
01574 Msg *msg;
01575 while((msg = gw_prioqueue_remove(privdata->outgoing_queue)) != NULL) {
01576 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
01577 }
01578 }
01579
01580 if (privdata->rport > 0)
01581 gwthread_wakeup(privdata->receiver_thread);
01582 return 0;
01583 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1612 of file smsc_emi.c. References privdata::allow_ip, privdata::alt_charset, privdata::alt_host, privdata::alt_port, privdata::can_write, cfg_get, cfg_get_integer(), privdata::check_time, smscconn::connect_time, smscconn::data, privdata::deny_ip, emi2_listener(), EMI2_MAX_TRN, emi2_open_listening_socket(), emi2_sender(), error(), privdata::flowcontrol, gw_prioqueue_create(), gw_prioqueue_destroy(), gwthread_create, gwthread_join(), gwthread_wakeup(), privdata::host, privdata::idle_timeout, info(), privdata::keepalive, privdata::last_activity_time, privdata::listening_socket, privdata::my_number, privdata::nadc, privdata::name, smscconn::name, privdata::npid, octstr_append(), octstr_append_char(), octstr_append_decimal(), octstr_create, octstr_destroy(), octstr_format(), octstr_get_cstr, octstr_imm(), octstr_len(), smscconn::our_host, privdata::our_port, privdata::outgoing_queue, privdata::password, privdata::port, privdata::priv_nexttrn, PrivData, smscconn::queued, privdata::receiver_thread, privdata::rport, smscconn::send_msg, privdata::sender_thread, privdata::sendtime, privdata::shutdown, smscconn::shutdown, privdata::slots, sms_priority_compare(), SMSCConn, smscconn::start_conn, smscconn::status, privdata::unacked, privdata::username, privdata::waitack, privdata::waitack_expire, warning(), smscconn::why_killed, and privdata::window. Referenced by smscconn_create(). 01613 {
01614 PrivData *privdata;
01615 Octstr *allow_ip, *deny_ip, *host, *alt_host;
01616 long portno, our_port, keepalive, flowcontrol, waitack,
01617 idle_timeout, alt_portno, alt_charset, waitack_expire;
01618 long window;
01619 /* has to be long because of cfg_get_integer */
01620 int i;
01621
01622 allow_ip = deny_ip = host = alt_host = NULL;
01623
01624 privdata = gw_malloc(sizeof(PrivData));
01625 privdata->outgoing_queue = gw_prioqueue_create(sms_priority_compare);
01626 privdata->listening_socket = -1;
01627 privdata->can_write = 1;
01628 privdata->priv_nexttrn = 0;
01629 privdata->last_activity_time = 0;
01630 privdata->check_time = 0;
01631
01632 host = cfg_get(cfg, octstr_imm("host"));
01633 if (host == NULL) {
01634 error(0, "EMI2[-]: 'host' missing in emi2 configuration.");
01635 goto error;
01636 }
01637 privdata->host = host;
01638
01639 if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1)
01640 portno = 0;
01641 privdata->port = portno;
01642 if (privdata->port <= 0 || privdata->port > 65535) {
01643 error(0, "EMI2[%s]: 'port' missing/invalid in emi2 configuration.",
01644 octstr_get_cstr(host));
01645 goto error;
01646 }
01647
01648 if (cfg_get_integer(&our_port, cfg, octstr_imm("our-port")) == -1)
01649 privdata->our_port = 0; /* 0 means use any port */
01650 else
01651 privdata->our_port = our_port;
01652
01653 privdata->name = cfg_get(cfg, octstr_imm("smsc-id"));
01654 if(privdata->name == NULL) {
01655 privdata->name = octstr_create("");
01656
01657 /* Add our_host */
01658 if(octstr_len(conn->our_host)) {
01659 octstr_append(privdata->name, conn->our_host);
01660 }
01661
01662 /* Add our_port */
01663 if(privdata->our_port != 0) {
01664 /* if we have our_port but not our_host, add kannel:our_port */
01665 if(octstr_len(privdata->name) == 0) {
01666 octstr_append(privdata->name, octstr_imm("kannel"));
01667 }
01668 octstr_append_char(privdata->name, ':');
01669 octstr_append_decimal(privdata->name, privdata->our_port);
01670 } else {
01671 if(octstr_len(privdata->name) != 0) {
01672 octstr_append(privdata->name, octstr_imm(":*"));
01673 }
01674 }
01675
01676 /* if we have our_host neither our_port */
01677 if(octstr_len(privdata->name) != 0)
01678 octstr_append(privdata->name, octstr_imm("->"));
01679
01680 octstr_append(privdata->name, privdata->host);
01681 octstr_append_char(privdata->name, ':');
01682 octstr_append_decimal(privdata->name, privdata->port);
01683 }
01684
01685
01686 if (cfg_get_integer(&idle_timeout, cfg, octstr_imm("idle-timeout")) == -1)
01687 idle_timeout = 0;
01688
01689 privdata->idle_timeout = idle_timeout;
01690
01691 alt_host = cfg_get(cfg, octstr_imm("alt-host"));
01692 privdata->alt_host = alt_host;
01693
01694 if (cfg_get_integer(&portno, cfg, octstr_imm("receive-port")) < 0)
01695 portno = 0;
01696 privdata->rport = portno;
01697
01698 if (cfg_get_integer(&alt_portno, cfg, octstr_imm("alt-port")) < 0)
01699 alt_portno = 0;
01700 privdata->alt_port = alt_portno;
01701
01702 allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
01703 if (allow_ip)
01704 deny_ip = octstr_create("*.*.*.*");
01705 else
01706 deny_ip = NULL;
01707 privdata->username = cfg_get(cfg, octstr_imm("smsc-username"));
01708 privdata->password = cfg_get(cfg, octstr_imm("smsc-password"));
01709
01710 privdata->my_number = cfg_get(cfg, octstr_imm("my-number"));
01711
01712 privdata->npid = cfg_get(cfg, octstr_imm("notification-pid"));
01713 privdata->nadc = cfg_get(cfg, octstr_imm("notification-addr"));
01714
01715 if ( (privdata->username == NULL && privdata->my_number == NULL)
01716 || cfg_get_integer(&keepalive, cfg, octstr_imm("keepalive")) < 0)
01717 privdata->keepalive = 0;
01718 else
01719 privdata->keepalive = keepalive;
01720
01721 if (cfg_get_integer(&flowcontrol, cfg, octstr_imm("flow-control")) < 0)
01722 privdata->flowcontrol = 0;
01723 else
01724 privdata->flowcontrol = flowcontrol;
01725 if (privdata->flowcontrol < 0 || privdata->flowcontrol > 1) {
01726 error(0, "EMI2[%s]: 'flow-control' invalid in emi2 configuration.",
01727 octstr_get_cstr(privdata->name));
01728 goto error;
01729 }
01730
01731 if (cfg_get_integer(&window, cfg, octstr_imm("window")) < 0)
01732 privdata->window = EMI2_MAX_TRN;
01733 else
01734 privdata->window = window;
01735 if (privdata->window > EMI2_MAX_TRN) {
01736 warning(0, "EMI2[%s]: Value of 'window' should be lesser or equal to %d..",
01737 octstr_get_cstr(privdata->name), EMI2_MAX_TRN);
01738 privdata->window = EMI2_MAX_TRN;
01739 }
01740
01741 if (cfg_get_integer(&waitack, cfg, octstr_imm("wait-ack")) < 0)
01742 privdata->waitack = 60;
01743 else
01744 privdata->waitack = waitack;
01745 if (privdata->waitack < 30 ) {
01746 error(0, "EMI2[%s]: 'wait-ack' invalid in emi2 configuration.",
01747 octstr_get_cstr(privdata->name));
01748 goto error;
01749 }
01750
01751 if (cfg_get_integer(&waitack_expire, cfg, octstr_imm("wait-ack-expire")) < 0)
01752 privdata->waitack_expire = 0;
01753 else
01754 privdata->waitack_expire = waitack_expire;
01755 if (privdata->waitack_expire >3 ) {
01756 error(0, "EMI2[%s]: 'wait-ack-expire' invalid in emi2 configuration.",
01757 octstr_get_cstr(privdata->name));
01758 goto error;
01759 }
01760
01761 if (privdata->rport < 0 || privdata->rport > 65535) {
01762 error(0, "EMI2[%s]: 'receive-port' missing/invalid in emi2 configuration.",
01763 octstr_get_cstr(privdata->name));
01764 goto error;
01765 }
01766
01767 if (cfg_get_integer(&alt_charset, cfg, octstr_imm("alt-charset")) < 0)
01768 privdata->alt_charset = 0;
01769 else
01770 privdata->alt_charset = alt_charset;
01771
01772 privdata->allow_ip = allow_ip;
01773 privdata->deny_ip = deny_ip;
01774
01775 if (privdata->rport > 0 && emi2_open_listening_socket(conn,privdata) < 0) {
01776 gw_free(privdata);
01777 privdata = NULL;
01778 goto error;
01779 }
01780
01781 conn->data = privdata;
01782
01783 conn->name = octstr_format("EMI2:%S:%d:%S", privdata->host, privdata->port,
01784 privdata->username ? privdata->username : octstr_imm("null"));
01785
01786 privdata->shutdown = 0;
01787
01788 for (i = 0; i < EMI2_MAX_TRN; i++)
01789 privdata->slots[i].sendtime = 0;
01790 privdata->unacked = 0;
01791
01792 conn->status = SMSCCONN_CONNECTING;
01793 conn->connect_time = time(NULL);
01794
01795 if ( privdata->rport > 0 && (privdata->receiver_thread =
01796 gwthread_create(emi2_listener, conn)) == -1)
01797 goto error;
01798
01799 if ((privdata->sender_thread = gwthread_create(emi2_sender, conn)) == -1) {
01800 privdata->shutdown = 1;
01801 if (privdata->rport > 0) {
01802 gwthread_wakeup(privdata->receiver_thread);
01803 gwthread_join(privdata->receiver_thread);
01804 }
01805 goto error;
01806 }
01807
01808 conn->shutdown = shutdown_cb;
01809 conn->queued = queued_cb;
01810 conn->start_conn = start_cb;
01811 conn->send_msg = add_msg_cb;
01812
01813 return 0;
01814
01815 error:
01816 error(0, "EMI2[%s]: Failed to create emi2 smsc connection",
01817 octstr_get_cstr(privdata->name));
01818 if (privdata != NULL) {
01819 gw_prioqueue_destroy(privdata->outgoing_queue, NULL);
01820 }
01821 gw_free(privdata);
01822 octstr_destroy(allow_ip);
01823 octstr_destroy(deny_ip);
01824 octstr_destroy(host);
01825 conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
01826 conn->status = SMSCCONN_DEAD;
01827 info(0, "EMI2[%s]: exiting", octstr_get_cstr(privdata->name));
01828 return -1;
01829 }
|
Here is the call graph for this function:

|
|
Definition at line 1586 of file smsc_emi.c. References smscconn::data, debug(), gwthread_wakeup(), privdata::name, octstr_get_cstr, PrivData, privdata::receiver_thread, privdata::rport, and SMSCConn. 01587 {
01588 PrivData *privdata = conn->data;
01589
01590 /* in case there are messages in the buffer already */
01591 if (privdata->rport > 0)
01592 gwthread_wakeup(privdata->receiver_thread);
01593 debug("smsc.emi2", 0, "EMI2[%s]: start called",
01594 octstr_get_cstr(privdata->name));
01595 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 182 of file smsc_emi.c. References conn_eof(), conn_error(), conn_read_packet(), conn_wait(), emimsg_destroy(), error(), emimsg::fields, get_fields(), privdata::name, octstr_destroy(), octstr_get_char(), octstr_get_cstr, emimsg::or, emimsg::ot, PrivData, privdata::shutdown, emimsg::trn, and warning(). 00183 {
00184 time_t timeout_time;
00185 int time_left;
00186 Octstr *str;
00187 struct emimsg *emimsg;
00188
00189 timeout_time = time(NULL) + t;
00190 while (1) {
00191 str = conn_read_packet(server, 2, 3);
00192 if (conn_eof(server)) {
00193 error(0, "EMI2[%s]: connection closed in wait_for_ack",
00194 octstr_get_cstr(privdata->name));
00195 return -1;
00196 }
00197 if (conn_error(server)) {
00198 error(0, "EMI2[%s]: connection error in wait_for_ack",
00199 octstr_get_cstr(privdata->name));
00200 return -1;
00201 }
00202 if (str) {
00203 emimsg = get_fields(str, privdata->name);
00204 if (emimsg == NULL) {
00205 octstr_destroy(str);
00206 continue;
00207 }
00208 if (emimsg->ot == ot && emimsg->trn == 0 && emimsg->or == 'R') {
00209 octstr_destroy(str);
00210 break;
00211 }
00212 warning(0, "EMI2[%s]: ignoring message %s while waiting for ack to"
00213 "ot:%d trn:%d", octstr_get_cstr(privdata->name),
00214 octstr_get_cstr(str), ot, 0);
00215 emimsg_destroy(emimsg);
00216 octstr_destroy(str);
00217 }
00218 time_left = timeout_time - time(NULL);
00219 if (time_left < 0 || privdata->shutdown)
00220 return 0;
00221 conn_wait(server, time_left);
00222 }
00223 if (octstr_get_char(emimsg->fields[0], 0) == 'N') {
00224 emimsg_destroy(emimsg);
00225 return -2;
00226 }
00227 emimsg_destroy(emimsg);
00228 return 1;
00229 }
|
Here is the call graph for this function:
