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

手机WAP编程

开发平台:

WINDOWS

  1.  /*
  2.  * smsc_sema.c - implement sms2000 protocal by using X25 access
  3.  * the data communication layer is implemented by using X28 protocol
  4.  * 
  5.  * Code implement submit invoke, status invoke, deliver invoke session
  6.  * there is no internal db for storing delivered and undelivered message
  7.  * 
  8.  * IA5 is most common line coding scheme. 
  9.  * smsc_sema support only IA5 encoding, hex and binary line encoding is not
  10.  * supported.
  11.  * 
  12.  * smsc_sema support IA5 and GSM Data Code Scheme for delivered invoke message
  13.  * smsc_sema support only IA5 Data Code Scheme for submit invoke message
  14.  *  
  15.  * Reference : SMS2000 Version 4.0 Open Interface Specification
  16.  *             Open Source WAP Gateway Architecture Design 
  17.  *             ESTI GSM 03.40
  18.  *
  19.  * Hao Shi 2000
  20.  */
  21. #include <errno.h>
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <fcntl.h>
  28. #include <termios.h>
  29. #include <sys/time.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <sys/param.h>
  33. #include <netinet/in.h>
  34. #include <netdb.h>
  35. #include "gwlib/gwlib.h"
  36. #include "smsc.h"
  37. #include "smsc_p.h"
  38. #include "alt_charsets.h"
  39. #include "smsc_sema.h"
  40. #include "sms.h"
  41. #ifndef CRTSCTS
  42. #define CRTSCTS 0
  43. #endif
  44. static unsigned char sema_counter[4] = "0000";
  45. static int sema_wait_report = 1;
  46. static int x28_data_mode = X28_COMMAND_MODE;
  47. SMSCenter * sema_open(char* smscnua, char* homenua, 
  48.       char* serialdevice, int waitreport)
  49. {
  50. SMSCenter *smsc;
  51. int nret = -1;
  52. smsc = smscenter_construct();
  53. if(smsc == NULL)
  54.   goto error;
  55. sprintf(smsc->name, "SEMA:X28:"); 
  56. smsc->type = SMSC_TYPE_SEMA_X28;
  57. smsc->sema_smscnua = gw_strdup(smscnua);
  58. smsc->sema_homenua = gw_strdup(homenua);
  59. smsc->sema_serialdevice = gw_strdup(serialdevice);
  60. sema_wait_report = waitreport;
  61. smsc->sema_mt = sema_msglist_new();
  62. if(smsc->sema_mt == NULL) goto error;
  63. smsc->sema_mo = sema_msglist_new();
  64. if(smsc->sema_mo == NULL) goto error;
  65. /* Open the device properly. Remember to set the
  66.    access codes correctly. */
  67. debug("smsc.sema", 0, "sema_open: open datalink");
  68. smsc->sema_fd = X28_open_data_link(smsc->sema_serialdevice);
  69. if(smsc->sema_fd == -1) goto error;
  70. /*  test the outgoing callX28 to smsc center */
  71.         debug("smsc.sema", 0, "sema_open: test send link");
  72. nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua);
  73. if(nret < 1){
  74.   sleep(2);
  75.   nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua);  
  76.   if(nret < 1)
  77.     goto error;
  78. }
  79. X28_close_send_link(smsc->sema_fd);
  80. return smsc;
  81. error:
  82. error(0, "sema_open: could not open");
  83. smscenter_destruct(smsc);
  84. return NULL;
  85. }
  86. int sema_reopen(SMSCenter *smsc)
  87. {
  88.     int nret = 0;
  89.     debug("smsc.sema", 0, "reopening the connection");
  90.     /*deallocate*/
  91.     sema_msglist_free(smsc->sema_mt);
  92.     sema_msglist_free(smsc->sema_mo);
  93.     /*reallocate*/
  94.     smsc->sema_mt = sema_msglist_new();
  95.     if(smsc->sema_mt == NULL) goto error;
  96.     smsc->sema_mo = sema_msglist_new();
  97.     if(smsc->sema_mo == NULL) goto error;
  98.     memset(smsc->buffer,0,sizeof(smsc->buffer));
  99.     /* Open the device properly. Remember to set the
  100.      access codes correctly. */
  101.     smsc->sema_fd = X28_reopen_data_link(smsc->sema_fd, smsc->sema_serialdevice);
  102.     if(smsc->sema_fd == -1){
  103. error(0,"sema_reopen_data_link: device file error");
  104. goto error;
  105.     }
  106.     /*test outgoing call to the smsc */
  107.     nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua);
  108.     if(nret < 1){
  109. error(0,"test send data link failed");
  110. goto error;
  111.     }
  112.     X28_close_send_link(smsc->sema_fd);
  113.     return 0;
  114. error:
  115.     error(0, "sema_reopen_data_link: failed");
  116.     return -1;
  117.   
  118. }
  119. int sema_close(SMSCenter *smsc)
  120. {
  121.     if(smsc->sema_fd > 0)
  122. close(smsc->sema_fd);
  123.     /*deallocate*/
  124.     sema_msglist_free(smsc->sema_mt);
  125.     sema_msglist_free(smsc->sema_mo);
  126.     return 0;
  127. }
  128. int sema_submit_msg(SMSCenter *smsc, Msg *msg)
  129. {
  130.         int nret = 0;
  131.         struct sema_msg *lmsg = NULL;
  132. struct sm_submit_invoke *submit_sm = NULL;
  133. char x28sender[2] = "A3";
  134.         
  135. /* Validate msg */
  136. if(smsc == NULL){
  137.     error(0,"sema_submit_msg: SMSC is empty");
  138.     goto error;
  139. }
  140. if(msg == NULL){
  141.     error(0, "sema_submit_msg: Msg is empty");
  142.     goto error;
  143. }
  144. if(msg_type(msg) != sms) {
  145.     error(0, "sema_submit_sms: Msg is WRONG TYPE");
  146.     goto error;
  147. }
  148. /*  user data header is not supported in sm2000 X25 access
  149.     if(msg->sms.coding == DC_7BIT){
  150.     error(0, "sema_submit_sms: submit invoke support in IA5 encoding(8 bits chars)");
  151.     goto error;
  152.     }
  153.     if(octstr_len(msg->sms.udhdata)){
  154.     error(0, "sema_submit_sms: submit invoke not support in IA5 encoding ");
  155.     goto error;
  156.     }
  157. */
  158. lmsg = sema_msg_new();
  159. submit_sm = gw_malloc(sizeof(struct sm_submit_invoke));
  160. memset(submit_sm, 0, sizeof(struct sm_submit_invoke));
  161. lmsg->type = 'S';
  162. lmsg->encodetype = LINE_ENCODE_IA5;
  163. /* set operation reference */
  164. increment_counter();
  165. memcpy(lmsg->optref,sema_counter,4);
  166. /*set sme reference number*/
  167. increment_counter();
  168. memcpy(submit_sm->smerefnum, sema_counter, 4);
  169. /*we send as not key type*/
  170. submit_sm->smereftype= 2; /*key type is 1*/
  171. /*we set prority as normal*/
  172. submit_sm->priority = 1; /*0 is high*/ 
  173. /*set valid period type as relative*/
  174. submit_sm->validperiodtype = 2; /* 1 is absolute */
  175. /*time*/
  176. submit_sm->validperiodrela = 1; /* from 0 to 143 , fomula is (V+1)*5 min*/
  177. /*send msg without 00 header*/
  178. submit_sm->msisdnlen= octstr_len(msg->sms.receiver);
  179. submit_sm->msisdn = octstr_copy(msg->sms.receiver,0,submit_sm->msisdnlen);
  180. /* X25 access will always append sender during data transfer */
  181. submit_sm->origaddlen= 2; /* we need only to orignate address type */
  182. submit_sm->origadd = octstr_create_from_data(x28sender,2);
  183. /*data encoding scheme ,support only IA5 in current version*/
  184. submit_sm->DCS = 15; /*gsm is 0 ,IA5 is 15*/
  185. /*protocal ,support only default value  0 in current version*/ 
  186. submit_sm->protocal = 0;
  187. /*replypath*/
  188. submit_sm->replypath= 0; /*gateway do not pay for reply*/
  189. /*status report*/
  190. if(sema_wait_report > 0)
  191.     submit_sm->statusreportrequest =4; /* deliver success, in bin form 00000100*/
  192. else
  193.     submit_sm->statusreportrequest = 0;/* no report */
  194. /* we support submit invoke only in IA5 line encoding*/
  195. submit_sm->textsizeoctect = submit_sm->textsizeseptet =
  196. octstr_len(msg->sms.msgdata);
  197. /*copy msg buffer*/
  198. submit_sm->shortmsg = octstr_copy(msg->sms.msgdata,
  199.   0, submit_sm->textsizeoctect);
  200. memset(submit_sm->smscrefnum,0,sizeof(submit_sm->smscrefnum));
  201.         /*pack the message body in 2kmsg*/
  202. lmsg->msgbody = (void**)(&submit_sm);
  203. nret = sema_msg_session_mt(smsc, lmsg);
  204. gw_free(submit_sm);
  205. submit_sm = NULL;
  206. sema_msg_free(lmsg);
  207. lmsg = NULL;
  208. if(nret == SESSION_MT_RECEIVE_SUCCESS){
  209.     debug("smsc.sema", 0, "sema_submit_msg: message is successfully delivered");
  210.     return 1; /*success*/
  211. }
  212. else if(nret == SESSION_MT_RECEIVE_TIMEOUT){
  213.     info(0, "sema_submit msg: session time out without return");
  214.     return 0;
  215. }
  216. else if(nret == SESSION_MT_RECEIVE_ERR){
  217.     info(0, "sema_submit msg: smsc say submit failed!");
  218.     return 0;
  219. }
  220. return 1;
  221. error:
  222. if(submit_sm)
  223.     gw_free(submit_sm);
  224. if(lmsg)
  225.     sema_msg_free(lmsg);
  226. return -1;
  227. }
  228. int sema_receive_msg(SMSCenter *smsc, Msg **msg)
  229. {
  230.     struct sema_msg *rmsg = NULL;
  231.     struct sm_deliver_invoke *recieve_sm = NULL;
  232.  
  233.     while(sema_msglist_pop(smsc->sema_mo, &rmsg) == 1 ) {
  234.   
  235. *msg = msg_create(sms);
  236. if(*msg==NULL) goto error;
  237.     
  238. recieve_sm = (struct sm_deliver_invoke*) (*(rmsg->msgbody));
  239. if(recieve_sm==NULL) goto error;
  240.           
  241. /* as IA5(8 bit character) is the default line encoding used by X28
  242.  * and we do not support other line encoding scheme like binary or
  243.  * hex encoding
  244.  */
  245. (*msg)->sms.coding = DC_8BIT;
  246. /* OIS in X28 implementation does not include udh field */
  247. (*msg)->sms.sender = octstr_create_from_data(
  248.     octstr_get_cstr(recieve_sm->origadd) +2,
  249.     octstr_len(recieve_sm->origadd)-2);  
  250. (*msg)->sms.receiver = octstr_create_from_data(
  251.     octstr_get_cstr(recieve_sm->destadd) +2,
  252.     octstr_len(recieve_sm->destadd)-2);
  253.   
  254. (*msg)->sms.msgdata = octstr_duplicate(recieve_sm->shortmsg);
  255. (*msg)->sms.udhdata = octstr_create("");
  256. gw_free(recieve_sm);
  257. sema_msg_free(rmsg);
  258. rmsg = NULL;
  259.     }
  260.     return 1;
  261. error:
  262.     error(0, "sema_receive_msg: can not create Smart Msg");
  263.     return -1;
  264. }
  265. int sema_pending_smsmessage(SMSCenter *smsc)
  266. {
  267.     char data[1024];
  268.     int ret = 0;
  269.     char clrbuff[]="CLR";
  270.     char errbuff[]="ERR";
  271.     /* struct sema_msg* smsg = NULL;*/
  272.   /* Receive raw data */
  273.     ret = X28_data_read(smsc->sema_fd, smsc->buffer);
  274.     if(ret == -1) {
  275. ret = X28_reopen_data_link(smsc->sema_fd, smsc->sema_serialdevice);
  276. if(ret == -1) goto error;
  277. return 0;
  278.     } 
  279.     /* Interpret the raw data */
  280.     memset(data,0,sizeof(data));
  281.     while(X28_msg_pop(smsc->buffer, data) == 0 ) {
  282. if(strlen(data) > 0){
  283.     if(strstr(data,clrbuff) != NULL ||
  284.        strstr(data,errbuff) != NULL){
  285. debug("smsc.sema", 0, "sema_pending_msg: Radio Pad Command line-%s",data);
  286.     }
  287.     else{   
  288.       
  289. ret = sema_msg_session_mo(smsc, data);
  290. if(ret == -1) goto error;
  291.     }
  292.     memset(data,0,sizeof(data));
  293. }
  294.     }
  295.     /* Signal that we got a MO message if mo list is not empty*/
  296.     if(smsc->sema_mo->first != NULL){
  297. return 1;
  298.     }
  299.     return 0;
  300. error:
  301.     error(0,"sema_pending message: device file error");
  302.     return -1;
  303. }
  304. static sema_msg* sema_msg_new(void)
  305. {
  306.     struct sema_msg *msg = NULL;
  307.     msg = gw_malloc(sizeof(struct sema_msg));
  308.     memset(msg, 0, sizeof(struct sema_msg));
  309.     return msg;
  310. }
  311. static int sema_msg_free(sema_msg *msg) {
  312.     if(msg == NULL) return 0;
  313.     gw_free(msg);
  314.     return 1;
  315. }
  316. static sema_msglist* sema_msglist_new(void) {
  317.     struct sema_msglist *mlist = NULL;
  318.     mlist = gw_malloc(sizeof(struct sema_msglist));
  319.     memset(mlist, 0, sizeof(struct sema_msglist));
  320.   
  321.     mlist->first = NULL;
  322.     mlist->last = NULL;
  323.     mlist->count = 0;
  324.     return mlist;
  325. }
  326. static void sema_msglist_free(sema_msglist *mlist) {
  327.     struct sema_msg *pmsg = NULL;
  328.     if(mlist == NULL) return; 
  329.     while( sema_msglist_pop(mlist, &pmsg) == 1 )  {
  330. if(pmsg==NULL) break;
  331. sema_msg_free(pmsg);
  332. pmsg = NULL;
  333.     }
  334.     gw_free(mlist);
  335.     mlist->count = 0;
  336. }
  337. static int sema_msglist_push(sema_msglist *plist, sema_msg *pmsg) {
  338.     struct sema_msg * lmsg = NULL;
  339.     if(plist == NULL) {
  340. info(0, "msglist_push: NULL msg list");
  341. goto error;
  342.     }
  343.     if(pmsg == NULL) {
  344. info(0, "msglist_push: NULL input");
  345. goto error;
  346.     }
  347.     /* If list is completely empty. */
  348.     if( plist->first == NULL ) {
  349. plist->last = pmsg;
  350. plist->first = pmsg;
  351. pmsg->prev = NULL;
  352. pmsg->next = NULL;
  353.     }
  354.     else{
  355. lmsg=plist->last;
  356. lmsg->next=pmsg;
  357. pmsg->prev=lmsg;
  358. pmsg->next=NULL;
  359. plist->last=pmsg;
  360.     }
  361.     plist->count += 1;
  362.     return 1;
  363. error:
  364.     error(0, "msglist_push: error");
  365.     return 0;
  366. }
  367. static int sema_msglist_pop(sema_msglist *plist, sema_msg **msg) {
  368.    if(plist == NULL) {
  369. info(0, "msglist_pop: NULL list");
  370. goto no_msg;
  371.     }
  372.     if(plist->first == NULL) {
  373. goto no_msg;
  374.     }
  375.     *msg = plist->first;
  376.     if(plist->last == *msg) {
  377. plist->first = NULL;
  378. (*msg)->prev = NULL;
  379. plist->last = NULL;
  380.     } 
  381.     else {
  382. plist->first = (*msg)->next;
  383. plist->first->prev = NULL; 
  384. if(plist->first->next == NULL) 
  385.     plist->last = plist->first;
  386.     }
  387.     plist->count -= 1;
  388.     return 1;
  389. no_msg:
  390.     return 0;
  391. }
  392. static int X28_open_data_link(char* device){
  393.     int fd = -1, iret;
  394.     struct termios tios;
  395.     info(0,"open serial device %s",device);
  396.     fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY);
  397.     if(fd==-1) {
  398. error(errno, "sema_open_data_link: error open(2)ing the character device <%s>",
  399.       device);
  400. if(errno == EACCES)
  401.     error(0, "sema_open_data_link: user have no right to access the serial device");
  402. return -1;
  403.     }
  404.     tcgetattr(fd, &tios);
  405.     cfsetospeed(&tios, B4800);  /* check radio pad parameter*/
  406.     cfsetispeed(&tios, B4800);
  407.     kannel_cfmakeraw(&tios);
  408.     tios.c_iflag |= IGNBRK|IGNPAR|INPCK|ISTRIP;
  409.     tios.c_cflag |= (CSIZE|HUPCL | CREAD | CRTSCTS);
  410.     tios.c_cflag ^= PARODD;
  411.     tios.c_cflag |=CS7;
  412.     iret = tcsetattr(fd, TCSANOW, &tios);
  413.     if(iret == -1){
  414. error(errno,"sema_open_data_link: fail to set termios attribute");
  415. goto error;
  416.     }
  417.     tcflush(fd, TCIOFLUSH);
  418.     return fd;
  419.   
  420. error:
  421.     return -1;
  422. }
  423. static int X28_reopen_data_link(int oldpadfd ,char* device){
  424.     int nret = 0;
  425.     if(oldpadfd > 0){
  426. nret= close(oldpadfd);
  427. if(nret == -1){
  428.     error(errno,"sema_reopen_data_link: close device file failed!!");
  429. }
  430.     }
  431.     sleep(1);
  432.     return X28_open_data_link(device);
  433. }
  434. static int X28_close_send_link(int padfd)
  435. {
  436.     unsigned char discnntbuff[5];
  437.     unsigned char readbuff[1024];
  438.     unsigned char finishconfirm[]="CLR CONF";
  439.     int nret = 0, readall = 0;
  440.     time_t tstart;
  441.     time(&tstart);
  442.     sprintf(discnntbuff,"%cCLRr",0x10);
  443.     memset(readbuff,0,sizeof(readbuff));
  444.     /* what ever is the close return, data mode is unreliable now*/
  445.     x28_data_mode = X28_COMMAND_MODE;
  446.     if(padfd <= 0)
  447. goto datalink_error;
  448.     while((time(NULL) - tstart) < INTERNAL_DISCONNECT_TIMEVAL){
  449. nret =write(padfd, discnntbuff, 5);
  450. if(nret == -1){
  451.     if(errno == EAGAIN || errno ==EINTR) continue;
  452.     else{
  453. goto datalink_error;
  454.     }
  455. }
  456. sleep(1); /*wait 1 senconds for virtual link break*/
  457. nret=read(padfd, readbuff+readall,128);
  458. if(nret == -1){
  459.     if(errno == EAGAIN || errno ==EINTR) continue;
  460.     else{
  461. goto datalink_error;
  462.     }
  463. }
  464. if(nret >0){
  465.     readall += nret;
  466.     if(strstr(readbuff,finishconfirm))
  467. return 1;
  468. }
  469.     }
  470.     return 0;
  471. datalink_error:
  472.     error(errno,"sema_close_send_link, device file error");
  473.     return -1;
  474. }
  475. static int X28_open_send_link(int padfd, char *nua) {
  476.     char readbuff[1024]; 
  477.     char writebuff[129];
  478.     char smscbuff[129];
  479.     int readall = 0, readonce = 0, writeonce = 0, writeall = 0, i = 0;
  480.     char X28prompt[]="*rn";
  481.     time_t timestart;
  482.   
  483.     debug("smsc.sema", 0, "sema_open send link: call smsc  <%s> for <%i> seconds",
  484.   nua, (int)INTERNAL_CONNECT_TIMEVAL);
  485.     /*  type few <cr> to invoke DTE */
  486.     writebuff[0] = 'r';       
  487.     memset(readbuff,0,sizeof(readbuff));     
  488.     for(i = 0; i <= 3; i++)
  489.     {
  490. readonce = writeonce = -1;
  491. writeonce = write(padfd, writebuff, 1);
  492. if(writeonce < 1){
  493.     if(errno == EINTR || errno == EAGAIN) continue;
  494.     else{
  495. goto datalink_error;
  496.     }
  497. }
  498. usleep(1000); /* wait for prompt */
  499. readonce = read(padfd, &readbuff[readall],1024);
  500. if(readonce == -1){
  501.     if(errno == EINTR || errno == EAGAIN) continue;
  502.     else{
  503. goto datalink_error;
  504.     }
  505. }
  506. else
  507.     readall += readonce;
  508.     }
  509.     if(strstr(readbuff, X28prompt) == NULL){
  510. warning(0,"X28_open_send_link: can not read command prompt, abort");
  511. return 0;
  512.     }
  513.     /* second, connect to the smsc now */
  514.     memset(writebuff,0,sizeof(writebuff));
  515.     memset(readbuff,0,sizeof(readbuff));  
  516.     writeall = readall = 0;
  517.     sprintf(writebuff, "%sr", nua);
  518.     sprintf(smscbuff, "%s COM",nua);
  519.   
  520.     while((size_t) writeall < strlen(writebuff)){
  521. writeonce = -1;
  522. writeonce = write(padfd, writebuff+writeall, strlen(writebuff)-writeall);
  523. if(writeonce == -1){
  524.     if(errno == EINTR || errno == EAGAIN)
  525. continue;
  526.     else
  527. goto datalink_error;
  528. }
  529. if(writeonce > 0)
  530.     writeall +=writeonce;
  531.     }
  532.     tcdrain(padfd); 
  533.     usleep(1000*1000);/* wait for smsc answer */
  534.     time(&timestart);
  535.     while(time(NULL) - timestart < INTERNAL_CONNECT_TIMEVAL){
  536. if((size_t) readall >= sizeof(readbuff))
  537.     goto error_overflow;
  538. /* We read 1 char a time */
  539. readonce = read(padfd, &readbuff[readall], 1);
  540. if(readonce == -1) {
  541.     if(errno == EINTR || errno == EAGAIN) continue;
  542.     else
  543. goto datalink_error;
  544. }
  545. if(readonce > 0)
  546.     readall += readonce;
  547. /* Search for reponse line. */
  548. if(readall > 2 &&
  549.    readbuff[readall-1] == 'n' && 
  550.    readbuff[readall-2] == 'r') {
  551.     if(strstr(readbuff, smscbuff)) {
  552. debug("smsc.sema", 0,
  553.       "sema_open send link: smsc respond, virtual link established");
  554. x28_data_mode = X28_MT_DATA_MODE; 
  555. return 1;
  556.     }
  557. usleep(1000);
  558.     }
  559.     info(0,"sema_open_send_link: connecting time out");
  560.     return 0;
  561. error_overflow:
  562.     warning(0, "sema_open_send_link: command buffer overflow");
  563.     return 0;
  564. datalink_error:
  565.     error(errno,"sema_open_send_link: device file error");
  566.     return -1;
  567. }
  568. static int X28_data_read(int padfd, char *cbuffer) {
  569.     char *p = NULL;
  570.     int ret,  len;
  571.     fd_set read_fd;
  572.     struct timeval tv, tvinit;
  573.     size_t readall;
  574.      
  575.     tvinit.tv_sec = 0;
  576.     tvinit.tv_usec = 1000;
  577.      
  578.     readall = 0;
  579.     for (;;) {
  580. FD_ZERO(&read_fd);
  581. FD_SET(padfd, &read_fd);
  582. tv = tvinit;
  583. ret = select(padfd + 1, &read_fd, NULL, NULL, &tv);
  584. if (ret == -1) {
  585.     if(errno==EINTR) goto got_data;
  586.     if(errno==EAGAIN) goto got_data;
  587.     error(errno, "Error doing select for fad");
  588.     return -1;
  589. } else if (ret == 0)
  590.     goto got_data;
  591. len = strlen(cbuffer);
  592. ret = read(padfd,
  593.    cbuffer + len,
  594.    256);    
  595. if (ret == -1) {
  596.             error(errno," read device file");
  597.     return -1;
  598. }
  599. if (ret == 0)
  600.     goto eof;
  601.        
  602. readall += ret;
  603. if ((size_t) len >  sizeof(cbuffer)- 256) {
  604.     p = gw_realloc(cbuffer, sizeof(cbuffer) * 2);
  605.     memset(p+len,0,sizeof(cbuffer)*2 - len);
  606.     cbuffer = p;
  607. }
  608. if(readall > 0)
  609.     break;
  610.     }
  611.      
  612. eof:
  613.     if(readall > 0)
  614. ret = 1;
  615.     goto unblock;
  616.      
  617. got_data:
  618.     ret = 0;
  619.     goto unblock;
  620. unblock:
  621.     return ret;  
  622. }
  623. static int X28_data_send(int padfd, char *cbuffer,int sentonce) {
  624.     int len = 0, pos = 0,writeonce = 0,writeall = 0;
  625.  
  626.     tcdrain(padfd);
  627.     len = strlen(cbuffer);
  628.     while(len > 0){
  629. if(len < sentonce) {
  630.     writeonce = write(padfd, cbuffer+pos, len);
  631. }
  632. else
  633.     writeonce = write(padfd, cbuffer+pos, sentonce);
  634.  
  635. if (writeonce == -1) {
  636.     if(errno == EINTR || errno == EINTR)
  637. continue;
  638.     else{
  639. goto error;
  640.     }
  641. }
  642. if(writeonce > 0){
  643.     len -= writeonce;
  644.     pos += writeonce;
  645.     writeall = pos;
  646. }
  647.     }
  648.     tcdrain(padfd);
  649.     return writeall;
  650. error:
  651.     error(errno,"sema_send data error: device file erro");
  652.     return -1;
  653. }
  654. static int X28_msg_pop(char *from, char *to)
  655. {
  656.     char* Rbuff =NULL;
  657.     char* RRbuff = NULL;
  658.     char mobuff[] ="COMrn";
  659.     char mobuffend[] = "r";
  660.     char prompbuff[] = "*r";
  661.     int len = 0, Llen= 0, Rlen = 0,RRlen = 0;
  662.     len = strlen(from);
  663.     if(len <=0) goto no_msg;
  664.     /* trim off rabbish header */
  665.     while(*from == 'r' || *from == 'n'){
  666. len = strlen(from);
  667. if(len > 1){
  668.     memmove(from, from +1, len-1);
  669.     memset(from+(len-1), 0, 1);
  670. }
  671. else{
  672.     memset(from,0,len);
  673.     return -1;
  674. }
  675.     }   
  676.     len = strlen(from); 
  677.     /*all kinds of useful infomation contains r*/
  678.     if((Rbuff=memchr(from,'r',len)) == NULL)
  679. goto no_msg;
  680.  
  681.     /*check if it is a command prompt *rn */
  682.     if((Rbuff -from) > 0 && *(Rbuff -1) == '*'){
  683. if(strlen(Rbuff) < 2) goto no_msg; /*n is not coming yet*/
  684.      
  685. if(Rbuff -from > 4){ /* command info */
  686.     Rlen = Rbuff -1 -from;
  687.     memcpy(to,from,Rlen);
  688. }
  689. x28_data_mode = X28_COMMAND_MODE;
  690. if(strlen(Rbuff+1) > 1){
  691.     Rlen = strlen(Rbuff +2);
  692.     memmove(from, Rbuff +2, Rlen);
  693.     memset(from+Rlen, 0, len-Rlen);
  694. }
  695. else
  696.     memset(from, 0,len);
  697.     }/* check mo msg , format X121address+COMrn+msg+r*/
  698.     else if((Rbuff-from) > 3 &&  strstr(Rbuff-4,mobuff)!= NULL){
  699. if(strlen(Rbuff) < 3 ||
  700.    (RRbuff = strstr(Rbuff + 2, mobuffend)) == NULL)
  701.     goto no_msg; /*the msg+r  is still coming*/
  702. RRlen = RRbuff - (Rbuff+2);
  703. if(RRlen > 4){ /* msg header is 4 byte always+msg content*/ 
  704.     memcpy(to, Rbuff +2 , RRlen);
  705.     x28_data_mode = X28_MO_DATA_MODE;
  706. }
  707. if(strlen(RRbuff) > 1){
  708.     Rlen = strlen(RRbuff +1);
  709.     memmove(from, RRbuff+1 ,Rlen);
  710.     memset(from+Rlen,0,len -Rlen);
  711. }
  712. else
  713.     memset(from,0,len);
  714.     }
  715.     else{/* it can be mt reply */
  716. if(Rbuff  - from > 0){ 
  717.     Llen = Rbuff - from;
  718.     memcpy(to, from, Llen);
  719. }    
  720. if(strlen(Rbuff) > 1){
  721.     Rlen = strlen(Rbuff+1);
  722.     memmove(from,Rbuff+1,Rlen);
  723.     memset(from+Rlen,0,len-Rlen);
  724. }
  725. else
  726.     memset(from,0,len);
  727.     }
  728.     /* check rest line for link state: command mode or data mode */
  729.     if(strstr(from,prompbuff) != NULL)
  730. x28_data_mode = X28_COMMAND_MODE;
  731.     return 0;
  732. no_msg:
  733.     return -1;
  734. }
  735. static int sema_submit_result(SMSCenter *smsc, sema_msg* srcmsg, int result)
  736. {
  737.     char IA5buff[1024];
  738.     unsigned char oct1byte[1];
  739.     unsigned char ia5byte[2];
  740.     unsigned char cTr='t';
  741.     unsigned char cMr='m';
  742.     unsigned char ccontinuebyte = 'P', ccr = 'r';
  743.     int j = 0, iret;
  744.     memset(IA5buff,0,sizeof(IA5buff));
  745.     switch(srcmsg->type)
  746.     {
  747.     case 'M':
  748. memcpy(IA5buff,&cMr,1);/*msg type*/
  749. memcpy(IA5buff+1,&ccontinuebyte,1); /*continue bit*/
  750. memcpy(IA5buff+2,srcmsg->optref,4); /*operation reference*/
  751. write_variable_value(result,oct1byte);
  752. j=internal_char_hex_to_IA5(oct1byte[0],ia5byte);
  753. memcpy(IA5buff+6,ia5byte,j);
  754. memcpy(IA5buff+6+j,&ccr,1);/*result*/
  755. iret = X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff));
  756. if(iret == -1) goto error;
  757. break;
  758.     case 'T':
  759. memcpy(IA5buff,&cTr,1);
  760. memcpy(IA5buff+1,&ccontinuebyte,1);
  761. memcpy(IA5buff+2,srcmsg->optref,4); 
  762. write_variable_value(result,oct1byte);
  763. j=internal_char_hex_to_IA5(oct1byte[0],ia5byte);
  764. memcpy(IA5buff+6,ia5byte,j);
  765. memcpy(IA5buff+6+j,&ccr,1);
  766. iret = X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff));
  767. if(iret == -1) goto error;   
  768. break;
  769.     default:  
  770. return 0; /*unsupoorted result msg type*/
  771.     }
  772.     return 1;
  773. error:
  774.     error(0,"sk_submit_result: write to device file failed");
  775.     return -1;
  776. }
  777. static int sema_msg_session_mt(SMSCenter *smsc, sema_msg* pmsg){
  778.     struct msg_hash *segments = NULL;
  779.     struct sema_msg* mtrmsg = NULL;
  780.     struct sm_statusreport_invoke* report_invoke = NULL;
  781.     struct sm_submit_result* submit_result = NULL;
  782.     struct sm_submit_invoke* submit_invoke = NULL;
  783.     struct sm_deliver_invoke* deliver_invoke = NULL;
  784.     char data[1024], IA5buff[256], IA5chars[1024], mochars[10*1024];
  785.     unsigned char ccontinuebyte, ccr = 'r';
  786.     unsigned char cerr[] = "ERR",cclr[] = "CLR", tmp1[5] , tmp2[5];
  787.   
  788.     int  i, iseg = 0, ilen = 0,iret = 0, moret;
  789.     int isrcved = 0, iTrcved = 0, decoderesult = 0;
  790.     time_t tstart;
  791.     submit_invoke=(struct sm_submit_invoke*)(*(pmsg->msgbody));
  792.     if(submit_invoke == NULL) goto error;
  793.     /*encode first*/
  794.     memset(IA5chars,0,sizeof(IA5chars));
  795.     if(sema_encode_msg(pmsg, IA5chars) < 1) goto encode_error;
  796.     /*divide segments, we send buffer no more than 128 byte once*/
  797.     iseg = strlen(IA5chars)/121 + 1;
  798.     segments = gw_malloc(iseg * sizeof(struct msg_hash));
  799.     if(segments == NULL) goto error;
  800.     /*first segments*/
  801.     if(strlen(IA5chars) < 121)
  802. ilen = strlen(IA5chars);
  803.     else
  804. ilen = 121;
  805.     segments[0].content = octstr_create_from_data(&(pmsg->type), 1);/*msg type, in hex*/
  806.     ccontinuebyte = pack_continous_byte(pmsg->encodetype, 1, iseg -1);
  807.     octstr_insert_data(segments[0].content, 1, 
  808.        &ccontinuebyte, 1);  /*continue char, in hex*/
  809.     octstr_insert_data(segments[0].content,
  810.        2, pmsg->optref, 4); /*operation reference, in hex*/
  811.     octstr_insert_data(segments[0].content, 6,
  812.        IA5chars, ilen);
  813.     octstr_insert_data(segments[0].content,
  814.        octstr_len(segments[0].content), &ccr, 1); /*<cr>*/
  815.  
  816.     /*rest segments*/
  817.     for( i = 1; i < iseg; i++){
  818. if(strlen(IA5chars) - i*121 < 121)
  819.     ilen = strlen(IA5chars) - i*121;
  820. else
  821.     ilen =121;
  822. segments[i].content= octstr_create_from_data(&(pmsg->type), 1); 
  823. ccontinuebyte = pack_continous_byte(pmsg->encodetype, 0, iseg -i-1);
  824. octstr_insert_data(segments[i].content, 1, &ccontinuebyte, 1); 
  825. octstr_insert_data(segments[i].content, 2, pmsg->optref, 4); 
  826. octstr_insert_data(segments[i].content, 6, 
  827.    IA5chars + i*121, ilen);
  828. octstr_insert_data(segments[i].content,
  829.    octstr_len(segments[i].content), &ccr, 1); 
  830.     }
  831.     if(x28_data_mode != X28_MT_DATA_MODE){
  832. /* do not trust any existing data mode*/    
  833. X28_close_send_link(smsc->sema_fd); 
  834. /*open send link*/
  835. if((iret = X28_open_send_link(smsc->sema_fd,smsc->sema_smscnua)) < 1){
  836.     if(iret == -1){
  837. iret = X28_reopen_data_link(smsc->sema_fd, smsc->sema_serialdevice);
  838. if(iret == -1){
  839.     goto error;
  840. }
  841.     }
  842.     X28_close_send_link(smsc->sema_fd); 
  843.     sleep(1);
  844.     iret = X28_open_send_link(smsc->sema_fd,smsc->sema_smscnua);
  845.     if(iret < 1)
  846. goto sendlink_error;
  847. }
  848.     }
  849.     /*deliver buff*/
  850.     for(i = 0; i < iseg; i++){
  851. memset(IA5buff,0,sizeof(IA5buff));
  852. memcpy(IA5buff,octstr_get_cstr(segments[i].content),
  853.        octstr_len(segments[i].content));
  854. iret =X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff));
  855. if(iret == -1)
  856.     goto error;
  857. octstr_destroy(segments[i].content);
  858.     }
  859.     gw_free(segments);
  860.     /*wait result and report return*/
  861.     mtrmsg = sema_msg_new();
  862.     memset(mochars,0,sizeof(mochars));
  863.     time(&tstart);
  864.     while(time(NULL) -tstart < INTERNAL_SESSION_MT_TIMEVAL){
  865. iret = X28_data_read(smsc->sema_fd, smsc->buffer);
  866. if(iret == -1)
  867.     goto error;
  868. /* Interpret the raw data */
  869. memset(data,0,sizeof(data));
  870. while(X28_msg_pop(smsc->buffer, data) == 0 ) {
  871.     if(strlen(data) > 0){
  872. if(strstr(data,cerr) != NULL ||
  873.    strstr(data,cclr) != NULL){
  874.   debug("smsc.sema", 0, "sema_mt_session: Radio Pad Command line-%s",data);
  875.     goto sendlink_error;
  876. }
  877. /* decode msg*/      
  878. decoderesult = sema_decode_msg(&mtrmsg,data);  
  879. if(decoderesult >= 0){
  880.     if(mtrmsg->type == 's'){ /*submit result*/
  881.  
  882. submit_result = (struct sm_submit_result*)(*mtrmsg->msgbody);
  883. if(submit_result == NULL) goto error;
  884. /* check result operation number is what we send */
  885. memset(tmp1,0,5); memset(tmp2,0,5);
  886. memcpy(tmp1,mtrmsg->optref,4);
  887. memcpy(tmp2, pmsg->optref,4);
  888. if(strstr(tmp1,tmp2) != NULL){
  889.     isrcved = 1;
  890.     memcpy(submit_invoke->smscrefnum, submit_result->smscrefnum,4);
  891. }
  892. if(isrcved == 1 &&
  893.    submit_result->smeresult != 0){  
  894.     gw_free(submit_result);
  895.     goto smsc_say_fail;  
  896. }
  897. gw_free(submit_result);
  898.     } 
  899.     else if(mtrmsg->type == 'T'){ /*report invoke*/
  900. report_invoke=(struct sm_statusreport_invoke*)(*mtrmsg->msgbody);
  901. if(report_invoke == NULL) goto error;
  902. /*check if report reference number is what we expect*/
  903. memset(tmp1,0,sizeof(tmp1)); memset(tmp2,0,sizeof(tmp2));
  904. memcpy(tmp1,report_invoke->smscrefnum,4);
  905. memcpy(tmp2,submit_invoke->smscrefnum,4);
  906. if(strstr(tmp1, tmp2) != NULL){
  907.     iTrcved = 1;
  908. }
  909. decoderesult = 0; 
  910. iret = sema_submit_result(smsc, mtrmsg, decoderesult);
  911. if(iret == -1) goto error;
  912. if(iTrcved == 1 &&
  913.    report_invoke->status != 3){ /*3 means ,msg delivered*/
  914.     info(0,"sema_mt_session: submit invoke failed with report value-%i",report_invoke->status);
  915.     gw_free(report_invoke);
  916.     goto smsc_say_fail;
  917. }
  918. gw_free(report_invoke);
  919.     }
  920.     else if(mtrmsg->type == 'M'){/* deliver invoke*/
  921.   
  922. /* we do not deal with deliver in mt session*/ 
  923. decoderesult = 0;
  924. iret = sema_submit_result(smsc, mtrmsg, decoderesult);
  925. if(iret == -1) goto error;
  926. deliver_invoke =(struct sm_deliver_invoke*)(*mtrmsg->msgbody);
  927. if(deliver_invoke != NULL){
  928.     gw_free(deliver_invoke);
  929.     /*append buffer back to  smsc->buffer*/
  930.     ilen=strlen(mochars);
  931.     memcpy(mochars+ilen,data,strlen(data));
  932.     ilen=strlen(mochars);
  933.     memcpy(mochars+ilen,&ccr,1);
  934. }
  935. time(&tstart);
  936.     }
  937.     /* clean msg for next read*/
  938.     memset(mtrmsg,0,sizeof(struct sema_msg));
  939. }
  940. /* clean buffer for next useful info*/
  941. memset(data,0,sizeof(data));
  942. if(sema_wait_report == 0 && isrcved == 1)
  943. {
  944.     info(0,"sema_mt_session: submit invoke deliver successfully to smsc");
  945.     goto mo_success;
  946. }
  947. if(sema_wait_report > 0 &&
  948.    isrcved == 1 && iTrcved == 1)
  949. {
  950.     info(0,"sema_mt_session: submit invoke deliver sucessfully to msisdn");
  951.     goto mo_success;
  952. }
  953.     }
  954. }
  955.     }
  956. /* mo_timeout: */
  957.       info(0,"sema_mt_session: time out without receive all expected return");
  958.       moret = SESSION_MT_RECEIVE_TIMEOUT;
  959.       goto mo_return;
  960. mo_success:
  961.     moret = SESSION_MT_RECEIVE_SUCCESS;
  962.     goto mo_return;
  963. smsc_say_fail:
  964.     info(0,"sema_mt_session: smsc says message deliver failed!");
  965.     moret = SESSION_MT_RECEIVE_ERR;
  966.     goto mo_return;
  967. mo_return:
  968.     X28_close_send_link(smsc->sema_fd);
  969.     /* we have to close here, otherwise smsc will wait for a long time
  970.        untill it find out nothing is coming */
  971.     sema_msg_free(mtrmsg);
  972.     ilen = strlen(mochars);
  973.     i =  strlen(smsc->buffer);
  974.     if(ilen > 0){
  975. memmove( smsc->buffer+ilen,smsc->buffer,i);
  976. memcpy(smsc->buffer, mochars,ilen);
  977.     }
  978.     return moret;      
  979. sendlink_error:
  980.     info(0,"sema_mt_session: X28 data link has broken");
  981.     if(mtrmsg != NULL)
  982. sema_msg_free(mtrmsg);
  983.     return 0;
  984. encode_error:
  985.     info(0,"sema_mt_session: Msg encode error");
  986.     return 0;
  987. error:
  988.     error(0,"sema_mt session: memory allocation error or device file error");
  989.     return -1;
  990. }
  991. static int sema_msg_session_mo(SMSCenter *smsc, char* cbuff){
  992.   
  993.     struct sema_msg *rmsg = NULL;
  994.     int iret = 0, retresult = 0;
  995.     struct sm_deliver_invoke* deliver_invoke = NULL;
  996.     struct sm_statusreport_invoke* report_invoke = NULL;
  997.  
  998.     rmsg = sema_msg_new();
  999.     iret = sema_decode_msg(&rmsg,cbuff);
  1000.     if(iret == - 1) goto msg_error;/* decode error */
  1001.     if(x28_data_mode == X28_COMMAND_MODE){
  1002. /* do not trust any existing data mode*/
  1003. /* XXX this should be fixed? -rpr */
  1004. X28_close_send_link(smsc->sema_fd); 
  1005. /*open send link*/
  1006. if(X28_open_send_link(smsc->sema_fd,smsc->sema_smscnua) < 1){
  1007.     info(0,"sema_mo_session: can not establish send link");
  1008.     return 0;
  1009. }   
  1010.     }
  1011.     if(rmsg->type == 'M'){  /* deliver invoke */
  1012. retresult = 0;   /* deliver invoke */  
  1013. iret = sema_submit_result(smsc, rmsg, retresult); 
  1014. if(iret == -1) goto error;
  1015. deliver_invoke= (struct sm_deliver_invoke*) (*rmsg->msgbody);
  1016. if(deliver_invoke == NULL) goto msg_error;
  1017. sema_msglist_push(smsc->sema_mo, rmsg);  
  1018. return 1;
  1019.     }
  1020.     else if(rmsg->type == 'T'){ /* status report */
  1021. retresult = 0;  /* let msg through */
  1022. sema_submit_result(smsc, rmsg, retresult);
  1023. if(iret == -1) goto error;
  1024. report_invoke = (struct sm_statusreport_invoke*)(*rmsg->msgbody);
  1025. if(report_invoke != NULL)  
  1026.     gw_free(report_invoke);
  1027.     }
  1028.     else{ /* add your additional support here*/
  1029.     }
  1030.     sema_msg_free(rmsg);
  1031.     return 1;
  1032.   
  1033. msg_error:
  1034.     sema_msg_free(rmsg);
  1035.     error(0,"sema_mo session: Msg decode failed");
  1036.     return 0;
  1037. error:  
  1038.     error(0,"sema_mo session: device file error or memory allocated problem!");
  1039.     return -1;
  1040. }
  1041. static int sema_decode_msg(sema_msg **desmsg, char* octsrc) {
  1042.     struct sm_deliver_invoke *receive_sm = NULL;
  1043.     struct sm_statusreport_invoke* receive_report = NULL;
  1044.     struct sm_submit_result* submit_result = NULL;
  1045.     unsigned char tmp[1024],tmpgsm[1024];
  1046.     int octetlen, iret, iusedbyte;
  1047.     int imsgtopseg = 0, imsgfollownum = 0, imsgencodetype = 0;
  1048.     unsigned char cmsgtype, cmsgcontinuebyte;
  1049.     /* message type */
  1050.     if(strlen(octsrc) <= 4) goto no_msg;
  1051.     /* check if we support this type */
  1052.     cmsgtype = *octsrc;
  1053.     if(cmsgtype != 's'  /* invoke reseult */
  1054.        && cmsgtype != 'M'   /* deliver invoke */
  1055.        && cmsgtype != 'T'){   /* report invoke */
  1056. info(0,"sema_decode: msg type not support");
  1057. goto error_msg;
  1058.     }
  1059.     /*check if continue bit is correct */
  1060.     cmsgcontinuebyte = *(octsrc+1);
  1061.     iret = unpack_continous_byte(cmsgcontinuebyte,
  1062.  &imsgencodetype,&imsgtopseg, &imsgfollownum);
  1063.     if(iret == -1){
  1064. info(0,"sema_decode: msg continue bit can not be interpret");
  1065. goto error_msg;
  1066.     }
  1067.     /*status report and submit result will always be 1 segments
  1068.       for deliver invoke, if smsc can not send all the data in one packet,
  1069.       text data will be truncated ,so it's also 1 packet*/
  1070.     if(imsgtopseg == 0){
  1071. info(0, "sema_decode: can not interpret more than one segments msg");
  1072. goto error_msg;
  1073.     }
  1074.     (*desmsg)->type = cmsgtype;
  1075.     (*desmsg)->continuebyte = cmsgcontinuebyte;
  1076.     (*desmsg)->encodetype = imsgencodetype;
  1077.     /*operation reference*/
  1078.     memcpy((*desmsg)->optref, octsrc +2, 4);
  1079.     octsrc += 6;
  1080.     iusedbyte = 0;
  1081.  
  1082.     switch(cmsgtype){
  1083.     case 's': /* submit invoke result */
  1084. submit_result = gw_malloc(sizeof(struct sm_submit_result)); 
  1085. memset(submit_result,0,sizeof(struct sm_submit_result));
  1086. /* result */ 
  1087. iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
  1088. if(iusedbyte < 1) goto error_submit;
  1089. octetlen = 1;
  1090. submit_result->smeresult = get_variable_value(tmp, &octetlen);
  1091. if(submit_result->smeresult == SM_RESULT_SUCCESS)
  1092. {
  1093.     /*smsc reference number*/
  1094.     octsrc += iusedbyte;
  1095.     iusedbyte = line_scan_IA5_hex(octsrc, 4,tmp);
  1096.     if(iusedbyte <1) goto error_submit;
  1097.     memcpy(submit_result->smscrefnum, tmp, 4);
  1098.     /*accept time*/
  1099.     octsrc += iusedbyte;  
  1100.     iusedbyte = line_scan_IA5_hex(octsrc, 14,tmp);
  1101.     if(iusedbyte < 1) goto error_submit;
  1102.     memcpy(submit_result->accepttime, tmp, 4);
  1103. }
  1104. (*desmsg)->msgbody = (void**)&submit_result;
  1105. break;
  1106.     case 'M': 
  1107. /* deliver invoke*/
  1108. receive_sm = gw_malloc(sizeof(struct sm_deliver_invoke));
  1109. memset(receive_sm, 0, sizeof(struct sm_deliver_invoke));
  1110. /*deliver destination address length*/
  1111. iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
  1112. if(iusedbyte < 1) goto error_deliver;
  1113. octetlen = 1;
  1114. receive_sm->destaddlen = get_variable_value(tmp, &octetlen);
  1115. /*deliver destination address*/
  1116. octsrc +=iusedbyte;    
  1117. iusedbyte = line_scan_IA5_hex(octsrc,receive_sm->destaddlen,tmp);
  1118. if(iusedbyte < 1) goto error_deliver;
  1119. receive_sm->destadd= octstr_create_from_data(tmp,  receive_sm->destaddlen);
  1120. /*smsc reference number*/
  1121. octsrc +=iusedbyte;
  1122. iusedbyte = line_scan_IA5_hex(octsrc, 4,tmp);
  1123. if(iusedbyte < 1) goto error_deliver;
  1124. memcpy(receive_sm->smscrefnum, tmp, 4);
  1125. /*originate address length*/
  1126. octsrc +=iusedbyte;
  1127. iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
  1128. if(iusedbyte < 1) goto error_deliver;
  1129. octetlen = 1;
  1130. receive_sm->origaddlen = get_variable_value(tmp, &octetlen);
  1131. /*originate address*/
  1132. octsrc +=iusedbyte;
  1133. iusedbyte = line_scan_IA5_hex(octsrc, receive_sm->origaddlen, tmp);
  1134. if(iusedbyte < 1) goto error_deliver;
  1135. receive_sm->origadd= octstr_create_from_data(tmp,receive_sm->origaddlen);
  1136. /* data code scheme */ 
  1137. octsrc +=iusedbyte;
  1138. if(iusedbyte < 1) goto error_deliver;
  1139. iusedbyte = line_scan_IA5_hex(octsrc, 1,tmp);
  1140. octetlen = 1;
  1141. receive_sm->DCS = get_variable_value(tmp, &octetlen);
  1142. if(receive_sm->DCS != ENCODE_IA5 && receive_sm->DCS !=ENCODE_GSM){
  1143.     info(0, "sema_decode, Data encoding scheme not support");
  1144.     goto error_deliver;
  1145. }
  1146. /* protocol */ 
  1147. octsrc +=iusedbyte;
  1148. iusedbyte = line_scan_IA5_hex(octsrc, 1,tmp);
  1149. if(iusedbyte < 1) goto error_deliver;
  1150. octetlen = 1;
  1151. receive_sm->protocal = get_variable_value(tmp, &octetlen);
  1152. /* reply path */
  1153. octsrc +=iusedbyte;
  1154. iusedbyte = line_scan_IA5_hex(octsrc, 1,tmp);
  1155. if(iusedbyte < 1) goto error_deliver;
  1156. octetlen = 1;
  1157. receive_sm->replypath = get_variable_value(tmp, &octetlen);
  1158. /*text size in septect*/
  1159. octsrc +=iusedbyte;
  1160. iusedbyte = internal_char_IA5_to_hex(octsrc, tmp);
  1161. if(iusedbyte < 1) goto error_deliver;
  1162. receive_sm->textsizeseptet = tmp[0];
  1163. /*text size in octects*/
  1164. octsrc +=iusedbyte;
  1165. iusedbyte = internal_char_IA5_to_hex(octsrc, tmp);
  1166. if(iusedbyte < 1) goto error_deliver;
  1167. receive_sm->textsizeoctect = tmp[0];
  1168. octsrc+=iusedbyte;
  1169. /*message text*/
  1170. iusedbyte = 0;
  1171. memset(tmp,0,sizeof(tmp));
  1172. if(receive_sm->DCS == ENCODE_IA5 && receive_sm->textsizeoctect > 0) 
  1173. {
  1174.     iusedbyte = line_scan_IA5_hex(octsrc,receive_sm->textsizeoctect,tmp);    
  1175.     if(iusedbyte < 1) goto error_deliver;
  1176.     receive_sm->shortmsg =octstr_create_from_data( tmp,receive_sm->textsizeoctect);
  1177. }
  1178. else if(receive_sm->DCS == ENCODE_GSM &&  receive_sm->textsizeseptet > 0)
  1179. {
  1180.     memset(tmpgsm,0,sizeof(tmpgsm));
  1181.   
  1182.     iusedbyte = line_scan_IA5_hex(octsrc,receive_sm->textsizeoctect,tmp);
  1183.     if(iusedbyte < 1) goto error_deliver;
  1184.     line_scan_hex_GSM7(tmp,receive_sm->textsizeoctect,
  1185.        receive_sm->textsizeseptet, tmpgsm);
  1186.     receive_sm->shortmsg = octstr_create_from_data(tmpgsm,
  1187.    receive_sm->textsizeseptet);
  1188. }
  1189. else if(receive_sm->textsizeoctect <= 0)
  1190.   receive_sm->shortmsg = octstr_create("");
  1191. /*accepttime*/
  1192. octsrc +=iusedbyte;
  1193. iusedbyte = line_scan_IA5_hex(octsrc,14,tmp);
  1194. if(iusedbyte < 1) goto error_deliver;
  1195. memcpy(receive_sm->accepttime, tmp,14);
  1196. /*valid time*/
  1197. octsrc +=iusedbyte;
  1198. iusedbyte = line_scan_IA5_hex(octsrc,14,tmp);
  1199. if(iusedbyte < 1) goto error_deliver;
  1200. memcpy(receive_sm->invoketime, tmp,14);
  1201. (*desmsg)->msgbody = (void**)&receive_sm;
  1202. break;
  1203.     case 'T': 
  1204. /* status report invoke */
  1205. receive_report = gw_malloc(sizeof(struct sm_statusreport_invoke)); 
  1206. memset(receive_report,0,sizeof(struct sm_statusreport_invoke));
  1207. /*deliver msisdn address length*/
  1208. iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
  1209. if(iusedbyte < 1) goto error_receive;
  1210. octetlen = 1;
  1211. receive_report->msisdnlen = get_variable_value(tmp, &octetlen);
  1212. /*msisdn*/
  1213. octsrc += iusedbyte;    
  1214. iusedbyte = line_scan_IA5_hex(octsrc, receive_report->msisdnlen, tmp);
  1215. if(iusedbyte < 1) goto error_receive;
  1216. receive_report->msisdn = octstr_create_from_data( tmp,receive_report->msisdnlen);
  1217. /*sme reference type*/
  1218. octsrc += iusedbyte;
  1219. iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
  1220. if(iusedbyte < 1) goto error_receive;
  1221. octetlen = 1;
  1222. receive_report->smetype = get_variable_value(tmp, &octetlen);
  1223. /*sme reference number */
  1224. octsrc += iusedbyte;    
  1225. iusedbyte = line_scan_IA5_hex(octsrc,4, tmp);
  1226. if(iusedbyte < 1) goto error_receive;
  1227. memcpy(receive_report->smerefnum ,tmp, 4);
  1228. /*smsc reference number */
  1229. octsrc += iusedbyte;
  1230. iusedbyte = line_scan_IA5_hex(octsrc,4, tmp);
  1231. if(iusedbyte < 1) goto error_receive;
  1232. memcpy(receive_report->smscrefnum ,tmp, 4);
  1233. /*accepted time*/ 
  1234. octsrc += iusedbyte;    
  1235. iusedbyte = line_scan_IA5_hex(octsrc,14, tmp);
  1236. if(iusedbyte < 1) goto error_receive;
  1237. memcpy(receive_report->accepttime ,tmp, 4);
  1238. /*status*/
  1239. octsrc += iusedbyte;    
  1240. iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
  1241. if(iusedbyte < 1) goto error_receive;
  1242. octetlen = 1; 
  1243. receive_report->status = get_variable_value(tmp, &octetlen);
  1244. octsrc += iusedbyte;
  1245. if(receive_report->status != 6) /*6 means unable to deliver , but retry*/
  1246. {
  1247.     iusedbyte = line_scan_IA5_hex(octsrc,14, tmp);
  1248.     if(iusedbyte < 1) goto error_receive;
  1249.     memcpy(receive_report->completetime ,tmp, 14);
  1250. }
  1251. else
  1252. {
  1253.     iusedbyte = line_scan_IA5_hex(octsrc,14, tmp);
  1254.     if(iusedbyte < 1) goto error_receive;
  1255.     memcpy(receive_report->intermediatime ,tmp, 14);
  1256. }
  1257. if(receive_report->status == 6 || receive_report->status == 1) /*unable to deliver ,both case */
  1258. {       
  1259.     octsrc += iusedbyte;
  1260.     iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
  1261.     if(iusedbyte < 1) goto error_receive;
  1262.     octetlen = 1;
  1263.     receive_report->failreason = get_variable_value(tmp, &octetlen);
  1264. }
  1265. /*deliver orignate address length*/
  1266. octsrc += iusedbyte;
  1267. iusedbyte = line_scan_IA5_hex(octsrc, 1, tmp);
  1268. if(iusedbyte < 1) goto error_receive;
  1269. octetlen = 1;
  1270. receive_report->origaddlen = get_variable_value(tmp, &octetlen);
  1271. /*orignate address*/
  1272. octsrc += iusedbyte;
  1273. iusedbyte = line_scan_IA5_hex(octsrc, receive_report->origaddlen, tmp);
  1274. if(iusedbyte < 1) goto error_receive;
  1275. receive_report->origadd = octstr_create_from_data(tmp,  receive_report->msisdnlen);
  1276. /* invoke time */
  1277. octsrc += iusedbyte;     
  1278. iusedbyte = line_scan_IA5_hex(octsrc,14, tmp);
  1279. if(iusedbyte < 1){
  1280.     goto error_receive;
  1281. }
  1282. memcpy(receive_report->invoketime ,tmp, 14);
  1283. (*desmsg)->msgbody = (void**)&receive_report;
  1284. break;
  1285.     }
  1286.     return 1;
  1287. no_msg:
  1288.     info(0,"sema_decode: msg in empty");
  1289.     return 0;
  1290. error_receive:
  1291.     gw_free(receive_report);
  1292.     goto error_msg;
  1293. error_submit:
  1294.     gw_free(submit_result);
  1295.     goto error_msg;
  1296. error_deliver:
  1297.     gw_free(receive_sm);
  1298.     goto error_msg;
  1299. error_msg:
  1300.     info(0,"sema_decode:msg parameter is not recognized or unsupported");
  1301.     return 0;
  1302. }
  1303. static int sema_encode_msg(sema_msg* pmsg, char* str) {
  1304.     struct sm_submit_invoke *submit_sm = NULL;
  1305.     Octstr *IA5msg = NULL;
  1306.     int tSize = 0;
  1307.     unsigned char oc1byte[10];
  1308.     IA5msg = octstr_create("");
  1309.     switch(pmsg->type)
  1310.     {
  1311.     case 'S':
  1312. submit_sm = (struct sm_submit_invoke *)(*(pmsg->msgbody)); 
  1313. write_variable_value(submit_sm->msisdnlen, oc1byte); /*msisdn len*/
  1314. line_append_hex_IA5(IA5msg, oc1byte,1);
  1315. line_append_hex_IA5(IA5msg, 
  1316.     octstr_get_cstr(submit_sm->msisdn),
  1317.     octstr_len(submit_sm->msisdn)); /*msisdn*/
  1318. write_variable_value(submit_sm->smereftype, oc1byte);/*smetype*/
  1319. line_append_hex_IA5(IA5msg, oc1byte,1);
  1320. line_append_hex_IA5(IA5msg, submit_sm->smerefnum,4);/*sme reference*/
  1321. write_variable_value(submit_sm->priority, oc1byte);/*priority*/
  1322. line_append_hex_IA5(IA5msg, oc1byte,1);
  1323. write_variable_value(submit_sm->origaddlen, oc1byte); /*orignating address length*/
  1324. line_append_hex_IA5(IA5msg, oc1byte,1);
  1325. line_append_hex_IA5(IA5msg, 
  1326.     octstr_get_cstr(submit_sm->origadd),
  1327.     octstr_len(submit_sm->origadd)); /*orignating address*/
  1328. write_variable_value(submit_sm->validperiodtype, oc1byte); /*valid period type*/
  1329. line_append_hex_IA5(IA5msg, oc1byte,1);
  1330. write_variable_value(submit_sm->validperiodrela, oc1byte); /*relative period*/
  1331. line_append_hex_IA5(IA5msg, oc1byte,1);
  1332. write_variable_value(submit_sm->DCS, oc1byte);/*data code scheme*/
  1333. line_append_hex_IA5(IA5msg, oc1byte,1);
  1334. write_variable_value(submit_sm->statusreportrequest, oc1byte);/*request report*/
  1335. line_append_hex_IA5(IA5msg, oc1byte,1);
  1336. write_variable_value(submit_sm->protocal, oc1byte);/*protocal id*/
  1337. line_append_hex_IA5(IA5msg, oc1byte, 1);
  1338. write_variable_value(submit_sm->replypath, oc1byte);/*use reply path*/
  1339. line_append_hex_IA5(IA5msg, oc1byte, 1);
  1340.             /*text size in 7 bits char*/
  1341.        tSize = internal_char_hex_to_IA5(submit_sm->textsizeseptet,oc1byte);
  1342. octstr_insert_data(IA5msg, octstr_len(IA5msg), oc1byte, tSize);
  1343.             /*text size in 8 bits char*/
  1344. tSize = internal_char_hex_to_IA5(submit_sm->textsizeoctect,oc1byte);  
  1345.   octstr_insert_data(IA5msg, octstr_len(IA5msg), oc1byte, tSize);
  1346. line_append_hex_IA5(IA5msg,       
  1347.     octstr_get_cstr(submit_sm->shortmsg),
  1348.     submit_sm->textsizeoctect); /*msg text*/
  1349. memcpy(str,octstr_get_cstr(IA5msg),octstr_len(IA5msg));
  1350. octstr_destroy(IA5msg);
  1351. return 1;
  1352.     }
  1353.     return 0;
  1354. }
  1355. static int line_scan_hex_GSM7(unsigned char* from, 
  1356.       int octects ,int spetets, unsigned char* to)
  1357. {
  1358.     char* cin2 =NULL;
  1359.     unsigned char c;
  1360.     char cin7[8];
  1361.     int i, pos, value;
  1362.     int lenin2=octects*8;
  1363.     cin2 = gw_malloc(lenin2);
  1364.     memset(cin2,48,lenin2); /*make many zeros*/
  1365.     /*tranverse the octects first, so ABC -> CBA(in bin form)*/
  1366.     for(i = 0; i < octects; i ++)
  1367.     {
  1368. c = *(from + i);
  1369.       
  1370. if(c & 1) 
  1371.     cin2[(octects-1-i)*8 +7] = 49;
  1372. if(c & 2) 
  1373.     cin2[(octects-1-i)*8 +6] = 49;
  1374. if(c & 4) 
  1375.     cin2[(octects-1-i)*8 +5] = 49;
  1376. if(c & 8) 
  1377.     cin2[(octects-1-i)*8 +4] = 49;
  1378. if(c & 16) 
  1379.     cin2[(octects-1-i)*8 +3] = 49;
  1380. if(c & 32) 
  1381.     cin2[(octects-1-i)*8 +2] = 49;
  1382. if(c & 64) 
  1383.     cin2[(octects-1-i)*8 +1] = 49;
  1384. if(c & 128) 
  1385.     cin2[(octects-1-i)*8] = 49;
  1386.     }
  1387.   
  1388.     i= 1;
  1389.     while( i <= spetets ){
  1390. pos=lenin2 -1 -(i*7 -1);
  1391. memset(cin7,0,sizeof(cin7));
  1392. memcpy(cin7, cin2 + pos, 7);
  1393. value = 0;
  1394. if(cin7[6] == '1')
  1395.     value += 1;
  1396. if(cin7[5] == '1')
  1397.     value += 2;
  1398. if(cin7[4] == '1')
  1399.     value += 4;
  1400. if(cin7[3] == '1')
  1401.     value += 8;
  1402. if(cin7[2] == '1')
  1403.     value += 16;
  1404. if(cin7[1] == '1')
  1405.     value += 32;
  1406. if(cin7[0] == '1')
  1407.     value += 64;
  1408.   
  1409. to[i-1]=internal_char_hex_to_gsm(value);
  1410. i +=1;
  1411.     }
  1412.     return i;
  1413.   
  1414. }
  1415. /* check SMS2000 Version 4.0 B.4.2.3 */
  1416. static int line_append_hex_IA5(Octstr* des, unsigned char* src, int len)
  1417. {
  1418.     unsigned char IA5char[3];
  1419.     unsigned char tmp[1024];
  1420.     int j=0;
  1421.     int i=0, iall=0;
  1422.     for(i=0; i<len; i++)
  1423.     {
  1424. memset(IA5char, 0, sizeof(IA5char));
  1425. j=internal_char_hex_to_IA5(*(src+i),IA5char);
  1426. if(j >0){
  1427.     memcpy(tmp+iall,IA5char,j);
  1428.     iall += j;
  1429. }
  1430.     }
  1431.     octstr_insert_data(des,octstr_len(des),tmp,iall);
  1432.     return iall;
  1433. }
  1434. /* check SMS2000 Version 4.0 B.4.2.3 */
  1435. static int line_scan_IA5_hex(unsigned char* from, 
  1436.      int hexnum, unsigned char* to)
  1437. {
  1438.     unsigned char cha[1];
  1439.     int cn =0, cnall = 0, i = 0;
  1440.     char *tmpfrom = NULL;
  1441.     tmpfrom = from;
  1442.     for(i = 0; i< hexnum; i++)
  1443.     {
  1444. cn=internal_char_IA5_to_hex(tmpfrom, cha);
  1445. if(cn >0)
  1446. {
  1447.     memcpy(to+i,cha,1);
  1448.     tmpfrom += cn;
  1449.     cnall += cn;
  1450. }
  1451. else
  1452.     return -1;
  1453.     }
  1454.     return cnall;
  1455. }
  1456. static unsigned char internal_char_hex_to_gsm(unsigned char from)
  1457. {
  1458.     switch (from){
  1459.     case 0x00: return '@';
  1460.     case 0x01: return '