smsc_emi.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:45k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*****************************************************************************
  2. * smsc_emi.c - implement interface to the CMG SMS Center (UCP/EMI).
  3. * Mikael Gueck for WapIT Ltd.
  4. */
  5. /* This file implements two smsc interfaces: EMI and EMI_IP */
  6. #include <errno.h>
  7. #include <string.h>
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include <fcntl.h>
  11. #include <termios.h>
  12. #include <stdarg.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <strings.h>
  16. #include <sys/time.h>
  17. #include <sys/types.h>
  18. #include <sys/socket.h>
  19. #include <sys/param.h>
  20. #include <sys/ioctl.h>
  21. #include "config.h"
  22. #include "smsc.h"
  23. #include "smsc_p.h"
  24. #include "gwlib/gwlib.h"
  25. #include "alt_charsets.h"
  26. #include "sms.h"
  27. #ifndef CRTSCTS
  28. #define CRTSCTS 0
  29. #endif
  30. /******************************************************************************
  31. * Static functions
  32. */
  33. static int get_data(SMSCenter *smsc, char *buff, int length);
  34. static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup);
  35. static int memorybuffer_append_data(SMSCenter *smsc, char *buff, int length);
  36. static int memorybuffer_insert_data(SMSCenter *smsc, char *buff, int length);
  37. static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth);
  38. static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length);
  39. static int parse_rawmessage_to_msg(SMSCenter *smsc, Msg **msg,
  40.                                    char *rawmessage, int length);
  41. static int parse_msg_to_rawmessage(SMSCenter *smsc, Msg *msg,
  42.                                    char *rawmessage, int length);
  43. static int acknowledge_from_rawmessage(SMSCenter *smsc,
  44.                                    char *rawmessage, int length);
  45. static int parse_emi_to_iso88591(char *from, char *to,
  46.                                  int length, int alt_charset);
  47. static int parse_iso88591_to_emi(char *from, char *to,
  48.                                  int length, int alt_charset);
  49. static int parse_binary_to_emi(char *from, char *to, int length);
  50. static int at_dial(char *device, char *phonenum,
  51.                    char *at_prefix, time_t how_long);
  52. static int guarantee_link(SMSCenter *smsc);
  53. static void generate_checksum(const unsigned char *buffer,
  54.                               unsigned char *checksum_out);
  55. static int wait_for_ack(SMSCenter *smsc, int op_type);
  56. static char char_iso_to_sms(unsigned char from, int alt_charset);
  57. static char char_sms_to_iso(unsigned char from, int alt_charset);
  58. /******************************************************************************
  59. * Open the connection and log in - handshake baby
  60. */
  61. static int emi_open_connection(SMSCenter *smsc)
  62. {
  63.     char tmpbuff[1024];
  64.     sprintf(tmpbuff, "/dev/%s", smsc->emi_serialdevice);
  65.     smsc->emi_fd = at_dial(tmpbuff, smsc->emi_phonenum, "ATD", 30);
  66.     if (smsc->emi_fd <= 0)
  67.         return -1;
  68.     return 0;
  69. }
  70. /* open EMI smscenter */
  71. SMSCenter *emi_open(char *phonenum, char *serialdevice, char *username, char *password)
  72. {
  73.     SMSCenter *smsc;
  74.     smsc = smscenter_construct();
  75.     if (smsc == NULL)
  76.         goto error;
  77.     smsc->type = SMSC_TYPE_EMI;
  78.     smsc->emi_phonenum = gw_strdup(phonenum);
  79.     smsc->emi_serialdevice = gw_strdup(serialdevice);
  80.     smsc->emi_username = gw_strdup(username);
  81.     smsc->emi_password = gw_strdup(password);
  82.     smsc->emi_current_msg_number = 0;
  83.     if (emi_open_connection(smsc) < 0)
  84.         goto error;
  85.     sprintf(smsc->name, "EMI:%s:%s", smsc->emi_phonenum,
  86.             smsc->emi_username);
  87.     return smsc;
  88. error:
  89.     error(0, "emi_open failed");
  90.     smscenter_destruct(smsc);
  91.     return NULL;
  92. }
  93. int emi_reopen(SMSCenter *smsc)
  94. {
  95.     emi_close(smsc);
  96.     if (emi_open_connection(smsc) < 0) {
  97.         error(0, "emi_reopen failed");
  98.         return -1;
  99.     }
  100.     return 0;
  101. }
  102. int emi_close(SMSCenter *smsc)
  103. {
  104.     return emi_close_ip(smsc);
  105. }
  106. static int emi_fill_ucp60_login(char *buf, char *OAdC, char *passwd) {
  107.     int max_ia5passwd_len;
  108.     char *ia5passwd;
  109.     max_ia5passwd_len = strlen(passwd) * 2 + 1;
  110.     ia5passwd = gw_malloc(max_ia5passwd_len);
  111.     if (parse_binary_to_emi(passwd, ia5passwd, strlen(passwd)) < 0) {
  112.         error(0, "parse_binary_to_emi failed");
  113.         gw_free(ia5passwd);
  114.         return -1;
  115.     }
  116.     sprintf(buf, "%s/%c/%c/%c/%s//%s/////",
  117.     OAdC,      /* OAdC: Address code originator */
  118.     '6',       /* OTON: 6 = Abbreviated number (short number alias) */
  119.     '5',       /* ONPI: 5 = Private (TCP/IP address/abbreviated number address) */
  120.     '1',       /* STYP: 1 = open session */
  121.     ia5passwd, /* PWD:  Current password encoded into IA5 characters */
  122.     "0100"     /* VERS: Version number  0100 */
  123.     );
  124.     gw_free(ia5passwd);
  125.     return 0;
  126. }
  127. static int emi_open_session(SMSCenter *smsc)
  128. {
  129.     char message_whole  [1024];
  130.     char message_body   [1024];
  131.     char message_header [50];
  132.     char message_footer [10];
  133.     char my_buffer      [1024];
  134.     int length;
  135.     memset(message_whole,  0, sizeof(message_whole));
  136.     memset(message_body,   0, sizeof(message_body));
  137.     memset(message_header, 0, sizeof(message_header));
  138.     memset(message_footer, 0, sizeof(message_footer));
  139.     if (emi_fill_ucp60_login(message_body, smsc->emi_username, smsc->emi_password) < 0) {
  140.         error(0, "emi_fill_ucp60_login failed");
  141.         return -1;
  142.     }
  143.     length = strlen(message_body);
  144.     length += 13;  /* header (fixed) */
  145.     length += 2;   /* footer (fixed) */
  146.     length += 2;   /* slashes between header, body, footer */
  147.     sprintf(message_header, "%02i/%05i/O/60",
  148.             (smsc->emi_current_msg_number++ % 100), length);
  149.     
  150.     /* FOOTER */
  151.     sprintf(my_buffer, "%s/%s/", message_header, message_body);
  152.     generate_checksum(my_buffer, message_footer);
  153.     sprintf(message_whole, "x02%s/%s/%sx03", message_header,
  154.             message_body, message_footer);
  155.     debug("bb.sms.emi", 0, "final UCP60 msg: <%s>", message_whole);
  156.     put_data(smsc, message_whole, strlen(message_whole), 0);
  157.     if (!wait_for_ack(smsc, 60)) {
  158. info(0, "emi_open_session: wait for ack failed!");
  159. return -1;
  160.     }
  161.     return 0;
  162. }
  163. /*******************************************************
  164.  * the actual protocol open... quite simple here */
  165. static int emi_open_connection_ip(SMSCenter *smsc)
  166. {
  167.     smsc->emi_fd =
  168.         tcpip_connect_to_server_with_port(smsc->emi_hostname,
  169.                                           smsc->emi_port, smsc->emi_our_port,
  170.   NULL);
  171.     /* XXX add interface_name if required */
  172.     if (smsc->emi_fd < 0)
  173.         return -1;
  174.     if (smsc->emi_username && smsc->emi_password) {
  175. return emi_open_session(smsc);
  176.     }
  177.     
  178.     return 0;
  179. }
  180. /******************************************************************************
  181. * Open the connection and log in
  182. */
  183. SMSCenter *emi_open_ip(char *hostname, int port, char *username,
  184.                        char *password, int receive_port, char *allow_ip,
  185.        int our_port)
  186. {
  187.     SMSCenter *smsc;
  188.     smsc = smscenter_construct();
  189.     if (smsc == NULL)
  190.         goto error;
  191.     smsc->type = SMSC_TYPE_EMI_IP;
  192.     smsc->emi_hostname = gw_strdup(hostname);
  193.     smsc->emi_port = port;
  194.     smsc->emi_username = username ? gw_strdup(username) : NULL;
  195.     smsc->emi_password = password ? gw_strdup(password) : NULL;
  196.     smsc->emi_backup_port = receive_port;
  197.     smsc->emi_backup_allow_ip = allow_ip ? gw_strdup(allow_ip) : NULL;
  198.     smsc->emi_our_port = our_port;
  199.     if (receive_port > 0 && allow_ip == NULL)
  200. warning(0, "EMI IP: receive-port set but no IPs allowed to connect!");
  201.     smsc->emi_current_msg_number = 0;
  202.     if (emi_open_connection_ip(smsc) < 0)
  203.         goto error;
  204.     sprintf(smsc->name, "EMIIP:%s:%s", smsc->emi_hostname,
  205.             username ? smsc->emi_username : "n/a");
  206.     /* if receive-port is defined, set it ready */
  207.     if (receive_port > 0) {
  208.         if ((smsc->emi_backup_fd = make_server_socket(receive_port, NULL)) <= 0)
  209. /* XXX add interface_name if required */
  210.             goto error;
  211.         debug("bb.sms.emi", 0, "EMI IP backup port at %d opened", receive_port);
  212.     }
  213.     return smsc;
  214. error:
  215.     error(0, "emi_open_ip failed");
  216.     smscenter_destruct(smsc);
  217.     return NULL;
  218. }
  219. int emi_reopen_ip(SMSCenter *smsc)
  220. {
  221.     emi_close_ip(smsc);
  222.     return emi_open_connection_ip(smsc);
  223. }
  224. int emi_close_ip(SMSCenter *smsc)
  225. {
  226.     if (smsc->emi_fd == -1) {
  227.         info(0, "Trying to close already closed EMI, ignoring");
  228.         return 0;
  229.     }
  230.     close(smsc->emi_fd);
  231.     smsc->emi_fd = -1;
  232.     return 0;
  233. }
  234. /******************************************************************************
  235. * Check if the buffers contain any messages
  236. */
  237. int emi_pending_smsmessage(SMSCenter *smsc)
  238. {
  239.     char *tmpbuff;
  240.     int n = 0;
  241.     /* time_t timenow; */
  242.     /* Block until we have a connection */
  243.     guarantee_link(smsc);
  244.     /* If we have MO-message, then act (return 1) */
  245.     if (memorybuffer_has_rawmessage(smsc, 52, 'O') > 0 ||
  246.         memorybuffer_has_rawmessage(smsc, 1, 'O') > 0 )
  247.         return 1;
  248.     tmpbuff = gw_malloc(10 * 1024);
  249.     memset(tmpbuff, 0, 10*1024);
  250.     /* check for data */
  251.     n = get_data(smsc, tmpbuff, 10 * 1024);
  252.     if (n > 0)
  253.         memorybuffer_insert_data(smsc, tmpbuff, n);
  254.     /* delete all ACKs/NACKs/whatever */
  255.     while (memorybuffer_has_rawmessage(smsc, 51, 'R') > 0 ||
  256.            memorybuffer_has_rawmessage(smsc, 1, 'R') > 0)
  257.         memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
  258.     gw_free(tmpbuff);
  259.     /* If we have MO-message, then act (return 1) */
  260.     if (memorybuffer_has_rawmessage(smsc, 52, 'O') > 0 ||
  261.         memorybuffer_has_rawmessage(smsc, 1, 'O') > 0)
  262.         return 1;
  263.     /*
  264.      time(&timenow);
  265.      if( (smsc->emi_last_spoke + 60*20) < timenow) {
  266.      time(&smsc->emi_last_spoke);
  267.      }
  268.     */
  269.     return 0;
  270. }
  271. /******************************************************************************
  272.  * Submit (send) a Mobile Terminated message to the EMI server
  273.  */
  274. int emi_submit_msg(SMSCenter *smsc, Msg *omsg)
  275. {
  276.     char *tmpbuff = NULL;
  277.     if (smsc == NULL) goto error;
  278.     if (omsg == NULL) goto error;
  279.     tmpbuff = gw_malloc(10 * 1024);
  280.     memset(tmpbuff, 0, 10*1024);
  281.     if (parse_msg_to_rawmessage(smsc, omsg, tmpbuff, 10*1024) < 1)
  282.         goto error;
  283.     if (put_data(smsc, tmpbuff, strlen(tmpbuff), 0) < 0) {
  284.         info(0, "put_data failed!");
  285.         goto error;
  286.     }
  287.     if (smsc->type == SMSC_TYPE_EMI_IP) {
  288.         if (!wait_for_ack(smsc, 51)) {
  289.             info(0, "emi_submit_smsmessage: wait for ack failed!");
  290.             goto error;
  291.         }
  292.     }
  293.     if (smsc->type == SMSC_TYPE_EMI)
  294.         wait_for_ack(smsc, 51);
  295.     /* smsc->emi_current_msg_number += 1; */
  296.     debug("bb.sms.emi", 0, "Submit Ok...");
  297.     gw_free(tmpbuff);
  298.     return 0;
  299. error:
  300.     debug("bb.sms.emi", 0, "Submit Error...");
  301.     gw_free(tmpbuff);
  302.     return -1;
  303. }
  304. /******************************************************************************
  305. * Receive a Mobile Terminated message to the EMI server
  306. */
  307. int emi_receive_msg(SMSCenter *smsc, Msg **tmsg)
  308. {
  309.     char *tmpbuff;
  310.     Msg *msg = NULL;
  311.     *tmsg = NULL;
  312.     tmpbuff = gw_malloc(10 * 1024);
  313.     memset(tmpbuff, 0, 10*1024);
  314.     /* get and delete message from buffer */
  315.     memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
  316.     parse_rawmessage_to_msg(smsc, &msg, tmpbuff, strlen(tmpbuff));
  317.     /* yeah yeah, I got the message... */
  318.     acknowledge_from_rawmessage(smsc, tmpbuff, strlen(tmpbuff));
  319.     /* return with the joyful news */
  320.     gw_free(tmpbuff);
  321.     if (msg == NULL) goto error;
  322.     *tmsg = msg;
  323.     return 1;
  324. error:
  325.     gw_free(tmpbuff);
  326.     msg_destroy(msg);
  327.     return -1;
  328. }
  329. /******************************************************************************
  330. * Internal functions
  331. */
  332. /******************************************************************************
  333. * Guarantee that we have a link
  334. */
  335. static int guarantee_link(SMSCenter *smsc)
  336. {
  337.     int need_to_connect = 0;
  338.     if (smsc->type == SMSC_TYPE_EMI_IP) {
  339.         /* We don't currently guarantee TCP connections. */
  340.         return 0;
  341.     }
  342.     /* If something is obviously wrong. */
  343.     if (strstr(smsc->buffer, "OK")) need_to_connect = 1;
  344.     if (strstr(smsc->buffer, "NO CARRIER")) need_to_connect = 1;
  345.     if (strstr(smsc->buffer, "NO DIALTONE")) need_to_connect = 1;
  346.     /* Clear the buffer */
  347.     while (need_to_connect) {
  348.         /* Connect */
  349.         need_to_connect = emi_open_connection(smsc) < 0;
  350.         /* Clear the buffer so that the next call to guarantee
  351.            doesn't find the "NO CARRIER" string again. */
  352.         smsc->buflen = 0;
  353.         memset(smsc->buffer, 0, smsc->bufsize);
  354.     }
  355.     return 0;
  356. }
  357. static int at_dial(char *device, char *phonenum, char *at_prefix, time_t how_long)
  358. {
  359.     char tmpbuff[1024];
  360.     int howmanyread = 0;
  361.     int thistime = 0;
  362.     int redial;
  363.     int fd = -1;
  364.     int ret;
  365.     time_t timestart;
  366.     struct termios tios;
  367.     /* The time at the start of the function is used when
  368.        determining whether we have used up our allotted
  369.        dial time and have to abort. */
  370.     time(&timestart);
  371.     /* Open the device properly. Remember to set the
  372.        access codes correctly. */
  373.     fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY);
  374.     if (fd == -1) {
  375.         error(errno, "at_dial: error opening character device <%s>", device);
  376.         goto error;
  377.     }
  378.     tcflush(fd, TCIOFLUSH);
  379.     /* The speed initialisation is pretty important. */
  380.     tcgetattr(fd, &tios);
  381.     cfsetospeed(&tios, B115200);
  382.     cfsetispeed(&tios, B115200);
  383.     kannel_cfmakeraw(&tios);
  384.     tios.c_cflag |= (HUPCL | CREAD | CRTSCTS);
  385.     tcsetattr(fd, TCSANOW, &tios);
  386.     /* Dial using an AT command string. */
  387.     for (redial = 1; redial; ) {
  388.         info(0, "at_dial: dialing <%s> on <%s> for <%i> seconds",
  389.              phonenum, device,
  390.              (int)(how_long - (time(NULL) - timestart)));
  391.         /* Send AT dial request. */
  392.         howmanyread = 0;
  393.         sprintf(tmpbuff, "%s%srn", at_prefix, phonenum);
  394.         ret = write(fd, tmpbuff, strlen(tmpbuff));  /* errors... -mg */
  395.         memset(&tmpbuff, 0, sizeof(tmpbuff));
  396.         /* Read the answer to the AT command and react accordingly. */
  397.         for (; ; ) {
  398.             /* We don't want to dial forever */
  399.             if (how_long != 0 && time(NULL) > timestart + how_long)
  400.                 goto timeout;
  401.             /* We don't need more space for dialout */
  402.             if (howmanyread >= (int) sizeof(tmpbuff))
  403.                 goto error;
  404.             /* We read 1 char a time so that we don't
  405.                accidentally read past the modem chat and
  406.                into the SMSC datastream -mg */
  407.             thistime = read(fd, &tmpbuff[howmanyread], 1);
  408.             if (thistime == -1) {
  409.                 if (errno == EAGAIN) continue;
  410.                 if (errno == EINTR) continue;
  411.                 goto error;
  412.             } else {
  413.                 howmanyread += thistime;
  414.             }
  415.             /* Search for the newline on the AT status line. */
  416.             if (tmpbuff[howmanyread - 1] == 'r'
  417.                 || tmpbuff[howmanyread - 1] == 'n') {
  418.                 /* XXX ADD ALL POSSIBLE CHAT STRINGS XXX */
  419.                 if (strstr(tmpbuff, "CONNECT") != NULL) {
  420.                     debug("bb.sms.emi", 0, "at_dial: CONNECT");
  421.                     redial = 0;
  422.                     break;
  423.                 } else if (strstr(tmpbuff, "NO CARRIER") != NULL) {
  424.                     debug("bb.sms.emi", 0, "at_dial: NO CARRIER");
  425.                     redial = 1;
  426.                     break;
  427.                 } else if (strstr(tmpbuff, "BUSY") != NULL) {
  428.                     debug("bb.sms.emi", 0, "at_dial: BUSY");
  429.                     redial = 1;
  430.                     break;
  431.                 } else if (strstr(tmpbuff, "NO DIALTONE") != NULL) {
  432.                     debug("bb.sms.emi", 0, "at_dial: NO DIALTONE");
  433.                     redial = 1;
  434.                     break;
  435.                 }
  436.             } /* End of if lastchr=='r'||'n'. */
  437.             /* Thou shall not consume all system resources
  438.                by repeatedly looping a strstr search when
  439.                the string update latency is very high as it
  440.                is in serial communication. -mg */
  441.             usleep(1000);
  442.         } /* End of read loop. */
  443.         /* Thou shall not flood the modem with dial requests. -mg */
  444.         sleep(1);
  445.     } /* End of dial loop. */
  446.     debug("bb.sms.emi", 0, "at_dial: done with dialing");
  447.     return fd;
  448. timeout:
  449.     error(0, "at_dial timed out");
  450.     close(fd);
  451.     return -1;
  452. error:
  453.     error(0, "at_dial failed");
  454.     close(fd);
  455.     return -1;
  456. }
  457. /******************************************************************************
  458.  * Wait for an ACK or NACK from the remote
  459.  *
  460.  * REQUIRED by the protocol that it must be waited...
  461.  */
  462. static int wait_for_ack(SMSCenter *smsc, int op_type)
  463. {
  464.     char *tmpbuff;
  465.     int found = 0;
  466.     int n;
  467.     time_t start;
  468.     tmpbuff = gw_malloc(10 * 1024);
  469.     memset(tmpbuff, 0, 10*1024);
  470.     start = time(NULL);
  471.     do {
  472.         /* check for data */
  473.         n = get_data(smsc, tmpbuff, 1024 * 10);
  474.         if (smsc->type == SMSC_TYPE_EMI) {
  475.             /* At least the X.31 interface wants to append the data.
  476.                Kalle, what about the TCP/IP interface? Am I correct
  477.                that you are assuming that the message arrives in a 
  478.                single read(2)? -mg */
  479.             if (n > 0)
  480. memorybuffer_append_data(smsc, tmpbuff, n);
  481.         } else if (smsc->type == SMSC_TYPE_EMI_IP) {
  482.             if (n > 0)
  483. memorybuffer_insert_data(smsc, tmpbuff, n);
  484.         }
  485.         /* act on data */
  486.         if (memorybuffer_has_rawmessage(smsc, op_type, 'R') > 0) {
  487.             memorybuffer_cut_rawmessage(smsc, tmpbuff, 10*1024);
  488.             debug("bb.sms.emi", 0, "Found ACK/NACK: <%s>", tmpbuff);
  489.             found = 1;
  490.         }
  491.     } while (!found && ((time(NULL) - start) < 5));
  492.     gw_free(tmpbuff);
  493.     return found;
  494. }
  495. /******************************************************************************
  496.  * Get the modem buffer data to buff, return the amount read
  497.  *
  498.  * Reads from main fd, but also from backup-fd - does accept if needed
  499.  */
  500. static int get_data(SMSCenter *smsc, char *buff, int length)
  501. {
  502.     int n = 0;
  503.     struct sockaddr_in client_addr;
  504.     socklen_t client_addr_len;
  505.     fd_set rf;
  506.     struct timeval to;
  507.     int ret;
  508.     memset(buff, 0, length);
  509.     if (smsc->type == SMSC_TYPE_EMI) {
  510.         tcdrain(smsc->emi_fd);
  511.         n = read(smsc->emi_fd, buff, length);
  512.         return n;
  513.     }
  514.     FD_ZERO(&rf);
  515.     if (smsc->emi_fd >= 0) FD_SET(smsc->emi_fd, &rf);
  516.     if (smsc->emi_secondary_fd >= 0) FD_SET(smsc->emi_secondary_fd, &rf);
  517.     if (smsc->emi_backup_fd > 0) FD_SET(smsc->emi_backup_fd, &rf);
  518.     FD_SET(0, &rf);
  519.     to.tv_sec = 0;
  520.     to.tv_usec = 100;
  521.     ret = select(FD_SETSIZE, &rf, NULL, NULL, &to);
  522.     if (ret > 0) {
  523.         if (smsc->emi_secondary_fd >= 0 && FD_ISSET(smsc->emi_secondary_fd, &rf)) {
  524.             n = read(smsc->emi_secondary_fd, buff, length - 1);
  525.             if (n == -1) {
  526.                 error(errno, "Error - Secondary socket closed");
  527.                 close(smsc->emi_secondary_fd);
  528.                 smsc->emi_secondary_fd = -1;
  529.             } else if (n == 0) {
  530.                 info(0, "Secondary socket closed by SMSC");
  531.                 close(smsc->emi_secondary_fd);
  532.                 smsc->emi_secondary_fd = -1;
  533.             } else { /* UGLY! We  put 'X' after message */
  534.                 buff[n] = 'X';  /* if it is from secondary fd!!!  */
  535.                 n++;
  536.             }
  537.         } else if (smsc->emi_fd >= 0 && FD_ISSET(smsc->emi_fd, &rf)) {
  538.             n = read(smsc->emi_fd, buff, length);
  539.             if (n == 0) {
  540.                 close(smsc->emi_fd);
  541.                 info(0, "Main EMI socket closed by SMSC");
  542.                 smsc->emi_fd = -1;  /* ready to be re-opened */
  543.             }
  544.         }
  545.         if ((smsc->emi_backup_fd > 0) && FD_ISSET(smsc->emi_backup_fd, &rf)) {
  546.             if (smsc->emi_secondary_fd == -1) {
  547. Octstr *ip, *allow;
  548.                 smsc->emi_secondary_fd = accept(smsc->emi_backup_fd,
  549.   (struct sockaddr *)&client_addr, &client_addr_len);
  550. ip = host_ip(client_addr);
  551. if (smsc->emi_backup_allow_ip == NULL)
  552.     allow = NULL;
  553. else
  554.     allow = octstr_create(smsc->emi_backup_allow_ip);
  555. if (is_allowed_ip(allow, octstr_imm("*.*.*.*"), ip) == 0) {
  556.     info(0, "SMSC secondary connection tried from <%s>, "
  557.          "disconnected",
  558.     octstr_get_cstr(ip));
  559.     octstr_destroy(ip);
  560.     octstr_destroy(allow);
  561.     close(smsc->emi_secondary_fd);
  562.     smsc->emi_secondary_fd = -1;
  563.     return 0;
  564. }
  565.                 info(0, "Secondary socket opened by SMSC from <%s>",
  566.      octstr_get_cstr(ip));
  567. octstr_destroy(ip);
  568. octstr_destroy(allow);
  569.             } else
  570.                 info(0, "New connection request while old secondary is open!");
  571.         }
  572.     }
  573.     if (n > 0) {
  574.         debug("bb.sms.emi", 0, "get_data:Read %d bytes: <%.*s>", n, n, buff);
  575.         debug("bb.sms.emi", 0, "get_data:smsc->buffer == <%s>", smsc->buffer);
  576.     }
  577.     return n;
  578. }
  579. /******************************************************************************
  580. * Put the buff data to the modem buffer, return the amount of data put
  581. */
  582. static int put_data(SMSCenter *smsc, char *buff, int length, int is_backup)
  583. {
  584.     size_t len = length;
  585.     int ret;
  586.     int fd = -1;
  587.     if (smsc->type == SMSC_TYPE_EMI_IP) {
  588.         if (is_backup) {
  589.             fd = smsc->emi_secondary_fd;
  590.             info(0, "Writing into secondary (backup) fd!");
  591.         } else {
  592.             if (smsc->emi_fd == -1) {
  593.                 info(0, "Reopening connection to SMSC");
  594. if (emi_open_connection_ip(smsc) < 0) {
  595.                     error(0, "put_data: Reopening failed!");
  596.                     return -1;
  597. }
  598.             }
  599.             fd = smsc->emi_fd;
  600.         }
  601.     }
  602.     if (smsc->type == SMSC_TYPE_EMI) {
  603.         fd = smsc->emi_fd;
  604.         tcdrain(smsc->emi_fd);
  605.     }
  606.     /* Write until all data has been successfully written to the fd. */
  607.     while (len > 0) {
  608.         ret = write(fd, buff, len);
  609.         if (ret == -1) {
  610.             if (errno == EINTR) continue;
  611.             if (errno == EAGAIN) continue;
  612.             error(errno, "Writing to fd failed");
  613.             if (fd == smsc->emi_fd && smsc->type == SMSC_TYPE_EMI_IP) {
  614.                 close(fd);
  615.                 smsc->emi_fd = -1;
  616.                 info(0, "Closed main EMI socket.");
  617.             }
  618.             return -1;
  619.         }
  620.         /* ret may be less than len, if the writing
  621.            was interrupted by a signal. */
  622.         len -= ret;
  623.         buff += ret;
  624.     }
  625.     if (smsc->type == SMSC_TYPE_EMI) {
  626.         /* Make sure the data gets written immediately.
  627.            Wait a while just to add some latency so
  628.            that the modem (or the UART) doesn't choke
  629.            on the data. */
  630.         tcdrain(smsc->emi_fd);
  631.         usleep(1000);
  632.     }
  633.     return 0;
  634. }
  635. /******************************************************************************
  636. * Append the buff data to smsc->buffer
  637. */
  638. static int memorybuffer_append_data(SMSCenter *smsc, char *buff, int length)
  639. {
  640.     while (smsc->bufsize < (smsc->buflen + length)) { /* buffer too small */
  641.         char *p = gw_realloc(smsc->buffer, smsc->bufsize * 2);
  642.         smsc->buffer = p;
  643.         smsc->bufsize *= 2;
  644.     }
  645.     memcpy(smsc->buffer + smsc->buflen, buff, length);
  646.     smsc->buflen += length;
  647.     return 0;
  648. }
  649. /******************************************************************************
  650. * Insert (put to head) the buff data to smsc->buffer
  651. */
  652. static int memorybuffer_insert_data(SMSCenter *smsc, char *buff, int length)
  653. {
  654.     while (smsc->bufsize < (smsc->buflen + length)) { /* buffer too small */
  655.         char *p = gw_realloc(smsc->buffer, smsc->bufsize * 2);
  656.         smsc->buffer = p;
  657.         smsc->bufsize *= 2;
  658.     }
  659.     memmove(smsc->buffer + length, smsc->buffer, smsc->buflen);
  660.     memcpy(smsc->buffer, buff, length);
  661.     smsc->buflen += length;
  662.     return 0;
  663. }
  664. /******************************************************************************
  665. * Check the smsc->buffer for a raw STX...ETX message
  666. */
  667. static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth)
  668. {
  669.     char tmpbuff[1024], tmpbuff2[1024];
  670.     char *stx, *etx;
  671.     stx = memchr(smsc->buffer, '2', smsc->buflen);
  672.     etx = memchr(smsc->buffer, '3', smsc->buflen);
  673.     if (stx && etx && stx < etx) {
  674.         strncpy(tmpbuff, stx, etx - stx + 1);
  675.         tmpbuff[etx - stx + 1] = '';
  676.         if (auth)
  677.             sprintf(tmpbuff2, "/%c/%02i/", auth, type);
  678.         else
  679.             sprintf(tmpbuff2, "/%02i/", type);
  680.         if (strstr(tmpbuff, tmpbuff2) != NULL) {
  681.             debug("bb.sms.emi", 0, "found message <%c/%02i>...msg <%s>", auth, type, tmpbuff);
  682.             return 1;
  683.         }
  684.     }
  685.     return 0;
  686. }
  687. /******************************************************************************
  688. * Cut the first raw message from the smsc->buffer
  689. * and put it in buff, return success 0, failure -1
  690. */
  691. static int memorybuffer_cut_rawmessage(SMSCenter *smsc, char *buff, int length)
  692. {
  693.     char *stx, *etx;
  694.     int size_of_cut_piece;
  695.     int size_of_the_rest;
  696.     /* We don't check for NULLs since we're sure that nobody has fooled
  697.        around with smsc->buffer since has_rawmessage was last called... */
  698.     stx = memchr(smsc->buffer, '2', smsc->buflen);
  699.     etx = memchr(smsc->buffer, '3', smsc->buflen);
  700.     if (*(etx + 1) == 'X') /* secondary! UGLY KLUDGE */
  701.         etx++;
  702.     size_of_cut_piece = (etx - stx) + 1;
  703.     size_of_the_rest = (smsc->buflen - size_of_cut_piece);
  704.     if (length < size_of_cut_piece) {
  705.         error(0, "the buffer you provided for cutting was too small");
  706.         return -1;
  707.     }
  708.     /* move the part before our magic rawmessage to the safe house */
  709.     memcpy(buff, stx, size_of_cut_piece);
  710.     buff[size_of_cut_piece] = '';  /* NULL-terminate */
  711.     /* move the stuff in membuffer one step down */
  712.     memmove(stx, etx + 1, (smsc->buffer + smsc->bufsize) - stx );
  713.     smsc->buflen -= size_of_cut_piece;
  714.     return 0;
  715. }
  716. /******************************************************************************
  717. * Parse the raw message to the Msg structure
  718. */
  719. static int parse_rawmessage_to_msg(SMSCenter *smsc, Msg **msg,
  720.                                    char *rawmessage, int length)
  721. {
  722.     char emivars[128][1024];
  723.     char *leftslash, *rightslash;
  724.     char isotext[2048];
  725.     int msgnbr;
  726.     int tmpint;
  727.     msgnbr = -1;
  728.     memset(isotext, 0, sizeof(isotext));
  729.     strncpy(isotext, rawmessage, length);
  730.     leftslash = isotext;
  731.     for (tmpint = 0; leftslash != NULL; tmpint++) {
  732.         rightslash = strchr(leftslash + 1, '/');
  733.         if (rightslash == NULL)
  734.             rightslash = strchr(leftslash + 1, '3');
  735.         if (rightslash == NULL)
  736.             break;
  737.         *rightslash = '';
  738.         strcpy(emivars[tmpint], leftslash + 1);
  739.         leftslash = rightslash;
  740.     }
  741.     if (strcmp(emivars[3], "01") == 0) {
  742.         if (strcmp(emivars[7], "2") == 0) {
  743.             strcpy(isotext, emivars[8]);
  744.         } else if (strcmp(emivars[7], "3") == 0) {
  745.             parse_emi_to_iso88591(emivars[8], isotext, sizeof(isotext),
  746.                                   smsc->alt_charset);
  747.         } else {
  748.             error(0, "Unknown 01-type EMI SMS (%s)", emivars[7]);
  749.             strcpy(isotext, "");
  750.         }
  751.     } else if (strcmp(emivars[3], "51") == 0) {
  752.         parse_emi_to_iso88591(emivars[24], isotext, sizeof(isotext),
  753.                               smsc->alt_charset);
  754.     } else if (strcmp(emivars[3], "52") == 0) {
  755.         parse_emi_to_iso88591(emivars[24], isotext, sizeof(isotext),
  756.                               smsc->alt_charset);
  757.     } else {
  758.         error(0, "HEY WE SHOULD NOT BE HERE!! Type = %s", emivars[3]);
  759.         strcpy(isotext, "");
  760.     }
  761.     *msg = msg_create(sms);
  762.     if (*msg == NULL) goto error;
  763.     (*msg)->sms.sender = octstr_create(emivars[5]);
  764.     (*msg)->sms.receiver = octstr_create(emivars[4]);
  765.     (*msg)->sms.msgdata = octstr_create(isotext);
  766.     (*msg)->sms.udhdata = NULL;
  767.     return msgnbr;
  768. error:
  769.     return -1;
  770. }
  771. /*
  772.  * notify the SMSC that we got the message
  773.  */
  774. static int acknowledge_from_rawmessage(SMSCenter *smsc,
  775.                                        char *rawmessage, int length)
  776. {
  777.     char emivars[128][1024];
  778.     char timestamp[2048], sender[2048], receiver[2048];
  779.     char emitext[2048], isotext[2048];
  780.     char *leftslash, *rightslash;
  781.     int msgnbr;
  782.     int tmpint;
  783.     int is_backup = 0;
  784.     msgnbr = -1;
  785.     memset(&sender, 0, sizeof(sender));
  786.     memset(&receiver, 0, sizeof(receiver));
  787.     memset(&emitext, 0, sizeof(emitext));
  788.     memset(&isotext, 0, sizeof(isotext));
  789.     memset(&timestamp, 0, sizeof(timestamp));
  790.     strncpy(isotext, rawmessage, length);
  791.     leftslash = isotext;
  792.     if (isotext[length - 1] == 'X')
  793.         is_backup = 1;
  794.     for (tmpint = 0; leftslash != NULL; tmpint++) {
  795.         rightslash = strchr(leftslash + 1, '/');
  796.         if (rightslash == NULL)
  797.             rightslash = strchr(leftslash + 1, '3');
  798.         if (rightslash == NULL)
  799.             break;
  800.         *rightslash = '';
  801.         strcpy(emivars[tmpint], leftslash + 1);
  802.         leftslash = rightslash;
  803.     }
  804.     /* BODY */
  805.     if (smsc->type == SMSC_TYPE_EMI) {
  806.         sprintf(isotext, "A//%s:%s", emivars[4], emivars[18]);
  807.         sprintf(isotext, "A//%s:", emivars[5]);
  808.         is_backup = 0;
  809.     }
  810.     if (smsc->type == SMSC_TYPE_EMI_IP) {
  811.         if (strcmp(emivars[3], "01") == 0)
  812.             sprintf(isotext, "A/%s:", emivars[4]);
  813.         else
  814.             sprintf(isotext, "A//%s:%s", emivars[4], emivars[18]);
  815.     }
  816.     /* HEADER */
  817.     debug("bb.sms.emi", 0, "acknowledge: type = '%s'", emivars[3]);
  818.     sprintf(emitext, "%s/%05i/%s/%s", emivars[0], (int) strlen(isotext) + 17,
  819.             "R", emivars[3]);
  820.     smsc->emi_current_msg_number = atoi(emivars[0]) + 1;
  821.     /* FOOTER */
  822.     sprintf(timestamp, "%s/%s/", emitext, isotext);
  823.     generate_checksum(timestamp, receiver);
  824.     sprintf(sender, "%c%s/%s/%s%c", 0x02, emitext, isotext, receiver, 0x03);
  825.     put_data(smsc, sender, strlen(sender), is_backup);
  826.     return msgnbr;
  827. }
  828. /******************************************************************************
  829. * Parse the Msg structure to the raw message format
  830. */
  831. static int parse_msg_to_rawmessage(SMSCenter *smsc, Msg *msg, char *rawmessage, int rawmessage_length)
  832. {
  833.     char message_whole[10*1024];
  834.     char message_body[10*1024];
  835.     char message_header[1024];
  836.     char message_footer[1024];
  837.     char my_buffer[10*1024];
  838.     char my_buffer2[10*1024];
  839.     char msgtext[1024];
  840.     int length;
  841.     char mt;
  842.     char mcl[20];
  843.     char snumbits[20];
  844.     char xser[1024];
  845.     int udh_len;
  846.     memset(&message_whole, 0, sizeof(message_whole));
  847.     memset(&message_body, 0, sizeof(message_body));
  848.     memset(&message_header, 0, sizeof(message_header));
  849.     memset(&message_footer, 0, sizeof(message_footer));
  850.     memset(&my_buffer, 0, sizeof(my_buffer));
  851.     memset(&my_buffer2, 0, sizeof(my_buffer2));
  852.     mt = '3';
  853.     memset(&snumbits, 0, sizeof(snumbits));
  854.     memset(&xser, 0, sizeof(xser));
  855.     /* XXX parse_iso88591_to_emi shouldn't use NUL terminated
  856.      * strings, but Octstr directly, or a char* and a length.
  857.      */
  858.     if (octstr_len(msg->sms.udhdata)) {
  859.         char xserbuf[258];
  860.         /* we need a properly formated UDH here, there first byte contains his length
  861.          * this will be formatted in the xser field of the EMI Protocol
  862.          */
  863.         udh_len = octstr_get_char(msg->sms.udhdata, 0) + 1;
  864.         xserbuf[0] = 1;
  865.         xserbuf[1] = udh_len;
  866.         octstr_get_many_chars(&xserbuf[2], msg->sms.udhdata, 0, udh_len);
  867.         parse_binary_to_emi(xserbuf, xser, udh_len + 2);
  868.     } else {
  869.         udh_len = 0;
  870.     }
  871.     if (msg->sms.coding == DC_7BIT ) {
  872.         octstr_get_many_chars(msgtext, msg->sms.msgdata, 0, octstr_len(msg->sms.msgdata));
  873.         msgtext[octstr_len(msg->sms.msgdata)] = '';
  874.         parse_iso88591_to_emi(msgtext, my_buffer2,
  875.                                            octstr_len(msg->sms.msgdata),
  876.                                            smsc->alt_charset);
  877.         strcpy(snumbits, "");
  878.         mt = '3';
  879.         strcpy(mcl, "");
  880.     } else {
  881.         octstr_get_many_chars(msgtext, msg->sms.msgdata, 0, octstr_len(msg->sms.msgdata));
  882.         parse_binary_to_emi(msgtext, my_buffer2, octstr_len(msg->sms.msgdata));
  883.         sprintf(snumbits, "%04ld", octstr_len(msg->sms.msgdata)*8);
  884.         mt = '4';
  885.         strcpy(mcl, "1");
  886.     }
  887.     /* XXX Where is DCS ? Is it in XSER like in emi2 ? 
  888.      * Please someone encode it with fields_to_dcs 
  889.      */
  890.     sprintf(message_body,
  891.             "%s/%s/%s/%s/%s//%s////////////%c/%s/%s////%s//////%s//",
  892.             octstr_get_cstr(msg->sms.receiver),
  893.             msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : "",
  894.             "",
  895.             "",
  896.             "",
  897.             "0100",
  898.             mt,
  899.             snumbits,
  900.             my_buffer2,
  901.             mcl,
  902.             xser);
  903.     /* HEADER */
  904.     length = strlen(message_body);
  905.     length += 13;  /* header (fixed) */
  906.     length += 2;  /* footer (fixed) */
  907.     length += 2;  /* slashes between header, body, footer */
  908.     sprintf(message_header, "%02i/%05i/%s/%s", (smsc->emi_current_msg_number++ % 100), length, "O", "51");
  909.     /* FOOTER */
  910.     sprintf(my_buffer, "%s/%s/", message_header, message_body);
  911.     generate_checksum(my_buffer, message_footer);
  912.     sprintf(message_whole, "%c%s/%s/%s%c", 0x02, message_header, message_body, message_footer, 0x03);
  913.     strncpy(rawmessage, message_whole, rawmessage_length);
  914.     if (smsc->type == SMSC_TYPE_EMI) {
  915.         /* IC3S braindead EMI stack chokes on this... must fix it at the next time... */
  916.         strcat(rawmessage, "r");
  917.     }
  918.     debug("bb.sms.emi", 0, "emi %d message %s",
  919.           smsc->emi_current_msg_number, rawmessage);
  920.     return strlen(rawmessage);
  921. }
  922. /******************************************************************************
  923. * Parse the data from the two byte EMI code to normal ISO-8869-1
  924. */
  925. static int parse_emi_to_iso88591(char *from, char *to, int length,
  926.                                  int alt_charset)
  927. {
  928.     int hmtg = 0;
  929.     unsigned int mychar;
  930.     char tmpbuff[128];
  931.     for (hmtg = 0; hmtg <= (int)strlen(from); hmtg += 2) {
  932.         strncpy(tmpbuff, from + hmtg, 2);
  933.         sscanf(tmpbuff, "%x", &mychar);
  934.         to[hmtg / 2] = char_sms_to_iso(mychar, alt_charset);
  935.     }
  936.     to[(hmtg / 2)-1] = '';
  937.     return 0;
  938. }
  939. /******************************************************************************
  940. * Parse the data from normal ISO-8869-1 to the two byte EMI code
  941. */
  942. static int parse_iso88591_to_emi(char *from, char *to,
  943.         int length, int alt_charset)
  944. {
  945.     char buf[10];
  946.     unsigned char tmpchar;
  947.     char *ptr;
  948.     if (!from || !to || length <= 0)
  949.         return -1;
  950.     *to = '';
  951.     debug("bb.sms.emi", 0, "emi parsing <%s> to emi, length %d", from, length);
  952.     for (ptr = from; length > 0; ptr++, length--) {
  953.         tmpchar = char_iso_to_sms(*ptr, alt_charset);
  954.         sprintf(buf, "%02X", tmpchar);
  955.         strncat(to, buf, 2);
  956.     }
  957.     return 0;
  958. }
  959. /******************************************************************************
  960. * Parse the data from binary to the two byte EMI code
  961. */
  962. static int parse_binary_to_emi(char *from, char *to, int length)
  963. {
  964.     char buf[10];
  965.     char *ptr;
  966.     if (!from || !to || length <= 0)
  967.         return -1;
  968.     *to = '';
  969.     for (ptr = from; length > 0; ptr++, length--) {
  970.         sprintf(buf, "%02X", (unsigned char)*ptr);
  971.         strncat(to, buf, 2);
  972.     }
  973.     return 0;
  974. }
  975. /******************************************************************************
  976. * Generate the EMI message checksum
  977. */
  978. static void generate_checksum(const unsigned char *buf, unsigned char *out)
  979. {
  980.     const unsigned char *p;
  981.     int j;
  982.     j = 0;
  983.     for (p = buf; *p != ''; p++) {
  984.         j += *p;
  985.         if (j >= 256)
  986.             j -= 256;
  987.     }
  988.     sprintf(out, "%02X", j);
  989. }
  990. /******************************************************************************
  991. * Translate character from iso to emi_mt
  992. * PGr鰊holm
  993. */
  994. static char char_iso_to_sms(unsigned char from, int alt_charset)
  995. {
  996.     switch ((char)from) {
  997.     case 'A':
  998.         return 0x41;
  999.     case 'B':
  1000.         return 0x42;
  1001.     case 'C':
  1002.         return 0x43;
  1003.     case 'D':
  1004.         return 0x44;
  1005.     case 'E':
  1006.         return 0x45;
  1007.     case 'F':
  1008.         return 0x46;
  1009.     case 'G':
  1010.         return 0x47;
  1011.     case 'H':
  1012.         return 0x48;
  1013.     case 'I':
  1014.         return 0x49;
  1015.     case 'J':
  1016.         return 0x4A;
  1017.     case 'K':
  1018.         return 0x4B;
  1019.     case 'L':
  1020.         return 0x4C;
  1021.     case 'M':
  1022.         return 0x4D;
  1023.     case 'N':
  1024.         return 0x4E;
  1025.     case 'O':
  1026.         return 0x4F;
  1027.     case 'P':
  1028.         return 0x50;
  1029.     case 'Q':
  1030.         return 0x51;
  1031.     case 'R':
  1032.         return 0x52;
  1033.     case 'S':
  1034.         return 0x53;
  1035.     case 'T':
  1036.         return 0x54;
  1037.     case 'U':
  1038.         return 0x55;
  1039.     case 'V':
  1040.         return 0x56;
  1041.     case 'W':
  1042.         return 0x57;
  1043.     case 'X':
  1044.         return 0x58;
  1045.     case 'Y':
  1046.         return 0x59;
  1047.     case 'Z':
  1048.         return 0x5A;
  1049.     case 'a':
  1050.         return 0x61;
  1051.     case 'b':
  1052.         return 0x62;
  1053.     case 'c':
  1054.         return 0x63;
  1055.     case 'd':
  1056.         return 0x64;
  1057.     case 'e':
  1058.         return 0x65;
  1059.     case 'f':
  1060.         return 0x66;
  1061.     case 'g':
  1062.         return 0x67;
  1063.     case 'h':
  1064.         return 0x68;
  1065.     case 'i':
  1066.         return 0x69;
  1067.     case 'j':
  1068.         return 0x6A;
  1069.     case 'k':
  1070.         return 0x6B;
  1071.     case 'l':
  1072.         return 0x6C;
  1073.     case 'm':
  1074.         return 0x6D;
  1075.     case 'n':
  1076.         return 0x6E;
  1077.     case 'o':
  1078.         return 0x6F;
  1079.     case 'p':
  1080.         return 0x70;
  1081.     case 'q':
  1082.         return 0x71;
  1083.     case 'r':
  1084.         return 0x72;
  1085.     case 's':
  1086.         return 0x73;
  1087.     case 't':
  1088.         return 0x74;
  1089.     case 'u':
  1090.         return 0x75;
  1091.     case 'v':
  1092.         return 0x76;
  1093.     case 'w':
  1094.         return 0x77;
  1095.     case 'x':
  1096.         return 0x78;
  1097.     case 'y':
  1098.         return 0x79;
  1099.     case 'z':
  1100.         return 0x7A;
  1101.     case '0':
  1102.         return 0x30;
  1103.     case '1':
  1104.         return 0x31;
  1105.     case '2':
  1106.         return 0x32;
  1107.     case '3':
  1108.         return 0x33;
  1109.     case '4':
  1110.         return 0x34;
  1111.     case '5':
  1112.         return 0x35;
  1113.     case '6':
  1114.         return 0x36;
  1115.     case '7':
  1116.         return 0x37;
  1117.     case '8':
  1118.         return 0x38;
  1119.     case '9':
  1120.         return 0x39;
  1121.     case ':':
  1122.         return 0x3A;
  1123.     case ';':
  1124.         return 0x3B;
  1125.     case '<':
  1126.         return 0x3C;
  1127.     case '=':
  1128.         return 0x3D;
  1129.     case '>':
  1130.         return 0x3E;
  1131.     case '?':
  1132.         return 0x3F;
  1133.     case '