📄 smsc_sema.c
字号:
return 1; } } return 0;datalink_error: error(errno,"sema_close_send_link, device file error"); return -1;}static int X28_open_send_link(int padfd, char *nua) { char readbuff[1024]; char writebuff[129]; char smscbuff[129]; int readall = 0, readonce = 0, writeonce = 0, writeall = 0, i = 0; char X28prompt[]="*\r\n\0"; time_t timestart; debug("smsc.sema", 0, "sema_open send link: call smsc <%s> for <%i> seconds", nua, (int)INTERNAL_CONNECT_TIMEVAL); /* type few <cr> to invoke DTE */ writebuff[0] = '\r'; memset(readbuff,0,sizeof(readbuff)); for(i = 0; i <= 3; i++) { readonce = writeonce = -1; writeonce = write(padfd, writebuff, 1); if(writeonce < 1){ if(errno == EINTR || errno == EAGAIN) continue; else{ goto datalink_error; } } usleep(1000); /* wait for prompt */ readonce = read(padfd, &readbuff[readall],1024); if(readonce == -1){ if(errno == EINTR || errno == EAGAIN) continue; else{ goto datalink_error; } } else readall += readonce; } if(strstr(readbuff, X28prompt) == NULL){ warning(0,"X28_open_send_link: can not read command prompt, abort"); return 0; } /* second, connect to the smsc now */ memset(writebuff,0,sizeof(writebuff)); memset(readbuff,0,sizeof(readbuff)); writeall = readall = 0; sprintf(writebuff, "%s\r", nua); sprintf(smscbuff, "%s COM",nua); while((size_t) writeall < strlen(writebuff)){ writeonce = -1; writeonce = write(padfd, writebuff+writeall, strlen(writebuff)-writeall); if(writeonce == -1){ if(errno == EINTR || errno == EAGAIN) continue; else goto datalink_error; } if(writeonce > 0) writeall +=writeonce; } tcdrain(padfd); usleep(1000*1000);/* wait for smsc answer */ time(×tart); while(time(NULL) - timestart < INTERNAL_CONNECT_TIMEVAL){ if((size_t) readall >= sizeof(readbuff)) goto error_overflow; /* We read 1 char a time */ readonce = read(padfd, &readbuff[readall], 1); if(readonce == -1) { if(errno == EINTR || errno == EAGAIN) continue; else goto datalink_error; } if(readonce > 0) readall += readonce; /* Search for reponse line. */ if(readall > 2 && readbuff[readall-1] == '\n' && readbuff[readall-2] == '\r') { if(strstr(readbuff, smscbuff)) { debug("smsc.sema", 0, "sema_open send link: smsc respond, virtual link established"); x28_data_mode = X28_MT_DATA_MODE; return 1; } } usleep(1000); } info(0,"sema_open_send_link: connecting time out"); return 0;error_overflow: warning(0, "sema_open_send_link: command buffer overflow"); return 0;datalink_error: error(errno,"sema_open_send_link: device file error"); return -1;}static int X28_data_read(int padfd, char *cbuffer) { char *p = NULL; int ret, len; fd_set read_fd; struct timeval tv, tvinit; size_t readall; tvinit.tv_sec = 0; tvinit.tv_usec = 1000; readall = 0; for (;;) { FD_ZERO(&read_fd); FD_SET(padfd, &read_fd); tv = tvinit; ret = select(padfd + 1, &read_fd, NULL, NULL, &tv); if (ret == -1) { if(errno==EINTR) goto got_data; if(errno==EAGAIN) goto got_data; error(errno, "Error doing select for fad"); return -1; } else if (ret == 0) goto got_data; len = strlen(cbuffer); ret = read(padfd, cbuffer + len, 256); if (ret == -1) { error(errno," read device file"); return -1; } if (ret == 0) goto eof; readall += ret; if ((size_t) len > sizeof(cbuffer)- 256) { p = gw_realloc(cbuffer, sizeof(cbuffer) * 2); memset(p+len,0,sizeof(cbuffer)*2 - len); cbuffer = p; } if(readall > 0) break; } eof: if(readall > 0) ret = 1; goto unblock; got_data: ret = 0; goto unblock;unblock: return ret; }static int X28_data_send(int padfd, char *cbuffer,int sentonce) { int len = 0, pos = 0,writeonce = 0,writeall = 0; tcdrain(padfd); len = strlen(cbuffer); while(len > 0){ if(len < sentonce) { writeonce = write(padfd, cbuffer+pos, len); } else writeonce = write(padfd, cbuffer+pos, sentonce); if (writeonce == -1) { if(errno == EINTR || errno == EINTR) continue; else{ goto error; } } if(writeonce > 0){ len -= writeonce; pos += writeonce; writeall = pos; } } tcdrain(padfd); return writeall;error: error(errno,"sema_send data error: device file erro"); return -1;}static int X28_msg_pop(char *from, char *to){ char* Rbuff =NULL; char* RRbuff = NULL; char mobuff[] ="COM\r\n\0"; char mobuffend[] = "\r\0"; char prompbuff[] = "*\r\0"; int len = 0, Llen= 0, Rlen = 0,RRlen = 0; len = strlen(from); if(len <=0) goto no_msg; /* trim off rabbish header */ while(*from == '\r' || *from == '\n'){ len = strlen(from); if(len > 1){ memmove(from, from +1, len-1); memset(from+(len-1), 0, 1); } else{ memset(from,0,len); return -1; } } len = strlen(from); /*all kinds of useful infomation contains \r*/ if((Rbuff=memchr(from,'\r',len)) == NULL) goto no_msg; /*check if it is a command prompt *\r\n */ if((Rbuff -from) > 0 && *(Rbuff -1) == '*'){ if(strlen(Rbuff) < 2) goto no_msg; /*\n is not coming yet*/ if(Rbuff -from > 4){ /* command info */ Rlen = Rbuff -1 -from; memcpy(to,from,Rlen); } x28_data_mode = X28_COMMAND_MODE; if(strlen(Rbuff+1) > 1){ Rlen = strlen(Rbuff +2); memmove(from, Rbuff +2, Rlen); memset(from+Rlen, 0, len-Rlen); } else memset(from, 0,len); }/* check mo msg , format X121address+COM\r\n+msg+\r*/ else if((Rbuff-from) > 3 && strstr(Rbuff-4,mobuff)!= NULL){ if(strlen(Rbuff) < 3 || (RRbuff = strstr(Rbuff + 2, mobuffend)) == NULL) goto no_msg; /*the msg+\r is still coming*/ RRlen = RRbuff - (Rbuff+2); if(RRlen > 4){ /* msg header is 4 byte always+msg content*/ memcpy(to, Rbuff +2 , RRlen); x28_data_mode = X28_MO_DATA_MODE; } if(strlen(RRbuff) > 1){ Rlen = strlen(RRbuff +1); memmove(from, RRbuff+1 ,Rlen); memset(from+Rlen,0,len -Rlen); } else memset(from,0,len); } else{/* it can be mt reply */ if(Rbuff - from > 0){ Llen = Rbuff - from; memcpy(to, from, Llen); } if(strlen(Rbuff) > 1){ Rlen = strlen(Rbuff+1); memmove(from,Rbuff+1,Rlen); memset(from+Rlen,0,len-Rlen); } else memset(from,0,len); } /* check rest line for link state: command mode or data mode */ if(strstr(from,prompbuff) != NULL) x28_data_mode = X28_COMMAND_MODE; return 0;no_msg: return -1;}static int sema_submit_result(SMSCenter *smsc, sema_msg* srcmsg, int result){ char IA5buff[1024]; unsigned char oct1byte[1]; unsigned char ia5byte[2]; unsigned char cTr='t'; unsigned char cMr='m'; unsigned char ccontinuebyte = 'P', ccr = '\r'; int j = 0, iret; memset(IA5buff,0,sizeof(IA5buff)); switch(srcmsg->type) { case 'M': memcpy(IA5buff,&cMr,1);/*msg type*/ memcpy(IA5buff+1,&ccontinuebyte,1); /*continue bit*/ memcpy(IA5buff+2,srcmsg->optref,4); /*operation reference*/ write_variable_value(result,oct1byte); j=internal_char_hex_to_IA5(oct1byte[0],ia5byte); memcpy(IA5buff+6,ia5byte,j); memcpy(IA5buff+6+j,&ccr,1);/*result*/ iret = X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff)); if(iret == -1) goto error; break; case 'T': memcpy(IA5buff,&cTr,1); memcpy(IA5buff+1,&ccontinuebyte,1); memcpy(IA5buff+2,srcmsg->optref,4); write_variable_value(result,oct1byte); j=internal_char_hex_to_IA5(oct1byte[0],ia5byte); memcpy(IA5buff+6,ia5byte,j); memcpy(IA5buff+6+j,&ccr,1); iret = X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff)); if(iret == -1) goto error; break; default: return 0; /*unsupoorted result msg type*/ } return 1; error: error(0,"sk_submit_result: write to device file failed"); return -1;}static int sema_msg_session_mt(SMSCenter *smsc, sema_msg* pmsg){ struct msg_hash *segments = NULL; struct sema_msg* mtrmsg = NULL; struct sm_statusreport_invoke* report_invoke = NULL; struct sm_submit_result* submit_result = NULL; struct sm_submit_invoke* submit_invoke = NULL; struct sm_deliver_invoke* deliver_invoke = NULL; char data[1024], IA5buff[256], IA5chars[1024], mochars[10*1024]; unsigned char ccontinuebyte, ccr = '\r'; unsigned char cerr[] = "ERR\0",cclr[] = "CLR\0", tmp1[5] , tmp2[5]; int i, iseg = 0, ilen = 0,iret = 0, moret; int isrcved = 0, iTrcved = 0, decoderesult = 0; time_t tstart; submit_invoke=(struct sm_submit_invoke*)(*(pmsg->msgbody)); if(submit_invoke == NULL) goto error; /*encode first*/ memset(IA5chars,0,sizeof(IA5chars)); if(sema_encode_msg(pmsg, IA5chars) < 1) goto encode_error; /*divide segments, we send buffer no more than 128 byte once*/ iseg = strlen(IA5chars)/121 + 1; segments = gw_malloc(iseg * sizeof(struct msg_hash)); if(segments == NULL) goto error; /*first segments*/ if(strlen(IA5chars) < 121) ilen = strlen(IA5chars); else ilen = 121; segments[0].content = octstr_create_from_data(&(pmsg->type), 1);/*msg type, in hex*/ ccontinuebyte = pack_continous_byte(pmsg->encodetype, 1, iseg -1); octstr_insert_data(segments[0].content, 1, &ccontinuebyte, 1); /*continue char, in hex*/ octstr_insert_data(segments[0].content, 2, pmsg->optref, 4); /*operation reference, in hex*/ octstr_insert_data(segments[0].content, 6, IA5chars, ilen); octstr_insert_data(segments[0].content, octstr_len(segments[0].content), &ccr, 1); /*<cr>*/ /*rest segments*/ for( i = 1; i < iseg; i++){ if(strlen(IA5chars) - i*121 < 121) ilen = strlen(IA5chars) - i*121; else ilen =121; segments[i].content= octstr_create_from_data(&(pmsg->type), 1); ccontinuebyte = pack_continous_byte(pmsg->encodetype, 0, iseg -i-1); octstr_insert_data(segments[i].content, 1, &ccontinuebyte, 1); octstr_insert_data(segments[i].content, 2, pmsg->optref, 4); octstr_insert_data(segments[i].content, 6, IA5chars + i*121, ilen); octstr_insert_data(segments[i].content, octstr_len(segments[i].content), &ccr, 1); } if(x28_data_mode != X28_MT_DATA_MODE){ /* do not trust any existing data mode*/ X28_close_send_link(smsc->sema_fd); /*open send link*/ if((iret = X28_open_send_link(smsc->sema_fd,smsc->sema_smscnua)) < 1){ if(iret == -1){ iret = X28_reopen_data_link(smsc->sema_fd, smsc->sema_serialdevice); if(iret == -1){ goto error; } } X28_close_send_link(smsc->sema_fd); sleep(1); iret = X28_open_send_link(smsc->sema_fd,smsc->sema_smscnua); if(iret < 1) goto sendlink_error; } } /*deliver buff*/ for(i = 0; i < iseg; i++){ memset(IA5buff,0,sizeof(IA5buff)); memcpy(IA5buff,octstr_get_cstr(segments[i].content), octstr_len(segments[i].content)); iret =X28_data_send(smsc->sema_fd,IA5buff,strlen(IA5buff)); if(iret == -1) goto error; octstr_destroy(segments[i].content); } gw_free(segments); /*wait result and report return*/ mtrmsg = sema_msg_new(); memset(mochars,0,sizeof(mochars)); time(&tstart); while(time(NULL) -tstart < INTERNAL_SESSION_MT_TIMEVAL){ iret = X28_data_read(smsc->sema_fd, smsc->buffer); if(iret == -1) goto error; /* Interpret the raw data */ memset(data,0,sizeof(data)); while(X28_msg_pop(smsc->buffer, data) == 0 ) { if(strlen(data) > 0){ if(strstr(data,cerr) != NULL || strstr(data,cclr) != NULL){ debug("smsc.sema", 0, "sema_mt_session: Radio Pad Command line-%s",data); goto sendlink_error; } /* decode msg*/ decoderesult = sema_decode_msg(&mtrmsg,data); if(decoderesult >= 0){ if(mtrmsg->type == 's'){ /*submit result*/ submit_result = (struct sm_submit_result*)(*mtrmsg->msgbody); if(submit_result == NULL) goto error; /* check result operation number is what we send */ memset(tmp1,0,5); memset(tmp2,0,5); memcpy(tmp1,mtrmsg->optref,4); memcpy(tmp2, pmsg->optref,4); if(strstr(tmp1,tmp2) != NULL){ isrcved = 1; memcpy(submit_invoke->smscrefnum, submit_result->smscrefnum,4); } if(isrcved == 1 && submit_result->smeresult != 0){ gw_free(submit_result); goto smsc_say_fail; } gw_free(submit_result); } else if(mtrmsg->type == 'T'){ /*report invoke*/ report_invoke=(struct sm_statusreport_invoke*)(*mtrmsg->msgbody); if(report_invoke == NULL) goto error; /*check if report reference number is what we expect*/ memset(tmp1,0,sizeof(tmp1)); memset(tmp2,0,sizeof(tmp2)); memcpy(tmp1,report_invoke->smscrefnum,4); memcpy(tmp2,submit_invoke->smscrefnum,4); if(strstr(tmp1, tmp2) != NULL){ iTrcved = 1; } decoderesult = 0; iret = sema_submit_result(smsc, mtrmsg, decoderesult); if(iret == -1) goto error; if(iTrcved == 1 && report_invoke->status != 3){ /*3 means ,msg delivered*/ info(0,"sema_mt_session: submit invoke failed with report value-%i",report_invoke->status); gw_free(report_invoke); goto smsc_say_fail; } gw_free(report_invoke); } else if(mtrmsg->type == 'M'){/* deliver invoke*/ /* we do not deal with deliver in mt session*/ decoderesult = 0; iret = sema_submit_result(smsc, mtrmsg, decoderesult); if(iret == -1) goto error; deliver_invoke =(struct sm_deliver_invoke*)(*mtrmsg->msgbody); if(deliver_invoke != NULL){ gw_free(deliver_invoke); /*append buffer back to smsc->buffer*/ ilen=strlen(mochars); memcpy(mochars+ilen,data,strlen(data)); ilen=strlen(mochars); memcpy(mochars+ilen,&ccr,1); } time(&tstart); } /* clean msg for next read*/ memset(mtrmsg,0,sizeof(struct sema_msg)); } /* clean buffer for next useful info*/ memset(data,0,sizeof(data)); if(sema_wait_report == 0 && isrcved == 1) { info(0,"sema_mt_session: submit invoke deliver successfully to smsc"); goto mo_success; } if(sema_wait_report > 0 && isrcved == 1 && iTrcved == 1) { info(0,"sema_mt_session: submit invoke deliver sucessfully to msisdn"); goto mo_success; } } } }/* mo_timeout: */ info(0,"sema_mt_session: time out without receive all expected return"); moret = SESSION_MT_RECEIVE_TIMEOUT; goto mo_return;mo_success: moret = SESSION_MT_RECEIVE_SUCCESS; goto mo_return;smsc_say_fail:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -