Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
smsc_oisd.c File Reference
#include <ctype.h>
#include <time.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include "gwlib/gwlib.h"
#include "smscconn.h"
#include "smscconn_p.h"
#include "bb_smscconn_cb.h"
#include "shared.h"
#include "sms.h"
#include "dlr.h"

Go to the source code of this file.

Data Structures

struct  privdata
 
struct  packet
 

Macros

#define RESPONSE_TIMEOUT   (10 * 1000000)
 
#define RESULT_SUCCESS   0
 
#define BOGUS_SEQUENCE   0
 

Typedefs

typedef struct privdata PrivData
 

Enumerations

enum  { INVOKE = 0, RESULT = 1 }
 
enum  {
  SUBMIT_SM = 0, STATUS_REPORT = 4, DELIVER_SM = 9, RETRIEVE_REQUEST = 11,
  RESPONSE = 50
}
 

Functions

static int isphonedigit (int c)
 
static int parm_valid_address (Octstr *value)
 
static int operation_find (int operation)
 
static Octstroperation_name (int operation)
 
static int operation_can_send (int operation)
 
static int operation_can_receive (int operation)
 
static Msgoisd_accept_delivery_report_message (struct packet *request, SMSCConn *conn)
 
static void packet_parse_header (struct packet *packet)
 
static struct packetpacket_parse (Octstr *packet_data)
 
static void packet_destroy (struct packet *packet)
 
static struct packetpacket_extract (Octstr *in, SMSCConn *conn)
 
static void packet_check_can_receive (struct packet *packet, SMSCConn *conn)
 
static int oisd_expand_gsm7_to_bits (char *bits, Octstr *raw7)
 
static char oisd_expand_gsm7_from_bits (const char *bits, int pos)
 
static Octstroisd_expand_gsm7 (Octstr *raw7)
 
static void oisd_shrink_gsm7 (Octstr *str)
 
static struct packetpacket_create (int operation, unsigned long opref)
 
static void packet_set_data_size (struct packet *packet)
 
static void packet_set_sequence (struct packet *packet, unsigned long opref)
 
static struct packetpacket_encode_message (Msg *msg, SMSCConn *conn)
 
static void packet_set_send_sequence (struct packet *packet, PrivData *pdata)
 
static struct packetoisd_get_packet (PrivData *pdata, Octstr **ts)
 
static void oisd_send_response (struct packet *request, PrivData *pdata)
 
static Msgoisd_accept_message (struct packet *request, SMSCConn *conn)
 
static void oisd_handle_request (struct packet *request, SMSCConn *conn)
 
static int oisd_request (struct packet *request, SMSCConn *conn, Octstr **ts)
 
static void oisd_close_socket (PrivData *pdata)
 
static int oisd_login (SMSCConn *conn)
 
static int oisd_send_delivery_request (SMSCConn *conn)
 
static void oisd_destroy (PrivData *pdata)
 
static int oisd_submit_msg (SMSCConn *conn, Msg *msg)
 
static int oisd_receive_msg (SMSCConn *conn, Msg **msg)
 
static Msgsms_receive (SMSCConn *conn)
 
static void io_thread (void *arg)
 
static int oisd_add_msg_cb (SMSCConn *conn, Msg *sms)
 
static int oisd_shutdown_cb (SMSCConn *conn, int finish_sending)
 
static void oisd_start_cb (SMSCConn *conn)
 
static void oisd_stop_cb (SMSCConn *conn)
 
static long oisd_queued_cb (SMSCConn *conn)
 
int smsc_oisd_create (SMSCConn *conn, CfgGroup *grp)
 

Variables

struct {
   char *   name
 
   int   code
 
   int   can_send
 
   int   can_receive
 
operations []
 

Macro Definition Documentation

#define BOGUS_SEQUENCE   0

Definition at line 249 of file smsc_oisd.c.

Referenced by oisd_send_delivery_request(), and packet_encode_message().

#define RESPONSE_TIMEOUT   (10 * 1000000)

Definition at line 116 of file smsc_oisd.c.

Referenced by oisd_get_packet().

#define RESULT_SUCCESS   0

Definition at line 117 of file smsc_oisd.c.

Referenced by oisd_send_response().

Typedef Documentation

typedef struct privdata PrivData

Enumeration Type Documentation

anonymous enum
Enumerator
INVOKE 
RESULT 

Definition at line 119 of file smsc_oisd.c.

119  {
120  INVOKE = 0,
121  RESULT = 1
122 };
anonymous enum
Enumerator
SUBMIT_SM 
STATUS_REPORT 
DELIVER_SM 
RETRIEVE_REQUEST 
RESPONSE 

Definition at line 126 of file smsc_oisd.c.

126  {
127  SUBMIT_SM = 0,
128  STATUS_REPORT = 4,
129  DELIVER_SM = 9,
130  RETRIEVE_REQUEST = 11,
131 
132  /* Not a request; add to any request to make it a response */
133  RESPONSE = 50
134 };

Function Documentation

static void io_thread ( void *  arg)
static

Definition at line 1344 of file smsc_oisd.c.

References bb_smscconn_connected(), bb_smscconn_receive(), smscconn::connect_time, smscconn::data, debug(), error(), smscconn::flow_mutex, gwlist_consume(), gwlist_extract_first(), gwthread_sleep(), smscconn::id, smscconn::log_idx, log_thread_to(), msg, mutex_lock, mutex_unlock, octstr_get_cstr, oisd_login(), oisd_submit_msg(), privdata::outgoing_queue, privdata::quitting, smscconn::reconnect_delay, sms_receive(), SMSCCONN_ACTIVE, SMSCCONN_RECONNECTING, smscconn::status, and privdata::stopped.

Referenced by smsc_oisd_create().

1345 {
1346  Msg *msg;
1347  SMSCConn *conn = arg;
1348  PrivData *pdata = conn->data;
1349  double sleep = 0.0001;
1350 
1351  /* Make sure we log into our own log-file if defined */
1352  log_thread_to(conn->log_idx);
1353 
1354  /* remove messages from SMSC until we are killed */
1355  while (!pdata->quitting) {
1356 
1357  gwlist_consume(pdata->stopped); /* block here if suspended/isolated */
1358 
1359  /* check that connection is active */
1360  if (conn->status != SMSCCONN_ACTIVE) {
1361  if (oisd_login(conn) != 0) {
1362  error(0, "OISD[%s]: Couldn't connect to SMSC (retrying in %ld seconds).",
1363  octstr_get_cstr(conn->id),
1364  conn->reconnect_delay);
1366  mutex_lock(conn->flow_mutex);
1367  conn->status = SMSCCONN_RECONNECTING;
1368  mutex_unlock(conn->flow_mutex);
1369  continue;
1370  }
1371  mutex_lock(conn->flow_mutex);
1372  conn->status = SMSCCONN_ACTIVE;
1373  conn->connect_time = time(NULL);
1374  bb_smscconn_connected(conn);
1375  mutex_unlock(conn->flow_mutex);
1376  }
1377 
1378  /* receive messages */
1379  do {
1380  msg = sms_receive(conn);
1381  if (msg) {
1382  sleep = 0;
1383  debug("bb.sms.oisd", 0, "OISD[%s]: new message received",
1384  octstr_get_cstr(conn->id));
1385  bb_smscconn_receive(conn, msg);
1386  }
1387  } while (msg);
1388 
1389  /* send messages */
1390  do {
1391  msg = gwlist_extract_first(pdata->outgoing_queue);
1392  if (msg) {
1393  sleep = 0;
1394  if (oisd_submit_msg(conn, msg) != 0) break;
1395  }
1396  } while (msg);
1397 
1398  if (sleep > 0) {
1399 
1400  /* note that this implementations means that we sleep even
1401  * when we fail connection.. but time is very short, anyway
1402  */
1403  gwthread_sleep(sleep);
1404  /* gradually sleep longer and longer times until something starts to
1405  * happen - this of course reduces response time, but that's better than
1406  * extensive CPU usage when it is not used
1407  */
1408  sleep *= 2;
1409  if (sleep >= 2.0)
1410  sleep = 1.999999;
1411  }
1412  else {
1413  sleep = 0.0001;
1414  }
1415  }
1416 }
void error(int err, const char *fmt,...)
Definition: log.c:612
void bb_smscconn_connected(SMSCConn *conn)
Definition: bb_smscconn.c:192
#define mutex_unlock(m)
Definition: thread.h:136
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
List * outgoing_queue
Definition: smsc_cgw.c:153
int log_idx
Definition: smscconn_p.h:197
#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
List * stopped
Definition: smsc_cimd2.c:121
Definition: msg.h:79
void * gwlist_extract_first(List *list)
Definition: list.c:305
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:478
time_t connect_time
Definition: smscconn_p.h:155
Mutex * flow_mutex
Definition: smscconn_p.h:157
int quitting
Definition: smsc_cimd2.c:120
void gwthread_sleep(double seconds)
static int oisd_submit_msg(SMSCConn *conn, Msg *msg)
Definition: smsc_oisd.c:1152
void * gwlist_consume(List *list)
Definition: list.c:427
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
smscconn_status_t status
Definition: smscconn_p.h:151
static Msg * sms_receive(SMSCConn *conn)
Definition: smsc_oisd.c:1320
#define mutex_lock(m)
Definition: thread.h:130
static int oisd_login(SMSCConn *conn)
Definition: smsc_oisd.c:1062
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static int isphonedigit ( int  c)
static

Definition at line 136 of file smsc_oisd.c.

Referenced by oisd_send_delivery_request(), packet_encode_message(), and parm_valid_address().

137 {
138  return isdigit(c) || c == '+' || c == '-';
139 }
static Msg * oisd_accept_delivery_report_message ( struct packet request,
SMSCConn conn 
)
static

Definition at line 1277 of file smsc_oisd.c.

References code, packet::data, DLR_FAIL, dlr_find(), DLR_SUCCESS, msg, smscconn::name, octstr_copy, octstr_destroy(), and octstr_get_char().

Referenced by oisd_handle_request().

1279 {
1280  Msg *msg = NULL;
1281  Octstr *destination = NULL;
1282  Octstr *timestamp = NULL;
1283  int st_code;
1284  int code;
1285  int dest_len;
1286 
1287  /* MSISDN length */
1288  dest_len = octstr_get_char(request->data, 10);
1289  /* MSISDN */
1290  destination = octstr_copy(request->data, 10+1, dest_len);
1291  /* Accept time */
1292  timestamp = octstr_copy(request->data, 10+1+dest_len+1+4+4, 14);
1293  /* SM status */
1294  st_code = octstr_get_char(request->data, 10+1+dest_len+1+4+4+14);
1295 
1296  switch (st_code) {
1297  case 1:
1298  case 2:
1299  code = DLR_FAIL;
1300  break;
1301  case 3: /* success */
1302  code = DLR_SUCCESS;
1303  break;
1304  case 4:
1305  case 5:
1306  case 6:
1307  default:
1308  code = 0;
1309  }
1310 
1311  if (code)
1312  msg = dlr_find(conn->name, timestamp, destination, code, 0);
1313 
1314  octstr_destroy(destination);
1315  octstr_destroy(timestamp);
1316 
1317  return msg;
1318 }
Octstr * name
Definition: smscconn_p.h:173
int code
Definition: smsc_oisd.c:158
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
Definition: dlr.c:387
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
#define DLR_SUCCESS
Definition: dlr.h:72
Definition: msg.h:79
Octstr * data
Definition: smsc_cimd2.c:446
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Definition: octstr.c:118
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
#define DLR_FAIL
Definition: dlr.h:73
static Msg* oisd_accept_message ( struct packet request,
SMSCConn conn 
)
static

Definition at line 777 of file smsc_oisd.c.

References charset_gsm_to_utf8(), packet::data, DC_7BIT, dcs_to_fields(), debug(), error(), smscconn::id, info(), msg, msg_create, msg_destroy(), octstr_copy, octstr_create, octstr_get_char(), octstr_get_cstr, octstr_len(), oisd_expand_gsm7(), and warning().

Referenced by oisd_handle_request().

778 {
779  Msg *msg = NULL;
780  int DCS;
781  int dest_len;
782  int origin_len;
783  int add_info;
784  int msglen7, msglen8;
785  int udh_len;
786 
787  msg = msg_create(sms);
788 
789  /* See GSM 03.38. The bit patterns we can handle are:
790  * 000xyyxx Uncompressed text, yy indicates alphabet.
791  * yy = 00, default alphabet
792  * yy = 01, 8-bit data
793  * yy = 10, UCS-2
794  * yy = 11, reserved
795  * 1111xyxx Data, y indicates alphabet.
796  * y = 0, default alphabet
797  * y = 1, 8-bit data
798  */
799 
800  /* Additional information
801  * xxxxxxyz This field conveys additional information to assist
802  * the recipient in interpreting the SM.
803  * z = reply path
804  * y = user data header indicator
805  * x = reserved
806  */
807 
808  /*
809  * Destination addr. and Originating addr. w/o TOA
810  */
811 
812  /* Destination addr. length */
813  dest_len = octstr_get_char(request->data, 10);
814 
815  /* Destination addr. */
816  msg->sms.receiver = octstr_copy(request->data, 11+2, dest_len-2);
817 
818  /* Originating addr. length */
819  origin_len = octstr_get_char(request->data, 11+dest_len+4);
820 
821  /* Originating addr. */
822  msg->sms.sender = octstr_copy(request->data, 11+dest_len+5+2, origin_len-2);
823 
824  DCS = octstr_get_char(request->data, 11+dest_len+5+origin_len);
825  if (!dcs_to_fields(&msg, DCS)) {
826  /* XXX: Should reject this message ? */
827  debug("bb.sms.oisd", 0, "OISD[%s]: Invalid DCS",
828  octstr_get_cstr(conn->id));
829  dcs_to_fields(&msg, 0);
830  }
831 
832  add_info = octstr_get_char(request->data,11+dest_len+5+origin_len+2);
833 
834  msglen7 = octstr_get_char(request->data, 11+dest_len+5+origin_len+3);
835  msglen8 = octstr_get_char(request->data, 11+dest_len+5+origin_len+4);
836 
837  msg->sms.rpi = add_info & 0x01;
838 
839  debug("bb.sms.oisd", 0,
840  "OISD[%s]: received DCS=%02X, add_info=%d, msglen7=%d, msglen8=%d, rpi=%ld",
841  octstr_get_cstr(conn->id),
842  DCS, add_info, msglen7, msglen8, msg->sms.rpi);
843 
844  if (msg->sms.coding == DC_7BIT) {
845  msg->sms.msgdata =
847  11+dest_len+5+origin_len+5,
848  msglen7));
849  debug("bb.sms.oisd", 0, "OISD[%s]: received raw8=%s ",
850  octstr_get_cstr(conn->id),
851  octstr_get_cstr(msg->sms.msgdata));
852  if (add_info & 0x02) {
853  warning(0, "OISD[%s]: 7-bit UDH ?",
854  octstr_get_cstr(conn->id));
855  } else {
856  charset_gsm_to_utf8(msg->sms.msgdata);
857  debug("bb.sms.oisd", 0, "OISD[%s]: received UTF-8=%s",
858  octstr_get_cstr(conn->id),
859  octstr_get_cstr(msg->sms.msgdata));
860  }
861  } else {
862  /* 0xf4, 0xf5, 0xf6, 0xf7; 8bit to disp, mem, sim or term */
863  if (add_info & 0x02) {
864  udh_len = octstr_get_char(request->data,
865  11+dest_len+5+origin_len+5)+1;
866  msg->sms.msgdata =
867  octstr_copy(request->data,
868  11+dest_len+5+origin_len+5+udh_len,
869  msglen8);
870  msg->sms.udhdata =
871  octstr_copy(request->data,
872  11+dest_len+5+origin_len+5,
873  udh_len);
874  } else {
875  msg->sms.msgdata =
876  octstr_copy(request->data,
877  11+dest_len+5+origin_len+5,
878  msglen8);
879  }
880  }
881 
882  /* Code elsewhere in the gateway always expects the sender and
883  * receiver fields to be filled, so we discard messages that
884  * lack them. If they should not be discarded, then the code
885  * handling sms messages should be reviewed. -- RB */
886  if (!(msg->sms.receiver) || octstr_len(msg->sms.receiver) == 0) {
887  info(0, "OISD[%s]: Got SMS without receiver, discarding.",
888  octstr_get_cstr(conn->id));
889  goto error;
890  }
891 
892  if (!(msg->sms.sender) || octstr_len(msg->sms.sender) == 0) {
893  info(0, "OISD[%s]: Got SMS without sender, discarding.",
894  octstr_get_cstr(conn->id));
895  goto error;
896  }
897 
898  if ((!(msg->sms.msgdata) || octstr_len(msg->sms.msgdata) == 0)
899  && (!(msg->sms.udhdata) || octstr_len(msg->sms.udhdata) == 0)) {
900  msg->sms.msgdata = octstr_create("");
901  }
902 
903  return msg;
904 
905 error:
906  msg_destroy(msg);
907  return NULL;
908 }
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
Octstr * id
Definition: smscconn_p.h:174
#define msg_create(type)
Definition: msg.h:136
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
Definition: msg.h:79
Octstr * data
Definition: smsc_cimd2.c:446
void msg_destroy(Msg *msg)
Definition: msg.c:132
void warning(int err, const char *fmt,...)
Definition: log.c:624
#define octstr_create(cstr)
Definition: octstr.h:125
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
int dcs_to_fields(Msg **msg, int dcs)
Definition: sms.c:139
static Octstr * oisd_expand_gsm7(Octstr *raw7)
Definition: smsc_oisd.c:387
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
#define DC_7BIT
Definition: sms.h:110
void charset_gsm_to_utf8(Octstr *ostr)
Definition: charset.c:220
static int oisd_add_msg_cb ( SMSCConn conn,
Msg sms 
)
static

Definition at line 1418 of file smsc_oisd.c.

References smscconn::data, gwlist_produce(), gwthread_wakeup(), privdata::io_thread, msg_duplicate(), and privdata::outgoing_queue.

Referenced by smsc_oisd_create().

1419 {
1420  PrivData *pdata = conn->data;
1421  Msg *copy;
1422 
1423  copy = msg_duplicate(sms);
1424  gwlist_produce(pdata->outgoing_queue, copy);
1425  gwthread_wakeup(pdata->io_thread);
1426 
1427  return 0;
1428 }
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 * outgoing_queue
Definition: smsc_cgw.c:153
int io_thread
Definition: smsc_cimd2.c:119
Definition: msg.h:79
void gwthread_wakeup(long thread)
static void oisd_close_socket ( PrivData pdata)
static

Definition at line 1043 of file smsc_oisd.c.

References privdata::conn, gw_assert(), smscconn::id, octstr_get_cstr, privdata::socket, and warning().

Referenced by oisd_login(), oisd_shutdown_cb(), oisd_submit_msg(), and sms_receive().

1044 {
1045  gw_assert(pdata != NULL);
1046 
1047  if (pdata->socket < 0)
1048  return;
1049 
1050  if (close(pdata->socket) < 0)
1051  warning(errno, "OISD[%s]: error closing socket",
1052  octstr_get_cstr(pdata->conn->id));
1053  pdata->socket = -1;
1054 }
Octstr * id
Definition: smscconn_p.h:174
int socket
Definition: smsc_cimd2.c:108
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void warning(int err, const char *fmt,...)
Definition: log.c:624
gw_assert(wtls_machine->packet_to_send!=NULL)
SMSCConn * conn
Definition: smsc_cimd2.c:118
static void oisd_destroy ( PrivData pdata)
static

Definition at line 1128 of file smsc_oisd.c.

References privdata::conn, gwlist_destroy(), gwlist_len(), privdata::host, smscconn::id, privdata::inbuffer, msg_destroy_item(), privdata::my_number, octstr_destroy(), octstr_get_cstr, privdata::outgoing_queue, privdata::received, privdata::stopped, and warning().

Referenced by oisd_shutdown_cb(), and smsc_oisd_create().

1129 {
1130  int discarded;
1131 
1132  if (pdata == NULL)
1133  return;
1134 
1135  octstr_destroy(pdata->host);
1136  octstr_destroy(pdata->inbuffer);
1137  octstr_destroy(pdata->my_number);
1138 
1139  discarded = gwlist_len(pdata->received);
1140  if (discarded > 0)
1141  warning(0, "OISD[%s]: discarded %d received messages",
1142  octstr_get_cstr(pdata->conn->id),
1143  discarded);
1144 
1146  gwlist_destroy(pdata->outgoing_queue, NULL);
1147  gwlist_destroy(pdata->stopped, NULL);
1148 
1149  gw_free(pdata);
1150 }
Octstr * inbuffer
Definition: smsc_cimd2.c:112
Octstr * id
Definition: smscconn_p.h:174
long gwlist_len(List *list)
Definition: list.c:166
List * outgoing_queue
Definition: smsc_cgw.c:153
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
List * stopped
Definition: smsc_cimd2.c:121
void msg_destroy_item(void *msg)
Definition: msg.c:147
Octstr * my_number
Definition: smsc_cimd2.c:105
void warning(int err, const char *fmt,...)
Definition: log.c:624
Octstr * host
Definition: smsc_cgw.c:163
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
List * received
Definition: smsc_cimd2.c:113
SMSCConn * conn
Definition: smsc_cimd2.c:118
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
static Octstr* oisd_expand_gsm7 ( Octstr raw7)
static

Definition at line 387 of file smsc_oisd.c.

References octstr_append_char(), octstr_create, octstr_len(), oisd_expand_gsm7_from_bits(), and oisd_expand_gsm7_to_bits().

Referenced by oisd_accept_message().

388 {
389  Octstr *raw8;
390  int i, len;
391  char *bits;
392 
393  raw8 = octstr_create("");
394  bits = gw_malloc(8 * octstr_len(raw7) + 1);
395 
396  oisd_expand_gsm7_to_bits(bits, raw7);
397  len = octstr_len(raw7);
398 
399  for (i = 0; i < len; ++i) {
401  }
402 
403  gw_free(bits);
404 
405  return raw8;
406 }
static char oisd_expand_gsm7_from_bits(const char *bits, int pos)
Definition: smsc_oisd.c:372
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
static int oisd_expand_gsm7_to_bits(char *bits, Octstr *raw7)
Definition: smsc_oisd.c:353
#define octstr_create(cstr)
Definition: octstr.h:125
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
static char oisd_expand_gsm7_from_bits ( const char *  bits,
int  pos 
)
static

Definition at line 372 of file smsc_oisd.c.

Referenced by oisd_expand_gsm7().

373 {
374  int i;
375  char ch;
376 
377  pos *= 7; /* septet position in bits */
378  ch = '\0';
379  for (i = 6; i >= 0; --i) {
380  ch <<= 1;
381  ch |= bits[pos + i];
382  }
383 
384  return ch;
385 }
static int oisd_expand_gsm7_to_bits ( char *  bits,
Octstr raw7 
)
static

Definition at line 353 of file smsc_oisd.c.

References octstr_get_char(), and octstr_len().

Referenced by oisd_expand_gsm7().

354 {
355  int i, j, k;
356  int len;
357  char ch;
358 
359  len = octstr_len(raw7) * 7; /* number of bits in the gsm 7-bit msg */
360 
361  for (j = i = 0; j < len; ++i) {
362  ch = octstr_get_char(raw7, i);
363  for (k = 0; k < 8; ++k) {
364  bits[j++] = (char) (ch & 0x01);
365  ch >>= 1;
366  }
367  }
368 
369  return j;
370 }
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static struct packet* oisd_get_packet ( PrivData pdata,
Octstr **  ts 
)
static

Definition at line 711 of file smsc_oisd.c.

References privdata::conn, packet::data, debug(), error(), gw_assert(), smscconn::id, privdata::inbuffer, privdata::keepalive, privdata::next_ping, octstr_append_from_socket(), octstr_copy, octstr_dump, octstr_get_cstr, packet::operation, packet_check_can_receive(), packet_extract(), read_available(), RESPONSE, RESPONSE_TIMEOUT, RETRIEVE_REQUEST, privdata::socket, and warning().

Referenced by oisd_request().

712 {
713  struct packet *packet = NULL;
714 
715  gw_assert(pdata != NULL);
716 
717  /* If packet is already available, don't try to read anything */
718  packet = packet_extract(pdata->inbuffer, pdata->conn);
719 
720  while (packet == NULL) {
721  if (read_available(pdata->socket, RESPONSE_TIMEOUT) != 1) {
722  warning(0, "OISD[%s]: SMSC is not responding",
723  octstr_get_cstr(pdata->conn->id));
724  return NULL;
725  }
726 
727  if (octstr_append_from_socket(pdata->inbuffer, pdata->socket) <= 0) {
728  error(0, "OISD[%s]: oisd_get_packet: read failed",
729  octstr_get_cstr(pdata->conn->id));
730  return NULL;
731  }
732 
733  packet = packet_extract(pdata->inbuffer, pdata->conn);
734  }
735 
736  packet_check_can_receive(packet, pdata->conn);
737  debug("bb.sms.oisd", 0, "OISD[%s]: received",
738  octstr_get_cstr(pdata->conn->id));
739  if (packet->operation != RETRIEVE_REQUEST + RESPONSE)
740  octstr_dump(packet->data, 0);
741  if (ts)
742  *ts = octstr_copy(packet->data, 15, 14);
743 
744  if (pdata->keepalive > 0)
745  pdata->next_ping = time(NULL) + pdata->keepalive;
746 
747  return packet;
748 }
static struct packet * packet_extract(Octstr *in, SMSCConn *conn)
Definition: smsc_oisd.c:299
void error(int err, const char *fmt,...)
Definition: log.c:612
int operation
Definition: smsc_cimd2.c:444
Octstr * inbuffer
Definition: smsc_cimd2.c:112
Octstr * id
Definition: smscconn_p.h:174
int octstr_append_from_socket(Octstr *ostr, int socket)
Definition: octstr.c:1278
int socket
Definition: smsc_cimd2.c:108
static void packet_check_can_receive(struct packet *packet, SMSCConn *conn)
Definition: smsc_oisd.c:340
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
time_t next_ping
Definition: smsc_cimd2.c:115
Octstr * data
Definition: smsc_cimd2.c:446
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
void warning(int err, const char *fmt,...)
Definition: log.c:624
gw_assert(wtls_machine->packet_to_send!=NULL)
int read_available(int fd, long wait_usec)
Definition: socket.c:406
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
#define RESPONSE_TIMEOUT
Definition: smsc_oisd.c:116
long keepalive
Definition: smsc_cimd2.c:104
SMSCConn * conn
Definition: smsc_cimd2.c:118
static void oisd_handle_request ( struct packet request,
SMSCConn conn 
)
static

Definition at line 911 of file smsc_oisd.c.

References smscconn::data, DELIVER_SM, gwlist_append(), msg, oisd_accept_delivery_report_message(), oisd_accept_message(), oisd_send_response(), packet::operation, privdata::received, and STATUS_REPORT.

Referenced by oisd_receive_msg(), and oisd_request().

912 {
913  PrivData *pdata = conn->data;
914  Msg *msg = NULL;
915 
916  if (request->operation == STATUS_REPORT) {
917  msg = oisd_accept_delivery_report_message(request, conn);
918  if (msg)
919  gwlist_append(pdata->received, msg);
920  } else if (request->operation == DELIVER_SM) {
921  msg = oisd_accept_message(request, conn);
922  if (msg)
923  gwlist_append(pdata->received, msg);
924  }
925 
926  oisd_send_response(request, pdata);
927 }
int operation
Definition: smsc_cimd2.c:444
static Msg * oisd_accept_message(struct packet *request, SMSCConn *conn)
Definition: smsc_oisd.c:777
void gwlist_append(List *list, void *item)
Definition: list.c:179
void * data
Definition: smscconn_p.h:249
static Msg * oisd_accept_delivery_report_message(struct packet *request, SMSCConn *conn)
Definition: smsc_oisd.c:1277
Definition: msg.h:79
static void oisd_send_response(struct packet *request, PrivData *pdata)
Definition: smsc_oisd.c:753
List * received
Definition: smsc_cimd2.c:113
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static int oisd_login ( SMSCConn conn)
static

Definition at line 1062 of file smsc_oisd.c.

References smscconn::data, error(), gw_assert(), privdata::host, smscconn::id, info(), octstr_get_cstr, oisd_close_socket(), smscconn::our_host, packet_destroy(), privdata::port, privdata::socket, tcpip_connect_to_server(), and warning().

Referenced by io_thread().

1063 {
1064  PrivData *pdata = conn->data;
1065  struct packet *packet = NULL;
1066 
1067  gw_assert(pdata != NULL);
1068 
1069  if (pdata->socket >= 0) {
1070  warning(0, "OISD[%s]: login: socket was already open; closing",
1071  octstr_get_cstr(conn->id));
1072  oisd_close_socket(pdata);
1073  }
1074 
1076  octstr_get_cstr(pdata->host),
1077  pdata->port,
1078  (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL));
1079  if (pdata->socket != -1) {
1080  info(0, "OISD[%s] logged in.",
1081  octstr_get_cstr(conn->id));
1082  return 0;
1083  }
1084  error(0, "OISD[%s] login failed.",
1085  octstr_get_cstr(conn->id));
1086  oisd_close_socket(pdata);
1087  packet_destroy(packet);
1088  return -1;
1089 }
int port
Definition: smsc_cgw.c:159
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
int tcpip_connect_to_server(char *hostname, int port, const char *source_addr)
Definition: socket.c:149
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
int socket
Definition: smsc_cimd2.c:108
Octstr * our_host
Definition: smscconn_p.h:192
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static void oisd_close_socket(PrivData *pdata)
Definition: smsc_oisd.c:1043
static void packet_destroy(struct packet *packet)
Definition: smsc_oisd.c:286
void warning(int err, const char *fmt,...)
Definition: log.c:624
Octstr * host
Definition: smsc_cgw.c:163
gw_assert(wtls_machine->packet_to_send!=NULL)
static long oisd_queued_cb ( SMSCConn conn)
static

Definition at line 1490 of file smsc_oisd.c.

References smscconn::data, gwlist_len(), smscconn::load, privdata::outgoing_queue, SMSCCONN_DEAD, and smscconn::status.

Referenced by smsc_oisd_create().

1491 {
1492  PrivData *pdata = conn->data;
1493  conn->load = (pdata ? (conn->status != SMSCCONN_DEAD ?
1494  gwlist_len(pdata->outgoing_queue) : 0) : 0);
1495  return conn->load;
1496 }
long gwlist_len(List *list)
Definition: list.c:166
void * data
Definition: smscconn_p.h:249
List * outgoing_queue
Definition: smsc_cgw.c:153
smscconn_status_t status
Definition: smscconn_p.h:151
int load
Definition: smscconn_p.h:152
static int oisd_receive_msg ( SMSCConn conn,
Msg **  msg 
)
static

Definition at line 1198 of file smsc_oisd.c.

References privdata::conn, smscconn::data, packet::data, debug(), error(), gw_assert(), gwlist_consume(), gwlist_len(), smscconn::id, privdata::inbuffer, privdata::keepalive, privdata::next_ping, octstr_append_from_socket(), octstr_dump, octstr_get_cstr, oisd_handle_request(), oisd_send_delivery_request(), packet::operation, packet_check_can_receive(), packet_destroy(), packet_extract(), read_available(), privdata::received, RESPONSE, privdata::socket, and warning().

Referenced by sms_receive().

1199 {
1200  PrivData *pdata = conn->data;
1201  long ret;
1202  struct packet *packet;
1203 
1204  gw_assert(pdata != NULL);
1205 
1206  if (gwlist_len(pdata->received) > 0) {
1207  *msg = gwlist_consume(pdata->received);
1208  return 1;
1209  }
1210 
1211  if (pdata->socket < 0) {
1212  /* XXX We have to assume that smsc_send_message is
1213  * currently trying to reopen, so we have to make
1214  * this thread wait. It should be done in a nicer
1215  * way. */
1216  return 0;
1217  }
1218 
1219  ret = read_available(pdata->socket, 0);
1220  if (ret == 0) {
1221  if (pdata->keepalive > 0 && pdata->next_ping < time(NULL)) {
1222  if (oisd_send_delivery_request(conn) < 0)
1223  return -1;
1224  }
1225  return 0;
1226  }
1227 
1228  if (ret < 0) {
1229  warning(errno, "OISD[%s]: oisd_receive_msg: read_available failed",
1230  octstr_get_cstr(conn->id));
1231  return -1;
1232  }
1233 
1234  /* We have some data waiting... see if it is an sms delivery. */
1235  ret = octstr_append_from_socket(pdata->inbuffer, pdata->socket);
1236 
1237  if (ret == 0) {
1238  warning(0, "OISD[%s]: oisd_receive_msg: service center closed connection.",
1239  octstr_get_cstr(conn->id));
1240  return -1;
1241  }
1242  if (ret < 0) {
1243  warning(0, "OISD[%s]: oisd_receive_msg: read failed",
1244  octstr_get_cstr(conn->id));
1245  return -1;
1246  }
1247 
1248 
1249  for (;;) {
1250  packet = packet_extract(pdata->inbuffer, conn);
1251  if (!packet)
1252  break;
1253 
1254  packet_check_can_receive(packet, conn);
1255  debug("bb.sms.oisd", 0, "OISD[%s]: received",
1256  octstr_get_cstr(pdata->conn->id));
1257  octstr_dump(packet->data, 0);
1258 
1259  if (packet->operation < RESPONSE)
1260  oisd_handle_request(packet, conn);
1261  else {
1262  error(0, "OISD[%s]: oisd_receive_msg: unexpected response packet",
1263  octstr_get_cstr(conn->id));
1264  octstr_dump(packet->data, 0);
1265  }
1266 
1267  packet_destroy(packet);
1268  }
1269 
1270  if (gwlist_len(pdata->received) > 0) {
1271  *msg = gwlist_consume(pdata->received);
1272  return 1;
1273  }
1274  return 0;
1275 }
static struct packet * packet_extract(Octstr *in, SMSCConn *conn)
Definition: smsc_oisd.c:299
void error(int err, const char *fmt,...)
Definition: log.c:612
int operation
Definition: smsc_cimd2.c:444
Octstr * inbuffer
Definition: smsc_cimd2.c:112
Octstr * id
Definition: smscconn_p.h:174
long gwlist_len(List *list)
Definition: list.c:166
void * data
Definition: smscconn_p.h:249
int octstr_append_from_socket(Octstr *ostr, int socket)
Definition: octstr.c:1278
int socket
Definition: smsc_cimd2.c:108
static void packet_check_can_receive(struct packet *packet, SMSCConn *conn)
Definition: smsc_oisd.c:340
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
time_t next_ping
Definition: smsc_cimd2.c:115
Octstr * data
Definition: smsc_cimd2.c:446
static void packet_destroy(struct packet *packet)
Definition: smsc_oisd.c:286
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
void warning(int err, const char *fmt,...)
Definition: log.c:624
gw_assert(wtls_machine->packet_to_send!=NULL)
static int oisd_send_delivery_request(SMSCConn *conn)
Definition: smsc_oisd.c:1091
void * gwlist_consume(List *list)
Definition: list.c:427
int read_available(int fd, long wait_usec)
Definition: socket.c:406
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
List * received
Definition: smsc_cimd2.c:113
static void oisd_handle_request(struct packet *request, SMSCConn *conn)
Definition: smsc_oisd.c:911
long keepalive
Definition: smsc_cimd2.c:104
SMSCConn * conn
Definition: smsc_cimd2.c:118
static int oisd_request ( struct packet request,
SMSCConn conn,
Octstr **  ts 
)
static

Definition at line 940 of file smsc_oisd.c.

References smscconn::data, packet::data, debug(), error(), gw_assert(), smscconn::id, octstr_destroy(), octstr_dump, octstr_get_char(), octstr_get_cstr, octstr_write_to_socket(), oisd_get_packet(), oisd_handle_request(), packet::operation, operation_can_send(), operation_name(), packet::opref, packet_destroy(), packet_set_data_size(), packet_set_send_sequence(), reply(), RESPONSE, RETRIEVE_REQUEST, privdata::socket, and warning().

Referenced by oisd_send_delivery_request(), and oisd_submit_msg().

941 {
942  PrivData *pdata = conn->data;
943  int ret;
944  struct packet *reply = NULL;
945  int errorcode;
946  int tries = 0;
947  Octstr *request_name;
948 
949  gw_assert(pdata != NULL);
950  gw_assert(request != NULL);
952 
953  if (pdata->socket < 0) {
954  warning(0, "OISD[%s]: oisd_request: socket not open.",
955  octstr_get_cstr(conn->id));
956  return -2;
957  }
958 
959  packet_set_data_size(request);
960 
961 retransmit:
962  packet_set_send_sequence(request, pdata);
963 
964  request_name = operation_name(request->operation);
965  debug("bb.sms.oisd", 0, "OISD[%s]: sending %s request",
966  octstr_get_cstr(conn->id),
967  octstr_get_cstr(request_name));
968  octstr_destroy(request_name);
969  if (request->operation != RETRIEVE_REQUEST)
970  octstr_dump(request->data, 0);
971 
972  ret = octstr_write_to_socket(pdata->socket, request->data);
973  if (ret < 0)
974  goto io_error;
975 
976 next_reply:
977  packet_destroy(reply); /* destroy old, if any */
978  reply = oisd_get_packet(pdata, ts);
979  if (!reply)
980  goto io_error;
981 
982  /* The server sent us a request. Handle it, then wait for
983  * a new reply. */
984  if (reply->operation < RESPONSE) {
985  oisd_handle_request(reply, conn);
986  goto next_reply;
987  }
988 
989  if (reply->opref != request->opref) {
990  /* We got a response to a different request number than
991  * what we send. Strange. */
992  warning(0, "OISD[%s]: response had unexpected sequence number; ignoring.",
993  octstr_get_cstr(conn->id));
994  goto next_reply;
995  }
996 
997  if (reply->operation != request->operation + RESPONSE) {
998  /* We got a response that didn't match our request */
999  Octstr *request_name = operation_name(request->operation);
1000  Octstr *reply_name = operation_name(reply->operation);
1001  warning(0, "OISD[%s]: %s request got a %s",
1002  octstr_get_cstr(conn->id),
1003  octstr_get_cstr(request_name),
1004  octstr_get_cstr(reply_name));
1005 
1006  octstr_destroy(request_name);
1007  octstr_destroy(reply_name);
1008  octstr_dump(reply->data, 0);
1009  goto retry;
1010  }
1011 
1012  errorcode = octstr_get_char(reply->data, 10); /* Result */
1013 
1014  if (errorcode > 0)
1015  goto error;
1016 
1017  /* The reply passed all the checks... looks like the SMSC accepted
1018  * our request! */
1019  packet_destroy(reply);
1020  return 0;
1021 
1022 io_error:
1023  packet_destroy(reply);
1024  return -2;
1025 
1026 error:
1027  packet_destroy(reply);
1028  return -1;
1029 
1030 retry:
1031  if (++tries < 3) {
1032  warning(0, "OISD[%s]: Retransmitting (take %d)",
1033  octstr_get_cstr(conn->id),
1034  tries);
1035  goto retransmit;
1036  }
1037  warning(0, "OISD[%s]: Giving up.",
1038  octstr_get_cstr(conn->id));
1039  goto io_error;
1040 }
void error(int err, const char *fmt,...)
Definition: log.c:612
int operation
Definition: smsc_cimd2.c:444
int octstr_write_to_socket(int socket, Octstr *ostr)
Definition: octstr.c:1225
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
int socket
Definition: smsc_cimd2.c:108
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * data
Definition: smsc_cimd2.c:446
static void packet_destroy(struct packet *packet)
Definition: smsc_oisd.c:286
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
void warning(int err, const char *fmt,...)
Definition: log.c:624
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
static void packet_set_data_size(struct packet *packet)
Definition: smsc_oisd.c:477
static Octstr * operation_name(int operation)
Definition: smsc_oisd.c:184
static void packet_set_send_sequence(struct packet *packet, PrivData *pdata)
Definition: smsc_oisd.c:703
static int operation_can_send(int operation)
Definition: smsc_oisd.c:206
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
unsigned long opref
Definition: smsc_oisd.c:243
static struct packet * oisd_get_packet(PrivData *pdata, Octstr **ts)
Definition: smsc_oisd.c:711
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static void oisd_handle_request(struct packet *request, SMSCConn *conn)
Definition: smsc_oisd.c:911
static void reply(HTTPClient *c, List *push_headers)
static int oisd_send_delivery_request ( SMSCConn conn)
static

Definition at line 1091 of file smsc_oisd.c.

References BOGUS_SEQUENCE, smscconn::data, packet::data, gw_assert(), smscconn::id, isphonedigit(), privdata::my_number, octstr_append(), octstr_append_char(), octstr_check_range(), octstr_get_cstr, octstr_len(), oisd_request(), packet_create(), packet_destroy(), RETRIEVE_REQUEST, and warning().

Referenced by oisd_receive_msg().

1092 {
1093  PrivData *pdata = conn->data;
1094  struct packet *packet = NULL;
1095  int ret;
1096 
1097  gw_assert(conn != NULL);
1098 
1100 
1102  octstr_len(pdata->my_number),
1103  isphonedigit));
1104  /* Originating address length */
1105  octstr_append_char(packet->data,
1106  (char) (octstr_len(pdata->my_number) + 2));
1107  /* TON */
1108  octstr_append_char(packet->data, 0x42);
1109  /* NPI */
1110  octstr_append_char(packet->data, 0x44);
1111  /* Originating address */
1112  octstr_append(packet->data, pdata->my_number);
1113  /* Receive ready flag */
1114  octstr_append_char(packet->data, 1);
1115  /* Retrieve order */
1116  octstr_append_char(packet->data, 0);
1117 
1118  ret = oisd_request(packet, conn, NULL);
1119  packet_destroy(packet);
1120 
1121  if (ret < 0)
1122  warning(0, "OISD[%s]: Sending delivery request failed.\n",
1123  octstr_get_cstr(conn->id));
1124 
1125  return ret;
1126 }
#define BOGUS_SEQUENCE
Definition: smsc_oisd.c:249
int octstr_check_range(Octstr *ostr, long pos, long len, octstr_func_t filter)
Definition: octstr.c:812
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
static int oisd_request(struct packet *request, SMSCConn *conn, Octstr **ts)
Definition: smsc_oisd.c:940
static int isphonedigit(int c)
Definition: smsc_oisd.c:136
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * my_number
Definition: smsc_cimd2.c:105
Octstr * data
Definition: smsc_cimd2.c:446
static void packet_destroy(struct packet *packet)
Definition: smsc_oisd.c:286
static struct packet * packet_create(int operation, unsigned long opref)
Definition: smsc_oisd.c:440
void warning(int err, const char *fmt,...)
Definition: log.c:624
gw_assert(wtls_machine->packet_to_send!=NULL)
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
static void oisd_send_response ( struct packet request,
PrivData pdata 
)
static

Definition at line 753 of file smsc_oisd.c.

References privdata::conn, packet::data, debug(), gw_assert(), smscconn::id, octstr_append_char(), octstr_dump, octstr_get_cstr, octstr_write_to_socket(), packet::operation, packet::opref, packet_create(), packet_destroy(), packet_set_data_size(), RESPONSE, response(), RESULT_SUCCESS, and privdata::socket.

Referenced by oisd_handle_request().

754 {
755  struct packet *response;
756 
757  gw_assert(request != NULL);
758  gw_assert(request->operation < RESPONSE);
759 
760  response = packet_create(request->operation + RESPONSE, request->opref);
761 
762  octstr_append_char(response->data, (char) RESULT_SUCCESS);
763 
764  packet_set_data_size(response);
765 
766  debug("bb.sms.oisd", 0, "OISD[%s]: sending response",
767  octstr_get_cstr(pdata->conn->id));
768  octstr_dump(response->data, 0);
769 
770  /* Don't check errors here because if there is something
771  * wrong with the socket, the main loop will detect it. */
772  octstr_write_to_socket(pdata->socket, response->data);
773 
774  packet_destroy(response);
775 }
int operation
Definition: smsc_cimd2.c:444
int octstr_write_to_socket(int socket, Octstr *ostr)
Definition: octstr.c:1225
#define RESULT_SUCCESS
Definition: smsc_oisd.c:117
Octstr * id
Definition: smscconn_p.h:174
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
int socket
Definition: smsc_cimd2.c:108
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * data
Definition: smsc_cimd2.c:446
static void packet_destroy(struct packet *packet)
Definition: smsc_oisd.c:286
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
static struct packet * packet_create(int operation, unsigned long opref)
Definition: smsc_oisd.c:440
gw_assert(wtls_machine->packet_to_send!=NULL)
static void packet_set_data_size(struct packet *packet)
Definition: smsc_oisd.c:477
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
unsigned long opref
Definition: smsc_oisd.c:243
static int response(List *push_headers, Octstr **username, Octstr **password)
SMSCConn * conn
Definition: smsc_cimd2.c:118
static void oisd_shrink_gsm7 ( Octstr str)
static

Definition at line 408 of file smsc_oisd.c.

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

Referenced by packet_encode_message().

409 {
410  Octstr *result;
411  int len, i;
412  int numbits, value;
413 
414  result = octstr_create("");
415  len = octstr_len(str);
416  value = 0;
417  numbits = 0;
418  for (i = 0; i < len; i++) {
419  value += octstr_get_char(str, i) << numbits;
420  numbits += 7;
421  if (numbits >= 8) {
422  octstr_append_char(result, value & 0xff);
423  value >>= 8;
424  numbits -= 8;
425  }
426  }
427  if (numbits > 0)
428  octstr_append_char(result, value);
429  octstr_delete(str, 0, LONG_MAX);
430  octstr_append(str, result);
431  octstr_destroy(result);
432 }
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 int oisd_shutdown_cb ( SMSCConn conn,
int  finish_sending 
)
static

Definition at line 1430 of file smsc_oisd.c.

References bb_smscconn_killed(), bb_smscconn_send_failed(), smscconn::data, debug(), gwlist_extract_first(), gwlist_remove_producer(), gwthread_join(), gwthread_wakeup(), smscconn::id, privdata::io_thread, smscconn::is_stopped, msg, octstr_get_cstr, oisd_close_socket(), oisd_destroy(), privdata::outgoing_queue, privdata::quitting, SMSCCONN_DEAD, SMSCCONN_FAILED_SHUTDOWN, SMSCCONN_KILLED_SHUTDOWN, smscconn::status, privdata::stopped, and smscconn::why_killed.

Referenced by smsc_oisd_create().

1431 {
1432  PrivData *pdata = conn->data;
1433 
1434  debug("bb.sms", 0, "Shutting down SMSCConn OISD %s (%s)",
1435  octstr_get_cstr(conn->id),
1436  finish_sending ? "slow" : "instant");
1437 
1438  /* Documentation claims this would have been done by smscconn.c,
1439  but isn't when this code is being written. */
1441  pdata->quitting = 1; /* Separate from why_killed to avoid locking, as
1442  * why_killed may be changed from outside? */
1443 
1444  if (finish_sending == 0) {
1445  Msg *msg;
1446  while ((msg = gwlist_extract_first(pdata->outgoing_queue)) != NULL) {
1448  }
1449  }
1450 
1451  if (conn->is_stopped) {
1453  conn->is_stopped = 0;
1454  }
1455 
1456  if (pdata->io_thread != -1) {
1457  gwthread_wakeup(pdata->io_thread);
1458  gwthread_join(pdata->io_thread);
1459  }
1460 
1461  oisd_close_socket(pdata);
1462  oisd_destroy(pdata);
1463 
1464  debug("bb.sms", 0, "SMSCConn OISD %s shut down.",
1465  octstr_get_cstr(conn->id));
1466  conn->status = SMSCCONN_DEAD;
1468  return 0;
1469 }
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
Octstr * id
Definition: smscconn_p.h:174
void gwthread_join(long thread)
void * data
Definition: smscconn_p.h:249
List * outgoing_queue
Definition: smsc_cgw.c:153
int io_thread
Definition: smsc_cimd2.c:119
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
List * stopped
Definition: smsc_cimd2.c:121
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
static void oisd_close_socket(PrivData *pdata)
Definition: smsc_oisd.c:1043
Definition: msg.h:79
void * gwlist_extract_first(List *list)
Definition: list.c:305
void gwlist_remove_producer(List *list)
Definition: list.c:401
static void oisd_destroy(PrivData *pdata)
Definition: smsc_oisd.c:1128
int quitting
Definition: smsc_cimd2.c:120
volatile sig_atomic_t is_stopped
Definition: smscconn_p.h:169
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
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
static void oisd_start_cb ( SMSCConn conn)
static

Definition at line 1471 of file smsc_oisd.c.

References smscconn::data, debug(), gwlist_remove_producer(), gwthread_wakeup(), smscconn::id, privdata::io_thread, octstr_get_cstr, and privdata::stopped.

Referenced by smsc_oisd_create().

1472 {
1473  PrivData *pdata = conn->data;
1474 
1476  /* in case there are messages in the buffer already */
1477  gwthread_wakeup(pdata->io_thread);
1478  debug("bb.sms", 0, "SMSCConn OISD %s, start called",
1479  octstr_get_cstr(conn->id));
1480 }
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
int io_thread
Definition: smsc_cimd2.c:119
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
List * stopped
Definition: smsc_cimd2.c:121
void gwlist_remove_producer(List *list)
Definition: list.c:401
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
void gwthread_wakeup(long thread)
static void oisd_stop_cb ( SMSCConn conn)
static

Definition at line 1482 of file smsc_oisd.c.

References smscconn::data, debug(), gwlist_add_producer(), smscconn::id, octstr_get_cstr, and privdata::stopped.

Referenced by smsc_oisd_create().

1483 {
1484  PrivData *pdata = conn->data;
1485  gwlist_add_producer(pdata->stopped);
1486  debug("bb.sms", 0, "SMSCConn OISD %s, stop called",
1487  octstr_get_cstr(conn->id));
1488 }
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
List * stopped
Definition: smsc_cimd2.c:121
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
void gwlist_add_producer(List *list)
Definition: list.c:383
static int oisd_submit_msg ( SMSCConn conn,
Msg msg 
)
static

Definition at line 1152 of file smsc_oisd.c.

References bb_smscconn_send_failed(), bb_smscconn_sent(), smscconn::data, debug(), dlr_add(), DLR_IS_SUCCESS_OR_FAIL, smscconn::flow_mutex, gw_assert(), smscconn::id, mutex_lock, mutex_unlock, smscconn::name, privdata::no_dlr, octstr_create, octstr_destroy(), octstr_get_cstr, oisd_close_socket(), oisd_request(), packet_destroy(), packet_encode_message(), SMSCCONN_DISCONNECTED, SMSCCONN_FAILED_MALFORMED, SMSCCONN_FAILED_REJECTED, SMSCCONN_FAILED_TEMPORARILY, and smscconn::status.

Referenced by io_thread().

1153 {
1154  PrivData *pdata = conn->data;
1155  struct packet *packet;
1156  Octstr *ts = NULL;
1157  int ret;
1158 
1159  gw_assert(pdata != NULL);
1160  debug("bb.sms.oisd", 0, "OISD[%s]: sending message",
1161  octstr_get_cstr(conn->id));
1162 
1163  packet = packet_encode_message(msg, conn);
1164  if (!packet) {
1165  /* This is a protocol error. Does this help? I doubt..
1166  * But nevermind that.
1167  */
1168  bb_smscconn_send_failed(conn, msg,
1170  return -1;
1171  }
1172 
1173  ret = oisd_request(packet, conn, &ts);
1174  if((ret == 0) && (ts) && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask) && !pdata->no_dlr) {
1175  dlr_add(conn->name, ts, msg, 0);
1176  }
1177  octstr_destroy(ts);
1178  packet_destroy(packet);
1179 
1180  if (ret == -1) {
1181  bb_smscconn_send_failed(conn, msg,
1183  }
1184  else if (ret == -2) {
1185  oisd_close_socket(pdata);
1187  mutex_lock(conn->flow_mutex);
1188  conn->status = SMSCCONN_DISCONNECTED;
1189  mutex_unlock(conn->flow_mutex);
1190  }
1191  else {
1192  bb_smscconn_sent(conn, msg, NULL);
1193  }
1194 
1195  return ret;
1196 }
Octstr * name
Definition: smscconn_p.h:173
#define mutex_unlock(m)
Definition: thread.h:136
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
static int oisd_request(struct packet *request, SMSCConn *conn, Octstr **ts)
Definition: smsc_oisd.c:940
void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg, int use_dst)
Definition: dlr.c:330
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static void oisd_close_socket(PrivData *pdata)
Definition: smsc_oisd.c:1043
static void packet_destroy(struct packet *packet)
Definition: smsc_oisd.c:286
Mutex * flow_mutex
Definition: smscconn_p.h:157
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
gw_assert(wtls_machine->packet_to_send!=NULL)
static struct packet * packet_encode_message(Msg *msg, SMSCConn *conn)
Definition: smsc_oisd.c:500
int no_dlr
Definition: smsc_cimd2.c:106
Definition: octstr.c:118
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:279
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
smscconn_status_t status
Definition: smscconn_p.h:151
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:328
#define mutex_lock(m)
Definition: thread.h:130
#define DLR_IS_SUCCESS_OR_FAIL(dlr)
Definition: dlr.h:85
static int operation_can_receive ( int  operation)
static

Definition at line 222 of file smsc_oisd.c.

References operation_can_send(), operation_find(), operations, and RESPONSE.

Referenced by operation_can_send(), and packet_check_can_receive().

223 {
224  int i = operation_find(operation);
225 
226  if (i >= 0)
227  return operations[i].can_receive;
228 
229  /* If we can send the request, then we can receive the response. */
230  if (operation >= RESPONSE)
232 
233  return 0;
234 }
int operation
Definition: smsc_cimd2.c:444
static int operation_can_send(int operation)
Definition: smsc_oisd.c:206
static const struct @26 operations[]
static int operation_find(int operation)
Definition: smsc_oisd.c:171
static int operation_can_send ( int  operation)
static

Definition at line 206 of file smsc_oisd.c.

References operation_can_receive(), operation_find(), operations, and RESPONSE.

Referenced by oisd_request(), and operation_can_receive().

207 {
208  int i = operation_find(operation);
209 
210  if (i >= 0)
211  return operations[i].can_send;
212 
213  /* If we can receive the request, then we can send the response. */
214  if (operation >= RESPONSE)
216 
217  return 0;
218 }
int operation
Definition: smsc_cimd2.c:444
static int operation_can_receive(int operation)
Definition: smsc_oisd.c:222
static const struct @26 operations[]
static int operation_find(int operation)
Definition: smsc_oisd.c:171
static int operation_find ( int  operation)
static

Definition at line 171 of file smsc_oisd.c.

References code, and operations.

Referenced by operation_can_receive(), operation_can_send(), and operation_name().

172 {
173  int i;
174 
175  for (i = 0; operations[i].name != NULL; i++) {
176  if (operations[i].code == operation)
177  return i;
178  }
179 
180  return -1;
181 }
int operation
Definition: smsc_cimd2.c:444
int code
Definition: smsc_oisd.c:158
static const struct @26 operations[]
static Octstr * operation_name ( int  operation)
static

Definition at line 184 of file smsc_oisd.c.

References name, octstr_append_cstr(), octstr_create, operation_find(), operations, and RESPONSE.

Referenced by oisd_request(), and packet_check_can_receive().

185 {
186  int i;
187 
189  if (i >= 0)
190  return octstr_create(operations[i].name);
191 
192  if (operation >= RESPONSE) {
194  if (i >= 0) {
195  Octstr *name = octstr_create(operations[i].name);
196  octstr_append_cstr(name, " response");
197  return name;
198  }
199  }
200 
201  /* Put the operation number here when we have octstr_format */
202  return octstr_create("(unknown)");
203 }
int operation
Definition: smsc_cimd2.c:444
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1509
#define octstr_create(cstr)
Definition: octstr.h:125
Definition: octstr.c:118
static const struct @26 operations[]
char * name
Definition: smsc_oisd.c:157
static int operation_find(int operation)
Definition: smsc_oisd.c:171
static void packet_check_can_receive ( struct packet packet,
SMSCConn conn 
)
static

Definition at line 340 of file smsc_oisd.c.

References gw_assert(), smscconn::id, name, octstr_destroy(), octstr_get_cstr, packet::operation, operation_can_receive(), operation_name(), and warning().

Referenced by oisd_get_packet(), and oisd_receive_msg().

341 {
342  gw_assert(packet != NULL);
343 
344  if (!operation_can_receive(packet->operation)) {
345  Octstr *name = operation_name(packet->operation);
346  warning(0, "OISD[%s]: SMSC sent us %s request",
347  octstr_get_cstr(conn->id),
348  octstr_get_cstr(name));
349  octstr_destroy(name);
350  }
351 }
int operation
Definition: smsc_cimd2.c:444
Octstr * id
Definition: smscconn_p.h:174
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void warning(int err, const char *fmt,...)
Definition: log.c:624
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
gw_assert(wtls_machine->packet_to_send!=NULL)
static int operation_can_receive(int operation)
Definition: smsc_oisd.c:222
static Octstr * operation_name(int operation)
Definition: smsc_oisd.c:184
Definition: octstr.c:118
char * name
Definition: smsc_oisd.c:157
static struct packet* packet_create ( int  operation,
unsigned long  opref 
)
static

Definition at line 440 of file smsc_oisd.c.

References packet::data, INVOKE, octstr_create_from_data, packet::operation, packet::opref, RESPONSE, and RESULT.

Referenced by oisd_send_delivery_request(), oisd_send_response(), and packet_encode_message().

441 {
442  struct packet *packet;
443  unsigned char header[10];
444 
445  packet = gw_malloc(sizeof(*packet));
446  packet->operation = operation;
447  packet->opref = opref;
448 
449  /* Opref */
450  header[0] = opref & 0xff;
451  header[1] = (opref >> 8) & 0xff;
452  header[2] = (opref >> 16) & 0xff;
453  header[3] = (opref >> 24) & 0xff;
454 
455  /* Message Type & Operation */
456  if (operation > RESPONSE) {
457  header[4] = RESULT;
458  header[5] = operation - RESPONSE;
459  } else {
460  header[4] = INVOKE;
461  header[5] = operation;
462  }
463 
464  /* Unused */
465  header[6] = 0;
466  header[7] = 0;
467 
468  /* Data Size */
469  header[8] = 0;
470  header[9] = 0;
471 
472  packet->data = octstr_create_from_data((char *)header, 10);
473 
474  return packet;
475 }
int operation
Definition: smsc_cimd2.c:444
Octstr * data
Definition: smsc_cimd2.c:446
unsigned long opref
Definition: smsc_oisd.c:243
#define octstr_create_from_data(data, len)
Definition: octstr.h:134
static void packet_destroy ( struct packet packet)
static

Definition at line 286 of file smsc_oisd.c.

References packet::data, and octstr_destroy().

Referenced by oisd_login(), oisd_receive_msg(), oisd_request(), oisd_send_delivery_request(), oisd_send_response(), and oisd_submit_msg().

287 {
288  if (packet != NULL) {
289  octstr_destroy(packet->data);
290  gw_free(packet);
291  }
292 }
Octstr * data
Definition: smsc_cimd2.c:446
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
static struct packet* packet_encode_message ( Msg msg,
SMSCConn conn 
)
static

Definition at line 500 of file smsc_oisd.c.

References BOGUS_SEQUENCE, charset_utf8_to_gsm(), smscconn::data, packet::data, DC_7BIT, DC_8BIT, DC_UNDEF, debug(), DLR_IS_SUCCESS_OR_FAIL, fields_to_dcs(), gw_assert(), smscconn::id, isphonedigit(), privdata::no_dlr, octstr_append(), octstr_append_char(), octstr_check_range(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_len(), oisd_shrink_gsm7(), packet_create(), parm_valid_address(), SMS_PARAM_UNDEFINED, SUBMIT_SM, Msg::type, privdata::validityperiod, and warning().

Referenced by oisd_submit_msg().

501 {
502  struct packet *packet;
503  PrivData *pdata = conn->data;
504  int DCS;
505  int setvalidity = SMS_PARAM_UNDEFINED;
506  int so = 0;
507  int udhlen7, udhlen8;
508  int msglen7, msglen8;
509  Octstr *udhdata = NULL;
510  Octstr *msgdata = NULL;
511 
512  gw_assert(msg != NULL);
513  gw_assert(msg->type == sms);
514  gw_assert(msg->sms.receiver != NULL);
515 
516  DCS = fields_to_dcs(msg, 0);
517  if (msg->sms.sender == NULL)
518  msg->sms.sender = octstr_create("");
519 
520  if (!parm_valid_address(msg->sms.receiver)) {
521  warning(0, "OISD[%s]: non-digits in destination phone number '%s', discarded",
522  octstr_get_cstr(conn->id),
523  octstr_get_cstr(msg->sms.receiver));
524  return NULL;
525  }
526 
527  if (!parm_valid_address(msg->sms.sender)) {
528  warning(0, "OISD[%s]: non-digits in originating phone number '%s', discarded",
529  octstr_get_cstr(conn->id),
530  octstr_get_cstr(msg->sms.sender));
531  return NULL;
532  }
533 
535 
536  gw_assert(octstr_check_range(msg->sms.receiver, 0,
537  octstr_len(msg->sms.receiver), isphonedigit));
538  /* MSISDN length */
539  octstr_append_char(packet->data,
540  (unsigned char) octstr_len(msg->sms.receiver));
541 
542  /* MSISDN */
543  octstr_append(packet->data, msg->sms.receiver);
544 
545  /* Duplicate msg. behaviour */
546  /* 1=reject duplicates, 2=allow duplicates */
547  octstr_append_char(packet->data, 2);
548 
549  /* SME ref. no. unused in this protocol implementation, but set */
550  octstr_append_char(packet->data, 0);
551  octstr_append_char(packet->data, 0);
552  octstr_append_char(packet->data, 0);
553  octstr_append_char(packet->data, 0);
554 
555  /* Priority 0=high, 1=normal */
556  octstr_append_char(packet->data, 1);
557  gw_assert(octstr_check_range(msg->sms.sender, 0,
558  octstr_len(msg->sms.sender), isphonedigit));
559 
560  /* Originating address length */
561  octstr_append_char(packet->data,
562  (unsigned char) (octstr_len(msg->sms.sender) + 2));
563 
564  /* XXX: GSM operator dependent ? */
565  /* TON */
566  octstr_append_char(packet->data, 0x42);
567 
568  /* NPI */
569  octstr_append_char(packet->data, 0x44);
570 
571  /* Originating address */
572  octstr_append(packet->data, msg->sms.sender);
573 
574  /* Validity period type 0=none, 1=absolute, 2=relative */
575 
576  /*
577  * Validity-Period (TP-VP)
578  * see GSM 03.40 section 9.2.3.12
579  */
580  if (msg->sms.validity != SMS_PARAM_UNDEFINED)
581  setvalidity = (msg->sms.validity - time(NULL)) / 60;
582  else if (setvalidity != SMS_PARAM_UNDEFINED)
583  setvalidity = pdata->validityperiod;
584  if (setvalidity != SMS_PARAM_UNDEFINED) {
585  /* Validity period type 0=none, 1=absolute, 2=relative */
586  octstr_append_char(packet->data, 2);
587 
588  if (setvalidity > 635040)
589  setvalidity = 255;
590  else if (setvalidity >= 50400 && setvalidity <= 635040)
591  setvalidity = (setvalidity - 1) / 7 / 24 / 60 + 192 + 1;
592  else if (setvalidity > 43200 && setvalidity < 50400)
593  setvalidity = 197;
594  else if (setvalidity >= 2880 && setvalidity <= 43200)
595  setvalidity = (setvalidity - 1) / 24 / 60 + 166 + 1;
596  else if (setvalidity > 1440 && setvalidity < 2880)
597  setvalidity = 168;
598  else if (setvalidity >= 750 && setvalidity <= 1440)
599  setvalidity = (setvalidity - 720 - 1) / 30 + 143 + 1;
600  else if (setvalidity > 720 && setvalidity < 750)
601  setvalidity = 144;
602  else if (setvalidity >= 5 && setvalidity <= 720)
603  setvalidity = (setvalidity - 1) / 5 - 1 + 1;
604  else if (setvalidity < 5)
605  setvalidity = 0;
606 
607  octstr_append_char(packet->data, setvalidity);
608  } else {
609  /* Validity period type 0=none, 1=absolute, 2=relative */
610  octstr_append_char(packet->data, 0);
611  setvalidity = 0; /* reset */
612  }
613 
614  if (setvalidity >= 0 && setvalidity <= 143)
615  debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d minutes",
616  octstr_get_cstr(conn->id), (setvalidity + 1)*5);
617  else if (setvalidity >= 144 && setvalidity <= 167)
618  debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %3.1f hours",
619  octstr_get_cstr(conn->id), ((float)(setvalidity - 143) / 2) + 12);
620  else if (setvalidity >= 168 && setvalidity <= 196)
621  debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d days",
622  octstr_get_cstr(conn->id), (setvalidity - 166));
623  else
624  debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d weeks",
625  octstr_get_cstr(conn->id), (setvalidity - 192));
626 
627  /* Data coding scheme */
628  octstr_append_char(packet->data, DCS);
629 
630  /* Explicitly ask not to get status reports.
631  * If we do not do this, the server's default might be to
632  * send status reports in some cases, and we don't do anything
633  * with those reports anyway. */
634  /* ask for the delivery reports if needed*/
635 
636  if (!pdata->no_dlr)
637  if (DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask))
638  octstr_append_char(packet->data, 7);
639  else
640  octstr_append_char(packet->data, 0);
641  else if (pdata->no_dlr && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask))
642  warning(0, "OISD[%s]: dlr request make no sense while no-dlr set to true",
643  octstr_get_cstr(conn->id));
644 
645  /* Protocol id 0=default */
646  octstr_append_char(packet->data, 0);
647 
648  if (octstr_len(msg->sms.udhdata))
649  so |= 0x02;
650  if (msg->sms.coding == DC_8BIT)
651  so |= 0x10;
652 
653  /* Submission options */
654  octstr_append_char(packet->data, so);
655 
656  udhlen8 = octstr_len(msg->sms.udhdata);
657  msglen8 = octstr_len(msg->sms.msgdata);
658 
659  udhdata = octstr_duplicate(msg->sms.udhdata);
660  msgdata = octstr_duplicate(msg->sms.msgdata);
661 
662  if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) {
663  debug("bb.sms.oisd", 0, "OISD[%s]: sending UTF-8=%s",
664  octstr_get_cstr(conn->id),
665  octstr_get_cstr(msg->sms.msgdata));
666  charset_utf8_to_gsm(msgdata);
667  oisd_shrink_gsm7(msgdata);
668  }
669 
670  /* calculate lengths */
671  udhlen7 = octstr_len(udhdata);
672  msglen7 = octstr_len(msgdata);
673 
674  octstr_append_char(packet->data, (unsigned char) (udhlen8 + msglen8));
675  octstr_append_char(packet->data, (unsigned char) (udhlen7 + msglen7));
676 
677  /*
678  * debug("bb.sms.oisd", 0, "OISD[%s]: packet_encode_message udhlen8=%d, msglen8=%d",
679  * octstr_get_cstr(conn->id), udhlen8, msglen8);
680  * debug("bb.sms.oisd", 0, "OISD[%s]: packet_encode_message udhlen7=%d, msglen7=%d",
681  * octstr_get_cstr(conn->id), udhlen7, msglen7);
682  */
683 
684  /* copy text */
685  octstr_append(packet->data, udhdata);
686  octstr_append(packet->data, msgdata);
687 
688  /* Sub-logical SME number */
689  octstr_append_char(packet->data, 0);
690  octstr_append_char(packet->data, 0);
691 
692  octstr_destroy(udhdata);
693  octstr_destroy(msgdata);
694 
695  return packet;
696 }
#define BOGUS_SEQUENCE
Definition: smsc_oisd.c:249
int octstr_check_range(Octstr *ostr, long pos, long len, octstr_func_t filter)
Definition: octstr.c:812
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
Octstr * id
Definition: smscconn_p.h:174
long validityperiod
Definition: smsc_oisd.c:94
void * data
Definition: smscconn_p.h:249
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
void charset_utf8_to_gsm(Octstr *ostr)
Definition: charset.c:288
#define DC_8BIT
Definition: sms.h:111
static void oisd_shrink_gsm7(Octstr *str)
Definition: smsc_oisd.c:408
static int isphonedigit(int c)
Definition: smsc_oisd.c:136
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * data
Definition: smsc_cimd2.c:446
#define octstr_duplicate(ostr)
Definition: octstr.h:187
static struct packet * packet_create(int operation, unsigned long opref)
Definition: smsc_oisd.c:440
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
int fields_to_dcs(Msg *msg, int mode)
Definition: sms.c:73
gw_assert(wtls_machine->packet_to_send!=NULL)
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
int no_dlr
Definition: smsc_cimd2.c:106
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
enum msg_type type
Definition: msg.h:80
#define DC_UNDEF
Definition: sms.h:109
static int parm_valid_address(Octstr *value)
Definition: smsc_oisd.c:141
#define DLR_IS_SUCCESS_OR_FAIL(dlr)
Definition: dlr.h:85
#define DC_7BIT
Definition: sms.h:110
static struct packet* packet_extract ( Octstr in,
SMSCConn conn 
)
static

Definition at line 299 of file smsc_oisd.c.

References error(), smscconn::id, octstr_copy, octstr_delete(), octstr_dump, octstr_get_char(), octstr_get_cstr, octstr_get_many_chars(), octstr_len(), packet_parse(), and size.

Referenced by oisd_get_packet(), and oisd_receive_msg().

300 {
301  Octstr *packet;
302  int size, i;
303  static char s[4][4] = {
304  { 0x01, 0x0b, 0x00, 0x00 },
305  { 0x01, 0x00, 0x00, 0x00 },
306  { 0x00, 0x04, 0x00, 0x00 },
307  { 0x00, 0x09, 0x00, 0x00 }
308  }; /* msgtype, oper, 0, 0 */
309  char known_bytes[4];
310 
311  if (octstr_len(in) < 10)
312  return NULL;
313  octstr_get_many_chars(known_bytes, in, 4, 4);
314  /* Find s, and delete everything up to it. */
315  /* If packet starts with one of s, it should be good packet */
316  for (i = 0; i < 4; i++) {
317  if (memcmp(s[i], known_bytes, 4) == 0)
318  break;
319  }
320 
321  if (i >= 4) {
322  error(0, "OISD[%s]: wrong packet",
323  octstr_get_cstr(conn->id));
324  octstr_dump(in, 0);
325  return NULL;
326  }
327 
328  /* Find end of packet */
329  size = (octstr_get_char(in, 9) << 8) | octstr_get_char(in, 8);
330 
331  if (size + 10 > octstr_len(in))
332  return NULL;
333 
334  packet = octstr_copy(in, 0, size + 10);
335  octstr_delete(in, 0, size + 10);
336 
337  return packet_parse(packet);
338 }
void error(int err, const char *fmt,...)
Definition: log.c:612
int size
Definition: wsasm.c:84
Octstr * id
Definition: smscconn_p.h:174
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
static struct packet * packet_parse(Octstr *packet_data)
Definition: smsc_oisd.c:272
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1525
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
Definition: octstr.c:423
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static struct packet* packet_parse ( Octstr packet_data)
static

Definition at line 272 of file smsc_oisd.c.

References packet::data, and packet_parse_header().

Referenced by packet_extract().

273 {
274  struct packet *packet;
275 
276  packet = gw_malloc(sizeof(*packet));
277  packet->data = packet_data;
278 
279  /* Fill in packet->operation and packet->opref */
280  packet_parse_header(packet);
281 
282  return packet;
283 }
static void packet_parse_header(struct packet *packet)
Definition: smsc_oisd.c:254
Octstr * data
Definition: smsc_cimd2.c:446
static void packet_parse_header ( struct packet packet)
static

Definition at line 254 of file smsc_oisd.c.

References packet::data, octstr_get_char(), packet::operation, packet::opref, and RESPONSE.

Referenced by packet_parse().

255 {
256  packet->opref = (octstr_get_char(packet->data, 3) << 24)
257  | (octstr_get_char(packet->data, 2) << 16)
258  | (octstr_get_char(packet->data, 1) << 8)
259  | (octstr_get_char(packet->data, 0));
260 
261  packet->operation = octstr_get_char(packet->data, 5);
262  if (octstr_get_char(packet->data, 4) == 1)
263  packet->operation += RESPONSE;
264 }
int operation
Definition: smsc_cimd2.c:444
Octstr * data
Definition: smsc_cimd2.c:446
unsigned long opref
Definition: smsc_oisd.c:243
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
static void packet_set_data_size ( struct packet packet)
static

Definition at line 477 of file smsc_oisd.c.

References packet::data, gw_assert(), octstr_len(), and octstr_set_char().

Referenced by oisd_request(), and oisd_send_response().

478 {
479  int len;
480 
481  gw_assert(packet != NULL);
482 
483  len = octstr_len(packet->data) - 10;
484 
485  octstr_set_char(packet->data, 8, len & 0xff); /* Data Size */
486  octstr_set_char(packet->data, 9, (len >> 8) & 0xff);
487 }
Octstr * data
Definition: smsc_cimd2.c:446
gw_assert(wtls_machine->packet_to_send!=NULL)
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:413
static void packet_set_send_sequence ( struct packet packet,
PrivData pdata 
)
static

Definition at line 703 of file smsc_oisd.c.

References gw_assert(), packet_set_sequence(), and privdata::send_seq.

Referenced by oisd_request().

704 {
705  gw_assert(pdata != NULL);
706 
707  packet_set_sequence(packet, pdata->send_seq);
708  pdata->send_seq++;
709 }
static void packet_set_sequence(struct packet *packet, unsigned long opref)
Definition: smsc_oisd.c:489
gw_assert(wtls_machine->packet_to_send!=NULL)
int send_seq
Definition: smsc_cimd2.c:109
static void packet_set_sequence ( struct packet packet,
unsigned long  opref 
)
static

Definition at line 489 of file smsc_oisd.c.

References packet::data, gw_assert(), octstr_set_char(), and packet::opref.

Referenced by packet_set_send_sequence().

490 {
491  gw_assert(packet != NULL);
492 
493  octstr_set_char(packet->data, 0, opref & 0xff);
494  octstr_set_char(packet->data, 1, (opref >> 8) & 0xff);
495  octstr_set_char(packet->data, 2, (opref >> 16) & 0xff);
496  octstr_set_char(packet->data, 3, (opref >> 24) & 0xff);
497  packet->opref = opref;
498 }
Octstr * data
Definition: smsc_cimd2.c:446
gw_assert(wtls_machine->packet_to_send!=NULL)
unsigned long opref
Definition: smsc_oisd.c:243
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:413
static int parm_valid_address ( Octstr value)
static

Definition at line 141 of file smsc_oisd.c.

References isphonedigit(), octstr_check_range(), and octstr_len().

Referenced by packet_encode_message().

142 {
143  return octstr_check_range(value, 0, octstr_len(value), isphonedigit);
144 }
int octstr_check_range(Octstr *ostr, long pos, long len, octstr_func_t filter)
Definition: octstr.c:812
static int isphonedigit(int c)
Definition: smsc_oisd.c:136
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
static Msg* sms_receive ( SMSCConn conn)
static

Definition at line 1320 of file smsc_oisd.c.

References smscconn::data, smscconn::flow_mutex, smscconn::id, msg_destroy(), mutex_lock, mutex_unlock, octstr_duplicate, oisd_close_socket(), oisd_receive_msg(), SMSCCONN_DISCONNECTED, and smscconn::status.

Referenced by io_thread().

1321 {
1322  PrivData *pdata = conn->data;
1323  int ret;
1324  Msg *newmsg = NULL;
1325 
1326  ret = oisd_receive_msg(conn, &newmsg);
1327  if (ret == 1) {
1328  /* if any smsc_id available, use it */
1329  newmsg->sms.smsc_id = octstr_duplicate(conn->id);
1330  return newmsg;
1331  }
1332  else if (ret == 0) { /* no message, just retry... */
1333  return NULL;
1334  }
1335  /* error. reconnect. */
1336  msg_destroy(newmsg);
1337  mutex_lock(conn->flow_mutex);
1338  oisd_close_socket(pdata);
1339  conn->status = SMSCCONN_DISCONNECTED;
1340  mutex_unlock(conn->flow_mutex);
1341  return NULL;
1342 }
static int oisd_receive_msg(SMSCConn *conn, Msg **msg)
Definition: smsc_oisd.c:1198
#define mutex_unlock(m)
Definition: thread.h:136
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
static void oisd_close_socket(PrivData *pdata)
Definition: smsc_oisd.c:1043
Definition: msg.h:79
#define octstr_duplicate(ostr)
Definition: octstr.h:187
Mutex * flow_mutex
Definition: smscconn_p.h:157
void msg_destroy(Msg *msg)
Definition: msg.c:132
smscconn_status_t status
Definition: smscconn_p.h:151
#define mutex_lock(m)
Definition: thread.h:130
int smsc_oisd_create ( SMSCConn conn,
CfgGroup grp 
)

Definition at line 1498 of file smsc_oisd.c.

References cfg_get, cfg_get_bool(), cfg_get_integer(), privdata::conn, smscconn::data, debug(), error(), gwlist_add_producer(), gwlist_create, gwthread_create, gwthread_join(), gwthread_wakeup(), privdata::host, smscconn::id, privdata::inbuffer, privdata::io_thread, io_thread(), smscconn::is_stopped, privdata::keepalive, privdata::my_number, smscconn::name, privdata::next_ping, privdata::no_dlr, octstr_create, octstr_format(), octstr_get_cstr, octstr_imm(), oisd_add_msg_cb(), oisd_destroy(), oisd_queued_cb(), oisd_shutdown_cb(), oisd_start_cb(), oisd_stop_cb(), ok, privdata::outgoing_queue, privdata::port, smscconn::queued, privdata::quitting, privdata::received, smscconn::send_msg, privdata::send_seq, smscconn::shutdown, SMS_PARAM_UNDEFINED, privdata::socket, smscconn::start_conn, smscconn::stop_conn, privdata::stopped, and privdata::validityperiod.

Referenced by smscconn_create().

1499 {
1500  PrivData *pdata;
1501  int ok;
1502 
1503  pdata = gw_malloc(sizeof(PrivData));
1504  conn->data = pdata;
1505  pdata->conn = conn;
1506 
1507  pdata->no_dlr = 0;
1508  pdata->quitting = 0;
1509  pdata->socket = -1;
1510  pdata->received = gwlist_create();
1511  pdata->inbuffer = octstr_create("");
1512  pdata->send_seq = 1;
1513  pdata->outgoing_queue = gwlist_create();
1514  pdata->stopped = gwlist_create();
1516 
1517  if (conn->is_stopped)
1518  gwlist_add_producer(pdata->stopped);
1519 
1520  pdata->host = cfg_get(grp, octstr_imm("host"));
1521  if (cfg_get_integer(&(pdata->port), grp, octstr_imm("port")) == -1)
1522  pdata->port = 0;
1523  pdata->my_number = cfg_get(grp, octstr_imm("my-number"));
1524  if (cfg_get_integer(&(pdata->keepalive), grp, octstr_imm("keepalive")) == -1)
1525  pdata->keepalive = 0;
1526  if (cfg_get_integer(&(pdata->validityperiod), grp, octstr_imm("validityperiod")) == -1)
1528 
1529  cfg_get_bool(&pdata->no_dlr, grp, octstr_imm("no-dlr"));
1530 
1531  /* Check that config is OK */
1532  ok = 1;
1533  if (pdata->host == NULL) {
1534  error(0, "OISD[%s]: Configuration file doesn't specify host",
1535  octstr_get_cstr(conn->id));
1536  ok = 0;
1537  }
1538  if (pdata->port == 0) {
1539  error(0, "OISD[%s]: Configuration file doesn't specify port",
1540  octstr_get_cstr(conn->id));
1541  ok = 0;
1542  }
1543  if (pdata->my_number == NULL && pdata->keepalive > 0) {
1544  error(0, "OISD[%s]: Configuration file doesn't specify my-number.",
1545  octstr_get_cstr(conn->id));
1546  ok = 0;
1547  }
1548 
1549  if (!ok) {
1550  oisd_destroy(pdata);
1551  return -1;
1552  }
1553 
1554  conn->name = octstr_format("OISD:%s:%d",
1555  octstr_get_cstr(pdata->host),
1556  pdata->port);
1557 
1558 
1559  if (pdata->keepalive > 0) {
1560  debug("bb.sms.oisd", 0, "OISD[%s]: Keepalive set to %ld seconds",
1561  octstr_get_cstr(conn->id),
1562  pdata->keepalive);
1563  pdata->next_ping = time(NULL) + pdata->keepalive;
1564  }
1565 
1566  if (pdata->validityperiod > 0) {
1567  debug("bb.sms.oisd", 0, "OISD[%s]: Validity-Period set to %ld",
1568  octstr_get_cstr(conn->id),
1569  pdata->validityperiod);
1570  }
1571 
1572  pdata->io_thread = gwthread_create(io_thread, conn);
1573 
1574  if (pdata->io_thread == -1) {
1575 
1576  error(0, "OISD[%s]: Couldn't start I/O thread.",
1577  octstr_get_cstr(conn->id));
1578  pdata->quitting = 1;
1579  gwthread_wakeup(pdata->io_thread);
1580  gwthread_join(pdata->io_thread);
1581  oisd_destroy(pdata);
1582  return -1;
1583  }
1584 
1585  conn->send_msg = oisd_add_msg_cb;
1586  conn->shutdown = oisd_shutdown_cb;
1587  conn->queued = oisd_queued_cb;
1588  conn->start_conn = oisd_start_cb;
1589  conn->stop_conn = oisd_stop_cb;
1590 
1591  return 0;
1592 }
int port
Definition: smsc_cgw.c:159
Octstr * name
Definition: smscconn_p.h:173
void error(int err, const char *fmt,...)
Definition: log.c:612
Octstr * inbuffer
Definition: smsc_cimd2.c:112
static void io_thread(void *arg)
Definition: smsc_oisd.c:1344
static void oisd_stop_cb(SMSCConn *conn)
Definition: smsc_oisd.c:1482
Octstr * id
Definition: smscconn_p.h:174
void gwthread_join(long thread)
long validityperiod
Definition: smsc_oisd.c:94
void * data
Definition: smscconn_p.h:249
List * outgoing_queue
Definition: smsc_cgw.c:153
void(* stop_conn)(SMSCConn *conn)
Definition: smscconn_p.h:246
int socket
Definition: smsc_cimd2.c:108
#define cfg_get(grp, varname)
Definition: cfg.h:86
int io_thread
Definition: smsc_cimd2.c:119
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void(* start_conn)(SMSCConn *conn)
Definition: smscconn_p.h:245
List * stopped
Definition: smsc_cimd2.c:121
time_t next_ping
Definition: smsc_cimd2.c:115
static int oisd_add_msg_cb(SMSCConn *conn, Msg *sms)
Definition: smsc_oisd.c:1418
static void oisd_start_cb(SMSCConn *conn)
Definition: smsc_oisd.c:1471
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Octstr * my_number
Definition: smsc_cimd2.c:105
static void oisd_destroy(PrivData *pdata)
Definition: smsc_oisd.c:1128
Octstr * host
Definition: smsc_cgw.c:163
int quitting
Definition: smsc_cimd2.c:120
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
volatile sig_atomic_t is_stopped
Definition: smscconn_p.h:169
static long oisd_queued_cb(SMSCConn *conn)
Definition: smsc_oisd.c:1490
int send_seq
Definition: smsc_cimd2.c:109
int no_dlr
Definition: smsc_cimd2.c:106
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:756
int(* shutdown)(SMSCConn *conn, int finish_sending)
Definition: smscconn_p.h:229
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
Definition: wtp_tid.h:82
void gwthread_wakeup(long thread)
List * received
Definition: smsc_cimd2.c:113
#define gwlist_create()
Definition: list.h:136
long(* queued)(SMSCConn *conn)
Definition: smscconn_p.h:240
int(* send_msg)(SMSCConn *conn, Msg *msg)
Definition: smscconn_p.h:235
void gwlist_add_producer(List *list)
Definition: list.c:383
long keepalive
Definition: smsc_cimd2.c:104
static int oisd_shutdown_cb(SMSCConn *conn, int finish_sending)
Definition: smsc_oisd.c:1430
SMSCConn * conn
Definition: smsc_cimd2.c:118

Variable Documentation

int can_receive

Definition at line 160 of file smsc_oisd.c.

int can_send

Definition at line 159 of file smsc_oisd.c.

int code

Definition at line 158 of file smsc_oisd.c.

Referenced by oisd_accept_delivery_report_message(), and operation_find().

char* name

Definition at line 157 of file smsc_oisd.c.

Referenced by operation_name(), and packet_check_can_receive().

const { ... } operations[]
Initial value:
= {
{ "Submit SM", SUBMIT_SM, 1, 0 },
{ "Status Report", STATUS_REPORT, 0, 1 },
{ "Deliver SM", DELIVER_SM, 0, 1 },
{ "Retrieve Request", RETRIEVE_REQUEST, 1, 0 },
{ NULL, 0, 0, 0 }
}

Referenced by operation_can_receive(), operation_can_send(), operation_find(), and operation_name().

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