Kannel: Open Source WAP and SMS gateway  svn-r5335
smsc_emi_x25.c File Reference
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdarg.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include "gwlib/gwlib.h"
#include "smsc.h"
#include "smsc_p.h"
#include "alt_charsets.h"
#include "sms.h"

Go to the source code of this file.

Macros

#define CRTSCTS   0
 

Functions

static int get_data (SMSCenter *smsc, char *buff, int length)
 
static int put_data (SMSCenter *smsc, char *buff, int length, int is_backup)
 
static int memorybuffer_append_data (SMSCenter *smsc, char *buff, int length)
 
static int memorybuffer_insert_data (SMSCenter *smsc, char *buff, int length)
 
static int memorybuffer_has_rawmessage (SMSCenter *smsc, int type, char auth)
 
static int memorybuffer_cut_rawmessage (SMSCenter *smsc, char *buff, int length)
 
static int parse_rawmessage_to_msg (SMSCenter *smsc, Msg **msg, char *rawmessage, int length)
 
static int parse_msg_to_rawmessage (SMSCenter *smsc, Msg *msg, char *rawmessage, int length)
 
static int acknowledge_from_rawmessage (SMSCenter *smsc, char *rawmessage, int length)
 
static int parse_emi_to_iso88591 (char *from, char *to, int length, int alt_charset)
 
static int parse_iso88591_to_emi (char *from, char *to, int length, int alt_charset)
 
static int parse_binary_to_emi (char *from, char *to, int length)
 
static int at_dial (char *device, char *phonenum, char *at_prefix, time_t how_long)
 
static int guarantee_link (SMSCenter *smsc)
 
static void generate_checksum (const unsigned char *buffer, unsigned char *checksum_out)
 
static int wait_for_ack (SMSCenter *smsc, int op_type)
 
static char char_iso_to_sms (unsigned char from, int alt_charset)
 
static char char_sms_to_iso (unsigned char from, int alt_charset)
 
static int emi_open_connection (SMSCenter *smsc)
 
SMSCenteremi_open (char *phonenum, char *serialdevice, char *username, char *password)
 
int emi_reopen (SMSCenter *smsc)
 
int emi_close (SMSCenter *smsc)
 
static int emi_fill_ucp60_login (char *buf, char *OAdC, char *passwd)
 
static int emi_open_session (SMSCenter *smsc)
 
static int emi_open_connection_ip (SMSCenter *smsc)
 
int emi_reopen_ip (SMSCenter *smsc)
 
int emi_close_ip (SMSCenter *smsc)
 
int emi_pending_smsmessage (SMSCenter *smsc)
 
int emi_submit_msg (SMSCenter *smsc, Msg *omsg)
 
int emi_receive_msg (SMSCenter *smsc, Msg **tmsg)
 

Macro Definition Documentation

◆ CRTSCTS

#define CRTSCTS   0

Definition at line 88 of file smsc_emi_x25.c.

Referenced by at2_open_device(), and at_dial().

Function Documentation

◆ acknowledge_from_rawmessage()

static int acknowledge_from_rawmessage ( SMSCenter smsc,
char *  rawmessage,
int  length 
)
static

Definition at line 964 of file smsc_emi_x25.c.

References debug(), SMSCenter::emi_current_msg_number, generate_checksum(), and put_data().

Referenced by emi_receive_msg().

966 {
967 
968  char emivars[128][1024];
969  char timestamp[2048], sender[2048], receiver[2048];
970  char emitext[2048], isotext[2048];
971  char *leftslash, *rightslash;
972  int msgnbr;
973  int tmpint;
974  int is_backup = 0;
975 
976  msgnbr = -1;
977  memset(&sender, 0, sizeof(sender));
978  memset(&receiver, 0, sizeof(receiver));
979  memset(&emitext, 0, sizeof(emitext));
980  memset(&isotext, 0, sizeof(isotext));
981  memset(&timestamp, 0, sizeof(timestamp));
982 
983  strncpy(isotext, rawmessage, length);
984  leftslash = isotext;
985 
986  if (isotext[length - 1] == 'X')
987  is_backup = 1;
988 
989  for (tmpint = 0; leftslash != NULL; tmpint++) {
990  rightslash = strchr(leftslash + 1, '/');
991 
992  if (rightslash == NULL)
993  rightslash = strchr(leftslash + 1, '\3');
994 
995  if (rightslash == NULL)
996  break;
997 
998  *rightslash = '\0';
999  strcpy(emivars[tmpint], leftslash + 1);
1000  leftslash = rightslash;
1001  }
1002 
1003  /* BODY */
1004  sprintf(isotext, "A//%s:%s", emivars[4], emivars[18]);
1005  sprintf(isotext, "A//%s:", emivars[5]);
1006  is_backup = 0;
1007 
1008  /* HEADER */
1009 
1010  debug("bb.sms.emi", 0, "acknowledge: type = '%s'", emivars[3]);
1011 
1012  sprintf(emitext, "%s/%05i/%s/%s", emivars[0], (int) strlen(isotext) + 17,
1013  "R", emivars[3]);
1014 
1015  smsc->emi_current_msg_number = atoi(emivars[0]) + 1;
1016 
1017  /* FOOTER */
1018  sprintf(timestamp, "%s/%s/", emitext, isotext);
1019  generate_checksum((unsigned char *)timestamp, (unsigned char *)receiver);
1020 
1021  sprintf(sender, "%c%s/%s/%s%c", 0x02, emitext, isotext, receiver, 0x03);
1022  put_data(smsc, sender, strlen(sender), is_backup);
1023 
1024  return msgnbr;
1025 
1026 }
static void generate_checksum(const unsigned char *buffer, unsigned char *checksum_out)
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup)
Definition: smsc_emi_x25.c:755
int emi_current_msg_number
Definition: smsc_p.h:153

◆ at_dial()

static int at_dial ( char *  device,
char *  phonenum,
char *  at_prefix,
time_t  how_long 
)
static

Definition at line 472 of file smsc_emi_x25.c.

References CRTSCTS, debug(), error(), info(), and kannel_cfmakeraw().

Referenced by emi_open_connection().

473 {
474  char tmpbuff[1024];
475  int howmanyread = 0;
476  int thistime = 0;
477  int redial;
478  int fd = -1;
479  int ret;
480  time_t timestart;
481  struct termios tios;
482 
483  /* The time at the start of the function is used when
484  determining whether we have used up our allotted
485  dial time and have to abort. */
486  time(&timestart);
487 
488  /* Open the device properly. Remember to set the
489  access codes correctly. */
490  fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY);
491  if (fd == -1) {
492  error(errno, "at_dial: error opening character device <%s>", device);
493  goto error;
494  }
495  tcflush(fd, TCIOFLUSH);
496 
497  /* The speed initialisation is pretty important. */
498  tcgetattr(fd, &tios);
499 #if defined(B115200)
500  cfsetospeed(&tios, B115200);
501  cfsetispeed(&tios, B115200);
502 #elif defined(B76800)
503  cfsetospeed(&tios, B76800);
504  cfsetispeed(&tios, B76800);
505 #elif defined(B57600)
506  cfsetospeed(&tios, B57600);
507  cfsetispeed(&tios, B57600);
508 #elif defined(B38400)
509  cfsetospeed(&tios, B38400);
510  cfsetispeed(&tios, B38400);
511 #elif defined(B19200)
512  cfsetospeed(&tios, B19200);
513  cfsetispeed(&tios, B19200);
514 #elif defined(B9600)
515  cfsetospeed(&tios, B9600);
516  cfsetispeed(&tios, B9600);
517 #endif
518  kannel_cfmakeraw(&tios);
519  tios.c_cflag |= (HUPCL | CREAD | CRTSCTS);
520  ret = tcsetattr(fd, TCSANOW, &tios);
521  if (ret == -1) {
522  error(errno, "EMI[X25]: at_dial: fail to set termios attribute");
523  }
524 
525  /* Dial using an AT command string. */
526  for (redial = 1; redial; ) {
527  info(0, "at_dial: dialing <%s> on <%s> for <%i> seconds",
528  phonenum, device,
529  (int)(how_long - (time(NULL) - timestart)));
530 
531  /* Send AT dial request. */
532  howmanyread = 0;
533  sprintf(tmpbuff, "%s%s\r\n", at_prefix, phonenum);
534  ret = write(fd, tmpbuff, strlen(tmpbuff)); /* errors... -mg */
535  memset(&tmpbuff, 0, sizeof(tmpbuff));
536 
537  /* Read the answer to the AT command and react accordingly. */
538  for (; ; ) {
539  /* We don't want to dial forever */
540  if (how_long != 0 && time(NULL) > timestart + how_long)
541  goto timeout;
542 
543  /* We don't need more space for dialout */
544  if (howmanyread >= (int) sizeof(tmpbuff))
545  goto error;
546 
547  /* We read 1 char a time so that we don't
548  accidentally read past the modem chat and
549  into the SMSC datastream -mg */
550  thistime = read(fd, &tmpbuff[howmanyread], 1);
551  if (thistime == -1) {
552  if (errno == EAGAIN) continue;
553  if (errno == EINTR) continue;
554  goto error;
555  } else {
556  howmanyread += thistime;
557  }
558 
559  /* Search for the newline on the AT status line. */
560  if (tmpbuff[howmanyread - 1] == '\r'
561  || tmpbuff[howmanyread - 1] == '\n') {
562 
563  /* XXX ADD ALL POSSIBLE CHAT STRINGS XXX */
564 
565  if (strstr(tmpbuff, "CONNECT") != NULL) {
566  debug("bb.sms.emi", 0, "at_dial: CONNECT");
567  redial = 0;
568  break;
569 
570  } else if (strstr(tmpbuff, "NO CARRIER") != NULL) {
571  debug("bb.sms.emi", 0, "at_dial: NO CARRIER");
572  redial = 1;
573  break;
574 
575  } else if (strstr(tmpbuff, "BUSY") != NULL) {
576  debug("bb.sms.emi", 0, "at_dial: BUSY");
577  redial = 1;
578  break;
579 
580  } else if (strstr(tmpbuff, "NO DIALTONE") != NULL) {
581  debug("bb.sms.emi", 0, "at_dial: NO DIALTONE");
582  redial = 1;
583  break;
584 
585  }
586 
587  } /* End of if lastchr=='\r'||'\n'. */
588 
589  /* Thou shall not consume all system resources
590  by repeatedly looping a strstr search when
591  the string update latency is very high as it
592  is in serial communication. -mg */
593  usleep(1000);
594 
595  } /* End of read loop. */
596 
597  /* Thou shall not flood the modem with dial requests. -mg */
598  sleep(1);
599 
600  } /* End of dial loop. */
601 
602  debug("bb.sms.emi", 0, "at_dial: done with dialing");
603  return fd;
604 
605 timeout:
606  error(0, "at_dial timed out");
607  close(fd);
608  return -1;
609 
610 error:
611  error(0, "at_dial failed");
612  close(fd);
613  return -1;
614 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define CRTSCTS
Definition: smsc_emi_x25.c:88
void kannel_cfmakeraw(struct termios *tio)
Definition: utils.c:951

◆ char_iso_to_sms()

static char char_iso_to_sms ( unsigned char  from,
int  alt_charset 
)
static

Definition at line 1235 of file smsc_emi_x25.c.

References alt_charset, EMI_SWAPPED_CHARS, and from.

Referenced by parse_iso88591_to_emi().

1236 {
1237 
1238  switch ((char)from) {
1239 
1240  case 'A':
1241  return 0x41;
1242  case 'B':
1243  return 0x42;
1244  case 'C':
1245  return 0x43;
1246  case 'D':
1247  return 0x44;
1248  case 'E':
1249  return 0x45;
1250  case 'F':
1251  return 0x46;
1252  case 'G':
1253  return 0x47;
1254  case 'H':
1255  return 0x48;
1256  case 'I':
1257  return 0x49;
1258  case 'J':
1259  return 0x4A;
1260  case 'K':
1261  return 0x4B;
1262  case 'L':
1263  return 0x4C;
1264  case 'M':
1265  return 0x4D;
1266  case 'N':
1267  return 0x4E;
1268  case 'O':
1269  return 0x4F;
1270  case 'P':
1271  return 0x50;
1272  case 'Q':
1273  return 0x51;
1274  case 'R':
1275  return 0x52;
1276  case 'S':
1277  return 0x53;
1278  case 'T':
1279  return 0x54;
1280  case 'U':
1281  return 0x55;
1282  case 'V':
1283  return 0x56;
1284  case 'W':
1285  return 0x57;
1286  case 'X':
1287  return 0x58;
1288  case 'Y':
1289  return 0x59;
1290  case 'Z':
1291  return 0x5A;
1292 
1293  case 'a':
1294  return 0x61;
1295  case 'b':
1296  return 0x62;
1297  case 'c':
1298  return 0x63;
1299  case 'd':
1300  return 0x64;
1301  case 'e':
1302  return 0x65;
1303  case 'f':
1304  return 0x66;
1305  case 'g':
1306  return 0x67;
1307  case 'h':
1308  return 0x68;
1309  case 'i':
1310  return 0x69;
1311  case 'j':
1312  return 0x6A;
1313  case 'k':
1314  return 0x6B;
1315  case 'l':
1316  return 0x6C;
1317  case 'm':
1318  return 0x6D;
1319  case 'n':
1320  return 0x6E;
1321  case 'o':
1322  return 0x6F;
1323  case 'p':
1324  return 0x70;
1325  case 'q':
1326  return 0x71;
1327  case 'r':
1328  return 0x72;
1329  case 's':
1330  return 0x73;
1331  case 't':
1332  return 0x74;
1333  case 'u':
1334  return 0x75;
1335  case 'v':
1336  return 0x76;
1337  case 'w':
1338  return 0x77;
1339  case 'x':
1340  return 0x78;
1341  case 'y':
1342  return 0x79;
1343  case 'z':
1344  return 0x7A;
1345 
1346  case '0':
1347  return 0x30;
1348  case '1':
1349  return 0x31;
1350  case '2':
1351  return 0x32;
1352  case '3':
1353  return 0x33;
1354  case '4':
1355  return 0x34;
1356  case '5':
1357  return 0x35;
1358  case '6':
1359  return 0x36;
1360  case '7':
1361  return 0x37;
1362  case '8':
1363  return 0x38;
1364  case '9':
1365  return 0x39;
1366  case ':':
1367  return 0x3A;
1368  case ';':
1369  return 0x3B;
1370  case '<':
1371  return 0x3C;
1372  case '=':
1373  return 0x3D;
1374  case '>':
1375  return 0x3E;
1376  case '?':
1377  return 0x3F;
1378 
1379  case 'Ä':
1380  return '[';
1381  case 'Ö':
1382  return '\\';
1383  case 'Å':
1384  return 0x0E;
1385  case 'Ü':
1386  return ']';
1387  case 'ä':
1388  return '{';
1389  case 'ö':
1390  return '|';
1391  case 'å':
1392  return 0x0F;
1393  case 'ü':
1394  return '}';
1395  case 'ß':
1396  return '~';
1397  case '§':
1398  return '^';
1399  case 'Ñ':
1400  return 0x5F;
1401  case 'ø':
1402  return 0x0C;
1403 
1404  /* case 'Delta': return 0x10; */
1405  /* case 'Fii': return 0x12; */
1406  /* case 'Lambda': return 0x13; */
1407  /* case 'Alpha': return 0x14; */
1408  /* case 'Omega': return 0x15; */
1409  /* case 'Pii': return 0x16; */
1410  /* case 'Pii': return 0x17; */
1411  /* case 'Delta': return 0x18; */
1412  /* case 'Delta': return 0x19; */
1413  /* case 'Delta': return 0x1A; */
1414 
1415  case ' ':
1416  return 0x20;
1417  case '@':
1419  return 0x00;
1420  else
1421  return 0x40;
1422  case '£':
1423  return 0x01;
1424  case '$':
1425  return 0x24;
1426  case '¥':
1427  return 0x03;
1428  case 'è':
1429  return 0x04;
1430  case 'é':
1431  return 0x05;
1432  case 'ù':
1433  return 0x06;
1434  case 'ì':
1435  return 0x07;
1436  case 'ò':
1437  return 0x08;
1438  case 'Ç':
1439  return 0x09;
1440  case '\r':
1441  return 0x0A;
1442  case 'Ø':
1443  return 0x0B;
1444  case '\n':
1445  return 0x0D;
1446  case 'Æ':
1447  return 0x1C;
1448  case 'æ':
1449  return 0x1D;
1450  case 'É':
1451  return 0x1F;
1452 
1453  case '!':
1454  return 0x21;
1455  case '"':
1456  return 0x22;
1457  case '#':
1458  return 0x23;
1459  case '¤':
1460  return 0x02;
1461  case '%':
1462  return 0x25;
1463 
1464  case '&':
1465  return 0x26;
1466  case '\'':
1467  return 0x27;
1468  case '(':
1469  return 0x28;
1470  case ')':
1471  return 0x29;
1472  case '*':
1473  return 0x2A;
1474 
1475  case '+':
1476  return 0x2B;
1477  case ',':
1478  return 0x2C;
1479  case '-':
1480  return 0x2D;
1481  case '.':
1482  return 0x2E;
1483  case '/':
1484  return 0x2F;
1485 
1486  case '¿':
1487  return 0x60;
1488  case 'ñ':
1489  return 0x1E;
1490  case 'à':
1491  return 0x7F;
1492  case '¡':
1494  return 0x40;
1495  else
1496  return 0x00;
1497  case '_':
1498  return 0x11;
1499 
1500  default:
1501  return 0x20; /* space */
1502 
1503  } /* switch */
1504 }
#define EMI_SWAPPED_CHARS
Definition: alt_charsets.h:77
static Octstr * from
Definition: mtbatch.c:95
static Octstr * alt_charset
Definition: opensmppbox.c:129

◆ char_sms_to_iso()

static char char_sms_to_iso ( unsigned char  from,
int  alt_charset 
)
static

Definition at line 1511 of file smsc_emi_x25.c.

References from.

Referenced by parse_emi_to_iso88591().

1512 {
1513 
1514  switch ((int)from) {
1515 
1516  case 0x41:
1517  return 'A';
1518  case 0x42:
1519  return 'B';
1520  case 0x43:
1521  return 'C';
1522  case 0x44:
1523  return 'D';
1524  case 0x45:
1525  return 'E';
1526  case 0x46:
1527  return 'F';
1528  case 0x47:
1529  return 'G';
1530  case 0x48:
1531  return 'H';
1532  case 0x49:
1533  return 'I';
1534  case 0x4A:
1535  return 'J';
1536  case 0x4B:
1537  return 'K';
1538  case 0x4C:
1539  return 'L';
1540  case 0x4D:
1541  return 'M';
1542  case 0x4E:
1543  return 'N';
1544  case 0x4F:
1545  return 'O';
1546  case 0x50:
1547  return 'P';
1548  case 0x51:
1549  return 'Q';
1550  case 0x52:
1551  return 'R';
1552  case 0x53:
1553  return 'S';
1554  case 0x54:
1555  return 'T';
1556  case 0x55:
1557  return 'U';
1558  case 0x56:
1559  return 'V';
1560  case 0x57:
1561  return 'W';
1562  case 0x58:
1563  return 'X';
1564  case 0x59:
1565  return 'Y';
1566  case 0x5A:
1567  return 'Z';
1568 
1569  case 0x61:
1570  return 'a';
1571  case 0x62:
1572  return 'b';
1573  case 0x63:
1574  return 'c';
1575  case 0x64:
1576  return 'd';
1577  case 0x65:
1578  return 'e';
1579  case 0x66:
1580  return 'f';
1581  case 0x67:
1582  return 'g';
1583  case 0x68:
1584  return 'h';
1585  case 0x69:
1586  return 'i';
1587  case 0x6A:
1588  return 'j';
1589  case 0x6B:
1590  return 'k';
1591  case 0x6C:
1592  return 'l';
1593  case 0x6D:
1594  return 'm';
1595  case 0x6E:
1596  return 'n';
1597  case 0x6F:
1598  return 'o';
1599  case 0x70:
1600  return 'p';
1601  case 0x71:
1602  return 'q';
1603  case 0x72:
1604  return 'r';
1605  case 0x73:
1606  return 's';
1607  case 0x74:
1608  return 't';
1609  case 0x75:
1610  return 'u';
1611  case 0x76:
1612  return 'v';
1613  case 0x77:
1614  return 'w';
1615  case 0x78:
1616  return 'x';
1617  case 0x79:
1618  return 'y';
1619  case 0x7A:
1620  return 'z';
1621 
1622  case 0x30:
1623  return '0';
1624  case 0x31:
1625  return '1';
1626  case 0x32:
1627  return '2';
1628  case 0x33:
1629  return '3';
1630  case 0x34:
1631  return '4';
1632  case 0x35:
1633  return '5';
1634  case 0x36:
1635  return '6';
1636  case 0x37:
1637  return '7';
1638  case 0x38:
1639  return '8';
1640  case 0x39:
1641  return '9';
1642  case 0x3A:
1643  return ':';
1644  case 0x3B:
1645  return ';';
1646  case 0x3C:
1647  return '<';
1648  case 0x3D:
1649  return '=';
1650  case 0x3E:
1651  return '>';
1652  case 0x3F:
1653  return '?';
1654 
1655  case '[':
1656  return 'Ä';
1657  case '\\':
1658  return 'Ö';
1659  case '\xC5':
1660  return 'Å';
1661  case ']':
1662  return 'Ü';
1663  case '{':
1664  return 'ä';
1665  case '|':
1666  return 'ö';
1667  case 0xE5:
1668  return 'å';
1669  case '}':
1670  return 'ü';
1671  case '~':
1672  return 'ß';
1673  case 0xA7:
1674  return '§';
1675  case 0xD1:
1676  return 'Ñ';
1677  case 0xF8:
1678  return 'ø';
1679 
1680  /* case 'Delta': return 0x10; */
1681  /* case 'Fii': return 0x12; */
1682  /* case 'Lambda': return 0x13; */
1683  /* case 'Alpha': return 0x14; */
1684  /* case 'Omega': return 0x15; */
1685  /* case 'Pii': return 0x16; */
1686  /* case 'Pii': return 0x17; */
1687  /* case 'Delta': return 0x18; */
1688  /* case 'Delta': return 0x19; */
1689  /* case 'Delta': return 0x1A; */
1690 
1691  case 0x20:
1692  return ' ';
1693  case 0x40:
1694  return '@';
1695  case 0xA3:
1696  return '£';
1697  case 0x24:
1698  return '$';
1699  case 0xA5:
1700  return '¥';
1701  case 0xE8:
1702  return 'è';
1703  case 0xE9:
1704  return 'é';
1705  case 0xF9:
1706  return 'ù';
1707  case 0xEC:
1708  return 'ì';
1709  case 0xF2:
1710  return 'ò';
1711  case 0xC7:
1712  return 'Ç';
1713  case 0x0A:
1714  return '\r';
1715  case 0xD8:
1716  return 'Ø';
1717  case 0x0D:
1718  return '\n';
1719  case 0xC6:
1720  return 'Æ';
1721  case 0xE6:
1722  return 'æ';
1723  case 0x1F:
1724  return 'É';
1725 
1726  case 0x21:
1727  return '!';
1728  case 0x22:
1729  return '"';
1730  case 0x23:
1731  return '#';
1732  case 0xA4:
1733  return '¤';
1734  case 0x25:
1735  return '%';
1736 
1737  case 0x26:
1738  return '&';
1739  case 0x27:
1740  return '\'';
1741  case 0x28:
1742  return '(';
1743  case 0x29:
1744  return ')';
1745  case 0x2A:
1746  return '*';
1747 
1748  case 0x2B:
1749  return '+';
1750  case 0x2C:
1751  return ',';
1752  case 0x2D:
1753  return '-';
1754  case 0x2E:
1755  return '.';
1756  case 0x2F:
1757  return '/';
1758 
1759  case 0xBF:
1760  return '¿';
1761  case 0xF1:
1762  return 'ñ';
1763  case 0xE0:
1764  return 'à';
1765  case 0xA1:
1766  return '¡';
1767  case 0x5F:
1768  return '_';
1769 
1770  default:
1771  return ' ';
1772 
1773  } /* switch */
1774 }
static Octstr * from
Definition: mtbatch.c:95

◆ emi_close()

int emi_close ( SMSCenter smsc)

Definition at line 194 of file smsc_emi_x25.c.

References emi_close_ip().

Referenced by emi_reopen(), and smsc_close().

195 {
196  return emi_close_ip(smsc);
197 }
int emi_close_ip(SMSCenter *smsc)
Definition: smsc_emi_x25.c:302

◆ emi_close_ip()

int emi_close_ip ( SMSCenter smsc)

Definition at line 302 of file smsc_emi_x25.c.

References SMSCenter::emi_fd, and info().

Referenced by emi_close(), and emi_reopen_ip().

303 {
304 
305  if (smsc->emi_fd == -1) {
306  info(0, "Trying to close already closed EMI, ignoring");
307  return 0;
308  }
309  close(smsc->emi_fd);
310  smsc->emi_fd = -1;
311 
312  return 0;
313 }
void info(int err, const char *fmt,...)
Definition: log.c:672
int emi_fd
Definition: smsc_p.h:145

◆ emi_fill_ucp60_login()

static int emi_fill_ucp60_login ( char *  buf,
char *  OAdC,
char *  passwd 
)
static

Definition at line 199 of file smsc_emi_x25.c.

References error(), and parse_binary_to_emi().

Referenced by emi_open_session().

199  {
200  int max_ia5passwd_len;
201  char *ia5passwd;
202 
203  max_ia5passwd_len = strlen(passwd) * 2 + 1;
204  ia5passwd = gw_malloc(max_ia5passwd_len);
205 
206  if (parse_binary_to_emi(passwd, ia5passwd, strlen(passwd)) < 0) {
207  error(0, "parse_binary_to_emi failed");
208  gw_free(ia5passwd);
209  return -1;
210  }
211 
212  sprintf(buf, "%s/%c/%c/%c/%s//%s/////",
213  OAdC, /* OAdC: Address code originator */
214  '6', /* OTON: 6 = Abbreviated number (short number alias) */
215  '5', /* ONPI: 5 = Private (TCP/IP address/abbreviated number address) */
216  '1', /* STYP: 1 = open session */
217  ia5passwd, /* PWD: Current password encoded into IA5 characters */
218  "0100" /* VERS: Version number 0100 */
219  );
220 
221  gw_free(ia5passwd);
222  return 0;
223 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static int parse_binary_to_emi(char *from, char *to, int length)

◆ emi_open()

SMSCenter* emi_open ( char *  phonenum,
char *  serialdevice,
char *  username,
char *  password 
)

Definition at line 153 of file smsc_emi_x25.c.

References SMSCenter::emi_current_msg_number, emi_open_connection(), SMSCenter::emi_password, SMSCenter::emi_phonenum, SMSCenter::emi_serialdevice, SMSCenter::emi_username, error(), SMSCenter::name, password, SMSC_TYPE_EMI_X25, smscenter_construct(), smscenter_destruct(), SMSCenter::type, and username.

Referenced by smsc_open().

154 {
155  SMSCenter *smsc;
156 
157  smsc = smscenter_construct();
158  if (smsc == NULL)
159  goto error;
160 
161  smsc->type = SMSC_TYPE_EMI_X25;
162 
163  smsc->emi_phonenum = gw_strdup(phonenum);
164  smsc->emi_serialdevice = gw_strdup(serialdevice);
165  smsc->emi_username = gw_strdup(username);
166  smsc->emi_password = gw_strdup(password);
167 
168  smsc->emi_current_msg_number = 0;
169 
170  if (emi_open_connection(smsc) < 0)
171  goto error;
172 
173  sprintf(smsc->name, "EMI:%s:%s", smsc->emi_phonenum,
174  smsc->emi_username);
175  return smsc;
176 
177 error:
178  error(0, "emi_open failed");
179  smscenter_destruct(smsc);
180  return NULL;
181 }
void error(int err, const char *fmt,...)
Definition: log.c:648
char * emi_password
Definition: smsc_p.h:152
unsigned char * username
Definition: test_cimd2.c:99
unsigned char * password
Definition: test_cimd2.c:100
char * emi_phonenum
Definition: smsc_p.h:147
SMSCenter * smscenter_construct(void)
Definition: smsc.c:101
char * emi_username
Definition: smsc_p.h:151
void smscenter_destruct(SMSCenter *smsc)
Definition: smsc.c:168
char * emi_serialdevice
Definition: smsc_p.h:148
static int emi_open_connection(SMSCenter *smsc)
Definition: smsc_emi_x25.c:138
int type
Definition: smsc_p.h:93
char name[1024]
Definition: smsc_p.h:96
int emi_current_msg_number
Definition: smsc_p.h:153

◆ emi_open_connection()

static int emi_open_connection ( SMSCenter smsc)
static

Definition at line 138 of file smsc_emi_x25.c.

References at_dial(), SMSCenter::emi_fd, SMSCenter::emi_phonenum, and SMSCenter::emi_serialdevice.

Referenced by emi_open(), emi_reopen(), and guarantee_link().

139 {
140  char tmpbuff[1024];
141 
142  sprintf(tmpbuff, "/dev/%s", smsc->emi_serialdevice);
143  smsc->emi_fd = at_dial(tmpbuff, smsc->emi_phonenum, "ATD", 30);
144 
145  if (smsc->emi_fd <= 0)
146  return -1;
147 
148  return 0;
149 }
char * emi_phonenum
Definition: smsc_p.h:147
char * emi_serialdevice
Definition: smsc_p.h:148
static int at_dial(char *device, char *phonenum, char *at_prefix, time_t how_long)
Definition: smsc_emi_x25.c:472
int emi_fd
Definition: smsc_p.h:145

◆ emi_open_connection_ip()

static int emi_open_connection_ip ( SMSCenter smsc)
static

Definition at line 276 of file smsc_emi_x25.c.

References SMSCenter::emi_fd, SMSCenter::emi_hostname, emi_open_session(), SMSCenter::emi_our_port, SMSCenter::emi_password, SMSCenter::emi_port, SMSCenter::emi_username, and tcpip_connect_to_server_with_port().

Referenced by emi_reopen_ip().

277 {
278  smsc->emi_fd =
280  smsc->emi_port, smsc->emi_our_port,
281  NULL);
282  /* XXX add interface_name if required */
283  if (smsc->emi_fd < 0)
284  return -1;
285 
286  if (smsc->emi_username && smsc->emi_password) {
287  return emi_open_session(smsc);
288  }
289 
290  return 0;
291 }
char * emi_password
Definition: smsc_p.h:152
char * emi_hostname
Definition: smsc_p.h:149
char * emi_username
Definition: smsc_p.h:151
int tcpip_connect_to_server_with_port(char *hostname, int port, int our_port, const char *source_addr)
Definition: socket.c:156
static int emi_open_session(SMSCenter *smsc)
Definition: smsc_emi_x25.c:225
int emi_fd
Definition: smsc_p.h:145
int emi_our_port
Definition: smsc_p.h:158
int emi_port
Definition: smsc_p.h:150

◆ emi_open_session()

static int emi_open_session ( SMSCenter smsc)
static

Definition at line 225 of file smsc_emi_x25.c.

References debug(), SMSCenter::emi_current_msg_number, emi_fill_ucp60_login(), SMSCenter::emi_password, SMSCenter::emi_username, error(), generate_checksum(), info(), put_data(), and wait_for_ack().

Referenced by emi_open_connection_ip().

226 {
227  char message_whole [1024];
228  char message_body [1024];
229  char message_header [50];
230  char message_footer [10];
231  char my_buffer [1024];
232  int length;
233 
234  memset(message_whole, 0, sizeof(message_whole));
235  memset(message_body, 0, sizeof(message_body));
236  memset(message_header, 0, sizeof(message_header));
237  memset(message_footer, 0, sizeof(message_footer));
238 
239  if (emi_fill_ucp60_login(message_body, smsc->emi_username, smsc->emi_password) < 0) {
240  error(0, "emi_fill_ucp60_login failed");
241  return -1;
242  }
243 
244  length = strlen(message_body);
245  length += 13; /* header (fixed) */
246  length += 2; /* footer (fixed) */
247  length += 2; /* slashes between header, body, footer */
248 
249  sprintf(message_header, "%02i/%05i/O/60",
250  (smsc->emi_current_msg_number++ % 100), length);
251 
252  /* FOOTER */
253 
254  sprintf(my_buffer, "%s/%s/", message_header, message_body);
255  generate_checksum((unsigned char *)my_buffer, (unsigned char *)message_footer);
256 
257  sprintf(message_whole, "\x02%s/%s/%s\x03", message_header,
258  message_body, message_footer);
259 
260  debug("bb.sms.emi", 0, "final UCP60 msg: <%s>", message_whole);
261 
262  put_data(smsc, message_whole, strlen(message_whole), 0);
263 
264  if (!wait_for_ack(smsc, 60)) {
265  info(0, "emi_open_session: wait for ack failed!");
266  return -1;
267  }
268 
269  return 0;
270 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
char * emi_password
Definition: smsc_p.h:152
static void generate_checksum(const unsigned char *buffer, unsigned char *checksum_out)
static int emi_fill_ucp60_login(char *buf, char *OAdC, char *passwd)
Definition: smsc_emi_x25.c:199
char * emi_username
Definition: smsc_p.h:151
static int wait_for_ack(SMSCenter *smsc, int op_type)
Definition: smsc_emi_x25.c:621
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup)
Definition: smsc_emi_x25.c:755
int emi_current_msg_number
Definition: smsc_p.h:153

◆ emi_pending_smsmessage()

int emi_pending_smsmessage ( SMSCenter smsc)

Definition at line 319 of file smsc_emi_x25.c.

References get_data(), guarantee_link(), memorybuffer_cut_rawmessage(), memorybuffer_has_rawmessage(), and memorybuffer_insert_data().

Referenced by smscenter_pending_smsmessage().

320 {
321 
322  char *tmpbuff;
323  int n = 0;
324  /* time_t timenow; */
325 
326  /* Block until we have a connection */
327  guarantee_link(smsc);
328 
329  /* If we have MO-message, then act (return 1) */
330  if (memorybuffer_has_rawmessage(smsc, 52, 'O') > 0 ||
331  memorybuffer_has_rawmessage(smsc, 1, 'O') > 0 )
332  return 1;
333 
334  tmpbuff = gw_malloc(10 * 1024);
335  memset(tmpbuff, 0, 10*1024);
336 
337  /* check for data */
338  n = get_data(smsc, tmpbuff, 10 * 1024);
339  if (n > 0)
340  memorybuffer_insert_data(smsc, tmpbuff, n);
341 
342  /* delete all ACKs/NACKs/whatever */
343  while (memorybuffer_has_rawmessage(smsc, 51, 'R') > 0 ||
344  memorybuffer_has_rawmessage(smsc, 1, 'R') > 0)
345  memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
346 
347  gw_free(tmpbuff);
348 
349  /* If we have MO-message, then act (return 1) */
350 
351  if (memorybuffer_has_rawmessage(smsc, 52, 'O') > 0 ||
352  memorybuffer_has_rawmessage(smsc, 1, 'O') > 0)
353  return 1;
354 
355  /*
356  time(&timenow);
357  if( (smsc->emi_last_spoke + 60*20) < timenow) {
358  time(&smsc->emi_last_spoke);
359  }
360  */
361 
362  return 0;
363 
364 }
static int memorybuffer_insert_data(SMSCenter *smsc, char *buff, int length)
Definition: smsc_emi_x25.c:811
static int guarantee_link(SMSCenter *smsc)
Definition: smsc_emi_x25.c:449
static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length)
Definition: smsc_emi_x25.c:857
static int get_data(SMSCenter *smsc, char *buff, int length)
Definition: smsc_emi_x25.c:660
static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth)
Definition: smsc_emi_x25.c:828

◆ emi_receive_msg()

int emi_receive_msg ( SMSCenter smsc,
Msg **  tmsg 
)

Definition at line 408 of file smsc_emi_x25.c.

References acknowledge_from_rawmessage(), error(), memorybuffer_cut_rawmessage(), msg, msg_destroy(), and parse_rawmessage_to_msg().

Referenced by smscenter_receive_msg().

409 {
410  char *tmpbuff;
411  Msg *msg = NULL;
412 
413  *tmsg = NULL;
414 
415  tmpbuff = gw_malloc(10 * 1024);
416  memset(tmpbuff, 0, 10*1024);
417 
418  /* get and delete message from buffer */
419  memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
420  parse_rawmessage_to_msg(smsc, &msg, tmpbuff, strlen(tmpbuff));
421 
422  /* yeah yeah, I got the message... */
423  acknowledge_from_rawmessage(smsc, tmpbuff, strlen(tmpbuff));
424 
425  /* return with the joyful news */
426  gw_free(tmpbuff);
427 
428  if (msg == NULL) goto error;
429 
430  *tmsg = msg;
431 
432  return 1;
433 
434 error:
435  gw_free(tmpbuff);
436  msg_destroy(msg);
437  return -1;
438 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static int acknowledge_from_rawmessage(SMSCenter *smsc, char *rawmessage, int length)
Definition: smsc_emi_x25.c:964
Definition: msg.h:79
static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length)
Definition: smsc_emi_x25.c:857
static int parse_rawmessage_to_msg(SMSCenter *smsc, Msg **msg, char *rawmessage, int length)
Definition: smsc_emi_x25.c:895
void msg_destroy(Msg *msg)
Definition: msg.c:132
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86

◆ emi_reopen()

int emi_reopen ( SMSCenter smsc)

Definition at line 183 of file smsc_emi_x25.c.

References emi_close(), emi_open_connection(), and error().

Referenced by smsc_reopen().

184 {
185  emi_close(smsc);
186 
187  if (emi_open_connection(smsc) < 0) {
188  error(0, "emi_reopen failed");
189  return -1;
190  }
191  return 0;
192 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static int emi_open_connection(SMSCenter *smsc)
Definition: smsc_emi_x25.c:138
int emi_close(SMSCenter *smsc)
Definition: smsc_emi_x25.c:194

◆ emi_reopen_ip()

int emi_reopen_ip ( SMSCenter smsc)

Definition at line 294 of file smsc_emi_x25.c.

References emi_close_ip(), and emi_open_connection_ip().

295 {
296  emi_close_ip(smsc);
297 
298  return emi_open_connection_ip(smsc);
299 }
static int emi_open_connection_ip(SMSCenter *smsc)
Definition: smsc_emi_x25.c:276
int emi_close_ip(SMSCenter *smsc)
Definition: smsc_emi_x25.c:302

◆ emi_submit_msg()

int emi_submit_msg ( SMSCenter smsc,
Msg omsg 
)

Definition at line 372 of file smsc_emi_x25.c.

References debug(), error(), info(), parse_msg_to_rawmessage(), put_data(), and wait_for_ack().

Referenced by smscenter_submit_msg().

373 {
374  char *tmpbuff = NULL;
375 
376  if (smsc == NULL) goto error;
377  if (omsg == NULL) goto error;
378 
379  tmpbuff = gw_malloc(10 * 1024);
380  memset(tmpbuff, 0, 10*1024);
381 
382  if (parse_msg_to_rawmessage(smsc, omsg, tmpbuff, 10*1024) < 1)
383  goto error;
384 
385  if (put_data(smsc, tmpbuff, strlen(tmpbuff), 0) < 0) {
386  info(0, "put_data failed!");
387  goto error;
388  }
389 
390  wait_for_ack(smsc, 51);
391 
392  /* smsc->emi_current_msg_number += 1; */
393  debug("bb.sms.emi", 0, "Submit Ok...");
394 
395  gw_free(tmpbuff);
396  return 0;
397 
398 error:
399  debug("bb.sms.emi", 0, "Submit Error...");
400 
401  gw_free(tmpbuff);
402  return -1;
403 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
static int parse_msg_to_rawmessage(SMSCenter *smsc, Msg *msg, char *rawmessage, int length)
static int wait_for_ack(SMSCenter *smsc, int op_type)
Definition: smsc_emi_x25.c:621
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup)
Definition: smsc_emi_x25.c:755

◆ generate_checksum()

static void generate_checksum ( const unsigned char *  buffer,
unsigned char *  checksum_out 
)
static

Definition at line 1213 of file smsc_emi_x25.c.

Referenced by acknowledge_from_rawmessage(), emi_open_session(), and parse_msg_to_rawmessage().

1214 {
1215  const unsigned char *p;
1216  int j;
1217 
1218  j = 0;
1219  for (p = buf; *p != '\0'; p++) {
1220  j += *p;
1221 
1222  if (j >= 256)
1223  j -= 256;
1224  }
1225 
1226  sprintf((char *)out, "%02X", j);
1227 }

◆ get_data()

static int get_data ( SMSCenter smsc,
char *  buff,
int  length 
)
static

Definition at line 660 of file smsc_emi_x25.c.

References SMSCenter::buffer, debug(), SMSCenter::emi_backup_allow_ip, SMSCenter::emi_backup_fd, SMSCenter::emi_fd, SMSCenter::emi_secondary_fd, error(), host_ip(), info(), is_allowed_ip(), octstr_create, octstr_destroy(), octstr_get_cstr, octstr_imm(), SMSC_TYPE_EMI_X25, and SMSCenter::type.

Referenced by emi_pending_smsmessage(), and wait_for_ack().

661 {
662  int n = 0;
663 
664  struct sockaddr_in client_addr;
665  socklen_t client_addr_len;
666 
667  fd_set rf;
668  struct timeval to;
669  int ret;
670 
671  memset(buff, 0, length);
672 
673  if (smsc->type == SMSC_TYPE_EMI_X25) {
674  tcdrain(smsc->emi_fd);
675  n = read(smsc->emi_fd, buff, length);
676  return n;
677  }
678 
679  FD_ZERO(&rf);
680  if (smsc->emi_fd >= 0) FD_SET(smsc->emi_fd, &rf);
681  if (smsc->emi_secondary_fd >= 0) FD_SET(smsc->emi_secondary_fd, &rf);
682  if (smsc->emi_backup_fd > 0) FD_SET(smsc->emi_backup_fd, &rf);
683 
684  FD_SET(0, &rf);
685  to.tv_sec = 0;
686  to.tv_usec = 100;
687 
688  ret = select(FD_SETSIZE, &rf, NULL, NULL, &to);
689 
690  if (ret > 0) {
691  if (smsc->emi_secondary_fd >= 0 && FD_ISSET(smsc->emi_secondary_fd, &rf)) {
692  n = read(smsc->emi_secondary_fd, buff, length - 1);
693 
694  if (n == -1) {
695  error(errno, "Error - Secondary socket closed");
696  close(smsc->emi_secondary_fd);
697  smsc->emi_secondary_fd = -1;
698  } else if (n == 0) {
699  info(0, "Secondary socket closed by SMSC");
700  close(smsc->emi_secondary_fd);
701  smsc->emi_secondary_fd = -1;
702  } else { /* UGLY! We put 'X' after message */
703  buff[n] = 'X'; /* if it is from secondary fd!!! */
704  n++;
705  }
706  } else if (smsc->emi_fd >= 0 && FD_ISSET(smsc->emi_fd, &rf)) {
707  n = read(smsc->emi_fd, buff, length);
708  if (n == 0) {
709  close(smsc->emi_fd);
710  info(0, "Main EMI socket closed by SMSC");
711  smsc->emi_fd = -1; /* ready to be re-opened */
712  }
713  }
714  if ((smsc->emi_backup_fd > 0) && FD_ISSET(smsc->emi_backup_fd, &rf)) {
715  if (smsc->emi_secondary_fd == -1) {
716  Octstr *ip, *allow;
717 
718  smsc->emi_secondary_fd = accept(smsc->emi_backup_fd,
719  (struct sockaddr *)&client_addr, &client_addr_len);
720 
721  ip = host_ip(client_addr);
722  if (smsc->emi_backup_allow_ip == NULL)
723  allow = NULL;
724  else
725  allow = octstr_create(smsc->emi_backup_allow_ip);
726  if (is_allowed_ip(allow, octstr_imm("*.*.*.*"), ip) == 0) {
727  info(0, "SMSC secondary connection tried from <%s>, "
728  "disconnected",
729  octstr_get_cstr(ip));
730  octstr_destroy(ip);
731  octstr_destroy(allow);
732  close(smsc->emi_secondary_fd);
733  smsc->emi_secondary_fd = -1;
734  return 0;
735  }
736  info(0, "Secondary socket opened by SMSC from <%s>",
737  octstr_get_cstr(ip));
738  octstr_destroy(ip);
739  octstr_destroy(allow);
740  } else
741  info(0, "New connection request while old secondary is open!");
742  }
743  }
744  if (n > 0) {
745  debug("bb.sms.emi", 0, "get_data:Read %d bytes: <%.*s>", n, n, buff);
746  debug("bb.sms.emi", 0, "get_data:smsc->buffer == <%s>", smsc->buffer);
747  }
748  return n;
749 
750 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
int is_allowed_ip(Octstr *allow_ip, Octstr *deny_ip, Octstr *ip)
Definition: utils.c:815
int emi_secondary_fd
Definition: smsc_p.h:159
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
int emi_backup_fd
Definition: smsc_p.h:155
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
Definition: octstr.c:118
char * emi_backup_allow_ip
Definition: smsc_p.h:157
Octstr * host_ip(struct sockaddr_in addr)
Definition: socket.c:615
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int type
Definition: smsc_p.h:93
char * buffer
Definition: smsc_p.h:184
int socklen_t
Definition: socket.h:73
int emi_fd
Definition: smsc_p.h:145

◆ guarantee_link()

static int guarantee_link ( SMSCenter smsc)
static

Definition at line 449 of file smsc_emi_x25.c.

References SMSCenter::buffer, SMSCenter::buflen, SMSCenter::bufsize, and emi_open_connection().

Referenced by emi_pending_smsmessage().

450 {
451  int need_to_connect = 0;
452 
453  /* If something is obviously wrong. */
454  if (strstr(smsc->buffer, "OK")) need_to_connect = 1;
455  if (strstr(smsc->buffer, "NO CARRIER")) need_to_connect = 1;
456  if (strstr(smsc->buffer, "NO DIALTONE")) need_to_connect = 1;
457 
458  /* Clear the buffer */
459  while (need_to_connect) {
460  /* Connect */
461  need_to_connect = emi_open_connection(smsc) < 0;
462 
463  /* Clear the buffer so that the next call to guarantee
464  doesn't find the "NO CARRIER" string again. */
465  smsc->buflen = 0;
466  memset(smsc->buffer, 0, smsc->bufsize);
467  }
468 
469  return 0;
470 }
size_t bufsize
Definition: smsc_p.h:185
size_t buflen
Definition: smsc_p.h:186
static int emi_open_connection(SMSCenter *smsc)
Definition: smsc_emi_x25.c:138
char * buffer
Definition: smsc_p.h:184

◆ memorybuffer_append_data()

static int memorybuffer_append_data ( SMSCenter smsc,
char *  buff,
int  length 
)
static

Definition at line 794 of file smsc_emi_x25.c.

References SMSCenter::buffer, SMSCenter::buflen, and SMSCenter::bufsize.

Referenced by wait_for_ack().

795 {
796  while (smsc->bufsize < (smsc->buflen + length)) { /* buffer too small */
797  char *p = gw_realloc(smsc->buffer, smsc->bufsize * 2);
798  smsc->buffer = p;
799  smsc->bufsize *= 2;
800  }
801 
802  memcpy(smsc->buffer + smsc->buflen, buff, length);
803  smsc->buflen += length;
804  return 0;
805 
806 }
size_t bufsize
Definition: smsc_p.h:185
size_t buflen
Definition: smsc_p.h:186
char * buffer
Definition: smsc_p.h:184

◆ memorybuffer_cut_rawmessage()

static int memorybuffer_cut_rawmessage ( SMSCenter smsc,
char *  buff,
int  length 
)
static

Definition at line 857 of file smsc_emi_x25.c.

References SMSCenter::buffer, SMSCenter::buflen, SMSCenter::bufsize, and error().

Referenced by emi_pending_smsmessage(), emi_receive_msg(), and wait_for_ack().

858 {
859 
860  char *stx, *etx;
861  int size_of_cut_piece;
862 
863  /* We don't check for NULLs since we're sure that nobody has fooled
864  around with smsc->buffer since has_rawmessage was last called... */
865 
866  stx = memchr(smsc->buffer, '\2', smsc->buflen);
867  etx = memchr(smsc->buffer, '\3', smsc->buflen);
868 
869  if (*(etx + 1) == 'X') /* secondary! UGLY KLUDGE */
870  etx++;
871 
872  size_of_cut_piece = (etx - stx) + 1;
873 
874  if (length < size_of_cut_piece) {
875  error(0, "the buffer you provided for cutting was too small");
876  return -1;
877  }
878 
879  /* move the part before our magic rawmessage to the safe house */
880  memcpy(buff, stx, size_of_cut_piece);
881  buff[size_of_cut_piece] = '\0'; /* NULL-terminate */
882 
883  /* move the stuff in membuffer one step down */
884  memmove(stx, etx + 1, (smsc->buffer + smsc->bufsize) - stx );
885 
886  smsc->buflen -= size_of_cut_piece;
887 
888  return 0;
889 
890 }
void error(int err, const char *fmt,...)
Definition: log.c:648
size_t bufsize
Definition: smsc_p.h:185
size_t buflen
Definition: smsc_p.h:186
char * buffer
Definition: smsc_p.h:184

◆ memorybuffer_has_rawmessage()

static int memorybuffer_has_rawmessage ( SMSCenter smsc,
int  type,
char  auth 
)
static

Definition at line 828 of file smsc_emi_x25.c.

References SMSCenter::buffer, SMSCenter::buflen, debug(), and type.

Referenced by emi_pending_smsmessage(), and wait_for_ack().

829 {
830  char tmpbuff[1024], tmpbuff2[1024];
831  char *stx, *etx;
832 
833  stx = memchr(smsc->buffer, '\2', smsc->buflen);
834  etx = memchr(smsc->buffer, '\3', smsc->buflen);
835 
836  if (stx && etx && stx < etx) {
837  strncpy(tmpbuff, stx, etx - stx + 1);
838  tmpbuff[etx - stx + 1] = '\0';
839  if (auth)
840  sprintf(tmpbuff2, "/%c/%02i/", auth, type);
841  else
842  sprintf(tmpbuff2, "/%02i/", type);
843 
844  if (strstr(tmpbuff, tmpbuff2) != NULL) {
845  debug("bb.sms.emi", 0, "found message <%c/%02i>...msg <%s>", auth, type, tmpbuff);
846  return 1;
847  }
848  }
849  return 0;
850 
851 }
size_t buflen
Definition: smsc_p.h:186
int type
Definition: smsc_cimd2.c:215
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
char * buffer
Definition: smsc_p.h:184

◆ memorybuffer_insert_data()

static int memorybuffer_insert_data ( SMSCenter smsc,
char *  buff,
int  length 
)
static

Definition at line 811 of file smsc_emi_x25.c.

References SMSCenter::buffer, SMSCenter::buflen, and SMSCenter::bufsize.

Referenced by emi_pending_smsmessage().

812 {
813  while (smsc->bufsize < (smsc->buflen + length)) { /* buffer too small */
814  char *p = gw_realloc(smsc->buffer, smsc->bufsize * 2);
815  smsc->buffer = p;
816  smsc->bufsize *= 2;
817  }
818  memmove(smsc->buffer + length, smsc->buffer, smsc->buflen);
819  memcpy(smsc->buffer, buff, length);
820  smsc->buflen += length;
821  return 0;
822 
823 }
size_t bufsize
Definition: smsc_p.h:185
size_t buflen
Definition: smsc_p.h:186
char * buffer
Definition: smsc_p.h:184

◆ parse_binary_to_emi()

static int parse_binary_to_emi ( char *  from,
char *  to,
int  length 
)
static

Definition at line 1191 of file smsc_emi_x25.c.

References from.

Referenced by emi_fill_ucp60_login(), and parse_msg_to_rawmessage().

1192 {
1193  char buf[10];
1194  char *ptr;
1195 
1196  if (!from || !to || length <= 0)
1197  return -1;
1198 
1199  *to = '\0';
1200 
1201  for (ptr = from; length > 0; ptr++, length--) {
1202  sprintf(buf, "%02X", (unsigned char)*ptr);
1203  strncat(to, buf, 2);
1204  }
1205 
1206  return 0;
1207 }
static Octstr * from
Definition: mtbatch.c:95

◆ parse_emi_to_iso88591()

static int parse_emi_to_iso88591 ( char *  from,
char *  to,
int  length,
int  alt_charset 
)
static

Definition at line 1144 of file smsc_emi_x25.c.

References alt_charset, char_sms_to_iso(), and from.

Referenced by parse_rawmessage_to_msg().

1146 {
1147  int hmtg = 0;
1148  unsigned int mychar;
1149  char tmpbuff[128];
1150 
1151  for (hmtg = 0; hmtg <= (int)strlen(from); hmtg += 2) {
1152  strncpy(tmpbuff, from + hmtg, 2);
1153  sscanf(tmpbuff, "%x", &mychar);
1154  to[hmtg / 2] = char_sms_to_iso(mychar, alt_charset);
1155  }
1156 
1157  to[(hmtg / 2)-1] = '\0';
1158 
1159  return 0;
1160 
1161 }
static char char_sms_to_iso(unsigned char from, int alt_charset)
static Octstr * from
Definition: mtbatch.c:95
static Octstr * alt_charset
Definition: opensmppbox.c:129

◆ parse_iso88591_to_emi()

static int parse_iso88591_to_emi ( char *  from,
char *  to,
int  length,
int  alt_charset 
)
static

Definition at line 1166 of file smsc_emi_x25.c.

References alt_charset, char_iso_to_sms(), debug(), and from.

Referenced by parse_msg_to_rawmessage().

1168 {
1169  char buf[10];
1170  unsigned char tmpchar;
1171  char *ptr;
1172 
1173  if (!from || !to || length <= 0)
1174  return -1;
1175 
1176  *to = '\0';
1177 
1178  debug("bb.sms.emi", 0, "emi parsing <%s> to emi, length %d", from, length);
1179 
1180  for (ptr = from; length > 0; ptr++, length--) {
1181  tmpchar = char_iso_to_sms(*ptr, alt_charset);
1182  sprintf(buf, "%02X", tmpchar);
1183  strncat(to, buf, 2);
1184  }
1185  return 0;
1186 }
static char char_iso_to_sms(unsigned char from, int alt_charset)
static Octstr * from
Definition: mtbatch.c:95
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static Octstr * alt_charset
Definition: opensmppbox.c:129

◆ parse_msg_to_rawmessage()

static int parse_msg_to_rawmessage ( SMSCenter smsc,
Msg msg,
char *  rawmessage,
int  length 
)
static

Definition at line 1032 of file smsc_emi_x25.c.

References SMSCenter::alt_charset, DC_7BIT, DC_UNDEF, debug(), SMSCenter::emi_current_msg_number, generate_checksum(), msg, octstr_get_char(), octstr_get_cstr, octstr_get_many_chars(), octstr_len(), parse_binary_to_emi(), parse_iso88591_to_emi(), SMSC_TYPE_EMI_X25, and SMSCenter::type.

Referenced by emi_submit_msg().

1033 {
1034  char message_whole[10*1024];
1035  char message_body[10*1024];
1036  char message_header[1024];
1037  char message_footer[1024];
1038 
1039  char my_buffer[10*1024];
1040  char my_buffer2[10*1024];
1041  char msgtext[1024];
1042  int length;
1043  char mt;
1044  char mcl[20];
1045  char snumbits[20];
1046  char xser[1024];
1047  int udh_len;
1048 
1049  memset(&message_whole, 0, sizeof(message_whole));
1050  memset(&message_body, 0, sizeof(message_body));
1051  memset(&message_header, 0, sizeof(message_header));
1052  memset(&message_footer, 0, sizeof(message_footer));
1053  memset(&my_buffer, 0, sizeof(my_buffer));
1054  memset(&my_buffer2, 0, sizeof(my_buffer2));
1055  mt = '3';
1056  memset(&snumbits, 0, sizeof(snumbits));
1057  memset(&xser, 0, sizeof(xser));
1058 
1059  /* XXX parse_iso88591_to_emi shouldn't use NUL terminated
1060  * strings, but Octstr directly, or a char* and a length.
1061  */
1062  if (octstr_len(msg->sms.udhdata)) {
1063  char xserbuf[258];
1064  /* we need a properly formated UDH here, there first byte contains his length
1065  * this will be formatted in the xser field of the EMI Protocol
1066  */
1067  udh_len = octstr_get_char(msg->sms.udhdata, 0) + 1;
1068  xserbuf[0] = 1;
1069  xserbuf[1] = udh_len;
1070  octstr_get_many_chars(&xserbuf[2], msg->sms.udhdata, 0, udh_len);
1071  parse_binary_to_emi(xserbuf, xser, udh_len + 2);
1072  } else {
1073  udh_len = 0;
1074  }
1075 
1076  if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) {
1077  octstr_get_many_chars(msgtext, msg->sms.msgdata, 0, octstr_len(msg->sms.msgdata));
1078  msgtext[octstr_len(msg->sms.msgdata)] = '\0';
1079  parse_iso88591_to_emi(msgtext, my_buffer2,
1080  octstr_len(msg->sms.msgdata),
1081  smsc->alt_charset);
1082 
1083  strcpy(snumbits, "");
1084  mt = '3';
1085  strcpy(mcl, "");
1086  } else {
1087  octstr_get_many_chars(msgtext, msg->sms.msgdata, 0, octstr_len(msg->sms.msgdata));
1088 
1089  parse_binary_to_emi(msgtext, my_buffer2, octstr_len(msg->sms.msgdata));
1090 
1091  sprintf(snumbits, "%04ld", octstr_len(msg->sms.msgdata)*8);
1092  mt = '4';
1093  strcpy(mcl, "1");
1094  }
1095 
1096  /* XXX Where is DCS ? Is it in XSER like in emi2 ?
1097  * Please someone encode it with fields_to_dcs
1098  */
1099 
1100  sprintf(message_body,
1101  "%s/%s/%s/%s/%s//%s////////////%c/%s/%s////%s//////%s//",
1102  octstr_get_cstr(msg->sms.receiver),
1103  msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : "",
1104  "",
1105  "",
1106  "",
1107  "0100",
1108  mt,
1109  snumbits,
1110  my_buffer2,
1111  mcl,
1112  xser);
1113 
1114  /* HEADER */
1115 
1116  length = strlen(message_body);
1117  length += 13; /* header (fixed) */
1118  length += 2; /* footer (fixed) */
1119  length += 2; /* slashes between header, body, footer */
1120 
1121  sprintf(message_header, "%02i/%05i/%s/%s", (smsc->emi_current_msg_number++ % 100), length, "O", "51");
1122 
1123  /* FOOTER */
1124 
1125  sprintf(my_buffer, "%s/%s/", message_header, message_body);
1126  generate_checksum((unsigned char *)my_buffer, (unsigned char *)message_footer);
1127 
1128  sprintf(message_whole, "%c%s/%s/%s%c", 0x02, message_header, message_body, message_footer, 0x03);
1129 
1130  strncpy(rawmessage, message_whole, rawmessage_length);
1131 
1132  if (smsc->type == SMSC_TYPE_EMI_X25) {
1133  /* IC3S braindead EMI stack chokes on this... must fix it at the next time... */
1134  strcat(rawmessage, "\r");
1135  }
1136  debug("bb.sms.emi", 0, "emi %d message %s",
1137  smsc->emi_current_msg_number, rawmessage);
1138  return strlen(rawmessage);
1139 }
static int parse_binary_to_emi(char *from, char *to, int length)
static int parse_iso88591_to_emi(char *from, char *to, int length, int alt_charset)
static void generate_checksum(const unsigned char *buffer, unsigned char *checksum_out)
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int type
Definition: smsc_p.h:93
long alt_charset
Definition: smsc_p.h:106
#define DC_UNDEF
Definition: sms.h:109
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
Definition: octstr.c:425
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
int emi_current_msg_number
Definition: smsc_p.h:153
#define DC_7BIT
Definition: sms.h:110

◆ parse_rawmessage_to_msg()

static int parse_rawmessage_to_msg ( SMSCenter smsc,
Msg **  msg,
char *  rawmessage,
int  length 
)
static

Definition at line 895 of file smsc_emi_x25.c.

References SMSCenter::alt_charset, error(), msg, msg_create, octstr_create, and parse_emi_to_iso88591().

Referenced by emi_receive_msg().

897 {
898 
899  char emivars[128][1024];
900  char *leftslash, *rightslash;
901  char isotext[2048];
902  int msgnbr;
903  int tmpint;
904 
905  msgnbr = -1;
906 
907  memset(isotext, 0, sizeof(isotext));
908 
909  strncpy(isotext, rawmessage, length);
910  leftslash = isotext;
911 
912  for (tmpint = 0; leftslash != NULL; tmpint++) {
913  rightslash = strchr(leftslash + 1, '/');
914 
915  if (rightslash == NULL)
916  rightslash = strchr(leftslash + 1, '\3');
917 
918  if (rightslash == NULL)
919  break;
920 
921  *rightslash = '\0';
922  strcpy(emivars[tmpint], leftslash + 1);
923  leftslash = rightslash;
924  }
925 
926  if (strcmp(emivars[3], "01") == 0) {
927  if (strcmp(emivars[7], "2") == 0) {
928  strcpy(isotext, emivars[8]);
929  } else if (strcmp(emivars[7], "3") == 0) {
930  parse_emi_to_iso88591(emivars[8], isotext, sizeof(isotext),
931  smsc->alt_charset);
932  } else {
933  error(0, "Unknown 01-type EMI SMS (%s)", emivars[7]);
934  strcpy(isotext, "");
935  }
936  } else if (strcmp(emivars[3], "51") == 0) {
937  parse_emi_to_iso88591(emivars[24], isotext, sizeof(isotext),
938  smsc->alt_charset);
939  } else if (strcmp(emivars[3], "52") == 0) {
940  parse_emi_to_iso88591(emivars[24], isotext, sizeof(isotext),
941  smsc->alt_charset);
942  } else {
943  error(0, "HEY WE SHOULD NOT BE HERE!! Type = %s", emivars[3]);
944  strcpy(isotext, "");
945  }
946 
947  *msg = msg_create(sms);
948  if (*msg == NULL) goto error;
949 
950  (*msg)->sms.sender = octstr_create(emivars[5]);
951  (*msg)->sms.receiver = octstr_create(emivars[4]);
952  (*msg)->sms.msgdata = octstr_create(isotext);
953  (*msg)->sms.udhdata = NULL;
954 
955  return msgnbr;
956 
957 error:
958  return -1;
959 }
void error(int err, const char *fmt,...)
Definition: log.c:648
#define msg_create(type)
Definition: msg.h:136
#define octstr_create(cstr)
Definition: octstr.h:125
static int parse_emi_to_iso88591(char *from, char *to, int length, int alt_charset)
long alt_charset
Definition: smsc_p.h:106
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86

◆ put_data()

static int put_data ( SMSCenter smsc,
char *  buff,
int  length,
int  is_backup 
)
static

Definition at line 755 of file smsc_emi_x25.c.

References SMSCenter::emi_fd, error(), SMSC_TYPE_EMI_X25, and SMSCenter::type.

Referenced by acknowledge_from_rawmessage(), emi_open_session(), and emi_submit_msg().

756 {
757  size_t len = length;
758  int ret;
759  int fd = -1;
760 
761  fd = smsc->emi_fd;
762  tcdrain(smsc->emi_fd);
763 
764  /* Write until all data has been successfully written to the fd. */
765  while (len > 0) {
766  ret = write(fd, buff, len);
767  if (ret == -1) {
768  if (errno == EINTR) continue;
769  if (errno == EAGAIN) continue;
770  error(errno, "Writing to fd failed");
771  return -1;
772  }
773  /* ret may be less than len, if the writing
774  was interrupted by a signal. */
775  len -= ret;
776  buff += ret;
777  }
778 
779  if (smsc->type == SMSC_TYPE_EMI_X25) {
780  /* Make sure the data gets written immediately.
781  Wait a while just to add some latency so
782  that the modem (or the UART) doesn't choke
783  on the data. */
784  tcdrain(smsc->emi_fd);
785  usleep(1000);
786  }
787 
788  return 0;
789 }
void error(int err, const char *fmt,...)
Definition: log.c:648
int type
Definition: smsc_p.h:93
int emi_fd
Definition: smsc_p.h:145

◆ wait_for_ack()

static int wait_for_ack ( SMSCenter smsc,
int  op_type 
)
static

Definition at line 621 of file smsc_emi_x25.c.

References debug(), found, get_data(), memorybuffer_append_data(), memorybuffer_cut_rawmessage(), memorybuffer_has_rawmessage(), and start.

Referenced by emi_open_session(), and emi_submit_msg().

622 {
623  char *tmpbuff;
624  int found = 0;
625  int n;
626  time_t start;
627 
628  tmpbuff = gw_malloc(10 * 1024);
629  memset(tmpbuff, 0, 10*1024);
630  start = time(NULL);
631  do {
632  /* check for data */
633  n = get_data(smsc, tmpbuff, 1024 * 10);
634 
635  /* At least the X.31 interface wants to append the data.
636  Kalle, what about the TCP/IP interface? Am I correct
637  that you are assuming that the message arrives in a
638  single read(2)? -mg */
639  if (n > 0)
640  memorybuffer_append_data(smsc, tmpbuff, n);
641 
642  /* act on data */
643  if (memorybuffer_has_rawmessage(smsc, op_type, 'R') > 0) {
644  memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
645  debug("bb.sms.emi", 0, "Found ACK/NACK: <%s>", tmpbuff);
646  found = 1;
647  }
648  } while (!found && ((time(NULL) - start) < 5));
649 
650  gw_free(tmpbuff);
651  return found;
652 }
static struct pid_list * found
static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length)
Definition: smsc_emi_x25.c:857
static int get_data(SMSCenter *smsc, char *buff, int length)
Definition: smsc_emi_x25.c:660
static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth)
Definition: smsc_emi_x25.c:828
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
static int start
static int memorybuffer_append_data(SMSCenter *smsc, char *buff, int length)
Definition: smsc_emi_x25.c:794
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.