📄 smsc_at.c
字号:
message->sms.sender = origin; /* Put a dummy address in the receiver for now (SMSC requires one) */ message->sms.receiver = octstr_create_from_data("1234", 4); /*message->sms.receiver = destination;*/ if (udhi) { message->sms.udhdata = udh; } message->sms.msgdata = text; message->sms.time = stime; /* cleanup */ octstr_destroy(pdu); octstr_destroy(tmpstr); return message;}/****************************************************************************** * Encode a Msg into a PDU */static int pdu_encode(Msg *msg, unsigned char *pdu, SMSCenter *smsc) { int pos = 0, i,len, setvalidity=0; int ntype = PNT_UNKNOWN; /* number type default */ int nstartpos = 0; /* offset for the phone number */ int dcs; /* data coding scheme (GSM 03.38) */ /* The message is encoded directly in the text representation of * the hex values that will be sent to the modem. * Each octet is coded with two characters. */ /* message type SUBMIT * 01010001 = 0x51 indicating add. UDH, TP-VP(Rel) & MSG_SUBMIT * or 00010001 = 0x11 for just TP-VP(Rel) & MSG_SUBMIT */ pdu[pos] = octstr_len(msg->sms.udhdata) ? numtext(5) : numtext(1); pos++; pdu[pos] = numtext(AT_SUBMIT_SM); pos++; /* message reference (0 for now) */ pdu[pos] = numtext(0); pos++; pdu[pos] = numtext(0); pos++; /* destination address */ octstr_strip_blanks(msg->sms.receiver); /* strip blanks before length calculation */ len = octstr_len(msg->sms.receiver); /* Check for international numbers * number starting with '+' or '00' are international, * others are national. */ if (strncmp(octstr_get_cstr(msg->sms.receiver), "+", 1) == 0) { debug("AT", 0, "international starting with + (%s)",octstr_get_cstr(msg->sms.receiver) ); nstartpos++; ntype = PNT_INTER; /* international */ } else if (strncmp(octstr_get_cstr(msg->sms.receiver), "00", 2) == 0) { debug("AT", 0, "international starting with 00 (%s)",octstr_get_cstr(msg->sms.receiver) ); nstartpos += 2; ntype = PNT_INTER; /* international */ } /* address length */ pdu[pos] = numtext(((len - nstartpos) & 240) >> 4); pos++; pdu[pos] = numtext((len - nstartpos) & 15); pos++; /* Type of number */ pdu[pos] = numtext(8 + ntype); pos++; /* numbering plan: ISDN/Telephone numbering plan */ pdu[pos] = numtext(1); pos++; /* make sure there is no blank in the phone number and encode * an even number of digits */ octstr_strip_blanks(msg->sms.receiver); for(i=nstartpos; i<len; i+=2) { if (i+1 < len) { pdu[pos] = octstr_get_char(msg->sms.receiver, i+1); } else { pdu[pos] = numtext (15); } pos++; pdu[pos] = octstr_get_char(msg->sms.receiver, i); pos++; } /* protocol identifier */ /* 0x00 implicit */ pdu[pos] = numtext(0); pos++; pdu[pos] = numtext(0); pos++; /* data coding scheme */ dcs = fields_to_dcs(msg, smsc->at_alt_dcs); pdu[pos] = numtext(dcs >> 4); pos++; pdu[pos] = numtext(dcs % 16); pos++; /* Validity-Period (TP-VP) * see GSM 03.40 section 9.2.3.12 * defaults to 24 hours = 167 if not set */ if ( msg->sms.validity) { if (msg->sms.validity > 635040) setvalidity = 255; if (msg->sms.validity >= 50400 && msg->sms.validity <= 635040) setvalidity = (msg->sms.validity - 1) / 7 / 24 / 60 + 192 + 1; if (msg->sms.validity > 43200 && msg->sms.validity < 50400) setvalidity = 197; if (msg->sms.validity >= 2880 && msg->sms.validity <= 43200) setvalidity = (msg->sms.validity - 1) / 24 / 60 + 166 + 1; if (msg->sms.validity > 1440 && msg->sms.validity < 2880) setvalidity = 168; if (msg->sms.validity >= 750 && msg->sms.validity <= 1440) setvalidity = (msg->sms.validity - 720 - 1) / 30 + 143 + 1; if (msg->sms.validity > 720 && msg->sms.validity < 750) setvalidity = 144; if (msg->sms.validity >= 5 && msg->sms.validity <= 720) setvalidity = (msg->sms.validity - 1) / 5 - 1 + 1; if (msg->sms.validity < 5) setvalidity = 0; } else setvalidity = (smsc->at_validityperiod != NULL ? atoi(smsc->at_validityperiod) : 167); if (setvalidity >= 0 && setvalidity <= 143) debug("AT", 0, "TP-Validity-Period: %d minutes", (setvalidity+1)*5); else if (setvalidity >= 144 && setvalidity <= 167) debug("AT", 0, "TP-Validity-Period: %3.1f hours", ((float)(setvalidity-143)/2)+12); else if (setvalidity >= 168 && setvalidity <= 196) debug("AT", 0, "TP-Validity-Period: %d days", (setvalidity-166)); else debug("AT", 0, "TP-Validity-Period: %d weeks", (setvalidity-192)); pdu[pos] = numtext((setvalidity & 240) >> 4); pos++; pdu[pos] = numtext(setvalidity & 15); pos++; /* user data length - include length of UDH if it exists*/ len = octstr_len(msg->sms.msgdata); if(octstr_len(msg->sms.udhdata)) { if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) { len += octstr_len(msg->sms.udhdata); } else { /* The reason we branch here is because UDH data length is determined in septets if we are in GSM coding, otherwise it's in octets. Adding 6 will ensure that for an octet length of 0, we get septet length 0, and for octet length 1 we get septet length 2.*/ len += (((8*octstr_len(msg->sms.udhdata)) + 6)/7); } } pdu[pos] = numtext((len & 240) >> 4); pos++; pdu[pos] = numtext(len & 15); pos++; /* udh */ if(octstr_len(msg->sms.udhdata)) { pos += encode8bituncompressed(msg->sms.udhdata, &pdu[pos]); } /* user data */ /* if the data is too long, it is cut */ if(msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) { pos += encode8bituncompressed(msg->sms.msgdata, &pdu[pos]); } else { int offset=0; if (octstr_len(msg->sms.udhdata)) { /* Have UDH */ int nbits = octstr_len(msg->sms.udhdata)*8; /* Includes UDH length byte */ offset = (((nbits/7)+1)*7-nbits)%7; /* Fill bits */ } pos += encode7bituncompressed(msg->sms.msgdata, &pdu[pos],offset); } pdu[pos] = 0; return 0;}/****************************************************************************** * Converts the text representation of hexa to binary */static Octstr *convertpdu(Octstr *pdutext) { Octstr *pdu; int i; int len = octstr_len(pdutext); pdu = octstr_create(""); for (i=0; i<len; i+=2) { octstr_append_char(pdu, hexchar(octstr_get_char(pdutext,i))*16 + hexchar(octstr_get_char(pdutext,i+1))); } return pdu;}/********************************************************************** * Encode 7bit uncompressed user data */int ermask[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };int elmask[8] = { 0, 64, 96, 112, 120, 124, 126, 127 };static int encode7bituncompressed(Octstr *input, unsigned char *encoded,int offset) { unsigned char prevoctet, tmpenc; int i; int c = 1; int r = 7; int pos = 0; int len; unsigned char enc7bit[256]; int j,encpos = 0; charset_latin1_to_gsm(input); len = octstr_len(input); /* prevoctet is set to the first character and we'll start the loop * at the following char. */ prevoctet = octstr_get_char(input ,0); for(i=1; i<octstr_len(input); i++) { /* a byte is encoded with what is left of the previous character * and filled with as much as possible of the current one. */ tmpenc = prevoctet + ((octstr_get_char(input,i) & ermask[c]) << r); enc7bit[encpos] = tmpenc; encpos++; c = (c>6)? 1 : c+1; r = (r<2)? 7 : r-1; /* prevoctet becomes the part of the current octet that hasn't * been copied to 'encoded' or the next char if the current has * been completely copied already. */ prevoctet = (octstr_get_char(input,i) & elmask[r]) >> (c-1); if(r == 7) { i++; prevoctet = octstr_get_char(input, i); } } /* if the length of the message is a multiple of 8 then we * are finished. Otherwise prevoctet still contains part of a * character so we add it. */ if((len/8)*8 != len) { enc7bit[encpos] = prevoctet;encpos++; } /* Now shift the buffer by the offset */ if (offset > 0) { unsigned char nextdrop, lastdrop; nextdrop = lastdrop = 0; for (i = 0; i < encpos; i++) { nextdrop = enc7bit[i] >> (8 - offset); /* This drops off by shifting */ if (i == 0) enc7bit[i] = enc7bit[i] << offset; /* This drops off by shifting */ else enc7bit[i] = (enc7bit[i] << offset) | lastdrop; lastdrop = nextdrop; } if (offset > ((len*7) % 8)) { enc7bit [i] = nextdrop; i++; } } else i = encpos; for (j = 0; j < i; j++) { encoded[pos] = numtext((enc7bit [j] & 240) >> 4); pos++; encoded[pos] = numtext(enc7bit [j] & 15); pos++; } return pos; }/********************************************************************** * Encode 8bit uncompressed user data */static int encode8bituncompressed(Octstr *input, unsigned char *encoded) { int len, i; len = octstr_len(input); for(i=0; i<len; i++) { /* each character is encoded in its hex representation (2 chars) */ encoded[i*2] = numtext((octstr_get_char(input, i) & 240) >> 4); encoded[i*2+1] = numtext(octstr_get_char(input, i) & 15); } return len*2;}/********************************************************************** * Decode 7bit uncompressed user data */int rmask[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };int lmask[8] = { 0, 128, 192, 224, 240, 248, 252, 254 };static void decode7bituncompressed(Octstr *input, int len, Octstr *decoded, int offset) { unsigned char septet, octet, prevoctet; int i; int r = 1; int c = 7; int pos = 0; /* Shift the buffer offset bits to the left */ if (offset > 0) { unsigned char *ip; for (i = 0, ip = octstr_get_cstr(input); i < octstr_len(input); i++) { if (i == octstr_len(input) - 1) *ip = *ip >> offset; else *ip = (*ip >> offset) | (*(ip + 1) << (8 - offset)); ip++; } } octet = octstr_get_char(input, pos); prevoctet = 0; for(i=0; i<len; i++) { septet = ((octet & rmask[c]) << (r-1)) + prevoctet; octstr_append_char(decoded, septet); prevoctet = (octet & lmask[r]) >> c; /* When r=7 we have a full character in prevoctet*/ if((r==7) && (i<len-1)){ i++; octstr_append_char(decoded, prevoctet); prevoctet = 0; } r = (r>6)? 1 : r+1; c = (c<2)? 7 : c-1; pos++; octet = octstr_get_char(input, pos); } charset_gsm_to_latin1(decoded);}/********************************************************************** * Code a half-byte to its text hexa representation */static int numtext(int num) { return (num > 9) ? (num+55) : (num+48);}/********************************************************************** * Get the numeric value of the text hex */static int hexchar(int hexc) { hexc = toupper(hexc) - 48; return (hexc>9) ? hexc-7 : hexc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -