Kannel: Open Source WAP and SMS gateway  svn-r5335
sms.c File Reference
#include "sms.h"
#include "dlr.h"

Go to the source code of this file.

Macros

#define CATENATE_UDH_LEN   5
 

Functions

int fields_to_dcs (Msg *msg, int mode)
 
int dcs_to_fields (Msg **msg, int dcs)
 
int sms_msgdata_len (Msg *msg)
 
int sms_swap (Msg *msg)
 
void prepend_catenation_udh (Msg *sms, int part_no, int num_messages, int msg_sequence)
 
static Octstrextract_msgdata_part (Octstr *msgdata, Octstr *split_chars, int max_part_len)
 
static Octstrextract_msgdata_part_by_coding (Msg *msg, Octstr *split_chars, int max_part_len)
 
Listsms_split (Msg *orig, Octstr *header, Octstr *footer, Octstr *nonlast_suffix, Octstr *split_chars, int catenate, unsigned long msg_sequence, int max_messages, int max_octets)
 
int sms_priority_compare (const void *a, const void *b)
 
int sms_charset_processing (Octstr *charset, Octstr *body, int coding)
 

Macro Definition Documentation

◆ CATENATE_UDH_LEN

#define CATENATE_UDH_LEN   5

Definition at line 221 of file sms.c.

Referenced by prepend_catenation_udh(), and sms_split().

Function Documentation

◆ dcs_to_fields()

int dcs_to_fields ( Msg **  msg,
int  dcs 
)

Definition at line 139 of file sms.c.

References DC_7BIT, DC_8BIT, DC_UCS2, and MC_UNDEF.

Referenced by at2_pdu_decode_deliver_sm(), cimd2_accept_message(), data_sm_to_msg(), handle_operation(), oisd_accept_message(), and pdu_to_msg().

140 {
141  /* Non-MWI Mode 1 */
142  if ((dcs & 0xF0) == 0xF0) {
143  dcs &= 0x07;
144  (*msg)->sms.coding = (dcs & 0x04) ? DC_8BIT : DC_7BIT; /* grab bit 2 */
145  (*msg)->sms.mclass = dcs & 0x03; /* grab bits 1,0 */
146  (*msg)->sms.alt_dcs = 1; /* set 0xFX data coding */
147  }
148 
149  /* Non-MWI Mode 0 */
150  else if ((dcs & 0xC0) == 0x00) {
151  (*msg)->sms.alt_dcs = 0;
152  (*msg)->sms.compress = ((dcs & 0x20) == 0x20) ? 1 : 0; /* grab bit 5 */
153  (*msg)->sms.mclass = ((dcs & 0x10) == 0x10) ? dcs & 0x03 : MC_UNDEF;
154  /* grab bit 0,1 if bit 4 is on */
155  (*msg)->sms.coding = (dcs & 0x0C) >> 2; /* grab bit 3,2 */
156  }
157 
158  /* MWI */
159  else if ((dcs & 0xC0) == 0xC0) {
160  (*msg)->sms.alt_dcs = 0;
161  (*msg)->sms.coding = ((dcs & 0x30) == 0x30) ? DC_UCS2 : DC_7BIT;
162  if (!(dcs & 0x08))
163  dcs |= 0x04; /* if bit 3 is active, have mwi += 4 */
164  dcs &= 0x07;
165  (*msg)->sms.mwi = dcs ; /* grab bits 1,0 */
166  }
167 
168  else {
169  return 0;
170  }
171 
172  return 1;
173 }
#define DC_8BIT
Definition: sms.h:111
#define MC_UNDEF
Definition: sms.h:93
#define DC_UCS2
Definition: sms.h:112
#define DC_7BIT
Definition: sms.h:110

◆ extract_msgdata_part()

static Octstr* extract_msgdata_part ( Octstr msgdata,
Octstr split_chars,
int  max_part_len 
)
static

Definition at line 247 of file sms.c.

References octstr_copy, octstr_delete(), octstr_get_char(), octstr_len(), and octstr_search_char().

Referenced by extract_msgdata_part_by_coding().

249 {
250  long i, len;
251  Octstr *part;
252 
253  len = max_part_len;
254  if (max_part_len < octstr_len(msgdata) && split_chars != NULL)
255  for (i = max_part_len; i > 0; i--)
256  if (octstr_search_char(split_chars,
257  octstr_get_char(msgdata, i - 1), 0) != -1) {
258  len = i;
259  break;
260  }
261  part = octstr_copy(msgdata, 0, len);
262  octstr_delete(msgdata, 0, len);
263  return part;
264 }
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1012
void octstr_delete(Octstr *ostr1, long pos, long len)
Definition: octstr.c:1527
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Definition: octstr.c:118
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:406

◆ extract_msgdata_part_by_coding()

static Octstr* extract_msgdata_part_by_coding ( Msg msg,
Octstr split_chars,
int  max_part_len 
)
static

Definition at line 267 of file sms.c.

References charset_gsm_to_utf8(), charset_gsm_truncate(), charset_utf8_to_gsm(), DC_8BIT, DC_UCS2, extract_msgdata_part(), msg, octstr_destroy(), octstr_duplicate, and octstr_len().

Referenced by sms_split().

269 {
270  Octstr *temp = NULL, *temp_utf;
271 
272  if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) {
273  /* nothing to do here, just call the original extract_msgdata_part */
274  return extract_msgdata_part(msg->sms.msgdata, split_chars, max_part_len);
275  }
276 
277  /*
278  * XXX TODO
279  * Convert to and the from gsm, so we drop all non GSM chars.
280  * This means effectively that we can NOT use any encoding specific
281  * characters in the SMSC module scope that are NOT in the GSM 03.38
282  * alphabet, i.e. UTF-8 0xC2 0xAE is latin1 0xAE and maps to an unknown
283  * character due to this round-trip transcoding.
284  */
285  charset_utf8_to_gsm(msg->sms.msgdata);
286  charset_gsm_to_utf8(msg->sms.msgdata);
287 
288  /*
289  * else we need to do something special. I'll just get charset_gsm_truncate to
290  * cut the string to the required length and then count real characters.
291  */
292  temp = octstr_duplicate(msg->sms.msgdata);
293  charset_utf8_to_gsm(temp);
294  charset_gsm_truncate(temp, max_part_len);
295 
296  /* calculate utf-8 length */
297  temp_utf = octstr_duplicate(temp);
298  charset_gsm_to_utf8(temp_utf);
299  max_part_len = octstr_len(temp_utf);
300 
301  octstr_destroy(temp);
302  octstr_destroy(temp_utf);
303 
304  /* now just call the original extract_msgdata_part with the new length */
305  return extract_msgdata_part(msg->sms.msgdata, split_chars, max_part_len);
306 }
void charset_utf8_to_gsm(Octstr *ostr)
Definition: charset.c:288
#define DC_8BIT
Definition: sms.h:111
static Octstr * extract_msgdata_part(Octstr *msgdata, Octstr *split_chars, int max_part_len)
Definition: sms.c:247
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Definition: octstr.c:118
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
int charset_gsm_truncate(Octstr *gsm, long max)
Definition: charset.c:512
#define DC_UCS2
Definition: sms.h:112
void charset_gsm_to_utf8(Octstr *ostr)
Definition: charset.c:220

◆ fields_to_dcs()

int fields_to_dcs ( Msg msg,
int  mode 
)

Definition at line 73 of file sms.c.

References COMPRESS_ON, DC_7BIT, DC_8BIT, DC_UCS2, DC_UNDEF, MC_UNDEF, msg, MWI_UNDEF, octstr_len(), and SMS_PARAM_UNDEFINED.

Referenced by at2_pdu_encode(), brunet_send_sms(), msg_to_emimsg(), msg_to_pdu(), packet_encode_message(), urltrans_fill_escape_codes(), and xidris_send_sms().

74 {
75  int dcs=0;
76 
77  /* Coding defaults to 7BIT or to 8BIT if udh is set */
78  if (msg->sms.coding == DC_UNDEF) {
79  if (octstr_len(msg->sms.udhdata))
80  msg->sms.coding = DC_8BIT;
81  else
82  msg->sms.coding = DC_7BIT;
83  }
84 
85 
86  /* MWI */
87  if (msg->sms.mwi != MWI_UNDEF) {
88  dcs = msg->sms.mwi; /* sets bits 2, 1 and 0 */
89 
90  if (dcs & 0x04)
91  dcs = (dcs & 0x03) | 0xC0; /* MWI Inactive */
92  else {
93  dcs = (dcs & 0x03) | 0x08; /* MWI Active, sets bit 3 */
94 
95  if (! octstr_len(msg->sms.msgdata))
96  dcs |= 0xC0; /* Discard */
97  else
98  if (msg->sms.coding == DC_7BIT)
99  dcs |= 0xD0; /* 7bit */
100  else
101  dcs |= 0xE0; /* UCS-2 */
102  /* XXX Shouldn't happen to have mwi and dc=DC_8BIT! */
103  }
104  }
105 
106  /* Non-MWI */
107  else {
108  /* mode 0 or mode UNDEF */
109  if (mode == 0 || mode == SMS_PARAM_UNDEFINED || msg->sms.coding == DC_UCS2
110  || msg->sms.compress == COMPRESS_ON) {
111  /* bits 7,6 are 0 */
112  if (msg->sms.compress == COMPRESS_ON)
113  dcs |= 0x20; /* sets bit 5 */
114  if (msg->sms.mclass != MC_UNDEF)
115  dcs |= (0x10 | msg->sms.mclass); /* sets bit 4,1,0 */
116  if (msg->sms.coding != DC_UNDEF)
117  dcs |= (msg->sms.coding << 2); /* sets bit 3,2 */
118  }
119 
120  /* mode 1 */
121  else {
122  dcs |= 0xF0; /* sets bits 7-3 */
123  if(msg->sms.coding != DC_UNDEF)
124  dcs |= (msg->sms.coding << 2); /* only DC_7BIT or DC_8BIT, sets bit 2*/
125  if (msg->sms.mclass == MC_UNDEF)
126  dcs |= 1; /* default meaning: ME specific */
127  else
128  dcs |= msg->sms.mclass; /* sets bit 1,0 */
129  }
130  }
131 
132  return dcs;
133 }
#define MWI_UNDEF
Definition: sms.h:99
#define DC_8BIT
Definition: sms.h:111
#define COMPRESS_ON
Definition: sms.h:116
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
#define MC_UNDEF
Definition: sms.h:93
#define DC_UNDEF
Definition: sms.h:109
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
#define DC_UCS2
Definition: sms.h:112
#define DC_7BIT
Definition: sms.h:110

◆ prepend_catenation_udh()

void prepend_catenation_udh ( Msg sms,
int  part_no,
int  num_messages,
int  msg_sequence 
)

Create multipart UDH

Definition at line 224 of file sms.c.

References CATENATE_UDH_LEN, num_messages, octstr_append_char(), octstr_create, octstr_format_append(), octstr_len(), and octstr_set_char().

Referenced by data_sm_to_msg(), pdu_to_msg(), and sms_split().

226 {
227  if (sms->sms.udhdata == NULL)
228  sms->sms.udhdata = octstr_create("");
229  if (octstr_len(sms->sms.udhdata) == 0)
230  octstr_append_char(sms->sms.udhdata, CATENATE_UDH_LEN);
231  octstr_format_append(sms->sms.udhdata, "%c\3%c%c%c",
232  0, msg_sequence, num_messages, part_no);
233 
234  /* Set the number of messages left, if any */
235  if (part_no < num_messages)
236  sms->sms.msg_left = num_messages - part_no;
237  else
238  sms->sms.msg_left = 0;
239  /*
240  * Now that we added the concatenation information the
241  * length is all wrong. we need to recalculate it.
242  */
243  octstr_set_char(sms->sms.udhdata, 0, octstr_len(sms->sms.udhdata) - 1 );
244 }
static long num_messages
Definition: test_smsc.c:90
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1517
#define octstr_create(cstr)
Definition: octstr.h:125
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
#define CATENATE_UDH_LEN
Definition: sms.c:221
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2507
void octstr_set_char(Octstr *ostr, long pos, int ch)
Definition: octstr.c:415

◆ sms_charset_processing()

int sms_charset_processing ( Octstr charset,
Octstr body,
int  coding 
)

Definition at line 419 of file sms.c.

References charset, charset_convert(), coding, DC_7BIT, DC_UCS2, error(), octstr_get_cstr, and octstr_len().

Referenced by generic_receive_sms(), kannel_receive_sms(), smsbox_req_handle(), and url_result_thread().

420 {
421  int resultcode = 0;
422 
423  /*
424  debug("gw.sms", 0, "%s: enter, charset=%s, coding=%d, msgdata is:",
425  __func__, octstr_get_cstr(charset), coding);
426  octstr_dump(body, 0);
427  */
428 
429  if (octstr_len(charset)) {
430  if (coding == DC_7BIT) {
431  /*
432  * For 7 bit, convert to UTF-8
433  */
434  if (charset_convert(body, octstr_get_cstr(charset), "UTF-8") < 0) {
435  error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave as is.",
436  octstr_get_cstr(charset), "UTF-8");
437  resultcode = -1;
438  }
439  } else if (coding == DC_UCS2) {
440  /*
441  * For UCS-2, convert to UTF-16BE
442  */
443  if (charset_convert(body, octstr_get_cstr(charset), "UTF-16BE") < 0) {
444  error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave as is.",
445  octstr_get_cstr(charset), "UTF-16BE");
446  resultcode = -1;
447  }
448  }
449  }
450 
451  /*
452  debug("gw.sms", 0, "%s: exit, charset=%s, coding=%d, msgdata is:",
453  __func__, octstr_get_cstr(charset), coding);
454  octstr_dump(body, 0);
455  */
456 
457  return resultcode;
458 }
void error(int err, const char *fmt,...)
Definition: log.c:648
static int coding
Definition: mtbatch.c:102
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * charset
Definition: test_ota.c:68
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
#define DC_UCS2
Definition: sms.h:112
int charset_convert(Octstr *string, char *charset_from, char *charset_to)
Definition: charset.c:589
#define DC_7BIT
Definition: sms.h:110

◆ sms_msgdata_len()

int sms_msgdata_len ( Msg msg)

Definition at line 180 of file sms.c.

References charset_utf8_to_gsm(), DC_7BIT, msg, octstr_destroy(), octstr_duplicate, and octstr_len().

Referenced by at2_pdu_encode(), and sms_split().

181 {
182  int ret = 0;
183  Octstr* msgdata = NULL;
184 
185  /* got a bad input */
186  if (!msg || !msg->sms.msgdata)
187  return -1;
188 
189  if (msg->sms.coding == DC_7BIT) {
190  msgdata = octstr_duplicate(msg->sms.msgdata);
191  charset_utf8_to_gsm(msgdata);
192  ret = octstr_len(msgdata);
193  octstr_destroy(msgdata);
194  } else
195  ret = octstr_len(msg->sms.msgdata);
196 
197  return ret;
198 }
void charset_utf8_to_gsm(Octstr *ostr)
Definition: charset.c:288
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
Definition: octstr.c:118
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
#define DC_7BIT
Definition: sms.h:110

◆ sms_priority_compare()

int sms_priority_compare ( const void *  a,
const void *  b 
)

Compare priority and time of two sms's.

Returns
-1 of a < b; 0 a = b; 1 a > b

Definition at line 395 of file sms.c.

References gw_assert().

Referenced by smpp_create(), smsc_at2_create(), and smsc_emi2_create().

396 {
397  int ret;
398  Msg *msg1 = (Msg*)a, *msg2 = (Msg*)b;
399  gw_assert(msg_type(msg1) == sms);
400  gw_assert(msg_type(msg2) == sms);
401 
402  if (msg1->sms.priority > msg2->sms.priority)
403  ret = 1;
404  else if (msg1->sms.priority < msg2->sms.priority)
405  ret = -1;
406  else {
407  if (msg1->sms.time > msg2->sms.time)
408  ret = 1;
409  else if (msg1->sms.time < msg2->sms.time)
410  ret = -1;
411  else
412  ret = 0;
413  }
414 
415  return ret;
416 }
gw_assert(wtls_machine->packet_to_send !=NULL)
msg_type
Definition: msg.h:73
Definition: msg.h:79

◆ sms_split()

List* sms_split ( Msg orig,
Octstr header,
Octstr footer,
Octstr nonlast_suffix,
Octstr split_chars,
int  catenate,
unsigned long  msg_sequence,
int  max_messages,
int  max_octets 
)

Definition at line 309 of file sms.c.

References CATENATE_UDH_LEN, DC_8BIT, DC_UCS2, DLR_IS_ENABLED, extract_msgdata_part_by_coding(), gwlist_append(), gwlist_create, gwlist_get(), max_messages, msg_destroy(), msg_duplicate(), octstr_append(), octstr_destroy(), octstr_insert(), octstr_len(), prepend_catenation_udh(), sms_msgdata_len(), and uuid_generate().

Referenced by dispatch_datagram(), msg_to_pdu(), run_batch(), send_message(), and smscconn_send().

313 {
314  long max_part_len, udh_len, hf_len, nlsuf_len;
315  unsigned long total_messages, msgno;
316  long last;
317  List *list;
318  Msg *part, *temp;
319 
320  hf_len = octstr_len(header) + octstr_len(footer);
321  nlsuf_len = octstr_len(nonlast_suffix);
322  udh_len = octstr_len(orig->sms.udhdata);
323 
324  /* First check whether the message is under one-part maximum */
325  if (orig->sms.coding == DC_8BIT || orig->sms.coding == DC_UCS2)
326  max_part_len = max_octets - udh_len - hf_len;
327  else
328  max_part_len = (max_octets - udh_len) * 8 / 7 - hf_len;
329 
330  if (sms_msgdata_len(orig) > max_part_len && catenate) {
331  /* Change part length to take concatenation overhead into account */
332  if (udh_len == 0)
333  udh_len = 1; /* Add the udh total length octet */
334  udh_len += CATENATE_UDH_LEN;
335  if (orig->sms.coding == DC_8BIT || orig->sms.coding == DC_UCS2)
336  max_part_len = max_octets - udh_len - hf_len;
337  else
338  max_part_len = (max_octets - udh_len) * 8 / 7 - hf_len;
339  }
340 
341  /* ensure max_part_len is never negativ */
342  max_part_len = max_part_len > 0 ? max_part_len : 0;
343 
344  temp = msg_duplicate(orig);
345  msgno = 0;
346  list = gwlist_create();
347 
348  last = 0;
349  do {
350  msgno++;
351  part = msg_duplicate(orig);
352 
353  /*
354  * if its a DLR request message getting split,
355  * only ask DLR for the first one
356  */
357  if ((msgno > 1) && DLR_IS_ENABLED(part->sms.dlr_mask)) {
358  octstr_destroy(part->sms.dlr_url);
359  part->sms.dlr_url = NULL;
360  part->sms.dlr_mask = 0;
361  }
362  octstr_destroy(part->sms.msgdata);
363  if (sms_msgdata_len(temp) <= max_part_len || msgno == max_messages)
364  last = 1;
365 
366  part->sms.msgdata =
367  extract_msgdata_part_by_coding(temp, split_chars,
368  max_part_len - nlsuf_len);
369  /* create new id for every part, except last */
370  if (!last)
371  uuid_generate(part->sms.id);
372 
373  if (header)
374  octstr_insert(part->sms.msgdata, header, 0);
375  if (footer)
376  octstr_append(part->sms.msgdata, footer);
377  if (!last && nonlast_suffix)
378  octstr_append(part->sms.msgdata, nonlast_suffix);
379  gwlist_append(list, part);
380  } while (!last);
381 
382  total_messages = msgno;
383  msg_destroy(temp);
384  if (catenate && total_messages > 1) {
385  for (msgno = 1; msgno <= total_messages; msgno++) {
386  part = gwlist_get(list, msgno - 1);
387  prepend_catenation_udh(part, msgno, total_messages, msg_sequence);
388  }
389  }
390 
391  return list;
392 }
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
void gwlist_append(List *list, void *item)
Definition: list.c:179
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1504
void * gwlist_get(List *list, long pos)
Definition: list.c:292
int sms_msgdata_len(Msg *msg)
Definition: sms.c:180
#define DC_8BIT
Definition: sms.h:111
void uuid_generate(uuid_t out)
Definition: gw_uuid.c:393
static Octstr * extract_msgdata_part_by_coding(Msg *msg, Octstr *split_chars, int max_part_len)
Definition: sms.c:267
Definition: msg.h:79
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
Definition: octstr.c:1303
long max_messages
Definition: wapbox.c:116
void msg_destroy(Msg *msg)
Definition: msg.c:132
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
#define CATENATE_UDH_LEN
Definition: sms.c:221
#define gwlist_create()
Definition: list.h:136
void prepend_catenation_udh(Msg *sms, int part_no, int num_messages, int msg_sequence)
Definition: sms.c:224
#define DLR_IS_ENABLED(dlr)
Definition: dlr.h:81
Definition: list.c:102
#define DC_UCS2
Definition: sms.h:112

◆ sms_swap()

int sms_swap ( Msg msg)

Definition at line 201 of file sms.c.

References msg.

Referenced by obey_request_thread().

202 {
203  Octstr *sender = NULL;
204 
205  if (msg->sms.sender != NULL && msg->sms.receiver != NULL) {
206  sender = msg->sms.sender;
207  msg->sms.sender = msg->sms.receiver;
208  msg->sms.receiver = sender;
209 
210  return 1;
211  }
212 
213  return 0;
214 }
Definition: octstr.c:118
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.