Kannel: Open Source WAP and SMS gateway  svn-r5335
smsc_at.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_at.c
59  *
60  * New driver for serial connected AT based
61  * devices.
62  * 4.9.2001
63  * Andreas Fink <andreas@fink.org>
64 
65  * 23.6.2008, Andreas Fink,
66  * added support for telnet connections
67  * (for example Multi-Tech MTCBA-G-EN-F4)
68  *
69  */
70 
71 #include <errno.h>
72 #include <stdarg.h>
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <unistd.h>
77 #include <fcntl.h>
78 #include <ctype.h>
79 #include <termios.h>
80 #include <sys/time.h>
81 #include <sys/types.h>
82 #include <sys/socket.h>
83 #include <netinet/in.h>
84 #include <netdb.h>
85 #include <sys/ioctl.h>
86 #include <time.h>
87 #include <math.h>
88 
89 #include "gwlib/gwlib.h"
90 #include "gwlib/charset.h"
91 #include "smscconn.h"
92 #include "smscconn_p.h"
93 #include "bb_smscconn_cb.h"
94 #include "msg.h"
95 #include "sms.h"
96 #include "dlr.h"
97 #include "smsc_at.h"
98 #include "load.h"
99 
100 static Octstr *gsm2number(Octstr *pdu);
101 static unsigned char nibble2hex(unsigned char b);
102 
104 {
105  int len;
106  int pos;
107  int start;
108  int a;
109  int b;
110  Octstr *hex;
111 
112  char answer[5];
113 
114 
115  if(!privdata->ilb)
116  return;
117  start = 0;
118  len = octstr_len(privdata->ilb);
119  hex = octstr_duplicate(privdata->ilb);
120  octstr_binary_to_hex(hex,1);
121 
122  octstr_destroy(hex);
123 
124  while(start < len)
125  {
126  pos = octstr_search_char(privdata->ilb, 0xFF, start);
127  if(pos < 0)
128  return;
129  if((len - pos )<3)
130  return;
131  a = octstr_get_char(privdata->ilb,pos+1);
132  b = octstr_get_char(privdata->ilb,pos+2);
133  switch(a)
134  {
135  case 0xFD: /* do! */
136  answer[0] = 0xFF; /* escape */
137  answer[1] = 0xFC; /* wont do any option*/
138  answer[2] = b;
139  write(privdata->fd,&answer,3);
140  octstr_delete(privdata->ilb,pos,3);
141  len -=3;
142  break;
143  break;
144  case 0xFA: /* do you support option b ? */
145  octstr_delete(privdata->ilb,pos,3);
146  len -=3;
147  break;
148  break;
149  case 0xFB: /* will */
150  octstr_delete(privdata->ilb,pos,3);
151  len -=3;
152  break;
153  case 0xFC: /* wont */
154  octstr_delete(privdata->ilb,pos,3);
155  len -=3;
156  break;
157  }
158  start = pos;
159  }
160 
161 }
162 
164 {
165  info(0, "AT2[%s]: opening device", octstr_get_cstr(privdata->name));
166  if (privdata->fd > 0) {
167  warning(0, "AT2[%s]: trying to open device with not closed device!!! Please report!!!",
170  }
171  if (privdata->is_serial) {
172  privdata->fd = open(octstr_get_cstr(privdata->device),
173  O_RDWR | O_NONBLOCK | O_NOCTTY);
174  privdata->use_telnet = 0;
175  } else {
176  if (octstr_str_compare(privdata->device, "rawtcp") == 0) {
177  privdata->use_telnet = 0;
179  privdata->rawtcp_port, NULL);
180  }
181  else if (octstr_str_compare(privdata->device, "telnet") == 0) {
182  privdata->use_telnet = 1;
184  privdata->rawtcp_port, NULL);
185 
186  } else {
187  gw_assert(0);
188  }
189  }
190  if (privdata->fd == -1) {
191  error(errno, "AT2[%s]: open failed! ERRNO=%d", octstr_get_cstr(privdata->name), errno);
192  privdata->fd = -1;
193  return -1;
194  }
195  debug("bb.smsc.at2", 0, "AT2[%s]: device opened. Telnet mode = %d", octstr_get_cstr(privdata->name),privdata->use_telnet);
196 
197  return 0;
198 }
199 
200 
202 {
203  info(0, "AT2[%s]: Logging in", octstr_get_cstr(privdata->name));
204 
206  gwthread_sleep(0.5);
208 
209  if((octstr_len(privdata->username) == 0 ) && (octstr_len(privdata->password)> 0)) {
210  at2_wait_modem_command(privdata, 10, 3, NULL); /* wait for Password: prompt */
212  at2_send_modem_command(privdata, "AT", 2,0); /* wait for OK: */
213  }
214  else if((octstr_len(privdata->username) > 0 ) && (octstr_len(privdata->password)> 0)) {
215  at2_wait_modem_command(privdata, 10, 2, NULL); /* wait for Login: prompt */
216  at2_send_modem_command(privdata, octstr_get_cstr(privdata->username), 10,3); /* wait fo Password: */
218  at2_send_modem_command(privdata, "AT", 2,0); /* wait for OK: */
219  }
220 
221  return 0;
222 }
223 
224 
226 {
227  struct termios tios;
228  int ret;
229 
230  if ((ret = at2_open_device1(privdata)) != 0)
231  return ret;
232 
233  if (!privdata->is_serial)
234  return 0;
235 
236  tcgetattr(privdata->fd, &tios);
237 
238  kannel_cfmakeraw(&tios);
239 
240  tios.c_iflag |= IGNBRK; /* ignore break & parity errors */
241  tios.c_iflag &= ~INPCK; /* INPCK: disable parity check */
242  tios.c_cflag |= HUPCL; /* hangup on close */
243  tios.c_cflag |= CREAD; /* enable receiver */
244  tios.c_cflag |= CLOCAL; /* Ignore modem control lines */
245  tios.c_cflag &= ~CSIZE; /* set to 8 bit */
246  tios.c_cflag |= CS8;
247  tios.c_oflag &= ~ONLCR; /* no NL to CR-NL mapping outgoing */
248  tios.c_iflag |= IGNPAR; /* ignore parity */
249  tios.c_iflag &= ~INPCK;
250 #if defined(CRTSCTS)
251  if(privdata->modem) {
252  if(privdata->modem->hardware_flow_control) {
253  tios.c_cflag |= CRTSCTS; /* enable hardware flow control */
254  }
255  else {
256  tios.c_cflag &= ~CRTSCTS; /* disable hardware flow control */
257  }
258  }
259  else {
260  tios.c_cflag &= ~CRTSCTS; /* disable hardware flow control */
261  }
262 #endif
263  tios.c_cc[VSUSP] = 0; /* otherwhise we can not send CTRL Z */
264 
265  /*
266  if ( ModemTypes[privdata->modemid].enable_parity )
267  tios.c_cflag ^= PARODD;
268  */
269 
270  ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */
271  if (ret == -1) {
272  error(errno, "AT2[%s]: at_data_link: fail to set termios attribute",
274  }
275  tcflush(privdata->fd, TCIOFLUSH);
276 
277  /*
278  * Nokia 7110 and 6210 need some time between opening
279  * the connection and sending the first AT commands
280  */
281  if (privdata->modem == NULL || privdata->modem->need_sleep)
282  sleep(1);
283  debug("bb.smsc.at2", 0, "AT2[%s]: device opened", octstr_get_cstr(privdata->name));
284  return 0;
285 }
286 
287 
289 {
290  info(0, "AT2[%s]: Closing device", octstr_get_cstr(privdata->name));
291  if (privdata->fd != -1)
292  close(privdata->fd);
293  privdata->fd = -1;
294  privdata->pin_ready = 0;
295  privdata->phase2plus = 0;
296  if (privdata->ilb != NULL)
297  octstr_destroy(privdata->ilb);
298  privdata->ilb = octstr_create("");
299 }
300 
301 
302 static void at2_read_buffer(PrivAT2data *privdata, double timeout)
303 {
304  char buf[MAX_READ + 1];
305  int ret;
306  size_t count;
307  signed int s;
308  fd_set read_fd;
309  struct timeval tv;
310 
311  if (privdata->fd == -1) {
312  error(errno, "AT2[%s]: at2_read_buffer: fd = -1. Can not read",
314  return;
315  }
316  count = MAX_READ;
317 
318 #ifdef SSIZE_MAX
319  if (count > SSIZE_MAX)
320  count = SSIZE_MAX;
321 #endif
322 
323  if (timeout <= 0) {
324  tv.tv_sec = 0;
325  tv.tv_usec = 1000;
326  } else {
327  int usecs = timeout * 1000000;
328  tv.tv_sec = usecs / 1000000;
329  tv.tv_usec = usecs % 1000000;
330  }
331 
332  FD_ZERO(&read_fd);
333  FD_SET(privdata->fd, &read_fd);
334  ret = select(privdata->fd + 1, &read_fd, NULL, NULL, &tv);
335  if (ret == -1) {
336  if (!(errno == EINTR || errno == EAGAIN))
337  error(errno, "AT2[%s]: error on select", octstr_get_cstr(privdata->name));
338  return;
339  }
340 
341  if (ret == 0)
342  return;
343 
344  s = read(privdata->fd, buf, count);
345  if (s < 0) {
346  error(errno, "AT2[%s]: at2_read_buffer: Error during read",
349  } else {
350  octstr_append_data(privdata->ilb, buf, s);
351  if(privdata->use_telnet)
353  }
354 }
355 
356 
357 static Octstr *at2_wait_line(PrivAT2data *privdata, time_t timeout, int gt_flag)
358 {
359  Octstr *line;
360  time_t end_time;
361  time_t cur_time;
362 
363  if (timeout == 0)
364  timeout = 3;
365  end_time = time(NULL) + timeout;
366 
367  if (privdata->lines != NULL)
368  octstr_destroy(privdata->lines);
369  privdata->lines = octstr_create("");
370  while (time(&cur_time) <= end_time) {
371  line = at2_read_line(privdata, gt_flag, timeout);
372  if (line)
373  return line;
374  }
375  return NULL;
376 }
377 
378 
380 {
381  int eol;
382  int gtloc;
383  int len;
384  Octstr *line;
385  Octstr *buf2;
386  int i;
387 
388  len = octstr_len(privdata->ilb);
389  if (len == 0)
390  return NULL;
391 
392  if (gt_flag==1) {
393  /* looking for > if needed */
394  gtloc = octstr_search_char(privdata->ilb, '>', 0);
395  } else if((gt_flag == 2) && (privdata->username)) { /* looking for "Login" */
396  gtloc = -1;
397  if(privdata->login_prompt) {
398  gtloc = octstr_search(privdata->ilb,privdata->login_prompt,0);
399  }
400  if(gtloc == -1) {
401  gtloc = octstr_search(privdata->ilb,octstr_imm("Login:"),0);
402  }
403  if(gtloc == -1) {
404  gtloc = octstr_search(privdata->ilb,octstr_imm("Username:"),0);
405  }
406  } else if ((gt_flag == 3) && (privdata->password)) {/* looking for Password */
407  gtloc = -1;
408  if(privdata->password_prompt) {
409  gtloc = octstr_search(privdata->ilb,privdata->password_prompt,0);
410  }
411  if(gtloc == -1) {
412  gtloc = octstr_search(privdata->ilb,octstr_imm("Password:"),0);
413  }
414  } else
415  gtloc = -1;
416 
417  /*
418  if (gt_flag && (gtloc != -1))
419  debug("bb.smsc.at2", 0, "in at2_read_line with gt_flag=1, gtloc=%d, ilb=%s",
420  gtloc, octstr_get_cstr(privdata->ilb));
421  */
422 
423  eol = octstr_search_char(privdata->ilb, '\r', 0); /* looking for CR */
424 
425  if ((gtloc != -1) && ((eol == -1) || (eol > gtloc)))
426  eol = gtloc;
427 
428  if (eol == -1)
429  return NULL;
430 
431  line = octstr_copy(privdata->ilb, 0, eol);
432  buf2 = octstr_copy(privdata->ilb, eol + 1, len);
433  octstr_destroy(privdata->ilb);
434  privdata->ilb = buf2;
435 
436  /* remove any non printable chars (including linefeed for example) */
437  for (i = 0; i < octstr_len(line); i++) {
438  if (octstr_get_char(line, i) < 32)
439  octstr_set_char(line, i, ' ');
440  }
441  octstr_strip_blanks(line);
442 
443  /* empty line, skipping */
444  if (octstr_len(line) == 0 && (gt_flag == 0)) {
445  return line;
446  }
447  if ((gt_flag) && (gtloc != -1)) {
448  /* got to re-add it again as the parser needs to see it */
449  octstr_append_cstr(line, ">");
450  }
451  debug("bb.smsc.at2", 0, "AT2[%s]: <-- %s", octstr_get_cstr(privdata->name),
452  octstr_get_cstr(line));
453  return line;
454 }
455 
456 
457 static Octstr *at2_read_line(PrivAT2data *privdata, int gt_flag, double timeout)
458 {
459  Octstr *line;
460 
461  line = at2_extract_line(privdata, gt_flag);
462  if (!line) {
463  at2_read_buffer(privdata, timeout);
464  line = at2_extract_line(privdata, gt_flag);
465  }
466  return line;
467 }
468 
469 
470 static int at2_write_line(PrivAT2data *privdata, char *line)
471 {
472  int count;
473  int s = 0;
474  int write_count = 0, data_written = 0;
475  Octstr *linestr = NULL;
476 
477  linestr = octstr_format("%s\r", line);
478 
479  debug("bb.smsc.at2", 0, "AT2[%s]: --> %s^M", octstr_get_cstr(privdata->name), line);
480 
481  count = octstr_len(linestr);
482  while (count > data_written) {
483  errno = 0;
484  s = write(privdata->fd, octstr_get_cstr(linestr) + data_written,
485  count - data_written);
486  if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
487  gwthread_sleep(1);
488  ++write_count;
489  } else if (s > 0) {
490  data_written += s;
491  write_count = 0;
492  } else
493  break;
494  }
495  O_DESTROY(linestr);
496  if (s < 0) {
497  error(errno, "AT2[%s]: Couldnot write to device.",
499  tcflush(privdata->fd, TCOFLUSH);
500  return s;
501  }
502  tcdrain(privdata->fd);
503  gwthread_sleep((double) (privdata->modem == NULL ?
504  100 : privdata->modem->sendline_sleep) / 1000);
505  return s;
506 }
507 
508 
510 {
511  int s;
512  char *ctrlz = "\032" ;
513  int write_count = 0;
514 
515  debug("bb.smsc.at2", 0, "AT2[%s]: --> ^Z", octstr_get_cstr(privdata->name));
516  while (1) {
517  errno = 0;
518  s = write(privdata->fd, ctrlz, 1);
519  if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
520  gwthread_sleep(1);
521  ++write_count;
522  } else
523  break;
524  }
525  if (s < 0) {
526  error(errno, "AT2[%s]: Couldnot write to device.",
528  tcflush(privdata->fd, TCOFLUSH);
529  return s;
530  }
531  tcdrain(privdata->fd);
532  gwthread_sleep((double) (privdata->modem == NULL ?
533  100 : privdata->modem->sendline_sleep) / 1000);
534  return s;
535 }
536 
537 
538 static int at2_write(PrivAT2data *privdata, char *line)
539 {
540  int count, data_written = 0, write_count = 0;
541  int s = 0;
542 
543  debug("bb.smsc.at2", 0, "AT2[%s]: --> %s", octstr_get_cstr(privdata->name), line);
544 
545  count = strlen(line);
546  while(count > data_written) {
547  s = write(privdata->fd, line + data_written, count - data_written);
548  if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
549  gwthread_sleep(1);
550  ++write_count;
551  } else if (s > 0) {
552  data_written += s;
553  write_count = 0;
554  } else
555  break;
556  }
557 
558  if (s < 0) {
559  error(errno, "AT2[%s]: Couldnot write to device.",
561  tcflush(privdata->fd, TCOFLUSH);
562  return s;
563  }
564  tcdrain(privdata->fd);
565  gwthread_sleep((double) (privdata->modem == NULL ?
566  100 : privdata->modem->sendline_sleep) / 1000);
567  return s;
568 }
569 
570 
572 {
574  octstr_destroy(privdata->ilb);
575  privdata->ilb = octstr_create("");
576 }
577 
578 
580 {
581  int ret;
582  Octstr *setpin;
583 
584  info(0, "AT2[%s]: init device", octstr_get_cstr(privdata->name));
585 
587  /* sleep 10 ms in order to get device some time to accept speed */
588  gwthread_sleep(0.1);
589 
590  /* reset the modem */
591  if (at2_send_modem_command(privdata, "ATZ", 0, 0) == -1) {
592  error(0, "AT2[%s]: Wrong or no answer to ATZ, ignoring",
594  return -1;
595  }
596 
597  /* check if the modem responded */
598  if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
599  error(0, "AT2[%s]: Wrong or no answer to AT. Trying again",
601  if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
602  error(0, "AT2[%s]: Second attempt to send AT failed",
604  return -1;
605  }
606  }
607 
609 
610  if (at2_send_modem_command(privdata, "AT&F", 7, 0) == -1) {
611  error(0, "AT2[%s]: No answer to AT&F. Trying again",
613  if (at2_send_modem_command(privdata, "AT&F", 7, 0) == -1) {
614  return -1;
615  }
616  }
617 
619 
620  /* check if the modem responded */
621  if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) {
622  error(0, "AT2[%s]: Wrong or no answer to ATE0. Trying again",
624  if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) {
625  error(0, "AT2[%s]: Second attempt to send ATE0 failed",
627  return -1;
628  }
629  }
630 
632 
633 
634  /* enable hardware handshake */
635  if (octstr_len(privdata->modem->enable_hwhs)) {
637  octstr_get_cstr(privdata->modem->enable_hwhs), 0, 0) == -1)
638  info(0, "AT2[%s]: cannot enable hardware handshake",
640  }
641 
642  /*
643  * Check does the modem require a PIN and, if so, send it.
644  * This is not supported by the Nokia Premicell
645  */
646  if (!privdata->modem->no_pin) {
647  ret = at2_send_modem_command(privdata, "AT+CPIN?", 10, 0);
648 
649  if (!privdata->pin_ready) {
650  if (ret == 2) {
651  if (privdata->pin == NULL)
652  return -1;
653  setpin = octstr_format("AT+CPIN=\"%s\"", octstr_get_cstr(privdata->pin));
654  ret = at2_send_modem_command(privdata, octstr_get_cstr(setpin), 0, 0);
655  octstr_destroy(setpin);
656  if (ret != 0 )
657  return -1;
658  } else if (ret == -1)
659  return -1;
660  }
661 
662  /*
663  * we have to wait until +CPIN: READY appears before issuing
664  * the next command. 10 sec should be suficient
665  */
666  if (!privdata->pin_ready) {
667  at2_wait_modem_command(privdata, 10, 0, NULL);
668  if (!privdata->pin_ready) {
669  at2_send_modem_command(privdata, "AT+CPIN?", 10, 0);
670  if (!privdata->pin_ready) {
671  return -1; /* give up */
672  }
673  }
674  }
675  }
676  /*
677  * Set the GSM SMS message center address if supplied
678  */
679  if (octstr_len(privdata->sms_center)) {
680  Octstr *temp;
681  temp = octstr_create("AT+CSCA=");
682  octstr_append_char(temp, 34);
683  octstr_append(temp, privdata->sms_center);
684  octstr_append_char(temp, 34);
685  /*
686  * XXX If some modem don't process the +, remove it and add ",145"
687  * and ",129" to national numbers
688  */
689  ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0);
690  octstr_destroy(temp);
691  if (ret == -1)
692  return -1;
693  if (ret > 0) {
694  info(0, "AT2[%s]: Cannot set SMS message center, continuing",
696  }
697  }
698 
699  /* Set the modem to PDU mode and autodisplay of new messages */
700  ret = at2_send_modem_command(privdata, "AT+CMGF=0", 0, 0);
701  if (ret != 0 )
702  return -1;
703 
704  /* lets see if it supports GSM SMS 2+ mode */
705  ret = at2_send_modem_command(privdata, "AT+CSMS=?", 0, 0);
706  if (ret != 0) {
707  /* if it doesnt even understand the command, I'm sure it wont support it */
708  privdata->phase2plus = 0;
709  } else {
710  /* we have to take a part a string like +CSMS: (0,1,128) */
711  Octstr *ts;
712  int i;
713  List *vals;
714 
715  ts = privdata->lines;
716  privdata->lines = NULL;
717 
718  i = octstr_search_char(ts, '(', 0);
719  if (i > 0) {
720  octstr_delete(ts, 0, i + 1);
721  }
722  i = octstr_search_char(ts, ')', 0);
723  if (i > 0) {
724  octstr_truncate(ts, i);
725  }
726  vals = octstr_split(ts, octstr_imm(","));
727  octstr_destroy(ts);
728  ts = gwlist_search(vals, octstr_imm("1"), (void*) octstr_item_match);
729  if (ts)
730  privdata->phase2plus = 1;
732  }
733  if (privdata->phase2plus) {
734  info(0, "AT2[%s]: Phase 2+ is supported", octstr_get_cstr(privdata->name));
735  ret = at2_send_modem_command(privdata, "AT+CSMS=1", 0, 0);
736  if (ret != 0)
737  return -1;
738  }
739 
740  /* send init string */
741  ret = at2_send_modem_command(privdata, octstr_get_cstr(privdata->modem->init_string), 0, 0);
742  if (ret != 0)
743  return -1;
744 
745  if (privdata->sms_memory_poll_interval && privdata->modem->message_storage) {
746  /* set message storage location for "SIM buffering" using the CPMS command */
747  if (at2_set_message_storage(privdata, privdata->modem->message_storage) != 0)
748  return -1;
749  }
750 
751  info(0, "AT2[%s]: AT SMSC successfully opened.", octstr_get_cstr(privdata->name));
752  return 0;
753 }
754 
755 
756 static int at2_send_modem_command(PrivAT2data *privdata, char *cmd, time_t timeout, int gt_flag)
757 {
758  if (at2_write_line(privdata, cmd) == -1)
759  return -1;
760  return at2_wait_modem_command(privdata, timeout, gt_flag, NULL);
761 }
762 
763 
764 static int at2_wait_modem_command(PrivAT2data *privdata, time_t timeout, int gt_flag, int *output)
765 {
766  Octstr *line = NULL;
767  Octstr *line2 = NULL;
768  Octstr *pdu = NULL;
769  Octstr *smsc_number = NULL;
770  int ret;
771  time_t end_time;
772  time_t cur_time;
773  Msg *msg;
774  int cmgr_flag = 0;
775 
776  if (!timeout)
777  timeout = 3;
778  end_time = time(NULL) + timeout;
779 
780  if (privdata->lines != NULL)
781  octstr_destroy(privdata->lines);
782  privdata->lines = octstr_create("");
783 
784  smsc_number = octstr_create("");
785  while (privdata->fd != -1 && time(&cur_time) <= end_time) {
786  O_DESTROY(line);
787  if ((line = at2_read_line(privdata, gt_flag, timeout))) {
788  octstr_append(privdata->lines, line);
789  octstr_append_cstr(privdata->lines, "\n");
790 
791  if (octstr_search(line, octstr_imm("SIM PIN"), 0) != -1) {
792  ret = 2;
793  goto end;
794  }
795  if (octstr_search(line, octstr_imm("OK"), 0) != -1) {
796  ret = 0;
797  goto end;
798  }
799  if ((gt_flag ) && (octstr_search(line, octstr_imm(">"), 0) != -1)) {
800  ret = 1;
801  goto end;
802  }
803  if (octstr_search(line, octstr_imm("RING"), 0) != -1) {
804  at2_write_line(privdata, "ATH0");
805  continue;
806  }
807  if (octstr_search(line, octstr_imm("+CPIN: READY"), 0) != -1) {
808  privdata->pin_ready = 1;
809  ret = 3;
810  goto end;
811  }
812  if (octstr_search(line, octstr_imm("+CMS ERROR"), 0) != -1) {
813  int errcode;
814  error(0, "AT2[%s]: +CMS ERROR: %s", octstr_get_cstr(privdata->name),
815  octstr_get_cstr(line));
816  if (sscanf(octstr_get_cstr(line), "+CMS ERROR: %d", &errcode) == 1)
817  error(0, "AT2[%s]: +CMS ERROR: %s (%d)", octstr_get_cstr(privdata->name),
818  at2_error_string(errcode), errcode);
819  ret = 1;
820  goto end;
821  } else if (octstr_search(line, octstr_imm("+CME ERROR"), 0) != -1) {
822  int errcode;
823  error(0, "AT2[%s]: +CME ERROR: %s", octstr_get_cstr(privdata->name),
824  octstr_get_cstr(line));
825  if (sscanf(octstr_get_cstr(line), "+CME ERROR: %d", &errcode) == 1)
826  error(0, "AT2[%s]: +CME ERROR: %s (%d)", octstr_get_cstr(privdata->name),
827  at2_error_string(errcode), errcode);
828  ret = 1;
829  goto end;
830  }
831  if (octstr_search(line, octstr_imm("+CMTI:"), 0) != -1 ||
832  octstr_search(line, octstr_imm("+CDSI:"), 0) != -1) {
833  /*
834  * we received an incoming message indication
835  * put it in the pending_incoming_messages queue for later retrieval
836  */
837  debug("bb.smsc.at2", 0, "AT2[%s]: +CMTI incoming SMS indication: %s",
839  gwlist_append(privdata->pending_incoming_messages, line);
840  line = NULL;
841  continue;
842  }
843  if (octstr_search(line, octstr_imm("+CMT:"), 0) != -1 ||
844  octstr_search(line, octstr_imm("+CDS:"), 0) != -1 ||
845  ((octstr_search(line, octstr_imm("+CMGR:"), 0) != -1) && (cmgr_flag = 1)) ) {
846  line2 = at2_wait_line(privdata, 1, 0);
847 
848  if (line2 == NULL) {
849  error(0, "AT2[%s]: got +CMT but waiting for next line timed out",
851  } else {
852  octstr_append_cstr(line, "\n");
853  octstr_append(line, line2);
854  O_DESTROY(line2);
855  at2_pdu_extract(privdata, &pdu, line, smsc_number);
856  if (pdu == NULL) {
857  error(0, "AT2[%s]: got +CMT but pdu_extract failed",
859  } else {
860  /* count message even if I can't decode it */
861  if (output)
862  ++(*output);
863  msg = at2_pdu_decode(pdu, privdata);
864  if (msg != NULL) {
865  octstr_destroy(msg->sms.smsc_id);
866  octstr_destroy(msg->sms.smsc_number);
867  msg->sms.smsc_id = octstr_duplicate(privdata->conn->id);
868  msg->sms.smsc_number = octstr_duplicate(smsc_number);
870  } else {
871  error(0, "AT2[%s]: could not decode PDU to a message.",
873  }
874 
875  if (!cmgr_flag) {
876  if (privdata->phase2plus) {
877  at2_send_modem_command(privdata, "AT+CNMA", 3, 0);
878  }
879  }
880 
881  O_DESTROY(pdu);
882  }
883  }
884  continue;
885  }
886  if ((octstr_search(line, octstr_imm("+CMGS:"),0) != -1) && (output)) {
887  /*
888  * found response to a +CMGS command, read the message id
889  * and return it in output
890  */
891  long temp;
892  if (octstr_parse_long(&temp, line, octstr_search(line, octstr_imm("+CMGS:"), 0) + 6, 10) == -1)
893  error(0, "AT2[%s]: Got +CMGS but failed to read message id",
895  else
896  *output = temp;
897  }
898  /* finally check if we received a generic error */
899  if (octstr_search(line, octstr_imm("ERROR"), 0) != -1) {
900  int errcode;
901  error(0, "AT2[%s]: Generic error: %s", octstr_get_cstr(privdata->name),
902  octstr_get_cstr(line));
903  if (sscanf(octstr_get_cstr(line), "ERROR: %d", &errcode) == 1)
904  error(0, "AT2[%s]: Generic error: %s (%d)", octstr_get_cstr(privdata->name),
905  at2_error_string(errcode), errcode);
906  ret = -1;
907  goto end;
908  }
909  }
910  }
911 
912  /*
913  error(0,"AT2[%s]: timeout. received <%s> until now, buffer size is %d, buf=%s",
914  octstr_get_cstr(privdata->name),
915  privdata->lines ? octstr_get_cstr(privdata->lines) : "<nothing>", len,
916  privdata->ilb ? octstr_get_cstr(privdata->ilb) : "<nothing>");
917  */
918  O_DESTROY(line);
919  O_DESTROY(line2);
920  O_DESTROY(pdu);
921  O_DESTROY(smsc_number);
922  return -1; /* timeout */
923 
924 end:
925  O_DESTROY(smsc_number);
926  octstr_append(privdata->lines, line);
927  octstr_append_cstr(privdata->lines, "\n");
928  O_DESTROY(line);
929  O_DESTROY(line2);
930  O_DESTROY(pdu);
931  return ret;
932 }
933 
934 
935 static int at2_read_delete_message(PrivAT2data* privdata, int message_number)
936 {
937  char cmd[20];
938  int message_count = 0;
939 
940  sprintf(cmd, "AT+CMGR=%d", message_number);
941  /* read one message from memory */
942  at2_write_line(privdata, cmd);
943  if (at2_wait_modem_command(privdata, 0, 0, &message_count) != 0) {
944  debug("bb.smsc.at2", 0, "AT2[%s]: failed to get message %d.",
945  octstr_get_cstr(privdata->name), message_number);
946  return 0; /* failed to read the message - skip to next message */
947  }
948 
949  /* no need to delete if no message collected */
950  if (!message_count) {
951  debug("bb.smsc.at2", 0, "AT2[%s]: not deleted.",
953  return 0;
954  }
955 
956  sprintf(cmd, "AT+CMGD=%d", message_number); /* delete the message we just read */
957  /*
958  * 3 seconds (default timeout of send_modem_command()) is not enough with some
959  * modems if the message is large, so we'll give it 7 seconds
960  */
961  if (at2_send_modem_command(privdata, cmd, 7, 0) != 0) {
962  /*
963  * failed to delete the message, we'll just ignore it for now,
964  * this is bad, since if the message really didn't get deleted
965  * we'll see it next time around.
966  */
967  error(2, "AT2[%s]: failed to delete message %d.",
968  octstr_get_cstr(privdata->name), message_number);
969  }
970 
971  return 1;
972 }
973 
974 
975 /*
976  * This function loops through the pending_incoming_messages queue for CMTI
977  * notifications.
978  * Every notification is parsed and the messages are read (and deleted)
979  * accordingly.
980 */
982 {
983  Octstr *current_storage = NULL;
984 
985  if (privdata->modem->message_storage) {
986  current_storage = octstr_duplicate(privdata->modem->message_storage);
987  }
988  while (gwlist_len(privdata->pending_incoming_messages) > 0) {
989  int pos;
990  long location;
991  Octstr *cmti_storage = NULL, *line = NULL;
992 
993  line = gwlist_extract_first(privdata->pending_incoming_messages);
994  /* message memory starts after the first quote in the string */
995  if ((pos = octstr_search_char(line, '"', 0)) != -1) {
996  /* grab memory storage name */
997  int next_quote = octstr_search_char(line, '"', ++pos);
998  if (next_quote == -1) { /* no second qoute - this line must be broken somehow */
999  O_DESTROY(line);
1000  continue;
1001  }
1002 
1003  /* store notification storage location for reference */
1004  cmti_storage = octstr_copy(line, pos, next_quote - pos);
1005  } else
1006  /* reset pos for the next lookup which would start from the beginning if no memory
1007  * location was found */
1008  pos = 0;
1009 
1010  /* if no message storage is set in configuration - set now */
1011  if (!privdata->modem->message_storage && cmti_storage) {
1012  info(2, "AT2[%s]: CMTI received, but no message-storage is set in confiuration."
1013  "setting now to <%s>", octstr_get_cstr(privdata->name), octstr_get_cstr(cmti_storage));
1014  privdata->modem->message_storage = octstr_duplicate(cmti_storage);
1015  current_storage = octstr_duplicate(cmti_storage);
1016  at2_set_message_storage(privdata, cmti_storage);
1017  }
1018 
1019  /* find the message id from the line, which should appear after the first comma */
1020  if ((pos = octstr_search_char(line, ',', pos)) == -1) { /* this CMTI notification is probably broken */
1021  error(2, "AT2[%s]: failed to find memory location in CMTI notification",
1023  O_DESTROY(line);
1024  octstr_destroy(cmti_storage);
1025  continue;
1026  }
1027 
1028  if ((pos = octstr_parse_long(&location, line, ++pos, 10)) == -1) {
1029  /* there was an error parsing the message id. next! */
1030  error(2, "AT2[%s]: error parsing memory location in CMTI notification",
1032  O_DESTROY(line);
1033  octstr_destroy(cmti_storage);
1034  continue;
1035  }
1036 
1037  /* check if we need to change storage location before issuing the read command */
1038  if (!current_storage || (octstr_compare(current_storage, cmti_storage) != 0)) {
1039  octstr_destroy(current_storage);
1040  current_storage = octstr_duplicate(cmti_storage);
1041  at2_set_message_storage(privdata, cmti_storage);
1042  }
1043 
1045  error(1, "AT2[%s]: CMTI notification received, but no message found in memory!",
1047  }
1048 
1049  octstr_destroy(line);
1050  octstr_destroy(cmti_storage);
1051  }
1052 
1053  /* set prefered message storage back to what configured */
1054  if (current_storage && privdata->modem->message_storage
1055  && (octstr_compare(privdata->modem->message_storage, current_storage) != 0))
1056  at2_set_message_storage(privdata, privdata->modem->message_storage);
1057 
1058  octstr_destroy(current_storage);
1059 }
1060 
1061 
1063 {
1064  /* get memory status */
1065  if (at2_check_sms_memory(privdata) == -1) {
1066  debug("bb.smsc.at2", 0, "AT2[%s]: memory check error", octstr_get_cstr(privdata->name));
1067  return -1;
1068  }
1069 
1070  if (privdata->sms_memory_usage) {
1071  /*
1072  * that is - greater then 0, meaning there are some messages to fetch
1073  * now - I used to just loop over the first input_mem_sms_used locations,
1074  * but it doesn't hold, since under load, messages may be received while
1075  * we're in the loop, and get stored in locations towards the end of the list,
1076  * thus creating 'holes' in the memory.
1077  *
1078  * There are two ways we can fix this :
1079  * (a) Just read the last message location, delete it and return.
1080  * It's not a complete solution since holes can still be created if messages
1081  * are received between the memory check and the delete command,
1082  * and anyway - it will slow us down and won't hold well under pressure
1083  * (b) Just scan the entire memory each call, bottom to top.
1084  * This will be slow too, but it'll be reliable.
1085  *
1086  * We can massivly improve performance by stopping after input_mem_sms_used messages
1087  * have been read, but send_modem_command returns 0 for no message as well as for a
1088  * message read, and the only other way to implement it is by doing memory_check
1089  * after each read and stoping when input_mem_sms_used get to 0. This is slow
1090  * (modem commands take time) so we improve speed only if there are less then 10
1091  * messages in memory.
1092  *
1093  * I implemented the alternative - changed at2_wait_modem_command to return the
1094  * number of messages it collected.
1095  */
1096  int i;
1097  int message_count = 0; /* cound number of messages collected */
1098  ModemDef *modem = privdata->modem;
1099 
1100  debug("bb.smsc.at2", 0, "AT2[%s]: %d messages waiting in memory",
1101  octstr_get_cstr(privdata->name), privdata->sms_memory_usage);
1102 
1103  /*
1104  * loop till end of memory or collected enouch messages
1105  */
1106  for (i = modem->message_start; i < (privdata->sms_memory_capacity + modem->message_start) && message_count < privdata->sms_memory_usage; ++i) {
1107 
1108  /* if (meanwhile) there are pending CMTI notifications, process these first
1109  * to not let CMTI and sim buffering sit in each others way */
1110  while (gwlist_len(privdata->pending_incoming_messages) > 0) {
1112  }
1113  /* read the message and delete it */
1114  message_count += at2_read_delete_message(privdata, i);
1115  }
1116  }
1117 
1118  /*
1119  at2_send_modem_command(privdata, ModemTypes[privdata->modemid].init1, 0, 0);
1120  */
1121  return 0;
1122 }
1123 
1124 
1126 {
1127  long values[4]; /* array to put response data in */
1128  int pos; /* position of parser in data stream */
1129  int ret;
1130  Octstr *search_cpms = NULL;
1131 
1132  /* select memory type and get report */
1133  if ((ret = at2_send_modem_command(privdata, "AT+CPMS?", 0, 0)) != 0) {
1134  debug("bb.smsc.at2.memory_check", 0, "failed to send mem select command to modem %d", ret);
1135  return -1;
1136  }
1137 
1138  search_cpms = octstr_create("+CPMS:");
1139 
1140  if ((pos = octstr_search(privdata->lines, search_cpms, 0)) != -1) {
1141  /* got back a +CPMS response */
1142  int index = 0; /* index in values array */
1143  pos += 6; /* position of parser in the stream - start after header */
1144 
1145  /* skip memory indication */
1146  pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1;
1147 
1148  /* find all the values */
1149  while (index < 4 && pos < octstr_len(privdata->lines) &&
1150  (pos = octstr_parse_long(&values[index], privdata->lines, pos, 10)) != -1) {
1151  ++pos; /* skip number seperator */
1152  ++index; /* increment array index */
1153  if (index == 2)
1154  /* skip second memory indication */
1155  pos = octstr_search(privdata->lines, octstr_imm(","), pos) + 1;
1156  }
1157 
1158  if (index < 4) {
1159  /* didn't get all memory data - I don't why, so I'll bail */
1160  debug("bb.smsc.at2", 0, "AT2[%s]: couldn't parse all memory locations : %d:'%s'.",
1161  octstr_get_cstr(privdata->name), index,
1162  &(octstr_get_cstr(privdata->lines)[pos]));
1163  O_DESTROY(search_cpms);
1164  return -1;
1165  }
1166 
1167  privdata->sms_memory_usage = values[0];
1168  privdata->sms_memory_capacity = values[1];
1169  /*
1170  privdata->output_mem_sms_used = values[2];
1171  privdata->output_mem_sms_capacity = values[3];
1172  */
1173 
1174  /* everything's cool */
1175  ret = 0;
1176 
1177  /* clear the buffer */
1178  O_DESTROY(privdata->lines);
1179 
1180  } else {
1181  debug("bb.smsc.at2", 0, "AT2[%s]: no correct header for CPMS response.",
1183 
1184  /* didn't get a +CPMS response - this is clearly an error */
1185  ret = -1;
1186  }
1187 
1188  O_DESTROY(search_cpms);
1189  return ret;
1190 }
1191 
1192 
1193 static void at2_set_speed(PrivAT2data *privdata, int bps)
1194 {
1195  struct termios tios;
1196  int ret;
1197  int speed;
1198 
1199  if (!privdata->is_serial)
1200  return;
1201 
1202  tcgetattr(privdata->fd, &tios);
1203 
1204  switch (bps) {
1205  case 300:
1206  speed = B300;
1207  break;
1208  case 1200:
1209  speed = B1200;
1210  break;
1211  case 2400:
1212  speed = B2400;
1213  break;
1214  case 4800:
1215  speed = B4800;
1216  break;
1217  case 9600:
1218  speed = B9600;
1219  break;
1220  case 19200:
1221  speed = B19200;
1222  break;
1223  case 38400:
1224  speed = B38400;
1225  break;
1226 #ifdef B57600
1227  case 57600:
1228  speed = B57600;
1229  break;
1230 #endif
1231 #ifdef B115200
1232  case 115200:
1233  speed = B115200;
1234  break;
1235 #endif
1236 #ifdef B230400
1237  case 230400:
1238  speed = B230400;
1239  break;
1240 #endif
1241 #ifdef B460800
1242  case 460800:
1243  speed = B460800;
1244  break;
1245 #endif
1246 #ifdef B500000
1247  case 500000:
1248  speed = B500000;
1249  break;
1250 #endif
1251 #ifdef B576000
1252  case 576000:
1253  speed = B576000;
1254  break;
1255 #endif
1256 #ifdef B921600
1257  case 921600:
1258  speed = B921600;
1259  break;
1260 #endif
1261  default:
1262 #if B9600 == 9600
1263  speed = bps;
1264 #else
1265  speed = B9600;
1266 #endif
1267  }
1268 
1269  cfsetospeed(&tios, speed);
1270  cfsetispeed(&tios, speed);
1271  ret = tcsetattr(privdata->fd, TCSANOW, &tios); /* apply changes now */
1272  if (ret == -1) {
1273  error(errno, "AT2[%s]: at_data_link: fail to set termios attribute",
1275  }
1276  tcflush(privdata->fd, TCIOFLUSH);
1277 
1278  info(0, "AT2[%s]: speed set to %d", octstr_get_cstr(privdata->name), bps);
1279 }
1280 
1281 
1282 static void at2_device_thread(void *arg)
1283 {
1284  SMSCConn *conn = arg;
1285  PrivAT2data *privdata = conn->data;
1286  int reconnecting = 0, error_count = 0;
1287  long idle_timeout, memory_poll_timeout = 0;
1288 
1289  conn->status = SMSCCONN_CONNECTING;
1290 
1291  /* Make sure we log into our own log-file if defined */
1292  log_thread_to(conn->log_idx);
1293 
1294 reconnect:
1295 
1296  do {
1297  if (reconnecting) {
1298  if (conn->status == SMSCCONN_ACTIVE) {
1299  mutex_lock(conn->flow_mutex);
1300  conn->status = SMSCCONN_RECONNECTING;
1301  mutex_unlock(conn->flow_mutex);
1302  }
1303  error(0, "AT2[%s]: Couldn't connect (retrying in %ld seconds).",
1306  reconnecting = 0;
1307  }
1308 
1309  /* If modems->speed is defined, try to use it, else autodetect */
1310  if (privdata->speed == 0 && privdata->modem != NULL && privdata->modem->speed != 0) {
1311 
1312  info(0, "AT2[%s]: trying to use speed <%ld> from modem definition",
1313  octstr_get_cstr(privdata->name), privdata->modem->speed);
1314  if (at2_test_speed(privdata, privdata->modem->speed) == 0) {
1315  privdata->speed = privdata->modem->speed;
1316  info(0, "AT2[%s]: speed is %ld",
1318  } else {
1319  info(0, "AT2[%s]: speed in modem definition don't work, will autodetect",
1321  }
1322  }
1323 
1324  if (privdata->speed == 0 && at2_detect_speed(privdata) == -1) {
1325  reconnecting = 1;
1326  continue;
1327  }
1328 
1329  if (privdata->modem == NULL && at2_detect_modem_type(privdata) == -1) {
1330  reconnecting = 1;
1331  continue;
1332  }
1333 
1334  if (at2_open_device(privdata)) {
1335  error(errno, "AT2[%s]: at2_device_thread: open_at2_device failed.",
1337  reconnecting = 1;
1338  continue;
1339  }
1340 
1341  if (at2_login_device(privdata)) {
1342  error(errno, "AT2[%s]: at2_device_thread: at2_login_device failed.",
1344  reconnecting = 1;
1345  continue;
1346  }
1347 
1348  if (privdata->max_error_count > 0 && error_count > privdata->max_error_count
1349  && privdata->modem != NULL && privdata->modem->reset_string != NULL) {
1350  error_count = 0;
1352  octstr_get_cstr(privdata->modem->reset_string), 0, 0) != 0) {
1353  error(0, "AT2[%s]: Reset of modem failed.", octstr_get_cstr(privdata->name));
1355  reconnecting = 1;
1356  continue;
1357  } else {
1358  info(0, "AT2[%s]: Modem reseted.", octstr_get_cstr(privdata->name));
1359  }
1360  }
1361 
1362  if (at2_init_device(privdata) != 0) {
1363  error(0, "AT2[%s]: Initialization of device failed. Attempt #%d on %ld max.", octstr_get_cstr(privdata->name),
1364  error_count, privdata->max_error_count);
1366  error_count++;
1367  reconnecting = 1;
1368  continue;
1369  } else
1370  error_count = 0;
1371 
1372  /* If we got here, then the device is opened */
1373  break;
1374  } while (!privdata->shutdown);
1375 
1376  mutex_lock(conn->flow_mutex);
1377  conn->status = SMSCCONN_ACTIVE;
1378  conn->connect_time = time(NULL);
1379  mutex_unlock(conn->flow_mutex);
1380  bb_smscconn_connected(conn);
1381 
1382  idle_timeout = 0;
1383  while (!privdata->shutdown) {
1384  at2_wait_modem_command(privdata, 1, 0, NULL);
1385 
1386  /* read error, so re-connect */
1387  if (privdata->fd == -1) {
1389  reconnecting = 1;
1390  goto reconnect;
1391  }
1392 
1393  while (gwlist_len(privdata->pending_incoming_messages) > 0) {
1395  }
1396 
1397  if (privdata->keepalive &&
1398  idle_timeout + privdata->keepalive < time(NULL)) {
1400  octstr_get_cstr(privdata->modem->keepalive_cmd), 5, 0) < 0) {
1402  reconnecting = 1;
1403  goto reconnect;
1404  }
1405  idle_timeout = time(NULL);
1406  }
1407 
1408  if (privdata->sms_memory_poll_interval &&
1409  memory_poll_timeout + privdata->sms_memory_poll_interval < time(NULL)) {
1410  if (at2_read_sms_memory(privdata) == -1) {
1412  reconnecting = 1;
1413  goto reconnect;
1414  }
1415  memory_poll_timeout = time(NULL);
1416  }
1417 
1420  idle_timeout = time(NULL);
1421  }
1422  }
1424  mutex_lock(conn->flow_mutex);
1425  conn->status = SMSCCONN_DISCONNECTED;
1426  mutex_unlock(conn->flow_mutex);
1427  /* maybe some cleanup here? */
1428  at2_destroy_modem(privdata->modem);
1429  octstr_destroy(privdata->device);
1430  octstr_destroy(privdata->ilb);
1431  octstr_destroy(privdata->lines);
1432  octstr_destroy(privdata->pin);
1435  octstr_destroy(privdata->sms_center);
1437  octstr_destroy(privdata->configfile);
1440  octstr_destroy(privdata->rawtcp_host);
1442  gwlist_destroy(privdata->pending_incoming_messages, octstr_destroy_item);
1443  load_destroy(privdata->load);
1444  gw_free(conn->data);
1445  conn->data = NULL;
1446  mutex_lock(conn->flow_mutex);
1448  conn->status = SMSCCONN_DEAD;
1449  mutex_unlock(conn->flow_mutex);
1451 }
1452 
1453 
1454 static int at2_shutdown_cb(SMSCConn *conn, int finish_sending)
1455 {
1456  PrivAT2data *privdata = conn->data;
1457 
1458  debug("bb.sms", 0, "AT2[%s]: Shutting down SMSCConn, %s",
1460  finish_sending ? "slow" : "instant");
1461 
1462  /*
1463  * Documentation claims this would have been done by smscconn.c,
1464  * but isn't when this code is being written.
1465  */
1467  privdata->shutdown = 1;
1468  /*
1469  * Separate from why_killed to avoid locking, as
1470  * why_killed may be changed from outside?
1471  */
1472  if (finish_sending == 0) {
1473  Msg *msg;
1474  while ((msg = gw_prioqueue_remove(privdata->outgoing_queue)) != NULL) {
1476  }
1477  }
1478  gwthread_wakeup(privdata->device_thread);
1479  return 0;
1480 
1481 }
1482 
1483 
1484 static long at2_queued_cb(SMSCConn *conn)
1485 {
1487 
1488  privdata = conn->data;
1489  conn->load = (privdata ? (conn->status != SMSCCONN_DEAD ?
1491  return conn->load;
1492 }
1493 
1494 
1495 static void at2_start_cb(SMSCConn *conn)
1496 {
1498 
1499  privdata = conn->data;
1500  if (conn->status == SMSCCONN_DISCONNECTED)
1501  conn->status = SMSCCONN_ACTIVE;
1502 
1503  /* in case there are messages in the buffer already */
1504  gwthread_wakeup(privdata->device_thread);
1505  debug("smsc.at2", 0, "AT2[%s]: start called", octstr_get_cstr(privdata->name));
1506 }
1507 
1508 static int at2_add_msg_cb(SMSCConn *conn, Msg *sms)
1509 {
1511 
1512  privdata = conn->data;
1514  gwthread_wakeup(privdata->device_thread);
1515  return 0;
1516 }
1517 
1518 
1520 {
1522  Octstr *modem_type_string;
1523  long portno; /* has to be long because of cfg_get_integer */
1524 
1525  privdata = gw_malloc(sizeof(PrivAT2data));
1526  memset(privdata, 0, sizeof(PrivAT2data));
1528  privdata->pending_incoming_messages = gwlist_create();
1529 
1530  privdata->configfile = cfg_get_configfile(cfg);
1531 
1532  privdata->device = cfg_get(cfg, octstr_imm("device"));
1533  if (privdata->device == NULL) {
1534  error(0, "AT2[-]: 'device' missing in at2 configuration.");
1535  goto error;
1536  }
1537 
1538  if (octstr_str_compare(privdata->device, "rawtcp") == 0) {
1539  privdata->rawtcp_host = cfg_get(cfg, octstr_imm("host"));
1540  if (privdata->rawtcp_host == NULL) {
1541  error(0, "AT2[-]: 'host' missing in at2 rawtcp configuration.");
1542  goto error;
1543  }
1544  if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1) {
1545  error(0, "AT2[-]: 'port' missing in at2 rawtcp configuration.");
1546  goto error;
1547  }
1548  privdata->rawtcp_port = portno;
1549  privdata->is_serial = 0;
1550  privdata->use_telnet = 0;
1551  } else if (octstr_str_compare(privdata->device, "telnet") == 0) {
1552  privdata->rawtcp_host = cfg_get(cfg, octstr_imm("host"));
1553  if (privdata->rawtcp_host == NULL) {
1554  error(0, "AT2[-]: 'host' missing in at2 telnet configuration.");
1555  goto error;
1556  }
1557  if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1) {
1558  error(0, "AT2[-]: 'port' missing in at2 telnet configuration.");
1559  goto error;
1560  }
1561  privdata->rawtcp_port = portno;
1562  privdata->is_serial = 0;
1563  privdata->use_telnet = 1;
1564  } else {
1565  privdata->is_serial = 1;
1566  privdata->use_telnet = 0;
1567  }
1568 
1569  privdata->name = cfg_get(cfg, octstr_imm("smsc-id"));
1570  if (privdata->name == NULL) {
1571  privdata->name = octstr_duplicate(privdata->device);
1572  }
1573 
1574  privdata->speed = 0;
1575  cfg_get_integer(&privdata->speed, cfg, octstr_imm("speed"));
1576 
1577  privdata->keepalive = 0;
1578  cfg_get_integer(&privdata->keepalive, cfg, octstr_imm("keepalive"));
1579 
1580  cfg_get_bool(&privdata->sms_memory_poll_interval, cfg, octstr_imm("sim-buffering"));
1581  if (privdata->sms_memory_poll_interval) {
1582  if (privdata->keepalive)
1583  privdata->sms_memory_poll_interval = privdata->keepalive;
1584  else
1585  privdata->sms_memory_poll_interval = AT2_DEFAULT_SMS_POLL_INTERVAL;
1586  }
1587 
1588  privdata->my_number = cfg_get(cfg, octstr_imm("my-number"));
1589  privdata->sms_center = cfg_get(cfg, octstr_imm("sms-center"));
1590  privdata->username = cfg_get(cfg, octstr_imm("smsc-username"));
1591  privdata->password = cfg_get(cfg, octstr_imm("smsc-password"));
1592  privdata->login_prompt = cfg_get(cfg, octstr_imm("login-prompt"));
1593  privdata->password_prompt = cfg_get(cfg, octstr_imm("password-prompt"));
1594  modem_type_string = cfg_get(cfg, octstr_imm("modemtype"));
1595 
1596  privdata->modem = NULL;
1597 
1598  if (modem_type_string != NULL) {
1599  if (octstr_compare(modem_type_string, octstr_imm("auto")) == 0 ||
1600  octstr_compare(modem_type_string, octstr_imm("autodetect")) == 0)
1601  O_DESTROY(modem_type_string);
1602  }
1603 
1604  if (octstr_len(modem_type_string) == 0) {
1605  info(0, "AT2[%s]: configuration doesn't show modemtype. will autodetect",
1607  } else {
1608  info(0, "AT2[%s]: configuration shows modemtype <%s>",
1610  octstr_get_cstr(modem_type_string));
1611  privdata->modem = at2_read_modems(privdata, privdata->configfile,
1612  modem_type_string, 0);
1613  if (privdata->modem == NULL) {
1614  info(0, "AT2[%s]: modemtype not found, revert to autodetect",
1616  } else {
1617  info(0, "AT2[%s]: read modem definition for <%s>",
1619  octstr_get_cstr(privdata->modem->name));
1620  }
1621  O_DESTROY(modem_type_string);
1622  }
1623 
1624  privdata->ilb = octstr_create("");
1625  privdata->fd = -1;
1626  privdata->lines = NULL;
1627  privdata->pin = cfg_get(cfg, octstr_imm("pin"));
1628  privdata->pin_ready = 0;
1629  privdata->conn = conn;
1630  privdata->phase2plus = 0;
1631  privdata->validityperiod = cfg_get(cfg, octstr_imm("validityperiod"));
1632  if (cfg_get_integer((long *) &privdata->max_error_count, cfg, octstr_imm("max-error-count")) == -1)
1633  privdata->max_error_count = -1;
1634 
1635  privdata->load = load_create_real(0);
1636  load_add_interval(privdata->load, 1);
1637 
1638  conn->data = privdata;
1639  conn->name = octstr_format("AT2[%s]", octstr_get_cstr(privdata->name));
1640  conn->status = SMSCCONN_CONNECTING;
1641  conn->connect_time = time(NULL);
1642 
1643  privdata->shutdown = 0;
1644 
1645  if ((privdata->device_thread = gwthread_create(at2_device_thread, conn)) == -1) {
1646  privdata->shutdown = 1;
1647  goto error;
1648  }
1649 
1650  conn->shutdown = at2_shutdown_cb;
1651  conn->queued = at2_queued_cb;
1652  conn->start_conn = at2_start_cb;
1653  conn->send_msg = at2_add_msg_cb;
1654  return 0;
1655 
1656 error:
1657  error(0, "AT2[%s]: Failed to create at2 smsc connection",
1659  if (privdata != NULL) {
1661  }
1662  gw_free(privdata);
1664  conn->status = SMSCCONN_DEAD;
1665  info(0, "AT2[%s]: exiting", octstr_get_cstr(privdata->name));
1666  return -1;
1667 }
1668 
1669 
1670 static int at2_pdu_extract(PrivAT2data *privdata, Octstr **pdu, Octstr *line, Octstr *smsc_number)
1671 {
1672  Octstr *buffer;
1673  long len = 0;
1674  int pos = 0;
1675  int tmp;
1676  Octstr *numtmp;
1677  Octstr *tmp2;
1678 
1679  buffer = octstr_duplicate(line);
1680  /* find the beginning of a message from the modem*/
1681 
1682  if ((pos = octstr_search(buffer, octstr_imm("+CDS:"), 0)) != -1)
1683  pos += 5;
1684  else {
1685  if ((pos = octstr_search(buffer, octstr_imm("+CMT:"), 0)) != -1)
1686  pos += 5;
1687  else if ((pos = octstr_search(buffer, octstr_imm("+CMGR:"), 0)) != -1) {
1688  /* skip status field in +CMGR response */
1689  if ((pos = octstr_search(buffer, octstr_imm(","), pos + 6)) != -1)
1690  pos++;
1691  else
1692  goto nomsg;
1693  } else
1694  goto nomsg;
1695 
1696  /* skip the next comma in CMGR and CMT responses */
1697  tmp = octstr_search(buffer, octstr_imm(","), pos);
1698  if (!privdata->modem->broken && tmp == -1)
1699  goto nomsg;
1700  if (tmp != -1)
1701  pos = tmp + 1;
1702  }
1703 
1704  /* read the message length */
1705  pos = octstr_parse_long(&len, buffer, pos, 10);
1706  if (pos == -1 || len == 0)
1707  goto nomsg;
1708 
1709  /* skip the spaces and line return */
1710  while (isspace(octstr_get_char(buffer, pos)))
1711  pos++;
1712 
1713  octstr_truncate(smsc_number,0);
1714 
1715  /* skip the SMSC address on some modem types */
1716  if (!privdata->modem->no_smsc) {
1717  tmp = at2_hexchar(octstr_get_char(buffer, pos)) * 16
1718  + at2_hexchar(octstr_get_char(buffer, pos + 1));
1719  if (tmp < 0)
1720  goto nomsg;
1721 
1722  numtmp = octstr_create_from_data(octstr_get_cstr(buffer)+pos+2,tmp * 2); /* we now have the hexchars of the SMSC in GSM encoding */
1723  octstr_hex_to_binary(numtmp);
1724  tmp2 = gsm2number(numtmp);
1725  debug("bb.smsc.at2", 0, "AT2[%s]: received message from SMSC: %s", octstr_get_cstr(privdata->name), octstr_get_cstr(tmp2));
1726  octstr_destroy(numtmp);
1727  octstr_append(smsc_number,tmp2);
1728  octstr_destroy(tmp2);
1729  pos += 2 + tmp * 2;
1730  }
1731 
1732  /* check if the buffer is long enough to contain the full message */
1733  if (!privdata->modem->broken && octstr_len(buffer) < len * 2 + pos)
1734  goto nomsg;
1735 
1736  if (privdata->modem->broken && octstr_len(buffer) < len * 2)
1737  goto nomsg;
1738 
1739  /* copy the PDU then remove it from the input buffer*/
1740  *pdu = octstr_copy(buffer, pos, len * 2);
1741 
1742  octstr_destroy(buffer);
1743  return 1;
1744 
1745 nomsg:
1746  octstr_destroy(buffer);
1747  return 0;
1748 }
1749 
1750 static unsigned char nibble2hex(unsigned char b)
1751 {
1752  if(b < 0x0A)
1753  return '0'+ b;
1754  else
1755  return 'A'+ b - 0x0A;
1756 }
1757 
1758 static Octstr *gsm2number(Octstr *pdu)
1759 {
1760  Octstr *tmp = NULL;
1761  unsigned char c;
1762  unsigned char a;
1763  unsigned char b;
1764  int ton;
1765  int len;
1766  int pos;
1767 
1768  pos=0;
1769  len = octstr_len(pdu);
1770  if(len<= 0)
1771  return octstr_create("");
1772 
1773  ton = octstr_get_char(pdu,pos++);
1774  ton = (ton >> 4) & 0x07;
1775 
1776  switch(ton)
1777  {
1778  case 0: /* unknown */
1779  tmp = octstr_create("");
1780  break;
1781  case 1: /* international */
1782  tmp = octstr_create("+");
1783  break;
1784  case 2: /* national */
1785  tmp = octstr_create("0");
1786  break;
1787  case 3: /* network-specific */
1788  default:
1789  tmp = octstr_create("");
1790  break;
1791  }
1792  while(--len > 0)
1793  {
1794  c = octstr_get_char(pdu,pos++);
1795  a = c & 0x0F;
1796  b = ((c & 0xF0) >> 4);
1797 
1798  if((b == 0x0F) && (len < 2))
1799  {
1800  octstr_append_char(tmp, nibble2hex(a));
1801  }
1802  else
1803  {
1804  octstr_append_char(tmp, nibble2hex(a));
1805  octstr_append_char(tmp, nibble2hex(b));
1806  }
1807  }
1808  return tmp;
1809 }
1810 
1811 static int at2_hexchar(int hexc)
1812 {
1813  hexc = toupper(hexc) - 48;
1814  return (hexc > 9) ? hexc - 7 : hexc;
1815 }
1816 
1817 
1819 {
1820  int type;
1821  Msg *msg = NULL;
1822 
1823  /* Get the PDU type */
1824  type = octstr_get_char(data, 1) & 3;
1825 
1826  switch (type) {
1827 
1828  case AT_DELIVER_SM:
1830  break;
1831  case AT_STATUS_REPORT_SM:
1833  break;
1834 
1835  /* Add other message types here: */
1836  }
1837 
1838  return msg;
1839 }
1840 
1841 
1843 {
1844  int len, pos, i, ntype;
1845  int udhi, dcs, udhlen, pid;
1846  Octstr *origin = NULL;
1847  Octstr *udh = NULL;
1848  Octstr *text = NULL, *tmpstr;
1849  Octstr *pdu = NULL;
1850  Msg *message = NULL;
1851  struct universaltime mtime; /* time structure */
1852  long stime; /* time in seconds */
1853  int timezone; /* timezone in 15 minutes jumps from GMT */
1854 
1855  /*
1856  * Note: some parts of the PDU are not decoded because they are
1857  * not needed for the Msg type.
1858  */
1859 
1860  /* convert the pdu to binary format for ease of processing */
1861  pdu = at2_convertpdu(data);
1862 
1863  /* UDH Indicator */
1864  udhi = (octstr_get_char(pdu, 0) & 64) >> 6;
1865 
1866  /* originating address */
1867  len = octstr_get_char(pdu, 1);
1868  if (len > 20) /* maximum valid number of semi-octets in Address-Value field */
1869  goto msg_error;
1870  ntype = octstr_get_char(pdu, 2);
1871 
1872  pos = 3;
1873  if ((ntype & 0xD0) == 0xD0) {
1874  /* Alphanumeric sender */
1875  origin = octstr_create("");
1876  tmpstr = octstr_copy(pdu, 3, len);
1877  at2_decode7bituncompressed(tmpstr, (((len - 1) * 4 - 3) / 7) + 1, origin, 0);
1878  octstr_destroy(tmpstr);
1879  debug("bb.smsc.at2", 0, "AT2[%s]: Alphanumeric sender <%s>",
1881  pos += (len + 1) / 2;
1882  } else {
1883  origin = octstr_create("");
1884  if ((ntype & 0x90) == 0x90) {
1885  /* International number */
1886  octstr_append_char(origin, '+');
1887  }
1888  for (i = 0; i < len; i += 2, pos++) {
1889  octstr_append_char(origin, (octstr_get_char(pdu, pos) & 15) + 48);
1890  if (i + 1 < len)
1891  octstr_append_char(origin, (octstr_get_char(pdu, pos) >> 4) + 48);
1892  }
1893  debug("bb.smsc.at2", 0, "AT2[%s]: Numeric sender %s <%s>",
1894  octstr_get_cstr(privdata->name), ((ntype & 0x90) == 0x90 ? "(international)" : ""),
1895  octstr_get_cstr(origin));
1896  }
1897 
1898  if (pos > octstr_len(pdu))
1899  goto msg_error;
1900 
1901  /* PID */
1902  pid = octstr_get_char(pdu, pos);
1903  pos++;
1904 
1905  /* DCS */
1906  dcs = octstr_get_char(pdu, pos);
1907  pos++;
1908 
1909  /* get the timestamp */
1910  mtime.year = swap_nibbles(octstr_get_char(pdu, pos));
1911  pos++;
1912  mtime.year += (mtime.year < 70 ? 2000 : 1900);
1913  mtime.month = swap_nibbles(octstr_get_char(pdu, pos));
1914  mtime.month--;
1915  pos++;
1916  mtime.day = swap_nibbles(octstr_get_char(pdu, pos));
1917  pos++;
1918  mtime.hour = swap_nibbles(octstr_get_char(pdu, pos));
1919  pos++;
1920  mtime.minute = swap_nibbles(octstr_get_char(pdu, pos));
1921  pos++;
1922  mtime.second = swap_nibbles(octstr_get_char(pdu, pos));
1923  pos++;
1924 
1925  /*
1926  * time zone:
1927  *
1928  * time zone is "swapped nibble", with the MSB as the sign (1 is negative).
1929  */
1930  timezone = swap_nibbles(octstr_get_char(pdu, pos));
1931  pos++;
1932  timezone = ((timezone >> 7) ? -1 : 1) * (timezone & 127);
1933  /*
1934  * Ok, that was the time zone as read from the PDU. Now how to interpert it?
1935  * All the handsets I tested send the timestamp of their local time and the
1936  * timezone as GMT+0. I assume that the timestamp is the handset's local time,
1937  * so we need to apply the timezone in reverse to get GM time:
1938  */
1939 
1940  /*
1941  * time in PDU is handset's local time and timezone is handset's time zone
1942  * difference from GMT
1943  */
1944  mtime.hour -= timezone / 4;
1945  mtime.minute -= 15 * (timezone % 4);
1946 
1947  stime = date_convert_universal(&mtime);
1948 
1949  /* get data length
1950  * TODO: Is it allowed to have length = 0 ??? (alex)
1951  */
1952  len = octstr_get_char(pdu, pos);
1953  pos++;
1954 
1955  debug("bb.smsc.at2", 0, "AT2[%s]: User data length read as (%d)",
1956  octstr_get_cstr(privdata->name), len);
1957 
1958  /* if there is a UDH */
1959  udhlen = 0;
1960  if (udhi && len > 0) {
1961  udhlen = octstr_get_char(pdu, pos);
1962  pos++;
1963  if (udhlen + 1 > len)
1964  goto msg_error;
1965  udh = octstr_copy(pdu, pos-1, udhlen+1);
1966  pos += udhlen;
1967  len -= udhlen + 1;
1968  } else if (len <= 0) /* len < 0 is impossible, but sure is sure */
1969  udhi = 0;
1970 
1971  debug("bb.smsc.at2", 0, "AT2[%s]: Udh decoding done len=%d udhi=%d udhlen=%d udh='%s'",
1972  octstr_get_cstr(privdata->name), len, udhi, udhlen, (udh ? octstr_get_cstr(udh) : ""));
1973 
1974  if (pos > octstr_len(pdu) || len < 0)
1975  goto msg_error;
1976 
1977  /* build the message */
1978  message = msg_create(sms);
1979  if (!dcs_to_fields(&message, dcs)) {
1980  /* TODO Should we reject this message? */
1981  error(0, "AT2[%s]: Invalid DCS (0x%02x)", octstr_get_cstr(privdata->name), dcs);
1982  dcs_to_fields(&message, 0);
1983  }
1984 
1985  message->sms.pid = pid;
1986 
1987  /* deal with the user data -- 7 or 8 bit encoded */
1988  tmpstr = octstr_copy(pdu, pos, len);
1989  if (message->sms.coding == DC_8BIT || message->sms.coding == DC_UCS2) {
1990  text = octstr_duplicate(tmpstr);
1991  } else {
1992  int offset = 0;
1993  text = octstr_create("");
1994  if (udhi && message->sms.coding == DC_7BIT) {
1995  int nbits;
1996  nbits = (udhlen + 1) * 8;
1997  /* fill bits for UDH to septet boundary */
1998  offset = (((nbits / 7) + 1) * 7 - nbits) % 7;
1999  /*
2000  * Fix length because UDH data length is determined
2001  * in septets if we are in GSM coding, otherwise it's in octets. Adding 6
2002  * will ensure that for an octet length of 0, we get septet length 0,
2003  * and for octet length 1 we get septet length 2.
2004  */
2005  len = len + udhlen + 1 - (8 * (udhlen + 1) + 6) / 7;
2006  }
2007  at2_decode7bituncompressed(tmpstr, len, text, offset);
2008  }
2009 
2010  message->sms.sender = origin;
2011  if (octstr_len(privdata->my_number)) {
2012  message->sms.receiver = octstr_duplicate(privdata->my_number);
2013  } else {
2014  /* Put a dummy address in the receiver for now (SMSC requires one) */
2015  message->sms.receiver = octstr_create_from_data("1234", 4);
2016  }
2017  if (udhi) {
2018  message->sms.udhdata = udh;
2019  }
2020  message->sms.msgdata = text;
2021  message->sms.time = stime;
2022 
2023  /* cleanup */
2024  octstr_destroy(pdu);
2025  octstr_destroy(tmpstr);
2026 
2027  return message;
2028 
2029 msg_error:
2030  error(1, "AT2[%s]: Invalid DELIVER-SMS pdu!", octstr_get_cstr(privdata->name));
2031  O_DESTROY(udh);
2032  O_DESTROY(origin);
2033  O_DESTROY(text);
2034  O_DESTROY(pdu);
2035  return NULL;
2036 }
2037 
2038 
2040 {
2041  Msg *dlrmsg = NULL;
2042  Octstr *pdu, *msg_id, *tmpstr = NULL, *receiver = NULL;
2043  int type, tp_mr, len, ntype, pos;
2044 
2045  /*
2046  * parse the PDU.
2047  */
2048 
2049  /* convert the pdu to binary format for ease of processing */
2050  pdu = at2_convertpdu(data);
2051 
2052  /* Message reference */
2053  tp_mr = octstr_get_char(pdu, 1);
2054  msg_id = octstr_format("%d", tp_mr);
2055  debug("bb.smsc.at2", 0, "AT2[%s]: got STATUS-REPORT for message <%d>:",
2056  octstr_get_cstr(privdata->name), tp_mr);
2057 
2058  /* reciver address */
2059  len = octstr_get_char(pdu, 2);
2060  ntype = octstr_get_char(pdu, 3);
2061 
2062  pos = 4;
2063  if ((ntype & 0xD0) == 0xD0) {
2064  /* Alphanumeric sender */
2065  receiver = octstr_create("");
2066  tmpstr = octstr_copy(pdu, pos, (len + 1) / 2);
2067  at2_decode7bituncompressed(tmpstr, (((len - 1) * 4 - 3) / 7) + 1, receiver, 0);
2068  octstr_destroy(tmpstr);
2069  debug("bb.smsc.at2", 0, "AT2[%s]: Alphanumeric receiver <%s>",
2071  pos += (len + 1) / 2;
2072  } else {
2073  int i;
2074  receiver = octstr_create("");
2075  if ((ntype & 0x90) == 0x90) {
2076  /* International number */
2078  }
2079  for (i = 0; i < len; i += 2, pos++) {
2080  octstr_append_char(receiver, (octstr_get_char(pdu, pos) & 15) + 48);
2081  if (i + 1 < len)
2082  octstr_append_char(receiver, (octstr_get_char(pdu, pos) >> 4) + 48);
2083  }
2084  debug("bb.smsc.at2", 0, "AT2[%s]: Numeric receiver %s <%s>",
2085  octstr_get_cstr(privdata->name), ((ntype & 0x90) == 0x90 ? "(international)" : ""),
2087  }
2088 
2089  pos += 14; /* skip time stamps for now */
2090 
2091  if ((type = octstr_get_char(pdu, pos)) == -1 ) {
2092  error(1, "AT2[%s]: STATUS-REPORT pdu too short to have TP-Status field !",
2094  goto error;
2095  }
2096 
2097  /* Check DLR type:
2098  * 3GPP TS 23.040 defines this a bit mapped field with lots of options
2099  * most of which are not really intersting to us, as we are only interested
2100  * in one of three conditions : failed, held in SC for delivery later, or delivered successfuly
2101  * and here's how I suggest to test it (read the 3GPP reference for further detailes) -
2102  * we'll test the 6th and 5th bits (7th bit when set making all other values 'reseved' so I want to test it).
2103  */
2104  type = type & 0xE0; /* filter out everything but the 7th, 6th and 5th bits */
2105  switch (type) {
2106  case 0x00:
2107  /* 0 0 : success class */
2108  type = DLR_SUCCESS;
2109  tmpstr = octstr_create("Success");
2110  break;
2111  case 0x20:
2112  /* 0 1 : buffered class (temporary error) */
2113  type = DLR_BUFFERED;
2114  tmpstr = octstr_create("Buffered");
2115  break;
2116  case 0x40:
2117  case 0x60:
2118  default:
2119  /* 1 0 : failed class */
2120  /* 1 1 : failed class (actually, temporary error but timed out) */
2121  /* and any other value (can't think of any) is considered failure */
2122  type = DLR_FAIL;
2123  tmpstr = octstr_create("Failed");
2124  break;
2125  }
2126  /* Actually, the above implementation is not correct, as the reference
2127  * says that implementations should consider any "reserved" values to be
2128  * "failure", but most reserved values fall into one of the three
2129  * categories. It will catch "reserved" values where the first 3 MSBits
2130  * are not set as "Success" which may not be correct. */
2131 
2132  if ((dlrmsg = dlr_find(privdata->conn->id, msg_id, receiver, type, 0)) == NULL) {
2133  debug("bb.smsc.at2", 1, "AT2[%s]: Received delivery notification but can't find that ID in the DLR storage",
2135  goto error;
2136  }
2137 
2138  /* Beware DLR URL is now in msg->sms.dlr_url given by dlr_find() */
2139  dlrmsg->sms.msgdata = octstr_duplicate(tmpstr);
2140 
2141 error:
2142  O_DESTROY(tmpstr);
2143  O_DESTROY(pdu);
2145  O_DESTROY(msg_id);
2146  return dlrmsg;
2147 }
2148 
2149 static Octstr *at2_convertpdu(Octstr *pdutext)
2150 {
2151  Octstr *pdu;
2152  int i;
2153  int len = octstr_len(pdutext);
2154 
2155  pdu = octstr_create("");
2156  for (i = 0; i < len; i += 2) {
2157  octstr_append_char(pdu, at2_hexchar(octstr_get_char(pdutext, i)) * 16
2158  + at2_hexchar(octstr_get_char(pdutext, i + 1)));
2159  }
2160  return pdu;
2161 }
2162 
2163 
2164 static int at2_rmask[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };
2165 static int at2_lmask[8] = { 0, 128, 192, 224, 240, 248, 252, 254 };
2166 
2167 static void at2_decode7bituncompressed(Octstr *input, int len, Octstr *decoded, int offset)
2168 {
2169  unsigned char septet, octet, prevoctet;
2170  int i;
2171  int r = 1;
2172  int c = 7;
2173  int pos = 0;
2174 
2175  /* Shift the buffer offset bits to the left */
2176  if (offset > 0) {
2177  unsigned char *ip;
2178  for (i = 0, ip = (unsigned char *)octstr_get_cstr(input); i < octstr_len(input); i++) {
2179  if (i == octstr_len(input) - 1)
2180  *ip = *ip >> offset;
2181  else
2182  *ip = (*ip >> offset) | (*(ip + 1) << (8 - offset));
2183  ip++;
2184  }
2185  }
2186  octet = octstr_get_char(input, pos);
2187  prevoctet = 0;
2188  for (i = 0; i < len; i++) {
2189  septet = ((octet & at2_rmask[c]) << (r - 1)) + prevoctet;
2190  octstr_append_char(decoded, septet);
2191 
2192  prevoctet = (octet & at2_lmask[r]) >> c;
2193 
2194  /* When r=7 we have a full character in prevoctet */
2195  if ((r == 7) && (i < len - 1)) {
2196  i++;
2197  octstr_append_char(decoded, prevoctet);
2198  prevoctet = 0;
2199  }
2200 
2201  r = (r > 6) ? 1 : r + 1;
2202  c = (c < 2) ? 7 : c - 1;
2203 
2204  pos++;
2205  octet = octstr_get_char(input, pos);
2206  }
2207  charset_gsm_to_utf8(decoded);
2208 }
2209 
2210 
2212 {
2213  Msg *msg;
2214 
2215  if (privdata->modem->enable_mms && gw_prioqueue_len(privdata->outgoing_queue) > 1)
2216  at2_send_modem_command(privdata, "AT+CMMS=2", 0, 0);
2217 
2218  if (privdata->conn->throughput > 0 && load_get(privdata->load, 0) >= privdata->conn->throughput) {
2219  debug("bb.sms.at2", 0, "AT2[%s]: throughput limit exceeded (load: %.02f, throughput: %.02f)",
2221  } else {
2223  load_increase(privdata->load);
2225  }
2226  }
2227 }
2228 
2229 
2231 {
2232  char command[500];
2233  int ret = -1;
2234  char sc[3];
2235 
2236  if (octstr_len(privdata->my_number)) {
2237  octstr_destroy(msg->sms.sender);
2238  msg->sms.sender = octstr_duplicate(privdata->my_number);
2239  }
2240 
2241  /*
2242  * The standard says you should be prepending the PDU with 00 to indicate
2243  * to use the default SC. Some older modems dont expect this so it can be
2244  * disabled
2245  * NB: This extra padding is not counted in the CMGS byte count
2246  */
2247  sc[0] = '\0';
2248 
2249  if (!privdata->modem->no_smsc)
2250  strcpy(sc, "00");
2251 
2252  if (msg_type(msg) == sms) {
2253  Octstr *pdu;
2254  int msg_id = -1;
2255 
2256  if ((pdu = at2_pdu_encode(msg, privdata)) == NULL) {
2257  error(2, "AT2[%s]: Error encoding PDU!",octstr_get_cstr(privdata->name));
2258  return;
2259  }
2260 
2261  /*
2262  * send the initial command and then wait for >
2263  */
2264  sprintf(command, "AT+CMGS=%ld", octstr_len(pdu) / 2);
2265 
2266  ret = at2_send_modem_command(privdata, command, 5, 1);
2267  debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
2268  octstr_get_cstr(privdata->name), ret);
2269 
2270  if (ret == 1) {/* > only! */
2271 
2272  /*
2273  * Ok the > has been see now so we can send the PDU now and a
2274  * control Z but no CR or LF
2275  *
2276  * We will handle the 'nokiaphone' types a bit differently, since
2277  * they have a generic error in accepting PDUs that are "too big".
2278  * Which means, PDU that are longer then 18 bytes get truncated by
2279  * the phone modems. We'll buffer the PDU output in a loop.
2280  * All other types will get handled as used to be.
2281  */
2282 
2283  if (octstr_compare(privdata->modem->id, octstr_imm("nokiaphone")) != 0) {
2284  sprintf(command, "%s%s", sc, octstr_get_cstr(pdu));
2285  at2_write(privdata, command);
2287  } else {
2288  /* include the CTRL-Z in the PDU string */
2289  sprintf(command, "%s%s%c", sc, octstr_get_cstr(pdu), 0x1A);
2290 
2291  /* chop PDU into 18-byte-at-a-time pieces to prevent choking
2292  * of certain GSM Phones (e.g. Nokia 6310, 6230 etc.) */
2293  if (strlen(command) > 18) {
2294  char chop[20];
2295  int len = strlen(command);
2296  int pos = 0;
2297  int ret = 18;
2298 
2299  while (pos < len) {
2300  if (pos + ret > len)
2301  ret = len - pos;
2302  memcpy(chop, command + pos, ret);
2303  pos += ret;
2304  chop[ret] = '\0';
2305  at2_write(privdata, chop);
2306  gwthread_sleep((double) 10/1000);
2307  }
2308  } else {
2309  at2_write(privdata, command);
2310  }
2311  }
2312 
2313  /* wait 20 secs for modem command */
2314  ret = at2_wait_modem_command(privdata, 20, 0, &msg_id);
2315  debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
2316  octstr_get_cstr(privdata->name), ret);
2317 
2318  if (ret != 0) {
2321  } else {
2322  /* store DLR message if needed for SMSC generated delivery reports */
2323  if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
2324  if (msg_id == -1)
2325  error(0,"AT2[%s]: delivery notification requested, but I have no message ID!",
2327  else {
2328  Octstr *dlrmsgid = octstr_format("%d", msg_id);
2329 
2330  dlr_add(privdata->conn->id, dlrmsgid, msg, 0);
2331 
2332  O_DESTROY(dlrmsgid);
2333 
2334  }
2335  }
2336 
2337  bb_smscconn_sent(privdata->conn, msg, NULL);
2338  }
2339  } else {
2340  error(0,"AT2[%s]: Error received, notifying failure, "
2341  "sender: %s receiver: %s msgdata: %s udhdata: %s",
2343  octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver),
2344  octstr_get_cstr(msg->sms.msgdata), octstr_get_cstr(msg->sms.udhdata));
2347  }
2348  O_DESTROY(pdu);
2349  }
2350 }
2351 
2352 
2354 {
2355  /*
2356  * Message coding is done as a binary octet string,
2357  * as per 3GPP TS 23.040 specification (GSM 03.40),
2358  */
2359  Octstr *pdu = NULL, *temp = NULL, *buffer = octstr_create("");
2360  int len, setvalidity = 0;
2361 
2362  /*
2363  * message type SUBMIT , bit mapped :
2364  * bit7 .. bit0
2365  * TP-RP , TP-UDHI, TP-SRR, TP-VPF(4), TP-VPF(3), TP-RD, TP-MTI(1), TP-MTI(0)
2366  */
2367  octstr_append_char(buffer,
2368  ((msg->sms.rpi > 0 ? 1 : 0) << 7) /* TP-RP */
2369  | ((octstr_len(msg->sms.udhdata) ? 1 : 0) << 6) /* TP-UDHI */
2370  | ((DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask) ? 1 : 0) << 5) /* TP-SRR */
2371  | 16 /* TP-VP(Rel)*/
2372  | 1 /* TP-MTI: SUBMIT_SM */
2373  );
2374 
2375  /* message reference (0 for now) */
2376  octstr_append_char(buffer, 0);
2377 
2378  /* destination address */
2379  if ((temp = at2_format_address_field(msg->sms.receiver)) == NULL)
2380  goto error;
2381  octstr_append(buffer, temp);
2382  O_DESTROY(temp);
2383 
2384  octstr_append_char(buffer, (msg->sms.pid == SMS_PARAM_UNDEFINED ? 0 : msg->sms.pid) ); /* protocol identifier */
2385  octstr_append_char(buffer, fields_to_dcs(msg, /* data coding scheme */
2386  (msg->sms.alt_dcs != SMS_PARAM_UNDEFINED ? msg->sms.alt_dcs : privdata->conn->alt_dcs)));
2387 
2388  /*
2389  * Validity-Period (TP-VP)
2390  * see GSM 03.40 section 9.2.3.12
2391  * defaults to 24 hours = 167 if not set
2392  */
2393  if (msg->sms.validity != MSG_PARAM_UNDEFINED) {
2394  long val = (msg->sms.validity - time(NULL)) / 60;
2395  if (val > 635040)
2396  setvalidity = 255;
2397  if (val >= 50400 && val <= 635040)
2398  setvalidity = (val - 1) / 7 / 24 / 60 + 192 + 1;
2399  if (val > 43200 && val < 50400)
2400  setvalidity = 197;
2401  if (val >= 2880 && val <= 43200)
2402  setvalidity = (val - 1) / 24 / 60 + 166 + 1;
2403  if (val > 1440 && val < 2880)
2404  setvalidity = 168;
2405  if (val >= 750 && val <= 1440)
2406  setvalidity = (val - 720 - 1) / 30 + 143 + 1;
2407  if (val > 720 && val < 750)
2408  setvalidity = 144;
2409  if (val >= 5 && val <= 720)
2410  setvalidity = (val - 1) / 5 - 1 + 1;
2411  if (val < 5)
2412  setvalidity = 0;
2413  } else
2414  setvalidity = (privdata->validityperiod != NULL ?
2415  atoi(octstr_get_cstr(privdata->validityperiod)) : 167);
2416 
2417  if (setvalidity >= 0 && setvalidity <= 143)
2418  debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d minutes",
2419  octstr_get_cstr(privdata->name), (setvalidity + 1)*5);
2420  else if (setvalidity >= 144 && setvalidity <= 167)
2421  debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %3.1f hours",
2422  octstr_get_cstr(privdata->name), ((float)(setvalidity - 143) / 2) + 12);
2423  else if (setvalidity >= 168 && setvalidity <= 196)
2424  debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d days",
2425  octstr_get_cstr(privdata->name), (setvalidity - 166));
2426  else
2427  debug("bb.smsc.at2", 0, "AT2[%s]: TP-Validity-Period: %d weeks",
2428  octstr_get_cstr(privdata->name), (setvalidity - 192));
2429  octstr_append_char(buffer, setvalidity);
2430 
2431  /* user data length - include length of UDH if it exists */
2432  len = sms_msgdata_len(msg);
2433 
2434  if (octstr_len(msg->sms.udhdata)) {
2435  if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
2436  len += octstr_len(msg->sms.udhdata);
2437  if (len > SMS_8BIT_MAX_LEN) { /* truncate user data to allow UDH to fit */
2438  octstr_delete(msg->sms.msgdata, SMS_8BIT_MAX_LEN - octstr_len(msg->sms.udhdata), 9999);
2439  len = SMS_8BIT_MAX_LEN;
2440  }
2441  } else {
2442  /*
2443  * The reason we branch here is because UDH data length is determined
2444  * in septets if we are in GSM coding, otherwise it's in octets. Adding 6
2445  * will ensure that for an octet length of 0, we get septet length 0,
2446  * and for octet length 1 we get septet length 2.
2447  */
2448  int temp_len;
2449  len += (temp_len = (((8 * octstr_len(msg->sms.udhdata)) + 6) / 7));
2450  if (len > SMS_7BIT_MAX_LEN) { /* truncate user data to allow UDH to fit */
2451  octstr_delete(msg->sms.msgdata, SMS_7BIT_MAX_LEN - temp_len, 9999);
2452  len = SMS_7BIT_MAX_LEN;
2453  }
2454  }
2455  }
2456 
2457  octstr_append_char(buffer,len);
2458 
2459  if (octstr_len(msg->sms.udhdata)) /* udh */
2460  octstr_append(buffer, msg->sms.udhdata);
2461 
2462  /* user data */
2463  if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
2464  octstr_append(buffer, msg->sms.msgdata);
2465  } else {
2466  int offset = 0;
2467  Octstr *msgdata;
2468 
2469  /*
2470  * calculate the number of fill bits needed to align
2471  * the 7bit encoded user data on septet boundry
2472  */
2473  if (octstr_len(msg->sms.udhdata)) { /* Have UDH */
2474  int nbits = octstr_len(msg->sms.udhdata) * 8; /* Includes UDH length byte */
2475  offset = (((nbits / 7) + 1) * 7 - nbits) % 7; /* Fill bits */
2476  }
2477 
2478  msgdata = octstr_duplicate(msg->sms.msgdata);
2479  charset_utf8_to_gsm(msgdata);
2480 
2481  if ((temp = at2_encode7bituncompressed(msgdata, offset)) != NULL)
2482  octstr_append(buffer, temp);
2483  O_DESTROY(temp);
2484  octstr_destroy(msgdata);
2485  }
2486 
2487  /* convert PDU to HEX representation suitable for the AT2 command set */
2488  pdu = at2_encode8bituncompressed(buffer);
2489  O_DESTROY(buffer);
2490 
2491  return pdu;
2492 
2493 error:
2494  O_DESTROY(temp);
2495  O_DESTROY(buffer);
2496  O_DESTROY(pdu);
2497  return NULL;
2498 }
2499 
2500 
2501 static Octstr *at2_encode7bituncompressed(Octstr *source, int offset)
2502 {
2503  int LSBmask[8] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
2504  int MSBmask[8] = { 0x00, 0x40, 0x60, 0x70, 0x78, 0x7C, 0x7E, 0x7F };
2505  int destRemain = (int)ceil((octstr_len(source) * 7.0 + offset) / 8.0);
2506  int i = (offset?8-offset:7), iStore = offset;
2507  int posS;
2508  Octstr *target = octstr_create("");
2509  int target_chr = 0, source_chr;
2510 
2511  /* start packing the septet stream into an octet stream */
2512  for (posS = 0; (source_chr = octstr_get_char(source, posS++)) != -1;) {
2513  /* grab least significant bits from current septet and
2514  * store them packed to the right */
2515  target_chr |= (source_chr & LSBmask[i]) << iStore;
2516  /* store current byte if last command filled it */
2517  if (iStore != 0) {
2518  destRemain--;
2519  octstr_append_char(target, target_chr);
2520  target_chr = 0;
2521  }
2522  /* grab most significant bits from current septet and
2523  * store them packed to the left */
2524  target_chr |= (source_chr & MSBmask[7 - i]) >> (8 - iStore) % 8;
2525  /* advance target bit index by 7 (modulo 8 addition ) */
2526  iStore = (--iStore < 0 ? 7 : iStore);
2527  /* if just finished packing 8 septets (into 7 octets) don't advance mask index */
2528  if (iStore != 0)
2529  i = (++i > 7 ? 1 : i);
2530  }
2531 
2532  /* don't forget to pack the leftovers ;-) */
2533  if (destRemain > 0)
2534  octstr_append_char(target, target_chr);
2535 
2536  return target;
2537 }
2538 
2539 
2541 {
2542  int len, i;
2543  Octstr *out = octstr_create("");
2544 
2545  len = octstr_len(input);
2546 
2547  for (i = 0; i < len; i++) {
2548  /* each character is encoded in its hex representation (2 chars) */
2549  octstr_append_char(out, at2_numtext( (octstr_get_char(input, i) & 0xF0) >> 4));
2550  octstr_append_char(out, at2_numtext( (octstr_get_char(input, i) & 0x0F)));
2551  }
2552  return out;
2553 }
2554 
2555 
2556 static int at2_numtext(int num)
2557 {
2558  return (num > 9) ? (num + 55) : (num + 48);
2559 }
2560 
2561 
2563 {
2564  int i;
2565  int autospeeds[] = {
2566 #ifdef B115200
2567  115200,
2568 #endif
2569 #ifdef B57600
2570  57600,
2571 #endif
2572  38400, 19200, 9600 };
2573 
2574  debug("bb.smsc.at2", 0, "AT2[%s]: detecting modem speed. ",
2576 
2577  for (i = 0; i < (sizeof(autospeeds) / sizeof(int)) && !privdata->shutdown; i++) {
2578  if(at2_test_speed(privdata, autospeeds[i]) == 0) {
2579  privdata->speed = autospeeds[i];
2580  break;
2581  }
2582  }
2583  if (privdata->speed == 0) {
2584  info(0, "AT2[%s]: cannot detect speed", octstr_get_cstr(privdata->name));
2585  return -1;
2586  }
2587  info(0, "AT2[%s]: detect speed is %ld", octstr_get_cstr(privdata->name), privdata->speed);
2588  return 0;
2589 }
2590 
2591 
2592 static int at2_test_speed(PrivAT2data *privdata, long speed)
2593 {
2594  int res;
2595 
2596  if (at2_open_device(privdata) == -1)
2597  return -1;
2598 
2599  at2_read_buffer(privdata, 0); /* give telnet escape sequences a chance */
2600  at2_set_speed(privdata, speed);
2601  /* send a return so the modem can detect the speed */
2602  res = at2_send_modem_command(privdata, "", 1, 0);
2603  res = at2_send_modem_command(privdata, "AT", 0, 0);
2604 
2605  if (res != 0)
2606  res = at2_send_modem_command(privdata, "AT", 0, 0);
2607  if (res != 0)
2608  res = at2_send_modem_command(privdata, "AT", 0, 0);
2609 
2611 
2612  return res;
2613 }
2614 
2615 
2617 {
2618  int res;
2619  ModemDef *modem;
2620  int i;
2621 
2622  debug("bb.smsc.at2", 0, "AT2[%s]: detecting modem type", octstr_get_cstr(privdata->name));
2623 
2624  if (at2_open_device(privdata) == -1)
2625  return -1;
2626 
2627  at2_set_speed(privdata, privdata->speed);
2628  /* sleep 10 ms in order to get device some time to accept speed */
2629  gwthread_sleep(0.1);
2630 
2631  /* reset the modem */
2632  if (at2_send_modem_command(privdata, "ATZ", 0, 0) == -1) {
2633  error(0, "AT2[%s]: Wrong or no answer to ATZ", octstr_get_cstr(privdata->name));
2635  return -1;
2636  }
2637 
2638  /* check if the modem responded */
2639  if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
2640  error(0, "AT2[%s]: Wrong or no answer to AT. Trying again", octstr_get_cstr(privdata->name));
2641  if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
2642  error(0, "AT2[%s]: Second attempt to send AT failed", octstr_get_cstr(privdata->name));
2644  return -1;
2645  }
2646  }
2647 
2649 
2650  /* send a return so the modem can detect the speed */
2651  res = at2_send_modem_command(privdata, "", 1, 0);
2652  res = at2_send_modem_command(privdata, "AT", 0, 0);
2653 
2654  if (at2_send_modem_command(privdata, "AT&F", 0, 0) == -1) {
2656  return -1;
2657  }
2658 
2660 
2661  if (at2_send_modem_command(privdata, "ATE0", 0, 0) == -1) {
2663  return -1;
2664  }
2665 
2667 
2668  if (at2_send_modem_command(privdata, "ATI", 0, 0) == -1) {
2670  return -1;
2671  }
2672 
2673  /* we try to detect the modem automatically */
2674  i = 1;
2675  while ((modem = at2_read_modems(privdata, privdata->configfile, NULL, i++)) != NULL) {
2676 
2677  if (octstr_len(modem->detect_string) == 0) {
2678  at2_destroy_modem(modem);
2679  continue;
2680  }
2681 
2682  /*
2683  debug("bb.smsc.at2",0,"AT2[%s]: searching for %s", octstr_get_cstr(privdata->name),
2684  octstr_get_cstr(modem->name));
2685  */
2686 
2687  if (octstr_search(privdata->lines, modem->detect_string, 0) != -1) {
2688  if (octstr_len(modem->detect_string2) == 0) {
2689  debug("bb.smsc.at2", 0, "AT2[%s]: found string <%s>, using modem definition <%s>",
2691  octstr_get_cstr(modem->name));
2692  privdata->modem = modem;
2693  break;
2694  } else {
2695  if (octstr_search(privdata->lines, modem->detect_string2, 0) != -1) {
2696  debug("bb.smsc.at2", 0, "AT2[%s]: found string <%s> plus <%s>, using modem "
2697  "definition <%s>", octstr_get_cstr(privdata->name),
2698  octstr_get_cstr(modem->detect_string),
2700  octstr_get_cstr(modem->name));
2701  privdata->modem = modem;
2702  break;
2703  }
2704  }
2705  } else {
2706  /* Destroy modem */
2707  at2_destroy_modem(modem);
2708  }
2709  }
2710 
2711  if (privdata->modem == NULL) {
2712  debug("bb.smsc.at2", 0, "AT2[%s]: Cannot detect modem, using generic",
2714  if ((modem = at2_read_modems(privdata, privdata->configfile, octstr_imm("generic"), 0)) == NULL) {
2715  panic(0, "AT2[%s]: Cannot detect modem and generic not found",
2717  } else {
2718  privdata->modem = modem;
2719  }
2720  }
2721 
2722  /* lets see if it supports GSM SMS 2+ mode */
2723  res = at2_send_modem_command(privdata, "AT+CSMS=?", 0, 0);
2724  if (res != 0)
2725  /* if it doesnt even understand the command, I'm sure it won't support it */
2726  privdata->phase2plus = 0;
2727  else {
2728  /* we have to take a part a string like +CSMS: (0,1,128) */
2729  Octstr *ts;
2730  int i;
2731  List *vals;
2732 
2733  ts = privdata->lines;
2734  privdata->lines = NULL;
2735 
2736  i = octstr_search_char(ts, '(', 0);
2737  if (i > 0) {
2738  octstr_delete(ts, 0, i + 1);
2739  }
2740  i = octstr_search_char(ts, ')', 0);
2741  if (i > 0) {
2742  octstr_truncate(ts, i);
2743  }
2744  vals = octstr_split(ts, octstr_imm(","));
2745  octstr_destroy(ts);
2746  ts = gwlist_search(vals, octstr_imm("1"), (void*) octstr_item_match);
2747  if (ts)
2748  privdata->phase2plus = 1;
2750  }
2751  if (privdata->phase2plus)
2752  info(0, "AT2[%s]: Phase 2+ is supported", octstr_get_cstr(privdata->name));
2754  return 0;
2755 }
2756 
2757 
2759 {
2760  Cfg *cfg;
2761  List *grplist;
2762  CfgGroup *grp;
2763  Octstr *p;
2764  ModemDef *modem;
2765  int i = 1;
2766 
2767  /*
2768  * Use id and idnumber=0 or id=NULL and idnumber > 0
2769  */
2770  if (octstr_len(id) == 0 && idnumber == 0)
2771  return NULL;
2772 
2773  if (idnumber == 0)
2774  debug("bb.smsc.at2", 0, "AT2[%s]: Reading modem definitions from <%s>",
2776  cfg = cfg_create(file);
2777 
2778  if (cfg_read(cfg) == -1)
2779  panic(0, "Cannot read modem definition file");
2780 
2781  grplist = cfg_get_multi_group(cfg, octstr_imm("modems"));
2782  if (idnumber == 0)
2783  debug("bb.smsc.at2", 0, "AT2[%s]: Found <%ld> modems in config",
2784  octstr_get_cstr(privdata->name), gwlist_len(grplist));
2785 
2786  if (grplist == NULL)
2787  panic(0, "Where are the modem definitions ?!?!");
2788 
2789  grp = NULL;
2790  while (grplist && (grp = gwlist_extract_first(grplist)) != NULL) {
2791  p = cfg_get(grp, octstr_imm("id"));
2792  if (p == NULL) {
2793  info(0, "Modems group without id, bad");
2794  continue;
2795  }
2796  /* Check by id */
2797  if (octstr_len(id) != 0 && octstr_compare(p, id) == 0) {
2798  O_DESTROY(p);
2799  break;
2800  }
2801  /* Check by idnumber */
2802  if (octstr_len(id) == 0 && idnumber == i) {
2803  O_DESTROY(p);
2804  break;
2805  }
2806  O_DESTROY(p);
2807  i++;
2808  grp = NULL;
2809  }
2810  if (grplist != NULL)
2811  gwlist_destroy(grplist, NULL);
2812 
2813  if (grp != NULL) {
2814  modem = gw_malloc(sizeof(ModemDef));
2815 
2816  modem->id = cfg_get(grp, octstr_imm("id"));
2817 
2818  modem->name = cfg_get(grp, octstr_imm("name"));
2819  if (modem->name == NULL)
2820  modem->name = octstr_duplicate(modem->id);
2821 
2822  modem->detect_string = cfg_get(grp, octstr_imm("detect-string"));
2823  modem->detect_string2 = cfg_get(grp, octstr_imm("detect-string2"));
2824 
2825  modem->init_string = cfg_get(grp, octstr_imm("init-string"));
2826  if (modem->init_string == NULL)
2827  modem->init_string = octstr_create("AT+CNMI=1,2,0,1,0");
2828 
2829  modem->reset_string = cfg_get(grp, octstr_imm("reset-string"));
2830 
2831  modem->speed = 9600;
2832  cfg_get_integer(&modem->speed, grp, octstr_imm("speed"));
2833 
2834  cfg_get_bool(&modem->need_sleep, grp, octstr_imm("need-sleep"));
2835 
2836  modem->enable_hwhs = cfg_get(grp, octstr_imm("enable-hwhs"));
2837  if (modem->enable_hwhs == NULL)
2838  modem->enable_hwhs = octstr_create("AT+IFC=2,2");
2839 
2840  cfg_get_bool(&modem->no_pin, grp, octstr_imm("no-pin"));
2841 
2842  cfg_get_bool(&modem->no_smsc, grp, octstr_imm("no-smsc"));
2843 
2844  modem->sendline_sleep = 100;
2845  cfg_get_integer(&modem->sendline_sleep, grp, octstr_imm("sendline-sleep"));
2846 
2847  modem->keepalive_cmd = cfg_get(grp, octstr_imm("keepalive-cmd"));
2848  if (modem->keepalive_cmd == NULL)
2849  modem->keepalive_cmd = octstr_create("AT");
2850 
2851  modem->message_storage = cfg_get(grp, octstr_imm("message-storage"));
2852  if (cfg_get_integer(&modem->message_start, grp, octstr_imm("message-start")))
2853  modem->message_start = 1;
2854 
2855  cfg_get_bool(&modem->enable_mms, grp, octstr_imm("enable-mms"));
2856  modem->hardware_flow_control = 1;
2857  cfg_get_bool(&modem->hardware_flow_control, grp, octstr_imm("hardware-flow-control"));
2858 
2859  /*
2860  if (modem->message_storage == NULL)
2861  modem->message_storage = octstr_create("SM");
2862  */
2863 
2864  cfg_get_bool(&modem->broken, grp, octstr_imm("broken"));
2865 
2866  cfg_destroy(cfg);
2867  return modem;
2868 
2869  } else {
2870  cfg_destroy(cfg);
2871  return NULL;
2872  }
2873 }
2874 
2875 
2876 static void at2_destroy_modem(ModemDef *modem)
2877 {
2878  if (modem != NULL) {
2879  O_DESTROY(modem->id);
2880  O_DESTROY(modem->name);
2881  O_DESTROY(modem->detect_string);
2882  O_DESTROY(modem->detect_string2);
2883  O_DESTROY(modem->init_string);
2884  O_DESTROY(modem->enable_hwhs);
2885  O_DESTROY(modem->keepalive_cmd);
2886  O_DESTROY(modem->message_storage);
2887  O_DESTROY(modem->reset_string);
2888  gw_free(modem);
2889  }
2890 }
2891 
2892 
2893 static int swap_nibbles(unsigned char byte)
2894 {
2895  return ( ( byte & 15 ) * 10 ) + ( byte >> 4 );
2896 }
2897 
2898 
2900 {
2901  int ntype = PNT_UNKNOWN;
2902  Octstr *out = octstr_create("");
2903  Octstr *temp = octstr_duplicate(msisdn);
2904 
2905  octstr_strip_blanks(temp);
2906  /*
2907  * Check for international numbers
2908  * number starting with '+' or '00' are international,
2909  * others are national.
2910  */
2911  if (strncmp(octstr_get_cstr(msisdn), "+", 1) == 0) {
2912  octstr_delete(temp, 0, 1);
2913  ntype = PNT_INTER; /* international */
2914  } else if (strncmp(octstr_get_cstr(msisdn), "00", 2) == 0) {
2915  octstr_delete(temp, 0, 2);
2916  ntype = PNT_INTER; /* international */
2917  }
2918 
2919  /* address length */
2920  octstr_append_char(out, octstr_len(temp));
2921 
2922  /* Type of address : bit mapped values */
2923  octstr_append_char(out, 0x80 /* Type-of-address prefix */ |
2924  0x01 /* Numbering-plan: MSISDN */ |
2925  (ntype == PNT_INTER ? 0x10 : 0x00) /* Type-of-number: International or National */
2926  );
2927 
2928  /* grab the digits from the MSISDN and encode as swapped semi-octets */
2929  while (out != NULL && octstr_len(temp) > 0) {
2930  int digit1, digit2;
2931  /* get the first two digit */
2932  digit1 = octstr_get_char(temp,0) - 48;
2933  digit2 = octstr_get_char(temp,1) - '0';
2934  if (digit2 < 0)
2935  digit2 = 0x0F;
2936  if(digit1 >= 0 && digit1 < 16 && digit2 < 16) {
2937  octstr_append_char(out, (digit2 << 4) | digit1);
2938  }
2939  else {
2940  O_DESTROY(out);
2941  out = NULL;
2942  }
2943  octstr_delete(temp, 0, 2);
2944  }
2945 
2946  O_DESTROY(temp);
2947  return out;
2948 }
2949 
2950 
2952 {
2953  Octstr *temp;
2954  int ret;
2955 
2956  if (!memory_name || !privdata)
2957  return -1;
2958 
2959  temp = octstr_format("AT+CPMS=\"%S\"", memory_name);
2960  ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0);
2961  octstr_destroy(temp);
2962 
2963  return !ret ? 0 : -1;
2964 }
2965 
2966 
2967 static const char *at2_error_string(int errcode)
2968 {
2969  /*
2970  * +CMS ERRORS
2971  * 0...127 from GSM 04.11 Annex E-2 values
2972  * 128...255 from GSM 03.40 subclause 9.2.3.22
2973  * 300...511 from GSM 07.05 subclause 3.2.5
2974  * 512+ are manufacturer specific according to GSM 07.05 subclause 3.2.5
2975  *
2976  * +CME ERRORS
2977  * CME Error codes from GSM 07.07 section 9.2
2978  * GPP TS 27.007 /2/
2979  * GPRS-related errors - (GSM 04.08 cause codes)
2980  *
2981  */
2982  switch (errcode) {
2983  case 0:
2984  /*
2985  * Default the code to 0 then when you extract the value from the
2986  * modem response message and no code is found, 0 will result.
2987  */
2988  return "Modem returned ERROR but no error code - possibly unsupported or invalid command?";
2989  case 1:
2990  /*
2991  * This cause indicates that the destination requested by the Mobile
2992  * Station cannot be reached because, although the number is in a
2993  * valid format, it is not currently assigned (allocated).
2994  */
2995  return "Unassigned (unallocated) number (+CMS) or No connection to phone (+CME)";
2996  case 2:
2997  return "Phone-adaptor link reserved";
2998  case 3:
2999  /*
3000  * This can be a lot of things, depending upon the command, but in general
3001  * it relates to trying to do a command when no connection exists.
3002  */
3003  return "Operation not allowed at this time (connection may be required)";
3004  case 4:
3005  /*
3006  * This can be a lot of things, depending upon the command, but in general
3007  * it relates to invaid parameters being passed.
3008  */
3009  return "Operation / Parameter(s) not supported";
3010  case 5:
3011  return "PH-SIM PIN required";
3012  case 8:
3013  /*
3014  * This cause indicates that the MS has tried to send a mobile originating
3015  * short message when the MS's network operator or service provider has
3016  * forbidden such transactions.
3017  */
3018  return "Operator determined barring";
3019  case 10:
3020  /*
3021  * This cause indicates that the outgoing call barred service applies to
3022  * the short message service for the called destination.
3023  */
3024  return "Call barred (+CMS) or SIM not inserted or Card inserted is not a SIM (+CME)";
3025  case 11:
3026  return "SIM PIN required";
3027  case 12:
3028  return "SIM PUK required";
3029  case 13:
3030  return "SIM failure";
3031  case 14:
3032  return "SIM busy";
3033  case 15:
3034  return "SIM wrong";
3035  case 16:
3036  return "Incorrect password";
3037  case 17:
3038  /*
3039  * This cause is sent to the MS if the MSC cannot service an MS generated
3040  * request because of PLMN failures, e.g. problems in MAP.
3041  */
3042  return "Network failure (+CMS) or SIM PIN2 required (+CME)";
3043  case 18:
3044  return "SIM PUK2 required";
3045  case 20:
3046  return "Memory full";
3047  case 21:
3048  /*
3049  * This cause indicates that the equipment sending this cause does not
3050  * wish to accept this short message, although it could have accepted
3051  * the short message since the equipment sending this cause is neither
3052  * busy nor incompatible.
3053  */
3054  return "Short message transfer rejected (+CMS) or Invalid Index (+CME)";
3055  case 22:
3056  /*
3057  * This cause is sent if the service request cannot be actioned because
3058  * of congestion (e.g. no channel, facility busy/congested etc.). Or
3059  * this cause indicates that the mobile station cannot store the
3060  * incoming short message due to lack of storage capacity.
3061  */
3062  return "Congestion (+CMS) or Memory capacity exceeded (+CME)";
3063  case 23:
3064  return "Memory failure";
3065  case 24:
3066  return "Text string too long"; /* +CPBW, +CPIN, +CPIN2, +CLCK, +CPWD */
3067  case 25:
3068  return "Invalid characters in text string";
3069  case 26:
3070  return "Dial string too long"; /* +CPBW, ATD, +CCFC */
3071  case 27:
3072  /*
3073  * This cause indicates that the destination indicated by the Mobile
3074  * Station cannot be reached because the interface to the destination
3075  * is not functioning correctly. The term "not functioning correctly"
3076  * indicates that a signalling message was unable to be delivered to
3077  * the remote user; e.g., a physical layer or data link layer failure
3078  * at the remote user, user equipment off-line, etc.
3079  * Also means "Invalid characters in dial string" for +CPBW.
3080  */
3081  return "Destination out of service";
3082  case 28:
3083  /*
3084  * This cause indicates that the subscriber is not registered in the PLMN
3085  * (i.e. IMSI not known).
3086  */
3087  return "Unidentified subscriber";
3088  case 29:
3089  /*
3090  * This cause indicates that the facility requested by the Mobile Station
3091  * is not supported by the PLMN.
3092  */
3093  return "Facility rejected";
3094  case 30:
3095  /*
3096  * This cause indicates that the subscriber is not registered in the HLR
3097  * (i.e. IMSI or directory number is not allocated to a subscriber).
3098  * Also means "No network service" for +VTS, +COPS=?, +CLCK, +CCFC, +CCWA, +CUSD
3099  */
3100  return "Unknown subscriber (+CMS) or No network service (+CME)";
3101  case 31:
3102  return "Network timeout";
3103  case 32:
3104  return "Network not allowed - emergency calls only"; /* +COPS */
3105  case 38:
3106  /*
3107  * This cause indicates that the network is not functioning correctly and
3108  * that the condition is likely to last a relatively long period of time;
3109  * e.g., immediately reattempting the short message transfer is not
3110  * likely to be successful.
3111  */
3112  return "Network out of order";
3113  case 40:
3114  return "Network personal PIN required (Network lock)";
3115  case 41:
3116  /*
3117  * This cause indicates that the network is not functioning correctly and
3118  * that the condition is not likely to last a long period of time; e.g.,
3119  * the Mobile Station may wish to try another short message transfer
3120  * attempt almost immediately.
3121  */
3122  return "Temporary failure (+CMS) or Network personalization PUK required (+CME)";
3123  case 42:
3124  /*
3125  * This cause indicates that the short message service cannot be serviced
3126  * because of high traffic.
3127  */
3128  return "Congestion (+CMS) or Network subset personalization PIN required (+CME)";
3129  case 43:
3130  return "Network subset personalization PUK required";
3131  case 44:
3132  return "Service provider personalization PIN required";
3133  case 45:
3134  return "Service provider personalization PUK required";
3135  case 46:
3136  return "Corporate personalization PIN required";
3137  case 47:
3138  /*
3139  * This cause is used to report a resource unavailable event only when no
3140  * other cause applies.
3141  */
3142  return "Resources unavailable, unspecified (+CMS) or Corporate personalization PUK required (+CME)";
3143  case 50:
3144  /*
3145  * This cause indicates that the requested short message service could not
3146  * be provided by the network because the user has not completed the
3147  * necessary administrative arrangements with its supporting networks.
3148  */
3149  return "Requested facility not subscribed";
3150  case 69:
3151  /*
3152  * This cause indicates that the network is unable to provide the
3153  * requested short message service.
3154  */
3155  return "Requested facility not implemented";
3156  case 81:
3157  /*
3158  * This cause indicates that the equipment sending this cause has received
3159  * a message with a short message reference which is not currently in use
3160  * on the MS-network interface.
3161  */
3162  return "Invalid short message transfer reference value";
3163  case 95:
3164  /*
3165  * This cause is used to report an invalid message event only when no
3166  * other cause in the invalid message class applies.
3167  */
3168  return "Invalid message, unspecified";
3169  case 96:
3170  /*
3171  * This cause indicates that the equipment sending this cause has received
3172  * a message where a mandatory information element is missing and/or has
3173  * a content error (the two cases are indistinguishable).
3174  */
3175  return "Invalid mandatory information";
3176  case 97:
3177  /*
3178  * This cause indicates that the equipment sending this cause has received
3179  * a message with a message type it does not recognize either because this
3180  * is a message not defined or defined but not implemented by the
3181  * equipment sending this cause.
3182  */
3183  return "Message type non-existent or not implemented";
3184  case 98:
3185  /*
3186  * This cause indicates that the equipment sending this cause has received
3187  * a message such that the procedures do not indicate that this is a
3188  * permissible message to receive while in the short message transfer
3189  * state.
3190  */
3191  return "Message not compatible with short message protocol state";
3192  case 99:
3193  /*
3194  * This cause indicates that the equipment sending this cause has received
3195  * a message which includes information elements not recognized because
3196  * the information element identifier is not defined or it is defined
3197  * but not implemented by the equipment sending the cause. However, the
3198  * information element is not required to be present in the message in
3199  * order for the equipment sending the cause to process the message.
3200  */
3201  return "Information element non-existent or not implemented";
3202  case 100:
3203  return "Unknown";
3204  case 103:
3205  return "Illegal MS (#3)"; /* +CGATT */
3206  case 106:
3207  return "Illegal ME (#6)"; /* +CGATT */
3208  case 107:
3209  return "GPRS services not allowed (#7)"; /* +CGATT */
3210  case 111:
3211  /*
3212  * This cause is used to report a protocol error event only when no other
3213  * cause applies.
3214  * Also means "PLMN not allowed (#11)" for +CGATT
3215  */
3216  return "Protocol error, unspecified (+CMS) or PLMN not allowed (#11) (+CME)";
3217  case 112:
3218  return "Location area not allowed (#12)"; /* +CGATT */
3219  case 113:
3220  return "Roaming not allowed in this area (#13)"; /* +CGATT */
3221  case 127:
3222  /*
3223  * This cause indicates that there has been interworking with a network
3224  * which does not provide causes for actions it takes; thus, the precise
3225  * cause for a message which is being send cannot be ascertained.
3226  */
3227  return "Interworking, unspecified";
3228  case 128:
3229  return "Telematic interworking not supported";
3230  case 129:
3231  return "Short message Type 0 not supported";
3232  case 130:
3233  return "Cannot replace short message";
3234  case 132:
3235  return "Service option not supported (#32)"; /* +CGACT +CGDATA ATD*99 */
3236  case 133:
3237  return "Requested service option not subscribed (#33)"; /* +CGACT +CGDATA ATD*99 */
3238  case 134:
3239  return "Service option temporarily out of order (#34)"; /* +CGACT +CGDATA ATD*99 */
3240  case 143:
3241  return "Unspecified TP-PID error";
3242  case 144:
3243  return "Data coding scheme (alphabet) not supported";
3244  case 145:
3245  return "Message class not supported";
3246  case 148:
3247  return "Unspecified GPRS error";
3248  case 149:
3249  return "PDP authentication failure"; /* +CGACT +CGDATA ATD*99 */
3250  case 150:
3251  return "Invalid mobile class";
3252  case 159:
3253  return "Unspecified TP-DCS error";
3254  case 160:
3255  return "Command cannot be actioned";
3256  case 161:
3257  return "Unsupported command";
3258  case 175:
3259  return "Unspecified TP-Command error";
3260  case 176:
3261  return "TPDU not supported";
3262  case 192:
3263  return "SC busy";
3264  case 193:
3265  return "No SC subscription";
3266  case 194:
3267  return "SC system failure";
3268  case 195:
3269  return "Invalid SME address";
3270  case 196:
3271  return "Destination SME barred";
3272  case 197:
3273  return "SM Rejected-Duplicate SM";
3274  case 198:
3275  return "TP-VPF not supported";
3276  case 199:
3277  return "TP-VP not supported";
3278  case 208:
3279  return "DO SIM SMS storage full";
3280  case 209:
3281  return "No SMS storage capability in SIM";
3282  case 210:
3283  return "Error in MS";
3284  case 211:
3285  return "SIM Memory Capacity Exceeded";
3286  case 212:
3287  return "SIM Application Toolkit Busy";
3288  case 213:
3289  return "SIM data download error";
3290  case 255:
3291  return "Unspecified error cause";
3292  case 300:
3293  /*
3294  * Mobile equipment refers to the mobile device that communicates with
3295  * the wireless network. Usually it is a mobile phone or GSM/GPRS modem.
3296  * The SIM card is defined as a separate entity and is not part of mobile equipment.
3297  */
3298  return "Mobile equipment (ME) failure";
3299  case 301:
3300  /*
3301  * See +CMS error code 300 for the meaning of mobile equipment.
3302  */
3303  return "SMS service of mobile equipment (ME) is reserved";
3304  case 302:
3305  return "The operation to be done by the AT command is not allowed";
3306  case 303:
3307  return "The operation to be done by the AT command is not supported";
3308  case 304:
3309  return "One or more parameter values assigned to the AT command are invalid";
3310  case 305:
3311  return "One or more parameter values assigned to the AT command are invalid";
3312  case 310:
3313  return "There is no SIM card";
3314  case 311:
3315  /*
3316  * The AT command +CPIN (command name in text: Enter PIN)
3317  * can be used to send the PIN to the SIM card.
3318  */
3319  return "The SIM card requires a PIN to operate";
3320  case 312:
3321  /*
3322  * The AT command +CPIN (command name in text: Enter PIN)
3323  * can be used to send the PH-SIM PIN to the SIM card.
3324  */
3325  return "The SIM card requires a PH-SIM PIN to operate";
3326  case 313:
3327  return "SIM card failure";
3328  case 314:
3329  return "The SIM card is busy";
3330  case 315:
3331  return "The SIM card is wrong";
3332  case 316:
3333  /*
3334  * The AT command +CPIN (command name in text: Enter PIN)
3335  * can be used to send the PUK to the SIM card.
3336  */
3337  return "The SIM card requires a PUK to operate";
3338  case 317:
3339  return "The SIM card requires a PIN2 to operate";
3340  case 318:
3341  return "The SIM card requires a PUK2 to operate";
3342  case 320:
3343  return "Memory/message storage failure";
3344  case 321:
3345  return "The memory/message storage index assigned to the AT command is invalid";
3346  case 322:
3347  return "The memory/message storage is out of space";
3348  case 330:
3349  return "The SMS center (SMSC) address is unknown";
3350  case 331:
3351  return "No network service is available";
3352  case 332:
3353  return "Network timeout occurred";
3354  case 340:
3355  return "There is no need to send message ack by the AT command +CNMA";
3356  case 500:
3357  return "An unknown error occurred";
3358  case 512:
3359  /*
3360  * Resulting from +CMGS, +CMSS
3361  */
3362  return "User abort or MM establishment failure (SMS)";
3363  case 513:
3364  /*
3365  * Resulting from +CMGS, +CMSS
3366  */
3367  return "Lower layer falure (SMS)";
3368  case 514:
3369  /*
3370  * Resulting from +CMGS, +CMSS
3371  */
3372  return "CP error (SMS)";
3373  case 515:
3374  return "Please wait, service not available, init or command in progress";
3375  case 517:
3376  /*
3377  * Resulting from +STGI
3378  */
3379  return "SIM ToolKit facility not supported";
3380  case 518:
3381  /*
3382  * Resulting from +STGI
3383  */
3384  return "SIM ToolKit indication not received";
3385  case 519:
3386  /*
3387  * Resulting from +ECHO, +VIP
3388  */
3389  return "Reset the product to activate or change a new echo cancellation algorithm";
3390  case 520:
3391  /*
3392  * Resulting from +COPS=?
3393  */
3394  return "Automatic abort about get plmn list for an incoming call";
3395  case 526:
3396  /*
3397  * Resulting from +CLCK
3398  */
3399  return "PIN deactivation forbidden with this SIM card";
3400  case 527:
3401  /*
3402  * Resulting from +COPS
3403  */
3404  return "Please wait, RR or MM is busy. Retry your selection later";
3405  case 528:
3406  /*
3407  * Resulting from +COPS
3408  */
3409  return "Location update failure. Emergency calls only";
3410  case 529:
3411  /*
3412  * Resulting from +COPS
3413  */
3414  return "PLMN selection failure. Emergency calls only";
3415  case 531:
3416  /*
3417  * Resulting from +CMGS, +CMSS
3418  */
3419  return "SMS not sent: the <da> is not in FDN phonebook, and FDN lock is enabled";
3420  case 532:
3421  /*
3422  * Resulting from +WOPEN
3423  */
3424  return "The embedded application is activated so the objects flash are not erased";
3425  case 533:
3426  /*
3427  * Resulting from +ATD*99,+GACT,+CGDATA
3428  */
3429  return "Missing or unknown APN";
3430  default:
3431  return "Error number unknown. Ask google and add it";
3432  }
3433 }
3434 
Octstr * detect_string2
Definition: smsc_at.h:103
Octstr * name
Definition: smscconn_p.h:173
void error(int err, const char *fmt,...)
Definition: log.c:648
long year
Definition: date.h:72
static void at2_device_thread(void *arg)
Definition: smsc_at.c:1282
static int at2_test_speed(PrivAT2data *privdata, long speed)
Definition: smsc_at.c:2592
void info(int err, const char *fmt,...)
Definition: log.c:672
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
#define PNT_INTER
Definition: smsc_at.h:83
void bb_smscconn_connected(SMSCConn *conn)
Definition: bb_smscconn.c:192
static int at2_wait_modem_command(PrivAT2data *privdata, time_t timeout, int gt_flag, int *output)
Definition: smsc_at.c:764
static Octstr * at2_convertpdu(Octstr *pdutext)
Definition: smsc_at.c:2149
void * gwlist_search(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:486
#define AT_DELIVER_SM
Definition: smsc_at.h:77
void octstr_append_data(Octstr *ostr, const char *data, long len)
Definition: octstr.c:1497
static const char * at2_error_string(int errcode)
Definition: smsc_at.c:2967
static long at2_queued_cb(SMSCConn *conn)
Definition: smsc_at.c:1484
#define RETRY_WRITE
Definition: smsc_at.h:87
gw_assert(wtls_machine->packet_to_send !=NULL)
static int at2_login_device(PrivAT2data *privdata)
Definition: smsc_at.c:201
#define mutex_unlock(m)
Definition: thread.h:136
void gwlist_append(List *list, void *item)
Definition: list.c:179
int alt_dcs
Definition: smscconn_p.h:201
int tcpip_connect_to_server(char *hostname, int port, const char *source_addr)
Definition: socket.c:149
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1504
#define AT2_DEFAULT_SMS_POLL_INTERVAL
Definition: smsc_at.h:94
Octstr * id
Definition: smscconn_p.h:174
long gwlist_len(List *list)
Definition: list.c:166
long validityperiod
Definition: smsc_oisd.c:94
void * data
Definition: smscconn_p.h:250
static int reconnect(SMSCConn *conn)
Definition: smsc_wrapper.c:97
Octstr * cfg_get_configfile(CfgGroup *grp)
Definition: cfg.c:716
static Msg * at2_pdu_decode(Octstr *data, PrivAT2data *privdata)
Definition: smsc_at.c:1818
static int at2_lmask[8]
Definition: smsc_at.c:2165
int no_pin
Definition: smsc_at.h:109
List * outgoing_queue
Definition: smsc_cgw.c:153
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1517
int sms_msgdata_len(Msg *msg)
Definition: sms.c:180
void charset_utf8_to_gsm(Octstr *ostr)
Definition: charset.c:288
int load_add_interval(Load *load, int interval)
Definition: load.c:111
msg_type
Definition: msg.h:73
Octstr * password
Definition: smsc_cimd2.c:100
int log_idx
Definition: smscconn_p.h:197
int type
Definition: smsc_cimd2.c:215
static Msg * at2_pdu_decode_deliver_sm(Octstr *data, PrivAT2data *privdata)
Definition: smsc_at.c:1842
Octstr * init_string
Definition: smsc_at.h:104
long octstr_search(const Octstr *haystack, const Octstr *needle, long pos)
Definition: octstr.c:1070
#define cfg_get(grp, varname)
Definition: cfg.h:86
#define DC_8BIT
Definition: sms.h:111
static int at2_check_sms_memory(PrivAT2data *privdata)
Definition: smsc_at.c:1125
Load * load_create_real(int heuristic)
Definition: load.c:97
#define gw_prioqueue_produce(queue, item)
Definition: gw-prioqueue.h:98
#define msg_create(type)
Definition: msg.h:136
long minute
Definition: date.h:74
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1511
static Cfg * cfg
Definition: opensmppbox.c:95
void octstr_strip_blanks(Octstr *text)
Definition: octstr.c:1346
double load_get(Load *load, int pos)
Definition: load.c:191
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
Definition: dlr.c:387
void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg, int use_dst)
Definition: dlr.c:330
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
void 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
static int at2_init_device(PrivAT2data *privdata)
Definition: smsc_at.c:579
long reconnect_delay
Definition: smscconn_p.h:199
void log_thread_to(int idx)
Definition: log.c:759
int hardware_flow_control
Definition: smsc_at.h:117
FILE * file
Definition: log.c:169
static int at2_set_message_storage(PrivAT2data *privdata, Octstr *memory_name)
Definition: smsc_at.c:2951
int smsc_at2_create(SMSCConn *conn, CfgGroup *cfg)
Definition: smsc_at.c:1519
Cfg * cfg_create(Octstr *filename)
Definition: cfg.c:318
#define SMS_7BIT_MAX_LEN
Definition: sms.h:122
int cfg_read(Cfg *cfg)
Definition: cfg.c:452
static Msg * at2_pdu_decode_report_sm(Octstr *data, PrivAT2data *privdata)
Definition: smsc_at.c:2039
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
#define DLR_SUCCESS
Definition: dlr.h:72
static void at2_read_pending_incoming_messages(PrivAT2data *privdata)
Definition: smsc_at.c:981
#define MAX_READ
Definition: smsc_at.h:74
static int at2_read_delete_message(PrivAT2data *privdata, int message_number)
Definition: smsc_at.c:935
int broken
Definition: smsc_at.h:113
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
void * location
Definition: test_cimd2.c:1001
Definition: msg.h:79
Definition: cfg.c:164
int sms_priority_compare(const void *a, const void *b)
Definition: sms.c:395
Octstr * my_number
Definition: smsc_cimd2.c:105
void cfg_destroy(Cfg *cfg)
Definition: cfg.c:331
void * gwlist_extract_first(List *list)
Definition: list.c:305
static int at2_hexchar(int hexc)
Definition: smsc_at.c:1811
static Octstr * gsm2number(Octstr *pdu)
Definition: smsc_at.c:1758
static int at2_shutdown_cb(SMSCConn *conn, int finish_sending)
Definition: smsc_at.c:1454
static ModemDef * at2_read_modems(PrivAT2data *privdata, Octstr *file, Octstr *id, int idnumber)
Definition: smsc_at.c:2758
Octstr * reset_string
Definition: smsc_at.h:105
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1527
static int at2_read_sms_memory(PrivAT2data *privdata)
Definition: smsc_at.c:1062
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:477
static void at2_flush_buffer(PrivAT2data *privdata)
Definition: smsc_at.c:571
char * text
Definition: smsc_cimd2.c:921
Octstr * message_storage
Definition: smsc_at.h:114
#define PNT_UNKNOWN
Definition: smsc_at.h:82
time_t connect_time
Definition: smscconn_p.h:155
static int at2_add_msg_cb(SMSCConn *conn, Msg *sms)
Definition: smsc_at.c:1508
static int at2_send_modem_command(PrivAT2data *privdata, char *cmd, time_t timeout, int gt_flag)
Definition: smsc_at.c:756
static int at2_detect_speed(PrivAT2data *privdata)
Definition: smsc_at.c:2562
#define octstr_duplicate(ostr)
Definition: octstr.h:187
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:645
static Octstr * at2_pdu_encode(Msg *msg, PrivAT2data *privdata)
Definition: smsc_at.c:2353
double throughput
Definition: smscconn_p.h:203
long day
Definition: date.h:70
int octstr_item_match(void *item, void *pattern)
Definition: octstr.c:1661
Mutex * flow_mutex
Definition: smscconn_p.h:157
static void at2_scan_for_telnet_escapes(PrivAT2data *privdata)
Definition: smsc_at.c:103
Octstr * username
Definition: smsc_cimd2.c:99
long speed
Definition: smsc_at.h:106
static unsigned char nibble2hex(unsigned char b)
Definition: smsc_at.c:1750
static int swap_nibbles(unsigned char byte)
Definition: smsc_at.c:2893
void warning(int err, const char *fmt,...)
Definition: log.c:660
void * gw_prioqueue_remove(gw_prioqueue_t *queue)
Definition: gw-prioqueue.c:265
time_t end_time
Definition: fakewap.c:241
static void at2_close_device(PrivAT2data *privdata)
Definition: smsc_at.c:288
Octstr * detect_string
Definition: smsc_at.h:102
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
long gw_prioqueue_len(gw_prioqueue_t *queue)
Definition: gw-prioqueue.c:220
static int at2_open_device1(PrivAT2data *privdata)
Definition: smsc_at.c:163
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define SMS_8BIT_MAX_LEN
Definition: sms.h:123
static void at2_send_one_message(PrivAT2data *privdata, Msg *msg)
Definition: smsc_at.c:2230
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
static void at2_set_speed(PrivAT2data *privdata, int bps)
Definition: smsc_at.c:1193
void octstr_destroy_item(void *os)
Definition: octstr.c:336
long message_start
Definition: smsc_at.h:115
int fields_to_dcs(Msg *msg, int mode)
Definition: sms.c:73
#define O_DESTROY(a)
Definition: smsbox.c:97
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
static void at2_send_messages(PrivAT2data *privdata)
Definition: smsc_at.c:2211
#define AT_STATUS_REPORT_SM
Definition: smsc_at.h:79
static int at2_rmask[8]
Definition: smsc_at.c:2164
long sendline_sleep
Definition: smsc_at.h:111
static Octstr * at2_encode7bituncompressed(Octstr *source, int offset)
Definition: smsc_at.c:2501
long second
Definition: date.h:75
Octstr * name
Definition: smsc_at.h:101
int shutdown
Definition: smsc_cgw.c:156
static void at2_read_buffer(PrivAT2data *privdata, double timeout)
Definition: smsc_at.c:302
static void at2_decode7bituncompressed(Octstr *input, int len, Octstr *decoded, int offset)
Definition: smsc_at.c:2167
#define load_increase(load)
Definition: load.h:94
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Octstr * id
Definition: smsc_at.h:100
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:759
void gw_prioqueue_destroy(gw_prioqueue_t *queue, void(*item_destroy)(void *))
Definition: gw-prioqueue.c:201
Octstr * enable_hwhs
Definition: smsc_at.h:107
Definition: octstr.c:118
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:281
int(* shutdown)(SMSCConn *conn, int finish_sending)
Definition: smscconn_p.h:230
int need_sleep
Definition: smsc_at.h:108
long hour
Definition: date.h:73
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 at2_destroy_modem(ModemDef *modem)
Definition: smsc_at.c:2876
#define panic
Definition: log.h:87
void gwthread_wakeup(long thread)
#define CRTSCTS
Definition: smsc_emi_x25.c:88
Definition: cfg.c:73
#define MSG_PARAM_UNDEFINED
Definition: msg.h:71
int octstr_hex_to_binary(Octstr *ostr)
Definition: octstr.c:494
int octstr_str_compare(const Octstr *ostr, const char *str)
Definition: octstr.c:973
void load_destroy(Load *load)
Definition: load.c:145
Octstr * keepalive_cmd
Definition: smsc_at.h:112
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
static int at2_numtext(int num)
Definition: smsc_at.c:2556
static int at2_open_device(PrivAT2data *privdata)
Definition: smsc_at.c:225
#define gwlist_create()
Definition: list.h:136
static int at2_write(PrivAT2data *privdata, char *line)
Definition: smsc_at.c:538
long(* queued)(SMSCConn *conn)
Definition: smscconn_p.h:241
static int at2_write_ctrlz(PrivAT2data *privdata)
Definition: smsc_at.c:509
void octstr_truncate(Octstr *ostr, int new_len)
Definition: octstr.c:1327
static int at2_pdu_extract(PrivAT2data *privdata, Octstr **pdu, Octstr *line, Octstr *smsc_number)
Definition: smsc_at.c:1670
int(* send_msg)(SMSCConn *conn, Msg *msg)
Definition: smscconn_p.h:236
void kannel_cfmakeraw(struct termios *tio)
Definition: utils.c:951
#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
static Octstr * at2_wait_line(PrivAT2data *privdata, time_t timeout, int gt_flag)
Definition: smsc_at.c:357
int dcs_to_fields(Msg **msg, int dcs)
Definition: sms.c:139
static void at2_start_cb(SMSCConn *conn)
Definition: smsc_at.c:1495
long date_convert_universal(struct universaltime *t)
Definition: date.c:118
static Octstr * at2_format_address_field(Octstr *msisdn)
Definition: smsc_at.c:2899
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406
#define mutex_lock(m)
Definition: thread.h:130
static int at2_write_line(PrivAT2data *privdata, char *line)
Definition: smsc_at.c:470
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:415
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82
int enable_mms
Definition: smsc_at.h:116
#define octstr_create_from_data(data, len)
Definition: octstr.h:134
static Octstr * at2_encode8bituncompressed(Octstr *input)
Definition: smsc_at.c:2540
List * octstr_split(const Octstr *os, const Octstr *sep)
Definition: octstr.c:1640
long keepalive
Definition: smsc_cimd2.c:104
Definition: list.c:102
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static Octstr * at2_extract_line(PrivAT2data *privdata, int gt_flag)
Definition: smsc_at.c:379
#define DLR_FAIL
Definition: dlr.h:73
int no_smsc
Definition: smsc_at.h:110
static int start
static Octstr * at2_read_line(PrivAT2data *privdata, int gt_flag, double timeout)
Definition: smsc_at.c:457
static int at2_detect_modem_type(PrivAT2data *privdata)
Definition: smsc_at.c:2616
#define DC_UCS2
Definition: sms.h:112
#define DC_7BIT
Definition: sms.h:110
SMSCConn * conn
Definition: smsc_cimd2.c:118
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
int load
Definition: smscconn_p.h:152
void charset_gsm_to_utf8(Octstr *ostr)
Definition: charset.c:220
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.