Kannel: Open Source WAP and SMS gateway  svn-r5335
drive_smpp.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  * drive_smpp.c - SMPP server for testing purposes
59  *
60  * Lars Wirzenius
61  */
62 
63 
64 #include <errno.h>
65 #include <signal.h>
66 #include <sys/types.h>
67 #include <sys/socket.h>
68 
69 #include "gwlib/gwlib.h"
70 #include "gw/smsc/smpp_pdu.h"
71 #include "gw/msg.h"
72 
73 
74 static int quitting = 0;
79 static int port_for_smsbox;
81 static long max_to_esme;
85 static time_t start_time = (time_t) -1;
86 static time_t first_to_esme = (time_t) -1;
87 static time_t last_to_esme = (time_t) -1;
88 static time_t last_from_esme = (time_t) -1;
89 static time_t first_from_bb = (time_t) -1;
90 static time_t last_to_bb = (time_t) -1;
91 static long enquire_interval = 1; /* Measured in messages, not time. */
92 
93 
94 static void quit(void)
95 {
96  quitting = 1;
98 }
99 
100 
101 typedef struct {
104  int receiver;
105  long version;
106 } ESME;
107 
108 
110 {
111  ESME *esme;
112 
113  esme = gw_malloc(sizeof(*esme));
114  esme->conn = conn;
115  esme->transmitter = 0;
116  esme->receiver = 0;
117  esme->version = 0;
118  return esme;
119 }
120 
121 
122 static void esme_destroy(ESME *esme)
123 {
124  if (esme != NULL) {
125  conn_destroy(esme->conn);
126  gw_free(esme);
127  }
128 }
129 
130 
132 {
133  SMPP_PDU *resp;
134 
135  esme->transmitter = 1;
136  esme->version = pdu->u.bind_transmitter.interface_version;
137  resp = smpp_pdu_create(bind_transmitter_resp,
138  pdu->u.bind_transmitter.sequence_number);
139 #if 0 /* XXX system_id is not implemented in the PDU at the moment */
140  resp->u.bind_transmitter_resp.system_id =
142 #endif
143  return resp;
144 }
145 
146 
148 {
149  SMPP_PDU *resp;
150 
151  esme->receiver = 1;
152  esme->version = pdu->u.bind_receiver.interface_version;
153  resp = smpp_pdu_create(bind_receiver_resp,
154  pdu->u.bind_receiver.sequence_number);
155 #if 0 /* XXX system_id is not implemented in the PDU at the moment */
156  resp->u.bind_receiver_resp.system_id = octstr_duplicate(smsc_system_id);
157 #endif
158  return resp;
159 }
160 
161 
163 {
164  SMPP_PDU *resp;
165  unsigned long id;
166 
167  debug("test.smpp", 0, "submit_sm: short_message = <%s>",
168  octstr_get_cstr(pdu->u.submit_sm.short_message));
170  if (id == max_to_esme)
171  info(0, "ESME has submitted all messages to SMSC.");
172  time(&last_from_esme);
173 
174  resp = smpp_pdu_create(submit_sm_resp, pdu->u.submit_sm.sequence_number);
175 #if 0 /* XXX message_id is not implemented in the PDU at the moment */
176  resp->u.submit_sm_resp.message_id =
178 #endif
179  return resp;
180 }
181 
182 
184 {
185  return NULL;
186 }
187 
188 
189 static SMPP_PDU *handle_unbind(ESME *esme, SMPP_PDU *pdu)
190 {
191  SMPP_PDU *resp;
192 
193  resp = smpp_pdu_create(unbind_resp, pdu->u.unbind.sequence_number);
194  return resp;
195 }
196 
197 
199 {
200  return smpp_pdu_create(enquire_link_resp,
201  pdu->u.enquire_link.sequence_number);
202 }
203 
204 
206 {
207  return NULL;
208 }
209 
210 
211 static struct {
212  unsigned long type;
213  SMPP_PDU *(*handler)(ESME *, SMPP_PDU *);
214 } handlers[] = {
215  #define HANDLER(name) { name, handle_ ## name },
216  HANDLER(bind_transmitter)
217  HANDLER(bind_receiver)
218  HANDLER(submit_sm)
219  HANDLER(deliver_sm_resp)
220  HANDLER(unbind)
221  HANDLER(enquire_link)
222  HANDLER(enquire_link_resp)
223  #undef HANDLER
224 };
225 static int num_handlers = sizeof(handlers) / sizeof(handlers[0]);
226 
227 
228 static void handle_pdu(ESME *esme, SMPP_PDU *pdu)
229 {
230  SMPP_PDU *resp;
231  Octstr *os;
232  int i;
233 
234  debug("test.smpp", 0, "Handling SMPP PDU of type %s", pdu->type_name);
235  for (i = 0; i < num_handlers; ++i) {
236  if (handlers[i].type == pdu->type) {
237  resp = handlers[i].handler(esme, pdu);
238  if (resp != NULL) {
239  os = smpp_pdu_pack(NULL, resp);
240  conn_write(esme->conn, os);
241  octstr_destroy(os);
242  smpp_pdu_destroy(resp);
243  }
244  return;
245  }
246  }
247 
248  error(0, "Unhandled SMPP PDU.");
249  smpp_pdu_dump(octstr_imm(""), pdu);
250 }
251 
252 
253 static void send_smpp_thread(void *arg)
254 {
255  ESME *esme;
256  Octstr *os;
257  SMPP_PDU *pdu;
258  unsigned long id;
259 
260  esme = arg;
261 
262  id = 0;
264  id = counter_increase(num_to_esme) + 1;
265  while (!quitting && counter_value(num_from_esme) + 500 < id)
266  gwthread_sleep(1.0);
267  if (quitting)
268  break;
270  pdu->u.deliver_sm.source_addr = octstr_create("456");
271  pdu->u.deliver_sm.destination_addr = octstr_create("123");
272  pdu->u.deliver_sm.short_message = octstr_format("%ld", id);
273  if (esme->version > 0x33)
274  pdu->u.deliver_sm.receipted_message_id = octstr_create("receipted_message_id\0");
275  os = smpp_pdu_pack(NULL, pdu);
276  conn_write(esme->conn, os);
277  octstr_destroy(os);
278  smpp_pdu_destroy(pdu);
279  if (first_to_esme == (time_t) -1)
280  time(&first_to_esme);
281  debug("test.smpp", 0, "Delivered SMS %ld of %ld to bearerbox via SMPP.",
282  id, max_to_esme);
283 
284  if ((id % enquire_interval) == 0) {
286  os = smpp_pdu_pack(NULL, pdu);
287  conn_write(esme->conn, os);
288  octstr_destroy(os);
289  smpp_pdu_destroy(pdu);
290  debug("test.smpp", 0, "Sent enquire_link to bearerbox.");
291  }
292  }
293  time(&last_to_esme);
294  if (id == max_to_esme)
295  info(0, "All messages sent to ESME.");
296  debug("test.smpp", 0, "%s terminates.", __func__);
297 }
298 
299 
300 static void receive_smpp_thread(void *arg)
301 {
302  ESME *esme;
303  Octstr *os;
304  long len;
305  long sender_id;
306  SMPP_PDU *pdu;
307 
308  esme = arg;
309 
310  sender_id = -1;
311  len = 0;
312  while (!quitting && conn_wait(esme->conn, -1.0) != -1) {
313  for (;;) {
314  if (len == 0) {
315  len = smpp_pdu_read_len(esme->conn);
316  if (len == -1) {
317  error(0, "Client sent garbage, closing connection.");
318  goto error;
319  } else if (len == 0) {
320  if (conn_eof(esme->conn) || conn_error(esme->conn))
321  goto error;
322  break;
323  }
324  }
325 
326  gw_assert(len > 0);
327  os = smpp_pdu_read_data(esme->conn, len);
328  if (os != NULL) {
329  len = 0;
330  pdu = smpp_pdu_unpack(NULL, os);
331  if (pdu == NULL) {
332  error(0, "PDU unpacking failed!");
333  octstr_dump(os, 0);
334  } else {
335  handle_pdu(esme, pdu);
336  smpp_pdu_destroy(pdu);
337  }
338  octstr_destroy(os);
339  } else if (conn_eof(esme->conn) || conn_error(esme->conn))
340  goto error;
341  else
342  break;
343  }
344 
345  if (!quitting && esme->receiver && sender_id == -1)
346  sender_id = gwthread_create(send_smpp_thread, esme);
347  }
348 
349 error:
350  if (sender_id != -1) {
351  quit();
352  gwthread_join(sender_id);
353  }
354  esme_destroy(esme);
355  quit();
356  debug("test.smpp", 0, "%s terminates.", __func__);
357 }
358 
359 
360 static void smsbox_thread(void *arg)
361 {
362  Connection *conn;
363  Msg *msg;
364  Octstr *os;
365  Octstr *reply_msg;
366  unsigned long count;
367 
368  msg = msg_create(sms);
369  msg->sms.sender = octstr_create("123");
370  msg->sms.receiver = octstr_create("456");
371  msg->sms.msgdata = octstr_create("hello world");
372  reply_msg = msg_pack(msg);
373  msg_destroy(msg);
374 
375  gwthread_sleep(1.0);
377  if (conn == NULL) {
378  gwthread_sleep(2.0);
380  if (conn == NULL)
381  panic(0, "Couldn't connect to bearerbox as smsbox");
382  }
383 
384  while (!quitting && conn_wait(conn, -1.0) != -1) {
385  for (;;) {
386  os = conn_read_withlen(conn);
387  if (os == NULL) {
388  if (conn_eof(conn) || conn_error(conn))
389  goto error;
390  break;
391  }
392 
393  msg = msg_unpack(os);
394  if (msg == NULL || msg->type == wdp_datagram)
395  error(0, "Bearerbox sent garbage to smsbox");
396 
397  if (msg->type == sms) {
398  if (first_from_bb == (time_t) -1)
399  time(&first_from_bb);
401  debug("test.smpp", 0,
402  "Bearerbox sent sms #%ld <%s> to smsbox, sending reply.",
403  count, octstr_get_cstr(msg->sms.msgdata));
404  if (count == max_to_esme)
405  info(0, "Bearerbox has sent all messages to smsbox.");
406  conn_write_withlen(conn, reply_msg);
408  }
409  msg_destroy(msg);
410  octstr_destroy(os);
411  time(&last_to_bb);
412  }
413  }
414 
415 error:
416  conn_destroy(conn);
417  octstr_destroy(reply_msg);
418  debug("test.smpp", 0, "%s terminates.", __func__);
419 }
420 
421 
422 static void accept_thread(void *arg)
423 {
424  int fd;
425  int new_fd;
426  int port;
427  socklen_t addrlen;
428  struct sockaddr addr;
429  long smsbox_thread_id;
430 
431  port = *(int *) arg;
432  fd = make_server_socket(port, NULL);
433  if (fd == -1)
434  panic(0, "Couldn't create SMPP listen port.");
435 
436  smsbox_thread_id = -1;
437  for (;;) {
438  if (gwthread_pollfd(fd, POLLIN, -1.0) != POLLIN)
439  break;
440  addrlen = sizeof(addr);
441  new_fd = accept(fd, &addr, &addrlen);
442  if (start_time == (time_t) -1)
443  time(&start_time);
445  esme_create(conn_wrap_fd(new_fd, 0)));
446  if (smsbox_thread_id == -1)
447  smsbox_thread_id = gwthread_create(smsbox_thread, NULL);
448  }
449 
450  debug("test.smpp", 0, "%s terminates.", __func__);
451 }
452 
453 
454 static void handler(int signal)
455 {
456  panic(0, "Caught signal %d.", signal);
457 }
458 
459 
460 static void help(void)
461 {
462  info(0, "drive_smpp [-h] [-v level][-l logfile][-p port][-m msgs][-c config]");
463 }
464 
465 
466 int main(int argc, char **argv)
467 {
468  struct sigaction act;
469  int port;
470  int opt;
471  double run_time;
472  char *log_file;
473  char *config_file;
474 
475  gwlib_init();
476 
477  act.sa_handler = handler;
478  sigemptyset(&act.sa_mask);
479  act.sa_flags = 0;
480  sigaction(SIGTERM, &act, NULL);
481  sigaction(SIGINT, &act, NULL);
482 
483  port = 2345;
484  smsc_system_id = octstr_create("kannel_smpp");
485  smsc_source_addr = octstr_create("123456");
487  bearerbox_host = octstr_create("127.0.0.1");
488  port_for_smsbox = 13001;
489  max_to_esme = 1;
494  log_file = config_file = NULL;
495 
496  while ((opt = getopt(argc, argv, "hv:p:m:l:c:")) != EOF) {
497  switch (opt) {
498  case 'v':
500  break;
501 
502  case 'h':
503  help();
504  exit(0);
505 
506  case 'm':
507  max_to_esme = atoi(optarg);
508  break;
509 
510  case 'p':
511  port = atoi(optarg);
512  break;
513 
514  case 'l':
515  log_file = optarg;
516  break;
517 
518  case 'c':
519  config_file = optarg;
520  break;
521 
522  case '?':
523  default:
524  error(0, "Invalid option %c", opt);
525  help();
526  panic(0, "Stopping.");
527  }
528  }
529 
530  if (log_file != NULL)
531  log_open(log_file, GW_DEBUG, GW_NON_EXCL);
532 
533  if (config_file != NULL) {
534  Cfg *cfg;
535  Octstr *tmp = octstr_create(config_file);
536 
537  cfg = cfg_create(tmp);
538  octstr_destroy(tmp);
539  if (cfg_read(cfg) == -1)
540  panic(0, "Errors in config file.");
542  cfg_destroy(cfg);
543  }
544 
545  info(0, "Starting drive_smpp test.");
548  debug("test.smpp", 0, "Program exiting normally.");
549 
550  run_time = difftime(last_from_esme, first_to_esme);
551 
552  info(0, "Number of messages sent to ESME: %ld",
554  info(0, "Number of messages sent to smsbox: %ld",
556  info(0, "Number of messages sent to bearerbox: %ld",
558  info(0, "Number of messages sent to SMSC: %ld",
560  info(0, "Time: %.0f secs", run_time);
561  info(0, "Time until all sent to ESME: %.0f secs",
562  difftime(last_to_esme, start_time));
563  info(0, "Time from first from bb to last to bb: %.0f secs",
564  difftime(last_to_bb, first_from_bb));
565  info(0, "Time until all sent to SMSC: %.0f secs",
566  difftime(last_from_esme, start_time));
567  info(0, "SMPP messages SMSC to ESME: %.1f msgs/sec",
568  counter_value(num_to_esme) / run_time);
569  info(0, "SMPP messages ESME to SMSC: %.1f msgs/sec",
570  counter_value(num_from_esme) / run_time);
571 
580 
581  gwlib_shutdown();
582  return 0;
583 }
void smpp_pdu_destroy(SMPP_PDU *pdu)
Definition: smpp_pdu.c:434
static SMPP_PDU * handle_bind_transmitter(ESME *esme, SMPP_PDU *pdu)
Definition: drive_smpp.c:131
static void quit(void)
Definition: drive_smpp.c:94
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
static time_t start_time
Definition: drive_smpp.c:85
static long max_to_esme
Definition: drive_smpp.c:81
void gwthread_join_all(void)
Definition: http.c:2014
Connection * conn_open_tcp(Octstr *host, int port, Octstr *our_host)
Definition: conn.c:496
static time_t last_to_bb
Definition: drive_smpp.c:90
static Octstr * smsc_source_addr
Definition: drive_smpp.c:76
static int port_for_smsbox
Definition: drive_smpp.c:79
#define HANDLER(name)
#define msg_unpack(os)
Definition: msg.h:183
int main(int argc, char **argv)
Definition: drive_smpp.c:466
gw_assert(wtls_machine->packet_to_send !=NULL)
void counter_destroy(Counter *counter)
Definition: counter.c:110
static struct @73 handlers[]
static int quitting
Definition: drive_smpp.c:74
void gwthread_join(long thread)
static SMPP_PDU * handle_enquire_link(ESME *esme, SMPP_PDU *pdu)
Definition: drive_smpp.c:198
static Counter * num_from_esme
Definition: drive_smpp.c:84
const char * type_name
Definition: smpp_pdu.h:92
static Octstr * smsc_system_id
Definition: drive_smpp.c:75
static int num_handlers
Definition: drive_smpp.c:225
unsigned long type
Definition: smpp_pdu.h:91
static void smsbox_thread(void *arg)
Definition: drive_smpp.c:360
long smpp_pdu_read_len(Connection *conn)
Definition: smpp_pdu.c:869
static time_t first_from_bb
Definition: drive_smpp.c:89
#define msg_create(type)
Definition: msg.h:136
static Counter * num_from_bearerbox
Definition: drive_smpp.c:82
static Cfg * cfg
Definition: opensmppbox.c:95
int conn_eof(Connection *conn)
Definition: conn.c:705
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static SMPP_PDU * handle_bind_receiver(ESME *esme, SMPP_PDU *pdu)
Definition: drive_smpp.c:147
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
Cfg * cfg_create(Octstr *filename)
Definition: cfg.c:318
long version
Definition: drive_smpp.c:105
int cfg_read(Cfg *cfg)
Definition: cfg.c:452
static int port
Definition: fakesmsc.c:121
int getopt(int argc, char **argv, char *opts)
Definition: attgetopt.c:84
#define POLLIN
Definition: gwpoll.h:91
static SMPP_PDU * handle_submit_sm(ESME *esme, SMPP_PDU *pdu)
Definition: drive_smpp.c:162
static SMPP_PDU * handle_enquire_link_resp(ESME *esme, SMPP_PDU *pdu)
Definition: drive_smpp.c:205
static void receive_smpp_thread(void *arg)
Definition: drive_smpp.c:300
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
Definition: cfg.c:164
static long enquire_interval
Definition: drive_smpp.c:91
Counter * counter_create(void)
Definition: counter.c:94
void cfg_destroy(Cfg *cfg)
Definition: cfg.c:331
void log_set_output_level(enum output_level level)
Definition: log.c:253
int receiver
Definition: drive_smpp.c:104
int transmitter
Definition: drive_smpp.c:103
void conn_destroy(Connection *conn)
Definition: conn.c:627
static Counter * num_to_bearerbox
Definition: drive_smpp.c:83
Definition: log.h:69
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
Octstr * smpp_pdu_pack(Octstr *smsc_id, SMPP_PDU *pdu)
Definition: smpp_pdu.c:458
static Counter * num_to_esme
Definition: drive_smpp.c:80
SMPP_PDU * smpp_pdu_unpack(Octstr *smsc_id, Octstr *data_without_len)
Definition: smpp_pdu.c:597
static time_t first_to_esme
Definition: drive_smpp.c:86
void msg_destroy(Msg *msg)
Definition: msg.c:132
static void send_smpp_thread(void *arg)
Definition: drive_smpp.c:253
static SMPP_PDU * handle_deliver_sm_resp(ESME *esme, SMPP_PDU *pdu)
Definition: drive_smpp.c:183
int make_server_socket(int port, const char *interface_name)
Definition: socket.c:93
static SMPP_PDU * handle_unbind(ESME *esme, SMPP_PDU *pdu)
Definition: drive_smpp.c:189
static void accept_thread(void *arg)
Definition: drive_smpp.c:422
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
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
void gwthread_sleep(double seconds)
Octstr * conn_read_withlen(Connection *conn)
Definition: conn.c:1169
static Counter * message_id_counter
Definition: drive_smpp.c:77
void smpp_pdu_dump(Octstr *smsc_id, SMPP_PDU *pdu)
Definition: smpp_pdu.c:766
union SMPP_PDU::@15 u
static void esme_destroy(ESME *esme)
Definition: drive_smpp.c:122
int conn_write_withlen(Connection *conn, Octstr *data)
Definition: conn.c:1075
int gwthread_pollfd(int fd, int events, double timeout)
static Octstr * bearerbox_host
Definition: drive_smpp.c:78
Octstr * smpp_pdu_read_data(Connection *conn, long len)
Definition: smpp_pdu.c:895
int log_open(char *filename, int level, enum excl_state excl)
Definition: log.c:375
static time_t last_from_esme
Definition: drive_smpp.c:88
Definition: octstr.c:118
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
char * optarg
Definition: attgetopt.c:82
#define panic
Definition: log.h:87
static void help(void)
Definition: drive_smpp.c:460
int socklen_t
Definition: socket.h:73
void gwlib_shutdown(void)
Definition: gwlib.c:94
static void handle_pdu(ESME *esme, SMPP_PDU *pdu)
Definition: drive_smpp.c:228
Octstr * msg_pack(Msg *msg)
Definition: msg.c:181
static ESME * esme_create(Connection *conn)
Definition: drive_smpp.c:109
unsigned long type
Definition: drive_smpp.c:212
int smpp_pdu_init(Cfg *cfg)
Definition: smpp_pdu.c:184
void gwlib_init(void)
Definition: gwlib.c:78
int conn_error(Connection *conn)
Definition: conn.c:716
Connection * conn
Definition: drive_smpp.c:102
SMPP_PDU *(* handler)(ESME *, SMPP_PDU *)
Definition: drive_smpp.c:213
static time_t last_to_esme
Definition: drive_smpp.c:87
void gwthread_wakeup_all(void)
SMPP_PDU * smpp_pdu_create(unsigned long type, unsigned long seq_no)
Definition: smpp_pdu.c:400
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
Connection * conn_wrap_fd(int fd, int ssl)
Definition: conn.c:566
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.