Kannel: Open Source WAP and SMS gateway  svn-r5335
smsc_emi.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_emi.c - interface to EMI/UCP SMS centers
59  *
60  * Uoti Urpala 2001
61  * Alexander Malysh and Stipe Tolj 2002-2003
62  * Vincent Chavanis 2005-2006
63  *
64  * References:
65  *
66  * [1] Short Message Service Centre 4.6 EMI - UCP Interface Specification
67  * document version 4.6, April 2003, CMG Wireless Data Solutions.
68  */
69 
70 /* Doesn't warn about unrecognized configuration variables */
71 /* The EMI specification doesn't document how connections should be
72  * opened/used. The way they currently work might need to be changed. */
73 
74 
75 #include <sys/types.h>
76 #include <sys/socket.h>
77 #include <unistd.h>
78 #include <errno.h>
79 #include <time.h>
80 #include <limits.h>
81 #include <float.h>
82 
83 #include "gwlib/gwlib.h"
84 #include "smscconn.h"
85 #include "smscconn_p.h"
86 #include "bb_smscconn_cb.h"
87 #include "msg.h"
88 #include "sms.h"
89 #include "emimsg.h"
90 #include "dlr.h"
91 #include "alt_charsets.h"
92 
93 #define EMI2_MAX_TRN 100
94 
95 typedef struct privdata {
98  long receiver_thread;
99  long sender_thread;
100  int shutdown; /* Internal signal to shut down */
101  int listening_socket; /* File descriptor */
102  int send_socket;
103  int port, alt_port; /* SMSC port */
104  int our_port; /* Optional local port number in which to
105  * bind our end of send connection */
106  int rport; /* Receive-port to listen */
109  Octstr *my_number; /* My number if we want to force one */
110  int unacked; /* Sent messages not acked */
111  struct {
112  time_t sendtime; /* When we sent out a message with a given
113  * TRN. Is 0 if the TRN slot is currently free. */
114  int sendtype; /* OT of message, undefined if time == 0 */
115  Msg *sendmsg; /* Corresponding message for OT == 51 */
116  } slots[EMI2_MAX_TRN];
117  int keepalive; /* Seconds to send a Keepalive Command (OT=31) */
118  int flowcontrol; /* 0=Windowing, 1=Stop-and-Wait */
119  int waitack; /* Seconds to wait to ack */
120  int waitack_expire; /* What to do on waitack expire */
121  int window; /* In windowed flow-control, the window size */
122  int can_write; /* write = 1, read = 0, for stop-and-wait flow control */
123  int priv_nexttrn; /* next TRN, this should never be accessed directly.
124  * use int emi2_next_trn (SMSCConn *conn) instead.
125  */
126  time_t last_activity_time; /* the last time something was sent over the main
127  * SMSC connection
128  */
129  time_t check_time;
130  int idle_timeout; /* Seconds a Main connection to the SMSC is allowed to be idle.
131  If 0, no idle timeout is in effect */
132  Octstr *npid; /* Notification PID value */
133  Octstr *nadc; /* Notification Address */
134  int alt_charset; /* Alternative GSM charset, defined via values in gwlib/alt_charsets.h */
135 } PrivData;
136 
137 typedef enum {
138  EMI2_SENDREQ, /* somebody asked this driver to send a SMS message */
139  EMI2_SMSCREQ, /* the SMSC wants something from us */
140  EMI2_CONNERR, /* an error condition in the SMSC main connection */
141  EMI2_TIMEOUT, /* timeout on the SMSC main connection */
142 } EMI2Event;
143 
144 #define PRIVDATA(conn) ((PrivData *)((conn)->data))
145 
146 #define SLOTBUSY(conn,i) (PRIVDATA(conn)->slots[(i)].sendtime != 0)
147 
148 #define CONNECTIONIDLE(conn) \
149 ((PRIVDATA(conn)->unacked == 0) && \
150  (PRIVDATA(conn)->idle_timeout ? \
151  (PRIVDATA(conn)->last_activity_time + PRIVDATA(conn)->idle_timeout) <= time(0):0))
152 
153 #define emi2_can_send(conn) \
154 ((PRIVDATA(conn)->can_write || !PRIVDATA(conn)->flowcontrol) && \
155  (PRIVDATA(conn)->unacked < PRIVDATA(conn)->window) && \
156  (!PRIVDATA(conn)->shutdown))
157 
158 #define emi2_needs_keepalive(conn) \
159 (emi2_can_send(conn) && \
160  (PRIVDATA(conn)->keepalive > 0) && \
161  (time(NULL) > (PRIVDATA(conn)->last_activity_time + PRIVDATA(conn)->keepalive)))
162 
163 /*
164  * Send an EMI message and update the last_activity_time field.
165  */
167 {
168  int result = emimsg_send(server, emimsg, PRIVDATA(conn)->name);
169 
170  if (result >= 0 && emimsg->or == 'O' && ( emimsg->ot == 31 || emimsg->ot == 51)) {
171  PRIVDATA(conn)->last_activity_time = time (NULL);
172  }
173 
174  return result;
175 }
176 
177 /* Wait for a message of type 'ot', sent with TRN 0, to be acked.
178  * Timeout after 't' seconds. Any other packets received are ignored.
179  * This function is meant for initial login packet(s) and testing.
180  * Return 1 for positive ACK, 0 for timeout, -1 for broken/closed connection,
181  * -2 for negative NACK. */
182 static int wait_for_ack(PrivData *privdata, Connection *server, int ot, int t)
183 {
184  time_t timeout_time;
185  int time_left;
186  Octstr *str;
187  struct emimsg *emimsg;
188 
189  timeout_time = time(NULL) + t;
190  while (1) {
191  str = conn_read_packet(server, 2, 3);
192  if (conn_eof(server)) {
193  error(0, "EMI2[%s]: connection closed in wait_for_ack",
195  return -1;
196  }
197  if (conn_error(server)) {
198  error(0, "EMI2[%s]: connection error in wait_for_ack",
200  return -1;
201  }
202  if (str) {
203  emimsg = get_fields(str, privdata->name);
204  if (emimsg == NULL) {
205  octstr_destroy(str);
206  continue;
207  }
208  if (emimsg->ot == ot && emimsg->trn == 0 && emimsg->or == 'R') {
209  octstr_destroy(str);
210  break;
211  }
212  warning(0, "EMI2[%s]: ignoring message %s while waiting for ack to"
213  "ot:%d trn:%d", octstr_get_cstr(privdata->name),
214  octstr_get_cstr(str), ot, 0);
216  octstr_destroy(str);
217  }
218  time_left = timeout_time - time(NULL);
219  if (time_left < 0 || privdata->shutdown)
220  return 0;
221  conn_wait(server, time_left);
222  }
223  if (octstr_get_char(emimsg->fields[0], 0) == 'N') {
225  return -2;
226  }
228  return 1;
229 }
230 
231 
232 static struct emimsg *make_emi31(PrivData *privdata, int trn)
233 {
234  struct emimsg *emimsg;
235 
240  } else {
242  }
243  emimsg->fields[1] = octstr_create("0539");
244  return emimsg;
245  } else {
246  return NULL;
247  }
248 }
249 
250 
252 {
253  struct emimsg *emimsg;
254 
262  emimsg->fields[E60_VERS] = octstr_create("0100");
263  return emimsg;
264 }
265 
266 
268 {
269  PrivData *privdata = conn->data;
270  int result, alt_host, do_alt_host;
271  struct emimsg *emimsg;
273  Msg *msg;
274  int connect_error = 0;
275  int wait_ack = 0;
276 
277  do_alt_host = octstr_len(privdata->alt_host) != 0 || privdata->alt_port != 0;
278 
279  alt_host = 0;
280 
281  mutex_lock(conn->flow_mutex);
283  mutex_unlock(conn->flow_mutex);
284 
285  while (!privdata->shutdown) {
286 
290  }
291 
292  /* if there is no alternative host, sleep and try to re-connect */
293  if (alt_host == 0 && connect_error) {
294  error(0, "EMI2[%s]: Couldn't connect to SMS center (retrying in %ld seconds).",
297  }
298 
299  if (alt_host != 1) {
300  info(0, "EMI2[%s]: connecting to Primary SMSC",
302  mutex_lock(conn->flow_mutex);
303  octstr_destroy(conn->name);
304  conn->name = octstr_format("EMI2:%S:%d:%S", privdata->host, privdata->port, privdata->username ? privdata->username : octstr_imm("null"));
305  mutex_unlock(conn->flow_mutex);
308  conn->our_host);
309  if(do_alt_host)
310  alt_host=1;
311  else
312  alt_host=0;
313  } else {
314  info(0, "EMI2[%s]: connecting to Alternate SMSC",
316  /* use alt_host or/and alt_port if defined */
317  mutex_lock(conn->flow_mutex);
318  octstr_destroy(conn->name);
319  conn->name = octstr_format("EMI2:%S:%d:%S", octstr_len(privdata->alt_host) ? privdata->alt_host : privdata->host,
322  mutex_unlock(conn->flow_mutex);
326  privdata->our_port, conn->our_host);
327  alt_host=0;
328  }
329  if (privdata->shutdown) {
331  return NULL;
332  }
333  if (server == NULL) {
334  error(0, "EMI2[%s]: opening TCP connection to %s failed",
337  connect_error = 1;
338  continue;
339  }
340 
341  if (privdata->username && privdata->password) {
345  wait_ack = privdata->waitack > 30 ? privdata->waitack : 30;
346  result = wait_for_ack(privdata, server, 60, wait_ack);
347  if (result == -2) {
348  /*
349  * Are SMSCs going to return any temporary errors? If so,
350  * testing for those error codes should be added here.
351  */
352  error(0, "EMI2[%s]: Server rejected our login",
355  connect_error = 1;
356  continue;
357  } else if (result == 0) {
358  error(0, "EMI2[%s]: Got no reply to login attempt "
359  "within %d seconds", octstr_get_cstr(privdata->name),
360  wait_ack);
362  connect_error = 1;
363  continue;
364  } else if (result == -1) { /* Broken connection, already logged */
366  connect_error = 1;
367  continue;
368  }
369  privdata->last_activity_time = 0; /* to force keepalive after login */
370  privdata->can_write = 1;
371  }
372 
373  mutex_lock(conn->flow_mutex);
374  conn->status = SMSCCONN_ACTIVE;
375  conn->connect_time = time(NULL);
376  mutex_unlock(conn->flow_mutex);
377  bb_smscconn_connected(conn);
378  return server;
379  }
380  return NULL;
381 }
382 
383 
384 static void pack_7bit(Octstr *str)
385 {
386  Octstr *result;
387  int len, i;
388  int numbits, value;
389 
390  result = octstr_create("0");
391  len = octstr_len(str);
392  value = 0;
393  numbits = 0;
394  for (i = 0; i < len; i++) {
395  value += octstr_get_char(str, i) << numbits;
396  numbits += 7;
397  if (numbits >= 8) {
398  octstr_append_char(result, value & 0xff);
399  value >>= 8;
400  numbits -= 8;
401  }
402  }
403  if (numbits > 0)
404  octstr_append_char(result, value);
405  octstr_set_char(result, 0, (len * 7 + 3) / 4);
406  octstr_delete(str, 0, LONG_MAX);
407  octstr_append(str, result);
408  octstr_binary_to_hex(str, 1);
409  octstr_destroy(result);
410 }
411 
412 
413 static struct emimsg *msg_to_emimsg(Msg *msg, int trn, PrivData *privdata)
414 {
415  Octstr *str;
416  struct emimsg *emimsg;
417  int dcs;
418  struct tm tm;
419  char p[20];
420 
421  emimsg = emimsg_create_op(51, trn, privdata->name);
422  str = octstr_duplicate(msg->sms.sender);
423  if(octstr_get_char(str,0) == '+') {
424  /* either alphanum or international */
425  if (!octstr_check_range(str, 1, 256, gw_isdigit)) {
426  /* alphanumeric sender address with + in front*/
427  charset_utf8_to_gsm(str);
428  octstr_truncate(str, 11); /* max length of alphanumeric OaDC */
429  emimsg->fields[E50_OTOA] = octstr_create("5039");
430  pack_7bit(str);
431  }
432  else {
433  /* international number. Set format and remove + */
434  emimsg->fields[E50_OTOA] = octstr_create("1139");
435  octstr_delete(str, 0, 1);
436  octstr_truncate(str, 22); /* max length of numeric OaDC */
437  }
438  }
439  else {
440  if (!octstr_check_range(str, 0, 256, gw_isdigit)) {
441  /* alphanumeric sender address */
442  charset_utf8_to_gsm(str);
443  octstr_truncate(str, 11); /* max length of alphanumeric OaDC */
444  emimsg->fields[E50_OTOA] = octstr_create("5039");
445  pack_7bit(str);
446  }
447  }
448 
449  emimsg->fields[E50_OADC] = str;
450 
451  /* set protocol id */
452  if (msg->sms.pid >= 0) {
453  emimsg->fields[E50_RPID] = octstr_format("%04d", msg->sms.pid);
454  }
455 
456  /* set reply path indicator */
457  if (msg->sms.rpi == 2)
459  else if (msg->sms.rpi > 0)
461 
462  str = octstr_duplicate(msg->sms.receiver);
463  if(octstr_get_char(str,0) == '+') {
464  /* international number format */
465  /* EMI doesnt understand + so we have to replace it with something useful */
466  /* we try 00 here. Should really be done in the config instead so this */
467  /* is only a workaround to make wrong configs work */
468  octstr_delete(str, 0, 1);
469  octstr_insert_data(str, 0, "00",2);
470  }
471  octstr_truncate(str, 16); /* max length of ADC */
472  emimsg->fields[E50_ADC] = str;
473 
475 
476  /* XSer 01: UDH */
477  if (octstr_len(msg->sms.udhdata)) {
478  str = octstr_create("");
479  octstr_append_char(str, 0x01);
480  octstr_append_char(str, octstr_len(msg->sms.udhdata));
481  octstr_append(str, msg->sms.udhdata);
482  octstr_binary_to_hex(str, 1);
484  octstr_destroy(str);
485  }
486 
487  /* XSer 02: DCS */
488  dcs = fields_to_dcs(msg, msg->sms.alt_dcs);
489  if (dcs != 0 && dcs != 4) {
490  str = octstr_create("");
491  octstr_append_char(str, 0x02);
492  octstr_append_char(str, 1); /* len 01 */
493  octstr_append_char(str, dcs);
494  octstr_binary_to_hex(str, 1);
496  octstr_destroy(str);
497  }
498 
499  /* XSer 0c: billing identifier */
500  if (octstr_len(msg->sms.binfo)) {
501  str = octstr_create("");
502  octstr_append_char(str, 0x0c);
503  octstr_append_char(str, octstr_len(msg->sms.binfo));
504  octstr_append(str, msg->sms.binfo);
505  octstr_binary_to_hex(str, 1);
507  octstr_destroy(str);
508  }
509 
510  if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
513  str = octstr_duplicate(msg->sms.msgdata);
514  emimsg->fields[E50_NB] =
515  octstr_format("%04d", 8 * octstr_len(str));
516  octstr_binary_to_hex(str, 1);
517  emimsg->fields[E50_TMSG] = str;
518  }
519  else {
521  str = octstr_duplicate(msg->sms.msgdata);
522  charset_utf8_to_gsm(str);
523 
524  /*
525  * Check if we have to apply some after GSM transcoding kludges
526  */
529 
530  /* Could still be too long after truncation if there's an UDH part,
531  * but this is only to notice errors elsewhere (should never happen).*/
532  if (charset_gsm_truncate(str, 160))
533  error(0, "EMI2[%s]: Message to send is longer "
534  "than 160 gsm characters",
536  octstr_binary_to_hex(str, 1);
537  emimsg->fields[E50_AMSG] = str;
538  }
539 
540  if (msg->sms.validity != SMS_PARAM_UNDEFINED) {
541  tm = gw_localtime(msg->sms.validity);
542  sprintf(p, "%02d%02d%02d%02d%02d",
543  tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100,
544  tm.tm_hour, tm.tm_min);
545  str = octstr_create(p);
546  emimsg->fields[E50_VP] = str;
547  }
548  if (msg->sms.deferred != SMS_PARAM_UNDEFINED) {
549  str = octstr_create("1");
550  emimsg->fields[E50_DD] = str;
551  tm = gw_localtime(msg->sms.deferred);
552  sprintf(p, "%02d%02d%02d%02d%02d",
553  tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100,
554  tm.tm_hour, tm.tm_min);
555  str = octstr_create(p);
556  emimsg->fields[E50_DDT] = str;
557  }
558 
559  /* if delivery reports are asked, lets ask for them too */
560  /* even the sender might not be interested in delivery or non delivery */
561  /* we still need them back to clear out the memory after the message */
562  /* has been delivered or non delivery has been confirmed */
563  if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
566  octstr_append_decimal(emimsg->fields[E50_NT], 3 + (DLR_IS_BUFFERED(msg->sms.dlr_mask) ? 4 : 0));
567  if (privdata->npid)
569  if (privdata->nadc)
571  }
572  return emimsg;
573 }
574 
575 
576 /* Return -1 if the connection broke, 0 if the request couldn't be handled
577  * (unknown type), or 1 if everything was successful */
579  struct emimsg *emimsg)
580 {
581  struct emimsg *reply;
582  Octstr *tempstr, *xser;
583  int type, len;
584  Msg *msg = NULL;
585  struct universaltime unitime;
586  int st_code;
587  PrivData *privdata = conn->data;
588 
589 
590  switch(emimsg->ot) {
591 
592  /*
593  * Handle OP/01 call input operation. This operation delivery MO messages
594  * from SMSC to SMT according to [1], section 4.2, p. 9.
595  */
596  case 01:
597  msg = msg_create(sms);
598  if (emimsg->fields[E01_AMSG] == NULL)
600  else if (octstr_hex_to_binary(emimsg->fields[E01_AMSG]) == -1)
601  warning(0, "EMI2[%s]: Couldn't decode message text",
603 
604  if (emimsg->fields[E01_MT] == NULL) {
605  warning(0, "EMI2[%s]: required field MT missing",
607  /* This guess could be incorrect, maybe the message should just
608  be dropped */
610  }
611 
612  if (octstr_get_char(emimsg->fields[E01_MT], 0) == '3') {
613  msg->sms.msgdata = emimsg->fields[E01_AMSG];
614  emimsg->fields[E01_AMSG] = NULL; /* So it's not freed */
615 
616  /* obey the NRC (national replacement codes) */
619 
620  charset_gsm_to_utf8(msg->sms.msgdata);
621  }
622  else {
623  error(0, "EMI2[%s]: MT == %s isn't supported for operation type 01",
626  msg->sms.msgdata = octstr_create("");
627  }
628 
629  msg->sms.sender = octstr_duplicate(emimsg->fields[E01_OADC]);
630  if (msg->sms.sender == NULL) {
631  warning(0, "EMI2[%s]: Empty sender field in received message",
633  msg->sms.sender = octstr_create("");
634  }
635 
636  if(octstr_len(PRIVDATA(conn)->my_number)) {
637  msg->sms.receiver = octstr_duplicate(PRIVDATA(conn)->my_number);
638  }
639  else {
640  msg->sms.receiver = octstr_duplicate(emimsg->fields[E01_ADC]);
641  }
642  if (msg->sms.receiver == NULL) {
643  warning(0, "EMI2[%s]: Empty receiver field in received message",
645  msg->sms.receiver = octstr_create("");
646  }
647 
648  /* Operation type 01 doesn't have a time stamp field */
649  time(&msg->sms.time);
650 
651  msg->sms.smsc_id = octstr_duplicate(conn->id);
652  bb_smscconn_receive(conn, msg);
654  if (emi2_emimsg_send(conn, server, reply) < 0) {
656  return -1;
657  }
659  return 1;
660 
661  /*
662  * Handle OP/52 delivery short message. This is the MO side of the protocol
663  * implementation. See [1], section 5.4, p. 40.
664  */
665  case 52:
666  msg = msg_create(sms);
667  /* AMSG is the same field as TMSG */
668  if (emimsg->fields[E50_AMSG] == NULL)
670  else if (octstr_hex_to_binary(emimsg->fields[E50_AMSG]) == -1)
671  warning(0, "EMI2[%s]: Couldn't decode message text",
673 
674  /* Process XSer fields */
675  xser = emimsg->fields[E50_XSER];
676  while (octstr_len(xser) > 0) {
677  int tempint;
678  tempstr = octstr_copy(xser, 0, 4);
679  if (octstr_hex_to_binary(tempstr) == -1)
680  error(0, "EMI2[%s]: Invalid XSer",
682  type = octstr_get_char(tempstr, 0);
683  len = octstr_get_char(tempstr, 1);
684  octstr_destroy(tempstr);
685  if (len < 0) {
686  error(0, "EMI2[%s]: Malformed emi XSer field",
688  break;
689  }
690 
691  /* Handle supported XSer fields */
692  switch (type) {
693 
694  case 0x01: /* XSer 01, GSM UDH information */
695  tempstr = octstr_copy(xser, 4, len * 2);
696  if (octstr_hex_to_binary(tempstr) == -1)
697  error(0, "EMI2[%s]: Invalid UDH contents",
699  msg->sms.udhdata = tempstr;
700  break;
701 
702  case 0x02: /* XSer 02, GSM DCS information */
703  tempstr = octstr_copy(xser, 4, 2);
704  octstr_hex_to_binary(tempstr);
705  tempint = octstr_get_char(tempstr, 0);
706  octstr_destroy(tempstr);
707  if (!dcs_to_fields(&msg, tempint)) {
708  error(0, "EMI2[%s]: Invalid DCS received",
710  /* XXX Should we discard message ? */
711  dcs_to_fields(&msg, 0);
712  }
713  break;
714 
715  /*
716  * XSer 03-0b are for CDMA/TDMA information exchange and are currently
717  * not implemented in this EMI interface. See CMG EMI/UCP spec 4.6,
718  * section 5.1.2.4 for more information.
719  */
720 
721  case 0x0c: /* XSer 0c, billing identifier */
722  tempstr = octstr_copy(xser, 4, len * 2);
723  if (octstr_hex_to_binary(tempstr) == -1) {
724  error(0, "EMI2[%s] Invalid XSer 0c billing identifier <%s>",
726  octstr_get_cstr(tempstr));
727  } else {
728  msg->sms.binfo = tempstr;
729  }
730  break;
731 
732  case 0x0d: /* XSer 0d, single shot indicator */
733  tempstr = octstr_copy(xser, 4, 2);
734  octstr_hex_to_binary(tempstr);
735  tempint = octstr_get_char(tempstr, 0);
736  octstr_destroy(tempstr);
737  if (tempint)
738  info(0, "EMI2[%s]: Single shot indicator set.",
740  break;
741 
742  /* XSer fields 0e-ff are reserved for future use and should not be used. */
743 
744  default:
745  warning(0, "EMI2[%s]: Unsupported EMI XSer field %d",
747  break;
748  }
749 
750  octstr_delete(xser, 0, 2 * len + 4);
751  }
752 
753  if (emimsg->fields[E50_MT] == NULL) {
754  warning(0, "EMI2[%s]: required field MT missing",
756  /* This guess could be incorrect, maybe the message should just
757  be dropped */
759  }
760  if (octstr_get_char(emimsg->fields[E50_MT], 0) == '3') {
761  msg->sms.msgdata = emimsg->fields[E50_AMSG];
762  emimsg->fields[E50_AMSG] = NULL; /* So it's not freed */
763 
764  /* obey the NRC (national replacement codes) */
767 
768  charset_gsm_to_utf8(msg->sms.msgdata);
769  }
770  else if (octstr_get_char(emimsg->fields[E50_MT], 0) == '4') {
771  msg->sms.msgdata = emimsg->fields[E50_TMSG];
772  emimsg->fields[E50_TMSG] = NULL;
773  }
774  else {
775  error(0, "EMI2[%s]: MT == %s isn't supported yet",
778  msg->sms.msgdata = octstr_create("");
779  }
780 
781  msg->sms.sender = octstr_duplicate(emimsg->fields[E50_OADC]);
782  if (msg->sms.sender == NULL) {
783  warning(0, "EMI2[%s]: Empty sender field in received message",
785  msg->sms.sender = octstr_create("");
786  }
787 
788  if(octstr_len(PRIVDATA(conn)->my_number)) {
789  msg->sms.receiver = octstr_duplicate(PRIVDATA(conn)->my_number);
790  }
791  else {
792  msg->sms.receiver = octstr_duplicate(emimsg->fields[E50_ADC]);
793  }
794  if (msg->sms.receiver == NULL) {
795  warning(0, "EMI2[%s]: Empty receiver field in received message",
797  msg->sms.receiver = octstr_create("");
798  }
799 
800  tempstr = emimsg->fields[E50_SCTS]; /* Just a shorter name */
801  if (tempstr == NULL) {
802  warning(0, "EMI2[%s]: Received EMI message doesn't have required timestamp",
804  goto notime;
805  }
806  if (octstr_len(tempstr) != 12) {
807  warning(0, "EMI2[%s]: EMI SCTS field must have length 12, now %ld",
809  goto notime;
810  }
811  if (octstr_parse_long(&unitime.second, tempstr, 10, 10) != 12 ||
812  (octstr_delete(tempstr, 10, 2),
813  octstr_parse_long(&unitime.minute, tempstr, 8, 10) != 10) ||
814  (octstr_delete(tempstr, 8, 2),
815  octstr_parse_long(&unitime.hour, tempstr, 6, 10) != 8) ||
816  (octstr_delete(tempstr, 6, 2),
817  octstr_parse_long(&unitime.year, tempstr, 4, 10) != 6) ||
818  (octstr_delete(tempstr, 4, 2),
819  octstr_parse_long(&unitime.month, tempstr, 2, 10) != 4) ||
820  (octstr_delete(tempstr, 2, 2),
821  octstr_parse_long(&unitime.day, tempstr, 0, 10) != 2)) {
822  error(0, "EMI2[%s]: EMI delivery time stamp looks malformed",
824  notime:
825  time(&msg->sms.time);
826  }
827  else {
828  unitime.year += 2000; /* Conversion function expects full year */
829  unitime.month -= 1; /* conversion function expects 0-based months */
830  msg->sms.time = date_convert_universal(&unitime);
831  }
832 
833  msg->sms.smsc_id = octstr_duplicate(conn->id);
834  bb_smscconn_receive(conn, msg);
836  if (emi2_emimsg_send(conn, server, reply) < 0) {
838  return -1;
839  }
841  return 1;
842 
843  /*
844  * Handle OP/53 delivery notification. See [1], section 5.5, p. 43.
845  */
846  case 53:
847  st_code = atoi(octstr_get_cstr(emimsg->fields[E50_DST]));
848  switch(st_code)
849  {
850  case 0: /* delivered */
851  msg = dlr_find((conn->id ? conn->id : privdata->name),
852  emimsg->fields[E50_SCTS], /* timestamp */
853  emimsg->fields[E50_OADC], /* destination */
854  DLR_SUCCESS, 1);
855  break;
856  case 1: /* buffered */
857  msg = dlr_find((conn->id ? conn->id : privdata->name),
858  emimsg->fields[E50_SCTS], /* timestamp */
859  emimsg->fields[E50_OADC], /* destination */
860  DLR_BUFFERED, 1);
861  break;
862  case 2: /* not delivered */
863  msg = dlr_find((conn->id ? conn->id : privdata->name),
864  emimsg->fields[E50_SCTS], /* timestamp */
865  emimsg->fields[E50_OADC], /* destination */
866  DLR_FAIL, 1);
867  break;
868  }
869  if (msg != NULL) {
870  /*
871  * Recode the msg structure with the given msgdata.
872  * Note: the DLR URL is delivered in msg->sms.dlr_url already.
873  */
874  if ((emimsg->fields[E50_AMSG]) == NULL)
875  msg->sms.msgdata = octstr_create("Delivery Report without text");
876  else
877  msg->sms.msgdata = octstr_duplicate(emimsg->fields[E50_AMSG]);
878  octstr_hex_to_binary(msg->sms.msgdata);
879  if (octstr_get_char(emimsg->fields[E50_MT], 0) == '3') {
880  /* obey the NRC (national replacement codes) */
883  charset_gsm_to_utf8(msg->sms.msgdata);
884  }
885  bb_smscconn_receive(conn, msg);
886  }
888  if (emi2_emimsg_send(conn, server, reply) < 0) {
890  return -1;
891  }
893  return 1;
894 
895  /*
896  * Handle OP/31 from SMSC side. This is not "purely" spec conform since,
897  * the protocol says "This operation can be used by a SMT to alert the SC.",
898  * which implies semantically only the opposite way. For the sake of EMI/UCP
899  * server implementations that send alert messages to SMTs we handle this
900  * without breaking any core protocol concept.
901  *
902  * See [1], section 4.6, p. 19.
903  */
904  case 31:
906  st_code = emi2_emimsg_send(conn, server, reply);
908  return (st_code < 0 ? -1 : 1);
909 
910  default:
911  error(0, "EMI2[%s]: I don't know how to handle operation type %d",
913  return 0;
914  }
915 }
916 
917 /*
918  * get all unacknowledged messages from the ringbuffer and queue them
919  * for retransmission.
920  */
922 {
923  int i;
924  debug("smsc.emi2", 0, "EMI2[%s]: clear_sent called",
926  for (i = 0; i < EMI2_MAX_TRN; i++) {
927  if (privdata->slots[i].sendtime && privdata->slots[i].sendtype == 51)
929  privdata->slots[i].sendtime = 0;
930  }
931  privdata->unacked = 0;
932 }
933 
934 /*
935  * wait seconds seconds for something to happen (a send SMS request, activity
936  * on the SMSC main connection, an error or timeout) and tell the caller
937  * what happened.
938  */
939 static EMI2Event emi2_wait (SMSCConn *conn, Connection *server, double seconds)
940 {
941  if (emi2_can_send(conn) && gw_prioqueue_len(PRIVDATA(conn)->outgoing_queue)) {
942  return EMI2_SENDREQ;
943  }
944 
945  if (server != NULL) {
946  switch (conn_wait(server, seconds)) {
947  case 1: return gw_prioqueue_len(PRIVDATA(conn)->outgoing_queue) ? EMI2_SENDREQ : EMI2_TIMEOUT;
948  case 0: return EMI2_SMSCREQ;
949  default: return EMI2_CONNERR;
950  }
951  } else {
952  gwthread_sleep(seconds);
953  return gw_prioqueue_len(PRIVDATA(conn)->outgoing_queue) ? EMI2_SENDREQ : EMI2_TIMEOUT;
954  }
955 }
956 
957 /*
958  * obtain the next free TRN.
959  */
960 static int emi2_next_trn (SMSCConn *conn)
961 {
962 #define INC_TRN(x) ((x)=((x) + 1) % EMI2_MAX_TRN)
963  int result;
964 
965  while (SLOTBUSY(conn,PRIVDATA(conn)->priv_nexttrn))
966  INC_TRN(PRIVDATA(conn)->priv_nexttrn); /* pick unused TRN */
967 
968  result = PRIVDATA(conn)->priv_nexttrn;
969  INC_TRN(PRIVDATA(conn)->priv_nexttrn);
970 
971  return result;
972 #undef INC_TRN
973 }
974 
975 /*
976  * send an EMI type 31 message when required.
977  */
979 {
980  struct emimsg *emimsg;
981  int nexttrn = emi2_next_trn (conn);
982 
983  emimsg = make_emi31(PRIVDATA(conn), nexttrn);
984  if(emimsg) {
985  PRIVDATA(conn)->slots[nexttrn].sendtype= 31;
986  PRIVDATA(conn)->slots[nexttrn].sendtime = time(NULL);
987  PRIVDATA(conn)->unacked++;
988 
989  if (emi2_emimsg_send(conn, server, emimsg) == -1) {
991  return -1;
992  }
994  }
995 
996  PRIVDATA(conn)->can_write = 0;
997 
998  return 0;
999 }
1000 
1001 
1002 /*
1003  * the actual send logic: Send all queued messages in a burst.
1004  */
1006 {
1007  struct emimsg *emimsg;
1008  Msg *msg;
1009  double delay = 0;
1010 
1011  if (conn->throughput > 0) {
1012  delay = 1.0 / conn->throughput;
1013  }
1014 
1015  /* Send messages if there's room in the sending window */
1016  while (emi2_can_send(conn) &&
1017  (msg = gw_prioqueue_remove(PRIVDATA(conn)->outgoing_queue)) != NULL) {
1018  int nexttrn = emi2_next_trn(conn);
1019 
1020  if (conn->throughput > 0)
1022 
1023  /* convert the generic Kannel message into an EMI type message */
1024  emimsg = msg_to_emimsg(msg, nexttrn, PRIVDATA(conn));
1025 
1026  /* remember the message for retransmission or DLR */
1027  PRIVDATA(conn)->slots[nexttrn].sendmsg = msg;
1028  PRIVDATA(conn)->slots[nexttrn].sendtype = 51;
1029  PRIVDATA(conn)->slots[nexttrn].sendtime = time(NULL);
1030 
1031  /* send the message */
1032  if (emi2_emimsg_send(conn, server, emimsg) == -1) {
1034  return -1;
1035  }
1036 
1037  /* we just sent a message */
1038  PRIVDATA(conn)->unacked++;
1039 
1041 
1042  /*
1043  * remember that there is an open request for stop-wait flow control
1044  * FIXME: couldn't this be done with the unacked field as well? After
1045  * all stop-wait is just a window of size 1.
1046  */
1047  PRIVDATA(conn)->can_write = 0;
1048  }
1049 
1050  return 0;
1051 }
1052 
1054 {
1055  Octstr *str;
1056  struct emimsg *emimsg;
1057  PrivData *privdata = conn->data;
1058 
1059  /* Read acks/nacks/ops from the server */
1060  while ((str = conn_read_packet(server, 2, 3))) {
1061  debug("smsc.emi2", 0, "EMI2[%s]: Got packet from the main socket",
1063 
1064  /* parse the msg */
1065  emimsg = get_fields(str, privdata->name);
1066  octstr_destroy(str);
1067 
1068  if (emimsg == NULL) {
1069  continue; /* The parse functions logged errors */
1070  }
1071 
1072  if (emimsg->or == 'O') {
1073  /* If the SMSC wants to send operations through this
1074  * socket, we'll have to read them because there
1075  * might be ACKs too. We just drop them while stopped,
1076  * hopefully the SMSC will resend them later. */
1077  if (!conn->is_stopped) {
1078  if (handle_operation(conn, server, emimsg) < 0)
1079  return -1; /* Connection broke */
1080  } else {
1081  info(0, "EMI2[%s]: Ignoring operation from main socket "
1082  "because the connection is stopped.",
1084  }
1085  } else { /* Already checked to be 'O' or 'R' */
1086  if (!SLOTBUSY(conn,emimsg->trn) ||
1087  emimsg->ot != PRIVDATA(conn)->slots[emimsg->trn].sendtype) {
1088  error(0, "EMI2[%s]: Got ack for TRN %d, don't remember sending O?",
1090  } else {
1091  PRIVDATA(conn)->can_write = 1;
1092  PRIVDATA(conn)->slots[emimsg->trn].sendtime = 0;
1093  PRIVDATA(conn)->unacked--;
1094 
1095  if (emimsg->ot == 51) {
1096  if (octstr_get_char(emimsg->fields[0], 0) == 'A') {
1097  /* we got an ack back. We might have to store the */
1098  /* timestamp for delivery notifications now */
1099  Octstr *ts, *adc;
1100  int i;
1101  Msg *m;
1102 
1103  ts = octstr_duplicate(emimsg->fields[2]);
1104  if (octstr_len(ts)) {
1105  i = octstr_search_char(ts,':',0);
1106  if (i>0) {
1107  octstr_delete(ts,0,i+1);
1108  adc = octstr_duplicate(emimsg->fields[2]);
1109  octstr_truncate(adc,i);
1110 
1111  m = PRIVDATA(conn)->slots[emimsg->trn].sendmsg;
1112  if(m == NULL) {
1113  info(0,"EMI2[%s]: uhhh m is NULL, very bad",
1115  } else if (DLR_IS_ENABLED_DEVICE(m->sms.dlr_mask)) {
1116  dlr_add((conn->id ? conn->id : privdata->name), ts, m, 1);
1117  }
1118  octstr_destroy(ts);
1119  octstr_destroy(adc);
1120  } else {
1121  octstr_destroy(ts);
1122  }
1123  }
1124  /*
1125  * report the successful transmission to the generic bb code.
1126  */
1127  bb_smscconn_sent(conn,
1128  PRIVDATA(conn)->slots[emimsg->trn].sendmsg,
1129  NULL);
1130  } else {
1131  Octstr *reply;
1132 
1133  /* create reply message */
1134  reply = octstr_create("");
1136  octstr_append_char(reply, '-');
1137  /* system message is optional */
1138  if (emimsg->fields[2] != NULL)
1140 
1141  /* XXX Process error code here
1142  long errorcode;
1143  octstr_parse_long(&errorcode, emimsg->fields[1], 0, 10);
1144  ... switch(errorcode) ...
1145  }
1146 
1147  else { */
1149  PRIVDATA(conn)->slots[emimsg->trn].sendmsg,
1151  /* } */
1152  }
1153  } else if (emimsg->ot == 31) {
1154  /* XXX Process error codes here
1155  if (octstr_get_char(emimsg->fields[0], 0) == 'N') {
1156  long errorcode;
1157  octstr_parse_long(&errorcode, emimsg->fields[1], 0, 10);
1158  ... switch errorcode ...
1159  }
1160 
1161  else { */
1162  ;
1163  /* } */
1164  } else {
1165  panic(0, "EMI2[%s]: Bug, ACK handler missing for sent packet",
1167  }
1168  }
1169  }
1171  }
1172 
1173  if (conn_error(server)) {
1174  error(0, "EMI2[%s]: Error trying to read ACKs from SMSC",
1176  return -1;
1177  }
1178 
1179  if (conn_eof(server)) {
1180  info(0, "EMI2[%s]: Main connection closed by SMSC",
1182  return -1;
1183  }
1184 
1185  return 0;
1186 }
1187 
1189 {
1190  time_t current_time;
1191  int i;
1192  PrivData *privdata = conn->data;
1193 
1194  /*
1195  * Check whether there are messages the server hasn't acked in a
1196  * reasonable time
1197  */
1198  current_time = time(NULL);
1199 
1200  if (PRIVDATA(conn)->unacked && (current_time > (PRIVDATA(conn)->check_time + 30))) {
1201  PRIVDATA(conn)->check_time = current_time;
1202  for (i = 0; i < PRIVDATA(conn)->window; i++) {
1203  if (SLOTBUSY(conn,i)
1204  && PRIVDATA(conn)->slots[i].sendtime < (current_time - PRIVDATA(conn)->waitack)) {
1205 
1206  if (PRIVDATA(conn)->slots[i].sendtype == 51) {
1207  if (PRIVDATA(conn)->waitack_expire == 0x00) {
1208  /* 0x00 - disconnect/reconnect */
1209  warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
1210  "in %d seconds, disconnecting and reconnection",
1211  octstr_get_cstr(privdata->name), i, PRIVDATA(conn)->waitack);
1212  PRIVDATA(conn)->slots[i].sendtime = 0;
1213  PRIVDATA(conn)->unacked--;
1214  info(0, "EMI2[%s]: closing connection.",
1216  conn_destroy(*server);
1217  *server = NULL;
1218  break;
1219  } else if (PRIVDATA(conn)->waitack_expire == 0x01) {
1220  /* 0x01 - resend */
1221  warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
1222  "in %d seconds, resending message", octstr_get_cstr(privdata->name),
1223  i, PRIVDATA(conn)->waitack);
1224  gw_prioqueue_produce(PRIVDATA(conn)->outgoing_queue,
1225  PRIVDATA(conn)->slots[i].sendmsg);
1226  PRIVDATA(conn)->slots[i].sendtime = 0;
1227  PRIVDATA(conn)->unacked--;
1228  if (PRIVDATA(conn)->flowcontrol) PRIVDATA(conn)->can_write=1;
1229  /* Wake up this same thread to send again
1230  * (simpler than avoiding sleep) */
1231  gwthread_wakeup(PRIVDATA(conn)->sender_thread);
1232  } else if (PRIVDATA(conn)->waitack_expire == 0x02) {
1233  /* 0x02 - carry on waiting */
1234  warning(0, "EMI2[%s]: received neither ACK nor NACK for message %d "
1235  "in %d seconds, carrying on waiting", octstr_get_cstr(privdata->name),
1236  i, PRIVDATA(conn)->waitack);
1237  }
1238  } else if (PRIVDATA(conn)->slots[i].sendtype == 31) {
1239  warning(0, "EMI2[%s]: Alert (operation 31) was not "
1240  "ACKed within %d seconds", octstr_get_cstr(privdata->name),
1241  PRIVDATA(conn)->waitack);
1242  if (PRIVDATA(conn)->flowcontrol) PRIVDATA(conn)->can_write=1;
1243  } else {
1244  panic(0, "EMI2[%s]: Bug, no timeout handler for sent packet",
1246  }
1247  }
1248  }
1249  }
1250 }
1251 
1253 {
1254  PrivData *privdata = conn->data;
1255 
1256  /*
1257  * close the connection if there was no activity.
1258  */
1259  if ((*server != NULL) && CONNECTIONIDLE(conn)) {
1260  info(0, "EMI2[%s]: closing idle connection.",
1262  conn_destroy(*server);
1263  *server = NULL;
1264  }
1265 }
1266 
1267 /*
1268  * this function calculates the new timeouttime.
1269  */
1271 {
1272  double ka_timeouttime = PRIVDATA(conn)->keepalive ? PRIVDATA(conn)->keepalive + 1 : DBL_MAX;
1273  double idle_timeouttime = (PRIVDATA(conn)->idle_timeout && server) ? PRIVDATA(conn)->idle_timeout : DBL_MAX;
1274  double result = ka_timeouttime < idle_timeouttime ? ka_timeouttime : idle_timeouttime;
1275 
1276  if (result == DBL_MAX)
1277  result = 30;
1278 
1279  return result;
1280 }
1281 
1282 /*
1283  * the main event processing loop.
1284  */
1286 {
1287  PrivData *privdata = conn->data;
1288 
1289  for (;;) {
1290  double timeouttime;
1291  EMI2Event event;
1292 
1293  if (emi2_needs_keepalive (conn)) {
1294  if (*server == NULL) {
1295  return; /* reopen the connection */
1296  }
1297 
1299  }
1300 
1301  timeouttime = emi2_get_timeouttime (conn, *server);
1302 
1303  event = emi2_wait (conn, *server, timeouttime);
1304 
1305  switch (event) {
1306  case EMI2_CONNERR:
1307  return;
1308 
1309  case EMI2_SENDREQ:
1310  if (*server == NULL) {
1311  return; /* reopen the connection */
1312  }
1313 
1314  if (emi2_do_send (conn, *server) < 0) {
1315  return; /* reopen the connection */
1316  }
1317  break;
1318 
1319  case EMI2_SMSCREQ:
1320  if (emi2_handle_smscreq (conn, *server) < 0) {
1321  return; /* reopen the connection */
1322  }
1323  break;
1324 
1325  case EMI2_TIMEOUT:
1326  break;
1327  }
1328 
1329  if ((*server !=NULL) && (emi2_handle_smscreq (conn, *server) < 0)) {
1330  return; /* reopen the connection */
1331  }
1332 
1333  emi2_idleprocessing (conn, server);
1335 
1336  if (PRIVDATA(conn)->shutdown && (PRIVDATA(conn)->unacked == 0)) {
1337  /* shutdown and no open messages */
1338  break;
1339  }
1340 
1341  if (*server != NULL) {
1342  if (conn_error(*server)) {
1343  warning(0, "EMI2[%s]: Error reading from the main connection",
1345  break;
1346  }
1347 
1348  if (conn_eof(*server)) {
1349  info(0, "EMI2[%s]: Main connection closed by SMSC",
1351  break;
1352  }
1353  }
1354  }
1355 }
1356 
1357 static void emi2_sender(void *arg)
1358 {
1359  SMSCConn *conn = arg;
1360  PrivData *privdata = conn->data;
1361  Msg *msg;
1362  Connection *server;
1363 
1364  /* Make sure we log into our own log-file if defined */
1365  log_thread_to(conn->log_idx);
1366 
1367  while (!privdata->shutdown) {
1368  if ((server = open_send_connection(conn)) == NULL) {
1369  privdata->shutdown = 1;
1370  if (privdata->rport > 0)
1372  break;
1373  }
1374  emi2_send_loop(conn, &server);
1376 
1377  if (server != NULL) {
1379  }
1380  }
1381 
1382  while((msg = gw_prioqueue_remove(privdata->outgoing_queue)) != NULL)
1384  if (privdata->rport > 0)
1386  mutex_lock(conn->flow_mutex);
1387 
1388  conn->status = SMSCCONN_DEAD;
1389 
1390  debug("bb.sms", 0, "EMI2[%s]: connection has completed shutdown.",
1392 
1404  gw_free(privdata);
1405  conn->data = NULL;
1406 
1407  mutex_unlock(conn->flow_mutex);
1409 }
1410 
1411 
1413 {
1414  PrivData *privdata = conn->data;
1415  Octstr *str;
1416  struct emimsg *emimsg;
1417 
1418  while (1) {
1419  if (conn_eof(server)) {
1420  info(0, "EMI2[%s]: receive connection closed by SMSC",
1422  return;
1423  }
1424  if (conn_error(server)) {
1425  error(0, "EMI2[%s]: receive connection broken",
1427  return;
1428  }
1429  if (conn->is_stopped)
1430  str = NULL;
1431  else
1432  str = conn_read_packet(server, 2, 3);
1433  if (str) {
1434  debug("smsc.emi2", 0, "EMI2[%s]: Got packet from the receive connection.",
1436  if ( (emimsg = get_fields(str, privdata->name)) ) {
1437  if (emimsg->or == 'O') {
1438  if (handle_operation(conn, server, emimsg) < 0) {
1440  return;
1441  }
1442  }
1443  else
1444  error(0, "EMI2[%s]: No ACKs expected on receive connection!",
1447  }
1448  octstr_destroy(str);
1449  }
1450  else
1451  conn_wait(server, -1);
1452  if (privdata->shutdown)
1453  break;
1454  }
1455  return;
1456 }
1457 
1458 
1460 {
1461  int s;
1462 
1463  if ( (s = make_server_socket(privdata->rport, (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL))) == -1) {
1464  error(0, "EMI2[%s]: could not create listening socket in port %d",
1466  return -1;
1467  }
1468  if (socket_set_blocking(s, 0) == -1) {
1469  error(0, "EMI2[%s]: couldn't make listening socket port %d "
1470  "non-blocking", octstr_get_cstr(privdata->name), privdata->rport);
1471  close(s);
1472  return -1;
1473  }
1475  return 0;
1476 }
1477 
1478 
1479 static void emi2_listener(void *arg)
1480 {
1481  SMSCConn *conn = arg;
1482  PrivData *privdata = conn->data;
1483  struct sockaddr_in server_addr;
1484  socklen_t server_addr_len;
1485  Octstr *ip;
1486  Connection *server;
1487  int s, ret;
1488 
1489  /* Make sure we log into our own log-file if defined */
1490  log_thread_to(conn->log_idx);
1491 
1492  while (!privdata->shutdown) {
1493 
1494  if (!privdata->host) {
1495  mutex_lock(conn->flow_mutex);
1496  conn->status = SMSCCONN_CONNECTING;
1497  conn->connect_time = time(NULL);
1498  mutex_unlock(conn->flow_mutex);
1499  }
1500 
1501  server_addr_len = sizeof(server_addr);
1503  if (ret == -1) {
1504  if (errno == EINTR)
1505  continue;
1506  error(0, "EMI2[%s]: Poll for emi2 smsc connections failed, shutting down",
1508  break;
1509  }
1510  if (privdata->shutdown)
1511  break;
1512  if (ret == 0) /* This thread was woken up from elsewhere, but
1513  if we're not shutting down nothing to do here. */
1514  continue;
1515  s = accept(privdata->listening_socket, (struct sockaddr *)&server_addr, &server_addr_len);
1516  if (s == -1) {
1517  warning(errno, "EMI2[%s]: emi2_listener: accept() failed, retrying...",
1519  continue;
1520  }
1521  ip = host_ip(server_addr);
1523  info(0, "EMI2[%s]: smsc connection tried from denied host <%s>,"
1524  " disconnected", octstr_get_cstr(privdata->name),
1525  octstr_get_cstr(ip));
1526  octstr_destroy(ip);
1527  close(s);
1528  continue;
1529  }
1530  server = conn_wrap_fd(s, 0);
1531  if (server == NULL) {
1532  error(0, "EMI2[%s]: emi2_listener: conn_wrap_fd failed on accept()ed fd",
1534  octstr_destroy(ip);
1535  close(s);
1536  continue;
1537  }
1538  conn_claim(server);
1539  info(0, "EMI2[%s]: smsc connected from %s",
1541  octstr_destroy(ip);
1542 
1543  if (!privdata->host) {
1544  mutex_lock(conn->flow_mutex);
1545  conn->status = SMSCCONN_ACTIVE;
1546  conn->connect_time = time(NULL);
1547  mutex_unlock(conn->flow_mutex);
1548  }
1549 
1550  emi2_receiver(conn, server);
1552  }
1553  if (close(privdata->listening_socket) == -1)
1554  warning(errno, "EMI2[%s]: couldn't close listening socket at shutdown",
1557 }
1558 
1559 
1560 static int add_msg_cb(SMSCConn *conn, Msg *sms)
1561 {
1562  PrivData *privdata = conn->data;
1563  Msg *copy;
1564 
1565  copy = msg_duplicate(sms);
1568 
1569  return 0;
1570 }
1571 
1572 
1573 static int shutdown_cb(SMSCConn *conn, int finish_sending)
1574 {
1575  PrivData *privdata = conn->data;
1576 
1577  if (!privdata->host)
1578  finish_sending = 0;
1579 
1580  debug("bb.sms", 0, "EMI2[%s]: Shutting down SMSCConn EMI2, %s",
1582  finish_sending ? "slow" : "instant");
1583 
1584  /* Documentation claims this would have been done by smscconn.c,
1585  but isn't when this code is being written. */
1587  privdata->shutdown = 1; /* Separate from why_killed to avoid locking, as
1588  why_killed may be changed from outside? */
1589 
1590  if (finish_sending == 0) {
1591  Msg *msg;
1592  while ((msg = gw_prioqueue_remove(privdata->outgoing_queue)) != NULL) {
1594  }
1595  }
1596 
1597  if (privdata->rport > 0)
1599  return 0;
1600 }
1601 
1602 
1603 static void start_cb(SMSCConn *conn)
1604 {
1605  PrivData *privdata = conn->data;
1606 
1607  /* in case there are messages in the buffer already */
1608  if (privdata->rport > 0)
1610  debug("smsc.emi2", 0, "EMI2[%s]: start called",
1612 }
1613 
1614 
1615 static long queued_cb(SMSCConn *conn)
1616 {
1617  PrivData *privdata = conn->data;
1618  long ret;
1619 
1621 
1622  /* use internal queue as load, maybe something else later */
1623 
1624  conn->load = ret;
1625  return ret;
1626 }
1627 
1628 
1630 {
1631  PrivData *privdata;
1632  Octstr *allow_ip, *deny_ip, *host, *alt_host;
1633  long portno, our_port, keepalive, flowcontrol, waitack,
1634  idle_timeout, alt_portno, alt_charset, waitack_expire;
1635  long window;
1636  /* has to be long because of cfg_get_integer */
1637  int i;
1638 
1639  allow_ip = deny_ip = host = alt_host = NULL;
1640 
1641  privdata = gw_malloc(sizeof(PrivData));
1643  privdata->listening_socket = -1;
1644  privdata->can_write = 1;
1645  privdata->priv_nexttrn = 0;
1647  privdata->check_time = 0;
1648 
1649  /* host may be empty if receive-port is used */
1650  host = cfg_get(cfg, octstr_imm("host"));
1651  privdata->host = host;
1652 
1653  if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1)
1654  portno = 0;
1655  privdata->port = portno;
1656  if (host && (privdata->port <= 0 || privdata->port > 65535)) {
1657  error(0, "EMI2[%s]: 'port' missing/invalid in emi2 configuration.",
1659  goto error;
1660  }
1661 
1662  if (cfg_get_integer(&our_port, cfg, octstr_imm("our-port")) == -1)
1663  privdata->our_port = 0; /* 0 means use any port */
1664  else
1666 
1667  privdata->name = cfg_get(cfg, octstr_imm("smsc-id"));
1668  if (privdata->name == NULL) {
1669  privdata->name = octstr_create("");
1670 
1671  /* Add our_host */
1672  if (octstr_len(conn->our_host)) {
1674  }
1675 
1676  /* Add our_port */
1677  if (privdata->our_port != 0) {
1678  /* if we have our_port but not our_host, add kannel:our_port */
1679  if(octstr_len(privdata->name) == 0) {
1680  octstr_append(privdata->name, octstr_imm("kannel"));
1681  }
1684  } else {
1685  if(octstr_len(privdata->name) != 0) {
1687  }
1688  }
1689 
1690  /* if we have our_host neither our_port */
1691  if (octstr_len(privdata->name) != 0)
1693 
1694  if (privdata->host) {
1698  }
1699  }
1700 
1701  if (cfg_get_integer(&idle_timeout, cfg, octstr_imm("idle-timeout")) == -1)
1702  idle_timeout = 0;
1703 
1704  privdata->idle_timeout = idle_timeout;
1705 
1706  alt_host = cfg_get(cfg, octstr_imm("alt-host"));
1707  privdata->alt_host = alt_host;
1708 
1709  if (cfg_get_integer(&portno, cfg, octstr_imm("receive-port")) < 0)
1710  portno = 0;
1711  privdata->rport = portno;
1712 
1713  /* if neither host, nor receive-port is defined */
1714  if (privdata->host == NULL && privdata->rport == 0) {
1715  error(0, "EMI2[-]: 'receive-port' missing/invalid in emi2 configuration, "
1716  "while no 'host' and 'port' defined.");
1717  goto error;
1718  }
1719 
1720  if (cfg_get_integer(&alt_portno, cfg, octstr_imm("alt-port")) < 0)
1721  alt_portno = 0;
1722  privdata->alt_port = alt_portno;
1723 
1724  allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
1725  if (allow_ip)
1726  deny_ip = octstr_create("*.*.*.*");
1727  else
1728  deny_ip = NULL;
1729  privdata->username = cfg_get(cfg, octstr_imm("smsc-username"));
1730  privdata->password = cfg_get(cfg, octstr_imm("smsc-password"));
1731 
1732  privdata->my_number = cfg_get(cfg, octstr_imm("my-number"));
1733 
1734  privdata->npid = cfg_get(cfg, octstr_imm("notification-pid"));
1735  privdata->nadc = cfg_get(cfg, octstr_imm("notification-addr"));
1736 
1737  if ( (privdata->username == NULL && privdata->my_number == NULL) ||
1738  cfg_get_integer(&keepalive, cfg, octstr_imm("keepalive")) < 0)
1739  privdata->keepalive = 0;
1740  else
1741  privdata->keepalive = keepalive;
1742 
1743  if (cfg_get_integer(&flowcontrol, cfg, octstr_imm("flow-control")) < 0)
1744  privdata->flowcontrol = 0;
1745  else
1746  privdata->flowcontrol = flowcontrol;
1747  if (privdata->flowcontrol < 0 || privdata->flowcontrol > 1) {
1748  error(0, "EMI2[%s]: 'flow-control' invalid in emi2 configuration.",
1750  goto error;
1751  }
1752 
1753  if (cfg_get_integer(&window, cfg, octstr_imm("window")) < 0)
1755  else
1756  privdata->window = window;
1757  if (privdata->window > EMI2_MAX_TRN) {
1758  warning(0, "EMI2[%s]: Value of 'window' should be lesser or equal to %d..",
1761  }
1762 
1763  if (cfg_get_integer(&waitack, cfg, octstr_imm("wait-ack")) < 0)
1764  privdata->waitack = 60;
1765  else
1766  privdata->waitack = waitack;
1767  if (privdata->waitack < 30 ) {
1768  error(0, "EMI2[%s]: 'wait-ack' invalid in emi2 configuration.",
1770  goto error;
1771  }
1772 
1773  if (cfg_get_integer(&waitack_expire, cfg, octstr_imm("wait-ack-expire")) < 0)
1774  privdata->waitack_expire = 0;
1775  else
1776  privdata->waitack_expire = waitack_expire;
1777  if (privdata->waitack_expire >3) {
1778  error(0, "EMI2[%s]: 'wait-ack-expire' invalid in emi2 configuration.",
1780  goto error;
1781  }
1782 
1783  if (privdata->rport < 0 || privdata->rport > 65535) {
1784  error(0, "EMI2[%s]: 'receive-port' missing/invalid in emi2 configuration.",
1786  goto error;
1787  }
1788 
1789  if (cfg_get_integer(&alt_charset, cfg, octstr_imm("alt-charset")) < 0)
1790  privdata->alt_charset = 0;
1791  else
1793 
1796 
1797  if (privdata->rport > 0 && emi2_open_listening_socket(conn,privdata) < 0) {
1798  gw_free(privdata);
1799  privdata = NULL;
1800  goto error;
1801  }
1802 
1803  conn->data = privdata;
1804 
1805  if (privdata->host) {
1806  conn->name = octstr_format("EMI2:%S:%d:%S", privdata->host, privdata->port,
1807  privdata->username ? privdata->username : octstr_imm("null"));
1808  } else {
1809  conn->name = octstr_format("EMI2:localhost:%d:%S", privdata->rport,
1810  privdata->username ? privdata->username : octstr_imm("null"));
1811  }
1812 
1813  privdata->shutdown = 0;
1814 
1815  for (i = 0; i < EMI2_MAX_TRN; i++)
1816  privdata->slots[i].sendtime = 0;
1817  privdata->unacked = 0;
1818 
1819  conn->status = SMSCCONN_CONNECTING;
1820  conn->connect_time = time(NULL);
1821 
1822  if (privdata->rport > 0 && (privdata->receiver_thread = gwthread_create(emi2_listener, conn)) == -1)
1823  goto error;
1824 
1825  if (privdata->host && (privdata->sender_thread = gwthread_create(emi2_sender, conn)) == -1) {
1826  privdata->shutdown = 1;
1827  if (privdata->rport > 0) {
1830  }
1831  goto error;
1832  }
1833 
1834  conn->shutdown = shutdown_cb;
1835  conn->queued = queued_cb;
1836  conn->start_conn = start_cb;
1837  conn->send_msg = add_msg_cb;
1838 
1839  return 0;
1840 
1841 error:
1842  error(0, "EMI2[%s]: Failed to create emi2 smsc connection",
1843  (privdata ? octstr_get_cstr(privdata->name) : "-"));
1844  if (privdata != NULL) {
1846  }
1847  gw_free(privdata);
1852  conn->status = SMSCCONN_DEAD;
1853  info(0, "EMI2[%s]: exiting", (privdata ? octstr_get_cstr(privdata->name) : "-"));
1854  return -1;
1855 }
int port
Definition: smsc_cgw.c:159
Octstr * name
Definition: smscconn_p.h:173
static int emi2_next_trn(SMSCConn *conn)
Definition: smsc_emi.c:960
void error(int err, const char *fmt,...)
Definition: log.c:648
long year
Definition: date.h:72
static struct emimsg * make_emi60(PrivData *privdata)
Definition: smsc_emi.c:251
Definition: emimsg.h:87
void info(int err, const char *fmt,...)
Definition: log.c:672
time_t check_time
Definition: smsc_emi.c:129
static long our_port
Definition: radius_acct.c:87
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
Msg * sendmsg[CGW_TRN_MAX]
Definition: smsc_cgw.c:167
Definition: emimsg.h:87
time_t last_activity_time
Definition: smsc_emi.c:126
int emimsg_send(Connection *conn, struct emimsg *emimsg, Octstr *whoami)
Definition: emimsg.c:368
static double emi2_get_timeouttime(SMSCConn *conn, Connection *server)
Definition: smsc_emi.c:1270
#define mutex_unlock(m)
Definition: thread.h:136
char or
Definition: emimsg.h:72
static int emi2_do_send(SMSCConn *conn, Connection *server)
Definition: smsc_emi.c:1005
int window
Definition: smsc_emi.c:121
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
int octstr_check_range(Octstr *ostr, long pos, long len, octstr_func_t filter)
Definition: octstr.c:814
static Connection * open_send_connection(SMSCConn *conn)
Definition: smsc_emi.c:267
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1504
void emimsg_destroy(struct emimsg *emimsg)
Definition: emimsg.c:215
Definition: emimsg.h:96
int send_socket
Definition: smsc_cgw.c:158
static EMI2Event emi2_wait(SMSCConn *conn, Connection *server, double seconds)
Definition: smsc_emi.c:939
Octstr * id
Definition: smscconn_p.h:174
void gwthread_join(long thread)
void * data
Definition: smscconn_p.h:250
int priv_nexttrn
Definition: smsc_emi.c:123
int waitack
Definition: smsc_cgw.c:171
#define SLOTBUSY(conn, i)
Definition: smsc_emi.c:146
List * outgoing_queue
Definition: smsc_cgw.c:153
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1517
void charset_utf8_to_gsm(Octstr *ostr)
Definition: charset.c:288
Octstr * password
Definition: smsc_cimd2.c:100
int log_idx
Definition: smscconn_p.h:197
int type
Definition: smsc_cimd2.c:215
int smsc_emi2_create(SMSCConn *conn, CfgGroup *cfg)
Definition: smsc_emi.c:1629
static Octstr * host
Definition: fakesmsc.c:122
Octstr * npid
Definition: smsc_emi.c:132
int trn
Definition: emimsg.h:71
#define cfg_get(grp, varname)
Definition: cfg.h:86
#define DC_8BIT
Definition: sms.h:111
struct emimsg * emimsg_create_op(int ot, int trn, Octstr *whoami)
Definition: emimsg.c:166
#define gw_prioqueue_produce(queue, item)
Definition: gw-prioqueue.h:98
int can_write
Definition: smsc_emi.c:122
Definition: emimsg.h:88
#define msg_create(type)
Definition: msg.h:136
#define EMI_NRC_ISO_21
Definition: alt_charsets.h:84
long minute
Definition: date.h:74
Octstr * our_host
Definition: smscconn_p.h:192
void charset_nrc_iso_21_german_to_gsm(Octstr *ostr)
Definition: charset.c:486
static Cfg * cfg
Definition: opensmppbox.c:95
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
Definition: octstr.c:1461
int conn_eof(Connection *conn)
Definition: conn.c:705
Definition: emimsg.h:70
static int emi2_handle_smscreq(SMSCConn *conn, Connection *server)
Definition: smsc_emi.c:1053
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
Definition: dlr.c:387
struct emimsg * get_fields(Octstr *message, Octstr *whoami)
Definition: emimsg.c:290
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 octstr_binary_to_hex(Octstr *ostr, int uppercase)
Definition: octstr.c:465
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
long reconnect_delay
Definition: smscconn_p.h:199
void log_thread_to(int idx)
Definition: log.c:759
static struct emimsg * make_emi31(PrivData *privdata, int trn)
Definition: smsc_emi.c:232
int is_allowed_ip(Octstr *allow_ip, Octstr *deny_ip, Octstr *ip)
Definition: utils.c:815
static void clear_sent(PrivData *privdata)
Definition: smsc_emi.c:921
static void emi2_receiver(SMSCConn *conn, Connection *server)
Definition: smsc_emi.c:1412
int flowcontrol
Definition: smsc_emi.c:118
static int shutdown_cb(SMSCConn *conn, int finish_sending)
Definition: smsc_emi.c:1573
#define INC_TRN(x)
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
static void emi2_sender(void *arg)
Definition: smsc_emi.c:1357
static int emi2_keepalive_handling(SMSCConn *conn, Connection *server)
Definition: smsc_emi.c:978
struct privdata::@23 slots[EMI2_MAX_TRN]
Definition: emimsg.h:89
void conn_claim(Connection *conn)
Definition: conn.c:671
#define DLR_SUCCESS
Definition: dlr.h:72
#define POLLIN
Definition: gwpoll.h:91
static struct emimsg * msg_to_emimsg(Msg *msg, int trn, PrivData *privdata)
Definition: smsc_emi.c:413
Definition: emimsg.h:88
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
Definition: msg.h:79
int sms_priority_compare(const void *a, const void *b)
Definition: sms.c:395
static int emi2_open_listening_socket(SMSCConn *conn, PrivData *privdata)
Definition: smsc_emi.c:1459
Octstr * my_number
Definition: smsc_cimd2.c:105
Octstr * conn_read_packet(Connection *conn, int startmark, int endmark)
Definition: conn.c:1214
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1527
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:477
#define emi2_needs_keepalive(conn)
Definition: smsc_emi.c:158
void conn_destroy(Connection *conn)
Definition: conn.c:627
EMI2Event
Definition: smsc_emi.c:137
#define emi2_can_send(conn)
Definition: smsc_emi.c:153
Definition: emimsg.h:81
#define EMI2_MAX_TRN
Definition: smsc_emi.c:93
time_t connect_time
Definition: smscconn_p.h:155
Definition: emimsg.h:88
#define octstr_duplicate(ostr)
Definition: octstr.h:187
double throughput
Definition: smscconn_p.h:203
static Octstr * deny_ip
Definition: bb_udp.c:112
long day
Definition: date.h:70
Mutex * flow_mutex
Definition: smscconn_p.h:157
struct emimsg * emimsg_create_reply(int ot, int trn, int positive, Octstr *whoami)
Definition: emimsg.c:199
Octstr * username
Definition: smsc_cimd2.c:99
Octstr * allow_ip
Definition: smsc_cgw.c:164
char * name
Definition: smsc_cimd2.c:212
Connection * conn_open_tcp_with_port(Octstr *host, int port, int our_port, Octstr *our_host)
Definition: conn.c:548
int gw_isdigit(int c)
Definition: utils.c:988
int keepalive
Definition: smsc_emi.c:117
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 * host
Definition: smsc_cgw.c:163
void * gw_prioqueue_remove(gw_prioqueue_t *queue)
Definition: gw-prioqueue.c:265
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
long gw_prioqueue_len(gw_prioqueue_t *queue)
Definition: gw-prioqueue.c:220
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
int rport
Definition: smsc_cgw.c:160
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
long check_time
Definition: smsc_cgw.c:173
Definition: emimsg.h:87
static void pack_7bit(Octstr *str)
Definition: smsc_emi.c:384
int fields_to_dcs(Msg *msg, int mode)
Definition: sms.c:73
Octstr * name
Definition: smsc_emi.c:96
gw_prioqueue_t * gw_prioqueue_create(int(*cmp)(const void *, const void *))
Definition: gw-prioqueue.c:174
void gwthread_sleep(double seconds)
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
volatile sig_atomic_t is_stopped
Definition: smscconn_p.h:169
static int add_msg_cb(SMSCConn *conn, Msg *sms)
Definition: smsc_emi.c:1560
static Octstr * allow_ip
Definition: bb_udp.c:111
int alt_port
Definition: smsc_emi.c:103
long second
Definition: date.h:75
int gwthread_pollfd(int fd, int events, double timeout)
int shutdown
Definition: smsc_cgw.c:156
#define DLR_IS_BUFFERED(dlr)
Definition: dlr.h:88
long sender_thread
Definition: smsc_cgw.c:155
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
void octstr_append_decimal(Octstr *ostr, long value)
Definition: octstr.c:1976
void gw_prioqueue_destroy(gw_prioqueue_t *queue, void(*item_destroy)(void *))
Definition: gw-prioqueue.c:201
int alt_charset
Definition: smsc_emi.c:134
int ot
Definition: emimsg.h:73
int waitack_expire
Definition: smsc_emi.c:120
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
Definition: emimsg.h:88
static int wait_for_ack(PrivData *privdata, Connection *server, int ot, int t)
Definition: smsc_emi.c:182
long hour
Definition: date.h:73
static int handle_operation(SMSCConn *conn, Connection *server, struct emimsg *emimsg)
Definition: smsc_emi.c:578
long month
Definition: date.h:71
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
static void emi2_idletimeout_handling(SMSCConn *conn, Connection **server)
Definition: smsc_emi.c:1252
static void emi2_listener(void *arg)
Definition: smsc_emi.c:1479
Definition: emimsg.h:81
static void start_cb(SMSCConn *conn)
Definition: smsc_emi.c:1603
Octstr * nadc
Definition: smsc_emi.c:133
#define panic
Definition: log.h:87
struct tm gw_localtime(time_t t)
Definition: protected.c:121
void gwthread_wakeup(long thread)
Definition: cfg.c:73
Octstr ** fields
Definition: emimsg.h:75
struct privdata PrivData
int octstr_hex_to_binary(Octstr *ostr)
Definition: octstr.c:494
Definition: emimsg.h:90
int socklen_t
Definition: socket.h:73
smscconn_status_t status
Definition: smscconn_p.h:151
long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
Definition: octstr.c:749
Octstr * alt_host
Definition: smsc_emi.c:108
static int emi2_emimsg_send(SMSCConn *conn, Connection *server, struct emimsg *emimsg)
Definition: smsc_emi.c:166
static void server(int lport, int pport)
long(* queued)(SMSCConn *conn)
Definition: smscconn_p.h:241
void octstr_truncate(Octstr *ostr, int new_len)
Definition: octstr.c:1327
int(* send_msg)(SMSCConn *conn, Msg *msg)
Definition: smscconn_p.h:236
void charset_gsm_to_nrc_iso_21_german(Octstr *ostr)
Definition: charset.c:460
long receiver_thread
Definition: smsc_cgw.c:154
gw_prioqueue_t * outgoing_queue
Definition: smsc_emi.c:97
int listening_socket
Definition: smsc_cgw.c:157
#define DLR_BUFFERED
Definition: dlr.h:74
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:329
int unacked
Definition: smsc_cgw.c:170
int dcs_to_fields(Msg **msg, int dcs)
Definition: sms.c:139
int conn_error(Connection *conn)
Definition: conn.c:716
int idle_timeout
Definition: smsc_emi.c:130
long date_convert_universal(struct universaltime *t)
Definition: date.c:118
time_t sendtime[CGW_TRN_MAX]
Definition: smsc_cgw.c:168
int our_port
Definition: smsc_cgw.c:161
#define PRIVDATA(conn)
Definition: smsc_emi.c:144
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406
#define mutex_lock(m)
Definition: thread.h:130
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:415
static long queued_cb(SMSCConn *conn)
Definition: smsc_emi.c:1615
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82
Octstr * deny_ip
Definition: smsc_cgw.c:164
long keepalive
Definition: smsc_cimd2.c:104
static Octstr * alt_charset
Definition: opensmppbox.c:129
int sendtype
Definition: smsc_emi.c:114
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
int charset_gsm_truncate(Octstr *gsm, long max)
Definition: charset.c:512
#define DLR_FAIL
Definition: dlr.h:73
#define CONNECTIONIDLE(conn)
Definition: smsc_emi.c:148
#define DC_UCS2
Definition: sms.h:112
static void emi2_send_loop(SMSCConn *conn, Connection **server)
Definition: smsc_emi.c:1285
Connection * conn_wrap_fd(int fd, int ssl)
Definition: conn.c:566
static void reply(HTTPClient *c, List *push_headers)
Definition: emimsg.h:89
static void emi2_idleprocessing(SMSCConn *conn, Connection **server)
Definition: smsc_emi.c:1188
int load
Definition: smscconn_p.h:152
void charset_gsm_to_utf8(Octstr *ostr)
Definition: charset.c:220
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.