?? smsc_sema.c
字號:
/* * smsc_sema.c - implement sms2000 protocal by using X25 access * the data communication layer is implemented by using X28 protocol * * Code implement submit invoke, status invoke, deliver invoke session * there is no internal db for storing delivered and undelivered message * * IA5 is most common line coding scheme. * smsc_sema support only IA5 encoding, hex and binary line encoding is not * supported. * * smsc_sema support IA5 and GSM Data Code Scheme for delivered invoke message * smsc_sema support only IA5 Data Code Scheme for submit invoke message * * Reference : SMS2000 Version 4.0 Open Interface Specification * Open Source WAP Gateway Architecture Design * ESTI GSM 03.40 * * Hao Shi 2000 */#include <errno.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <termios.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/param.h>#include <netinet/in.h>#include <netdb.h>#include "gwlib/gwlib.h"#include "smsc.h"#include "smsc_p.h"#include "alt_charsets.h"#include "smsc_sema.h"#include "sms.h"#ifndef CRTSCTS#define CRTSCTS 0#endifstatic unsigned char sema_counter[4] = "0000";static int sema_wait_report = 1;static int x28_data_mode = X28_COMMAND_MODE;SMSCenter * sema_open(char* smscnua, char* homenua, char* serialdevice, int waitreport){ SMSCenter *smsc; int nret = -1; smsc = smscenter_construct(); if(smsc == NULL) goto error; sprintf(smsc->name, "SEMA:X28:"); smsc->type = SMSC_TYPE_SEMA_X28; smsc->sema_smscnua = gw_strdup(smscnua); smsc->sema_homenua = gw_strdup(homenua); smsc->sema_serialdevice = gw_strdup(serialdevice); sema_wait_report = waitreport; smsc->sema_mt = sema_msglist_new(); if(smsc->sema_mt == NULL) goto error; smsc->sema_mo = sema_msglist_new(); if(smsc->sema_mo == NULL) goto error; /* Open the device properly. Remember to set the access codes correctly. */ debug("smsc.sema", 0, "sema_open: open datalink"); smsc->sema_fd = X28_open_data_link(smsc->sema_serialdevice); if(smsc->sema_fd == -1) goto error; /* test the outgoing callX28 to smsc center */ debug("smsc.sema", 0, "sema_open: test send link"); nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua); if(nret < 1){ sleep(2); nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua); if(nret < 1) goto error; } X28_close_send_link(smsc->sema_fd); return smsc;error: error(0, "sema_open: could not open"); smscenter_destruct(smsc); return NULL;}int sema_reopen(SMSCenter *smsc){ int nret = 0; debug("smsc.sema", 0, "reopening the connection"); /*deallocate*/ sema_msglist_free(smsc->sema_mt); sema_msglist_free(smsc->sema_mo); /*reallocate*/ smsc->sema_mt = sema_msglist_new(); if(smsc->sema_mt == NULL) goto error; smsc->sema_mo = sema_msglist_new(); if(smsc->sema_mo == NULL) goto error; memset(smsc->buffer,0,sizeof(smsc->buffer)); /* Open the device properly. Remember to set the access codes correctly. */ smsc->sema_fd = X28_reopen_data_link(smsc->sema_fd, smsc->sema_serialdevice); if(smsc->sema_fd == -1){ error(0,"sema_reopen_data_link: device file error"); goto error; } /*test outgoing call to the smsc */ nret = X28_open_send_link(smsc->sema_fd, smsc->sema_smscnua); if(nret < 1){ error(0,"test send data link failed"); goto error; } X28_close_send_link(smsc->sema_fd); return 0;error: error(0, "sema_reopen_data_link: failed"); return -1; }int sema_close(SMSCenter *smsc){ if(smsc->sema_fd > 0) close(smsc->sema_fd); /*deallocate*/ sema_msglist_free(smsc->sema_mt); sema_msglist_free(smsc->sema_mo); return 0;}int sema_submit_msg(SMSCenter *smsc, Msg *msg){ int nret = 0; struct sema_msg *lmsg = NULL; struct sm_submit_invoke *submit_sm = NULL; char x28sender[2] = "A3"; /* Validate msg */ if(smsc == NULL){ error(0,"sema_submit_msg: SMSC is empty"); goto error; } if(msg == NULL){ error(0, "sema_submit_msg: Msg is empty"); goto error; } if(msg_type(msg) != sms) { error(0, "sema_submit_sms: Msg is WRONG TYPE"); goto error; } /* user data header is not supported in sm2000 X25 access if(msg->sms.coding == DC_7BIT){ error(0, "sema_submit_sms: submit invoke support in IA5 encoding(8 bits chars)"); goto error; } if(octstr_len(msg->sms.udhdata)){ error(0, "sema_submit_sms: submit invoke not support in IA5 encoding "); goto error; } */ lmsg = sema_msg_new(); submit_sm = gw_malloc(sizeof(struct sm_submit_invoke)); memset(submit_sm, 0, sizeof(struct sm_submit_invoke)); lmsg->type = 'S'; lmsg->encodetype = LINE_ENCODE_IA5; /* set operation reference */ increment_counter(); memcpy(lmsg->optref,sema_counter,4); /*set sme reference number*/ increment_counter(); memcpy(submit_sm->smerefnum, sema_counter, 4); /*we send as not key type*/ submit_sm->smereftype= 2; /*key type is 1*/ /*we set prority as normal*/ submit_sm->priority = 1; /*0 is high*/ /*set valid period type as relative*/ submit_sm->validperiodtype = 2; /* 1 is absolute */ /*time*/ submit_sm->validperiodrela = 1; /* from 0 to 143 , fomula is (V+1)*5 min*/ /*send msg without 00 header*/ submit_sm->msisdnlen= octstr_len(msg->sms.receiver); submit_sm->msisdn = octstr_copy(msg->sms.receiver,0,submit_sm->msisdnlen); /* X25 access will always append sender during data transfer */ submit_sm->origaddlen= 2; /* we need only to orignate address type */ submit_sm->origadd = octstr_create_from_data(x28sender,2); /*data encoding scheme ,support only IA5 in current version*/ submit_sm->DCS = 15; /*gsm is 0 ,IA5 is 15*/ /*protocal ,support only default value 0 in current version*/ submit_sm->protocal = 0; /*replypath*/ submit_sm->replypath= 0; /*gateway do not pay for reply*/ /*status report*/ if(sema_wait_report > 0) submit_sm->statusreportrequest =4; /* deliver success, in bin form 00000100*/ else submit_sm->statusreportrequest = 0;/* no report */ /* we support submit invoke only in IA5 line encoding*/ submit_sm->textsizeoctect = submit_sm->textsizeseptet = octstr_len(msg->sms.msgdata); /*copy msg buffer*/ submit_sm->shortmsg = octstr_copy(msg->sms.msgdata, 0, submit_sm->textsizeoctect); memset(submit_sm->smscrefnum,0,sizeof(submit_sm->smscrefnum)); /*pack the message body in 2kmsg*/ lmsg->msgbody = (void**)(&submit_sm); nret = sema_msg_session_mt(smsc, lmsg); gw_free(submit_sm); submit_sm = NULL; sema_msg_free(lmsg); lmsg = NULL; if(nret == SESSION_MT_RECEIVE_SUCCESS){ debug("smsc.sema", 0, "sema_submit_msg: message is successfully delivered"); return 1; /*success*/ } else if(nret == SESSION_MT_RECEIVE_TIMEOUT){ info(0, "sema_submit msg: session time out without return"); return 0; } else if(nret == SESSION_MT_RECEIVE_ERR){ info(0, "sema_submit msg: smsc say submit failed!"); return 0; } return 1; error: if(submit_sm) gw_free(submit_sm); if(lmsg) sema_msg_free(lmsg); return -1;}int sema_receive_msg(SMSCenter *smsc, Msg **msg){ struct sema_msg *rmsg = NULL; struct sm_deliver_invoke *recieve_sm = NULL; while(sema_msglist_pop(smsc->sema_mo, &rmsg) == 1 ) { *msg = msg_create(sms); if(*msg==NULL) goto error; recieve_sm = (struct sm_deliver_invoke*) (*(rmsg->msgbody)); if(recieve_sm==NULL) goto error; /* as IA5(8 bit character) is the default line encoding used by X28 * and we do not support other line encoding scheme like binary or * hex encoding */ (*msg)->sms.coding = DC_8BIT; /* OIS in X28 implementation does not include udh field */ (*msg)->sms.sender = octstr_create_from_data( octstr_get_cstr(recieve_sm->origadd) +2, octstr_len(recieve_sm->origadd)-2); (*msg)->sms.receiver = octstr_create_from_data( octstr_get_cstr(recieve_sm->destadd) +2, octstr_len(recieve_sm->destadd)-2); (*msg)->sms.msgdata = octstr_duplicate(recieve_sm->shortmsg); (*msg)->sms.udhdata = octstr_create(""); gw_free(recieve_sm); sema_msg_free(rmsg); rmsg = NULL; } return 1;error: error(0, "sema_receive_msg: can not create Smart Msg"); return -1;}int sema_pending_smsmessage(SMSCenter *smsc){ char data[1024]; int ret = 0; char clrbuff[]="CLR\0"; char errbuff[]="ERR\0"; /* struct sema_msg* smsg = NULL;*/ /* Receive raw data */ ret = X28_data_read(smsc->sema_fd, smsc->buffer); if(ret == -1) { ret = X28_reopen_data_link(smsc->sema_fd, smsc->sema_serialdevice); if(ret == -1) goto error; return 0; } /* Interpret the raw data */ memset(data,0,sizeof(data)); while(X28_msg_pop(smsc->buffer, data) == 0 ) { if(strlen(data) > 0){ if(strstr(data,clrbuff) != NULL || strstr(data,errbuff) != NULL){ debug("smsc.sema", 0, "sema_pending_msg: Radio Pad Command line-%s",data); } else{ ret = sema_msg_session_mo(smsc, data); if(ret == -1) goto error; } memset(data,0,sizeof(data)); } } /* Signal that we got a MO message if mo list is not empty*/ if(smsc->sema_mo->first != NULL){ return 1; } return 0;error: error(0,"sema_pending message: device file error"); return -1;}static sema_msg* sema_msg_new(void){ struct sema_msg *msg = NULL; msg = gw_malloc(sizeof(struct sema_msg)); memset(msg, 0, sizeof(struct sema_msg)); return msg;}static int sema_msg_free(sema_msg *msg) { if(msg == NULL) return 0; gw_free(msg); return 1;}static sema_msglist* sema_msglist_new(void) { struct sema_msglist *mlist = NULL; mlist = gw_malloc(sizeof(struct sema_msglist)); memset(mlist, 0, sizeof(struct sema_msglist)); mlist->first = NULL; mlist->last = NULL; mlist->count = 0; return mlist;}static void sema_msglist_free(sema_msglist *mlist) { struct sema_msg *pmsg = NULL; if(mlist == NULL) return; while( sema_msglist_pop(mlist, &pmsg) == 1 ) { if(pmsg==NULL) break; sema_msg_free(pmsg); pmsg = NULL; } gw_free(mlist); mlist->count = 0;}static int sema_msglist_push(sema_msglist *plist, sema_msg *pmsg) { struct sema_msg * lmsg = NULL; if(plist == NULL) { info(0, "msglist_push: NULL msg list"); goto error; } if(pmsg == NULL) { info(0, "msglist_push: NULL input"); goto error; } /* If list is completely empty. */ if( plist->first == NULL ) { plist->last = pmsg; plist->first = pmsg; pmsg->prev = NULL; pmsg->next = NULL; } else{ lmsg=plist->last; lmsg->next=pmsg; pmsg->prev=lmsg; pmsg->next=NULL; plist->last=pmsg; } plist->count += 1; return 1;error: error(0, "msglist_push: error"); return 0;}static int sema_msglist_pop(sema_msglist *plist, sema_msg **msg) { if(plist == NULL) { info(0, "msglist_pop: NULL list"); goto no_msg; } if(plist->first == NULL) { goto no_msg; } *msg = plist->first; if(plist->last == *msg) { plist->first = NULL; (*msg)->prev = NULL; plist->last = NULL; } else { plist->first = (*msg)->next; plist->first->prev = NULL; if(plist->first->next == NULL) plist->last = plist->first; } plist->count -= 1; return 1;no_msg: return 0;}static int X28_open_data_link(char* device){ int fd = -1, iret; struct termios tios; info(0,"open serial device %s",device); fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY); if(fd==-1) { error(errno, "sema_open_data_link: error open(2)ing the character device <%s>", device); if(errno == EACCES) error(0, "sema_open_data_link: user have no right to access the serial device"); return -1; } tcgetattr(fd, &tios); cfsetospeed(&tios, B4800); /* check radio pad parameter*/ cfsetispeed(&tios, B4800); kannel_cfmakeraw(&tios); tios.c_iflag |= IGNBRK|IGNPAR|INPCK|ISTRIP; tios.c_cflag |= (CSIZE|HUPCL | CREAD | CRTSCTS); tios.c_cflag ^= PARODD; tios.c_cflag |=CS7; iret = tcsetattr(fd, TCSANOW, &tios); if(iret == -1){ error(errno,"sema_open_data_link: fail to set termios attribute"); goto error; } tcflush(fd, TCIOFLUSH); return fd; error: return -1;}static int X28_reopen_data_link(int oldpadfd ,char* device){ int nret = 0; if(oldpadfd > 0){ nret= close(oldpadfd); if(nret == -1){ error(errno,"sema_reopen_data_link: close device file failed!!"); } } sleep(1); return X28_open_data_link(device);} static int X28_close_send_link(int padfd){ unsigned char discnntbuff[5]; unsigned char readbuff[1024]; unsigned char finishconfirm[]="CLR CONF\0"; int nret = 0, readall = 0; time_t tstart; time(&tstart); sprintf(discnntbuff,"%cCLR\r",0x10); memset(readbuff,0,sizeof(readbuff)); /* what ever is the close return, data mode is unreliable now*/ x28_data_mode = X28_COMMAND_MODE; if(padfd <= 0) goto datalink_error; while((time(NULL) - tstart) < INTERNAL_DISCONNECT_TIMEVAL){ nret =write(padfd, discnntbuff, 5); if(nret == -1){ if(errno == EAGAIN || errno ==EINTR) continue; else{ goto datalink_error; } } sleep(1); /*wait 1 senconds for virtual link break*/ nret=read(padfd, readbuff+readall,128); if(nret == -1){ if(errno == EAGAIN || errno ==EINTR) continue; else{ goto datalink_error; } } if(nret >0){ readall += nret; if(strstr(readbuff,finishconfirm))
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -