1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2014 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.oisd.c - Driver for Sema Group SMS Center G8.1 (OIS 5.8)
59  * using direct TCP/IP access interface
60  *
61  * Dariusz Markowicz <dm@tenbit.pl> 2002-2004
62  *
63  * This code is based on the CIMD2 module design.
64  *
65  * References:
66  *
67  *   [1] Sema SMSC Version G8.1 Open Interface Specification
68  *       document version 5.8, 18 January 2001, Sema Telecoms.
69  */
70 
71 #include <ctype.h>
72 #include <time.h>
73 #include <errno.h>
74 #include <limits.h>
75 #include <string.h>
76 
77 #include <unistd.h>
78 
79 #include "gwlib/gwlib.h"
80 #include "smscconn.h"
81 #include "smscconn_p.h"
82 #include "bb_smscconn_cb.h"
83 
84 #include "shared.h"
85 #include "sms.h"
86 #include "dlr.h"
87 
88 
89 typedef struct privdata {
90     Octstr  *host;
91     long    port;
92     long    keepalive;
93     Octstr  *my_number;
94     long    validityperiod;
95     int     no_dlr;
96 
97     int     socket;
98     unsigned long send_seq;
99 
100     Octstr  *inbuffer;
101     List    *received;
102 
103     time_t  next_ping;
104 
105     List *outgoing_queue;
106     SMSCConn *conn;
107     int io_thread;
108     int quitting;
109     List *stopped; /* list-trick for suspend/isolate */
110 
111 } PrivData;
112 
113 
114 
115 /* Microseconds before giving up on a request */
116 #define RESPONSE_TIMEOUT (10 * 1000000)
117 #define RESULT_SUCCESS 0
118 
119 enum {
120     INVOKE = 0,
121     RESULT = 1
122 };
123 
124 /* Textual names for the operation codes defined by the OISD spec. */
125 /* If you make changes here, also change the operation table. */
126 enum {
127     SUBMIT_SM = 0,
128     STATUS_REPORT = 4,
129     DELIVER_SM = 9,
130     RETRIEVE_REQUEST = 11,
131 
132     /* Not a request; add to any request to make it a response */
133     RESPONSE = 50
134 };
135 
isphonedigit(int c)136 static int isphonedigit(int c)
137 {
138     return isdigit(c) || c == '+' || c == '-';
139 }
140 
parm_valid_address(Octstr * value)141 static int parm_valid_address(Octstr *value)
142 {
143     return octstr_check_range(value, 0, octstr_len(value), isphonedigit);
144 }
145 
146 /***************************************************************************/
147 /* Some functions to look up information about operation codes             */
148 /***************************************************************************/
149 
150 static int operation_find(int operation);
151 static Octstr *operation_name(int operation);
152 static int operation_can_send(int operation);
153 static int operation_can_receive(int operation);
154 
155 static const struct
156 {
157     char *name;
158     int code;
159     int can_send;
160     int can_receive;
161 }
162 operations[] = {
163     { "Submit SM", SUBMIT_SM, 1, 0 },
164     { "Status Report", STATUS_REPORT, 0, 1 },
165     { "Deliver SM", DELIVER_SM, 0, 1 },
166     { "Retrieve Request", RETRIEVE_REQUEST, 1, 0 },
167 
168     { NULL, 0, 0, 0 }
169 };
170 
operation_find(int operation)171 static int operation_find(int operation)
172 {
173     int i;
174 
175     for (i = 0; operations[i].name != NULL; i++) {
176         if (operations[i].code == operation)
177             return i;
178     }
179 
180     return -1;
181 }
182 
183 /* Return a human-readable representation of this operation code */
operation_name(int operation)184 static Octstr *operation_name(int operation)
185 {
186     int i;
187 
188     i = operation_find(operation);
189     if (i >= 0)
190         return octstr_create(operations[i].name);
191 
192     if (operation >= RESPONSE) {
193         i = operation_find(operation - RESPONSE);
194         if (i >= 0) {
195             Octstr *name = octstr_create(operations[i].name);
196             octstr_append_cstr(name, " response");
197             return name;
198         }
199     }
200 
201     /* Put the operation number here when we have octstr_format */
202     return octstr_create("(unknown)");
203 }
204 
205 /* Return true if a OISD client may send this operation */
operation_can_send(int operation)206 static int operation_can_send(int operation)
207 {
208     int i = operation_find(operation);
209 
210     if (i >= 0)
211         return operations[i].can_send;
212 
213     /* If we can receive the request, then we can send the response. */
214     if (operation >= RESPONSE)
215         return operation_can_receive(operation - RESPONSE);
216 
217     return 0;
218 }
219 
220 
221 /* Return true if a OISD server may send this operation */
operation_can_receive(int operation)222 static int operation_can_receive(int operation)
223 {
224     int i = operation_find(operation);
225 
226     if (i >= 0)
227         return operations[i].can_receive;
228 
229     /* If we can send the request, then we can receive the response. */
230     if (operation >= RESPONSE)
231         return operation_can_send(operation - RESPONSE);
232 
233     return 0;
234 }
235 
236 /***************************************************************************
237  * Packet encoding/decoding functions.  They handle packets at the octet   *
238  * level, and know nothing of the network.                                 *
239  ***************************************************************************/
240 
241 struct packet
242 {
243     unsigned long opref; /* operation reference */
244     int operation;
245     Octstr *data;        /* Encoded packet */
246 };
247 
248 /* A reminder that packets are created without a valid sequence number */
249 #define BOGUS_SEQUENCE 0
250 
251 static Msg *oisd_accept_delivery_report_message(struct packet *request,
252                                                 SMSCConn *conn);
253 
packet_parse_header(struct packet * packet)254 static void packet_parse_header(struct packet *packet)
255 {
256     packet->opref = (octstr_get_char(packet->data, 3) << 24)
257                   | (octstr_get_char(packet->data, 2) << 16)
258                   | (octstr_get_char(packet->data, 1) << 8)
259                   | (octstr_get_char(packet->data, 0));
260 
261     packet->operation = octstr_get_char(packet->data, 5);
262     if (octstr_get_char(packet->data, 4) == 1)
263         packet->operation += RESPONSE;
264 }
265 
266 
267 /*
268  * Accept an Octstr containing one packet, build a struct packet around
269  * it, and return that struct.  The Octstr is stored in the struct.
270  * No error checking is done here yet.
271  */
packet_parse(Octstr * packet_data)272 static struct packet *packet_parse(Octstr *packet_data)
273 {
274     struct packet *packet;
275 
276     packet = gw_malloc(sizeof(*packet));
277     packet->data = packet_data;
278 
279     /* Fill in packet->operation and packet->opref */
280     packet_parse_header(packet);
281 
282     return packet;
283 }
284 
285 /* Deallocate this packet */
packet_destroy(struct packet * packet)286 static void packet_destroy(struct packet *packet)
287 {
288     if (packet != NULL) {
289         octstr_destroy(packet->data);
290         gw_free(packet);
291     }
292 }
293 
294 /*
295  * Find the first packet in "in", delete it from "in", and return it as
296  * a struct.  Return NULL if "in" contains no packet.  Always delete
297  * leading non-packet data from "in".
298  */
packet_extract(Octstr * in,SMSCConn * conn)299 static struct packet *packet_extract(Octstr *in, SMSCConn *conn)
300 {
301     Octstr *packet;
302     int size, i;
303     static char s[4][4] = {
304         { 0x01, 0x0b, 0x00, 0x00 },
305         { 0x01, 0x00, 0x00, 0x00 },
306         { 0x00, 0x04, 0x00, 0x00 },
307         { 0x00, 0x09, 0x00, 0x00 }
308     }; /* msgtype, oper, 0, 0 */
309     char known_bytes[4];
310 
311     if (octstr_len(in) < 10)
312         return NULL;
313     octstr_get_many_chars(known_bytes, in, 4, 4);
314     /* Find s, and delete everything up to it. */
315     /* If packet starts with one of s, it should be good packet */
316     for (i = 0; i < 4; i++) {
317         if (memcmp(s[i], known_bytes, 4) == 0)
318             break;
319     }
320 
321     if (i >= 4) {
322         error(0, "OISD[%s]: wrong packet",
323               octstr_get_cstr(conn->id));
324         octstr_dump(in, 0);
325         return NULL;
326     }
327 
328     /* Find end of packet */
329     size = (octstr_get_char(in, 9) << 8) | octstr_get_char(in, 8);
330 
331     if (size + 10 > octstr_len(in))
332         return NULL;
333 
334     packet = octstr_copy(in, 0, size + 10);
335     octstr_delete(in, 0, size + 10);
336 
337     return packet_parse(packet);
338 }
339 
packet_check_can_receive(struct packet * packet,SMSCConn * conn)340 static void packet_check_can_receive(struct packet *packet, SMSCConn *conn)
341 {
342     gw_assert(packet != NULL);
343 
344     if (!operation_can_receive(packet->operation)) {
345         Octstr *name = operation_name(packet->operation);
346         warning(0, "OISD[%s]: SMSC sent us %s request",
347                 octstr_get_cstr(conn->id),
348                 octstr_get_cstr(name));
349         octstr_destroy(name);
350     }
351 }
352 
oisd_expand_gsm7_to_bits(char * bits,Octstr * raw7)353 static int oisd_expand_gsm7_to_bits(char *bits, Octstr *raw7)
354 {
355     int i, j, k;
356     int len;
357     char ch;
358 
359     len = octstr_len(raw7) * 7; /* number of bits in the gsm 7-bit msg */
360 
361     for (j = i = 0; j < len; ++i) {
362         ch = octstr_get_char(raw7, i);
363         for (k = 0; k < 8; ++k) {
364             bits[j++] = (char) (ch & 0x01);
365             ch >>= 1;
366         }
367     }
368 
369     return j;
370 }
371 
oisd_expand_gsm7_from_bits(const char * bits,int pos)372 static char oisd_expand_gsm7_from_bits(const char *bits, int pos)
373 {
374     int i;
375     char ch;
376 
377     pos *= 7; /* septet position in bits */
378     ch = '\0';
379     for (i = 6; i >= 0; --i) {
380         ch <<= 1;
381         ch |= bits[pos + i];
382     }
383 
384     return ch;
385 }
386 
oisd_expand_gsm7(Octstr * raw7)387 static Octstr *oisd_expand_gsm7(Octstr *raw7)
388 {
389     Octstr *raw8;
390     int i, len;
391     char *bits;
392 
393     raw8 = octstr_create("");
394     bits = gw_malloc(8 * octstr_len(raw7) + 1);
395 
396     oisd_expand_gsm7_to_bits(bits, raw7);
397     len = octstr_len(raw7);
398 
399     for (i = 0; i < len; ++i) {
400         octstr_append_char(raw8, oisd_expand_gsm7_from_bits(bits, i));
401     }
402 
403     gw_free(bits);
404 
405     return raw8;
406 }
407 
oisd_shrink_gsm7(Octstr * str)408 static void oisd_shrink_gsm7(Octstr *str)
409 {
410     Octstr *result;
411     int len, i;
412     int numbits, value;
413 
414     result = octstr_create("");
415     len = octstr_len(str);
416     value = 0;
417     numbits = 0;
418     for (i = 0; i < len; i++) {
419         value += octstr_get_char(str, i) << numbits;
420         numbits += 7;
421         if (numbits >= 8) {
422             octstr_append_char(result, value & 0xff);
423             value >>= 8;
424             numbits -= 8;
425         }
426     }
427     if (numbits > 0)
428         octstr_append_char(result, value);
429     octstr_delete(str, 0, LONG_MAX);
430     octstr_append(str, result);
431     octstr_destroy(result);
432 }
433 
434 /****************************************************************************
435  * Packet encoding functions.  They do not allow the creation of invalid
436  * OISD packets.
437  ***************************************************************************/
438 
439 /* Build a new packet struct with this operation code and sequence number. */
packet_create(int operation,unsigned long opref)440 static struct packet *packet_create(int operation, unsigned long opref)
441 {
442     struct packet *packet;
443     unsigned char header[10];
444 
445     packet = gw_malloc(sizeof(*packet));
446     packet->operation = operation;
447     packet->opref = opref;
448 
449     /* Opref */
450     header[0] = opref & 0xff;
451     header[1] = (opref >> 8) & 0xff;
452     header[2] = (opref >> 16) & 0xff;
453     header[3] = (opref >> 24) & 0xff;
454 
455     /* Message Type & Operation */
456     if (operation > RESPONSE) {
457         header[4] = RESULT;
458         header[5] = operation - RESPONSE;
459     } else {
460         header[4] = INVOKE;
461         header[5] = operation;
462     }
463 
464     /* Unused */
465     header[6] = 0;
466     header[7] = 0;
467 
468     /* Data Size */
469     header[8] = 0;
470     header[9] = 0;
471 
472     packet->data = octstr_create_from_data((char *)header, 10);
473 
474     return packet;
475 }
476 
packet_set_data_size(struct packet * packet)477 static void packet_set_data_size(struct packet *packet)
478 {
479     int len;
480 
481     gw_assert(packet != NULL);
482 
483     len = octstr_len(packet->data) - 10;
484 
485     octstr_set_char(packet->data, 8, len & 0xff); /* Data Size */
486     octstr_set_char(packet->data, 9, (len >> 8) & 0xff);
487 }
488 
packet_set_sequence(struct packet * packet,unsigned long opref)489 static void packet_set_sequence(struct packet *packet, unsigned long opref)
490 {
491     gw_assert(packet != NULL);
492 
493     octstr_set_char(packet->data, 0, opref & 0xff);
494     octstr_set_char(packet->data, 1, (opref >> 8) & 0xff);
495     octstr_set_char(packet->data, 2, (opref >> 16) & 0xff);
496     octstr_set_char(packet->data, 3, (opref >> 24) & 0xff);
497     packet->opref = opref;
498 }
499 
packet_encode_message(Msg * msg,SMSCConn * conn)500 static struct packet *packet_encode_message(Msg *msg, SMSCConn *conn)
501 {
502     struct packet *packet;
503     PrivData *pdata = conn->data;
504     int DCS;
505     int setvalidity = SMS_PARAM_UNDEFINED;
506     int so = 0;
507     int udhlen7, udhlen8;
508     int msglen7, msglen8;
509     Octstr *udhdata = NULL;
510     Octstr *msgdata = NULL;
511 
512     gw_assert(msg != NULL);
513     gw_assert(msg->type == sms);
514     gw_assert(msg->sms.receiver != NULL);
515 
516     DCS = fields_to_dcs(msg, 0);
517     if (msg->sms.sender == NULL)
518         msg->sms.sender = octstr_create("");
519 
520     if (!parm_valid_address(msg->sms.receiver)) {
521         warning(0, "OISD[%s]: non-digits in destination phone number '%s', discarded",
522                 octstr_get_cstr(conn->id),
523                 octstr_get_cstr(msg->sms.receiver));
524         return NULL;
525     }
526 
527     if (!parm_valid_address(msg->sms.sender)) {
528         warning(0, "OISD[%s]: non-digits in originating phone number '%s', discarded",
529                 octstr_get_cstr(conn->id),
530                 octstr_get_cstr(msg->sms.sender));
531         return NULL;
532     }
533 
534     packet = packet_create(SUBMIT_SM, BOGUS_SEQUENCE);
535 
536     gw_assert(octstr_check_range(msg->sms.receiver, 0,
537                                  octstr_len(msg->sms.receiver), isphonedigit));
538     /* MSISDN length */
539     octstr_append_char(packet->data,
540                        (unsigned char) octstr_len(msg->sms.receiver));
541 
542     /* MSISDN */
543     octstr_append(packet->data, msg->sms.receiver);
544 
545     /* Duplicate msg. behaviour */
546     /* 1=reject duplicates, 2=allow duplicates */
547     octstr_append_char(packet->data, 2);
548 
549     /* SME ref. no. unused in this protocol implementation, but set */
550     octstr_append_char(packet->data, 0);
551     octstr_append_char(packet->data, 0);
552     octstr_append_char(packet->data, 0);
553     octstr_append_char(packet->data, 0);
554 
555     /* Priority 0=high, 1=normal */
556     octstr_append_char(packet->data, 1);
557     gw_assert(octstr_check_range(msg->sms.sender, 0,
558                                  octstr_len(msg->sms.sender), isphonedigit));
559 
560     /* Originating address length */
561     octstr_append_char(packet->data,
562                        (unsigned char) (octstr_len(msg->sms.sender) + 2));
563 
564     /* XXX: GSM operator dependent ? */
565     /* TON */
566     octstr_append_char(packet->data, 0x42);
567 
568     /* NPI */
569     octstr_append_char(packet->data, 0x44);
570 
571     /* Originating address */
572     octstr_append(packet->data, msg->sms.sender);
573 
574     /* Validity period type 0=none, 1=absolute, 2=relative */
575 
576     /*
577      * Validity-Period (TP-VP)
578      * see GSM 03.40 section 9.2.3.12
579      */
580     if (msg->sms.validity != SMS_PARAM_UNDEFINED)
581     	setvalidity = (msg->sms.validity - time(NULL)) / 60;
582     else if (setvalidity != SMS_PARAM_UNDEFINED)
583     	setvalidity = pdata->validityperiod;
584     if (setvalidity != SMS_PARAM_UNDEFINED) {
585         /* Validity period type 0=none, 1=absolute, 2=relative */
586         octstr_append_char(packet->data, 2);
587 
588         if (setvalidity > 635040)
589             setvalidity = 255;
590         else if (setvalidity >= 50400 && setvalidity <= 635040)
591             setvalidity = (setvalidity - 1) / 7 / 24 / 60 + 192 + 1;
592         else if (setvalidity > 43200 && setvalidity < 50400)
593             setvalidity = 197;
594         else if (setvalidity >= 2880 && setvalidity <= 43200)
595             setvalidity = (setvalidity - 1) / 24 / 60 + 166 + 1;
596         else if (setvalidity > 1440 && setvalidity < 2880)
597             setvalidity = 168;
598         else if (setvalidity >= 750 && setvalidity <= 1440)
599             setvalidity = (setvalidity - 720 - 1) / 30 + 143 + 1;
600         else if (setvalidity > 720 && setvalidity < 750)
601             setvalidity = 144;
602         else if (setvalidity >= 5 && setvalidity <= 720)
603             setvalidity = (setvalidity - 1) / 5 - 1 + 1;
604         else if (setvalidity < 5)
605             setvalidity = 0;
606 
607         octstr_append_char(packet->data, setvalidity);
608     } else {
609         /* Validity period type 0=none, 1=absolute, 2=relative */
610         octstr_append_char(packet->data, 0);
611         setvalidity = 0; /* reset */
612     }
613 
614     if (setvalidity >= 0 && setvalidity <= 143)
615         debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d minutes",
616               octstr_get_cstr(conn->id), (setvalidity + 1)*5);
617     else if (setvalidity >= 144 && setvalidity <= 167)
618         debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %3.1f hours",
619               octstr_get_cstr(conn->id), ((float)(setvalidity - 143) / 2) + 12);
620     else if (setvalidity >= 168 && setvalidity <= 196)
621         debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d days",
622               octstr_get_cstr(conn->id), (setvalidity - 166));
623     else
624         debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d weeks",
625               octstr_get_cstr(conn->id), (setvalidity - 192));
626 
627     /* Data coding scheme */
628     octstr_append_char(packet->data, DCS);
629 
630     /* Explicitly ask not to get status reports.
631      * If we do not do this, the server's default might be to
632      * send status reports in some cases, and we don't do anything
633      * with those reports anyway. */
634     /* ask for the delivery reports if needed*/
635 
636     if (!pdata->no_dlr)
637         if (DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask))
638             octstr_append_char(packet->data, 7);
639         else
640             octstr_append_char(packet->data, 0);
641     else if (pdata->no_dlr && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask))
642         warning(0, "OISD[%s]: dlr request make no sense while no-dlr set to true",
643              octstr_get_cstr(conn->id));
644 
645     /* Protocol id 0=default */
646     octstr_append_char(packet->data, 0);
647 
648     if (octstr_len(msg->sms.udhdata))
649         so |= 0x02;
650     if (msg->sms.coding == DC_8BIT)
651         so |= 0x10;
652 
653     /* Submission options */
654     octstr_append_char(packet->data, so);
655 
656     udhlen8 = octstr_len(msg->sms.udhdata);
657     msglen8 = octstr_len(msg->sms.msgdata);
658 
659     udhdata = octstr_duplicate(msg->sms.udhdata);
660     msgdata = octstr_duplicate(msg->sms.msgdata);
661 
662     if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) {
663         debug("bb.sms.oisd", 0, "OISD[%s]: sending UTF-8=%s",
664               octstr_get_cstr(conn->id),
665               octstr_get_cstr(msg->sms.msgdata));
666         charset_utf8_to_gsm(msgdata);
667         oisd_shrink_gsm7(msgdata);
668     }
669 
670     /* calculate lengths */
671     udhlen7 = octstr_len(udhdata);
672     msglen7 = octstr_len(msgdata);
673 
674     octstr_append_char(packet->data, (unsigned char) (udhlen8 + msglen8));
675     octstr_append_char(packet->data, (unsigned char) (udhlen7 + msglen7));
676 
677     /*
678      * debug("bb.sms.oisd", 0, "OISD[%s]: packet_encode_message udhlen8=%d, msglen8=%d",
679      *       octstr_get_cstr(conn->id), udhlen8, msglen8);
680      * debug("bb.sms.oisd", 0, "OISD[%s]: packet_encode_message udhlen7=%d, msglen7=%d",
681      *       octstr_get_cstr(conn->id), udhlen7, msglen7);
682      */
683 
684     /* copy text */
685     octstr_append(packet->data, udhdata);
686     octstr_append(packet->data, msgdata);
687 
688     /* Sub-logical SME number */
689     octstr_append_char(packet->data, 0);
690     octstr_append_char(packet->data, 0);
691 
692     octstr_destroy(udhdata);
693     octstr_destroy(msgdata);
694 
695     return packet;
696 }
697 
698 /***************************************************************************
699  * Protocol functions.  These implement various transactions.              *
700  ***************************************************************************/
701 
702 /* Give this packet a proper sequence number for sending. */
packet_set_send_sequence(struct packet * packet,PrivData * pdata)703 static void packet_set_send_sequence(struct packet *packet, PrivData *pdata)
704 {
705     gw_assert(pdata != NULL);
706 
707     packet_set_sequence(packet, pdata->send_seq);
708     pdata->send_seq++;
709 }
710 
oisd_get_packet(PrivData * pdata,Octstr ** ts)711 static struct packet *oisd_get_packet(PrivData *pdata, Octstr **ts)
712 {
713     struct packet *packet = NULL;
714 
715     gw_assert(pdata != NULL);
716 
717     /* If packet is already available, don't try to read anything */
718     packet = packet_extract(pdata->inbuffer, pdata->conn);
719 
720     while (packet == NULL) {
721         if (read_available(pdata->socket, RESPONSE_TIMEOUT) != 1) {
722             warning(0, "OISD[%s]: SMSC is not responding",
723                     octstr_get_cstr(pdata->conn->id));
724             return NULL;
725         }
726 
727         if (octstr_append_from_socket(pdata->inbuffer, pdata->socket) <= 0) {
728             error(0, "OISD[%s]: oisd_get_packet: read failed",
729                   octstr_get_cstr(pdata->conn->id));
730             return NULL;
731         }
732 
733         packet = packet_extract(pdata->inbuffer, pdata->conn);
734     }
735 
736     packet_check_can_receive(packet, pdata->conn);
737     debug("bb.sms.oisd", 0, "OISD[%s]: received",
738           octstr_get_cstr(pdata->conn->id));
739     if (packet->operation != RETRIEVE_REQUEST + RESPONSE)
740         octstr_dump(packet->data, 0);
741     if (ts)
742         *ts = octstr_copy(packet->data, 15, 14);
743 
744     if (pdata->keepalive > 0)
745         pdata->next_ping = time(NULL) + pdata->keepalive;
746 
747     return packet;
748 }
749 
750 /*
751  * Acknowledge a request.
752  */
oisd_send_response(struct packet * request,PrivData * pdata)753 static void oisd_send_response(struct packet *request, PrivData *pdata)
754 {
755     struct packet *response;
756 
757     gw_assert(request != NULL);
758     gw_assert(request->operation < RESPONSE);
759 
760     response = packet_create(request->operation + RESPONSE, request->opref);
761 
762     octstr_append_char(response->data, (char) RESULT_SUCCESS);
763 
764     packet_set_data_size(response);
765 
766     debug("bb.sms.oisd", 0, "OISD[%s]: sending response",
767           octstr_get_cstr(pdata->conn->id));
768     octstr_dump(response->data, 0);
769 
770     /* Don't check errors here because if there is something
771      * wrong with the socket, the main loop will detect it. */
772     octstr_write_to_socket(pdata->socket, response->data);
773 
774     packet_destroy(response);
775 }
776 
oisd_accept_message(struct packet * request,SMSCConn * conn)777 static Msg *oisd_accept_message(struct packet *request, SMSCConn *conn)
778 {
779     Msg *msg = NULL;
780     int DCS;
781     int dest_len;
782     int origin_len;
783     int add_info;
784     int msglen7, msglen8;
785     int udh_len;
786 
787     msg = msg_create(sms);
788 
789     /* See GSM 03.38.  The bit patterns we can handle are:
790      *   000xyyxx  Uncompressed text, yy indicates alphabet.
791      *                   yy = 00, default alphabet
792      *                   yy = 01, 8-bit data
793      *                   yy = 10, UCS-2
794      *                   yy = 11, reserved
795      *   1111xyxx  Data, y indicates alphabet.
796      *                   y = 0, default alphabet
797      *                   y = 1, 8-bit data
798      */
799 
800     /* Additional information
801      *   xxxxxxyz  This field conveys additional information to assist
802      *             the recipient in interpreting the SM.
803      *                   z = reply path
804      *                   y = user data header indicator
805      *                   x = reserved
806      */
807 
808     /*
809      * Destination addr. and Originating addr. w/o TOA
810      */
811 
812     /* Destination addr. length */
813     dest_len = octstr_get_char(request->data, 10);
814 
815     /* Destination addr. */
816     msg->sms.receiver = octstr_copy(request->data, 11+2, dest_len-2);
817 
818     /* Originating addr. length */
819     origin_len = octstr_get_char(request->data, 11+dest_len+4);
820 
821     /* Originating addr. */
822     msg->sms.sender = octstr_copy(request->data, 11+dest_len+5+2, origin_len-2);
823 
824     DCS = octstr_get_char(request->data, 11+dest_len+5+origin_len);
825     if (!dcs_to_fields(&msg, DCS)) {
826         /* XXX: Should reject this message ? */
827         debug("bb.sms.oisd", 0, "OISD[%s]: Invalid DCS",
828               octstr_get_cstr(conn->id));
829         dcs_to_fields(&msg, 0);
830     }
831 
832     add_info = octstr_get_char(request->data,11+dest_len+5+origin_len+2);
833 
834     msglen7 = octstr_get_char(request->data, 11+dest_len+5+origin_len+3);
835     msglen8 = octstr_get_char(request->data, 11+dest_len+5+origin_len+4);
836 
837     msg->sms.rpi = add_info & 0x01;
838 
839     debug("bb.sms.oisd", 0,
840           "OISD[%s]: received DCS=%02X, add_info=%d, msglen7=%d, msglen8=%d, rpi=%ld",
841           octstr_get_cstr(conn->id),
842           DCS, add_info, msglen7, msglen8, msg->sms.rpi);
843 
844     if (msg->sms.coding == DC_7BIT) {
845         msg->sms.msgdata =
846             oisd_expand_gsm7(octstr_copy(request->data,
847                                          11+dest_len+5+origin_len+5,
848                                          msglen7));
849             debug("bb.sms.oisd", 0, "OISD[%s]: received raw8=%s ",
850                   octstr_get_cstr(conn->id),
851                   octstr_get_cstr(msg->sms.msgdata));
852         if (add_info & 0x02) {
853             warning(0, "OISD[%s]: 7-bit UDH ?",
854                     octstr_get_cstr(conn->id));
855         } else {
856             charset_gsm_to_utf8(msg->sms.msgdata);
857             debug("bb.sms.oisd", 0, "OISD[%s]: received UTF-8=%s",
858                   octstr_get_cstr(conn->id),
859                   octstr_get_cstr(msg->sms.msgdata));
860         }
861     } else {
862         /* 0xf4, 0xf5, 0xf6, 0xf7; 8bit to disp, mem, sim or term */
863         if (add_info & 0x02) {
864             udh_len = octstr_get_char(request->data,
865                                       11+dest_len+5+origin_len+5)+1;
866             msg->sms.msgdata =
867                 octstr_copy(request->data,
868                             11+dest_len+5+origin_len+5+udh_len,
869                             msglen8);
870             msg->sms.udhdata =
871                 octstr_copy(request->data,
872                             11+dest_len+5+origin_len+5,
873                             udh_len);
874         } else {
875             msg->sms.msgdata =
876                 octstr_copy(request->data,
877                             11+dest_len+5+origin_len+5,
878                             msglen8);
879         }
880     }
881 
882     /* Code elsewhere in the gateway always expects the sender and
883      * receiver fields to be filled, so we discard messages that
884      * lack them.  If they should not be discarded, then the code
885      * handling sms messages should be reviewed.  -- RB */
886     if (!(msg->sms.receiver) || octstr_len(msg->sms.receiver) == 0) {
887         info(0, "OISD[%s]: Got SMS without receiver, discarding.",
888              octstr_get_cstr(conn->id));
889         goto error;
890     }
891 
892     if (!(msg->sms.sender) || octstr_len(msg->sms.sender) == 0) {
893         info(0, "OISD[%s]: Got SMS without sender, discarding.",
894               octstr_get_cstr(conn->id));
895         goto error;
896     }
897 
898     if ((!(msg->sms.msgdata) || octstr_len(msg->sms.msgdata) == 0)
899         && (!(msg->sms.udhdata) || octstr_len(msg->sms.udhdata) == 0)) {
900         msg->sms.msgdata = octstr_create("");
901     }
902 
903     return msg;
904 
905 error:
906     msg_destroy(msg);
907     return NULL;
908 }
909 
910 /* Deal with a request from the OISD server, and acknowledge it. */
oisd_handle_request(struct packet * request,SMSCConn * conn)911 static void oisd_handle_request(struct packet *request, SMSCConn *conn)
912 {
913     PrivData *pdata = conn->data;
914     Msg *msg = NULL;
915 
916     if (request->operation == STATUS_REPORT) {
917         msg = oisd_accept_delivery_report_message(request, conn);
918         if (msg)
919             gwlist_append(pdata->received, msg);
920     } else if (request->operation == DELIVER_SM) {
921         msg = oisd_accept_message(request, conn);
922         if (msg)
923             gwlist_append(pdata->received, msg);
924     }
925 
926     oisd_send_response(request, pdata);
927 }
928 
929 /* Send a request and wait for the ack.  If the other side responds with
930  * an error code, attempt to correct and retry.
931  * If other packets arrive while we wait for the ack, handle them.
932  *
933  * Return -1 if the SMSC refused the request.  Return -2 for other
934  * errors, such as being unable to send the request at all.  If the
935  * function returns -2, the caller would do well to try to reopen the
936  * connection.
937  *
938  * The SMSCenter must be already open.
939  */
oisd_request(struct packet * request,SMSCConn * conn,Octstr ** ts)940 static int oisd_request(struct packet *request, SMSCConn *conn, Octstr **ts)
941 {
942     PrivData *pdata = conn->data;
943     int ret;
944     struct packet *reply = NULL;
945     int errorcode;
946     int tries = 0;
947     Octstr *request_name;
948 
949     gw_assert(pdata != NULL);
950     gw_assert(request != NULL);
951     gw_assert(operation_can_send(request->operation));
952 
953     if (pdata->socket < 0) {
954         warning(0, "OISD[%s]: oisd_request: socket not open.",
955                 octstr_get_cstr(conn->id));
956         return -2;
957     }
958 
959     packet_set_data_size(request);
960 
961 retransmit:
962     packet_set_send_sequence(request, pdata);
963 
964     request_name = operation_name(request->operation);
965     debug("bb.sms.oisd", 0, "OISD[%s]: sending %s request",
966           octstr_get_cstr(conn->id),
967           octstr_get_cstr(request_name));
968     octstr_destroy(request_name);
969     if (request->operation != RETRIEVE_REQUEST)
970         octstr_dump(request->data, 0);
971 
972     ret = octstr_write_to_socket(pdata->socket, request->data);
973     if (ret < 0)
974         goto io_error;
975 
976 next_reply:
977     packet_destroy(reply);  /* destroy old, if any */
978     reply = oisd_get_packet(pdata, ts);
979     if (!reply)
980         goto io_error;
981 
982     /* The server sent us a request.  Handle it, then wait for
983      * a new reply. */
984     if (reply->operation < RESPONSE) {
985         oisd_handle_request(reply, conn);
986         goto next_reply;
987     }
988 
989     if (reply->opref != request->opref) {
990         /* We got a response to a different request number than
991          * what we send.  Strange. */
992         warning(0, "OISD[%s]: response had unexpected sequence number; ignoring.",
993                 octstr_get_cstr(conn->id));
994         goto next_reply;
995     }
996 
997     if (reply->operation != request->operation + RESPONSE) {
998         /* We got a response that didn't match our request */
999         Octstr *request_name = operation_name(request->operation);
1000         Octstr *reply_name = operation_name(reply->operation);
1001         warning(0, "OISD[%s]: %s request got a %s",
1002                 octstr_get_cstr(conn->id),
1003                 octstr_get_cstr(request_name),
1004                 octstr_get_cstr(reply_name));
1005 
1006         octstr_destroy(request_name);
1007         octstr_destroy(reply_name);
1008         octstr_dump(reply->data, 0);
1009         goto retry;
1010     }
1011 
1012     errorcode = octstr_get_char(reply->data, 10); /* Result */
1013 
1014     if (errorcode > 0)
1015         goto error;
1016 
1017     /* The reply passed all the checks... looks like the SMSC accepted
1018      * our request! */
1019     packet_destroy(reply);
1020     return 0;
1021 
1022 io_error:
1023     packet_destroy(reply);
1024     return -2;
1025 
1026 error:
1027     packet_destroy(reply);
1028     return -1;
1029 
1030 retry:
1031     if (++tries < 3) {
1032         warning(0, "OISD[%s]: Retransmitting (take %d)",
1033                 octstr_get_cstr(conn->id),
1034                 tries);
1035         goto retransmit;
1036     }
1037     warning(0, "OISD[%s]: Giving up.",
1038             octstr_get_cstr(conn->id));
1039     goto io_error;
1040 }
1041 
1042 /* Close the SMSC socket without fanfare. */
oisd_close_socket(PrivData * pdata)1043 static void oisd_close_socket(PrivData *pdata)
1044 {
1045     gw_assert(pdata != NULL);
1046 
1047     if (pdata->socket < 0)
1048         return;
1049 
1050     if (close(pdata->socket) < 0)
1051         warning(errno, "OISD[%s]: error closing socket",
1052                 octstr_get_cstr(pdata->conn->id));
1053     pdata->socket = -1;
1054 }
1055 
1056 /*
1057  * Open a socket to the SMSC, send a login packet, and wait for ack.
1058  * This may block.  Return 0 for success, or -1 for failure.
1059  * Make sure the socket is closed before calling this function, otherwise
1060  * we will leak fd's.
1061  */
oisd_login(SMSCConn * conn)1062 static int oisd_login(SMSCConn *conn)
1063 {
1064     PrivData *pdata = conn->data;
1065     struct packet *packet = NULL;
1066 
1067     gw_assert(pdata != NULL);
1068 
1069     if (pdata->socket >= 0) {
1070         warning(0, "OISD[%s]: login: socket was already open; closing",
1071                 octstr_get_cstr(conn->id));
1072         oisd_close_socket(pdata);
1073     }
1074 
1075     pdata->socket = tcpip_connect_to_server(
1076                         octstr_get_cstr(pdata->host),
1077                         pdata->port,
1078                         (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL));
1079     if (pdata->socket != -1) {
1080         info(0, "OISD[%s] logged in.",
1081              octstr_get_cstr(conn->id));
1082         return 0;
1083     }
1084     error(0, "OISD[%s] login failed.",
1085           octstr_get_cstr(conn->id));
1086     oisd_close_socket(pdata);
1087     packet_destroy(packet);
1088     return -1;
1089 }
1090 
oisd_send_delivery_request(SMSCConn * conn)1091 static int oisd_send_delivery_request(SMSCConn *conn)
1092 {
1093     PrivData *pdata = conn->data;
1094     struct packet *packet = NULL;
1095     int ret;
1096 
1097     gw_assert(conn != NULL);
1098 
1099     packet = packet_create(RETRIEVE_REQUEST, BOGUS_SEQUENCE);
1100 
1101     gw_assert(octstr_check_range(pdata->my_number, 0,
1102                                  octstr_len(pdata->my_number),
1103                                  isphonedigit));
1104     /* Originating address length */
1105     octstr_append_char(packet->data,
1106                        (char) (octstr_len(pdata->my_number) + 2));
1107     /* TON */
1108     octstr_append_char(packet->data, 0x42);
1109     /* NPI */
1110     octstr_append_char(packet->data, 0x44);
1111     /* Originating address */
1112     octstr_append(packet->data, pdata->my_number);
1113     /* Receive ready flag */
1114     octstr_append_char(packet->data, 1);
1115     /* Retrieve order */
1116     octstr_append_char(packet->data, 0);
1117 
1118     ret = oisd_request(packet, conn, NULL);
1119     packet_destroy(packet);
1120 
1121     if (ret < 0)
1122         warning(0, "OISD[%s]: Sending delivery request failed.\n",
1123                 octstr_get_cstr(conn->id));
1124 
1125     return ret;
1126 }
1127 
oisd_destroy(PrivData * pdata)1128 static void oisd_destroy(PrivData *pdata)
1129 {
1130     int discarded;
1131 
1132     if (pdata == NULL)
1133         return;
1134 
1135     octstr_destroy(pdata->host);
1136     octstr_destroy(pdata->inbuffer);
1137     octstr_destroy(pdata->my_number);
1138 
1139     discarded = gwlist_len(pdata->received);
1140     if (discarded > 0)
1141         warning(0, "OISD[%s]: discarded %d received messages",
1142                 octstr_get_cstr(pdata->conn->id),
1143                 discarded);
1144 
1145     gwlist_destroy(pdata->received, msg_destroy_item);
1146     gwlist_destroy(pdata->outgoing_queue, NULL);
1147     gwlist_destroy(pdata->stopped, NULL);
1148 
1149     gw_free(pdata);
1150 }
1151 
oisd_submit_msg(SMSCConn * conn,Msg * msg)1152 static int oisd_submit_msg(SMSCConn *conn, Msg *msg)
1153 {
1154     PrivData *pdata = conn->data;
1155     struct packet *packet;
1156     Octstr *ts = NULL;
1157     int ret;
1158 
1159     gw_assert(pdata != NULL);
1160     debug("bb.sms.oisd", 0, "OISD[%s]: sending message",
1161           octstr_get_cstr(conn->id));
1162 
1163     packet = packet_encode_message(msg, conn);
1164     if (!packet) {
1165         /* This is a protocol error. Does this help? I doubt..
1166          * But nevermind that.
1167          */
1168         bb_smscconn_send_failed(conn, msg,
1169                 SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED"));
1170         return -1;
1171     }
1172 
1173     ret = oisd_request(packet, conn, &ts);
1174     if((ret == 0) && (ts) && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask) && !pdata->no_dlr) {
1175         dlr_add(conn->name, ts, msg, 0);
1176     }
1177     octstr_destroy(ts);
1178     packet_destroy(packet);
1179 
1180     if (ret == -1) {
1181         bb_smscconn_send_failed(conn, msg,
1182                 SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED"));
1183     }
1184     else if (ret == -2) {
1185         oisd_close_socket(pdata);
1186         bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL);
1187         mutex_lock(conn->flow_mutex);
1188         conn->status = SMSCCONN_DISCONNECTED;
1189         mutex_unlock(conn->flow_mutex);
1190     }
1191     else {
1192         bb_smscconn_sent(conn, msg, NULL);
1193     }
1194 
1195     return ret;
1196 }
1197 
oisd_receive_msg(SMSCConn * conn,Msg ** msg)1198 static int oisd_receive_msg(SMSCConn *conn, Msg **msg)
1199 {
1200     PrivData *pdata = conn->data;
1201     long ret;
1202     struct packet *packet;
1203 
1204     gw_assert(pdata != NULL);
1205 
1206     if (gwlist_len(pdata->received) > 0) {
1207         *msg = gwlist_consume(pdata->received);
1208         return 1;
1209     }
1210 
1211     if (pdata->socket < 0) {
1212         /* XXX We have to assume that smsc_send_message is
1213          * currently trying to reopen, so we have to make
1214          * this thread wait.  It should be done in a nicer
1215          * way. */
1216         return 0;
1217     }
1218 
1219     ret = read_available(pdata->socket, 0);
1220     if (ret == 0) {
1221         if (pdata->keepalive > 0 && pdata->next_ping < time(NULL)) {
1222             if (oisd_send_delivery_request(conn) < 0)
1223                 return -1;
1224         }
1225         return 0;
1226     }
1227 
1228     if (ret < 0) {
1229         warning(errno, "OISD[%s]: oisd_receive_msg: read_available failed",
1230                 octstr_get_cstr(conn->id));
1231         return -1;
1232     }
1233 
1234     /* We have some data waiting... see if it is an sms delivery. */
1235     ret = octstr_append_from_socket(pdata->inbuffer, pdata->socket);
1236 
1237     if (ret == 0) {
1238         warning(0, "OISD[%s]: oisd_receive_msg: service center closed connection.",
1239                 octstr_get_cstr(conn->id));
1240         return -1;
1241     }
1242     if (ret < 0) {
1243         warning(0, "OISD[%s]: oisd_receive_msg: read failed",
1244                 octstr_get_cstr(conn->id));
1245         return -1;
1246     }
1247 
1248 
1249     for (;;) {
1250         packet = packet_extract(pdata->inbuffer, conn);
1251         if (!packet)
1252             break;
1253 
1254         packet_check_can_receive(packet, conn);
1255         debug("bb.sms.oisd", 0, "OISD[%s]: received",
1256               octstr_get_cstr(pdata->conn->id));
1257         octstr_dump(packet->data, 0);
1258 
1259         if (packet->operation < RESPONSE)
1260             oisd_handle_request(packet, conn);
1261         else {
1262             error(0, "OISD[%s]: oisd_receive_msg: unexpected response packet",
1263                   octstr_get_cstr(conn->id));
1264             octstr_dump(packet->data, 0);
1265         }
1266 
1267         packet_destroy(packet);
1268     }
1269 
1270     if (gwlist_len(pdata->received) > 0) {
1271         *msg = gwlist_consume(pdata->received);
1272         return 1;
1273     }
1274     return 0;
1275 }
1276 
oisd_accept_delivery_report_message(struct packet * request,SMSCConn * conn)1277 static Msg *oisd_accept_delivery_report_message(struct packet *request,
1278                                                 SMSCConn *conn)
1279 {
1280     Msg *msg = NULL;
1281     Octstr *destination = NULL;
1282     Octstr *timestamp = NULL;
1283     int st_code;
1284     int code;
1285     int dest_len;
1286 
1287     /* MSISDN length */
1288     dest_len = octstr_get_char(request->data, 10);
1289     /* MSISDN */
1290     destination = octstr_copy(request->data, 10+1, dest_len);
1291     /* Accept time */
1292     timestamp = octstr_copy(request->data, 10+1+dest_len+1+4+4, 14);
1293     /* SM status */
1294     st_code = octstr_get_char(request->data, 10+1+dest_len+1+4+4+14);
1295 
1296     switch (st_code) {
1297     case 1:
1298     case 2:
1299         code = DLR_FAIL;
1300         break;
1301     case 3:   /* success */
1302         code = DLR_SUCCESS;
1303         break;
1304     case 4:
1305     case 5:
1306     case 6:
1307     default:
1308         code = 0;
1309     }
1310 
1311     if (code)
1312         msg = dlr_find(conn->name, timestamp, destination, code, 0);
1313 
1314     octstr_destroy(destination);
1315     octstr_destroy(timestamp);
1316 
1317     return msg;
1318 }
1319 
sms_receive(SMSCConn * conn)1320 static Msg *sms_receive(SMSCConn *conn)
1321 {
1322     PrivData *pdata = conn->data;
1323     int ret;
1324     Msg *newmsg = NULL;
1325 
1326     ret = oisd_receive_msg(conn, &newmsg);
1327     if (ret == 1) {
1328         /* if any smsc_id available, use it */
1329         newmsg->sms.smsc_id = octstr_duplicate(conn->id);
1330         return newmsg;
1331     }
1332     else if (ret == 0) { /* no message, just retry... */
1333         return NULL;
1334     }
1335     /* error. reconnect. */
1336     msg_destroy(newmsg);
1337     mutex_lock(conn->flow_mutex);
1338     oisd_close_socket(pdata);
1339     conn->status = SMSCCONN_DISCONNECTED;
1340     mutex_unlock(conn->flow_mutex);
1341     return NULL;
1342 }
1343 
io_thread(void * arg)1344 static void io_thread (void *arg)
1345 {
1346     Msg       *msg;
1347     SMSCConn  *conn = arg;
1348     PrivData *pdata = conn->data;
1349     double    sleep = 0.0001;
1350 
1351     /* Make sure we log into our own log-file if defined */
1352     log_thread_to(conn->log_idx);
1353 
1354     /* remove messages from SMSC until we are killed */
1355     while (!pdata->quitting) {
1356 
1357         gwlist_consume(pdata->stopped); /* block here if suspended/isolated */
1358 
1359         /* check that connection is active */
1360         if (conn->status != SMSCCONN_ACTIVE) {
1361             if (oisd_login(conn) != 0) {
1362                 error(0, "OISD[%s]: Couldn't connect to SMSC (retrying in %ld seconds).",
1363                       octstr_get_cstr(conn->id),
1364                       conn->reconnect_delay);
1365                 gwthread_sleep(conn->reconnect_delay);
1366                 mutex_lock(conn->flow_mutex);
1367                 conn->status = SMSCCONN_RECONNECTING;
1368                 mutex_unlock(conn->flow_mutex);
1369                 continue;
1370             }
1371             mutex_lock(conn->flow_mutex);
1372             conn->status = SMSCCONN_ACTIVE;
1373             conn->connect_time = time(NULL);
1374             bb_smscconn_connected(conn);
1375             mutex_unlock(conn->flow_mutex);
1376         }
1377 
1378         /* receive messages */
1379         do {
1380             msg = sms_receive(conn);
1381             if (msg) {
1382                 sleep = 0;
1383                 debug("bb.sms.oisd", 0, "OISD[%s]: new message received",
1384                       octstr_get_cstr(conn->id));
1385                 bb_smscconn_receive(conn, msg);
1386             }
1387         } while (msg);
1388 
1389         /* send messages */
1390         do {
1391             msg = gwlist_extract_first(pdata->outgoing_queue);
1392             if (msg) {
1393                 sleep = 0;
1394                 if (oisd_submit_msg(conn, msg) != 0) break;
1395             }
1396         } while (msg);
1397 
1398         if (sleep > 0) {
1399 
1400             /* note that this implementations means that we sleep even
1401              * when we fail connection.. but time is very short, anyway
1402              */
1403             gwthread_sleep(sleep);
1404             /* gradually sleep longer and longer times until something starts to
1405              * happen - this of course reduces response time, but that's better than
1406              * extensive CPU usage when it is not used
1407              */
1408             sleep *= 2;
1409             if (sleep >= 2.0)
1410                 sleep = 1.999999;
1411         }
1412         else {
1413             sleep = 0.0001;
1414         }
1415     }
1416 }
1417 
oisd_add_msg_cb(SMSCConn * conn,Msg * sms)1418 static int oisd_add_msg_cb (SMSCConn *conn, Msg *sms)
1419 {
1420     PrivData *pdata = conn->data;
1421     Msg *copy;
1422 
1423     copy = msg_duplicate(sms);
1424     gwlist_produce(pdata->outgoing_queue, copy);
1425     gwthread_wakeup(pdata->io_thread);
1426 
1427     return 0;
1428 }
1429 
oisd_shutdown_cb(SMSCConn * conn,int finish_sending)1430 static int oisd_shutdown_cb (SMSCConn *conn, int finish_sending)
1431 {
1432     PrivData *pdata = conn->data;
1433 
1434     debug("bb.sms", 0, "Shutting down SMSCConn OISD %s (%s)",
1435           octstr_get_cstr(conn->id),
1436           finish_sending ? "slow" : "instant");
1437 
1438     /* Documentation claims this would have been done by smscconn.c,
1439        but isn't when this code is being written. */
1440     conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
1441     pdata->quitting = 1;     /* Separate from why_killed to avoid locking, as
1442                               * why_killed may be changed from outside? */
1443 
1444     if (finish_sending == 0) {
1445         Msg *msg;
1446         while ((msg = gwlist_extract_first(pdata->outgoing_queue)) != NULL) {
1447             bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
1448         }
1449     }
1450 
1451     if (conn->is_stopped) {
1452         gwlist_remove_producer(pdata->stopped);
1453         conn->is_stopped = 0;
1454     }
1455 
1456     if (pdata->io_thread != -1) {
1457         gwthread_wakeup(pdata->io_thread);
1458         gwthread_join(pdata->io_thread);
1459     }
1460 
1461     oisd_close_socket(pdata);
1462     oisd_destroy(pdata);
1463 
1464     debug("bb.sms", 0, "SMSCConn OISD %s shut down.",
1465           octstr_get_cstr(conn->id));
1466     conn->status = SMSCCONN_DEAD;
1467     bb_smscconn_killed();
1468     return 0;
1469 }
1470 
oisd_start_cb(SMSCConn * conn)1471 static void oisd_start_cb (SMSCConn *conn)
1472 {
1473     PrivData *pdata = conn->data;
1474 
1475     gwlist_remove_producer(pdata->stopped);
1476     /* in case there are messages in the buffer already */
1477     gwthread_wakeup(pdata->io_thread);
1478     debug("bb.sms", 0, "SMSCConn OISD %s, start called",
1479           octstr_get_cstr(conn->id));
1480 }
1481 
oisd_stop_cb(SMSCConn * conn)1482 static void oisd_stop_cb (SMSCConn *conn)
1483 {
1484     PrivData *pdata = conn->data;
1485     gwlist_add_producer(pdata->stopped);
1486     debug("bb.sms", 0, "SMSCConn OISD %s, stop called",
1487           octstr_get_cstr(conn->id));
1488 }
1489 
oisd_queued_cb(SMSCConn * conn)1490 static long oisd_queued_cb (SMSCConn *conn)
1491 {
1492     PrivData *pdata = conn->data;
1493     conn->load = (pdata ? (conn->status != SMSCCONN_DEAD ?
1494                   gwlist_len(pdata->outgoing_queue) : 0) : 0);
1495     return conn->load;
1496 }
1497 
smsc_oisd_create(SMSCConn * conn,CfgGroup * grp)1498 int smsc_oisd_create(SMSCConn *conn, CfgGroup *grp)
1499 {
1500     PrivData *pdata;
1501     int ok;
1502 
1503     pdata = gw_malloc(sizeof(PrivData));
1504     conn->data = pdata;
1505     pdata->conn = conn;
1506 
1507     pdata->no_dlr = 0;
1508     pdata->quitting = 0;
1509     pdata->socket = -1;
1510     pdata->received = gwlist_create();
1511     pdata->inbuffer = octstr_create("");
1512     pdata->send_seq = 1;
1513     pdata->outgoing_queue = gwlist_create();
1514     pdata->stopped = gwlist_create();
1515     gwlist_add_producer(pdata->outgoing_queue);
1516 
1517     if (conn->is_stopped)
1518         gwlist_add_producer(pdata->stopped);
1519 
1520     pdata->host = cfg_get(grp, octstr_imm("host"));
1521     if (cfg_get_integer(&(pdata->port), grp, octstr_imm("port")) == -1)
1522         pdata->port = 0;
1523     pdata->my_number = cfg_get(grp, octstr_imm("my-number"));
1524     if (cfg_get_integer(&(pdata->keepalive), grp, octstr_imm("keepalive")) == -1)
1525         pdata->keepalive = 0;
1526     if (cfg_get_integer(&(pdata->validityperiod), grp, octstr_imm("validityperiod")) == -1)
1527         pdata->validityperiod = SMS_PARAM_UNDEFINED;
1528 
1529     cfg_get_bool(&pdata->no_dlr, grp, octstr_imm("no-dlr"));
1530 
1531     /* Check that config is OK */
1532     ok = 1;
1533     if (pdata->host == NULL) {
1534         error(0, "OISD[%s]: Configuration file doesn't specify host",
1535               octstr_get_cstr(conn->id));
1536         ok = 0;
1537     }
1538     if (pdata->port == 0) {
1539         error(0, "OISD[%s]: Configuration file doesn't specify port",
1540               octstr_get_cstr(conn->id));
1541         ok = 0;
1542     }
1543     if (pdata->my_number == NULL && pdata->keepalive > 0) {
1544         error(0, "OISD[%s]: Configuration file doesn't specify my-number.",
1545               octstr_get_cstr(conn->id));
1546         ok = 0;
1547     }
1548 
1549     if (!ok) {
1550         oisd_destroy(pdata);
1551         return -1;
1552     }
1553 
1554     conn->name = octstr_format("OISD:%s:%d",
1555                      octstr_get_cstr(pdata->host),
1556                      pdata->port);
1557 
1558 
1559     if (pdata->keepalive > 0) {
1560         debug("bb.sms.oisd", 0, "OISD[%s]: Keepalive set to %ld seconds",
1561               octstr_get_cstr(conn->id),
1562               pdata->keepalive);
1563         pdata->next_ping = time(NULL) + pdata->keepalive;
1564     }
1565 
1566     if (pdata->validityperiod > 0) {
1567         debug("bb.sms.oisd", 0, "OISD[%s]: Validity-Period set to %ld",
1568               octstr_get_cstr(conn->id),
1569               pdata->validityperiod);
1570     }
1571 
1572     pdata->io_thread = gwthread_create(io_thread, conn);
1573 
1574     if (pdata->io_thread == -1) {
1575 
1576         error(0, "OISD[%s]: Couldn't start I/O thread.",
1577               octstr_get_cstr(conn->id));
1578         pdata->quitting = 1;
1579         gwthread_wakeup(pdata->io_thread);
1580         gwthread_join(pdata->io_thread);
1581         oisd_destroy(pdata);
1582         return -1;
1583     }
1584 
1585     conn->send_msg = oisd_add_msg_cb;
1586     conn->shutdown = oisd_shutdown_cb;
1587     conn->queued = oisd_queued_cb;
1588     conn->start_conn = oisd_start_cb;
1589     conn->stop_conn = oisd_stop_cb;
1590 
1591     return 0;
1592 }
1593 
1594