Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
smsc_fake.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 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  }
105  privdata->listening_socket = s;
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("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 }
256 
257 
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 }
356 
357 
358 static void fake_listener(void *arg)
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 }
449 
450 
451 static int add_msg_cb(SMSCConn *conn, Msg *sms)
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 }
478 
479 
480 static int shutdown_cb(SMSCConn *conn, int finish_sending)
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 }
508 
509 
510 static void start_cb(SMSCConn *conn)
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 }
518 
519 
520 static long queued_cb(SMSCConn *conn)
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 }
532 
533 
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
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
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:258
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:1502
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:249
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:1744
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82
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:510
#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:561
#define msg_create(type)
Definition: msg.h:136
Octstr * our_host
Definition: smscconn_p.h:192
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
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:245
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1010
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
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
void conn_claim(Connection *conn)
Definition: conn.c:663
#define DLR_SUCCESS
Definition: dlr.h:72
#define POLLIN
Definition: gwpoll.h:91
static void fake_listener(void *arg)
Definition: smsc_fake.c:358
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
int conn_write(Connection *conn, Octstr *data)
Definition: conn.c:1043
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
static int shutdown_cb(SMSCConn *conn, int finish_sending)
Definition: smsc_fake.c:480
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:624
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
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:451
int smsc_fake_create(SMSCConn *conn, CfgGroup *cfg)
Definition: smsc_fake.c:534
static Cfg * cfg
Definition: smsbox.c:115
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
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
int(* shutdown)(SMSCConn *conn, int finish_sending)
Definition: smscconn_p.h:229
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 cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
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:240
int(* send_msg)(SMSCConn *conn, Msg *msg)
Definition: smscconn_p.h:235
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
int conn_error(Connection *conn)
Definition: conn.c:708
#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
Octstr * deny_ip
Definition: smsc_cgw.c:164
static long queued_cb(SMSCConn *conn)
Definition: smsc_fake.c:520
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:1671
#define DC_UCS2
Definition: sms.h:112
Connection * conn_wrap_fd(int fd, int ssl)
Definition: conn.c:558
#define DC_7BIT
Definition: sms.h:110
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869
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.