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

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * emimsg.c
  3.  *
  4.  * Functions for working with EMI messages
  5.  * Uoti Urpala 2001 */
  6. #include "emimsg.h"
  7. /* Return an error string corresponding to the number. */
  8. static char *emi_strerror(int errnum)
  9. {
  10.     switch (errnum) {
  11.     case  1: return "Checksum error";
  12.     case  2: return "Syntax error";
  13.     case  3: return "Operation not supported by system";
  14.     case  4: return "Operation not allowed";
  15.     case  5: return "Call barring active";
  16.     case  6: return "AdC invalid";
  17.     case  7: return "Authentication failure";
  18.     case  8: return "Legitimisation code for all calls, failure";
  19.     case  9: return "GA not valid";
  20.     case 10: return "Repetition not allowed";
  21.     case 11: return "Legitimisation code for repetition, failure";
  22.     case 12: return "Priority call not allowed";
  23.     case 13: return "Legitimisation code for priority call, failure";
  24.     case 14: return "Urgent message not allowed";
  25.     case 15: return "Legitimisation code for urgent message, failure";
  26.     case 16: return "Reverse charging not allowed";
  27.     case 17: return "Legitimisation code for reverse charging, failure";
  28.     case 18: return "Deferred delivery not allowed";
  29.     case 19: return "New AC not valid";
  30.     case 20: return "New legitimisation code not valid";
  31.     case 21: return "Standard text not valid";
  32.     case 22: return "Time period not valid";
  33.     case 23: return "Message type not supported by system";
  34.     case 24: return "Message too long";
  35.     case 25: return "Requested standard text not valid";
  36.     case 26: return "Message type not valid for the pager type";
  37.     case 27: return "Message not found in smsc";
  38.     case 30: return "Subscriber hang-up";
  39.     case 31: return "Fax group not supported";
  40.     case 32: return "Fax message type not supported";
  41.     case 33: return "Address already in list (60 series)";
  42.     case 34: return "Address not in list (60 series)";
  43.     case 35: return "List full, cannot add address to list (60 series)";
  44.     case 36: return "RPID already in use";
  45.     case 37: return "Delivery in progress";
  46.     case 38: return "Message forwarded";
  47.     default: return "!UNRECOGNIZED ERROR CODE!";
  48.     }
  49. }
  50. static int field_count_op(int ot, Octstr *whoami)
  51. {
  52.     switch (ot) {
  53.     case 01:
  54. return SZ01;
  55.     case 31:
  56. return 2;
  57.     case 51:
  58.     case 52:
  59.     case 53:
  60. return SZ50;
  61.     case 60:
  62. return SZ60;
  63.     default:
  64. error(0, "EMI2[%s]: Unsupported EMI operation request type %d", 
  65.       octstr_get_cstr(whoami), ot);
  66. return -1;
  67.     }
  68. }
  69. static int field_count_reply(int ot, int posit, Octstr *whoami)
  70. {
  71.     switch(ot) {
  72.     case 01:
  73. return posit ? 2 : 3;
  74.     case 31:
  75. return posit ? 2 : 3;
  76.     case 51:
  77.     case 52:
  78.     case 53:
  79. return 3;
  80.     case 60:
  81. return posit ? 2 : 3;
  82.     default:
  83. error(0, "EMI2[%s]: Unsupported EMI operation reply type %d", 
  84.       octstr_get_cstr(whoami), ot);
  85. return -1;
  86.     }
  87. }
  88. static struct emimsg *emimsg_create_withlen(int len)
  89. {
  90.     struct emimsg *ret;
  91.     ret = gw_malloc(sizeof(struct emimsg));
  92.     ret->fields = gw_malloc(len * sizeof(Octstr *));
  93.     ret->num_fields = len;
  94.     while (--len >= 0)
  95. ret->fields[len] = NULL;
  96.     return ret;
  97. }
  98. struct emimsg *emimsg_create_op(int ot, int trn, Octstr *whoami)
  99. {
  100.     int len;
  101.     struct emimsg *ret;
  102.     len = field_count_op(ot, whoami);
  103.     if (len < 0)
  104. return NULL;
  105.     ret = emimsg_create_withlen(len);
  106.     ret->ot = ot;
  107.     ret->or = 'O';
  108.     ret->trn = trn;
  109.     return ret;
  110. }
  111. static struct emimsg *emimsg_create_reply_s(int ot, int trn, int positive,
  112. Octstr *whoami)
  113. {
  114.     int len;
  115.     struct emimsg *ret;
  116.     len = field_count_reply(ot, positive, whoami);
  117.     if (len < 0)
  118. return NULL;
  119.     ret = emimsg_create_withlen(len);
  120.     ret->ot = ot;
  121.     ret->or = 'R';
  122.     ret->trn = trn;
  123.     return ret;
  124. }
  125. struct emimsg *emimsg_create_reply(int ot, int trn, int positive, 
  126. Octstr *whoami)
  127. {
  128.     struct emimsg *ret;
  129.     ret = emimsg_create_reply_s(ot, trn, positive, whoami);
  130.     if (ret) {
  131. if (positive)
  132.     ret->fields[0] = octstr_create("A");
  133. else
  134.     ret->fields[0] = octstr_create("N");
  135.     }
  136.     return ret;
  137. }
  138. void emimsg_destroy(struct emimsg *emimsg)
  139. {
  140.     int len;
  141.     len = emimsg->num_fields;
  142.     while (--len >= 0)
  143. octstr_destroy(emimsg->fields[len]);  /* octstr_destroy(NULL) is ok */
  144.     gw_free(emimsg->fields);
  145.     gw_free(emimsg);
  146. }
  147. /* The argument can be either the whole message (with the stx/etx start/end
  148.    characters), or miss the last 3 characters (checksum digits and etx) */
  149. static int calculate_checksum(Octstr *message)
  150. {
  151.     int end, i, checksum;
  152.     end = octstr_len(message);
  153.     if (octstr_get_char(message, end - 1) == 3)  /* etx, whole message */
  154. end -= 3;
  155.     checksum = 0;
  156.     for (i = 1; i < end; i++)
  157. checksum += octstr_get_char(message, i);
  158.     return checksum & 0xff;
  159. }
  160. static Octstr *emimsg_tostring(struct emimsg *emimsg)
  161. {
  162.     int i, checksum;
  163.     Octstr *result, *data;
  164.     char *hexits = "0123456789ABCDEF";
  165.     data = octstr_create("");
  166.     for (i = 0; i < emimsg->num_fields; i++) {
  167. if (emimsg->fields[i])
  168.     octstr_append(data, emimsg->fields[i]);
  169. octstr_append_char(data, '/');
  170.     }
  171.     result = octstr_format("2%02d/%05d/%c/%02d/%S", emimsg->trn,
  172. octstr_len(data) + 16, emimsg->or, emimsg->ot, data);
  173.     checksum = calculate_checksum(result);
  174.     octstr_append_char(result, hexits[checksum >> 4 & 15]);
  175.     octstr_append_char(result, hexits[checksum & 15]);
  176.     octstr_append_char(result, 3);
  177.     octstr_destroy(data);
  178.     return result;
  179. }
  180. /* Doesn't check that the string is strictly according to format */
  181. struct emimsg *get_fields(Octstr *message, Octstr *whoami)
  182. {
  183.     long trn, len, ot, checksum; /* because of Octstr_parse_long... */
  184.     char or, posit;
  185.     long fieldno, pos, pos2;
  186.     struct emimsg *result = NULL;
  187.     debug("smsc.emi2", 0, "EMI2[%s]: emi2 parsing packet: <%s>",
  188.   octstr_get_cstr(whoami), octstr_get_cstr(message));
  189.     if (octstr_get_char(message, 0) != 2 ||
  190. octstr_get_char(message, octstr_len(message) - 1) != 3)
  191. goto error;
  192.     if (octstr_parse_long(&trn, message, 1, 10) != 3)
  193. goto error;
  194.     if (octstr_parse_long(&len, message, 4, 10) != 9)
  195. goto error;
  196.     if (octstr_len(message) != len + 2)     /* +2 for start/end markers */
  197. goto error;
  198.     if ( (or = octstr_get_char(message, 10)) != 'O' && or != 'R')
  199. goto error;
  200.     if (octstr_parse_long(&ot, message, 12, 10) != 14)
  201. goto error;
  202.     if (or == 'O')
  203. result = emimsg_create_op(ot, trn, whoami);
  204.     else {
  205. posit = octstr_get_char(message, 15);
  206. if (posit == 'A')
  207.     result = emimsg_create_reply_s(ot, trn, 1, whoami);
  208. else if (posit == 'N')
  209.     result = emimsg_create_reply_s(ot, trn, 0, whoami);
  210. else
  211.     goto error;
  212.     }
  213.     if (result == NULL)
  214. goto error;
  215.     pos2 = 14;
  216.     for (fieldno = 0; fieldno < result->num_fields; fieldno++) {
  217. pos = pos2 + 1;
  218. if ( (pos2 = octstr_search_char(message, '/', pos)) == -1)
  219.     goto error;
  220. if (pos2 > pos)
  221.     result->fields[fieldno] = octstr_copy(message, pos, pos2 - pos);
  222.     }
  223.     if (octstr_search_char(message, '/', pos2 + 1) != -1) {
  224. int extrafields = 0;
  225. pos = pos2;
  226. while ((pos = octstr_search_char(message, '/', pos + 1)) != -1) {
  227.     extrafields++;
  228.     pos2 = pos;
  229. }
  230. /* The extra fields are ignored */
  231. warning(0, "get_fields: EMI message of type %d/%c has %d more fields "
  232. "than expected.", result->ot, result->or, extrafields);
  233.     }
  234.     if (octstr_parse_long(&checksum, message, pos2 + 1, 16) !=
  235. octstr_len(message) - 1 || checksum != calculate_checksum(message))
  236. goto error;
  237.     if (result->or == 'R' && octstr_get_char(result->fields[0], 0) == 'N') {
  238. long errcode;
  239. if (!result->fields[1] ||
  240.     octstr_parse_long(&errcode, result->fields[1], 0, 10) != 2)
  241.     goto error;
  242. error(0, "EMI2[%s]: Got negative ack. op:%d, trn:%d, error:%ld (%s), message:%s",
  243.       octstr_get_cstr(whoami),
  244.       result->ot, result->trn, errcode, emi_strerror(errcode),
  245.       result->fields[2] ? octstr_get_cstr(result->fields[2]) : "");
  246.     }
  247.     return result;
  248. error:
  249.     error(0, "EMI2[%s]: Invalid EMI packet: %s", octstr_get_cstr(whoami),
  250.   octstr_get_cstr(message));
  251.     if (result)
  252. emimsg_destroy(result);
  253.     return NULL;
  254. }
  255. int emimsg_send(Connection *conn, struct emimsg *emimsg, Octstr *whoami)
  256. {
  257.     Octstr *string;
  258.     string = emimsg_tostring(emimsg);
  259.     if (!string) {
  260. error(0, "EMI2[%s]: emimsg_send: conversion to string failed",
  261.       octstr_get_cstr(whoami));
  262. return -1;
  263.     }
  264.     if (emimsg->ot == 60)
  265. debug("smsc.emi2", 0, "EMI2[%s]: Sending operation type 60, message with "
  266.       "password not shown in log file.", octstr_get_cstr(whoami));
  267.     else
  268. debug("smsc.emi2", 0, "EMI2[%s]: emi2 sending packet: <%s>",
  269.       octstr_get_cstr(whoami), octstr_get_cstr(string));
  270.     if (conn_write(conn, string) == -1) {
  271. octstr_destroy(string);
  272. error(0, "EMI2[%s]: emimsg_send: write failed",
  273.       octstr_get_cstr(whoami));
  274. return -1;
  275.     }
  276.     octstr_destroy(string);
  277.     return 1;
  278. }