Kannel: Open Source WAP and SMS gateway  svn-r5335
smsc_sema.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 
58  /*
59  * smsc_sema.c - implement sms2000 protocal by using X25 access
60  * the data communication layer is implemented by using X28 protocol
61  *
62  * Code implement submit invoke, status invoke, deliver invoke session
63  * there is no internal db for storing delivered and undelivered message
64  *
65  * IA5 is most common line coding scheme.
66  * smsc_sema support only IA5 encoding, hex and binary line encoding is not
67  * supported.
68  *
69  * smsc_sema support IA5 and GSM Data Code Scheme for delivered invoke message
70  * smsc_sema support only IA5 Data Code Scheme for submit invoke message
71  *
72  * Reference : SMS2000 Version 4.0 Open Interface Specification
73  * Open Source WAP Gateway Architecture Design
74  * ESTI GSM 03.40
75  *
76  * Hao Shi 2000
77  */
78 
79 #include <errno.h>
80 #include <stdarg.h>
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <unistd.h>
85 #include <fcntl.h>
86 #include <termios.h>
87 
88 #include <sys/time.h>
89 #include <sys/types.h>
90 #include <sys/socket.h>
91 #include <sys/param.h>
92 
93 
94 #include <netinet/in.h>
95 #include <netdb.h>
96 
97 #include "gwlib/gwlib.h"
98 #include "smsc.h"
99 #include "smsc_p.h"
100 #include "alt_charsets.h"
101 #include "smsc_sema.h"
102 #include "sms.h"
103 
104 #ifndef CRTSCTS
105 #define CRTSCTS 0
106 #endif
107 
108 
109 static unsigned char sema_counter[4] = "0000";
110 static int sema_wait_report = 1;
112 
113 SMSCenter * sema_open(char* smscnua, char* homenua,
114  char* serialdevice, int waitreport)
115 {
116  SMSCenter *smsc;
117  int nret = -1;
118 
119  smsc = smscenter_construct();
120  if(smsc == NULL)
121  goto error;
122 
123  sprintf(smsc->name, "SEMA:X28:");
124 
125  smsc->type = SMSC_TYPE_SEMA_X28;
126  smsc->sema_smscnua = gw_strdup(smscnua);
127  smsc->sema_homenua = gw_strdup(homenua);
128  smsc->sema_serialdevice = gw_strdup(serialdevice);
129  sema_wait_report = waitreport;
130 
131  smsc->sema_mt = sema_msglist_new();
132  if(smsc->sema_mt == NULL) goto error;
133 
134  smsc->sema_mo = sema_msglist_new();
135  if(smsc->sema_mo == NULL) goto error;
136 
137  /* Open the device properly. Remember to set the
138  access codes correctly. */
139  debug("smsc.sema", 0, "sema_open: open datalink");
141  if(smsc->sema_fd == -1) goto error;
142 
143  /* test the outgoing callX28 to smsc center */
144  debug("smsc.sema", 0, "sema_open: test send link");
145  nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua);
146  if(nret < 1){
147  sleep(2);
148  nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua);
149  if(nret < 1)
150  goto error;
151  }
153  return smsc;
154 
155 error:
156  error(0, "sema_open: could not open");
157  smscenter_destruct(smsc);
158  return NULL;
159 }
160 
161 
163 {
164  int nret = 0;
165 
166  debug("smsc.sema", 0, "reopening the connection");
167 
168  /*deallocate*/
169  sema_msglist_free(smsc->sema_mt);
170  sema_msglist_free(smsc->sema_mo);
171  /*reallocate*/
172  smsc->sema_mt = sema_msglist_new();
173  if(smsc->sema_mt == NULL) goto error;
174  smsc->sema_mo = sema_msglist_new();
175  if(smsc->sema_mo == NULL) goto error;
176  memset(smsc->buffer,0,sizeof(smsc->buffer));
177 
178  /* Open the device properly. Remember to set the
179  access codes correctly. */
181  if(smsc->sema_fd == -1){
182  error(0,"sema_reopen_data_link: device file error");
183  goto error;
184  }
185  /*test outgoing call to the smsc */
186  nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua);
187  if(nret < 1){
188  error(0,"test send data link failed");
189  goto error;
190  }
192  return 0;
193 error:
194  error(0, "sema_reopen_data_link: failed");
195  return -1;
196 
197 }
198 
200 {
201  if(smsc->sema_fd > 0)
202  close(smsc->sema_fd);
203  /*deallocate*/
204  sema_msglist_free(smsc->sema_mt);
205  sema_msglist_free(smsc->sema_mo);
206  return 0;
207 }
208 
209 
211 {
212  int nret = 0;
213  struct sema_msg *lmsg = NULL;
214  struct sm_submit_invoke *submit_sm = NULL;
215  char x28sender[2] = "A3";
216 
217  /* Validate msg */
218  if(smsc == NULL){
219  error(0,"sema_submit_msg: SMSC is empty");
220  goto error;
221  }
222  if(msg == NULL){
223  error(0, "sema_submit_msg: Msg is empty");
224  goto error;
225  }
226 
227  if(msg_type(msg) != sms) {
228  error(0, "sema_submit_sms: Msg is WRONG TYPE");
229  goto error;
230  }
231  /* user data header is not supported in sm2000 X25 access
232  if(msg->sms.coding == DC_7BIT ...|| DC_UNDEF?){
233  error(0, "sema_submit_sms: submit invoke support in IA5 encoding(8 bits chars)");
234  goto error;
235  }
236 
237  if(octstr_len(msg->sms.udhdata)){
238  error(0, "sema_submit_sms: submit invoke not support in IA5 encoding ");
239  goto error;
240  }
241  */
242  lmsg = sema_msg_new();
243 
244  submit_sm = gw_malloc(sizeof(struct sm_submit_invoke));
245  memset(submit_sm, 0, sizeof(struct sm_submit_invoke));
246 
247  lmsg->type = 'S';
248  lmsg->encodetype = LINE_ENCODE_IA5;
249 
250  /* set operation reference */
252  memcpy(lmsg->optref,sema_counter,4);
253  /*set sme reference number*/
255  memcpy(submit_sm->smerefnum, sema_counter, 4);
256  /*we send as not key type*/
257  submit_sm->smereftype= 2; /*key type is 1*/
258  /*we set prority as normal*/
259  submit_sm->priority = 1; /*0 is high*/
260  /*set valid period type as relative*/
261  submit_sm->validperiodtype = 2; /* 1 is absolute */
262  /*time*/
263  submit_sm->validperiodrela = 1; /* from 0 to 143 , fomula is (V+1)*5 min*/
264  /*send msg without 00 header*/
265  submit_sm->msisdnlen= octstr_len(msg->sms.receiver);
266  submit_sm->msisdn = octstr_copy(msg->sms.receiver,0,submit_sm->msisdnlen);
267  /* X25 access will always append sender during data transfer */
268  submit_sm->origaddlen= 2; /* we need only to orignate address type */
269  submit_sm->origadd = octstr_create_from_data(x28sender,2);
270  /*data encoding scheme ,support only IA5 in current version*/
271  submit_sm->DCS = 15; /*gsm is 0 ,IA5 is 15*/
272  /*protocal ,support only default value 0 in current version*/
273  submit_sm->protocal = 0;
274  /*replypath*/
275  submit_sm->replypath= 0; /*gateway do not pay for reply*/
276  /*status report*/
277  if(sema_wait_report > 0)
278  submit_sm->statusreportrequest =4; /* deliver success, in bin form 00000100*/
279  else
280  submit_sm->statusreportrequest = 0;/* no report */
281  /* we support submit invoke only in IA5 line encoding*/
282  submit_sm->textsizeoctect = submit_sm->textsizeseptet =
283  octstr_len(msg->sms.msgdata);
284  /*copy msg buffer*/
285  submit_sm->shortmsg = octstr_copy(msg->sms.msgdata,
286  0, submit_sm->textsizeoctect);
287 
288  memset(submit_sm->smscrefnum,0,sizeof(submit_sm->smscrefnum));
289  /*pack the message body in 2kmsg*/
290  lmsg->msgbody = submit_sm;
291  nret = sema_msg_session_mt(smsc, lmsg);
292 
293  gw_free(submit_sm);
294  submit_sm = NULL;
295  sema_msg_free(lmsg);
296  lmsg = NULL;
297 
298 
299  if(nret == SESSION_MT_RECEIVE_SUCCESS){
300  debug("smsc.sema", 0, "sema_submit_msg: message is successfully delivered");
301  return 1; /*success*/
302  }
303  else if(nret == SESSION_MT_RECEIVE_TIMEOUT){
304  info(0, "sema_submit msg: session timed out without return");
305  return 0;
306  }
307  else if(nret == SESSION_MT_RECEIVE_ERR){
308  info(0, "sema_submit msg: smsc says submit failed!");
309  return 0;
310  }
311 
312  return 1;
313 
314 error:
315  if(submit_sm)
316  gw_free(submit_sm);
317  if(lmsg)
318  sema_msg_free(lmsg);
319  return -1;
320 }
321 
322 
324 {
325 
326  struct sema_msg *rmsg = NULL;
327  struct sm_deliver_invoke *recieve_sm = NULL;
328 
329  while(sema_msglist_pop(smsc->sema_mo, &rmsg) == 1 ) {
330 
331  *msg = msg_create(sms);
332  if(*msg==NULL) goto error;
333 
334  recieve_sm = (struct sm_deliver_invoke*) rmsg->msgbody;
335  if(recieve_sm==NULL) goto error;
336 
337  /* as IA5(8 bit character) is the default line encoding used by X28
338  * and we do not support other line encoding scheme like binary or
339  * hex encoding
340  */
341  (*msg)->sms.coding = DC_8BIT;
342  /* OIS in X28 implementation does not include udh field */
343 
344  (*msg)->sms.sender = octstr_create_from_data(
345  octstr_get_cstr(recieve_sm->origadd) +2,
346  octstr_len(recieve_sm->origadd)-2);
347  (*msg)->sms.receiver = octstr_create_from_data(
348  octstr_get_cstr(recieve_sm->destadd) +2,
349  octstr_len(recieve_sm->destadd)-2);
350 
351  (*msg)->sms.msgdata = octstr_duplicate(recieve_sm->shortmsg);
352  (*msg)->sms.udhdata = octstr_create("");
353  gw_free(recieve_sm);
354  sema_msg_free(rmsg);
355  rmsg = NULL;
356  }
357  return 1;
358 
359 error:
360  error(0, "sema_receive_msg: can not create Smart Msg");
361  return -1;
362 }
363 
364 
366 {
367 
368  char data[1024];
369  int ret = 0;
370  char clrbuff[]="CLR\0";
371  char errbuff[]="ERR\0";
372  /* struct sema_msg* smsg = NULL;*/
373 
374  /* Receive raw data */
375  ret = X28_data_read(smsc->sema_fd, smsc->buffer);
376  if(ret == -1) {
377  ret = X28_reopen_data_link(smsc->sema_fd, smsc->sema_serialdevice);
378  if(ret == -1) goto error;
379  return 0;
380  }
381 
382  /* Interpret the raw data */
383  memset(data,0,sizeof(data));
384  while(X28_msg_pop(smsc->buffer, data) == 0 ) {
385  if(strlen(data) > 0){
386  if(strstr(data,clrbuff) != NULL ||
387  strstr(data,errbuff) != NULL){
388  debug("smsc.sema", 0, "sema_pending_msg: Radio Pad Command line-%s",data);
389  }
390  else{
391 
392  ret = sema_msg_session_mo(smsc, data);
393  if(ret == -1) goto error;
394  }
395  memset(data,0,sizeof(data));
396  }
397  }
398 
399  /* Signal that we got a MO message if mo list is not empty*/
400  if(smsc->sema_mo->first != NULL){
401  return 1;
402  }
403 
404 
405  return 0;
406 
407 error:
408  error(0,"sema_pending message: device file error");
409  return -1;
410 }
411 
412 
413 
414 static sema_msg* sema_msg_new(void)
415 {
416  struct sema_msg *msg = NULL;
417  msg = gw_malloc(sizeof(struct sema_msg));
418  memset(msg, 0, sizeof(struct sema_msg));
419  return msg;
420 }
421 
422 static int sema_msg_free(sema_msg *msg) {
423  if(msg == NULL) return 0;
424  gw_free(msg);
425  return 1;
426 }
427 
429 
430  struct sema_msglist *mlist = NULL;
431  mlist = gw_malloc(sizeof(struct sema_msglist));
432  memset(mlist, 0, sizeof(struct sema_msglist));
433 
434  mlist->first = NULL;
435  mlist->last = NULL;
436  mlist->count = 0;
437  return mlist;
438 }
439 
440 static void sema_msglist_free(sema_msglist *mlist) {
441 
442  struct sema_msg *pmsg = NULL;
443  if(mlist == NULL) return;
444  while( sema_msglist_pop(mlist, &pmsg) == 1 ) {
445  if(pmsg==NULL) break;
446  sema_msg_free(pmsg);
447  pmsg = NULL;
448  }
449  gw_free(mlist);
450  mlist->count = 0;
451 }
452 
453 static int sema_msglist_push(sema_msglist *plist, sema_msg *pmsg) {
454 
455  struct sema_msg * lmsg = NULL;
456  if(plist == NULL) {
457  info(0, "msglist_push: NULL msg list");
458  goto error;
459  }
460  if(pmsg == NULL) {
461  info(0, "msglist_push: NULL input");
462  goto error;
463  }
464  /* If list is completely empty. */
465  if( plist->first == NULL ) {
466  plist->last = pmsg;
467  plist->first = pmsg;
468  pmsg->prev = NULL;
469  pmsg->next = NULL;
470  }
471  else{
472  lmsg=plist->last;
473  lmsg->next=pmsg;
474  pmsg->prev=lmsg;
475  pmsg->next=NULL;
476  plist->last=pmsg;
477  }
478  plist->count += 1;
479  return 1;
480 
481 error:
482  error(0, "msglist_push: error");
483  return 0;
484 
485 }
486 
487 static int sema_msglist_pop(sema_msglist *plist, sema_msg **msg) {
488 
489  if(plist == NULL) {
490  info(0, "msglist_pop: NULL list");
491  goto no_msg;
492  }
493  if(plist->first == NULL) {
494  goto no_msg;
495  }
496 
497  *msg = plist->first;
498  if(plist->last == *msg) {
499  plist->first = NULL;
500  (*msg)->prev = NULL;
501  plist->last = NULL;
502  }
503  else {
504  plist->first = (*msg)->next;
505  plist->first->prev = NULL;
506  if(plist->first->next == NULL)
507  plist->last = plist->first;
508  }
509  plist->count -= 1;
510  return 1;
511 
512 no_msg:
513  return 0;
514 }
515 
516 
517 
518 static int X28_open_data_link(char* device){
519  int fd = -1, iret;
520  struct termios tios;
521  info(0,"open serial device %s",device);
522  fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY);
523  if(fd==-1) {
524  error(errno, "sema_open_data_link: error open(2)ing the character device <%s>",
525  device);
526  if(errno == EACCES)
527  error(0, "sema_open_data_link: user has no right to access the serial device");
528  return -1;
529  }
530 
531  tcgetattr(fd, &tios);
532  cfsetospeed(&tios, B4800); /* check radio pad parameter*/
533  cfsetispeed(&tios, B4800);
534  kannel_cfmakeraw(&tios);
535  tios.c_iflag |= IGNBRK|IGNPAR|INPCK|ISTRIP;
536  tios.c_cflag |= (CSIZE|HUPCL | CREAD | CRTSCTS);
537  tios.c_cflag ^= PARODD;
538  tios.c_cflag |=CS7;
539  iret = tcsetattr(fd, TCSANOW, &tios);
540  if(iret == -1){
541  error(errno,"sema_open_data_link: fail to set termios attribute");
542  goto error;
543  }
544  tcflush(fd, TCIOFLUSH);
545  return fd;
546 
547 error:
548  return -1;
549 }
550 
551 static int X28_reopen_data_link(int oldpadfd ,char* device){
552  int nret = 0;
553  if(oldpadfd > 0){
554  nret= close(oldpadfd);
555  if(nret == -1){
556  error(errno,"sema_reopen_data_link: close device file failed!!");
557  }
558  }
559  sleep(1);
560  return X28_open_data_link(device);
561 }
562 
563 
564 static int X28_close_send_link(int padfd)
565 {
566  char discnntbuff[6];
567  char readbuff[1024];
568  char finishconfirm[]="CLR CONF\0";
569  int nret = 0, readall = 0;
570  time_t tstart;
571  time(&tstart);
572 
573  sprintf(discnntbuff,"%cCLR\r",0x10);
574  memset(readbuff,0,sizeof(readbuff));
575 
576  /* what ever is the close return, data mode is unreliable now*/
578 
579  if(padfd <= 0)
580  goto datalink_error;
581  while((time(NULL) - tstart) < INTERNAL_DISCONNECT_TIMEVAL){
582  nret =write(padfd, discnntbuff, 6);
583  if(nret == -1){
584  if(errno == EAGAIN || errno ==EINTR) continue;
585  else{
586  goto datalink_error;
587  }
588  }
589  sleep(1); /*wait 1 senconds for virtual link break*/
590  nret=read(padfd, readbuff+readall,128);
591  if(nret == -1){
592  if(errno == EAGAIN || errno ==EINTR) continue;
593  else{
594  goto datalink_error;
595  }
596  }
597  if(nret >0){
598  readall += nret;
599  if(strstr(readbuff,finishconfirm))
600  return 1;
601  }
602  }
603  return 0;
604 datalink_error:
605  error(errno,"sema_close_send_link, device file error");
606  return -1;
607 }
608 
609 
610 
611 static int X28_open_send_link(int padfd, char *nua) {
612 
613  char readbuff[1024];
614  char writebuff[129];
615  char smscbuff[129];
616  int readall = 0, readonce = 0, writeonce = 0, writeall = 0, i = 0;
617  char X28prompt[]="*\r\n\0";
618  time_t timestart;
619 
620  debug("smsc.sema", 0, "sema_open send link: call smsc <%s> for <%i> seconds",
621  nua, (int)INTERNAL_CONNECT_TIMEVAL);
622 
623  /* type few <cr> to invoke DTE */
624  writebuff[0] = '\r';
625  memset(readbuff,0,sizeof(readbuff));
626  for(i = 0; i <= 3; i++)
627  {
628  readonce = writeonce = -1;
629  writeonce = write(padfd, writebuff, 1);
630  if(writeonce < 1){
631  if(errno == EINTR || errno == EAGAIN) continue;
632  else{
633  goto datalink_error;
634  }
635  }
636  usleep(1000); /* wait for prompt */
637  readonce = read(padfd, &readbuff[readall],1024);
638  if(readonce == -1){
639  if(errno == EINTR || errno == EAGAIN) continue;
640  else{
641  goto datalink_error;
642  }
643  }
644  else
645  readall += readonce;
646  }
647  if(strstr(readbuff, X28prompt) == NULL){
648  warning(0,"X28_open_send_link: can not read command prompt, abort");
649  return 0;
650  }
651 
652 
653  /* second, connect to the smsc now */
654  memset(writebuff,0,sizeof(writebuff));
655  memset(readbuff,0,sizeof(readbuff));
656  writeall = readall = 0;
657  sprintf(writebuff, "%s\r", nua);
658  sprintf(smscbuff, "%s COM",nua);
659 
660  while((size_t) writeall < strlen(writebuff)){
661  writeonce = -1;
662  writeonce = write(padfd, writebuff+writeall, strlen(writebuff)-writeall);
663  if(writeonce == -1){
664  if(errno == EINTR || errno == EAGAIN)
665  continue;
666  else
667  goto datalink_error;
668  }
669  if(writeonce > 0)
670  writeall +=writeonce;
671  }
672  tcdrain(padfd);
673  usleep(1000*1000);/* wait for smsc answer */
674 
675  time(&timestart);
676  while(time(NULL) - timestart < INTERNAL_CONNECT_TIMEVAL){
677  if((size_t) readall >= sizeof(readbuff))
678  goto error_overflow;
679  /* We read 1 char a time */
680  readonce = read(padfd, &readbuff[readall], 1);
681  if(readonce == -1) {
682  if(errno == EINTR || errno == EAGAIN) continue;
683  else
684  goto datalink_error;
685  }
686  if(readonce > 0)
687  readall += readonce;
688  /* Search for response line. */
689  if(readall > 2 &&
690  readbuff[readall-1] == '\n' &&
691  readbuff[readall-2] == '\r') {
692  if(strstr(readbuff, smscbuff)) {
693  debug("smsc.sema", 0,
694  "sema_open send link: smsc responded, virtual link established");
696  return 1;
697  }
698  }
699  usleep(1000);
700  }
701  info(0,"sema_open_send_link: connect timeout");
702  return 0;
703 error_overflow:
704  warning(0, "sema_open_send_link: command buffer overflow");
705  return 0;
706 datalink_error:
707  error(errno,"sema_open_send_link: device file error");
708  return -1;
709 }
710 
711 
712 
713 static int X28_data_read(int padfd, char *cbuffer) {
714  char *p = NULL;
715  int ret, len;
716  fd_set read_fd;
717  struct timeval tv, tvinit;
718  size_t readall;
719 
720  tvinit.tv_sec = 0;
721  tvinit.tv_usec = 1000;
722 
723  readall = 0;
724  for (;;) {
725  FD_ZERO(&read_fd);
726  FD_SET(padfd, &read_fd);
727  tv = tvinit;
728  ret = select(padfd + 1, &read_fd, NULL, NULL, &tv);
729  if (ret == -1) {
730  if(errno==EINTR) goto got_data;
731  if(errno==EAGAIN) goto got_data;
732  error(errno, "Error doing select for fad");
733  return -1;
734  } else if (ret == 0)
735  goto got_data;
736  len = strlen(cbuffer);
737  ret = read(padfd,
738  cbuffer + len,
739  256);
740  if (ret == -1) {
741  error(errno," read device file");
742  return -1;
743  }
744  if (ret == 0)
745  goto eof;
746 
747  readall += ret;
748  if ((size_t) len > sizeof(cbuffer)- 256) {
749  p = gw_realloc(cbuffer, sizeof(cbuffer) * 2);
750  memset(p+len,0,sizeof(cbuffer)*2 - len);
751  cbuffer = p;
752  }
753  if(readall > 0)
754  break;
755  }
756 
757 eof:
758  if(readall > 0)
759  ret = 1;
760  goto unblock;
761 
762 got_data:
763  ret = 0;
764  goto unblock;
765 
766 unblock:
767  return ret;
768 
769 }
770 
771 static int X28_data_send(int padfd, char *cbuffer,int sentonce) {
772  int len = 0, pos = 0,writeonce = 0,writeall = 0;
773 
774  tcdrain(padfd);
775  len = strlen(cbuffer);
776  while(len > 0){
777  if(len < sentonce) {
778  writeonce = write(padfd, cbuffer+pos, len);
779  }
780  else
781  writeonce = write(padfd, cbuffer+pos, sentonce);
782 
783  if (writeonce == -1) {
784  if(errno == EINTR || errno == EINTR)
785  continue;
786  else{
787  goto error;
788  }
789  }
790  if(writeonce > 0){
791  len -= writeonce;
792  pos += writeonce;
793  writeall = pos;
794  }
795  }
796  tcdrain(padfd);
797  return writeall;
798 
799 error:
800  error(errno,"sema_send data error: device file error");
801  return -1;
802 }
803 
804 static int X28_msg_pop(char *from, char *to)
805 {
806  char* Rbuff =NULL;
807  char* RRbuff = NULL;
808  char mobuff[] ="COM\r\n\0";
809  char mobuffend[] = "\r\0";
810  char prompbuff[] = "*\r\0";
811  int len = 0, Llen= 0, Rlen = 0,RRlen = 0;
812 
813  len = strlen(from);
814  if(len <=0) goto no_msg;
815 
816  /* trim off rabbish header */
817  while(*from == '\r' || *from == '\n'){
818  len = strlen(from);
819  if(len > 1){
820  memmove(from, from +1, len-1);
821  memset(from+(len-1), 0, 1);
822  }
823  else{
824  memset(from,0,len);
825  return -1;
826  }
827  }
828 
829  len = strlen(from);
830  /*all kinds of useful infomation contains \r*/
831  if((Rbuff=memchr(from,'\r',len)) == NULL)
832  goto no_msg;
833 
834 
835  /*check if it is a command prompt *\r\n */
836  if((Rbuff -from) > 0 && *(Rbuff -1) == '*'){
837  if(strlen(Rbuff) < 2) goto no_msg; /*\n is not coming yet*/
838 
839  if(Rbuff -from > 4){ /* command info */
840  Rlen = Rbuff -1 -from;
841  memcpy(to,from,Rlen);
842  }
844  if(strlen(Rbuff+1) > 1){
845  Rlen = strlen(Rbuff +2);
846  memmove(from, Rbuff +2, Rlen);
847  memset(from+Rlen, 0, len-Rlen);
848  }
849  else
850  memset(from, 0,len);
851  }/* check mo msg , format X121address+COM\r\n+msg+\r*/
852  else if((Rbuff-from) > 3 && strstr(Rbuff-4,mobuff)!= NULL){
853  if(strlen(Rbuff) < 3 ||
854  (RRbuff = strstr(Rbuff + 2, mobuffend)) == NULL)
855  goto no_msg; /*the msg+\r is still coming*/
856 
857  RRlen = RRbuff - (Rbuff+2);
858  if(RRlen > 4){ /* msg header is 4 byte always+msg content*/
859  memcpy(to, Rbuff +2 , RRlen);
861  }
862 
863  if(strlen(RRbuff) > 1){
864  Rlen = strlen(RRbuff +1);
865  memmove(from, RRbuff+1 ,Rlen);
866  memset(from+Rlen,0,len -Rlen);
867  }
868  else
869  memset(from,0,len);
870  }
871  else{/* it can be mt reply */
872  if(Rbuff - from > 0){
873  Llen = Rbuff - from;
874  memcpy(to, from, Llen);
875  }
876  if(strlen(Rbuff) > 1){
877  Rlen = strlen(Rbuff+1);
878  memmove(from,Rbuff+1,Rlen);
879  memset(from+Rlen,0,len-Rlen);
880  }
881  else
882  memset(from,0,len);
883  }
884 
885  /* check rest of line for link state: command mode or data mode */
886  if(strstr(from,prompbuff) != NULL)
888 
889  return 0;
890 no_msg:
891  return -1;
892 }
893 
894 
895 
896 static int sema_submit_result(SMSCenter *smsc, sema_msg* srcmsg, int result)
897 {
898  char IA5buff[1024];
899  unsigned char oct1byte[1];
900  unsigned char ia5byte[2];
901  unsigned char cTr='t';
902  unsigned char cMr='m';
903  unsigned char ccontinuebyte = 'P', ccr = '\r';
904  int j = 0, iret;
905 
906  memset(IA5buff,0,sizeof(IA5buff));
907  switch(srcmsg->type)
908  {
909  case 'M':
910  memcpy(IA5buff,&cMr,1);/*msg type*/
911  memcpy(IA5buff+1,&ccontinuebyte,1); /*continue bit*/
912  memcpy(IA5buff+2,srcmsg->optref,4); /*operation reference*/
913  write_variable_value(result,oct1byte);
914  j=internal_char_hex_to_IA5(oct1byte[0],ia5byte);
915  memcpy(IA5buff+6,ia5byte,j);
916  memcpy(IA5buff+6+j,&ccr,1);/*result*/
917  iret = X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff));
918  if(iret == -1) goto error;
919  break;
920  case 'T':
921  memcpy(IA5buff,&cTr,1);
922  memcpy(IA5buff+1,&ccontinuebyte,1);
923  memcpy(IA5buff+2,srcmsg->optref,4);
924  write_variable_value(result,oct1byte);
925  j=internal_char_hex_to_IA5(oct1byte[0],ia5byte);
926  memcpy(IA5buff+6,ia5byte,j);
927  memcpy(IA5buff+6+j,&ccr,1);
928  iret = X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff));
929  if(iret == -1) goto error;
930  break;
931  default:
932  return 0; /*unsupoorted result msg type*/
933  }
934  return 1;
935 error:
936  error(0,"sk_submit_result: write to device file failed");
937  return -1;
938 }
939 
940 static int sema_msg_session_mt(SMSCenter *smsc, sema_msg* pmsg){
941  struct msg_hash *segments = NULL;
942  struct sema_msg* mtrmsg = NULL;
943  struct sm_statusreport_invoke* report_invoke = NULL;
944  struct sm_submit_result* submit_result = NULL;
945  struct sm_submit_invoke* submit_invoke = NULL;
946  struct sm_deliver_invoke* deliver_invoke = NULL;
947 
948  char data[1024], IA5buff[256], IA5chars[1024], mochars[10*1024];
949  unsigned char ccontinuebyte, ccr = '\r';
950  unsigned char cerr[] = "ERR\0",cclr[] = "CLR\0", tmp1[5] , tmp2[5];
951 
952  int i, iseg = 0, ilen = 0,iret = 0, moret;
953  int isrcved = 0, iTrcved = 0, decoderesult = 0;
954  time_t tstart;
955 
956  submit_invoke = (struct sm_submit_invoke*) pmsg->msgbody;
957  if(submit_invoke == NULL) goto error;
958 
959  /*encode first*/
960  memset(IA5chars,0,sizeof(IA5chars));
961 
962  if(sema_encode_msg(pmsg, IA5chars) < 1) goto encode_error;
963 
964  /*divide segments, we send buffer no more than 128 byte once*/
965  iseg = strlen(IA5chars)/121 + 1;
966  segments = gw_malloc(iseg * sizeof(struct msg_hash));
967  if(segments == NULL) goto error;
968 
969 
970  /*first segments*/
971  if(strlen(IA5chars) < 121)
972  ilen = strlen(IA5chars);
973  else
974  ilen = 121;
975  segments[0].content = octstr_create_from_data((char *)&(pmsg->type), 1);/*msg type, in hex*/
976  ccontinuebyte = pack_continous_byte(pmsg->encodetype, 1, iseg -1);
977  octstr_insert_data(segments[0].content, 1,
978  (char *)&ccontinuebyte, 1); /*continue char, in hex*/
979  octstr_insert_data(segments[0].content,
980  2, (char *)pmsg->optref, 4); /*operation reference, in hex*/
981  octstr_insert_data(segments[0].content, 6,
982  IA5chars, ilen);
983  octstr_insert_data(segments[0].content,
984  octstr_len(segments[0].content), (char *)&ccr, 1); /*<cr>*/
985 
986  /*rest segments*/
987  for( i = 1; i < iseg; i++){
988  if(strlen(IA5chars) - i*121 < 121)
989  ilen = strlen(IA5chars) - i*121;
990  else
991  ilen =121;
992  segments[i].content= octstr_create_from_data((char *)&(pmsg->type), 1);
993  ccontinuebyte = pack_continous_byte(pmsg->encodetype, 0, iseg -i-1);
994  octstr_insert_data(segments[i].content, 1, (char *)&ccontinuebyte, 1);
995  octstr_insert_data(segments[i].content, 2, (char *)pmsg->optref, 4);
996  octstr_insert_data(segments[i].content, 6,
997  IA5chars + i*121, ilen);
998  octstr_insert_data(segments[i].content,
999  octstr_len(segments[i].content),(char *)&ccr, 1);
1000  }
1001 
1003  /* do not trust any existing data mode*/
1004  X28_close_send_link(smsc->sema_fd);
1005  /*open send link*/
1006  if((iret = X28_open_send_link(smsc->sema_fd,smsc->sema_smscnua)) < 1){
1007  if(iret == -1){
1008  iret = X28_reopen_data_link(smsc->sema_fd, smsc->sema_serialdevice);
1009  if(iret == -1){
1010  goto error;
1011  }
1012  }
1013  X28_close_send_link(smsc->sema_fd);
1014  sleep(1);
1015  iret = X28_open_send_link(smsc->sema_fd,smsc->sema_smscnua);
1016  if(iret < 1)
1017  goto sendlink_error;
1018  }
1019  }
1020  /*deliver buff*/
1021  for(i = 0; i < iseg; i++){
1022  memset(IA5buff,0,sizeof(IA5buff));
1023  memcpy(IA5buff,octstr_get_cstr(segments[i].content),
1024  octstr_len(segments[i].content));
1025 
1026  iret =X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff));
1027  if(iret == -1)
1028  goto error;
1029  octstr_destroy(segments[i].content);
1030  }
1031  gw_free(segments);
1032 
1033  /*wait result and report return*/
1034  mtrmsg = sema_msg_new();
1035  memset(mochars,0,sizeof(mochars));
1036 
1037  time(&tstart);
1038  while(time(NULL) -tstart < INTERNAL_SESSION_MT_TIMEVAL){
1039  iret = X28_data_read(smsc->sema_fd, smsc->buffer);
1040  if(iret == -1)
1041  goto error;
1042 
1043  /* Interpret the raw data */
1044  memset(data,0,sizeof(data));
1045  while(X28_msg_pop(smsc->buffer, data) == 0 ) {
1046  if(strlen(data) > 0){
1047  if(strstr(data,(char *)cerr) != NULL ||
1048  strstr(data,(char *)cclr) != NULL){
1049  debug("smsc.sema", 0, "sema_mt_session: Radio Pad Command line-%s",data);
1050  goto sendlink_error;
1051  }
1052  /* decode msg*/
1053  decoderesult = sema_decode_msg(&mtrmsg,data);
1054  if(decoderesult >= 0){
1055  if(mtrmsg->type == 's'){ /*submit result*/
1056 
1057  submit_result = (struct sm_submit_result*) mtrmsg->msgbody;
1058  if(submit_result == NULL) goto error;
1059  /* check result operation number is what we send */
1060  memset(tmp1,0,5); memset(tmp2,0,5);
1061  memcpy(tmp1,mtrmsg->optref,4);
1062  memcpy(tmp2, pmsg->optref,4);
1063  if(strstr((char *)tmp1,(char *)tmp2) != NULL){
1064  isrcved = 1;
1065  memcpy(submit_invoke->smscrefnum, submit_result->smscrefnum,4);
1066  }
1067  if(isrcved == 1 &&
1068  submit_result->smeresult != 0){
1069  gw_free(submit_result);
1070  goto smsc_say_fail;
1071  }
1072  gw_free(submit_result);
1073 
1074  }
1075  else if(mtrmsg->type == 'T'){ /*report invoke*/
1076 
1077  report_invoke = (struct sm_statusreport_invoke*) mtrmsg->msgbody;
1078  if(report_invoke == NULL) goto error;
1079  /*check if report reference number is what we expect*/
1080  memset(tmp1,0,sizeof(tmp1)); memset(tmp2,0,sizeof(tmp2));
1081  memcpy(tmp1,report_invoke->smscrefnum,4);
1082  memcpy(tmp2,submit_invoke->smscrefnum,4);
1083  if(strstr((char *)tmp1,(char *)tmp2) != NULL){
1084  iTrcved = 1;
1085  }
1086  decoderesult = 0;
1087  iret = sema_submit_result(smsc, mtrmsg, decoderesult);
1088  if(iret == -1) goto error;
1089  if(iTrcved == 1 &&
1090  report_invoke->status != 3){ /*3 means msg delivered*/
1091  info(0,"sema_mt_session: submit invoke failed with report value-%i",report_invoke->status);
1092  gw_free(report_invoke);
1093  goto smsc_say_fail;
1094  }
1095  gw_free(report_invoke);
1096 
1097  }
1098  else if(mtrmsg->type == 'M'){/* deliver invoke*/
1099 
1100  /* we do not deal with deliver in mt session*/
1101  decoderesult = 0;
1102  iret = sema_submit_result(smsc, mtrmsg, decoderesult);
1103  if(iret == -1) goto error;
1104  deliver_invoke = (struct sm_deliver_invoke*) mtrmsg->msgbody;
1105  if(deliver_invoke != NULL){
1106  gw_free(deliver_invoke);
1107  /*append buffer back to smsc->buffer*/
1108  ilen=strlen(mochars);
1109  memcpy(mochars+ilen,data,strlen(data));
1110  ilen=strlen(mochars);
1111  memcpy(mochars+ilen,&ccr,1);
1112  }
1113  time(&tstart);
1114  }
1115  /* clean msg for next read*/
1116  memset(mtrmsg,0,sizeof(struct sema_msg));
1117  }
1118  /* clean buffer for next useful info*/
1119  memset(data,0,sizeof(data));
1120  if(sema_wait_report == 0 && isrcved == 1)
1121  {
1122  info(0,"sema_mt_session: submit invoke delivered successfully to smsc");
1123  goto mo_success;
1124  }
1125  if(sema_wait_report > 0 &&
1126  isrcved == 1 && iTrcved == 1)
1127  {
1128  info(0,"sema_mt_session: submit invoke delivered successfully to msisdn");
1129  goto mo_success;
1130  }
1131  }
1132  }
1133  }
1134 
1135 /* mo_timeout: */
1136  info(0,"sema_mt_session: timeout without receiving all expected returns");
1138  goto mo_return;
1139 mo_success:
1141  goto mo_return;
1142 smsc_say_fail:
1143  info(0,"sema_mt_session: smsc says message deliver failed!");
1144  moret = SESSION_MT_RECEIVE_ERR;
1145  goto mo_return;
1146 mo_return:
1148  /* we have to close here, otherwise smsc will wait for a long time
1149  untill it find out nothing is coming */
1150  sema_msg_free(mtrmsg);
1151  ilen = strlen(mochars);
1152  i = strlen(smsc->buffer);
1153  if(ilen > 0){
1154  memmove( smsc->buffer+ilen,smsc->buffer,i);
1155  memcpy(smsc->buffer, mochars,ilen);
1156  }
1157  return moret;
1158 sendlink_error:
1159  info(0,"sema_mt_session: X28 data link has broken");
1160  if(mtrmsg != NULL)
1161  sema_msg_free(mtrmsg);
1162  return 0;
1163 encode_error:
1164  info(0,"sema_mt_session: Msg encode error");
1165  return 0;
1166 error:
1167  error(0,"sema_mt session: memory allocation error or device file error");
1168  return -1;
1169 
1170 }
1171 
1172 
1173 static int sema_msg_session_mo(SMSCenter *smsc, char* cbuff){
1174 
1175  struct sema_msg *rmsg = NULL;
1176  int iret = 0, retresult = 0;
1177 
1178  struct sm_deliver_invoke* deliver_invoke = NULL;
1179  struct sm_statusreport_invoke* report_invoke = NULL;
1180 
1181  rmsg = sema_msg_new();
1182 
1183  iret = sema_decode_msg(&rmsg,cbuff);
1184  if(iret == - 1) goto msg_error;/* decode error */
1185 
1187  /* do not trust any existing data mode*/
1188 
1189  /* XXX this should be fixed? -rpr */
1190 
1191  X28_close_send_link(smsc->sema_fd);
1192  /*open send link*/
1193  if(X28_open_send_link(smsc->sema_fd,smsc->sema_smscnua) < 1){
1194  info(0,"sema_mo_session: can not establish send link");
1195  return 0;
1196  }
1197  }
1198 
1199  if(rmsg->type == 'M'){ /* deliver invoke */
1200  retresult = 0; /* deliver invoke */
1201  iret = sema_submit_result(smsc, rmsg, retresult);
1202  if(iret == -1) goto error;
1203  deliver_invoke = (struct sm_deliver_invoke*) rmsg->msgbody;
1204  if(deliver_invoke == NULL) goto msg_error;
1205  sema_msglist_push(smsc->sema_mo, rmsg);
1206  return 1;
1207  }
1208  else if(rmsg->type == 'T'){ /* status report */
1209  retresult = 0; /* let msg through */
1210  sema_submit_result(smsc, rmsg, retresult);
1211  if(iret == -1) goto error;
1212  report_invoke = (struct sm_statusreport_invoke*) rmsg->msgbody;
1213  if(report_invoke != NULL)
1214  gw_free(report_invoke);
1215  }
1216  else{ /* add your additional support here*/
1217  }
1218  sema_msg_free(rmsg);
1219  return 1;
1220 
1221 msg_error:
1222  sema_msg_free(rmsg);
1223  error(0,"sema_mo session: Msg decode failed");
1224  return 0;
1225 error:
1226  error(0,"sema_mo session: device file error or memory allocation problem!");
1227  return -1;
1228 }
1229 
1230 
1231 
1232 static int sema_decode_msg(sema_msg **desmsg, char* octsrc) {
1233  struct sm_deliver_invoke *receive_sm = NULL;
1234  struct sm_statusreport_invoke* receive_report = NULL;
1235  struct sm_submit_result* submit_result = NULL;
1236 
1237  unsigned char tmp[1024],tmpgsm[1024];
1238  int octetlen, iret, iusedbyte;
1239  int imsgtopseg = 0, imsgfollownum = 0, imsgencodetype = 0;
1240  unsigned char cmsgtype, cmsgcontinuebyte;
1241 
1242  /* message type */
1243  if(strlen(octsrc) <= 4) goto no_msg;
1244 
1245  /* check if we support this type */
1246  cmsgtype = *octsrc;
1247  if(cmsgtype != 's' /* invoke reseult */
1248  && cmsgtype != 'M' /* deliver invoke */
1249  && cmsgtype != 'T'){ /* report invoke */
1250  info(0,"sema_decode: msg type not supported");
1251  goto error_msg;
1252  }
1253 
1254  /*check if continue bit is correct */
1255  cmsgcontinuebyte = *(octsrc+1);
1256  iret = unpack_continous_byte(cmsgcontinuebyte,
1257  &imsgencodetype,&imsgtopseg, &imsgfollownum);
1258 
1259  if(iret == -1){
1260  info(0,"sema_decode: msg continue bit can not be interpreted");
1261  goto error_msg;
1262  }
1263 
1264  /*status report and submit result will always be 1 segments
1265  for deliver invoke, if smsc can not send all the data in one packet,
1266  text data will be truncated ,so it's also 1 packet*/
1267 
1268  if(imsgtopseg == 0){
1269  info(0, "sema_decode: can not interpret more than one segments msg");
1270  goto error_msg;
1271  }
1272 
1273  (*desmsg)->type = cmsgtype;
1274  (*desmsg)->continuebyte = cmsgcontinuebyte;
1275  (*desmsg)->encodetype = imsgencodetype;
1276 
1277  /*operation reference*/
1278 
1279  memcpy((*desmsg)->optref, octsrc +2, 4);
1280  octsrc += 6;
1281  iusedbyte = 0;
1282 
1283  switch(cmsgtype){
1284  case 's': /* submit invoke result */
1285  submit_result = gw_malloc(sizeof(struct sm_submit_result));
1286  memset(submit_result,0,sizeof(struct sm_submit_result));
1287 
1288  /* result */
1289  iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
1290  if(iusedbyte < 1) goto error_submit;
1291  octetlen = 1;
1292  submit_result->smeresult = get_variable_value(tmp, &octetlen);
1293  if(submit_result->smeresult == SM_RESULT_SUCCESS)
1294  {
1295  /*smsc reference number*/
1296  octsrc += iusedbyte;
1297  iusedbyte = line_scan_IA5_hex(octsrc, 4,tmp);
1298  if(iusedbyte <1) goto error_submit;
1299  memcpy(submit_result->smscrefnum, tmp, 4);
1300  /*accept time*/
1301  octsrc += iusedbyte;
1302  iusedbyte = line_scan_IA5_hex(octsrc, 14,tmp);
1303  if(iusedbyte < 1) goto error_submit;
1304  memcpy(submit_result->accepttime, tmp, 4);
1305  }
1306  (*desmsg)->msgbody = submit_result;
1307  break;
1308  case 'M':
1309  /* deliver invoke*/
1310  receive_sm = gw_malloc(sizeof(struct sm_deliver_invoke));
1311  memset(receive_sm, 0, sizeof(struct sm_deliver_invoke));
1312  /*deliver destination address length*/
1313  iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
1314  if(iusedbyte < 1) goto error_deliver;
1315  octetlen = 1;
1316  receive_sm->destaddlen = get_variable_value(tmp, &octetlen);
1317  /*deliver destination address*/
1318  octsrc +=iusedbyte;
1319  iusedbyte = line_scan_IA5_hex(octsrc,receive_sm->destaddlen,tmp);
1320  if(iusedbyte < 1) goto error_deliver;
1321  receive_sm->destadd= octstr_create_from_data((char *)tmp, receive_sm->destaddlen);
1322  /*smsc reference number*/
1323  octsrc +=iusedbyte;
1324  iusedbyte = line_scan_IA5_hex(octsrc, 4,tmp);
1325  if(iusedbyte < 1) goto error_deliver;
1326  memcpy(receive_sm->smscrefnum, tmp, 4);
1327  /*originate address length*/
1328  octsrc +=iusedbyte;
1329  iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
1330  if(iusedbyte < 1) goto error_deliver;
1331  octetlen = 1;
1332  receive_sm->origaddlen = get_variable_value(tmp, &octetlen);
1333  /*originate address*/
1334  octsrc +=iusedbyte;
1335  iusedbyte = line_scan_IA5_hex(octsrc, receive_sm->origaddlen, tmp);
1336  if(iusedbyte < 1) goto error_deliver;
1337  receive_sm->origadd= octstr_create_from_data((char *)tmp,receive_sm->origaddlen);
1338  /* data code scheme */
1339  octsrc +=iusedbyte;
1340  if(iusedbyte < 1) goto error_deliver;
1341  iusedbyte = line_scan_IA5_hex(octsrc, 1,tmp);
1342  octetlen = 1;
1343  receive_sm->DCS = get_variable_value(tmp, &octetlen);
1344  if(receive_sm->DCS != ENCODE_IA5 && receive_sm->DCS !=ENCODE_GSM){
1345  info(0, "sema_decode, Data encoding scheme not supported");
1346  goto error_deliver;
1347  }
1348  /* protocol */
1349  octsrc +=iusedbyte;
1350  iusedbyte = line_scan_IA5_hex(octsrc, 1,tmp);
1351  if(iusedbyte < 1) goto error_deliver;
1352  octetlen = 1;
1353  receive_sm->protocal = get_variable_value(tmp, &octetlen);
1354  /* reply path */
1355  octsrc +=iusedbyte;
1356  iusedbyte = line_scan_IA5_hex(octsrc, 1,tmp);
1357  if(iusedbyte < 1) goto error_deliver;
1358  octetlen = 1;
1359  receive_sm->replypath = get_variable_value(tmp, &octetlen);
1360  /*text size in septect*/
1361  octsrc +=iusedbyte;
1362  iusedbyte = internal_char_IA5_to_hex(octsrc, tmp);
1363  if(iusedbyte < 1) goto error_deliver;
1364  receive_sm->textsizeseptet = tmp[0];
1365  /*text size in octects*/
1366  octsrc +=iusedbyte;
1367  iusedbyte = internal_char_IA5_to_hex(octsrc, tmp);
1368  if(iusedbyte < 1) goto error_deliver;
1369  receive_sm->textsizeoctect = tmp[0];
1370  octsrc+=iusedbyte;
1371 
1372  /*message text*/
1373 
1374  iusedbyte = 0;
1375  memset(tmp,0,sizeof(tmp));
1376  if(receive_sm->DCS == ENCODE_IA5 && receive_sm->textsizeoctect > 0)
1377  {
1378  iusedbyte = line_scan_IA5_hex(octsrc,receive_sm->textsizeoctect,tmp);
1379  if(iusedbyte < 1) goto error_deliver;
1380  receive_sm->shortmsg =octstr_create_from_data( (char *)tmp,receive_sm->textsizeoctect);
1381  }
1382  else if(receive_sm->DCS == ENCODE_GSM && receive_sm->textsizeseptet > 0)
1383  {
1384  memset(tmpgsm,0,sizeof(tmpgsm));
1385 
1386  iusedbyte = line_scan_IA5_hex(octsrc,receive_sm->textsizeoctect,tmp);
1387  if(iusedbyte < 1) goto error_deliver;
1388  line_scan_hex_GSM7(tmp,receive_sm->textsizeoctect,
1389  receive_sm->textsizeseptet, tmpgsm);
1390  receive_sm->shortmsg = octstr_create_from_data((char *)tmpgsm,
1391  receive_sm->textsizeseptet);
1392 
1393  }
1394  else if(receive_sm->textsizeoctect <= 0)
1395  receive_sm->shortmsg = octstr_create("");
1396 
1397  /*accepttime*/
1398  octsrc +=iusedbyte;
1399  iusedbyte = line_scan_IA5_hex(octsrc,14,tmp);
1400  if(iusedbyte < 1) goto error_deliver;
1401  memcpy(receive_sm->accepttime, tmp,14);
1402  /*valid time*/
1403  octsrc +=iusedbyte;
1404  iusedbyte = line_scan_IA5_hex(octsrc,14,tmp);
1405  if(iusedbyte < 1) goto error_deliver;
1406  memcpy(receive_sm->invoketime, tmp,14);
1407  (*desmsg)->msgbody = receive_sm;
1408  break;
1409  case 'T':
1410  /* status report invoke */
1411  receive_report = gw_malloc(sizeof(struct sm_statusreport_invoke));
1412  memset(receive_report,0,sizeof(struct sm_statusreport_invoke));
1413  /*deliver msisdn address length*/
1414  iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
1415  if(iusedbyte < 1) goto error_receive;
1416  octetlen = 1;
1417  receive_report->msisdnlen = get_variable_value(tmp, &octetlen);
1418  /*msisdn*/
1419  octsrc += iusedbyte;
1420  iusedbyte = line_scan_IA5_hex(octsrc, receive_report->msisdnlen, tmp);
1421  if(iusedbyte < 1) goto error_receive;
1422  receive_report->msisdn = octstr_create_from_data( (char *)tmp,receive_report->msisdnlen);
1423  /*sme reference type*/
1424  octsrc += iusedbyte;
1425  iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
1426  if(iusedbyte < 1) goto error_receive;
1427  octetlen = 1;
1428  receive_report->smetype = get_variable_value(tmp, &octetlen);
1429  /*sme reference number */
1430  octsrc += iusedbyte;
1431  iusedbyte = line_scan_IA5_hex(octsrc,4, tmp);
1432  if(iusedbyte < 1) goto error_receive;
1433  memcpy(receive_report->smerefnum ,tmp, 4);
1434  /*smsc reference number */
1435  octsrc += iusedbyte;
1436  iusedbyte = line_scan_IA5_hex(octsrc,4, tmp);
1437  if(iusedbyte < 1) goto error_receive;
1438  memcpy(receive_report->smscrefnum ,tmp, 4);
1439  /*accepted time*/
1440  octsrc += iusedbyte;
1441  iusedbyte = line_scan_IA5_hex(octsrc,14, tmp);
1442  if(iusedbyte < 1) goto error_receive;
1443  memcpy(receive_report->accepttime ,tmp, 4);
1444  /*status*/
1445  octsrc += iusedbyte;
1446  iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
1447  if(iusedbyte < 1) goto error_receive;
1448  octetlen = 1;
1449  receive_report->status = get_variable_value(tmp, &octetlen);
1450  octsrc += iusedbyte;
1451  if(receive_report->status != 6) /*6 means unable to deliver , but retry*/
1452  {
1453  iusedbyte = line_scan_IA5_hex(octsrc,14, tmp);
1454  if(iusedbyte < 1) goto error_receive;
1455  memcpy(receive_report->completetime ,tmp, 14);
1456  }
1457  else
1458  {
1459  iusedbyte = line_scan_IA5_hex(octsrc,14, tmp);
1460  if(iusedbyte < 1) goto error_receive;
1461  memcpy(receive_report->intermediatime ,tmp, 14);
1462  }
1463  if(receive_report->status == 6 || receive_report->status == 1) /*unable to deliver ,both case */
1464  {
1465  octsrc += iusedbyte;
1466  iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
1467  if(iusedbyte < 1) goto error_receive;
1468  octetlen = 1;
1469  receive_report->failreason = get_variable_value(tmp, &octetlen);
1470  }
1471  /*deliver orignate address length*/
1472  octsrc += iusedbyte;
1473  iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
1474  if(iusedbyte < 1) goto error_receive;
1475  octetlen = 1;
1476  receive_report->origaddlen = get_variable_value(tmp, &octetlen);
1477  /*orignate address*/
1478  octsrc += iusedbyte;
1479  iusedbyte = line_scan_IA5_hex(octsrc, receive_report->origaddlen, tmp);
1480  if(iusedbyte < 1) goto error_receive;
1481  receive_report->origadd = octstr_create_from_data((char *)tmp, receive_report->msisdnlen);
1482  /* invoke time */
1483  octsrc += iusedbyte;
1484  iusedbyte = line_scan_IA5_hex(octsrc,14, tmp);
1485  if(iusedbyte < 1){
1486  goto error_receive;
1487  }
1488  memcpy(receive_report->invoketime ,tmp, 14);
1489  (*desmsg)->msgbody = receive_report;
1490  break;
1491  }
1492  return 1;
1493 
1494 no_msg:
1495  info(0,"sema_decode: msg is empty");
1496  return 0;
1497 error_receive:
1498  gw_free(receive_report);
1499  goto error_msg;
1500 error_submit:
1501  gw_free(submit_result);
1502  goto error_msg;
1503 error_deliver:
1504  gw_free(receive_sm);
1505  goto error_msg;
1506 error_msg:
1507  info(0,"sema_decode:msg parameter is not recognized or unsupported");
1508  return 0;
1509 }
1510 
1511 
1512 static int sema_encode_msg(sema_msg* pmsg, char* str) {
1513  struct sm_submit_invoke *submit_sm = NULL;
1514  Octstr *IA5msg = NULL;
1515  int tSize = 0;
1516  unsigned char oc1byte[10];
1517  IA5msg = octstr_create("");
1518  switch(pmsg->type)
1519  {
1520  case 'S':
1521  submit_sm = (struct sm_submit_invoke *) pmsg->msgbody;
1522  write_variable_value(submit_sm->msisdnlen, oc1byte); /*msisdn len*/
1523  line_append_hex_IA5(IA5msg, oc1byte,1);
1524  line_append_hex_IA5(IA5msg,
1525  (unsigned char *)octstr_get_cstr(submit_sm->msisdn),
1526  octstr_len(submit_sm->msisdn)); /*msisdn*/
1527  write_variable_value(submit_sm->smereftype, oc1byte);/*smetype*/
1528  line_append_hex_IA5(IA5msg, oc1byte,1);
1529  line_append_hex_IA5(IA5msg, submit_sm->smerefnum,4);/*sme reference*/
1530  write_variable_value(submit_sm->priority, oc1byte);/*priority*/
1531  line_append_hex_IA5(IA5msg, oc1byte,1);
1532  write_variable_value(submit_sm->origaddlen, oc1byte); /*orignating address length*/
1533  line_append_hex_IA5(IA5msg, oc1byte,1);
1534  line_append_hex_IA5(IA5msg,
1535  (unsigned char *)octstr_get_cstr(submit_sm->origadd),
1536  octstr_len(submit_sm->origadd)); /*orignating address*/
1537  write_variable_value(submit_sm->validperiodtype, oc1byte); /*valid period type*/
1538  line_append_hex_IA5(IA5msg, oc1byte,1);
1539  write_variable_value(submit_sm->validperiodrela, oc1byte); /*relative period*/
1540  line_append_hex_IA5(IA5msg, oc1byte,1);
1541  write_variable_value(submit_sm->DCS, oc1byte);/*data code scheme*/
1542  line_append_hex_IA5(IA5msg, oc1byte,1);
1543  write_variable_value(submit_sm->statusreportrequest, oc1byte);/*request report*/
1544  line_append_hex_IA5(IA5msg, oc1byte,1);
1545  write_variable_value(submit_sm->protocal, oc1byte);/*protocal id*/
1546  line_append_hex_IA5(IA5msg, oc1byte, 1);
1547  write_variable_value(submit_sm->replypath, oc1byte);/*use reply path*/
1548  line_append_hex_IA5(IA5msg, oc1byte, 1);
1549 
1550  /*text size in 7 bits char*/
1551  tSize = internal_char_hex_to_IA5(submit_sm->textsizeseptet,oc1byte);
1552  octstr_insert_data(IA5msg, octstr_len(IA5msg), (char *)oc1byte, tSize);
1553 
1554  /*text size in 8 bits char*/
1555  tSize = internal_char_hex_to_IA5(submit_sm->textsizeoctect,oc1byte);
1556  octstr_insert_data(IA5msg, octstr_len(IA5msg),(char *) oc1byte, tSize);
1557 
1558  line_append_hex_IA5(IA5msg,
1559  (unsigned char *)octstr_get_cstr(submit_sm->shortmsg),
1560  submit_sm->textsizeoctect); /*msg text*/
1561  memcpy(str,octstr_get_cstr(IA5msg),octstr_len(IA5msg));
1562  octstr_destroy(IA5msg);
1563  return 1;
1564  }
1565  return 0;
1566 }
1567 
1568 
1569 static int line_scan_hex_GSM7(unsigned char* from,
1570  int octects ,int spetets, unsigned char* to)
1571 {
1572  char* cin2 =NULL;
1573  unsigned char c;
1574  char cin7[8];
1575  int i, pos, value;
1576 
1577  int lenin2=octects*8;
1578  cin2 = gw_malloc(lenin2);
1579 
1580  memset(cin2,48,lenin2); /*make many zeros*/
1581  /*tranverse the octects first, so ABC -> CBA(in bin form)*/
1582  for(i = 0; i < octects; i ++)
1583  {
1584  c = *(from + i);
1585 
1586  if(c & 1)
1587  cin2[(octects-1-i)*8 +7] = 49;
1588  if(c & 2)
1589  cin2[(octects-1-i)*8 +6] = 49;
1590  if(c & 4)
1591  cin2[(octects-1-i)*8 +5] = 49;
1592  if(c & 8)
1593  cin2[(octects-1-i)*8 +4] = 49;
1594  if(c & 16)
1595  cin2[(octects-1-i)*8 +3] = 49;
1596  if(c & 32)
1597  cin2[(octects-1-i)*8 +2] = 49;
1598  if(c & 64)
1599  cin2[(octects-1-i)*8 +1] = 49;
1600  if(c & 128)
1601  cin2[(octects-1-i)*8] = 49;
1602  }
1603 
1604  i= 1;
1605  while( i <= spetets ){
1606  pos=lenin2 -1 -(i*7 -1);
1607  memset(cin7,0,sizeof(cin7));
1608  memcpy(cin7, cin2 + pos, 7);
1609  value = 0;
1610 
1611  if(cin7[6] == '1')
1612  value += 1;
1613  if(cin7[5] == '1')
1614  value += 2;
1615  if(cin7[4] == '1')
1616  value += 4;
1617  if(cin7[3] == '1')
1618  value += 8;
1619  if(cin7[2] == '1')
1620  value += 16;
1621  if(cin7[1] == '1')
1622  value += 32;
1623  if(cin7[0] == '1')
1624  value += 64;
1625 
1626  to[i-1]=internal_char_hex_to_gsm(value);
1627  i +=1;
1628  }
1629  return i;
1630 
1631 }
1632 
1633 /* check SMS2000 Version 4.0 B.4.2.3 */
1634 static int line_append_hex_IA5(Octstr* des, unsigned char* src, int len)
1635 {
1636 
1637  unsigned char IA5char[3];
1638  unsigned char tmp[1024];
1639  int j=0;
1640  int i=0, iall=0;
1641  for(i=0; i<len; i++)
1642  {
1643  memset(IA5char, 0, sizeof(IA5char));
1644  j=internal_char_hex_to_IA5(*(src+i),IA5char);
1645  if(j >0){
1646  memcpy(tmp+iall,IA5char,j);
1647  iall += j;
1648  }
1649  }
1650  octstr_insert_data(des,octstr_len(des),(char *)tmp,iall);
1651  return iall;
1652 }
1653 
1654 
1655 /* check SMS2000 Version 4.0 B.4.2.3 */
1656 static int line_scan_IA5_hex(char* from,
1657  int hexnum, unsigned char* to)
1658 {
1659  unsigned char cha[1];
1660  int cn =0, cnall = 0, i = 0;
1661  char *tmpfrom = NULL;
1662  tmpfrom = from;
1663  for(i = 0; i< hexnum; i++)
1664  {
1665  cn=internal_char_IA5_to_hex(tmpfrom, cha);
1666  if(cn >0)
1667  {
1668  memcpy(to+i,cha,1);
1669  tmpfrom += cn;
1670  cnall += cn;
1671  }
1672  else
1673  return -1;
1674  }
1675  return cnall;
1676 }
1677 
1678 
1679 static unsigned char internal_char_hex_to_gsm(unsigned char from)
1680 {
1681  switch (from){
1682  case 0x00: return '@';
1683  case 0x01: return '£';
1684  case 0x02: return '$';
1685  case 0x03: return '¥';
1686  case 0x04: return 'è';
1687  case 0x05: return 'é';
1688  case 0x06: return 'ù';
1689  case 0x07: return 'ì';
1690  case 0x08: return 'ò';
1691  case 0x09: return 'Ç';
1692  case 0x0A: return '\n';
1693  case 0x0B: return 'Ø';
1694  case 0x0C: return 'ø';
1695  case 0x0D: return '\r';
1696  case 0x0E: return 'Å';
1697  case 0x0F: return 'å';
1698  case 0x10: return 'D';
1699  case 0x11: return ' ';
1700  case 0x12: return 'F';
1701  case 0x13: return 'G';
1702  case 0x14: return 'L';
1703  case 0x15: return 'W';
1704  case 0x16: return 'P';
1705  case 0x17: return 'Y';
1706  case 0x18: return 'S';
1707  case 0x19: return 'Q';
1708  case 0x1A: return 'X';
1709  case 0x1B: return ' ';
1710  case 0x1C: return 'Æ';
1711  case 0x1D: return 'æ';
1712  case 0x1E: return 'b';
1713  case 0x1F: return 'É';
1714  case 0x5B: return 'Ä';
1715  case 0x5C: return 'Ö';
1716  case 0x5D: return 'Ñ';
1717  case 0x5E: return 'Ü';
1718  case 0x5F: return '§';
1719  case 0x60: return '¿';
1720  case 0x7B: return 'a';
1721  case 0x7C: return 'ö';
1722  case 0x7D: return 'ñ';
1723  case 0x7E: return 'ü';
1724  case 0x7F: return 'à';
1725  default: return from;
1726  }
1727 }
1728 
1729 /* check SMS2000 Version 4.0 B.4.2.3 */
1730 static int internal_char_hex_to_IA5(unsigned char from, unsigned char * to){
1731 
1732  if(from <= 0x1F)
1733  {
1734  to[0] = '^';
1735  to[1] = 0x40 + from;
1736  return 2;
1737  }
1738  else if(from ==0x5C)
1739  {
1740  to[0] = 0x5C;
1741  to[1] = 0x5C;
1742  return 2;
1743  }
1744  else if(from == 0x5E)
1745  {
1746  to[0] = 0x5C;
1747  to[1] = 0x5E;
1748  return 2;
1749  }
1750  else if(from == 0x60)
1751  {
1752  to[0] = 0x5C;
1753  to[1] = 0x60;
1754  return 2;
1755  }
1756  else if(from == 0x7E)
1757  {
1758  to[0] = 0x5C;
1759  to[1] = 0x7E;
1760  return 2;
1761  }
1762  else if(from >= 0x20 && from <= 0x7E)
1763  {
1764  to [0] = from;
1765  return 1;
1766  }
1767  else if(from == 0x7F)
1768  {
1769  to[0] = 0x5E;
1770  to[1] = 0x7E;
1771  return 2;
1772  }
1773  else if(from >= 0x80 && from <=0x9F)
1774  {
1775  to[0] = 0x7E;
1776  to[1] = from -0x40;
1777  return 2;
1778  }
1779  else if(from >= 0xA0 && from <=0xFE)
1780  {
1781  to[0] = 0x60;
1782  to[1] = from -0x80;
1783  return 2;
1784  }
1785  else if(from == 0xFF)
1786  {
1787  to[0] =to[1] = 0x7E;
1788  return 2;
1789  }
1790  else
1791 
1792  return -1;
1793 }
1794 
1795 static int internal_char_IA5_to_hex(char *from, unsigned char * to){
1796  int ret = -1;
1797  int len = strlen(from);
1798 
1799  if(*from == '^' && len >= 2 &&
1800  *(from +1) == '~')
1801  {
1802  *to = 0x7F;
1803  ret = 2;
1804  }
1805  else if(*from ==0x5C && len >= 2 &&
1806  *(from +1) == 0x5C)
1807  {
1808  *to= 0x5C;
1809  ret = 2;
1810  }
1811  else if(*from == 0x5C && len >= 2 &&
1812  *(from+1) == 0x5E)
1813  {
1814  *to= 0x5E;
1815  ret = 2;
1816  }
1817  else if(*from == 0x5C && len >= 2 &&
1818  *(from+1) == 0x60)
1819  {
1820  *to= 0x60;
1821  ret = 2;
1822  }
1823  else if(*from == 0x5C && len >=2 &&
1824  *(from+1) == 0x7E)
1825  {
1826  *to= 0x7E;
1827  ret = 2;
1828  }
1829  else if(*from == '^' && len >= 2 &&
1830  (*(from +1) >= 0x40 && *(from +1) <= 0x5F))
1831  {
1832  *to = *(from +1) -0x40;
1833  ret = 2;
1834  }
1835  else if(*from == '~' && len >= 2 &&
1836  (*(from +1) >= 0x40 && *(from +1) <= 0x5F))
1837  {
1838  *to = *(from +1) +0x40;
1839  ret = 2;
1840  }
1841  else if(*from == '`' && len >= 2 &&
1842  (*(from+1) >= 0x20 && *(from +1) <= 0x7E))
1843  {
1844  *to = *(from +1) +0x80;
1845  ret = 2;
1846  }
1847  else if(*from >=0x20 &&
1848  *from <=0x7E)
1849  {
1850  *to= *from;
1851  ret = 1;
1852  }
1853 
1854  return ret;
1855 }
1856 
1857 
1858 static void increment_counter(void)
1859 {
1860  if(sema_counter[3] == 0x39)
1861  sema_counter[3] = 0x30;
1862  else
1863  {
1864  sema_counter[3] += 0x01;
1865  return;
1866  }
1867  if(sema_counter[2] == 0x39)
1868  sema_counter[2] = 0x30;
1869  else
1870  {
1871  sema_counter[2] += 0x01;
1872  return;
1873  }
1874  if(sema_counter[1] == 0x39)
1875  sema_counter[1] = 0x30;
1876  else
1877  {
1878  sema_counter[1] += 0x01;
1879  return;
1880  }
1881  if(sema_counter[0] == 0x39)
1882  sema_counter[0] = 0x30;
1883  else
1884  sema_counter[0] += 0x01;
1885  return;
1886 }
1887 
1888 /* check SMS2000 Version 4.0 B.4.2.2 */
1889 static unsigned char pack_continous_byte(int encode,
1890  int isfirst, int follownum)
1891 {
1892  char bin[4];
1893  int value;
1894 
1895  memset(bin, 0, 4);
1896  value = 0;
1897 
1898  if(isfirst == 1)
1899  strncpy(bin,"0101",4);
1900  else
1901  strncpy(bin,"0110",4);
1902 
1903  if(bin[3] == '1')
1904  value += 16;
1905  if(bin[2] == '1')
1906  value += 32;
1907  if(bin[1] == '1')
1908  value += 64;
1909  if(bin[0] == '1') /* although it's impossible */
1910  value += 128;
1911  return (value+follownum);
1912 }
1913 
1914 /* check SMS2000 Version 4.0 B.4.2.2 */
1915 static int unpack_continous_byte(unsigned char continueCount,
1916  int * encode,
1917  int * isfirst,
1918  int * follownum)
1919 {
1920  int rest = 0;
1921  int head = 0;
1922 
1923  if(continueCount & 1)
1924  rest +=1;
1925  if(continueCount & 2)
1926  rest +=2;
1927  if(continueCount & 4)
1928  rest += 4;
1929  if(continueCount & 8)
1930  rest += 8;
1931 
1932  *follownum = rest;
1933 
1934  if(continueCount & 16)
1935  head += 1;
1936 
1937  if(continueCount & 32)
1938  head += 2;
1939 
1940  if(continueCount & 64)
1941  head += 4;
1942 
1943  if(continueCount & 128) /* though not possible */
1944  head += 8;
1945 
1946 
1947  *encode = *isfirst = -1;
1948 
1949  if(head == 5)
1950  {
1951  *encode =LINE_ENCODE_IA5;
1952  *isfirst = 1;
1953  }
1954  else if(head == 6)
1955  {
1956  *encode =LINE_ENCODE_IA5;
1957  *isfirst = 0;
1958  }
1959  else if(head == 4)
1960  {
1961  *encode =LINE_ENCODE_HEX;
1962  *isfirst = 1;
1963  }
1964  else if(head == 3)
1965  {
1966  *encode =LINE_ENCODE_HEX;
1967  *isfirst = 0;
1968  }
1969  else if(head == 7)
1970  {
1971  *encode =LINE_ENCODE_BIN;
1972  *isfirst = 1;
1973  }
1974  else if(head == 2)
1975  {
1976  *encode =LINE_ENCODE_BIN;
1977  *isfirst = 0;
1978  }
1979  if(*encode != -1 && *isfirst != -1)
1980  return 0;
1981  else
1982  return -1;
1983 }
1984 
#define SM_RESULT_SUCCESS
Definition: smsc_sema.h:64
#define SESSION_MT_RECEIVE_ERR
Definition: smsc_sema.h:105
Octstr * shortmsg
Definition: smsc_sema.h:216
int sema_reopen(SMSCenter *smsc)
Definition: smsc_sema.c:162
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
unsigned int statusreportrequest
Definition: smsc_sema.h:185
char invoketime[14]
Definition: smsc_sema.h:218
struct sema_msg * next
Definition: smsc_sema.h:126
static int line_scan_hex_GSM7(unsigned char *from, int octects, int spetets, unsigned char *to)
Definition: smsc_sema.c:1569
unsigned int textsizeoctect
Definition: smsc_sema.h:215
unsigned int textsizeoctect
Definition: smsc_sema.h:191
#define INTERNAL_CONNECT_TIMEVAL
Definition: smsc_sema.h:102
Octstr * destadd
Definition: smsc_sema.h:205
#define LINE_ENCODE_IA5
Definition: smsc_sema.h:92
static int X28_close_send_link(int padfd)
Definition: smsc_sema.c:564
#define INTERNAL_DISCONNECT_TIMEVAL
Definition: smsc_sema.h:100
struct sema_msglist * sema_mo
Definition: smsc_p.h:166
unsigned int origaddlen
Definition: smsc_sema.h:177
unsigned int replypath
Definition: smsc_sema.h:213
unsigned int smereftype
Definition: smsc_sema.h:174
int sema_fd
Definition: smsc_p.h:167
unsigned char optref[4]
Definition: smsc_sema.h:120
static int sema_msg_session_mt(SMSCenter *smsc, sema_msg *pmsg)
Definition: smsc_sema.c:940
unsigned int protocal
Definition: smsc_sema.h:212
static int line_scan_IA5_hex(char *from, int hexnum, unsigned char *to)
Definition: smsc_sema.c:1656
msg_type
Definition: msg.h:73
#define CRTSCTS
Definition: smsc_sema.c:105
unsigned int validperiodtype
Definition: smsc_sema.h:180
#define DC_8BIT
Definition: sms.h:111
static void sema_msglist_free(sema_msglist *mlist)
Definition: smsc_sema.c:440
unsigned char smerefnum[4]
Definition: smsc_sema.h:147
unsigned char smscrefnum[4]
Definition: smsc_sema.h:194
#define msg_create(type)
Definition: msg.h:136
struct sema_msg * prev
Definition: smsc_sema.h:126
void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
Definition: octstr.c:1461
unsigned int validperiodrela
Definition: smsc_sema.h:182
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
#define INTERNAL_SESSION_MT_TIMEVAL
Definition: smsc_sema.h:103
#define LINE_ENCODE_BIN
Definition: smsc_sema.h:94
static int sema_msg_session_mo(SMSCenter *smsc, char *cbuff)
Definition: smsc_sema.c:1173
unsigned int smeresult
Definition: smsc_sema.h:162
char accepttime[14]
Definition: smsc_sema.h:217
static int sema_msglist_pop(sema_msglist *plist, sema_msg **msg)
Definition: smsc_sema.c:487
#define ENCODE_IA5
Definition: smsc_sema.h:87
static Octstr * from
Definition: mtbatch.c:95
unsigned int priority
Definition: smsc_sema.h:176
static int X28_data_read(int padfd, char *cbuffer)
Definition: smsc_sema.c:713
static unsigned char internal_char_hex_to_gsm(unsigned char from)
Definition: smsc_sema.c:1679
unsigned char smscrefnum[4]
Definition: smsc_sema.h:167
unsigned char type
Definition: smsc_sema.h:118
Definition: msg.h:79
static int X28_msg_pop(char *from, char *to)
Definition: smsc_sema.c:804
static int sema_msglist_push(sema_msglist *plist, sema_msg *pmsg)
Definition: smsc_sema.c:453
Octstr * content
Definition: smsc_sema.h:112
static void increment_counter(void)
Definition: smsc_sema.c:1858
Octstr * origadd
Definition: smsc_sema.h:208
unsigned int msisdnlen
Definition: smsc_sema.h:172
static int sema_encode_msg(sema_msg *pmsg, char *str)
Definition: smsc_sema.c:1512
Octstr * msisdn
Definition: smsc_sema.h:173
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define SESSION_MT_RECEIVE_SUCCESS
Definition: smsc_sema.h:107
static unsigned char sema_counter[4]
Definition: smsc_sema.c:109
SMSCenter * smscenter_construct(void)
Definition: smsc.c:101
int sema_close(SMSCenter *smsc)
Definition: smsc_sema.c:199
int encodetype
Definition: smsc_sema.h:121
unsigned int protocal
Definition: smsc_sema.h:188
void warning(int err, const char *fmt,...)
Definition: log.c:660
void smscenter_destruct(SMSCenter *smsc)
Definition: smsc.c:168
unsigned int textsizeseptet
Definition: smsc_sema.h:190
static int sema_submit_result(SMSCenter *smsc, sema_msg *srcmsg, int result)
Definition: smsc_sema.c:896
int sema_submit_msg(SMSCenter *smsc, Msg *msg)
Definition: smsc_sema.c:210
unsigned int failreason
Definition: smsc_sema.h:153
unsigned int status
Definition: smsc_sema.h:150
unsigned int DCS
Definition: smsc_sema.h:184
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
Octstr * origadd
Definition: smsc_sema.h:178
unsigned int textsizeseptet
Definition: smsc_sema.h:214
#define octstr_create(cstr)
Definition: octstr.h:125
char * sema_smscnua
Definition: smsc_p.h:163
unsigned int origaddlen
Definition: smsc_sema.h:154
int sema_receive_msg(SMSCenter *smsc, Msg **msg)
Definition: smsc_sema.c:323
static sema_msglist * sema_msglist_new(void)
Definition: smsc_sema.c:428
#define X28_COMMAND_MODE
Definition: smsc_sema.h:96
static int sema_wait_report
Definition: smsc_sema.c:110
char * sema_serialdevice
Definition: smsc_p.h:165
#define ENCODE_GSM
Definition: smsc_sema.h:88
static unsigned char pack_continous_byte(int encode, int isfirst, int follownum)
Definition: smsc_sema.c:1889
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
struct sema_msglist * sema_mt
Definition: smsc_p.h:166
unsigned int origaddlen
Definition: smsc_sema.h:207
#define LINE_ENCODE_HEX
Definition: smsc_sema.h:93
static int unpack_continous_byte(unsigned char continueCount, int *encode, int *isfirst, int *follownum)
Definition: smsc_sema.c:1915
#define X28_MT_DATA_MODE
Definition: smsc_sema.h:97
Definition: octstr.c:118
unsigned int replypath
Definition: smsc_sema.h:189
char accepttime[14]
Definition: smsc_sema.h:168
unsigned int msisdnlen
Definition: smsc_sema.h:144
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
char * sema_homenua
Definition: smsc_p.h:164
unsigned int DCS
Definition: smsc_sema.h:211
int type
Definition: smsc_p.h:93
char * buffer
Definition: smsc_p.h:184
static int X28_open_data_link(char *device)
Definition: smsc_sema.c:518
SMSCenter * sema_open(char *smscnua, char *homenua, char *serialdevice, int waitreport)
Definition: smsc_sema.c:113
static int internal_char_hex_to_IA5(unsigned char from, unsigned char *to)
Definition: smsc_sema.c:1730
#define X28_MO_DATA_MODE
Definition: smsc_sema.h:98
MultibyteInt get_variable_value(Octet *source, int *len)
Definition: utils.c:477
static int internal_char_IA5_to_hex(char *from, unsigned char *to)
Definition: smsc_sema.c:1795
unsigned char smscrefnum[4]
Definition: smsc_sema.h:148
unsigned int destaddlen
Definition: smsc_sema.h:204
void kannel_cfmakeraw(struct termios *tio)
Definition: utils.c:951
void * msgbody
Definition: smsc_sema.h:124
unsigned char smerefnum[4]
Definition: smsc_sema.h:175
int write_variable_value(MultibyteInt value, Octet *dest)
Definition: utils.c:490
sema_msg * first
Definition: smsc_sema.h:132
static int sema_msg_free(sema_msg *msg)
Definition: smsc_sema.c:422
unsigned int smetype
Definition: smsc_sema.h:146
static int X28_open_send_link(int padfd, char *nua)
Definition: smsc_sema.c:611
unsigned char smscrefnum[4]
Definition: smsc_sema.h:206
static int X28_data_send(int padfd, char *cbuffer, int sentonce)
Definition: smsc_sema.c:771
static int sema_decode_msg(sema_msg **desmsg, char *octsrc)
Definition: smsc_sema.c:1232
static sema_msg * sema_msg_new(void)
Definition: smsc_sema.c:414
char name[1024]
Definition: smsc_p.h:96
Octstr * shortmsg
Definition: smsc_sema.h:192
#define octstr_create_from_data(data, len)
Definition: octstr.h:134
static int line_append_hex_IA5(Octstr *des, unsigned char *src, int len)
Definition: smsc_sema.c:1634
static int x28_data_mode
Definition: smsc_sema.c:111
#define SESSION_MT_RECEIVE_TIMEOUT
Definition: smsc_sema.h:106
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
static int X28_reopen_data_link(int oldpadfd, char *device)
Definition: smsc_sema.c:551
int sema_pending_smsmessage(SMSCenter *smsc)
Definition: smsc_sema.c:365
sema_msg * last
Definition: smsc_sema.h:133
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.