Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
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

typedef struct privdata PrivData

Function Documentation

static int add_msg_cb ( SMSCConn conn,
Msg sms 
)
static

Definition at line 451 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().

452 {
453  PrivData *privdata = conn->data;
454  Msg *copy;
455 
456  copy = msg_duplicate(sms);
457 
458  /*
459  * Send DLR if desired, which means first add the DLR entry
460  * and then later find it and remove it. We need to ensure
461  * that we put the DLR in first before producing the copy
462  * to the list.
463  */
464  if (DLR_IS_ENABLED_DEVICE(sms->sms.dlr_mask)) {
465  Octstr *tmp;
466  char id[UUID_STR_LEN + 1];
467  uuid_unparse(sms->sms.id, id);
468  tmp = octstr_format("%s", id);
469  dlr_add(conn->id, tmp, sms, 0);
470  octstr_destroy(tmp);
471  }
472  gwlist_produce(privdata->outgoing_queue, copy);
473 
475 
476  return 0;
477 }
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:249
List * outgoing_queue
Definition: smsc_cgw.c:153
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:561
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:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
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)
static void fake_listener ( void *  arg)
static

Definition at line 358 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().

359 {
360  SMSCConn *conn = arg;
361  PrivData *privdata = conn->data;
362  struct sockaddr_in client_addr;
363  socklen_t client_addr_len;
364  Octstr *ip;
366  int s, ret;
367  Msg *msg;
368 
369  /* Make sure we log into our own log-file if defined */
370  log_thread_to(conn->log_idx);
371 
372  while (1) {
373  client_addr_len = sizeof(client_addr);
374  ret = gwthread_pollfd(privdata->listening_socket, POLLIN, -1);
375  if (ret == -1) {
376  if (errno == EINTR)
377  continue;
378  error(0, "Poll for fakesmsc connections failed, shutting down");
379  break;
380  }
381  if (privdata->shutdown)
382  break;
383  if (ret == 0)
384  /*
385  * This thread was woke up from elsewhere, but
386  * if we're not shutting down nothing to do here.
387  */
388  continue;
389  s = accept(privdata->listening_socket, (struct sockaddr *)&client_addr,
390  &client_addr_len);
391  if (s == -1) {
392  warning(errno, "fake_listener: accept() failed, retrying...");
393  continue;
394  }
395  ip = host_ip(client_addr);
396  if (!is_allowed_ip(privdata->allow_ip, privdata->deny_ip, ip)) {
397  info(0, "Fakesmsc connection tried from denied host <%s>, "
398  "disconnected", octstr_get_cstr(ip));
399  octstr_destroy(ip);
400  close(s);
401  continue;
402  }
403  client = conn_wrap_fd(s, 0);
404  if (client == NULL) {
405  error(0, "fake_listener: conn_wrap_fd failed on accept()ed fd");
406  octstr_destroy(ip);
407  close(s);
408  continue;
409  }
410  conn_claim(client);
411  info(0, "Fakesmsc client connected from %s", octstr_get_cstr(ip));
412  octstr_destroy(ip);
413  mutex_lock(conn->flow_mutex);
414  conn->status = SMSCCONN_ACTIVE;
415  conn->connect_time = time(NULL);
416  mutex_unlock(conn->flow_mutex);
417  bb_smscconn_connected(conn);
418 
419  main_connection_loop(conn, client);
420 
421  if (privdata->shutdown)
422  break;
423  mutex_lock(conn->flow_mutex);
425  mutex_unlock(conn->flow_mutex);
426  while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
428  }
429  }
430  if (close(privdata->listening_socket) == -1)
431  warning(errno, "smsc_fake: couldn't close listening socket at shutdown");
432  mutex_lock(conn->flow_mutex);
433 
434  conn->status = SMSCCONN_DEAD;
435 
436  while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
438  }
439  gwlist_destroy(privdata->outgoing_queue, NULL);
440  octstr_destroy(privdata->allow_ip);
441  octstr_destroy(privdata->deny_ip);
442  gw_free(privdata);
443  conn->data = NULL;
444 
445  mutex_unlock(conn->flow_mutex);
446  debug("bb.sms", 0, "smsc_fake connection has completed shutdown.");
448 }
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
void bb_smscconn_connected(SMSCConn *conn)
Definition: bb_smscconn.c:192
static void main_connection_loop(SMSCConn *conn, Connection *client)
Definition: smsc_fake.c:258
#define mutex_unlock(m)
Definition: thread.h:136
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
void * data
Definition: smscconn_p.h:249
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:723
int is_allowed_ip(Octstr *allow_ip, Octstr *deny_ip, Octstr *ip)
Definition: utils.c:815
void conn_claim(Connection *conn)
Definition: conn.c:663
#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:624
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
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:690
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:328
#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:558
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
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  }
105  privdata->listening_socket = s;
106  return 0;
107 }
int port
Definition: smsc_cgw.c:159
void error(int err, const char *fmt,...)
Definition: log.c:612
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
static void main_connection_loop ( SMSCConn conn,
Connection client 
)
static

Definition at line 258 of file smsc_fake.c.

References bb_smscconn_receive(), bb_smscconn_send_failed(), bb_smscconn_sent(), 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().

259 {
260  PrivData *privdata = conn->data;
261  Octstr *line;
262  Msg *msg;
263  double delay = 0;
264 
265  if (conn->throughput > 0) {
266  delay = 1.0 / conn->throughput;
267  }
268 
269  while (1) {
270  while (!conn->is_stopped && !privdata->shutdown &&
271  (line = conn_read_line(client)))
272  msg_to_bb(conn, line);
273  if (conn_error(client))
274  goto error;
275  if (conn_eof(client))
276  goto eof;
277 
278  /*
279  * We won't get DLRs from fakesmsc itself, due that we don't have
280  * corresponding message IDs etc. We threat the DLR receiving here. So
281  * DLR "originate" from the protocol layer towards abstraction layer.
282  * This is all for pure debugging and testing.
283  */
284 
285  while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
286 
287  /* pass msg to fakesmsc daemon */
288  if (sms_to_client(client, msg) == 1) {
289  Msg *copy = msg_duplicate(msg);
290 
291  /*
292  * Actually no guarantee of it having been really sent,
293  * but I suppose that doesn't matter since this interface
294  * is just for debugging anyway. The upper layer will send
295  * a SMSC success DLR if mask is set. Be aware that msg is
296  * destroyed in abstraction layer, that's why we use a copy
297  * afterwards to handle the final DLR.
298  */
299  bb_smscconn_sent(conn, msg, NULL);
300 
301  /* and now the final DLR */
302  if (DLR_IS_SUCCESS_OR_FAIL(copy->sms.dlr_mask)) {
303  Msg *dlrmsg;
304  Octstr *tmp;
305  int dlrstat = DLR_SUCCESS;
306  char id[UUID_STR_LEN + 1];
307 
308  uuid_unparse(copy->sms.id, id);
309  tmp = octstr_create(id);
310  dlrmsg = dlr_find(conn->id,
311  tmp, /* smsc message id */
312  copy->sms.receiver, /* destination */
313  dlrstat, 0);
314  if (dlrmsg != NULL) {
315  /* XXX TODO: Provide a SMPP DLR text in msgdata */
316  bb_smscconn_receive(conn, dlrmsg);
317  } else {
318  error(0,"smsc_fale: got DLR but could not find message or "
319  "was not interested in it");
320  }
321  octstr_destroy(tmp);
322  }
323  msg_destroy(copy);
324 
325  } else {
326  bb_smscconn_send_failed(conn, msg,
328  goto error;
329  }
330 
331  /* obey throughput speed limit, if any */
332  if (conn->throughput > 0) {
333  gwthread_sleep(delay);
334  }
335  }
336  if (privdata->shutdown) {
337  debug("bb.sms", 0, "smsc_fake shutting down, closing client socket");
338  conn_destroy(client);
339  return;
340  }
341  conn_wait(client, -1);
342  if (conn_error(client))
343  goto error;
344  if (conn_eof(client))
345  goto eof;
346  }
347 error:
348  info(0, "IO error to fakesmsc client. Closing connection.");
349  conn_destroy(client);
350  return;
351 eof:
352  info(0, "EOF from fakesmsc client. Closing connection.");
353  conn_destroy(client);
354  return;
355 }
Octstr * conn_read_line(Connection *conn)
Definition: conn.c:1126
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
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:249
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:561
int conn_eof(Connection *conn)
Definition: conn.c:697
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:478
void conn_destroy(Connection *conn)
Definition: conn.c:619
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:322
#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:279
int conn_wait(Connection *conn, double seconds)
Definition: conn.c:896
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:328
int conn_error(Connection *conn)
Definition: conn.c:708
#define DLR_IS_SUCCESS_OR_FAIL(dlr)
Definition: dlr.h:85
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
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("route"))) {
199  p2 = octstr_search_char(line, ' ', p + 1);
200  if (p2 == -1)
201  goto error;
202  msg->sms.boxc_id = octstr_copy(line, p + 1, p2 - p - 1);
203  msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX);
204  }
205  else if (!octstr_compare(type, octstr_imm("udh-data")) || !octstr_compare(type, octstr_imm("udh"))) {
206  p2 = octstr_search_char(line, ' ', p + 1);
207  if (p2 == -1)
208  goto error;
209  msg->sms.udhdata = octstr_copy(line, p + 1, p2 - p - 1);
210  msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX);
211  if (msg->sms.coding == DC_UNDEF)
212  msg->sms.coding = DC_8BIT;
213  if (octstr_url_decode(msg->sms.msgdata) == -1 ||
214  octstr_url_decode(msg->sms.udhdata) == -1)
215  warning(0, "smsc_fake: url-encoded data from client looks malformed");
216  }
217  else if (!octstr_compare(type, octstr_imm("udh-text"))) {
218  p2 = octstr_search_char(line, ' ', p + 1);
219  if (p2 == -1)
220  goto error;
221  msg->sms.udhdata = octstr_copy(line, p + 1, p2 - p - 1);
222  msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX);
223  if (msg->sms.coding == DC_UNDEF)
224  msg->sms.coding = DC_7BIT;
225  if (octstr_url_decode(msg->sms.udhdata) == -1)
226  warning(0, "smsc_fake: url-encoded udh data from client looks malformed");
227  }
228  else if (!octstr_compare(type, octstr_imm("dlr-mask"))) {
229  Octstr *tmp;
230  p2 = octstr_search_char(line, ' ', p + 1);
231  if (p2 == -1)
232  goto error;
233  tmp = octstr_copy(line, p + 1, p2 - p - 1);
234  msg->sms.dlr_mask = atoi(octstr_get_cstr(tmp));
235  octstr_destroy(tmp);
236  msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX);
237  }
238  else
239  goto error;
240  octstr_destroy(line);
241  octstr_destroy(type);
242  time(&msg->sms.time);
243  msg->sms.smsc_id = octstr_duplicate(conn->id);
244 
245  debug("bb.sms", 0, "smsc_fake: new message received");
246  /* msg_dump(msg, 0); */
247  bb_smscconn_receive(conn, msg);
248  return;
249 error:
250  warning(0, "smsc_fake: invalid message syntax from client, ignored");
251  msg_destroy(msg);
252  octstr_destroy(line);
253  octstr_destroy(type);
254  return;
255 }
void error(int err, const char *fmt,...)
Definition: log.c:612
Octstr * id
Definition: smscconn_p.h:174
int octstr_url_decode(Octstr *ostr)
Definition: octstr.c:1744
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:1010
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Definition: msg.h:79
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:478
#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:624
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
#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:869
static long queued_cb ( SMSCConn conn)
static

Definition at line 520 of file smsc_fake.c.

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

Referenced by smsc_fake_create().

521 {
522  PrivData *privdata = conn->data;
523  long ret;
524 
525  ret = (privdata ? gwlist_len(privdata->outgoing_queue) : 0);
526 
527  /* use internal queue as load, maybe something else later */
528 
529  conn->load = ret;
530  return ret;
531 }
long gwlist_len(List *list)
Definition: list.c:166
void * data
Definition: smscconn_p.h:249
List * outgoing_queue
Definition: smsc_cgw.c:153
int load
Definition: smscconn_p.h:152
static int shutdown_cb ( SMSCConn conn,
int  finish_sending 
)
static

Definition at line 480 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().

481 {
482  PrivData *privdata = conn->data;
483 
484  debug("bb.sms", 0, "Shutting down SMSCConn FAKE, %s",
485  finish_sending ? "slow" : "instant");
486 
487  /*
488  * Documentation claims this would have been done by smscconn.c,
489  * but isn't when this code is being written.
490  */
492  privdata->shutdown = 1;
493  /*
494  * Separate from why_killed to avoid locking, as
495  * why_killed may be changed from outside?
496  */
497 
498  if (finish_sending == 0) {
499  Msg *msg;
500  while((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
502  }
503  }
504 
506  return 0;
507 }
void * data
Definition: smscconn_p.h:249
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:690
void gwthread_wakeup(long thread)
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 int sms_to_client ( Connection client,
Msg msg 
)
static

Definition at line 110 of file smsc_fake.c.

References conn_write(), DC_8BIT, DC_UCS2, debug(), 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:1502
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
#define DC_8BIT
Definition: sms.h:111
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
int conn_write(Connection *conn, Octstr *data)
Definition: conn.c:1043
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
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
void octstr_url_encode(Octstr *ostr)
Definition: octstr.c:1671
#define DC_UCS2
Definition: sms.h:112
int smsc_fake_create ( SMSCConn conn,
CfgGroup cfg 
)

Definition at line 534 of file smsc_fake.c.

References add_msg_cb(), allow_ip, privdata::allow_ip, 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().

535 {
536  PrivData *privdata = NULL;
538  long portno; /* has to be long because of cfg_get_integer */
539 
540  if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1)
541  portno = 0;
542  allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
543  if (allow_ip)
544  deny_ip = octstr_create("*.*.*.*");
545  else
546  deny_ip = NULL;
547 
548  if (portno == 0) {
549  error(0, "'port' invalid in 'fake' record.");
550  goto error;
551  }
552  privdata = gw_malloc(sizeof(PrivData));
553  privdata->listening_socket = -1;
554 
555  privdata->port = portno;
556  privdata->allow_ip = allow_ip;
557  privdata->deny_ip = deny_ip;
558 
559  if (fake_open_connection(conn, privdata) < 0) {
560  gw_free(privdata);
561  privdata = NULL;
562  goto error;
563  }
564 
565  conn->data = privdata;
566 
567  conn->name = octstr_format("FAKE:%d", privdata->port);
568 
569  privdata->outgoing_queue = gwlist_create();
570  privdata->shutdown = 0;
571 
572  conn->status = SMSCCONN_CONNECTING;
573  conn->connect_time = time(NULL);
574 
575  if ((privdata->connection_thread = gwthread_create(fake_listener, conn)) == -1)
576  goto error;
577 
578  conn->shutdown = shutdown_cb;
579  conn->queued = queued_cb;
580  conn->start_conn = start_cb;
581  conn->send_msg = add_msg_cb;
582 
583  return 0;
584 
585 error:
586  error(0, "Failed to create fake smsc connection");
587  if (privdata != NULL) {
588  gwlist_destroy(privdata->outgoing_queue, NULL);
589  if (close(privdata->listening_socket == -1)) {
590  error(errno, "smsc_fake: closing listening socket port %d failed",
591  privdata->listening_socket);
592  }
593  }
594  gw_free(privdata);
595  octstr_destroy(allow_ip);
596  octstr_destroy(deny_ip);
598  conn->status = SMSCCONN_DEAD;
599  return -1;
600 }
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
void * data
Definition: smscconn_p.h:249
List * outgoing_queue
Definition: smsc_cgw.c:153
static void start_cb(SMSCConn *conn)
Definition: smsc_fake.c:510
#define cfg_get(grp, varname)
Definition: cfg.h:86
void(* start_conn)(SMSCConn *conn)
Definition: smscconn_p.h:245
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
static void fake_listener(void *arg)
Definition: smsc_fake.c:358
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
static int shutdown_cb(SMSCConn *conn, int finish_sending)
Definition: smsc_fake.c:480
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:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#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:451
Definition: octstr.c:118
int(* shutdown)(SMSCConn *conn, int finish_sending)
Definition: smscconn_p.h:229
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
smscconn_status_t status
Definition: smscconn_p.h:151
#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
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:520
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
static void start_cb ( SMSCConn conn)
static

Definition at line 510 of file smsc_fake.c.

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

Referenced by smsc_fake_create().

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