Kannel: Open Source WAP and SMS gateway  svn-r5335
smsc_fake.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * smsc_fake.c - interface to fakesmsc.c
59  *
60  * Uoti Urpala 2001
61  */
62 
63 /* Doesn't support multi-send
64  * Doesn't warn about unrecognized configuration variables */
65 
66 #include <sys/types.h>
67 #include <sys/socket.h>
68 #include <unistd.h>
69 #include <errno.h>
70 #include <time.h>
71 #include <limits.h>
72 
73 #include "gwlib/gwlib.h"
74 #include "smscconn.h"
75 #include "smscconn_p.h"
76 #include "bb_smscconn_cb.h"
77 #include "msg.h"
78 #include "sms.h"
79 #include "dlr.h"
80 
81 typedef struct privdata {
84  int shutdown; /* Signal to the connection thread to shut down */
85  int listening_socket; /* File descriptor */
86  int port; /* Port number to listen */
88 } PrivData;
89 
90 
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 }
108 
109 
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 }
161 
162 
163 static void msg_to_bb(SMSCConn *conn, Octstr *line)
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 }
262 
263 
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 }
362 
363 
364 static void fake_listener(void *arg)
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 }
455 
456 
457 static int add_msg_cb(SMSCConn *conn, Msg *sms)
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 }
484 
485 
486 static int shutdown_cb(SMSCConn *conn, int finish_sending)
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 }
514 
515 
516 static void start_cb(SMSCConn *conn)
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 }
524 
525 
526 static long queued_cb(SMSCConn *conn)
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 }
538 
539 
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
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
void bb_smscconn_connected(SMSCConn *conn)
Definition: bb_smscconn.c:192
int socket_set_blocking(int fd, int blocking)
Definition: socket.c:368
struct privdata PrivData
static void main_connection_loop(SMSCConn *conn, Connection *client)
Definition: smsc_fake.c:264
static int sms_to_client(Connection *client, Msg *msg)
Definition: smsc_fake.c:110
#define mutex_unlock(m)
Definition: thread.h:136
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1504
void gwlist_produce(List *list, void *item)
Definition: list.c:411
Octstr * id
Definition: smscconn_p.h:174
long gwlist_len(List *list)
Definition: list.c:166
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 octstr_url_decode(Octstr *ostr)
Definition: octstr.c:1746
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1517
int log_idx
Definition: smscconn_p.h:197
int type
Definition: smsc_cimd2.c:215
static void msg_to_bb(SMSCConn *conn, Octstr *line)
Definition: smsc_fake.c:163
static void start_cb(SMSCConn *conn)
Definition: smsc_fake.c:516
#define cfg_get(grp, varname)
Definition: cfg.h:86
#define DC_8BIT
Definition: sms.h:111
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
#define msg_create(type)
Definition: msg.h:136
Octstr * our_host
Definition: smscconn_p.h:192
static Cfg * cfg
Definition: opensmppbox.c:95
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
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
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
void(* start_conn)(SMSCConn *conn)
Definition: smscconn_p.h:246
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1012
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
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
void conn_claim(Connection *conn)
Definition: conn.c:671
#define DLR_SUCCESS
Definition: dlr.h:72
#define POLLIN
Definition: gwpoll.h:91
static void fake_listener(void *arg)
Definition: smsc_fake.c:364
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
int conn_write(Connection *conn, Octstr *data)
Definition: conn.c:1051
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
static int shutdown_cb(SMSCConn *conn, int finish_sending)
Definition: smsc_fake.c:486
time_t connect_time
Definition: smscconn_p.h:155
#define octstr_duplicate(ostr)
Definition: octstr.h:187
double throughput
Definition: smscconn_p.h:203
static Octstr * deny_ip
Definition: bb_udp.c:112
Mutex * flow_mutex
Definition: smscconn_p.h:157
void msg_destroy(Msg *msg)
Definition: msg.c:132
Octstr * allow_ip
Definition: smsc_cgw.c:164
static double delay
Definition: mtbatch.c:99
int make_server_socket(int port, const char *interface_name)
Definition: socket.c:93
void warning(int err, const char *fmt,...)
Definition: log.c:660
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
void gwthread_sleep(double seconds)
long connection_thread
Definition: smsc_fake.c:83
volatile sig_atomic_t is_stopped
Definition: smscconn_p.h:169
static Octstr * allow_ip
Definition: bb_udp.c:111
#define UUID_STR_LEN
Definition: gw_uuid.h:19
int gwthread_pollfd(int fd, int events, double timeout)
int shutdown
Definition: smsc_cgw.c:156
static int add_msg_cb(SMSCConn *conn, Msg *sms)
Definition: smsc_fake.c:457
int smsc_fake_create(SMSCConn *conn, CfgGroup *cfg)
Definition: smsc_fake.c:540
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
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
int(* shutdown)(SMSCConn *conn, int finish_sending)
Definition: smscconn_p.h:230
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 cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:742
void gwthread_wakeup(long thread)
Definition: cfg.c:73
int socklen_t
Definition: socket.h:73
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
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 DC_UNDEF
Definition: sms.h:109
static int fake_open_connection(SMSCConn *conn, PrivData *privdata)
Definition: smsc_fake.c:91
#define mutex_lock(m)
Definition: thread.h:130
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82
Octstr * deny_ip
Definition: smsc_cgw.c:164
static long queued_cb(SMSCConn *conn)
Definition: smsc_fake.c:526
Definition: list.c:102
#define DLR_IS_SUCCESS_OR_FAIL(dlr)
Definition: dlr.h:85
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
Connection * conn_wrap_fd(int fd, int ssl)
Definition: conn.c:566
#define DC_7BIT
Definition: sms.h:110
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
int load
Definition: smscconn_p.h:152
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.