Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
smsc_smasi.c File Reference
#include "gwlib/gwlib.h"
#include "msg.h"
#include "smsc_p.h"
#include "smasi_pdu.h"
#include "smscconn_p.h"
#include "bb_smscconn_cb.h"
#include "sms.h"
#include "dlr.h"

Go to the source code of this file.

Data Structures

struct  SMASI
 

Macros

#define DEBUG   1
 
#define SMASI_DEFAULT_PORT   21500
 
#define SMASI_DEFAULT_PRIORITY   0
 
#define MAX_PENDING_SUBMITS   10
 
#define SMASI_THROTTLING_SLEEP_TIME   15
 
#define SMASI_ENQUIRE_LINK_INTERVAL   30.0
 
#define SMASI_OVERRIDE_SOURCE_TON   1
 
#define SMASI_OVERRIDE_SOURCE_NPI   -1
 
#define SMASI_OVERRIDE_DEST_TON   -1
 
#define SMASI_OVERRIDE_DEST_NPI   -1
 

Functions

static void dump_pdu (const char *msg, Octstr *id, SMASI_PDU *pdu)
 
static SMASIsmasi_create (SMSCConn *conn)
 
static void smasi_destroy (SMASI *smasi)
 
static void escape_data (Octstr *data)
 
static void unescape_data (Octstr *data)
 
static void encode_binary_data (Octstr *data)
 
static void decode_binary_data (Octstr *data)
 
static Octstrget_ton_npi_value (int override, int message)
 
static Octstrget_source_addr_ton (SMASI *smasi, Msg *msg)
 
static Octstrget_source_addr_npi (SMASI *smasi, Msg *msg)
 
static Octstrget_dest_addr_ton (SMASI *smasi, Msg *msg)
 
static Octstrget_dest_addr_npi (SMASI *smasi, Msg *msg)
 
static Octstrget_originator_type (SMASI *smasi, Octstr *originator)
 
static SMASI_PDUmsg_to_pdu (SMASI *smasi, Msg *msg)
 
static Msgpdu_to_msg (SMASI_PDU *pdu)
 
static void send_logoff (SMASI *smasi, Connection *conn)
 
static void send_enquire_link (SMASI *smasi, Connection *conn, long *last_sent)
 
static int send_pdu (Connection *conn, Octstr *id, SMASI_PDU *pdu)
 
static int read_pdu (SMASI *smasi, Connection *conn, SMASI_PDU **pdu)
 
static void handle_pdu (SMASI *smasi, Connection *conn, SMASI_PDU *pdu, long *pending_submits)
 
static Connectionopen_connection (SMASI *smasi)
 
static void send_messages (SMASI *smasi, Connection *conn, long *pending_submits)
 
static void smasi_thread (void *arg)
 
static long queued_cb (SMSCConn *conn)
 
static int send_msg_cb (SMSCConn *conn, Msg *msg)
 
static int shutdown_cb (SMSCConn *conn, int finish_sending)
 
static int init_configuration (SMASI *smasi, CfgGroup *config)
 
int smsc_smasi_create (SMSCConn *conn, CfgGroup *config)
 

Variables

static Octstrcolon = NULL
 
static Octstrassign = NULL
 
static Octstrcomma = NULL
 
static Octstrcr = NULL
 
static Octstrlf = NULL
 

Macro Definition Documentation

#define DEBUG   1

Definition at line 91 of file smsc_smasi.c.

#define MAX_PENDING_SUBMITS   10

Definition at line 110 of file smsc_smasi.c.

Referenced by send_messages().

#define SMASI_DEFAULT_PORT   21500

Definition at line 108 of file smsc_smasi.c.

Referenced by init_configuration().

#define SMASI_DEFAULT_PRIORITY   0

Definition at line 109 of file smsc_smasi.c.

Referenced by init_configuration().

#define SMASI_ENQUIRE_LINK_INTERVAL   30.0

Definition at line 112 of file smsc_smasi.c.

Referenced by init_configuration().

#define SMASI_OVERRIDE_DEST_NPI   -1

Definition at line 128 of file smsc_smasi.c.

Referenced by init_configuration().

#define SMASI_OVERRIDE_DEST_TON   -1

Definition at line 127 of file smsc_smasi.c.

Referenced by init_configuration().

#define SMASI_OVERRIDE_SOURCE_NPI   -1

Definition at line 126 of file smsc_smasi.c.

Referenced by init_configuration().

#define SMASI_OVERRIDE_SOURCE_TON   1

Definition at line 125 of file smsc_smasi.c.

Referenced by init_configuration().

#define SMASI_THROTTLING_SLEEP_TIME   15

Definition at line 111 of file smsc_smasi.c.

Referenced by smasi_thread().

Function Documentation

static void decode_binary_data ( Octstr data)
static

Definition at line 341 of file smsc_smasi.c.

References check(), error(), octstr_append_char(), octstr_create, octstr_delete(), octstr_destroy(), octstr_get_char(), octstr_hex_to_binary(), octstr_insert(), and octstr_len().

Referenced by pdu_to_msg().

342 {
343  long pos = 0;
344 
345  while (pos < octstr_len(data)) {
346  int check = octstr_get_char(data, pos);
347 
348  if (check == ':') {
349  Octstr *byte;
350  int msb = octstr_get_char(data, pos + 1);
351  int lsb = octstr_get_char(data, pos + 2);
352 
353  if (msb != -1 && lsb != -1) {
354  byte = octstr_create("");
355  octstr_append_char(byte, msb);
356  octstr_append_char(byte, lsb);
357 
358  if (octstr_hex_to_binary(byte) != -1) {
359  /* Do inplace unescaping. */
360  octstr_delete(data, pos, 3);
361  octstr_insert(data, byte, pos);
362  } else {
363  error(0, "Malformed binary encoded data.");
364  }
365 
366  octstr_destroy(byte);
367  }
368  }
369  pos++;
370  }
371 }
void error(int err, const char *fmt,...)
Definition: log.c:612
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
static void check(void *arg)
Definition: check_counter.c:76
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
Definition: octstr.c:1301
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
int octstr_hex_to_binary(Octstr *ostr)
Definition: octstr.c:492
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static void dump_pdu ( const char *  msg,
Octstr id,
SMASI_PDU pdu 
)
static

Definition at line 96 of file smsc_smasi.c.

References debug(), octstr_get_cstr, and smasi_pdu_dump().

Referenced by send_enquire_link(), send_logoff(), send_pdu(), and smasi_thread().

97 {
98  debug("bb.sms.smasi", 0, "SMASI[%s]: %s", octstr_get_cstr(id), msg);
99  smasi_pdu_dump(pdu);
100 }
void smasi_pdu_dump(SMASI_PDU *pdu)
Definition: smasi_pdu.c:280
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static void encode_binary_data ( Octstr data)
static

Definition at line 305 of file smsc_smasi.c.

References octstr_append(), octstr_append_char(), octstr_create, octstr_delete(), octstr_destroy(), octstr_get_char(), and octstr_len().

Referenced by msg_to_pdu().

306 {
307  Octstr *result = octstr_create("");
308  long pos = 0;
309 
310  while (pos < octstr_len(data)) {
311  int encode = octstr_get_char(data, pos);
312  int msb = (encode & 0xf0) >> 4;
313  int lsb = (encode & 0x0f) >> 0;
314 
315  if (msb == 0) msb = '0';
316  else if (msb < 10) msb = '1' + msb - 1;
317  else msb = 'a' + msb - 10;
318 
319  if (lsb == 0) lsb = '0';
320  else if (lsb < 10) lsb = '1' + lsb - 1;
321  else lsb = 'a' + lsb - 10;
322 
323  octstr_append_char(result, ':');
324  octstr_append_char(result, msb);
325  octstr_append_char(result, lsb);
326 
327  pos++;
328  }
329  /* Replace binary data octet string with ASCII representation. */
330  octstr_delete(data, 0, octstr_len(data));
331  octstr_append(data, result);
332  octstr_destroy(result);
333 }
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static void escape_data ( Octstr data)
static

Definition at line 229 of file smsc_smasi.c.

References assign, check(), colon, comma, cr, lf, octstr_delete(), octstr_get_char(), octstr_insert(), and octstr_len().

Referenced by msg_to_pdu().

230 {
231  long pos = 0;
232 
233  /* This one uses a different approach than the encode and decode
234  * functions. Because it is assumed, that only a fraction of the
235  * contained chars have to be escaped.
236  */
237  while (pos < octstr_len(data)) {
238  Octstr * escaped = NULL;
239  int check = octstr_get_char(data, pos);
240 
241  if (check == ':') escaped = colon;
242  else if (check == '=') escaped = assign;
243  else if (check == ',') escaped = comma;
244  else if (check == '\n') escaped = cr;
245  else if (check == '\r') escaped = lf;
246 
247  if (escaped != NULL) {
248  /* If the current char has to be escaped, delete the char from
249  * the source string, replace it with the escape sequence, and
250  * advance position until after the inserted sequence.
251  */
252  octstr_delete(data, pos, 1);
253  octstr_insert(data, escaped, pos);
254  pos += octstr_len(escaped);
255  } else {
256  /* If not escaped, simply skip the current char. */
257  pos++;
258  }
259  }
260 }
static Octstr * cr
Definition: smsc_smasi.c:221
static Octstr * comma
Definition: smsc_smasi.c:220
static void check(void *arg)
Definition: check_counter.c:76
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
Definition: octstr.c:1301
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
static Octstr * colon
Definition: smsc_smasi.c:218
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static Octstr * lf
Definition: smsc_smasi.c:222
static Octstr * assign
Definition: smsc_smasi.c:219
static Octstr* get_dest_addr_npi ( SMASI smasi,
Msg msg 
)
static

Definition at line 431 of file smsc_smasi.c.

References SMASI::dest_addr_npi, get_ton_npi_value(), and GSM_ADDR_NPI_E164.

Referenced by msg_to_pdu().

432 {
433  return get_ton_npi_value(smasi->dest_addr_npi,
435 }
static Octstr * get_ton_npi_value(int override, int message)
Definition: smsc_smasi.c:378
#define GSM_ADDR_NPI_E164
Definition: smasi_pdu.h:112
long dest_addr_npi
Definition: smsc_smasi.c:150
static Octstr* get_dest_addr_ton ( SMASI smasi,
Msg msg 
)
static

Definition at line 419 of file smsc_smasi.c.

References SMASI::dest_addr_ton, get_ton_npi_value(), and GSM_ADDR_TON_INTERNATIONAL.

Referenced by msg_to_pdu().

420 {
421  return get_ton_npi_value(smasi->dest_addr_ton,
423 }
#define GSM_ADDR_TON_INTERNATIONAL
Definition: smasi_pdu.h:103
static Octstr * get_ton_npi_value(int override, int message)
Definition: smsc_smasi.c:378
long dest_addr_ton
Definition: smsc_smasi.c:149
static Octstr* get_originator_type ( SMASI smasi,
Octstr originator 
)
static

Definition at line 442 of file smsc_smasi.c.

References GSM_ADDR_TON_ALPHANUMERIC, GSM_ADDR_TON_INTERNATIONAL, gw_isdigit(), octstr_check_range(), octstr_delete(), octstr_format(), and octstr_get_char().

Referenced by msg_to_pdu().

443 {
444  /* International or alphanumeric sender? */
445  if (octstr_get_char(originator, 0) == '+') {
446  if (!octstr_check_range(originator, 1, 256, gw_isdigit)) {
448  } else {
449  /* Numeric sender address with + in front: The + has to be
450  * removed from this international number.
451  */
452  octstr_delete(originator, 0, 1);
454  }
455  } else if (!octstr_check_range(originator, 0, 256, gw_isdigit)) {
457  }
458 
459  /* Return the default value. */
461 }
int octstr_check_range(Octstr *ostr, long pos, long len, octstr_func_t filter)
Definition: octstr.c:812
#define GSM_ADDR_TON_INTERNATIONAL
Definition: smasi_pdu.h:103
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
int gw_isdigit(int c)
Definition: utils.c:988
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
#define GSM_ADDR_TON_ALPHANUMERIC
Definition: smasi_pdu.h:107
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static Octstr* get_source_addr_npi ( SMASI smasi,
Msg msg 
)
static

Definition at line 407 of file smsc_smasi.c.

References get_ton_npi_value(), GSM_ADDR_NPI_E164, and SMASI::source_addr_npi.

Referenced by msg_to_pdu().

408 {
409  return get_ton_npi_value(smasi->source_addr_npi,
411 }
long source_addr_npi
Definition: smsc_smasi.c:148
static Octstr * get_ton_npi_value(int override, int message)
Definition: smsc_smasi.c:378
#define GSM_ADDR_NPI_E164
Definition: smasi_pdu.h:112
static Octstr* get_source_addr_ton ( SMASI smasi,
Msg msg 
)
static

Definition at line 395 of file smsc_smasi.c.

References get_ton_npi_value(), GSM_ADDR_TON_INTERNATIONAL, and SMASI::source_addr_ton.

Referenced by msg_to_pdu().

396 {
397  return get_ton_npi_value(smasi->source_addr_ton,
399 }
#define GSM_ADDR_TON_INTERNATIONAL
Definition: smasi_pdu.h:103
static Octstr * get_ton_npi_value(int override, int message)
Definition: smsc_smasi.c:378
long source_addr_ton
Definition: smsc_smasi.c:147
static Octstr* get_ton_npi_value ( int  override,
int  message 
)
static

Definition at line 378 of file smsc_smasi.c.

References debug(), and octstr_format().

Referenced by get_dest_addr_npi(), get_dest_addr_ton(), get_source_addr_npi(), and get_source_addr_ton().

379 {
380  if (override != -1) {
381  debug("bb.sms.smasi", 0, "SMASI: Manually forced ton or npi to `%d'",
382  override);
383  return (octstr_format("%ld", override));
384  } else {
385  return (octstr_format("%ld", message));
386  }
387 }
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
static void handle_pdu ( SMASI smasi,
Connection conn,
SMASI_PDU pdu,
long *  pending_submits 
)
static

Definition at line 711 of file smsc_smasi.c.

References bb_smscconn_connected(), bb_smscconn_receive(), bb_smscconn_send_failed(), bb_smscconn_sent(), SMASI::conn, smscconn::connect_time, debug(), dict_remove(), error(), smscconn::id, info(), SMASI::logged_off, msg, msg_dump(), SMASI::my_number, octstr_create, octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_len(), pdu_to_msg(), send_pdu(), SMASI::sent_msgs, smasi_pdu_create(), smasi_pdu_destroy(), SMSCCONN_ACTIVE, SMSCCONN_FAILED_REJECTED, smscconn::status, SMASI_PDU::type, SMASI_PDU::type_name, SMASI_PDU::u, and warning().

Referenced by smasi_thread().

713 {
714  SMASI_PDU *resp = NULL;
715  Msg *msg = NULL;
716  long reason;
717 
718  switch (pdu->type) {
719 
720  case DeliverReq:
721  msg = pdu_to_msg(pdu);
722 
723  msg_dump(msg, 0);
724 
725  if (smasi->my_number && octstr_len(smasi->my_number)) {
726  octstr_destroy(msg->sms.receiver);
727  msg->sms.receiver = octstr_duplicate(smasi->my_number);
728  }
729 
730  time(&msg->sms.time);
731  msg->sms.smsc_id = octstr_duplicate(smasi->conn->id);
732  bb_smscconn_receive(smasi->conn, msg);
733  resp = smasi_pdu_create(DeliverConf);
734 
735  if (pdu->u.DeliverReq.Sequence)
736  resp->u.DeliverConf.Sequence =
737  octstr_duplicate(pdu->u.DeliverReq.Sequence);
738 
739  if (pdu->u.DeliverReq.MsgReference)
740  resp->u.DeliverConf.MsgReference =
741  octstr_duplicate(pdu->u.DeliverReq.MsgReference);
742  break;
743 
744  case SubmitConf:
745  if (pdu->u.SubmitConf.Sequence) {
746  msg = dict_remove(smasi->sent_msgs,
747  pdu->u.SubmitConf.Sequence);
748  } else {
749  msg = NULL;
750  }
751 
752  if (msg == NULL) {
753  warning(0, "SMASI[%s]: SMSC sent SubmitConf for unknown message.",
754  octstr_get_cstr(smasi->conn->id));
755  } else {
756  debug("bb.sms.smasi",0,
757  "SMSC[%s]: SMSC confirmed msg seq <%s> ref <%s>",
758  octstr_get_cstr(smasi->conn->id),
759  octstr_get_cstr(pdu->u.SubmitConf.Sequence),
760  octstr_get_cstr(pdu->u.SubmitConf.MsgReference));
761 
762  bb_smscconn_sent(smasi->conn, msg, NULL);
763 
764  --(*pending_submits);
765  }
766  break;
767 
768  case SubmitRej:
769  if (pdu->u.SubmitRej.Sequence) {
770  msg = dict_remove(smasi->sent_msgs,
771  pdu->u.SubmitRej.Sequence);
772  } else {
773  msg = NULL;
774  }
775 
776  error(0, "SMASI[%s]: SMSC returned error code %s for "
777  "message ref <%s>", octstr_get_cstr(smasi->conn->id),
778  octstr_get_cstr(pdu->u.SubmitRej.RejectCode),
779  octstr_get_cstr(pdu->u.SubmitRej.MsgReference));
780 
781  if (msg == NULL) {
782  warning(0, "SMASI[%s]: SMSC sent SubmitRej for unknown message.",
783  octstr_get_cstr(smasi->conn->id));
784  } else {
785  reason = SMSCCONN_FAILED_REJECTED;
786  bb_smscconn_send_failed(smasi->conn, msg, reason,
787  octstr_create("REJECTED"));
788  --(*pending_submits);
789  }
790  break;
791 
792  case LogonConf:
793  *pending_submits = 0;
794 
795  smasi->conn->status = SMSCCONN_ACTIVE;
796  smasi->conn->connect_time = time(NULL);
797 
798  bb_smscconn_connected(smasi->conn);
799 
800  info(0, "SMASI[%s]: connection to SMSC established.",
801  octstr_get_cstr(smasi->conn->id));
802  break;
803 
804  case LogonRej:
805  if (octstr_len(pdu->u.LogonRej.Reason) > 0) {
806  error(0, "SMASI[%s]: SMSC rejected login with reason <%s>",
807  octstr_get_cstr(smasi->conn->id),
808  octstr_get_cstr(pdu->u.LogonRej.Reason));
809  } else {
810  error(0, "SMASI[%s]: SMSC rejected login without reason",
811  octstr_get_cstr(smasi->conn->id));
812  }
813  break;
814 
815  case LogoffConf:
816  info(0, "SMASI[%s]: SMSC confirmed logoff.",
817  octstr_get_cstr(smasi->conn->id));
818  smasi->logged_off = 1;
819  break;
820 
821  default:
822  warning(0, "SMASI[%s]: Unknown PDU type <%s>, ignored.",
823  octstr_get_cstr(smasi->conn->id), pdu->type_name);
824  break;
825  }
826 
827  if (resp != NULL) {
828  send_pdu(conn, smasi->conn->id, resp);
829  smasi_pdu_destroy(resp);
830  }
831 }
static int send_pdu(Connection *conn, Octstr *id, SMASI_PDU *pdu)
Definition: smsc_smasi.c:665
void msg_dump(Msg *msg, int level)
Definition: msg.c:152
void error(int err, const char *fmt,...)
Definition: log.c:612
const char * type_name
Definition: smasi_pdu.h:86
SMSCConn * conn
Definition: smsc_smasi.c:136
void info(int err, const char *fmt,...)
Definition: log.c:636
Dict * sent_msgs
Definition: smsc_smasi.c:139
void bb_smscconn_connected(SMSCConn *conn)
Definition: bb_smscconn.c:192
Octstr * id
Definition: smscconn_p.h:174
unsigned long type
Definition: smasi_pdu.h:85
int logged_off
Definition: smsc_smasi.c:155
SMASI_PDU * smasi_pdu_create(unsigned long type)
Definition: smasi_pdu.c:132
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * my_number
Definition: smsc_smasi.c:146
Definition: msg.h:79
void * dict_remove(Dict *dict, Octstr *key)
Definition: dict.c:307
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:478
time_t connect_time
Definition: smscconn_p.h:155
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void warning(int err, const char *fmt,...)
Definition: log.c:624
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:279
static Msg * pdu_to_msg(SMASI_PDU *pdu)
Definition: smsc_smasi.c:552
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
smscconn_status_t status
Definition: smscconn_p.h:151
union SMASI_PDU::@11 u
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:328
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void smasi_pdu_destroy(SMASI_PDU *pdu)
Definition: smasi_pdu.c:160
static int init_configuration ( SMASI smasi,
CfgGroup config 
)
static

Definition at line 1071 of file smsc_smasi.c.

References cfg_get, cfg_get_integer(), SMASI::conn, smscconn::data, SMASI::dest_addr_npi, SMASI::dest_addr_ton, SMASI::enquire_link_interval, error(), SMASI::host, smscconn::id, SMASI::my_number, smscconn::name, octstr_duplicate, octstr_format(), octstr_imm(), SMASI::password, SMASI::port, SMASI::priority, SMASI_DEFAULT_PORT, SMASI_DEFAULT_PRIORITY, SMASI_ENQUIRE_LINK_INTERVAL, SMASI_OVERRIDE_DEST_NPI, SMASI_OVERRIDE_DEST_TON, SMASI_OVERRIDE_SOURCE_NPI, SMASI_OVERRIDE_SOURCE_TON, SMASI::source_addr_npi, SMASI::source_addr_ton, and SMASI::username.

Referenced by smsc_smasi_create().

1072 {
1073  /* Read mandatory entries. */
1074  smasi->host = cfg_get(config, octstr_imm("host"));
1075  smasi->username = cfg_get(config, octstr_imm("smsc-username"));
1076  smasi->password = cfg_get(config, octstr_imm("smsc-password"));
1077 
1078  /* Check configuration. */
1079  if (smasi->host == NULL) {
1080  error(0,"SMASI: Configuration file doesn't specify host");
1081  return -1;
1082  }
1083  if (smasi->username == NULL) {
1084  error(0, "SMASI: Configuration file doesn't specify username.");
1085  return -1;
1086  }
1087  if (smasi->password == NULL) {
1088  error(0, "SMASI: Configuration file doesn't specify password.");
1089  return -1;
1090  }
1091 
1092  /* Read optional entries. Set default values if not set. */
1093  smasi->my_number = cfg_get(config, octstr_imm("my-number"));
1094  if (cfg_get_integer(&smasi->port, config, octstr_imm("port")) == -1)
1095  smasi->port = SMASI_DEFAULT_PORT;
1096  if (cfg_get_integer(&smasi->source_addr_ton, config,
1097  octstr_imm("source-addr-ton")) == -1)
1099  if (cfg_get_integer(&smasi->source_addr_npi, config,
1100  octstr_imm("source-addr-npi")) == -1)
1102  if (cfg_get_integer(&smasi->dest_addr_ton, config,
1103  octstr_imm("dest-addr-ton")) == -1)
1105  if (cfg_get_integer(&smasi->dest_addr_npi, config,
1106  octstr_imm("dest-addr-npi")) == -1)
1108  if (cfg_get_integer(&smasi->priority, config,
1109  octstr_imm("priority")) == -1)
1111  if (cfg_get_integer(&smasi->enquire_link_interval, config,
1112  octstr_imm("enquire-link-interval")) == -1)
1114 
1115  /* Configure SMSC connection. */
1116  smasi->conn->data = smasi;
1117  smasi->conn->name = octstr_format("SMASI:%S:%d:%S",
1118  smasi->host, smasi->port, smasi->username);
1119 
1120  smasi->conn->id = cfg_get(config, octstr_imm("smsc-id"));
1121 
1122  if (smasi->conn->id == NULL)
1123  smasi->conn->id = octstr_duplicate(smasi->conn->name);
1124 
1125  return 0;
1126 }
Octstr * name
Definition: smscconn_p.h:173
void error(int err, const char *fmt,...)
Definition: log.c:612
SMSCConn * conn
Definition: smsc_smasi.c:136
long source_addr_npi
Definition: smsc_smasi.c:148
#define SMASI_OVERRIDE_SOURCE_TON
Definition: smsc_smasi.c:125
#define SMASI_OVERRIDE_SOURCE_NPI
Definition: smsc_smasi.c:126
#define SMASI_DEFAULT_PRIORITY
Definition: smsc_smasi.c:109
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
#define SMASI_OVERRIDE_DEST_TON
Definition: smsc_smasi.c:127
#define cfg_get(grp, varname)
Definition: cfg.h:86
long enquire_link_interval
Definition: smsc_smasi.c:154
Octstr * my_number
Definition: smsc_smasi.c:146
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Octstr * host
Definition: smsc_smasi.c:142
#define octstr_duplicate(ostr)
Definition: octstr.h:187
Octstr * password
Definition: smsc_smasi.c:145
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
#define SMASI_ENQUIRE_LINK_INTERVAL
Definition: smsc_smasi.c:112
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
long dest_addr_npi
Definition: smsc_smasi.c:150
long dest_addr_ton
Definition: smsc_smasi.c:149
#define SMASI_DEFAULT_PORT
Definition: smsc_smasi.c:108
Octstr * username
Definition: smsc_smasi.c:144
long priority
Definition: smsc_smasi.c:151
#define SMASI_OVERRIDE_DEST_NPI
Definition: smsc_smasi.c:128
long source_addr_ton
Definition: smsc_smasi.c:147
long port
Definition: smsc_smasi.c:143
static SMASI_PDU* msg_to_pdu ( SMASI smasi,
Msg msg 
)
static

Definition at line 467 of file smsc_smasi.c.

References counter_increase(), DC_7BIT, DC_8BIT, DC_UCS2, DC_UNDEF, encode_binary_data(), escape_data(), get_dest_addr_npi(), get_dest_addr_ton(), get_originator_type(), get_source_addr_npi(), get_source_addr_ton(), MC_UNDEF, SMASI::message_id_counter, octstr_create, octstr_delete(), octstr_destroy(), octstr_duplicate, octstr_format(), octstr_get_char(), octstr_len(), SMASI::priority, smasi_pdu_create(), SMS_PARAM_UNDEFINED, and SMASI_PDU::u.

Referenced by send_messages().

468 {
469  SMASI_PDU *pdu = smasi_pdu_create(SubmitReq);
470 
471  pdu->u.SubmitReq.Destination = octstr_duplicate(msg->sms.receiver);
472  pdu->u.SubmitReq.Body = octstr_duplicate(msg->sms.msgdata);
473  pdu->u.SubmitReq.Originator = octstr_duplicate(msg->sms.sender);
474 
475  pdu->u.SubmitReq.OriginatorType =
476  get_originator_type(smasi, pdu->u.SubmitReq.Originator);
477 
478  pdu->u.SubmitReq.Sequence =
480 
481 
482  /* If its a international number starting with +, lets remove the +. */
483  if (octstr_get_char(pdu->u.SubmitReq.Destination, 0) == '+')
484  octstr_delete(pdu->u.SubmitReq.Destination, 0, 1);
485 
486  /* Do ton and npi override - if configured. Use values from message
487  * otherwise.
488  */
489  pdu->u.SubmitReq.OriginatorType = get_source_addr_ton(smasi, msg);
490  pdu->u.SubmitReq.OriginatorPlan = get_source_addr_npi(smasi, msg);
491  pdu->u.SubmitReq.DestinationType = get_dest_addr_ton(smasi, msg);
492  pdu->u.SubmitReq.DestinationPlan = get_dest_addr_npi(smasi, msg);
493 
494  /* Set priority. */
495  if (smasi->priority >= 0 && smasi->priority <= 3) {
496  pdu->u.SubmitReq.MqPriority = octstr_format("%ld", smasi->priority);
497  } else {
498  pdu->u.SubmitReq.MqPriority = octstr_format("%ld", 0);
499  }
500 
501  /* Set encoding. */
502  if (msg->sms.coding != DC_UNDEF) {
503  if (msg->sms.coding == DC_7BIT)
504  pdu->u.SubmitReq.MsEncoding = octstr_create("7bit");
505  else if (msg->sms.coding == DC_8BIT)
506  pdu->u.SubmitReq.MsEncoding = octstr_create("8bit");
507  else if (msg->sms.coding == DC_UCS2)
508  pdu->u.SubmitReq.MsEncoding = octstr_create("16bit");
509 
510  /* Everything else will default to 7bit. */
511  }
512 
513  /* Set messaging class - if within defined parameter range. */
514  if (msg->sms.mclass != MC_UNDEF)
515  pdu->u.SubmitReq.Class = octstr_format("%ld", msg->sms.mclass);
516 
517  /* Set Protocol ID. */
518  pdu->u.SubmitReq.ProtocolID = octstr_format("%ld",
519  (msg->sms.pid == SMS_PARAM_UNDEFINED ? 0 : msg->sms.pid));
520 
521  /* Check if SMS is binary. */
522  if (msg->sms.udhdata && octstr_len(msg->sms.udhdata) > 0) {
523 
524  pdu->u.SubmitReq.UserDataHeader =
525  octstr_duplicate(msg->sms.udhdata);
526 
527  pdu->u.SubmitReq.BodyEncoding =
528  octstr_create("Data");
529 
530  if (pdu->u.SubmitReq.MsEncoding)
531  octstr_destroy(pdu->u.SubmitReq.MsEncoding);
532 
533  pdu->u.SubmitReq.MsEncoding =
534  octstr_create("transparent");
535 
536  /* Encode data. */
537  encode_binary_data(pdu->u.SubmitReq.UserDataHeader);
538  encode_binary_data(pdu->u.SubmitReq.Body);
539  } else {
540 
541  /* Otherwise do data escaping. */
542  escape_data(pdu->u.SubmitReq.Body);
543  }
544 
545  return pdu;
546 }
#define DC_8BIT
Definition: sms.h:111
static void escape_data(Octstr *data)
Definition: smsc_smasi.c:229
SMASI_PDU * smasi_pdu_create(unsigned long type)
Definition: smasi_pdu.c:132
static void encode_binary_data(Octstr *data)
Definition: smsc_smasi.c:305
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
static Octstr * get_originator_type(SMASI *smasi, Octstr *originator)
Definition: smsc_smasi.c:442
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
static Octstr * get_source_addr_npi(SMASI *smasi, Msg *msg)
Definition: smsc_smasi.c:407
#define octstr_duplicate(ostr)
Definition: octstr.h:187
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
static Octstr * get_source_addr_ton(SMASI *smasi, Msg *msg)
Definition: smsc_smasi.c:395
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
#define MC_UNDEF
Definition: sms.h:93
static Octstr * get_dest_addr_npi(SMASI *smasi, Msg *msg)
Definition: smsc_smasi.c:431
static Octstr * get_dest_addr_ton(SMASI *smasi, Msg *msg)
Definition: smsc_smasi.c:419
union SMASI_PDU::@11 u
long priority
Definition: smsc_smasi.c:151
#define DC_UNDEF
Definition: sms.h:109
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
Counter * message_id_counter
Definition: smsc_smasi.c:141
#define DC_UCS2
Definition: sms.h:112
#define DC_7BIT
Definition: sms.h:110
static Connection* open_connection ( SMASI smasi)
static

Definition at line 843 of file smsc_smasi.c.

References SMASI::conn, conn_open_tcp_with_port(), counter_increase(), error(), SMASI::host, smscconn::id, SMASI::message_id_counter, octstr_duplicate, octstr_get_cstr, smscconn::our_host, SMASI::password, SMASI::port, send_pdu(), smasi_pdu_create(), smasi_pdu_destroy(), SMASI_PDU::u, and SMASI::username.

Referenced by smasi_thread().

844 {
845  Connection *conn = conn_open_tcp_with_port(smasi->host, smasi->port, 0, smasi->conn->our_host);
846 
847  if (conn == NULL) {
848  error(0, "SMASI[%s]: Couldn't connect to server.",
849  octstr_get_cstr(smasi->conn->id));
850  return NULL;
851  } else {
852  SMASI_PDU *logon = smasi_pdu_create(LogonReq);
853 
854  logon->u.LogonReq.Name = octstr_duplicate(smasi->username);
855  logon->u.LogonReq.Password = octstr_duplicate(smasi->password);
856 
858 
859  send_pdu(conn, smasi->conn->id, logon);
860 
861  smasi_pdu_destroy(logon);
862  }
863 
864  return conn;
865 }
static int send_pdu(Connection *conn, Octstr *id, SMASI_PDU *pdu)
Definition: smsc_smasi.c:665
void error(int err, const char *fmt,...)
Definition: log.c:612
SMSCConn * conn
Definition: smsc_smasi.c:136
Octstr * id
Definition: smscconn_p.h:174
Octstr * our_host
Definition: smscconn_p.h:192
SMASI_PDU * smasi_pdu_create(unsigned long type)
Definition: smasi_pdu.c:132
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
Octstr * host
Definition: smsc_smasi.c:142
#define octstr_duplicate(ostr)
Definition: octstr.h:187
Connection * conn_open_tcp_with_port(Octstr *host, int port, int our_port, Octstr *our_host)
Definition: conn.c:540
Octstr * password
Definition: smsc_smasi.c:145
Octstr * username
Definition: smsc_smasi.c:144
union SMASI_PDU::@11 u
long port
Definition: smsc_smasi.c:143
void smasi_pdu_destroy(SMASI_PDU *pdu)
Definition: smasi_pdu.c:160
Counter * message_id_counter
Definition: smsc_smasi.c:141
static Msg* pdu_to_msg ( SMASI_PDU pdu)
static

Definition at line 552 of file smsc_smasi.c.

References DC_7BIT, DC_8BIT, DC_UCS2, decode_binary_data(), gw_assert(), MC_UNDEF, msg, msg_create, octstr_duplicate, octstr_len(), octstr_parse_long(), octstr_str_compare(), SMS_PARAM_UNDEFINED, SMASI_PDU::type, SMASI_PDU::u, and unescape_data().

Referenced by handle_pdu().

553 {
554  Msg *msg = NULL;
555 
556  gw_assert(pdu->type == DeliverReq);
557  gw_assert(pdu->u.DeliverReq.Originator);
558  gw_assert(pdu->u.DeliverReq.Destination);
559  gw_assert(pdu->u.DeliverReq.Body);
560 
561  msg = msg_create(sms);
562 
563  msg->sms.sender = octstr_duplicate(pdu->u.DeliverReq.Originator);
564  msg->sms.receiver = octstr_duplicate(pdu->u.DeliverReq.Destination);
565  msg->sms.msgdata = octstr_duplicate(pdu->u.DeliverReq.Body);
566 
567  /* Read priority. */
568  if (pdu->u.DeliverReq.ProtocolId)
569  if (octstr_parse_long(&msg->sms.pid,
570  pdu->u.DeliverReq.ProtocolId, 0, 10) == -1)
571  msg->sms.pid = SMS_PARAM_UNDEFINED;
572 
573  /* Read Coding. */
574  if (pdu->u.DeliverReq.MsEncoding) {
575 
576  /* Use specified coding. */
577  if (octstr_str_compare(pdu->u.DeliverReq.MsEncoding, "7bit") == 0)
578  msg->sms.coding = DC_7BIT;
579  else if (octstr_str_compare(pdu->u.DeliverReq.MsEncoding, "8bit") == 0)
580  msg->sms.coding = DC_8BIT;
581  else if (octstr_str_compare(pdu->u.DeliverReq.MsEncoding, "UCS2") == 0)
582  msg->sms.coding = DC_UCS2;
583  else if (octstr_str_compare(pdu->u.DeliverReq.MsEncoding, "transparent") == 0)
584  msg->sms.coding = DC_8BIT;
585  } else {
586 
587  /* Determine specified coding according to udhdata presence. */
588  if (pdu->u.DeliverReq.UserDataHeader)
589  msg->sms.coding = DC_8BIT;
590  else
591  msg->sms.coding = DC_7BIT;
592  }
593 
594  /* Unescape (non-binary) or decode (binary) data. */
595  if (msg->sms.coding == DC_8BIT) {
596 
597  decode_binary_data(msg->sms.msgdata);
598  if (pdu->u.DeliverReq.UserDataHeader &&
599  octstr_len(pdu->u.DeliverReq.UserDataHeader) > 0) {
600  msg->sms.udhdata = octstr_duplicate(pdu->u.DeliverReq.UserDataHeader);
601  decode_binary_data(msg->sms.udhdata);
602  }
603 
604  } else {
605  unescape_data(msg->sms.msgdata);
606  }
607 
608  /* Read message class. */
609  if (pdu->u.DeliverReq.Class &&
610  octstr_parse_long(&msg->sms.mclass,
611  pdu->u.DeliverReq.Class, 0, 10) == -1)
612  msg->sms.mclass = MC_UNDEF; /* Set to unspecified. */
613 
614  /* Read protocol ID. */
615  if (pdu->u.DeliverReq.ProtocolId &&
616  octstr_parse_long(&msg->sms.pid,
617  pdu->u.DeliverReq.ProtocolId, 0, 10) == -1)
618  msg->sms.pid = SMS_PARAM_UNDEFINED;
619 
620  return msg;
621 }
static void decode_binary_data(Octstr *data)
Definition: smsc_smasi.c:341
unsigned long type
Definition: smasi_pdu.h:85
#define DC_8BIT
Definition: sms.h:111
#define msg_create(type)
Definition: msg.h:136
static void unescape_data(Octstr *data)
Definition: smsc_smasi.c:267
Definition: msg.h:79
#define octstr_duplicate(ostr)
Definition: octstr.h:187
gw_assert(wtls_machine->packet_to_send!=NULL)
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
#define MC_UNDEF
Definition: sms.h:93
int octstr_str_compare(const Octstr *ostr, const char *str)
Definition: octstr.c:971
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
Definition: octstr.c:747
union SMASI_PDU::@11 u
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
#define DC_UCS2
Definition: sms.h:112
#define DC_7BIT
Definition: sms.h:110
static long queued_cb ( SMSCConn conn)
static

Definition at line 1012 of file smsc_smasi.c.

References smscconn::data, gwlist_len(), smscconn::load, SMASI::msgs_to_send, SMSCCONN_DEAD, and smscconn::status.

Referenced by smsc_smasi_create().

1013 {
1014  SMASI *smasi = conn->data;
1015 
1016  conn->load = (smasi ? (conn->status != SMSCCONN_DEAD ?
1017  gwlist_len(smasi->msgs_to_send) : 0) : 0);
1018 
1019  return conn->load;
1020 }
long gwlist_len(List *list)
Definition: list.c:166
void * data
Definition: smscconn_p.h:249
List * msgs_to_send
Definition: smsc_smasi.c:138
smscconn_status_t status
Definition: smscconn_p.h:151
int load
Definition: smscconn_p.h:152
static int read_pdu ( SMASI smasi,
Connection conn,
SMASI_PDU **  pdu 
)
static

Definition at line 685 of file smsc_smasi.c.

References SMASI::conn, conn_eof(), conn_error(), debug(), error(), smscconn::id, octstr_destroy(), octstr_dump, octstr_get_cstr, smasi_pdu_read(), and smasi_pdu_unpack().

Referenced by smasi_thread().

686 {
687  Octstr *os;
688 
689  os = smasi_pdu_read(conn);
690  if (os == NULL) {
691  if (conn_eof(conn) || conn_error(conn))
692  return -1;
693  return 0;
694  }
695 
696  *pdu = smasi_pdu_unpack(os);
697  if (*pdu == NULL) {
698  error(0, "SMASI[%s]: PDU unpacking failed.",
699  octstr_get_cstr(smasi->conn->id));
700  debug("bb.sms.smasi", 0, "SMASI[%s]: Failed PDU follows.",
701  octstr_get_cstr(smasi->conn->id));
702  octstr_dump(os, 0);
703  octstr_destroy(os);
704  return -1;
705  }
706  octstr_destroy(os);
707  return 1;
708 }
void error(int err, const char *fmt,...)
Definition: log.c:612
SMSCConn * conn
Definition: smsc_smasi.c:136
Octstr * id
Definition: smscconn_p.h:174
int conn_eof(Connection *conn)
Definition: conn.c:697
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
SMASI_PDU * smasi_pdu_unpack(Octstr *data_without_len)
Definition: smasi_pdu.c:223
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
Octstr * smasi_pdu_read(Connection *conn)
Definition: smasi_pdu.c:299
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
int conn_error(Connection *conn)
Definition: conn.c:708
static void send_enquire_link ( SMASI smasi,
Connection conn,
long *  last_sent 
)
static

Definition at line 646 of file smsc_smasi.c.

References SMASI::conn, conn_write(), date_universal_now(), dump_pdu(), smscconn::id, octstr_destroy(), smasi_pdu_create(), smasi_pdu_destroy(), and smasi_pdu_pack().

Referenced by smasi_thread().

647 {
648  SMASI_PDU *pdu = NULL;
649  Octstr *os = NULL;
650 
651  if (date_universal_now() - *last_sent < smasi->enquire_link_interval)
652  return;
653  *last_sent = date_universal_now();
654 
655  pdu = smasi_pdu_create(EnquireLinkReq);
656  dump_pdu("Sending EnquireLinkReq:", smasi->conn->id, pdu);
657  os = smasi_pdu_pack(pdu);
658  if (os)
659  conn_write(conn, os); /* Write errors checked by caller. */
660  octstr_destroy(os);
661  smasi_pdu_destroy(pdu);
662 }
SMSCConn * conn
Definition: smsc_smasi.c:136
Octstr * id
Definition: smscconn_p.h:174
SMASI_PDU * smasi_pdu_create(unsigned long type)
Definition: smasi_pdu.c:132
Octstr * smasi_pdu_pack(SMASI_PDU *pdu)
Definition: smasi_pdu.c:178
int conn_write(Connection *conn, Octstr *data)
Definition: conn.c:1043
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
long date_universal_now(void)
Definition: date.c:304
Definition: octstr.c:118
static void dump_pdu(const char *msg, Octstr *id, SMASI_PDU *pdu)
Definition: smsc_smasi.c:96
void smasi_pdu_destroy(SMASI_PDU *pdu)
Definition: smasi_pdu.c:160
static void send_logoff ( SMASI smasi,
Connection conn 
)
static

Definition at line 628 of file smsc_smasi.c.

References SMASI::conn, conn_write(), counter_increase(), dump_pdu(), smscconn::id, SMASI::message_id_counter, octstr_create, octstr_destroy(), smasi_pdu_create(), smasi_pdu_destroy(), smasi_pdu_pack(), and SMASI_PDU::u.

Referenced by smasi_thread().

629 {
630  SMASI_PDU *pdu = NULL;
631  Octstr *os = NULL;
632 
634 
635  pdu = smasi_pdu_create(LogoffReq);
636  pdu->u.LogoffReq.Reason = octstr_create("Client shutting down");
637  dump_pdu("Sending !LogoffReq:", smasi->conn->id, pdu);
638 
639  os = smasi_pdu_pack(pdu);
640  conn_write(conn, os);
641  octstr_destroy(os);
642  smasi_pdu_destroy(pdu);
643 }
SMSCConn * conn
Definition: smsc_smasi.c:136
Octstr * id
Definition: smscconn_p.h:174
SMASI_PDU * smasi_pdu_create(unsigned long type)
Definition: smasi_pdu.c:132
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
Octstr * smasi_pdu_pack(SMASI_PDU *pdu)
Definition: smasi_pdu.c:178
int conn_write(Connection *conn, Octstr *data)
Definition: conn.c:1043
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
Definition: octstr.c:118
static void dump_pdu(const char *msg, Octstr *id, SMASI_PDU *pdu)
Definition: smsc_smasi.c:96
union SMASI_PDU::@11 u
void smasi_pdu_destroy(SMASI_PDU *pdu)
Definition: smasi_pdu.c:160
Counter * message_id_counter
Definition: smsc_smasi.c:141
static void send_messages ( SMASI smasi,
Connection conn,
long *  pending_submits 
)
static

Definition at line 868 of file smsc_smasi.c.

References SMASI::conn, delay, dict_put(), gwlist_extract_first(), gwthread_sleep(), smscconn::id, MAX_PENDING_SUBMITS, msg, msg_to_pdu(), SMASI::msgs_to_send, send_pdu(), SMASI::sent_msgs, smasi_pdu_destroy(), smscconn::throughput, and SMASI_PDU::u.

Referenced by smasi_thread().

870 {
871  double delay = 0;
872 
873  if (*pending_submits == -1) return;
874 
875  if (smasi->conn->throughput > 0) {
876  delay = 1.0 / smasi->conn->throughput;
877  }
878 
879  while (*pending_submits < MAX_PENDING_SUBMITS) {
880  SMASI_PDU *pdu = NULL;
881  /* Get next message, quit if none to be sent. */
883 
884  if (msg == NULL) break;
885 
886  /* Send PDU, record it as waiting for ack from SMSC. */
887  pdu = msg_to_pdu(smasi, msg);
888 
889  if (pdu->u.SubmitReq.Sequence)
890  dict_put(smasi->sent_msgs, pdu->u.SubmitReq.Sequence, msg);
891 
892  send_pdu(conn, smasi->conn->id, pdu);
893 
894  smasi_pdu_destroy(pdu);
895 
896  /* obey throughput speed limit, if any */
897  if (smasi->conn->throughput > 0)
898  gwthread_sleep(delay);
899 
900  ++(*pending_submits);
901  }
902 }
static int send_pdu(Connection *conn, Octstr *id, SMASI_PDU *pdu)
Definition: smsc_smasi.c:665
SMSCConn * conn
Definition: smsc_smasi.c:136
Dict * sent_msgs
Definition: smsc_smasi.c:139
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
Octstr * id
Definition: smscconn_p.h:174
static SMASI_PDU * msg_to_pdu(SMASI *smasi, Msg *msg)
Definition: smsc_smasi.c:467
Definition: msg.h:79
void * gwlist_extract_first(List *list)
Definition: list.c:305
double throughput
Definition: smscconn_p.h:203
static double delay
Definition: mtbatch.c:99
void gwthread_sleep(double seconds)
#define MAX_PENDING_SUBMITS
Definition: smsc_smasi.c:110
List * msgs_to_send
Definition: smsc_smasi.c:138
union SMASI_PDU::@11 u
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void smasi_pdu_destroy(SMASI_PDU *pdu)
Definition: smasi_pdu.c:160
static int send_msg_cb ( SMSCConn conn,
Msg msg 
)
static

Definition at line 1023 of file smsc_smasi.c.

References smscconn::data, gwlist_produce(), gwthread_wakeup(), msg_duplicate(), SMASI::msgs_to_send, and SMASI::thread_handle.

Referenced by smsc_smasi_create().

1024 {
1025  SMASI *smasi = conn->data;
1026 
1029 
1030  return 0;
1031 }
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
void gwlist_produce(List *list, void *item)
Definition: list.c:411
void * data
Definition: smscconn_p.h:249
List * msgs_to_send
Definition: smsc_smasi.c:138
void gwthread_wakeup(long thread)
int thread_handle
Definition: smsc_smasi.c:137
static int send_pdu ( Connection conn,
Octstr id,
SMASI_PDU pdu 
)
static

Definition at line 665 of file smsc_smasi.c.

References conn_write(), dump_pdu(), octstr_destroy(), and smasi_pdu_pack().

Referenced by handle_pdu(), open_connection(), and send_messages().

666 {
667  Octstr * os = NULL;
668  int ret = 0;
669 
670  dump_pdu("Sending PDU:", id, pdu);
671  os = smasi_pdu_pack(pdu);
672  if (os) ret = conn_write(conn, os);
673  else ret = -1;
674 
675  octstr_destroy(os);
676  return ret;
677 }
Octstr * smasi_pdu_pack(SMASI_PDU *pdu)
Definition: smasi_pdu.c:178
int conn_write(Connection *conn, Octstr *data)
Definition: conn.c:1043
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Definition: octstr.c:118
static void dump_pdu(const char *msg, Octstr *id, SMASI_PDU *pdu)
Definition: smsc_smasi.c:96
static int shutdown_cb ( SMSCConn conn,
int  finish_sending 
)
static

Definition at line 1034 of file smsc_smasi.c.

References bb_smscconn_killed(), smscconn::data, debug(), gwthread_join(), gwthread_wakeup(), smscconn::name, octstr_destroy(), octstr_get_cstr, SMASI::quitting, smasi_destroy(), SMSCCONN_DEAD, SMSCCONN_KILLED_SHUTDOWN, smscconn::status, SMASI::thread_handle, and smscconn::why_killed.

Referenced by smsc_smasi_create().

1035 {
1036  SMASI *smasi = NULL;
1037 
1038  debug("bb.sms.smasi", 0, "Shutting down SMSCConn %s (%s)",
1039  octstr_get_cstr(conn->name), finish_sending ? "slow" : "instant");
1040 
1042 
1043  smasi = conn->data;
1044  smasi->quitting = 1;
1046  gwthread_join(smasi->thread_handle);
1047  smasi_destroy(smasi);
1048 
1049  debug("bb.sms.smasi", 0, "SMSCConn %s shut down.",
1050  octstr_get_cstr(conn->name));
1051  conn->status = SMSCCONN_DEAD;
1053 
1054  /* Clean up. */
1058  octstr_destroy(cr);
1059  octstr_destroy(lf);
1060 
1061  return 0;
1062 }
Octstr * name
Definition: smscconn_p.h:173
static Octstr * cr
Definition: smsc_smasi.c:221
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
void gwthread_join(long thread)
void * data
Definition: smscconn_p.h:249
static Octstr * comma
Definition: smsc_smasi.c:220
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
static void smasi_destroy(SMASI *smasi)
Definition: smsc_smasi.c:192
int quitting
Definition: smsc_smasi.c:153
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
static Octstr * colon
Definition: smsc_smasi.c:218
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
void gwthread_wakeup(long thread)
smscconn_status_t status
Definition: smscconn_p.h:151
int thread_handle
Definition: smsc_smasi.c:137
static Octstr * lf
Definition: smsc_smasi.c:222
static Octstr * assign
Definition: smsc_smasi.c:219
static SMASI* smasi_create ( SMSCConn conn)
static

Definition at line 159 of file smsc_smasi.c.

References SMASI::conn, counter_create(), SMASI::dest_addr_npi, SMASI::dest_addr_ton, dict_create(), SMASI::enquire_link_interval, gwlist_add_producer(), gwlist_create, SMASI::host, SMASI::logged_off, SMASI::message_id_counter, SMASI::msgs_to_send, SMASI::my_number, SMASI::password, SMASI::port, SMASI::priority, SMASI::quitting, SMASI::received_msgs, SMASI::sent_msgs, SMASI::source_addr_npi, SMASI::source_addr_ton, SMASI::thread_handle, SMASI::throttling_err_time, and SMASI::username.

Referenced by smsc_smasi_create().

160 {
161 
162  SMASI *smasi = gw_malloc(sizeof(SMASI));
163 
164  smasi->conn = conn;
165 
166  smasi->thread_handle = -1;
167  smasi->msgs_to_send = gwlist_create();
168  smasi->sent_msgs = dict_create(16, NULL);
169  smasi->received_msgs = gwlist_create();
171  smasi->host = NULL;
172  smasi->username = NULL;
173  smasi->password = NULL;
174  smasi->source_addr_ton = -1;
175  smasi->source_addr_npi = -1;
176  smasi->dest_addr_ton = -1;
177  smasi->dest_addr_npi = -1;
178  smasi->my_number = NULL;
179  smasi->port = 21500;
180  smasi->quitting = 0;
181  smasi->logged_off = 0;
182  smasi->priority = 0;
183  smasi->throttling_err_time = 0;
184  smasi->enquire_link_interval = 30;
185 
187 
188  return smasi;
189 }
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
Definition: dict.c:192
SMSCConn * conn
Definition: smsc_smasi.c:136
Dict * sent_msgs
Definition: smsc_smasi.c:139
long source_addr_npi
Definition: smsc_smasi.c:148
time_t throttling_err_time
Definition: smsc_smasi.c:152
List * received_msgs
Definition: smsc_smasi.c:140
int logged_off
Definition: smsc_smasi.c:155
long enquire_link_interval
Definition: smsc_smasi.c:154
Octstr * my_number
Definition: smsc_smasi.c:146
Counter * counter_create(void)
Definition: counter.c:94
Octstr * host
Definition: smsc_smasi.c:142
Octstr * password
Definition: smsc_smasi.c:145
int quitting
Definition: smsc_smasi.c:153
List * msgs_to_send
Definition: smsc_smasi.c:138
long dest_addr_npi
Definition: smsc_smasi.c:150
long dest_addr_ton
Definition: smsc_smasi.c:149
Octstr * username
Definition: smsc_smasi.c:144
int thread_handle
Definition: smsc_smasi.c:137
#define gwlist_create()
Definition: list.h:136
long priority
Definition: smsc_smasi.c:151
long source_addr_ton
Definition: smsc_smasi.c:147
void gwlist_add_producer(List *list)
Definition: list.c:383
long port
Definition: smsc_smasi.c:143
Counter * message_id_counter
Definition: smsc_smasi.c:141
static void smasi_destroy ( SMASI smasi)
static

Definition at line 192 of file smsc_smasi.c.

References counter_destroy(), dict_destroy(), gwlist_destroy(), SMASI::host, SMASI::message_id_counter, msg_destroy_item(), SMASI::msgs_to_send, octstr_destroy(), SMASI::password, SMASI::received_msgs, SMASI::sent_msgs, and SMASI::username.

Referenced by shutdown_cb(), and smsc_smasi_create().

193 {
194  if (smasi == NULL) return;
195 
197  dict_destroy(smasi->sent_msgs);
200  octstr_destroy(smasi->host);
201  octstr_destroy(smasi->username);
202  octstr_destroy(smasi->password);
203  gw_free(smasi);
204 }
Dict * sent_msgs
Definition: smsc_smasi.c:139
void counter_destroy(Counter *counter)
Definition: counter.c:110
List * received_msgs
Definition: smsc_smasi.c:140
void msg_destroy_item(void *msg)
Definition: msg.c:147
Octstr * host
Definition: smsc_smasi.c:142
Octstr * password
Definition: smsc_smasi.c:145
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
List * msgs_to_send
Definition: smsc_smasi.c:138
void dict_destroy(Dict *dict)
Definition: dict.c:215
Octstr * username
Definition: smsc_smasi.c:144
Counter * message_id_counter
Definition: smsc_smasi.c:141
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
static void smasi_thread ( void *  arg)
static

Definition at line 911 of file smsc_smasi.c.

References SMASI::conn, conn_destroy(), conn_wait(), date_universal_now(), dump_pdu(), SMASI::enquire_link_interval, error(), gwthread_sleep(), handle_pdu(), smscconn::id, smscconn::log_idx, log_thread_to(), SMASI::logged_off, octstr_get_cstr, open_connection(), SMASI::quitting, read_pdu(), smscconn::reconnect_delay, send_enquire_link(), send_logoff(), send_messages(), smasi_pdu_destroy(), SMASI_THROTTLING_SLEEP_TIME, SMSCCONN_RECONNECTING, smscconn::status, and SMASI::throttling_err_time.

Referenced by smsc_smasi_create().

912 {
913  long pending_submits;
914  SMASI_PDU *pdu;
915  SMASI *smasi;
916  int logoff_already_sent = 0;
917  int ret;
918  Connection *conn;
919  long last_enquire_sent;
920  double timeout;
921 
922  smasi = arg;
923 
924  /* Make sure we log into our own log-file if defined */
925  log_thread_to(smasi->conn->log_idx);
926 
927  while (!smasi->quitting) {
928 
929  conn = open_connection(smasi);
930  if (conn == NULL) {
931  error(0, "SMASI[%s]: Could not connect to SMSC center " \
932  "(retrying in %ld seconds).",
933  octstr_get_cstr(smasi->conn->id), smasi->conn->reconnect_delay);
934 
937  continue;
938  }
939 
940  last_enquire_sent = date_universal_now();
941  pending_submits = -1;
942 
943  for (;;) {
944  timeout = last_enquire_sent + smasi->enquire_link_interval
945  - date_universal_now();
946 
947  /* wait for activity */
948  if (conn_wait(conn, timeout) == -1) {
949  error(0, "SMASI[%s]: I/O error or other error. Re-connecting.",
950  octstr_get_cstr(smasi->conn->id));
951  break;
952  }
953 
954  /* Send logoff request if module is shutting down. */
955  if (smasi->quitting && !logoff_already_sent) {
956  send_logoff(smasi, conn);
957  logoff_already_sent = 1;
958  }
959 
960  /* send an enquire link */
961  send_enquire_link(smasi, conn, &last_enquire_sent);
962 
963  /* Receive incoming PDUs. */
964  while ((ret = read_pdu(smasi, conn, &pdu)) == 1) {
965  /* Deal with the PDU we just got */
966  dump_pdu("Got PDU:", smasi->conn->id, pdu);
967 
968  /* Process the received PDU. */
969  handle_pdu(smasi, conn, pdu, &pending_submits);
970 
971  smasi_pdu_destroy(pdu);
972 
973  /* Bail out if logoff confirmed. */
974  if (smasi->logged_off) break;
975 
976  /* Make sure we send even if we read a lot. */
977  if ((!smasi->throttling_err_time ||
978  ((time(NULL) - smasi->throttling_err_time) >
980  && !(smasi->throttling_err_time = 0))))
981  send_messages(smasi, conn, &pending_submits);
982  }
983 
984  /* Check if connection broken. */
985  if (ret == -1) {
986  error(0, "SMASI[%s]: I/O error or other error. Re-connecting.",
987  octstr_get_cstr(smasi->conn->id));
988  break;
989  }
990 
991  /* Bail out if logoff confirmed. */
992  if (smasi->logged_off) break;
993 
994  if ((!smasi->throttling_err_time ||
995  ((time(NULL) - smasi->throttling_err_time) >
997  && !(smasi->throttling_err_time = 0))))
998  send_messages(smasi, conn, &pending_submits);
999 
1000  }
1001 
1002  conn_destroy(conn);
1003  conn = NULL;
1004  }
1005 }
void error(int err, const char *fmt,...)
Definition: log.c:612
SMSCConn * conn
Definition: smsc_smasi.c:136
Octstr * id
Definition: smscconn_p.h:174
time_t throttling_err_time
Definition: smsc_smasi.c:152
int log_idx
Definition: smscconn_p.h:197
int logged_off
Definition: smsc_smasi.c:155
long enquire_link_interval
Definition: smsc_smasi.c:154
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
long reconnect_delay
Definition: smscconn_p.h:199
void log_thread_to(int idx)
Definition: log.c:723
static void send_enquire_link(SMASI *smasi, Connection *conn, long *last_sent)
Definition: smsc_smasi.c:646
void conn_destroy(Connection *conn)
Definition: conn.c:619
static void send_messages(SMASI *smasi, Connection *conn, long *pending_submits)
Definition: smsc_smasi.c:868
#define SMASI_THROTTLING_SLEEP_TIME
Definition: smsc_smasi.c:111
int quitting
Definition: smsc_smasi.c:153
void gwthread_sleep(double seconds)
long date_universal_now(void)
Definition: date.c:304
static void send_logoff(SMASI *smasi, Connection *conn)
Definition: smsc_smasi.c:628
int conn_wait(Connection *conn, double seconds)
Definition: conn.c:896
smscconn_status_t status
Definition: smscconn_p.h:151
static void dump_pdu(const char *msg, Octstr *id, SMASI_PDU *pdu)
Definition: smsc_smasi.c:96
static int read_pdu(SMASI *smasi, Connection *conn, SMASI_PDU **pdu)
Definition: smsc_smasi.c:685
static void handle_pdu(SMASI *smasi, Connection *conn, SMASI_PDU *pdu, long *pending_submits)
Definition: smsc_smasi.c:711
void smasi_pdu_destroy(SMASI_PDU *pdu)
Definition: smasi_pdu.c:160
static Connection * open_connection(SMASI *smasi)
Definition: smsc_smasi.c:843
int smsc_smasi_create ( SMSCConn conn,
CfgGroup config 
)

Definition at line 1129 of file smsc_smasi.c.

References SMASI::conn, smscconn::data, error(), gwthread_create, smscconn::id, init_configuration(), octstr_create, octstr_get_cstr, panic, smscconn::queued, queued_cb(), smscconn::send_msg, send_msg_cb(), smscconn::shutdown, shutdown_cb(), smasi_create(), smasi_destroy(), smasi_thread(), SMSCCONN_CONNECTING, smscconn::status, and SMASI::thread_handle.

Referenced by smscconn_create().

1130 {
1131  SMASI *smasi = NULL;
1132 
1133  /* Initialize data encoding subsystem. */
1134  colon = octstr_create(":3a");
1135  assign = octstr_create(":3d");
1136  comma = octstr_create(":2c");
1137  cr = octstr_create(":0a");
1138  lf = octstr_create(":0d");
1139 
1140  /* Create main SMASI structure and initialize it with configuration
1141  * settings.
1142  */
1143  smasi = smasi_create(conn);
1144 
1145  if (init_configuration(smasi, config) != 0)
1146  panic(0, "SMASI SMSC module configuration invalid.");
1147 
1148  conn->status = SMSCCONN_CONNECTING;
1149 
1150  /* Port is always set to a configured value or defaults to 21500.
1151  * Therefore, threads are always started.
1152  */
1153  smasi->thread_handle = gwthread_create(smasi_thread, smasi);
1154 
1155  if (smasi->thread_handle == -1) {
1156  error(0, "SMASI[%s]: Couldn't start SMASI thread.",
1157  octstr_get_cstr(smasi->conn->id));
1158  smasi_destroy(conn->data);
1159  return -1;
1160  }
1161 
1162  /* Setup control function pointers. */
1163  conn->shutdown = shutdown_cb;
1164  conn->queued = queued_cb;
1165  conn->send_msg = send_msg_cb;
1166 
1167  return 0;
1168 }
void error(int err, const char *fmt,...)
Definition: log.c:612
static Octstr * cr
Definition: smsc_smasi.c:221
SMSCConn * conn
Definition: smsc_smasi.c:136
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
static int shutdown_cb(SMSCConn *conn, int finish_sending)
Definition: smsc_smasi.c:1034
static Octstr * comma
Definition: smsc_smasi.c:220
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static SMASI * smasi_create(SMSCConn *conn)
Definition: smsc_smasi.c:159
static void smasi_destroy(SMASI *smasi)
Definition: smsc_smasi.c:192
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
static Octstr * colon
Definition: smsc_smasi.c:218
static int init_configuration(SMASI *smasi, CfgGroup *config)
Definition: smsc_smasi.c:1071
int(* shutdown)(SMSCConn *conn, int finish_sending)
Definition: smscconn_p.h:229
static int send_msg_cb(SMSCConn *conn, Msg *msg)
Definition: smsc_smasi.c:1023
#define panic
Definition: log.h:87
smscconn_status_t status
Definition: smscconn_p.h:151
int thread_handle
Definition: smsc_smasi.c:137
long(* queued)(SMSCConn *conn)
Definition: smscconn_p.h:240
int(* send_msg)(SMSCConn *conn, Msg *msg)
Definition: smscconn_p.h:235
static void smasi_thread(void *arg)
Definition: smsc_smasi.c:911
static Octstr * lf
Definition: smsc_smasi.c:222
static long queued_cb(SMSCConn *conn)
Definition: smsc_smasi.c:1012
static Octstr * assign
Definition: smsc_smasi.c:219
static void unescape_data ( Octstr data)
static

Definition at line 267 of file smsc_smasi.c.

References check(), octstr_delete(), octstr_get_char(), octstr_insert_data(), and octstr_len().

Referenced by pdu_to_msg().

268 {
269  long pos = 0;
270 
271  /* Again, an inplace transformation is used. Because, again, it is
272  * assumed that only a fraction of chars has to be unescaped.
273  */
274  while (pos < octstr_len(data)) {
275  int check = octstr_get_char(data, pos);
276 
277  if (check == ':') {
278  char byte = 0;
279  int msb = octstr_get_char(data, pos + 1);
280  int lsb = octstr_get_char(data, pos + 2);
281 
282  if (msb == '0') msb = 0;
283  else if (msb >= '1' && msb <= '9') msb -= '1' + 1;
284  else msb -= 'a' + 10;
285 
286  if (lsb == '0') lsb = 0;
287  else if (lsb >= '1' && lsb <= '9') lsb -= '1' + 1;
288  else lsb -= 'a' + 10;
289 
290  byte = msb << 4 | lsb;
291 
292  /* Do inplace unescaping. */
293  octstr_delete(data, pos, 3);
294  octstr_insert_data(data, pos, &byte, 1);
295  }
296  pos++;
297  }
298 }
static void check(void *arg)
Definition: check_counter.c:76
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
Definition: octstr.c:1459
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404

Variable Documentation

Octstr* assign = NULL
static

Definition at line 219 of file smsc_smasi.c.

Referenced by escape_data().

Octstr* comma = NULL
static

Definition at line 220 of file smsc_smasi.c.

Referenced by escape_data().

Octstr* cr = NULL
static

Definition at line 221 of file smsc_smasi.c.

Referenced by escape_data().

Octstr* lf = NULL
static

Definition at line 222 of file smsc_smasi.c.

Referenced by escape_data(), init_bearerbox(), init_smsbox(), and init_wapbox().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.