Kannel: Open Source WAP and SMS gateway  svn-r5335
smsc_fake.c File Reference
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <limits.h>
#include "gwlib/gwlib.h"
#include "smscconn.h"
#include "smscconn_p.h"
#include "bb_smscconn_cb.h"
#include "msg.h"
#include "sms.h"
#include "dlr.h"

Go to the source code of this file.

Data Structures

struct  privdata
 

Typedefs

typedef struct privdata PrivData
 

Functions

static int fake_open_connection (SMSCConn *conn, PrivData *privdata)
 
static int sms_to_client (Connection *client, Msg *msg)
 
static void msg_to_bb (SMSCConn *conn, Octstr *line)
 
static void main_connection_loop (SMSCConn *conn, Connection *client)
 
static void fake_listener (void *arg)
 
static int add_msg_cb (SMSCConn *conn, Msg *sms)
 
static int shutdown_cb (SMSCConn *conn, int finish_sending)
 
static void start_cb (SMSCConn *conn)
 
static long queued_cb (SMSCConn *conn)
 
int smsc_fake_create (SMSCConn *conn, CfgGroup *cfg)
 

Typedef Documentation

◆ PrivData

typedef struct privdata PrivData

Function Documentation

◆ add_msg_cb()

static int add_msg_cb ( SMSCConn conn,
Msg sms 
)
static

Definition at line 457 of file smsc_fake.c.

References privdata::connection_thread, smscconn::data, dlr_add(), DLR_IS_ENABLED_DEVICE, gwlist_produce(), gwthread_wakeup(), smscconn::id, msg_duplicate(), octstr_destroy(), octstr_format(), privdata::outgoing_queue, UUID_STR_LEN, and uuid_unparse().

Referenced by smsc_fake_create().

458 {
459  PrivData *privdata = conn->data;
460  Msg *copy;
461 
462  copy = msg_duplicate(sms);
463 
464  /*
465  * Send DLR if desired, which means first add the DLR entry
466  * and then later find it and remove it. We need to ensure
467  * that we put the DLR in first before producing the copy
468  * to the list.
469  */
470  if (DLR_IS_ENABLED_DEVICE(sms->sms.dlr_mask)) {
471  Octstr *tmp;
472  char id[UUID_STR_LEN + 1];
473  uuid_unparse(sms->sms.id, id);
474  tmp = octstr_format("%s", id);
475  dlr_add(conn->id, tmp, sms, 0);
476  octstr_destroy(tmp);
477  }
479 
481 
482  return 0;
483 }
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
void gwlist_produce(List *list, void *item)
Definition: list.c:411
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:250
List * outgoing_queue
Definition: smsc_cgw.c:153
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg, int use_dst)
Definition: dlr.c:330
Definition: msg.h:79
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
long connection_thread
Definition: smsc_fake.c:83
#define UUID_STR_LEN
Definition: gw_uuid.h:19
Definition: octstr.c:118
void gwthread_wakeup(long thread)
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82

◆ fake_listener()

static void fake_listener ( void *  arg)
static

Definition at line 364 of file smsc_fake.c.

References privdata::allow_ip, bb_smscconn_connected(), bb_smscconn_killed(), bb_smscconn_send_failed(), client(), conn_claim(), conn_wrap_fd(), smscconn::connect_time, smscconn::data, debug(), privdata::deny_ip, error(), smscconn::flow_mutex, gwlist_destroy(), gwlist_extract_first(), gwthread_pollfd(), host_ip(), info(), is_allowed_ip(), privdata::listening_socket, smscconn::log_idx, log_thread_to(), main_connection_loop(), msg, mutex_lock, mutex_unlock, octstr_destroy(), octstr_get_cstr, privdata::outgoing_queue, POLLIN, privdata::shutdown, SMSCCONN_ACTIVE, SMSCCONN_DEAD, SMSCCONN_FAILED_SHUTDOWN, SMSCCONN_FAILED_TEMPORARILY, SMSCCONN_RECONNECTING, smscconn::status, and warning().

Referenced by smsc_fake_create().

365 {
366  SMSCConn *conn = arg;
367  PrivData *privdata = conn->data;
368  struct sockaddr_in client_addr;
369  socklen_t client_addr_len;
370  Octstr *ip;
372  int s, ret;
373  Msg *msg;
374 
375  /* Make sure we log into our own log-file if defined */
376  log_thread_to(conn->log_idx);
377 
378  while (1) {
379  client_addr_len = sizeof(client_addr);
381  if (ret == -1) {
382  if (errno == EINTR)
383  continue;
384  error(0, "Poll for fakesmsc connections failed, shutting down");
385  break;
386  }
387  if (privdata->shutdown)
388  break;
389  if (ret == 0)
390  /*
391  * This thread was woke up from elsewhere, but
392  * if we're not shutting down nothing to do here.
393  */
394  continue;
395  s = accept(privdata->listening_socket, (struct sockaddr *)&client_addr,
396  &client_addr_len);
397  if (s == -1) {
398  warning(errno, "fake_listener: accept() failed, retrying...");
399  continue;
400  }
401  ip = host_ip(client_addr);
403  info(0, "Fakesmsc connection tried from denied host <%s>, "
404  "disconnected", octstr_get_cstr(ip));
405  octstr_destroy(ip);
406  close(s);
407  continue;
408  }
409  client = conn_wrap_fd(s, 0);
410  if (client == NULL) {
411  error(0, "fake_listener: conn_wrap_fd failed on accept()ed fd");
412  octstr_destroy(ip);
413  close(s);
414  continue;
415  }
417  info(0, "Fakesmsc client connected from %s", octstr_get_cstr(ip));
418  octstr_destroy(ip);
419  mutex_lock(conn->flow_mutex);
420  conn->status = SMSCCONN_ACTIVE;
421  conn->connect_time = time(NULL);
422  mutex_unlock(conn->flow_mutex);
423  bb_smscconn_connected(conn);
424 
426 
427  if (privdata->shutdown)
428  break;
429  mutex_lock(conn->flow_mutex);
431  mutex_unlock(conn->flow_mutex);
432  while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
434  }
435  }
436  if (close(privdata->listening_socket) == -1)
437  warning(errno, "smsc_fake: couldn't close listening socket at shutdown");
438  mutex_lock(conn->flow_mutex);
439 
440  conn->status = SMSCCONN_DEAD;
441 
442  while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
444  }
448  gw_free(privdata);
449  conn->data = NULL;
450 
451  mutex_unlock(conn->flow_mutex);
452  debug("bb.sms", 0, "smsc_fake connection has completed shutdown.");
454 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
void bb_smscconn_connected(SMSCConn *conn)
Definition: bb_smscconn.c:192
static void main_connection_loop(SMSCConn *conn, Connection *client)
Definition: smsc_fake.c:264
#define mutex_unlock(m)
Definition: thread.h:136
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
void * data
Definition: smscconn_p.h:250
static void client(int port)
Definition: test_udp.c:77
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
void log_thread_to(int idx)
Definition: log.c:759
int is_allowed_ip(Octstr *allow_ip, Octstr *deny_ip, Octstr *ip)
Definition: utils.c:815
void conn_claim(Connection *conn)
Definition: conn.c:671
#define POLLIN
Definition: gwpoll.h:91
Definition: msg.h:79
void * gwlist_extract_first(List *list)
Definition: list.c:305
time_t connect_time
Definition: smscconn_p.h:155
Mutex * flow_mutex
Definition: smscconn_p.h:157
Octstr * allow_ip
Definition: smsc_cgw.c:164
void warning(int err, const char *fmt,...)
Definition: log.c:660
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
int gwthread_pollfd(int fd, int events, double timeout)
int shutdown
Definition: smsc_cgw.c:156
Definition: octstr.c:118
Octstr * host_ip(struct sockaddr_in addr)
Definition: socket.c:615
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int socklen_t
Definition: socket.h:73
smscconn_status_t status
Definition: smscconn_p.h:151
int listening_socket
Definition: smsc_cgw.c:157
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:329
#define mutex_lock(m)
Definition: thread.h:130
Octstr * deny_ip
Definition: smsc_cgw.c:164
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
Connection * conn_wrap_fd(int fd, int ssl)
Definition: conn.c:566
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ fake_open_connection()

static int fake_open_connection ( SMSCConn conn,
PrivData privdata 
)
static

Definition at line 91 of file smsc_fake.c.

References error(), privdata::listening_socket, make_server_socket(), octstr_get_cstr, smscconn::our_host, privdata::port, and socket_set_blocking().

Referenced by smsc_fake_create().

92 {
93  int s;
94 
95  if ((s = make_server_socket(privdata->port, (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL))) == -1) {
96  error(0, "smsc_fake: could not create listening socket in port %d",
97  privdata->port);
98  return -1;
99  }
100  if (socket_set_blocking(s, 0) == -1) {
101  error(0, "smsc_fake: couldn't make listening socket port %d non-blocking",
102  privdata->port);
103  return -1;
104  }
106  return 0;
107 }
int port
Definition: smsc_cgw.c:159
void error(int err, const char *fmt,...)
Definition: log.c:648
int socket_set_blocking(int fd, int blocking)
Definition: socket.c:368
Octstr * our_host
Definition: smscconn_p.h:192
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
int make_server_socket(int port, const char *interface_name)
Definition: socket.c:93
int listening_socket
Definition: smsc_cgw.c:157

◆ main_connection_loop()

static void main_connection_loop ( SMSCConn conn,
Connection client 
)
static

Definition at line 264 of file smsc_fake.c.

References bb_smscconn_receive(), bb_smscconn_send_failed(), bb_smscconn_sent(), client(), conn_destroy(), conn_eof(), conn_error(), conn_read_line(), conn_wait(), smscconn::data, debug(), delay, dlr_find(), DLR_IS_SUCCESS_OR_FAIL, DLR_SUCCESS, error(), gwlist_extract_first(), gwthread_sleep(), smscconn::id, info(), smscconn::is_stopped, msg, msg_destroy(), msg_duplicate(), msg_to_bb(), octstr_create, octstr_destroy(), privdata::outgoing_queue, privdata::shutdown, sms_to_client(), SMSCCONN_FAILED_REJECTED, smscconn::throughput, UUID_STR_LEN, and uuid_unparse().

Referenced by fake_listener().

265 {
266  PrivData *privdata = conn->data;
267  Octstr *line;
268  Msg *msg;
269  double delay = 0;
270 
271  if (conn->throughput > 0) {
272  delay = 1.0 / conn->throughput;
273  }
274 
275  while (1) {
276  while (!conn->is_stopped && !privdata->shutdown &&
277  (line = conn_read_line(client)))
278  msg_to_bb(conn, line);
279  if (conn_error(client))
280  goto error;
281  if (conn_eof(client))
282  goto eof;
283 
284  /*
285  * We won't get DLRs from fakesmsc itself, due that we don't have
286  * corresponding message IDs etc. We threat the DLR receiving here. So
287  * DLR "originate" from the protocol layer towards abstraction layer.
288  * This is all for pure debugging and testing.
289  */
290 
291  while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
292 
293  /* pass msg to fakesmsc daemon */
294  if (sms_to_client(client, msg) == 1) {
295  Msg *copy = msg_duplicate(msg);
296 
297  /*
298  * Actually no guarantee of it having been really sent,
299  * but I suppose that doesn't matter since this interface
300  * is just for debugging anyway. The upper layer will send
301  * a SMSC success DLR if mask is set. Be aware that msg is
302  * destroyed in abstraction layer, that's why we use a copy
303  * afterwards to handle the final DLR.
304  */
305  bb_smscconn_sent(conn, msg, NULL);
306 
307  /* and now the final DLR */
308  if (DLR_IS_SUCCESS_OR_FAIL(copy->sms.dlr_mask)) {
309  Msg *dlrmsg;
310  Octstr *tmp;
311  int dlrstat = DLR_SUCCESS;
312  char id[UUID_STR_LEN + 1];
313 
314  uuid_unparse(copy->sms.id, id);
315  tmp = octstr_create(id);
316  dlrmsg = dlr_find(conn->id,
317  tmp, /* smsc message id */
318  copy->sms.receiver, /* destination */
319  dlrstat, 0);
320  if (dlrmsg != NULL) {
321  /* XXX TODO: Provide a SMPP DLR text in msgdata */
322  bb_smscconn_receive(conn, dlrmsg);
323  } else {
324  error(0,"smsc_fale: got DLR but could not find message or "
325  "was not interested in it");
326  }
327  octstr_destroy(tmp);
328  }
329  msg_destroy(copy);
330 
331  } else {
334  goto error;
335  }
336 
337  /* obey throughput speed limit, if any */
338  if (conn->throughput > 0) {
340  }
341  }
342  if (privdata->shutdown) {
343  debug("bb.sms", 0, "smsc_fake shutting down, closing client socket");
345  return;
346  }
347  conn_wait(client, -1);
348  if (conn_error(client))
349  goto error;
350  if (conn_eof(client))
351  goto eof;
352  }
353 error:
354  info(0, "IO error to fakesmsc client. Closing connection.");
356  return;
357 eof:
358  info(0, "EOF from fakesmsc client. Closing connection.");
360  return;
361 }
Octstr * conn_read_line(Connection *conn)
Definition: conn.c:1134
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
static int sms_to_client(Connection *client, Msg *msg)
Definition: smsc_fake.c:110
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:250
static void client(int port)
Definition: test_udp.c:77
List * outgoing_queue
Definition: smsc_cgw.c:153
static void msg_to_bb(SMSCConn *conn, Octstr *line)
Definition: smsc_fake.c:163
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
int conn_eof(Connection *conn)
Definition: conn.c:705
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
Definition: dlr.c:387
#define DLR_SUCCESS
Definition: dlr.h:72
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:477
void conn_destroy(Connection *conn)
Definition: conn.c:627
double throughput
Definition: smscconn_p.h:203
void msg_destroy(Msg *msg)
Definition: msg.c:132
static double delay
Definition: mtbatch.c:99
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
void gwthread_sleep(double seconds)
volatile sig_atomic_t is_stopped
Definition: smscconn_p.h:169
#define UUID_STR_LEN
Definition: gw_uuid.h:19
int shutdown
Definition: smsc_cgw.c:156
Definition: octstr.c:118
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:281
int conn_wait(Connection *conn, double seconds)
Definition: conn.c:904
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:329
int conn_error(Connection *conn)
Definition: conn.c:716
#define DLR_IS_SUCCESS_OR_FAIL(dlr)
Definition: dlr.h:85
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86

◆ msg_to_bb()

static void msg_to_bb ( SMSCConn conn,
Octstr line 
)
static

Definition at line 163 of file smsc_fake.c.

References bb_smscconn_receive(), DC_7BIT, DC_8BIT, DC_UCS2, DC_UNDEF, debug(), error(), smscconn::id, msg, msg_create, msg_destroy(), octstr_compare(), octstr_copy, octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_imm(), octstr_search_char(), octstr_url_decode(), type, and warning().

Referenced by main_connection_loop().

164 {
165  long p, p2;
166  Msg *msg;
167  Octstr *type = NULL; /* might be destroyed after error before created */
168 
169  msg = msg_create(sms);
170  p = octstr_search_char(line, ' ', 0);
171  if (p == -1)
172  goto error;
173  msg->sms.sender = octstr_copy(line, 0, p);
174  p2 = octstr_search_char(line, ' ', p + 1);
175  if (p2 == -1)
176  goto error;
177  msg->sms.receiver = octstr_copy(line, p + 1, p2 - p - 1);
178  p = octstr_search_char(line, ' ', p2 + 1);
179  if (p == -1)
180  goto error;
181  type = octstr_copy(line, p2 + 1, p - p2 - 1);
182  if (!octstr_compare(type, octstr_imm("text"))) {
183  msg->sms.msgdata = octstr_copy(line, p + 1, LONG_MAX);
184  msg->sms.coding = DC_7BIT;
185  }
186  else if (!octstr_compare(type, octstr_imm("data"))) {
187  msg->sms.msgdata = octstr_copy(line, p + 1, LONG_MAX);
188  msg->sms.coding = DC_8BIT;
189  if (octstr_url_decode(msg->sms.msgdata) == -1)
190  warning(0, "smsc_fake: url-encoded data from client looks malformed");
191  }
192  else if (!octstr_compare(type, octstr_imm("ucs2"))) {
193  msg->sms.msgdata = octstr_copy(line, p + 1, LONG_MAX);
194  msg->sms.coding = DC_UCS2;
195  if (octstr_url_decode(msg->sms.msgdata) == -1)
196  warning(0, "smsc_fake: url-encoded data from client looks malformed");
197  }
198  else if (!octstr_compare(type, octstr_imm("utf8"))) {
199  msg->sms.msgdata = octstr_copy(line, p + 1, LONG_MAX);
200  msg->sms.coding = DC_7BIT;
201  if (octstr_url_decode(msg->sms.msgdata) == -1)
202  warning(0, "smsc_fake: url-encoded data from client looks malformed");
203  }
204  else if (!octstr_compare(type, octstr_imm("route"))) {
205  p2 = octstr_search_char(line, ' ', p + 1);
206  if (p2 == -1)
207  goto error;
208  msg->sms.boxc_id = octstr_copy(line, p + 1, p2 - p - 1);
209  msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX);
210  }
211  else if (!octstr_compare(type, octstr_imm("udh-data")) || !octstr_compare(type, octstr_imm("udh"))) {
212  p2 = octstr_search_char(line, ' ', p + 1);
213  if (p2 == -1)
214  goto error;
215  msg->sms.udhdata = octstr_copy(line, p + 1, p2 - p - 1);
216  msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX);
217  if (msg->sms.coding == DC_UNDEF)
218  msg->sms.coding = DC_8BIT;
219  if (octstr_url_decode(msg->sms.msgdata) == -1 ||
220  octstr_url_decode(msg->sms.udhdata) == -1)
221  warning(0, "smsc_fake: url-encoded data from client looks malformed");
222  }
223  else if (!octstr_compare(type, octstr_imm("udh-text"))) {
224  p2 = octstr_search_char(line, ' ', p + 1);
225  if (p2 == -1)
226  goto error;
227  msg->sms.udhdata = octstr_copy(line, p + 1, p2 - p - 1);
228  msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX);
229  if (msg->sms.coding == DC_UNDEF)
230  msg->sms.coding = DC_7BIT;
231  if (octstr_url_decode(msg->sms.udhdata) == -1)
232  warning(0, "smsc_fake: url-encoded udh data from client looks malformed");
233  }
234  else if (!octstr_compare(type, octstr_imm("dlr-mask"))) {
235  Octstr *tmp;
236  p2 = octstr_search_char(line, ' ', p + 1);
237  if (p2 == -1)
238  goto error;
239  tmp = octstr_copy(line, p + 1, p2 - p - 1);
240  msg->sms.dlr_mask = atoi(octstr_get_cstr(tmp));
241  octstr_destroy(tmp);
242  msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX);
243  }
244  else
245  goto error;
246  octstr_destroy(line);
248  time(&msg->sms.time);
249  msg->sms.smsc_id = octstr_duplicate(conn->id);
250 
251  debug("bb.sms", 0, "smsc_fake: new message received");
252  /* msg_dump(msg, 0); */
253  bb_smscconn_receive(conn, msg);
254  return;
255 error:
256  warning(0, "smsc_fake: invalid message syntax from client, ignored");
257  msg_destroy(msg);
258  octstr_destroy(line);
260  return;
261 }
void error(int err, const char *fmt,...)
Definition: log.c:648
Octstr * id
Definition: smscconn_p.h:174
int octstr_url_decode(Octstr *ostr)
Definition: octstr.c:1746
int type
Definition: smsc_cimd2.c:215
#define DC_8BIT
Definition: sms.h:111
#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
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1012
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
Definition: msg.h:79
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:477
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void msg_destroy(Msg *msg)
Definition: msg.c:132
void warning(int err, const char *fmt,...)
Definition: log.c:660
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define DC_UNDEF
Definition: sms.h:109
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
#define DC_UCS2
Definition: sms.h:112
#define DC_7BIT
Definition: sms.h:110
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871

◆ queued_cb()

static long queued_cb ( SMSCConn conn)
static

Definition at line 526 of file smsc_fake.c.

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

Referenced by smsc_fake_create().

527 {
528  PrivData *privdata = conn->data;
529  long ret;
530 
531  ret = (privdata ? gwlist_len(privdata->outgoing_queue) : 0);
532 
533  /* use internal queue as load, maybe something else later */
534 
535  conn->load = ret;
536  return ret;
537 }
long gwlist_len(List *list)
Definition: list.c:166
void * data
Definition: smscconn_p.h:250
List * outgoing_queue
Definition: smsc_cgw.c:153
int load
Definition: smscconn_p.h:152

◆ shutdown_cb()

static int shutdown_cb ( SMSCConn conn,
int  finish_sending 
)
static

Definition at line 486 of file smsc_fake.c.

References bb_smscconn_send_failed(), privdata::connection_thread, smscconn::data, debug(), gwlist_extract_first(), gwthread_wakeup(), msg, privdata::outgoing_queue, privdata::shutdown, SMSCCONN_FAILED_SHUTDOWN, SMSCCONN_KILLED_SHUTDOWN, and smscconn::why_killed.

Referenced by smsc_fake_create().

487 {
488  PrivData *privdata = conn->data;
489 
490  debug("bb.sms", 0, "Shutting down SMSCConn FAKE, %s",
491  finish_sending ? "slow" : "instant");
492 
493  /*
494  * Documentation claims this would have been done by smscconn.c,
495  * but isn't when this code is being written.
496  */
498  privdata->shutdown = 1;
499  /*
500  * Separate from why_killed to avoid locking, as
501  * why_killed may be changed from outside?
502  */
503 
504  if (finish_sending == 0) {
505  Msg *msg;
506  while((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
508  }
509  }
510 
512  return 0;
513 }
void * data
Definition: smscconn_p.h:250
List * outgoing_queue
Definition: smsc_cgw.c:153
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
Definition: msg.h:79
void * gwlist_extract_first(List *list)
Definition: list.c:305
long connection_thread
Definition: smsc_fake.c:83
int shutdown
Definition: smsc_cgw.c:156
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void gwthread_wakeup(long thread)
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:329
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86

◆ sms_to_client()

static int sms_to_client ( Connection client,
Msg msg 
)
static

Definition at line 110 of file smsc_fake.c.

References client(), conn_write(), DC_8BIT, DC_UCS2, debug(), msg, octstr_append(), octstr_append_char(), octstr_destroy(), octstr_duplicate, octstr_imm(), octstr_len(), and octstr_url_encode().

Referenced by main_connection_loop().

111 {
112  Octstr *line;
113  Octstr *msgdata = NULL; /* NULL to allow octstr_destroy */
114 
115  debug("bb.sms", 0, "smsc_fake: sending message to client");
116  /* msg_dump(msg, 0); */
117 
118  line = octstr_duplicate(msg->sms.sender);
119  octstr_append_char(line, ' ');
120  octstr_append(line, msg->sms.receiver);
121  if (octstr_len(msg->sms.udhdata)) {
122  octstr_append(line, octstr_imm(" udh "));
123  msgdata = octstr_duplicate(msg->sms.udhdata);
124  octstr_url_encode(msgdata);
125  octstr_append(line, msgdata);
126  octstr_destroy(msgdata);
127  octstr_append(line, octstr_imm(" data "));
128  msgdata = octstr_duplicate(msg->sms.msgdata);
129  octstr_url_encode(msgdata);
130  octstr_append(line, msgdata);
131  } else {
132  if (msg->sms.coding == DC_8BIT) {
133  octstr_append(line, octstr_imm(" data "));
134  msgdata = octstr_duplicate(msg->sms.msgdata);
135  octstr_url_encode(msgdata);
136  octstr_append(line, msgdata);
137  }
138  else if (msg->sms.coding == DC_UCS2) {
139  octstr_append(line, octstr_imm(" ucs-2 "));
140  msgdata = octstr_duplicate(msg->sms.msgdata);
141  octstr_url_encode(msgdata);
142  octstr_append(line, msgdata);
143  }
144  else {
145  octstr_append(line, octstr_imm(" text "));
146  octstr_append(line, msg->sms.msgdata);
147  }
148  }
149 
150  octstr_append_char(line, 10);
151 
152  if (conn_write(client, line) == -1) {
153  octstr_destroy(msgdata);
154  octstr_destroy(line);
155  return -1;
156  }
157  octstr_destroy(msgdata);
158  octstr_destroy(line);
159  return 1;
160 }
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1504
static void client(int port)
Definition: test_udp.c:77
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1517
#define DC_8BIT
Definition: sms.h:111
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
int conn_write(Connection *conn, Octstr *data)
Definition: conn.c:1051
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void octstr_url_encode(Octstr *ostr)
Definition: octstr.c:1673
#define DC_UCS2
Definition: sms.h:112

◆ smsc_fake_create()

int smsc_fake_create ( SMSCConn conn,
CfgGroup cfg 
)

Definition at line 540 of file smsc_fake.c.

References add_msg_cb(), allow_ip, privdata::allow_ip, cfg, cfg_get, cfg_get_integer(), smscconn::connect_time, privdata::connection_thread, smscconn::data, deny_ip, privdata::deny_ip, error(), fake_listener(), fake_open_connection(), gwlist_create, gwlist_destroy(), gwthread_create, privdata::listening_socket, smscconn::name, octstr_create, octstr_destroy(), octstr_format(), octstr_imm(), privdata::outgoing_queue, privdata::port, smscconn::queued, queued_cb(), smscconn::send_msg, privdata::shutdown, smscconn::shutdown, shutdown_cb(), SMSCCONN_CONNECTING, SMSCCONN_DEAD, SMSCCONN_KILLED_CANNOT_CONNECT, start_cb(), smscconn::start_conn, smscconn::status, and smscconn::why_killed.

Referenced by smscconn_create().

541 {
542  PrivData *privdata = NULL;
544  long portno; /* has to be long because of cfg_get_integer */
545 
546  if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1)
547  portno = 0;
548  allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
549  if (allow_ip)
550  deny_ip = octstr_create("*.*.*.*");
551  else
552  deny_ip = NULL;
553 
554  if (portno == 0) {
555  error(0, "'port' invalid in 'fake' record.");
556  goto error;
557  }
558  privdata = gw_malloc(sizeof(PrivData));
560 
561  privdata->port = portno;
564 
565  if (fake_open_connection(conn, privdata) < 0) {
566  gw_free(privdata);
567  privdata = NULL;
568  goto error;
569  }
570 
571  conn->data = privdata;
572 
573  conn->name = octstr_format("FAKE:%d", privdata->port);
574 
576  privdata->shutdown = 0;
577 
578  conn->status = SMSCCONN_CONNECTING;
579  conn->connect_time = time(NULL);
580 
582  goto error;
583 
584  conn->shutdown = shutdown_cb;
585  conn->queued = queued_cb;
586  conn->start_conn = start_cb;
587  conn->send_msg = add_msg_cb;
588 
589  return 0;
590 
591 error:
592  error(0, "Failed to create fake smsc connection");
593  if (privdata != NULL) {
595  if (close(privdata->listening_socket == -1)) {
596  error(errno, "smsc_fake: closing listening socket port %d failed",
598  }
599  }
600  gw_free(privdata);
604  conn->status = SMSCCONN_DEAD;
605  return -1;
606 }
int port
Definition: smsc_cgw.c:159
Octstr * name
Definition: smscconn_p.h:173
void error(int err, const char *fmt,...)
Definition: log.c:648
void * data
Definition: smscconn_p.h:250
List * outgoing_queue
Definition: smsc_cgw.c:153
static void start_cb(SMSCConn *conn)
Definition: smsc_fake.c:516
#define cfg_get(grp, varname)
Definition: cfg.h:86
static Cfg * cfg
Definition: opensmppbox.c:95
void(* start_conn)(SMSCConn *conn)
Definition: smscconn_p.h:246
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
static void fake_listener(void *arg)
Definition: smsc_fake.c:364
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
static int shutdown_cb(SMSCConn *conn, int finish_sending)
Definition: smsc_fake.c:486
time_t connect_time
Definition: smscconn_p.h:155
static Octstr * deny_ip
Definition: bb_udp.c:112
Octstr * allow_ip
Definition: smsc_cgw.c:164
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
long connection_thread
Definition: smsc_fake.c:83
static Octstr * allow_ip
Definition: bb_udp.c:111
int shutdown
Definition: smsc_cgw.c:156
static int add_msg_cb(SMSCConn *conn, Msg *sms)
Definition: smsc_fake.c:457
Definition: octstr.c:118
int(* shutdown)(SMSCConn *conn, int finish_sending)
Definition: smscconn_p.h:230
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:742
smscconn_status_t status
Definition: smscconn_p.h:151
#define gwlist_create()
Definition: list.h:136
long(* queued)(SMSCConn *conn)
Definition: smscconn_p.h:241
int(* send_msg)(SMSCConn *conn, Msg *msg)
Definition: smscconn_p.h:236
int listening_socket
Definition: smsc_cgw.c:157
static int fake_open_connection(SMSCConn *conn, PrivData *privdata)
Definition: smsc_fake.c:91
Octstr * deny_ip
Definition: smsc_cgw.c:164
static long queued_cb(SMSCConn *conn)
Definition: smsc_fake.c:526
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ start_cb()

static void start_cb ( SMSCConn conn)
static

Definition at line 516 of file smsc_fake.c.

References privdata::connection_thread, smscconn::data, debug(), and gwthread_wakeup().

Referenced by smsc_fake_create().

517 {
518  PrivData *privdata = conn->data;
519 
520  /* in case there are messages in the buffer already */
522  debug("bb.sms", 0, "smsc_fake: start called");
523 }
void * data
Definition: smscconn_p.h:250
long connection_thread
Definition: smsc_fake.c:83
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void gwthread_wakeup(long thread)
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.