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

手机WAP编程

开发平台:

WINDOWS

  1. /* Driver for CIMD 2 SMS centres.
  2.  * Copyright 2000  WapIT Oy Ltd.
  3.  * Author: Richard Braakman
  4.  */
  5. /* TODO: Check checksums on incoming packets */
  6. /* TODO: Leading or trailing spaces are not allowed on parameters
  7.  * "user identity" and "password".  Check this. */
  8. /* TODO: Try to use the "More messages to send" flag */
  9. /* This code is based on the CIMD 2 spec, version 2-0 en.
  10.  * All USSD-specific parts have been left out, since we only want to
  11.  * communicate with SMSC's.
  12.  *
  13.  * I found one contradiction in the spec:
  14.  *
  15.  * - The definition of Integer parameters specifies decimal digits only,
  16.  *   but at least one Integer parameter (Validity Period Relative) can
  17.  *   be negative.  I assume that this means a leading - is valid.
  18.  */
  19. #include <ctype.h>
  20. #include <time.h>
  21. #include <errno.h>
  22. #include <limits.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include "gwlib/gwlib.h"
  26. #include "smsc_p.h"
  27. #include "sms.h"
  28. #include "dlr.h"
  29. #ifndef CIMD2_TRACE
  30. #define CIMD2_TRACE 0
  31. #endif
  32. /* Microseconds before giving up on a request */
  33. #define RESPONSE_TIMEOUT (10 * 1000000)
  34. /* Textual names for the operation codes defined by the CIMD 2 spec. */
  35. /* If you make changes here, also change the operation table. */
  36. enum {
  37.     /* Requests from client */
  38.     LOGIN = 1,
  39.     LOGOUT = 2,
  40.     SUBMIT_MESSAGE = 3,
  41.     ENQUIRE_MESSAGE_STATUS = 4,
  42.     DELIVERY_REQUEST = 5,
  43.     CANCEL_MESSAGE = 6,
  44.     SET_REQ = 8,
  45.     GET_REQ = 9,
  46.     /* Requests from server */
  47.     DELIVER_MESSAGE = 20,
  48.     DELIVER_STATUS_REPORT = 23,
  49.     /* Requests from either */
  50.     ALIVE = 40,
  51.     /* Not a request; add to any request to make it a response */
  52.     RESPONSE = 50,
  53.     /* Responses not related to requests */
  54.     GENERAL_ERROR_RESPONSE = 98,
  55.     NACK = 99
  56. };
  57. /* Textual names for the parameters defined by the CIMD 2 spec. */
  58. /* If you make changes here, also change the parameter table. */
  59. enum {
  60.     P_USER_IDENTITY = 10,
  61.     P_PASSWORD = 11,
  62.     P_DESTINATION_ADDRESS = 21,
  63.     P_ORIGINATING_ADDRESS = 23,
  64.     P_ORIGINATING_IMSI = 26,
  65.     P_ORIGINATED_VISITED_MSC = 28,
  66.     P_DATA_CODING_SCHEME = 30,
  67.     P_USER_DATA_HEADER = 32,
  68.     P_USER_DATA = 33,
  69.     P_USER_DATA_BINARY = 34,
  70.     P_MORE_MESSAGES_TO_SEND = 44,
  71.     P_VALIDITY_PERIOD_RELATIVE = 50,
  72.     P_VALIDITY_PERIOD_ABSOLUTE = 51,
  73.     P_PROTOCOL_IDENTIFIER = 52,
  74.     P_FIRST_DELIVERY_TIME_RELATIVE = 53,
  75.     P_FIRST_DELIVERY_TIME_ABSOLUTE = 54,
  76.     P_REPLY_PATH = 55,
  77.     P_STATUS_REPORT_REQUEST = 56,
  78.     P_CANCEL_ENABLED = 58,
  79.     P_CANCEL_MODE = 59,
  80.     P_MC_TIMESTAMP = 60,
  81.     P_STATUS_CODE = 61,
  82.     P_STATUS_ERROR_CODE = 62,
  83.     P_DISCHARGE_TIME = 63,
  84.     P_TARIFF_CLASS = 64,
  85.     P_SERVICE_DESCRIPTION = 65,
  86.     P_MESSAGE_COUNT = 66,
  87.     P_PRIORITY = 67,
  88.     P_DELIVERY_REQUEST_MODE = 68,
  89.     P_GET_PARAMETER = 500,
  90.     P_MC_TIME = 501,
  91.     P_ERROR_CODE = 900,
  92.     P_ERROR_TEXT = 901
  93. };
  94. /***************************************************************************/
  95. /* Table of properties of the parameters defined by CIMD 2, and some       */
  96. /* functions to look up fields.                                            */
  97. /***************************************************************************/
  98. /* Parameter types, internal.  CIMD 2 spec considers P_TIME to be "Integer"
  99.  * and P_SMS to be "User Data". */
  100. enum { P_INT, P_STRING, P_ADDRESS, P_TIME, P_HEX, P_SMS };
  101. /* Information about the parameters defined by the CIMD 2 spec.
  102.  * Used for warning about invalid incoming messages, and for validating
  103.  * outgoing messages. */
  104. static const struct
  105. {
  106.     unsigned char *name;
  107.     int number;
  108.     int maxlen;
  109.     int type;  /* P_ values */
  110.     int minval, maxval;  /* For P_INT */
  111. }
  112. parameters[] = {
  113.     { "user identity", P_USER_IDENTITY, 32, P_STRING },
  114.     { "password", P_PASSWORD, 32, P_STRING },
  115.     { "destination address", P_DESTINATION_ADDRESS, 20, P_ADDRESS },
  116.     { "originating address", P_ORIGINATING_ADDRESS, 20, P_ADDRESS },
  117.     /* IMSI is International Mobile Subscriber Identity number */
  118.     { "originating IMSI", P_ORIGINATING_IMSI, 20, P_ADDRESS },
  119.     { "originated visited MSC", P_ORIGINATED_VISITED_MSC, 20, P_ADDRESS },
  120.     { "data coding scheme", P_DATA_CODING_SCHEME, 3, P_INT, 0, 255 },
  121.     { "user data header", P_USER_DATA_HEADER, 280, P_HEX },
  122.     { "user data", P_USER_DATA, 480, P_SMS },
  123.     { "user data binary", P_USER_DATA_BINARY, 280, P_HEX },
  124.     { "more messages to send", P_MORE_MESSAGES_TO_SEND, 1, P_INT, 0, 1 },
  125.     { "validity period relative", P_VALIDITY_PERIOD_RELATIVE, 3, P_INT, -1, 255 },
  126.     { "validity period absolute", P_VALIDITY_PERIOD_ABSOLUTE, 12, P_TIME },
  127.     { "protocol identifier", P_PROTOCOL_IDENTIFIER, 3, P_INT, 0, 255 },
  128.     { "first delivery time relative", P_FIRST_DELIVERY_TIME_RELATIVE, 3, P_INT, -1, 255 },
  129.     { "first delivery time absolute", P_FIRST_DELIVERY_TIME_ABSOLUTE, 12, P_TIME },
  130.     { "reply path", P_REPLY_PATH, 1, P_INT, 0, 1 },
  131.     { "status report request", P_STATUS_REPORT_REQUEST, 2, P_INT, 0, 63 },
  132.     { "cancel enabled", P_CANCEL_ENABLED, 1, P_INT, 0, 1 },
  133.     { "cancel mode", P_CANCEL_MODE, 1, P_INT, 0, 2 },
  134.     { "service centre timestamp", P_MC_TIMESTAMP, 12, P_TIME },
  135.     { "status code", P_STATUS_CODE, 2, P_INT, 0, 9 },
  136.     { "status error code", P_STATUS_ERROR_CODE, 3, P_INT, 0, 999 },
  137.     { "discharge time", P_DISCHARGE_TIME, 12, P_TIME },
  138.     { "tariff class", P_TARIFF_CLASS, 2, P_INT, 0, 99 },
  139.     { "service description", P_SERVICE_DESCRIPTION, 1, P_INT, 0, 9 },
  140.     { "message count", P_MESSAGE_COUNT, 3, P_INT, 0, 999 },
  141.     { "priority", P_PRIORITY, 1, P_INT, 1, 9 },
  142.     { "delivery request mode", P_DELIVERY_REQUEST_MODE, 1, P_INT, 0, 2 },
  143.     { "get parameter", P_GET_PARAMETER, 3, P_INT, 501, 999 },
  144.     { "MC time", P_MC_TIME, 12, P_TIME },
  145.     { "error code", P_ERROR_CODE, 3, P_INT, 0, 999 },
  146.     { "error text", P_ERROR_TEXT, 64, P_STRING },
  147.     { NULL }
  148. };
  149. /* Return the index in the parameters array for this parameter id.
  150.  * Return -1 if it is not found. */
  151. static const int parm_index(int parmno)
  152. {
  153.     int i;
  154.     for (i = 0; parameters[i].name != NULL; i++) {
  155.         if (parameters[i].number == parmno)
  156.             return i;
  157.     }
  158.     return -1;
  159. }
  160. #ifndef NO_GWASSERT
  161. /* Return the type of this parameter id.  Return -1 if the id is unknown. */
  162. static const int parm_type(int parmno)
  163. {
  164.     int i = parm_index(parmno);
  165.     if (i < 0)
  166.         return -1;
  167.     return parameters[i].type;
  168. }
  169. #endif
  170. /* Return the max length for this parameter id.
  171.  * Return -1 if the id is unknown. */
  172. static const int parm_maxlen(int parmno)
  173. {
  174.     int i = parm_index(parmno);
  175.     if (i < 0)
  176.         return -1;
  177.     return parameters[i].maxlen;
  178. }
  179. static const char *parm_name(int parmno)
  180. {
  181.     int i = parm_index(parmno);
  182.     if (i < 0)
  183.         return NULL;
  184.     return parameters[i].name;
  185. }
  186. #ifndef NO_GWASSERT
  187. /* Return 1 if the value for this (Integer) parameter is in range.
  188.  * Return 0 otherwise.  Return -1 if the parameter was not found.  */
  189. static const int parm_in_range(int parmno, long value)
  190. {
  191.     int i;
  192.     i = parm_index(parmno);
  193.     if (i < 0)
  194.         return -1;
  195.     return (value >= parameters[i].minval && value <= parameters[i].maxval);
  196. }
  197. #endif
  198. /* Helper function to check P_ADDRESS type */
  199. static int isphonedigit(int c)
  200. {
  201.     return isdigit(c) || c == '+' || c == '-';
  202. }
  203. static const int parm_valid_address(Octstr *value)
  204. {
  205.     return octstr_check_range(value, 0, octstr_len(value), isphonedigit);
  206. }
  207. /***************************************************************************/
  208. /* Some functions to look up information about operation codes             */
  209. /***************************************************************************/
  210. static int operation_find(int operation);
  211. static Octstr *operation_name(int operation);
  212. static const int operation_can_send(int operation);
  213. static const int operation_can_receive(int operation);
  214. static const struct
  215. {
  216.     unsigned char *name;
  217.     int code;
  218.     int can_send;
  219.     int can_receive;
  220. }
  221. operations[] = {
  222.     { "Login", LOGIN, 1, 0 },
  223.     { "Logout", LOGOUT, 1, 0 },
  224.     { "Submit message", SUBMIT_MESSAGE, 1, 0 },
  225.     { "Enquire message status", ENQUIRE_MESSAGE_STATUS, 1, 0 },
  226.     { "Delivery request", DELIVERY_REQUEST, 1, 0 },
  227.     { "Cancel message", CANCEL_MESSAGE, 1, 0 },
  228.     { "Set parameter", SET_REQ, 1, 0 },
  229.     { "Get parameter", GET_REQ, 1, 0 },
  230.     { "Deliver message", DELIVER_MESSAGE, 0, 1 },
  231.     { "Deliver status report", DELIVER_STATUS_REPORT, 0, 1 },
  232.     { "Alive", ALIVE, 1, 1 },
  233.     { "NACK", NACK, 1, 1 },
  234.     { "General error response", GENERAL_ERROR_RESPONSE, 0, 1 },
  235.     { NULL, 0, 0, 0 }
  236. };
  237. static int operation_find(int operation)
  238. {
  239.     int i;
  240.     for (i = 0; operations[i].name != NULL; i++) {
  241.         if (operations[i].code == operation)
  242.             return i;
  243.     }
  244.     return -1;
  245. }
  246. /* Return a human-readable representation of this operation code */
  247. static Octstr *operation_name(int operation)
  248. {
  249.     int i;
  250.     i = operation_find(operation);
  251.     if (i >= 0)
  252.         return octstr_create(operations[i].name);
  253.     if (operation >= RESPONSE) {
  254.         i = operation_find(operation - RESPONSE);
  255.         if (i >= 0) {
  256.             Octstr *name = octstr_create(operations[i].name);
  257.             octstr_append_cstr(name, " response");
  258.             return name;
  259.         }
  260.     }
  261.     /* Put the operation number here when we have octstr_format */
  262.     return octstr_create("(unknown)");
  263. }
  264. /* Return true if a CIMD2 client may send this operation */
  265. static const int operation_can_send(int operation)
  266. {
  267.     int i = operation_find(operation);
  268.     if (i >= 0)
  269.         return operations[i].can_send;
  270.     /* If we can receive the request, then we can send the response. */
  271.     if (operation >= RESPONSE)
  272.         return operation_can_receive(operation - RESPONSE);
  273.     return 0;
  274. }
  275. /* Return true if a CIMD2 server may send this operation */
  276. static const int operation_can_receive(int operation)
  277. {
  278.     int i = operation_find(operation);
  279.     if (i >= 0)
  280.         return operations[i].can_receive;
  281.     /* If we can send the request, then we can receive the response. */
  282.     if (operation >= RESPONSE)
  283.         return operation_can_send(operation - RESPONSE);
  284.     return 0;
  285. }
  286. /***************************************************************************/
  287. /* Packet encoding/decoding functions.  They handle packets at the octet   */
  288. /* level, and know nothing of the network.                                 */
  289. /***************************************************************************/
  290. struct packet
  291. {
  292.     /* operation and seq are -1 if their value could not be parsed */
  293.     int operation;
  294.     int seq;   /* Sequence number */
  295.     Octstr *data;   /* Encoded packet */
  296.     /* CIMD 2 packet structure is so simple that packet information is
  297.      * stored as a valid encoded packet, and decoded as necessary. 
  298.      * Exceptions: operation code and sequence number are also stored
  299.      * as ints for speed, and the checksum is not added until the packet
  300.      * is about to be sent.  Since checksums are optional, the packet
  301.      * is still valid without a checksum.
  302.      *
  303.      * The sequence number is kept at 0 until it's time to actually
  304.      * send the packet, so that the send functions have control over
  305.      * the sequence numbers.
  306.      */
  307. };
  308. /* These are the separators defined by the CIMD 2 spec */
  309. #define STX 2   /* Start of packet */
  310. #define ETX 3   /* End of packet */
  311. #define TAB 9   /* End of parameter */
  312. /* The same separators, in string form */
  313. #define STX_str "2"
  314. #define ETX_str "3"
  315. #define TAB_str "11"
  316. /* A reminder that packets are created without a valid sequence number */
  317. #define BOGUS_SEQUENCE 0
  318. static Msg *cimd2_accept_delivery_report_message(struct packet *request, SMSCenter *smsc);
  319. /* Look for the STX OO:SSS TAB header defined by CIMD 2, where OO is the
  320.  * operation code in two decimals and SSS is the sequence number in three
  321.  * decimals.  Leave the results in the proper fields of the packet.
  322.  * Try to make sense of headers that don't fit this pattern; validating
  323.  * the packet format is not our job. */
  324. static void packet_parse_header(struct packet *packet)
  325. {
  326.     int pos;
  327.     long number;
  328.     /* Set default values, in case we can't parse the fields */
  329.     packet->operation = -1;
  330.     packet->seq = -1;
  331.     pos = octstr_parse_long(&number, packet->data, 1, 10);
  332.     if (pos < 0)
  333.         return;
  334.     packet->operation = number;
  335.     if (octstr_get_char(packet->data, pos++) != ':')
  336.         return;
  337.     pos = octstr_parse_long(&number, packet->data, pos, 10);
  338.     if (pos < 0)
  339.         return;
  340.     packet->seq = number;
  341. }
  342. /* Accept an Octstr containing one packet, build a struct packet around
  343.  * it, and return that struct.  The Octstr is stored in the struct.
  344.  * No error checking is done here yet. */
  345. static struct packet *packet_parse(Octstr *packet_data)
  346. {
  347.     struct packet *packet;
  348.     packet = gw_malloc(sizeof(*packet));
  349.     packet->data = packet_data;
  350.     /* Fill in packet->operation and packet->seq */
  351.     packet_parse_header(packet);
  352.     return packet;
  353. }
  354. /* Deallocate this packet */
  355. static void packet_destroy(struct packet *packet)
  356. {
  357.     if (packet != NULL) {
  358.         octstr_destroy(packet->data);
  359.         gw_free(packet);
  360.     }
  361. }
  362. /* Find the first packet in "in", delete it from "in", and return it as
  363.  * a struct.  Return NULL if "in" contains no packet.  Always delete
  364.  * leading non-packet data from "in".  (The CIMD 2 spec says we should
  365.  * ignore any data between the packet markers). */
  366. static struct packet *packet_extract(Octstr *in)
  367. {
  368.     int stx, etx;
  369.     Octstr *packet;
  370.     /* Find STX, and delete everything up to it */
  371.     stx = octstr_search_char(in, STX, 0);
  372.     if (stx < 0) {
  373.         octstr_delete(in, 0, octstr_len(in));
  374.         return NULL;
  375.     } else {
  376.         octstr_delete(in, 0, stx);
  377.     }
  378.     /* STX is now in position 0.  Find ETX. */
  379.     etx = octstr_search_char(in, ETX, 1);
  380.     if (etx < 0)
  381.         return NULL;
  382.     /* What shall we do with STX data... STX data... ETX?
  383.      * Either skip to the second STX, or assume an ETX marker before
  384.      * the STX.  Doing the latter has a chance of succeeding, and
  385.      * will at least allow good logging of the error. */
  386.     stx = octstr_search_char(in, STX, 1);
  387.     if (stx >= 0 && stx < etx) {
  388.         warning(0, "CIMD2: packet without end marker");
  389.         packet = octstr_copy(in, 0, stx);
  390.         octstr_delete(in, 0, stx);
  391.         octstr_append_cstr(packet, ETX_str);
  392.     } else {
  393.         /* Normal case. Copy packet, and cut it from the source. */
  394.         packet = octstr_copy(in, 0, etx + 1);
  395.         octstr_delete(in, 0, etx + 1);
  396.     }
  397.     return packet_parse(packet);
  398. }
  399. /* The get_parm functions always return the first parameter with the
  400.  * correct id.  There is only one case where the spec allows multiple
  401.  * parameters with the same id, and that is when an SMS has multiple
  402.  * destination addresses.  We only support one destination address anyway. */
  403. /* Look for the first parameter with id 'parmno' and return its value.
  404.  * Return NULL if the parameter was not found. */
  405. static Octstr *packet_get_parm(struct packet *packet, int parmno)
  406. {
  407.     long pos, next;
  408.     long valuepos;
  409.     long number;
  410.     gw_assert(packet != NULL);
  411.     pos = octstr_search_char(packet->data, TAB, 0);
  412.     if (pos < 0)
  413.         return NULL;  /* Bad packet, nothing we can do */
  414.     /* Parameters have a tab on each end.  If we don't find the
  415.      * closing tab, we're at the checksum, so we stop. */
  416.     for ( ;
  417.           (next = octstr_search_char(packet->data, TAB, pos + 1)) >= 0;
  418.           pos = next) {
  419.         if (octstr_parse_long(&number, packet->data, pos + 1, 10) < 0)
  420.             continue;
  421.         if (number != parmno)
  422.             continue;
  423.         valuepos = octstr_search_char(packet->data, ':', pos + 1);
  424.         if (valuepos < 0)
  425.             continue;  /* badly formatted parm */
  426.         valuepos++;  /* skip the ':' */
  427.         /* Found the right parameter */
  428.         return octstr_copy(packet->data, valuepos, next - valuepos);
  429.     }
  430.     return NULL;
  431. }
  432. /* Look for an Integer parameter with id 'parmno' in the packet and
  433.  * return its value.  Return INT_MIN if the parameter was not found.
  434.  * (Unfortunately, -1 is a valid parameter value for at least one
  435.  * parameter.) */
  436. static long packet_get_int_parm(struct packet *packet, int parmno)
  437. {
  438.     Octstr *valuestr = NULL;
  439.     long value;
  440.     /* Our code should never even try a bad parameter access. */
  441.     gw_assert(parm_type(parmno) == P_INT);
  442.     valuestr = packet_get_parm(packet, parmno);
  443.     if (!valuestr)
  444.         goto error;
  445.     if (octstr_parse_long(&value, valuestr, 0, 10) < 0)
  446.         goto error;
  447.     octstr_destroy(valuestr);
  448.     return value;
  449. error:
  450.     octstr_destroy(valuestr);
  451.     return INT_MIN;
  452. }
  453. /* Look for a String parameter with id 'parmno' in the packet and
  454.  * return its value.  Return NULL if the parameter was not found.
  455.  * No translations are done on the value. */
  456. static Octstr *packet_get_string_parm(struct packet *packet, int parmno)
  457. {
  458.     /* Our code should never even try a bad parameter access. */
  459.     gw_assert(parm_type(parmno) == P_STRING);
  460.     return packet_get_parm(packet, parmno);
  461. }
  462. /* Look for an Address parameter with id 'parmno' in the packet and
  463.  * return its value.  Return NULL if the parameter was not found.
  464.  * No translations are done on the value. */
  465. static Octstr *packet_get_address_parm(struct packet *packet, int parmno)
  466. {
  467.     /* Our code should never even try a bad parameter access. */
  468.     gw_assert(parm_type(parmno) == P_ADDRESS);
  469.     return packet_get_parm(packet, parmno);
  470. }
  471. /* Look for an SMS parameter with id 'parmno' in the packet and return its
  472.  * value.  Return NULL if the parameter was not found.  No translations
  473.  * are done on the value, so it will be in the ISO-Latin-1 character set
  474.  * with CIMD2-specific escapes. */
  475. static Octstr *packet_get_sms_parm(struct packet *packet, int parmno)
  476. {
  477.     /* Our code should never even try a bad parameter access. */
  478.     gw_assert(parm_type(parmno) == P_SMS);
  479.     return packet_get_parm(packet, parmno);
  480. }
  481. /* There is no packet_get_time_parm because the CIMD 2 timestamp
  482.  * format is useless.  It's in the local time of the MC, with
  483.  * a 2-digit year and no DST information.  We can do without.
  484.  */
  485. /* Look for a Hex parameter with id 'parmno' in the packet and return
  486.  * its value.  Return NULL if the parameter was not found.  The value
  487.  * is de-hexed. */
  488. static Octstr *packet_get_hex_parm(struct packet *packet, int parmno)
  489. {
  490.     Octstr *value = NULL;
  491.     /* Our code should never even try a bad parameter access. */
  492.     gw_assert(parm_type(parmno) == P_HEX);
  493.     value = packet_get_parm(packet, parmno);
  494.     if (!value)
  495.         goto error;
  496.     if (octstr_hex_to_binary(value) < 0)
  497.         goto error;
  498.     return value;
  499. error:
  500.     octstr_destroy(value);
  501.     return NULL;
  502. }
  503. /* Check if the header is according to CIMD 2 spec, generating log
  504.  * entries as necessary.  Return -1 if anything was wrong, otherwise 0. */
  505. static int packet_check_header(struct packet *packet)
  506. {
  507.     Octstr *data;
  508.     gw_assert(packet != NULL);
  509.     data = packet->data;
  510.     /* The header must have a two-digit operation code, a colon,
  511.      * and a three-digit sequence number, followed by a tab.
  512.      * (CIMD2, 3.1) */
  513.     if (octstr_len(data) < 8 ||
  514.         !octstr_check_range(data, 1, 2, gw_isdigit) ||
  515.         octstr_get_char(data, 3) != ':' ||
  516.         !octstr_check_range(data, 4, 3, gw_isdigit) ||
  517.         octstr_get_char(data, 7) != TAB) {
  518.         warning(0, "CIMD2 packet header in wrong format");
  519.         return -1;
  520.     }
  521.     return 0;
  522. }
  523. static int packet_check_parameter(struct packet *packet, long pos, long len)
  524. {
  525.     Octstr *data;
  526.     long parm;
  527.     long dpos, dlen;
  528.     int negative;
  529.     long value;
  530.     int i;
  531.     int errors = 0;
  532.     gw_assert(packet != NULL);
  533.     data = packet->data;
  534.     /* The parameter header should be TAB, followed by a three-digit
  535.      * parameter number, a colon, and the data.  We already know about
  536.      * the tab. */
  537.     if (len < 5 ||
  538.         !octstr_check_range(data, pos + 1, 3, gw_isdigit) ||
  539.         octstr_get_char(data, pos + 4) != ':') {
  540.         warning(0, "CIMD2 parameter at offset %ld in wrong format",
  541.                 pos);
  542.         errors++;
  543.     }
  544.     /* If we can't parse a parameter number, there's nothing more
  545.      * that we can check. */
  546.     dpos = octstr_parse_long(&parm, data, pos + 1, 10);
  547.     if (dpos < 0)
  548.         return -1;
  549.     if (octstr_get_char(data, dpos) == ':')
  550.         dpos++;
  551.     dlen = len - (dpos - pos);
  552.     /* dlen can not go negative because octstr_parse_long must have
  553.      * been stopped by the TAB at the end of the parameter data. */
  554.     gw_assert(dlen >= 0);
  555.     i = parm_index(parm);
  556.     if (i < 0) {
  557.         warning(0, "CIMD2 packet contains unknown parameter %ld", parm);
  558.         return -1;
  559.     }
  560.     if (dlen > parameters[i].maxlen) {
  561.         warning(0, "CIMD2 packet has '%s' parameter with length %ld, spec says max %d",
  562.                 parameters[i].name, len, parameters[i].maxlen);
  563.         errors++;
  564.     }
  565.     switch (parameters[i].type) {
  566.     case P_INT:
  567.         /* Allow a leading - */
  568.         negative = (octstr_get_char(data, dpos) == '-');
  569.         if (!octstr_check_range(data, dpos + negative,
  570.                                 dlen - negative, gw_isdigit)) {
  571.             warning(0, "CIMD2 packet has '%s' parameter with non-integer contents", parameters[i].name);
  572.             errors++;
  573.         }
  574.         if (octstr_parse_long(&value, data, dpos, 10) >= 0 &&
  575.             (value < parameters[i].minval || value > parameters[i].maxval)) {
  576.             warning(0, "CIMD2 packet has '%s' parameter out of range (value %ld, min %d, max %d)",
  577.                     parameters[i].name, value,
  578.                     parameters[i].minval, parameters[i].maxval);
  579.             errors++;
  580.         }
  581.         break;
  582.     case P_TIME:
  583.         if (!octstr_check_range(data, dpos, dlen, gw_isdigit)) {
  584.             warning(0, "CIMD2 packet has '%s' parameter with non-digit contents", parameters[i].name);
  585.             errors++;
  586.         }
  587.         break;
  588.     case P_ADDRESS:
  589.         if (!octstr_check_range(data, dpos, dlen, isphonedigit)) {
  590.             warning(0, "CIMD2 packet has '%s' parameter with non phone number contents", parameters[i].name);
  591.             errors++;
  592.         }
  593.         break;
  594.     case P_HEX:
  595.         if (!octstr_check_range(data, dpos, dlen, gw_isxdigit)) {
  596.             warning(0, "CIMD2 packet has '%s' parameter with non-hex contents", parameters[i].name);
  597.             errors++;
  598.         }
  599.         if (dlen % 2 != 0) {
  600.             warning(0, "CIMD2 packet has odd-length '%s' parameter", parameters[i].name);
  601.             errors++;
  602.         }
  603.         break;
  604.     case P_SMS:
  605.     case P_STRING:  /* nothing to check */
  606.         break;
  607.     }
  608.     if (errors > 0)
  609.         return -1;
  610.     return 0;
  611. }
  612. /* Check the packet against the CIMD 2 spec, generating log entries as
  613.  * necessary. Return -1 if anything was wrong, otherwise 0. */
  614. /* TODO: Check if parameters found actually belong in the packet type */
  615. static int packet_check(struct packet *packet)
  616. {
  617.     int errors = 0;
  618.     long pos, len, next;
  619.     Octstr *data;
  620.     gw_assert(packet != NULL);
  621.     data = packet->data;
  622.     if (octstr_search_char(data, 0, 0) >= 0) {
  623.         /* CIMD2 spec does not allow NUL bytes in a packet */
  624.         warning(0, "CIMD2 packet contains NULs");
  625.         errors++;
  626.     }
  627.     /* Assume the packet starts with STX and ends with ETX,
  628.      * because we parsed it that way in the first place. */
  629.     errors += (packet_check_header(packet) < 0);
  630.     /* Parameters are separated by tabs.  After the last parameter
  631.      * there is a tab, an optional two-digit checksum, and the ETX.
  632.      * Check each parameter in turn, by skipping from tab to tab.
  633.      */
  634.     len = octstr_len(data);
  635.     /* Start at the first tab, wherever it is, so that we can still
  636.      * check parameters if the header was weird. */
  637.     pos = octstr_search_char(data, TAB, 0);
  638.     for ( ; pos >= 0; pos = next) {
  639.         next = octstr_search_char(data, TAB, pos + 1);
  640.         if (next >= 0) {
  641.             errors += (packet_check_parameter(packet, pos, next - pos) < 0);
  642.         } else {
  643.             /* Check if the checksum has the right format.  Don't
  644.              * check the sum itself here, that will be done in a
  645.              * separate call later. */
  646.             /* There are two valid formats: TAB ETX (no checksum)
  647.              * and TAB digit digit ETX.  We already know the TAB
  648.              * and the ETX are there. */
  649.             if (!(octstr_len(data) - pos == 2 ||
  650.                   (octstr_len(data) - pos == 4 &&
  651.                    octstr_check_range(data, pos + 1, 2, gw_isxdigit)))) {
  652.                 warning(0, "CIMD2 packet checksum in wrong format");
  653.                 errors++;
  654.             }
  655.         }
  656.     }
  657.     if (errors > 0) {
  658.         octstr_dump(packet->data, 0);
  659.         return -1;
  660.     }
  661.     return 0;
  662. }
  663. static void packet_check_can_receive(struct packet *packet)
  664. {
  665.     gw_assert(packet != NULL);
  666.     if (!operation_can_receive(packet->operation)) {
  667.         Octstr *name = operation_name(packet->operation);
  668.         warning(0, "CIMD2 SMSC sent us %s request",
  669.                 octstr_get_cstr(name));
  670.         octstr_destroy(name);
  671.     }
  672. }
  673. /* Table of known error codes */
  674. static struct
  675. {
  676.     int code;
  677.     unsigned char *text;
  678. }
  679. cimd2_errors[] = {
  680.     { 0, "No error" },
  681.     { 1, "Unexpected operation" },
  682.     { 2, "Syntax error" },
  683.     { 3, "Unsupported parameter error" },
  684.     { 4, "Connection to message center lost" },
  685.     { 5, "No response from message center" },
  686.     { 6, "General system error" },
  687.     { 7, "Cannot find information" },
  688.     { 8, "Parameter formatting error" },
  689.     { 9, "Requested operation failed" },
  690.     /* LOGIN error codes */
  691.     { 100, "Invalid login" },
  692.     { 101, "Incorrect access type" },
  693.     { 102, "Too many users with this login id" },
  694.     { 103, "Login refused by message center" },
  695.     /* SUBMIT MESSAGE error codes */
  696.     { 300, "Incorrect destination address" },
  697.     { 301, "Incorrect number of destination addresses" },
  698.     { 302, "Syntax error in user data parameter" },
  699.     { 303, "Incorrect bin/head/normal user data parameter combination" },
  700.     { 304, "Incorrect data coding scheme parameter usage" },
  701.     { 305, "Incorrect validity period parameters usage" },
  702.     { 306, "Incorrect originator address usage" },
  703.     { 307, "Incorrect pid paramterer usage" },
  704.     { 308, "Incorrect first delivery parameter usage" },
  705.     { 309, "Incorrect reply path usage" },
  706.     { 310, "Incorrect status report request parameter usage" },
  707.     { 311, "Incorrect cancel enabled parameter usage" },
  708.     { 312, "Incorrect priority parameter usage" },
  709.     { 313, "Incorrect tariff class parameter usage" },
  710.     { 314, "Incorrect service description parameter usage" },
  711.     { 315, "Incorrect transport type parameter usage" },
  712.     { 316, "Incorrect message type parameter usage" },
  713.     { 318, "Incorrect mms parameter usage" },
  714.     { 319, "Incorrect operation timer parameter usage" },
  715.     /* ENQUIRE MESSAGE STATUS error codes */
  716.     { 400, "Incorrect address parameter usage" },
  717.     { 401, "Incorrect scts parameter usage" },
  718.     /* DELIVERY REQUEST error codes */
  719.     { 500, "Incorrect scts parameter usage" },
  720.     { 501, "Incorrect mode parameter usage" },
  721.     { 502, "Incorrect parameter combination" },
  722.     /* CANCEL MESSAGE error codes */
  723.     { 600, "Incorrect scts parameter usage" },
  724.     { 601, "Incorrect address parameter usage" },
  725.     { 602, "Incorrect mode parameter usage" },
  726.     { 603, "Incorrect parameter combination" },
  727.     /* SET error codes */
  728.     { 800, "Changing password failed" },
  729.     { 801, "Changing password not allowed" },
  730.     /* GET error codes */
  731.     { 900, "Unsupported item requested" },
  732.     { -1, NULL }
  733. };
  734. static int packet_display_error(struct packet *packet)
  735. {
  736.     int code;
  737.     Octstr *text = NULL;
  738.     Octstr *opname = NULL;
  739.     code = packet_get_int_parm(packet, P_ERROR_CODE);
  740.     text = packet_get_string_parm(packet, P_ERROR_TEXT);
  741.     if (code <= 0) {
  742.         octstr_destroy(text);
  743.         return 0;
  744.     }
  745.     if (text == NULL) {
  746.         /* No error text.  Try to find it in the table. */
  747.         int i;
  748.         for (i = 0; cimd2_errors[i].text != NULL; i++) {
  749.             if (cimd2_errors[i].code == code) {
  750.                 text = octstr_create(cimd2_errors[i].text);
  751.                 break;
  752.             }
  753.         }
  754.     }
  755.     if (text == NULL) {
  756.         /* Still no error text.  Make one up. */
  757.         text = octstr_create("Unknown error");
  758.     }
  759.     opname = operation_name(packet->operation);
  760.     error(0, "CIMD2 %s contained error message:",
  761.           octstr_get_cstr(opname));
  762.     error(0, "code %03d: %s", code, octstr_get_cstr(text));
  763.     octstr_destroy(opname);
  764.     octstr_destroy(text);
  765.     return code;
  766. }
  767. /* Table of special combinations, for convert_gsm_to_latin1. */
  768. /* Each cimd1, cimd2 pair is mapped to a character in the GSM default
  769.  * character set. */
  770. static const struct
  771. {
  772.     unsigned char cimd1, cimd2;
  773.     unsigned char gsm;
  774. }
  775. cimd_combinations[] = {
  776.     { 'O', 'a', 0 },     /* @ */
  777.     { 'L', '-', 1 },     /* Pounds sterling */
  778.     { 'Y', '-', 3 },     /* Yen */
  779.     { 'e', '`', 4 },     /* egrave */
  780.     { 'e', ''', 5 },    /* eacute */
  781.     { 'u', '`', 6 },     /* ugrave */
  782.     { 'i', '`', 7 },     /* igrave */
  783.     { 'o', '`', 8 },     /* ograve */
  784.     { 'C', ',', 9 },     /* C cedilla */
  785.     { 'O', '/', 11 },    /* Oslash */
  786.     { 'o', '/', 12 },    /* oslash */
  787.     { 'A', '*', 14 },    /* Aring */
  788.     { 'a', '*', 15 },    /* aring */
  789.     { 'g', 'd', 16 },    /* greek delta */
  790.     { '-', '-', 17 },    /* underscore */
  791.     { 'g', 'f', 18 },    /* greek phi */
  792.     { 'g', 'g', 19 },    /* greek gamma */
  793.     { 'g', 'l', 20 },    /* greek lambda */
  794.     { 'g', 'o', 21 },    /* greek omega */
  795.     { 'g', 'p', 22 },    /* greek pi */
  796.     { 'g', 'i', 23 },    /* greek psi */
  797.     { 'g', 's', 24 },    /* greek sigma */
  798.     { 'g', 't', 25 },    /* greek theta */
  799.     { 'g', 'x', 26 },    /* greek xi */
  800.     { 'X', 'X', 27 },    /* escape */
  801.     { 'A', 'E', 28 },    /* AE ligature */
  802.     { 'a', 'e', 29 },    /* ae ligature */
  803.     { 's', 's', 30 },    /* german double s */
  804.     { 'E', ''', 31 },   /* Eacute */
  805.     { 'q', 'q', '"' },
  806.     { 'o', 'x', 36 },    /* international currency symbol */
  807.     { '!', '!', 64 },    /* inverted ! */
  808.     { 'A', '"', 91 },    /* Adieresis */
  809.     { 'O', '"', 92 },    /* Odieresis */
  810.     { 'N', '~', 93 },    /* N tilde */
  811.     { 'U', '"', 94 },    /* Udieresis */
  812.     { 's', 'o', 95 },    /* section mark */
  813.     { '?', '?', 96 },    /* inverted ? */
  814.     { 'a', '"', 123 },   /* adieresis */
  815.     { 'o', '"', 124 },   /* odieresis */
  816.     { 'n', '~', 125 },   /* n tilde */
  817.     { 'u', '"', 126 },   /* udieresis */
  818.     { 'a', '`', 127 },   /* agrave */
  819.     { 0, 0, 0 }
  820. };
  821. /* Convert text in the CIMD2 User Data format to the GSM default
  822.  * character set.
  823.  * CIMD2 allows 8-bit characters in this format; they map directly
  824.  * to the corresponding ISO-8859-1 characters.  Since we are heading
  825.  * toward that character set in the end, we don't bother converting
  826.  * those to GSM. */
  827. static void convert_cimd2_to_gsm(Octstr *text)
  828. {
  829.     long pos, len;
  830.     int cimd1, cimd2;
  831.     int c;
  832.     int i;
  833.     /* CIMD2 uses four single-character mappings that do not map
  834.      * to themselves:
  835.      * '@' from 64 to 0, '$' from 36 to 2, ']' from 93 to 14 (A-ring),
  836.      * and '}' from 125 to 15 (a-ring).
  837.      * Other than those, we only have to worry about the escape
  838.      * sequences introduced by _ (underscore).
  839.      */
  840.     len = octstr_len(text);
  841.     for (pos = 0; pos < len; pos++) {
  842.         c = octstr_get_char(text, pos);
  843.         if (c == '@')
  844.             octstr_set_char(text, pos, 0);
  845.         else if (c == '$')
  846.             octstr_set_char(text, pos, 2);
  847.         else if (c == ']')
  848.             octstr_set_char(text, pos, 14);
  849.         else if (c == '}')
  850.             octstr_set_char(text, pos, 15);
  851.         else if (c == '_' && pos + 2 < len) {
  852.             cimd1 = octstr_get_char(text, pos + 1);
  853.             cimd2 = octstr_get_char(text, pos + 2);
  854.             for (i = 0; cimd_combinations[i].cimd1 != 0; i++) {
  855.                 if (cimd_combinations[i].cimd1 == cimd1 &&
  856.                     cimd_combinations[i].cimd2 == cimd2)
  857.                     break;
  858.             }
  859.             if (cimd_combinations[i].cimd1 == 0)
  860.                 warning(0, "CIMD2: Encountered unknown "
  861.                         "escape code _%c%c, ignoring.",
  862.                         cimd1, cimd2);
  863.             else {
  864.                 octstr_delete(text, pos, 2);
  865.                 octstr_set_char(text, pos, cimd_combinations[i].gsm);
  866.                 len = octstr_len(text);
  867.             }
  868.         }
  869.     }
  870. }
  871. /* Convert text in the GSM default character set to the CIMD2 User Data
  872.  * format, which is a representation of the GSM default character set
  873.  * in the lower 7 bits of ISO-8859-1.  (8-bit characters are also
  874.  * allowed, but it's just as easy not to use them.) */
  875. static void convert_gsm_to_cimd2(Octstr *text)
  876. {
  877.     long pos, len;
  878.     len = octstr_len(text);
  879.     for (pos = 0; pos < len; pos++) {
  880.         int c, i;
  881.         c = octstr_get_char(text, pos);
  882.         /* If c is not in the GSM alphabet at this point,
  883.          * the caller did something badly wrong. */
  884.         gw_assert(c >= 0);
  885.         gw_assert(c < 128);
  886.         for (i = 0; cimd_combinations[i].cimd1 != 0; i++) {
  887.             if (cimd_combinations[i].gsm == c)
  888.                 break;
  889.         }
  890.         if (cimd_combinations[i].gsm == c) {
  891.             /* Escape sequence */
  892.             octstr_insert_data(text, pos, "_ ", 2);
  893.             pos += 2;
  894.             len += 2;
  895.             octstr_set_char(text, pos - 1, cimd_combinations[i].cimd1);
  896.             octstr_set_char(text, pos, cimd_combinations[i].cimd2);
  897.         } else if (c == 2) {
  898.             /* The dollar sign is the only GSM character that
  899.               * does not have a CIMD escape sequence and does not
  900.              * map to itself. */
  901.             octstr_set_char(text, pos, '$');
  902.         }
  903.     }
  904. }
  905. /***************************************************************************/
  906. /* Packet encoding functions.  They do not allow the creation of invalid   */
  907. /* CIMD 2 packets.                                                         */
  908. /***************************************************************************/
  909. /* Build a new packet struct with this operation code and sequence number. */
  910. static struct packet *packet_create(int operation, int seq)
  911. {
  912.     struct packet *packet;
  913.     unsigned char minpacket[sizeof("sOO:SSSte")];
  914.     packet = gw_malloc(sizeof(*packet));
  915.     packet->operation = operation;
  916.     packet->seq = seq;
  917.     sprintf(minpacket, STX_str "%02d:%03d" TAB_str ETX_str, operation, seq);
  918.     packet->data = octstr_create(minpacket);
  919.     return packet;
  920. }
  921. /* Add a parameter to the end of packet */
  922. static void packet_add_parm(struct packet *packet, int parmtype,
  923.                             int parmno, Octstr *value)
  924. {
  925.     unsigned char parmh[sizeof("tPPP:")];
  926.     long position;
  927.     long len;
  928.     int copied = 0;
  929.     len = octstr_len(value);
  930.     gw_assert(packet != NULL);
  931.     gw_assert(parm_type(parmno) == parmtype);
  932.     if (len > parm_maxlen(parmno)) {
  933.         warning(0, "CIMD2: %s parameter too long, truncating from "
  934.                 "%ld to %ld characters", parm_name(parmno),
  935.                 len, (long) parm_maxlen(parmno));
  936.         value = octstr_copy(value, 0, parm_maxlen(parmno));
  937.         copied = 1;
  938.     }
  939.     /* There's a TAB and ETX at the end; insert it before those.
  940.      * The new parameter will come with a new starting TAB. */
  941.     position = octstr_len(packet->data) - 2;
  942.     sprintf(parmh, TAB_str "%03d:", parmno);
  943.     octstr_insert_data(packet->data, position, parmh, strlen(parmh));
  944.     octstr_insert(packet->data, value, position + strlen(parmh));
  945.     if (copied)
  946.         octstr_destroy(value);
  947. }
  948. /* Add a String parameter to the packet */
  949. static void packet_add_string_parm(struct packet *packet, int parmno, Octstr *value)
  950. {
  951.     packet_add_parm(packet, P_STRING, parmno, value);
  952. }
  953. /* Add an Address parameter to the packet */
  954. static void packet_add_address_parm(struct packet *packet, int parmno, Octstr *value)
  955. {
  956.     gw_assert(octstr_check_range(value, 0, octstr_len(value), isphonedigit));
  957.     packet_add_parm(packet, P_ADDRESS, parmno, value);
  958. }
  959. /* Add an SMS parameter to the packet.  The caller is expected to have done
  960.  * the translation to the GSM character set already.  */
  961. static void packet_add_sms_parm(struct packet *packet, int parmno, Octstr *value)
  962. {
  963.     packet_add_parm(packet, P_SMS, parmno, value);
  964. }
  965. /* There is no function for adding a Time parameter to the packet, because
  966.  * the format makes Time parameters useless for us.  If you find that you
  967.  * need to use them, then also add code for querying the SMS center timestamp
  968.  * and using that for synchronization.  And beware of DST changes. */
  969. /* Add a Hexadecimal parameter to the packet */
  970. static void packet_add_hex_parm(struct packet *packet, int parmno, Octstr *value)
  971. {
  972.     value = octstr_duplicate(value);
  973.     octstr_binary_to_hex(value, 1);   /* 1 for uppercase hex, i.e. A .. F */
  974.     packet_add_parm(packet, P_HEX, parmno, value);
  975.     octstr_destroy(value);
  976. }
  977. /* Add an Integer parameter to the packet */
  978. static void packet_add_int_parm(struct packet *packet, int parmno, long value)
  979. {
  980.     unsigned char buf[128];
  981.     Octstr *valuestr;
  982.     gw_assert(parm_in_range(parmno, value));
  983.     sprintf(buf, "%ld", value);
  984.     valuestr = octstr_create(buf);
  985.     packet_add_parm(packet, P_INT, parmno, valuestr);
  986.     octstr_destroy(valuestr);
  987. }
  988. static void packet_set_checksum(struct packet *packet)
  989. {
  990.     Octstr *data;
  991.     int checksum;
  992.     long pos, len;
  993.     unsigned char buf[16];
  994.     gw_assert(packet != NULL);
  995.     data = packet->data;
  996.     if (octstr_get_char(data, octstr_len(data) - 2) != TAB) {
  997.         /* Packet already has checksum; kill it. */
  998.         octstr_delete(data, octstr_len(data) - 3, 2);
  999.     }
  1000.     gw_assert(octstr_get_char(data, octstr_len(data) - 2) == TAB);
  1001.     /* Sum all the way up to the last TAB */
  1002.     checksum = 0;
  1003.     for (pos = 0, len = octstr_len(data); pos < len - 1; pos++) {
  1004.         checksum += octstr_get_char(data, pos);
  1005.         checksum &= 0xff;
  1006.     }
  1007.     sprintf(buf, "%02X", checksum);
  1008.     octstr_insert_data(data, len - 1, buf, 2);
  1009. }
  1010. static void packet_set_sequence(struct packet *packet, int seq)
  1011. {
  1012.     unsigned char buf[16];
  1013.     gw_assert(packet != NULL);
  1014.     gw_assert(seq >= 0);
  1015.     gw_assert(seq < 256);
  1016.     sprintf(buf, "%03d", seq);
  1017.     /* Start at 4 to skip the <STX> ZZ: part of the header. */
  1018.     octstr_set_char(packet->data, 4, buf[0]);
  1019.     octstr_set_char(packet->data, 5, buf[1]);
  1020.     octstr_set_char(packet->data, 6, buf[2]);
  1021.     packet->seq = seq;
  1022. }
  1023. static struct packet *packet_encode_message(Msg *msg, Octstr *sender_prefix)
  1024. {
  1025.     struct packet *packet;
  1026.     Octstr *text;
  1027.     int spaceleft;
  1028.     long truncated;
  1029.     int dcs = 0;
  1030.     gw_assert(msg != NULL);
  1031.     gw_assert(msg->type == sms);
  1032.     gw_assert(msg->sms.receiver != NULL);
  1033.     dcs = fields_to_dcs(msg, 0);
  1034.     if (msg->sms.sender == NULL)
  1035.         msg->sms.sender = octstr_create("");
  1036.     if (!parm_valid_address(msg->sms.receiver)) {
  1037.         warning(0, "cimd2_submit_msg: non-digits in "
  1038.                 "destination phone number '%s', discarded",
  1039.                 octstr_get_cstr(msg->sms.receiver));
  1040.         return NULL;
  1041.     }
  1042.     if (!parm_valid_address(msg->sms.sender)) {
  1043.         warning(0, "cimd2_submit_msg: non-digits in "
  1044.                 "originating phone number '%s', discarded",
  1045.                 octstr_get_cstr(msg->sms.sender));
  1046.         return NULL;
  1047.     }
  1048.     packet = packet_create(SUBMIT_MESSAGE, BOGUS_SEQUENCE);
  1049.     packet_add_address_parm(packet, P_DESTINATION_ADDRESS, msg->sms.receiver);
  1050.     /* CIMD2 interprets the originating address as a sub-address to
  1051.      * our connection number (so if the connection is "400" and we
  1052.      * fill in "600" as the sender number, the user sees "400600").
  1053.      * Since we have no way to ask what this number is, it has to
  1054.      * be configured. */
  1055.     if (octstr_len(sender_prefix) == 0) { /* Speed up the default case */
  1056.         packet_add_address_parm(packet, P_ORIGINATING_ADDRESS,
  1057.                                 msg->sms.sender);
  1058.     } else if (octstr_compare(sender_prefix, octstr_imm("never")) != 0) {
  1059.         if (octstr_ncompare(sender_prefix, msg->sms.sender,
  1060.                             octstr_len(sender_prefix)) == 0) {
  1061.             Octstr *sender;
  1062.             sender = octstr_copy(msg->sms.sender,
  1063.                 octstr_len(sender_prefix), octstr_len(msg->sms.sender));
  1064.             packet_add_address_parm(packet, P_ORIGINATING_ADDRESS, sender);
  1065.             octstr_destroy(sender);
  1066.         } else {
  1067.             warning(0, "CIMD2: Sending message with originating address <%s>, "
  1068.                        "which does not start with the sender-prefix.",
  1069.                     octstr_get_cstr(msg->sms.sender));
  1070.         }
  1071.     }
  1072.     /* Explicitly ask not to get status reports.
  1073.      * If we do not do this, the server's default might be to
  1074.      * send status reports in some cases, and we don't do anything
  1075.      * with those reports anyway. */
  1076.     /* ask for the delivery reports if needed*/
  1077.     if (msg->sms.dlr_mask & 0x03)
  1078.     {
  1079. packet_add_int_parm(packet, P_STATUS_REPORT_REQUEST, 14);
  1080.     }
  1081.     else
  1082. packet_add_int_parm(packet, P_STATUS_REPORT_REQUEST, 0);
  1083.     truncated = 0;
  1084.     spaceleft = 140;
  1085.     if (octstr_len(msg->sms.udhdata)) {
  1086.         /* udhdata will be truncated and warned about if
  1087.          * it does not fit. */
  1088.         packet_add_hex_parm(packet, P_USER_DATA_HEADER, msg->sms.udhdata);
  1089.         spaceleft -= octstr_len(msg->sms.udhdata);
  1090.     }
  1091.     if (msg->sms.coding == DC_7BIT)
  1092.         spaceleft = spaceleft * 8 / 7;
  1093.     if (spaceleft < 0)
  1094.         spaceleft = 0;
  1095.     text = octstr_duplicate(msg->sms.msgdata);
  1096.     if (octstr_len(text) > 0 && spaceleft == 0) {
  1097.         warning(0, "CIMD2: message filled up with "
  1098.                 "UDH, no room for message text");
  1099.     } else if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
  1100.         if (octstr_len(text) > spaceleft) {
  1101.             truncated = octstr_len(text) - spaceleft;
  1102.             octstr_truncate(text, spaceleft);
  1103.         }
  1104.         packet_add_hex_parm(packet, P_USER_DATA_BINARY, text);
  1105.     } else {
  1106. #if CIMD2_TRACE
  1107.         debug("bb.sms.cimd2", 0, "CIMD2 sending message.  Text:");
  1108.         octstr_dump(text, 0);
  1109. #endif
  1110.         /* Going from latin1 to GSM to CIMD2 may seem like a
  1111.          * detour, but it's the only way to get all the escape
  1112.          * codes right. */
  1113.         charset_latin1_to_gsm(text);
  1114.         truncated = charset_gsm_truncate(text, spaceleft);
  1115.         convert_gsm_to_cimd2(text);
  1116. #if CIMD2_TRACE
  1117.         debug("bb.sms.cimd2", 0, "After CIMD2 encoding:");
  1118.         octstr_dump(text, 0);
  1119. #endif
  1120.         packet_add_sms_parm(packet, P_USER_DATA, text);
  1121.     }
  1122.     if (dcs != 0)
  1123.         packet_add_int_parm(packet, P_DATA_CODING_SCHEME, dcs);
  1124.     if (truncated > 0) {
  1125.         warning(0, "CIMD2: truncating message text to fit "
  1126.                 "in %d characters.", spaceleft);
  1127.     }
  1128.     octstr_destroy(text);
  1129.     return packet;
  1130. }
  1131. /***************************************************************************/
  1132. /* Protocol functions.  These implement various transactions.              */
  1133. /***************************************************************************/
  1134. /* Give this packet a proper sequence number for sending. */
  1135. static void packet_set_send_sequence(struct packet *packet, SMSCenter *smsc)
  1136. {
  1137.     gw_assert(smsc != NULL);
  1138.     /* Send sequence numbers are always odd, receiving are always even */
  1139.     gw_assert(smsc->cimd2_send_seq % 2 == 1);
  1140.     packet_set_sequence(packet, smsc->cimd2_send_seq);
  1141.     smsc->cimd2_send_seq += 2;
  1142.     if (smsc->cimd2_send_seq > 256)
  1143.         smsc->cimd2_send_seq = 1;
  1144. }
  1145. static struct packet *cimd2_get_packet(SMSCenter *smsc, Octstr **ts)
  1146. {
  1147.     struct packet *packet = NULL;
  1148.     gw_assert(smsc != NULL);
  1149.     /* If packet is already available, don't try to read anything */
  1150.     packet = packet_extract(smsc->cimd2_inbuffer);
  1151.     while (packet == NULL) {
  1152.         if (read_available(smsc->socket, RESPONSE_TIMEOUT) != 1) {
  1153.             warning(0, "CIMD2 SMSCenter is not responding");
  1154.             return NULL;
  1155.         }
  1156.         if (octstr_append_from_socket(smsc->cimd2_inbuffer, smsc->socket) <= 0) {
  1157.             error(0, "cimd2_get_packet: read failed");
  1158.             return NULL;
  1159.         }
  1160.         packet = packet_extract(smsc->cimd2_inbuffer);
  1161.     }
  1162.     packet_check(packet);
  1163.     packet_check_can_receive(packet);
  1164. if(ts)
  1165.     *ts = packet_get_parm(packet,P_MC_TIMESTAMP);
  1166.     if (smsc->keepalive > 0)
  1167.         smsc->cimd2_next_ping = time(NULL) + 60 * smsc->keepalive;
  1168.     return packet;
  1169. }
  1170. /* Acknowledge a request.  The CIMD 2 spec only defines positive responses
  1171.  * to the server, because the server is perfect. */
  1172. static void cimd2_send_response(struct packet *request, SMSCenter *smsc)
  1173. {
  1174.     struct packet *response;
  1175.     gw_assert(request != NULL);
  1176.     gw_assert(request->operation < RESPONSE);
  1177.     response = packet_create(request->operation + RESPONSE, request->seq);
  1178.     packet_set_checksum(response);
  1179.     /* Don't check errors here because if there is something
  1180.      * wrong with the socket, the main loop will detect it. */
  1181.     octstr_write_to_socket(smsc->socket, response->data);
  1182.     packet_destroy(response);
  1183. }
  1184. static Msg *cimd2_accept_message(struct packet *request)
  1185. {
  1186.     Msg *message = NULL;
  1187.     Octstr *destination = NULL;
  1188.     Octstr *origin = NULL;
  1189.     Octstr *UDH = NULL;
  1190.     Octstr *text = NULL;
  1191.     int DCS;
  1192.     /* See GSM 03.38.  The bit patterns we can handle are:
  1193.      *   000xyyxx  Uncompressed text, yy indicates alphabet.
  1194.             *                   yy = 00, default alphabet
  1195.      *                   yy = 01, 8-bit data
  1196.      *                   yy = 10, UCS2 (can't handle yet)
  1197.      *                   yy = 11, reserved
  1198.      *   1111xyxx  Data, y indicates alphabet.
  1199.      *                   y = 0, default alphabet
  1200.      *                   y = 1, 8-bit data
  1201.      */
  1202.     DCS = packet_get_int_parm(request, P_DATA_CODING_SCHEME);
  1203.     destination = packet_get_address_parm(request, P_DESTINATION_ADDRESS);
  1204.     origin = packet_get_address_parm(request, P_ORIGINATING_ADDRESS);
  1205.     UDH = packet_get_hex_parm(request, P_USER_DATA_HEADER);
  1206.     /* Text is either in User Data or User Data Binary field. */
  1207.     text = packet_get_sms_parm(request, P_USER_DATA);
  1208.     if (text != NULL) {
  1209. #if CIMD2_TRACE
  1210.         debug("bb.sms.cimd2", 0, "CIMD2 received message.  Text:");
  1211.         octstr_dump(text, 0);
  1212. #endif
  1213.         convert_cimd2_to_gsm(text);
  1214.         charset_gsm_to_latin1(text);
  1215. #if CIMD2_TRACE
  1216.         debug("bb.sms.cimd", 0, "Text in latin1:");
  1217.         octstr_dump(text, 0);
  1218. #endif
  1219.     } else {
  1220.         text = packet_get_hex_parm(request, P_USER_DATA_BINARY);
  1221. #if CIMD2_TRACE
  1222.         debug("bb.sms.cimd2", 0, "CIMD2 received message.  Text:");
  1223.         octstr_dump(text, 0);
  1224. #endif
  1225.     }
  1226.     /* Code elsewhere in the gateway always expects the sender and
  1227.      * receiver fields to be filled, so we discard messages that
  1228.       * lack them.  If they should not be discarded, then the code
  1229.      * handling sms messages should be reviewed.  -- RB */
  1230.     if (!destination || octstr_len(destination) == 0) {
  1231.         info(0, "CIMD2: Got SMS without receiver, discarding.");
  1232.         goto error;
  1233.     }
  1234.     if (!origin || octstr_len(origin) == 0) {
  1235.         info(0, "CIMD2: Got SMS without sender, discarding.");
  1236.         goto error;
  1237.     }
  1238.     if ((!text || octstr_len(text) == 0) && (!UDH || octstr_len(UDH) == 0)) {
  1239.         info(0, "CIMD2: Got empty SMS, ignoring.");
  1240.         goto error;
  1241.     }
  1242.     message = msg_create(sms);
  1243.     if (! dcs_to_fields(&message, DCS)) {
  1244. /* XXX Should reject this message ? */
  1245. debug("CIMD2", 0, "Invalid DCS");
  1246. dcs_to_fields(&message, 0);
  1247.     }
  1248.     message->sms.sender = origin;
  1249.     message->sms.receiver = destination;
  1250.     if (UDH) {
  1251.         message->sms.udhdata = UDH;
  1252.     }
  1253.     message->sms.msgdata = text;
  1254.     return message;
  1255. error:
  1256.     msg_destroy(message);
  1257.     octstr_destroy(destination);
  1258.     octstr_destroy(origin);
  1259.     octstr_destroy(UDH);
  1260.     octstr_destroy(text);
  1261.     return NULL;
  1262. }
  1263. /* Deal with a request from the CIMD2 server, and acknowledge it. */
  1264. static void cimd2_handle_request(struct packet *request, SMSCenter *smsc)
  1265. {
  1266.     Msg *message = NULL;
  1267.     /* TODO: Check if the sequence number of this request is what we
  1268.      * expected. */
  1269.     if (request->operation == DELIVER_STATUS_REPORT) {
  1270.         message = cimd2_accept_delivery_report_message(request,smsc);
  1271.         if (message)
  1272.             list_append(smsc->cimd2_received, message);
  1273.      }
  1274.      else if (request->operation == DELIVER_MESSAGE) {
  1275.          message = cimd2_accept_message(request);
  1276.          if (message)
  1277.              list_append(smsc->cimd2_received, message);
  1278.     }
  1279.     cimd2_send_response(request, smsc);
  1280. }
  1281. /* Send a request and wait for the ack.  If the other side responds with
  1282.  * an error code, attempt to correct and retry. 
  1283.  * If other packets arrive while we wait for the ack, handle them.
  1284.  *
  1285.  * Return -1 if the SMSC refused the request.  Return -2 for other
  1286.  * errors, such as being unable to send the request at all.  If the
  1287.  * function returns -2, the caller would do well to try to reopen the
  1288.  * connection.
  1289.  *
  1290.  * The SMSCenter must be already open.
  1291.  *
  1292.  * TODO: This function has grown large and complex.  Break it up
  1293.  * into smaller pieces.
  1294.  */
  1295. static int cimd2_request(struct packet *request, SMSCenter *smsc, Octstr **ts)
  1296. {
  1297.     int ret;
  1298.     struct packet *reply = NULL;
  1299.     int errorcode;
  1300.     int tries = 0;
  1301.     gw_assert(smsc != NULL);
  1302.     gw_assert(request != NULL);
  1303.     gw_assert(operation_can_send(request->operation));
  1304.     if (smsc->socket < 0) {
  1305.         warning(0, "cimd2_request: socket not open.");
  1306.         goto io_error;
  1307.     }
  1308. retransmit:
  1309.     packet_set_send_sequence(request, smsc);
  1310.     packet_set_checksum(request);
  1311.     ret = octstr_write_to_socket(smsc->socket, request->data);
  1312.     if (ret < 0)
  1313.         goto io_error;
  1314. next_reply:
  1315.     /*reply = cimd2_get_packet(smsc,ts);*/
  1316.     reply = cimd2_get_packet(smsc, NULL);
  1317.     if (!reply)
  1318.         goto io_error;
  1319.     errorcode = packet_display_error(reply);
  1320.     if (reply->operation == NACK) {
  1321.         warning(0, "CIMD2 received NACK");
  1322.         octstr_dump(reply->data, 0);
  1323.         /* Correct sequence number if server says it was wrong,
  1324.          * but only if server's number is sane. */
  1325.         if (reply->seq != request->seq && (reply->seq % 1) == 1) {
  1326.             warning(0, "correcting sequence number from %ld to %ld.",
  1327.                     (long) smsc->cimd2_send_seq, (long) reply->seq);
  1328.             smsc->cimd2_send_seq = reply->seq;
  1329.         }
  1330.         goto retry;
  1331.     }
  1332.     if (reply->operation == GENERAL_ERROR_RESPONSE) {
  1333.         error(0, "CIMD2 received general error response");
  1334.         goto io_error;
  1335.     }
  1336.     /* The server sent us a request.  Handle it, then wait for
  1337.      * a new reply. */
  1338.     if (reply->operation < RESPONSE) {
  1339.         cimd2_handle_request(reply, smsc);
  1340.         packet_destroy(reply);
  1341.         goto next_reply;
  1342.     }
  1343.     if (reply->seq != request->seq) {
  1344.         /* We got a response to a different request number than
  1345.          * what we send.  Strange. */
  1346.         warning(0, "CIMD2: response had unexpected sequence number; ignoring.n");
  1347.         goto next_reply;
  1348.     }
  1349.     if (reply->operation != request->operation + RESPONSE) {
  1350.         /* We got a response that didn't match our request */
  1351.         Octstr *request_name = operation_name(request->operation);
  1352.         Octstr *reply_name = operation_name(reply->operation);
  1353.         warning(0, "CIMD2: %s request got a %s",
  1354.                 octstr_get_cstr(request_name),
  1355.                 octstr_get_cstr(reply_name));
  1356.         octstr_destroy(request_name);
  1357.         octstr_destroy(reply_name);
  1358.         octstr_dump(reply->data, 0);
  1359.         goto retry;
  1360.     }
  1361.     if (errorcode > 0)
  1362.         goto error;
  1363.     /* The reply passed all the checks... looks like the SMSC accepted
  1364.      * our request! */
  1365.     packet_destroy(reply);
  1366.     return 0;
  1367. io_error:
  1368.     packet_destroy(reply);
  1369.     return -2;
  1370. error:
  1371.     packet_destroy(reply);
  1372.     return -1;
  1373. retry:
  1374.     if (++tries < 3) {
  1375.         warning(0, "Retransmitting (take %d)", tries);
  1376.         goto retransmit;
  1377.     }
  1378.     warning(0, "Giving up.");
  1379.     goto io_error;
  1380. }
  1381. /* Close the SMSC socket without fanfare. */
  1382. static void cimd2_close_socket(SMSCenter *smsc)
  1383. {
  1384.     gw_assert(smsc != NULL);
  1385.     if (smsc->socket < 0)
  1386.         return;
  1387.     if (close(smsc->socket) < 0)
  1388.         warning(errno, "error closing CIMD2 socket");
  1389.     smsc->socket = -1;
  1390. }
  1391. /* Open a socket to the SMSC, send a login packet, and wait for ack.
  1392.  * This may block.  Return 0 for success, or -1 for failure. */
  1393. /* Make sure the socket is closed before calling this function, otherwise
  1394.  * we will leak fd's. */
  1395. static int cimd2_login(SMSCenter *smsc)
  1396. {
  1397.     int ret;
  1398.     struct packet *packet = NULL;
  1399.     gw_assert(smsc != NULL);
  1400.     if (smsc->socket >= 0) {
  1401.         warning(0, "cimd2_login: socket was already open; closing");
  1402.         cimd2_close_socket(smsc);
  1403.     }
  1404.     smsc->socket = tcpip_connect_to_server(octstr_get_cstr(smsc->cimd2_hostname), 
  1405.     smsc->cimd2_port, NULL);
  1406.     /* XXX add interface_name if required */
  1407.     if (smsc->socket == -1)
  1408.         goto error;
  1409.     packet = packet_create(LOGIN, BOGUS_SEQUENCE);
  1410.     packet_add_string_parm(packet, P_USER_IDENTITY, smsc->cimd2_username);
  1411.     packet_add_string_parm(packet, P_PASSWORD, smsc->cimd2_password);
  1412.     ret = cimd2_request(packet, smsc, NULL);
  1413.     if (ret < 0)
  1414.         goto error;
  1415.     packet_destroy(packet);
  1416.     info(0, "%s logged in.", smsc_name(smsc));
  1417.     return 0;
  1418. error:
  1419.     error(0, "cimd2_login failed");
  1420.     cimd2_close_socket(smsc);
  1421.     packet_destroy(packet);
  1422.     return -1;
  1423. }
  1424. static void cimd2_logout(SMSCenter *smsc)
  1425. {
  1426.     struct packet *packet = NULL;
  1427.     gw_assert(smsc != NULL);
  1428.     packet = packet_create(LOGOUT, BOGUS_SEQUENCE);
  1429.     /* TODO: Don't wait very long for a response in this case. */
  1430.     cimd2_request(packet, smsc,NULL);
  1431.     packet_destroy(packet);
  1432. }
  1433. static int cimd2_send_alive(SMSCenter *smsc)
  1434. {
  1435.     struct packet *packet = NULL;
  1436.     int ret;
  1437.     gw_assert(smsc != NULL);
  1438.     packet = packet_create(ALIVE, BOGUS_SEQUENCE);
  1439.     ret = cimd2_request(packet, smsc,NULL);
  1440.     packet_destroy(packet);
  1441.     if (ret < 0)
  1442.         warning(0, "CIMD2: SMSC not alive.n");
  1443.     return ret;
  1444. }
  1445. /***************************************************************************/
  1446. /* SMSC Interface, as defined in smsc_interface.def                        */
  1447. /***************************************************************************/
  1448. SMSCenter *cimd2_open(Octstr *hostname, int port, Octstr *username,
  1449. Octstr *password, int keepalive, Octstr *sender_prefix)
  1450. {
  1451.     SMSCenter *smsc = NULL;
  1452.     int maxlen;
  1453.     smsc = smscenter_construct();
  1454.     gw_assert(smsc != NULL);
  1455.     smsc->type = SMSC_TYPE_CIMD2;
  1456.     smsc->keepalive = keepalive;
  1457.     smsc->cimd2_hostname = octstr_duplicate(hostname);
  1458.     smsc->cimd2_port = port;
  1459.     smsc->cimd2_username = octstr_duplicate(username);
  1460.     smsc->cimd2_password = octstr_duplicate(password);
  1461.     smsc->sender_prefix = octstr_duplicate(sender_prefix);
  1462.     sprintf(smsc->name, "CIMD2:%s:%d:%s", octstr_get_cstr(hostname), port, octstr_get_cstr(username));
  1463.     smsc->cimd2_received = list_create();
  1464.     smsc->cimd2_inbuffer = octstr_create("");
  1465.     smsc->cimd2_error = 0;
  1466.     if (keepalive > 0)
  1467.         smsc->cimd2_next_ping = time(NULL) + keepalive * 60;
  1468.     maxlen = parm_maxlen(P_USER_IDENTITY);
  1469.     if (octstr_len(smsc->cimd2_username) > maxlen) {
  1470.         octstr_truncate(smsc->cimd2_username, maxlen);
  1471.         warning(0, "Truncating CIMD2 username to %d chars", maxlen);
  1472.     }
  1473.     maxlen = parm_maxlen(P_PASSWORD);
  1474.     if (octstr_len(smsc->cimd2_password) > maxlen) {
  1475.         octstr_truncate(smsc->cimd2_password, maxlen);
  1476.         warning(0, "Truncating CIMD2 password to %d chars", maxlen);
  1477.     }
  1478.     if (cimd2_login(smsc) < 0)
  1479.         goto error;
  1480.     return smsc;
  1481. error:
  1482.     error(0, "cimd2_open failed");
  1483.     smscenter_destruct(smsc);
  1484.     return NULL;
  1485. }
  1486. int cimd2_reopen(SMSCenter *smsc)
  1487. {
  1488.     gw_assert(smsc != NULL);
  1489.     warning(0, "Attempting to re-open CIMD2 connection");
  1490.     cimd2_close_socket(smsc);
  1491.     /* Restore message counters to their default values */
  1492.     smsc->cimd2_send_seq = 1;
  1493.     smsc->cimd2_receive_seq = 0;
  1494.     /* Clear leftover input */
  1495.     octstr_destroy(smsc->cimd2_inbuffer);
  1496.     smsc->cimd2_inbuffer = octstr_create("");
  1497.     return cimd2_login(smsc);
  1498. }
  1499. int cimd2_close(SMSCenter *smsc)
  1500. {
  1501.     int ret;
  1502.     int discarded;
  1503.     gw_assert(smsc != NULL);
  1504.     debug("bb.sms.cimd2", 0, "Closing CIMD2 SMSC");
  1505.     if (smsc->socket < 0) {
  1506.         warning(0, "cimd2_close: already closed.n");
  1507.         return 0;
  1508.     }
  1509.     cimd2_logout(smsc);
  1510.     ret = close(smsc->socket);
  1511.     smsc->socket = -1;
  1512.     smsc->cimd2_send_seq = 0;
  1513.     smsc->cimd2_receive_seq = 1;
  1514.     octstr_destroy(smsc->cimd2_hostname);
  1515.     octstr_destroy(smsc->cimd2_username);
  1516.     octstr_destroy(smsc->cimd2_password);
  1517.     octstr_destroy(smsc->cimd2_inbuffer);
  1518.     discarded = list_len(smsc->cimd2_received);
  1519.     list_destroy(smsc->cimd2_received, msg_destroy_item);
  1520.     if (discarded > 0)
  1521.         warning(0, "CIMD2: discarded %d received messages", discarded);
  1522.     return ret;
  1523. }
  1524. int cimd2_submit_msg(SMSCenter *smsc, Msg *msg)
  1525. {
  1526.     struct packet *packet;
  1527.     int ret = 0;
  1528.     int tries;
  1529.     Octstr *ts;
  1530.     ts = NULL;
  1531.     gw_assert(smsc != NULL);
  1532.     packet = packet_encode_message(msg, smsc->sender_prefix);
  1533.     if (!packet)
  1534.         return 0;   /* We can't signal protocol errors yet */
  1535.     for (tries = 0; tries < 3; tries++) {
  1536.         ret = cimd2_request(packet, smsc,&ts);
  1537.         if((ret == 0) && (ts) && (msg->sms.dlr_mask & 0x03))
  1538.         {
  1539.             dlr_add(smsc->name,
  1540.                 octstr_get_cstr(ts), 
  1541.                 octstr_get_cstr(msg->sms.sender),
  1542.                 octstr_get_cstr(msg->sms.receiver),
  1543.                 octstr_get_cstr(msg->sms.service),
  1544.                 octstr_get_cstr(msg->sms.dlr_url),
  1545.                 msg->sms.dlr_mask);
  1546.             octstr_destroy(ts);
  1547.             ts = NULL;
  1548. }
  1549. if (ret == 0 || ret == -1)
  1550.             break;
  1551.         if (cimd2_reopen(smsc) < 0) {
  1552.             ret = -1;
  1553.             break;
  1554.         }
  1555.     }
  1556.     packet_destroy(packet);
  1557.     return ret;
  1558. }
  1559. /* The bearerbox really doesn't like it if pending_smsmessage returns
  1560.  * an error code.  We work around it until the bearerbox is rewritten.
  1561.  * Record the error here, and return it in cimd2_receive_msg.  Return
  1562.  * "message available" if there is an error so that cimd2_receive_msg
  1563.  * is called. */
  1564. int cimd2_pending_smsmessage(SMSCenter *smsc)
  1565. {
  1566.     long ret;
  1567.     struct packet *packet;
  1568.     gw_assert(smsc != NULL);
  1569.     gw_assert(smsc->type == SMSC_TYPE_CIMD2);
  1570.     if (list_len(smsc->cimd2_received) > 0)
  1571.         return 1;
  1572.     if (smsc->socket < 0) {
  1573.         /* XXX We have to assume that smsc_send_message is
  1574.          * currently trying to reopen, so we have to make
  1575.          * this thread wait.  It should be done in a nicer
  1576.          * way. */ 
  1577.         return 0;
  1578.     }
  1579.     ret = read_available(smsc->socket, 0);
  1580.     if (ret == 0) {
  1581.         if (smsc->keepalive > 0 && smsc->cimd2_next_ping < time(NULL)) {
  1582.             if (cimd2_send_alive(smsc) < 0) {
  1583.                 smsc->cimd2_error = 1;
  1584.                 return 1;
  1585.             }
  1586.         }
  1587.         return 0;
  1588.     }
  1589.     if (ret < 0) {
  1590.         warning(errno, "cimd2_pending_smsmessage: read_available failed");
  1591.         smsc->cimd2_error = 1;
  1592.         return 1;
  1593.     }
  1594.     /* We have some data waiting... see if it is an sms delivery. */
  1595.     ret = octstr_append_from_socket(smsc->cimd2_inbuffer, smsc->socket);
  1596.     if (ret == 0) {
  1597.         warning(0, "cimd2_pending_smsmessage: service center closed connection.");
  1598.         smsc->cimd2_error = 1;
  1599.         return 1;
  1600.     }
  1601.     if (ret < 0) {
  1602.         warning(0, "cimd2_pending_smsmessage: read failed");
  1603.         smsc->cimd2_error = 1;
  1604.         return 1;
  1605.     }
  1606.     for (;;) {
  1607.         packet = packet_extract(smsc->cimd2_inbuffer);
  1608.         if (!packet)
  1609.             break;
  1610.         packet_check(packet);
  1611.         packet_check_can_receive(packet);
  1612.         if (packet->operation < RESPONSE)
  1613.             cimd2_handle_request(packet, smsc);
  1614.         else {
  1615.             error(0, "cimd2_pending_smsmessage: unexpected response packet");
  1616.             octstr_dump(packet->data, 0);
  1617.         }
  1618.         packet_destroy(packet);
  1619.     }
  1620.     if (list_len(smsc->cimd2_received) > 0)
  1621.         return 1;
  1622.     return 0;
  1623. }
  1624. int cimd2_receive_msg(SMSCenter *smsc, Msg **msg)
  1625. {
  1626.     gw_assert(smsc != NULL);
  1627.     gw_assert(msg != NULL);
  1628.     if (smsc->cimd2_error) {
  1629.         smsc->cimd2_error = 0;
  1630.         return -1;
  1631.     }
  1632.     *msg = list_consume(smsc->cimd2_received);
  1633.     return 1;
  1634. }
  1635. static Msg *cimd2_accept_delivery_report_message(struct packet *request, SMSCenter *smsc)
  1636. {
  1637.     Msg *msg = NULL;
  1638.     Octstr *destination = NULL;
  1639.     Octstr *timestamp = NULL;
  1640.     Octstr *statuscode = NULL;
  1641.     int st_code; 
  1642.     int code;
  1643.     destination = packet_get_parm(request, P_DESTINATION_ADDRESS);
  1644.     timestamp = packet_get_parm(request, P_MC_TIMESTAMP);
  1645.     statuscode = packet_get_parm(request, P_STATUS_CODE);
  1646.     st_code = atoi(octstr_get_cstr(statuscode));
  1647.     
  1648.     switch(st_code)
  1649.     {
  1650.     case 2:  /* validity period expired */
  1651.     case 3:  /* delivery failed */
  1652. code = DLR_FAIL;
  1653.      break;
  1654.     case 4: /* delivery successful */
  1655.      code = DLR_SUCCESS;
  1656.      break;
  1657.     default:
  1658.         code = 0;
  1659.     }
  1660.     if(code)
  1661.      msg = dlr_find(smsc->name,
  1662.             octstr_get_cstr(timestamp), 
  1663.             octstr_get_cstr(destination),
  1664.             code);
  1665.     else
  1666.         msg = NULL;
  1667.     octstr_destroy(statuscode);
  1668.     octstr_destroy(destination);
  1669.     octstr_destroy(timestamp);
  1670.     /* recode the body into msgdata */
  1671.     if (msg) {
  1672.         msg->sms.msgdata = packet_get_parm(request, P_USER_DATA);
  1673.     }
  1674.     return msg;
  1675.  }