📄 smsc_ois.c
字号:
/* check the (initial) header and trailer */ buflen = strlen(str) - 1; if (buflen < 7 || str[0] != 'M' || (str[1] & 0x50) != 0x50 || str[buflen] != EOL) { goto error; } count = str[1] & 0x0f; while (--count >= 0) { /* check the additional header */ sprintf(buffer, "%c%c%c%.4s", EOL, 'M', /* deliver sm invoke */ (char)(0x60|count), /* ia5 encoding, additional part */ &str[2]); if (strstr(str, buffer) == NULL) { goto error; } } return 0; error: return -1;}static int ois_adjust_destination_address(Msg *msg, const char *raw){ int len; SAY(3, "ois_adjust_destination_address"); len = raw[0] & 0xff; msg->sms.receiver = octstr_create_from_data(&raw[1+2], len-2); return 1 + len;}static int ois_ignore_smsc_reference_number(const char *raw){ int value; SAY(3, "ois_ignore_smsc_reference_number"); value = raw[3] & 0xff; value <<= 8; value |= raw[2] & 0xff; value <<= 8; value |= raw[1] & 0xff; value <<= 8; value |= raw[0] & 0xff; return 4;}static int ois_adjust_originating_address(Msg *msg, const char *raw){ int len; SAY(3, "ois_adjust_originating_address"); len = raw[0] & 0xff; msg->sms.sender = octstr_create_from_data(&raw[1+2], len-2); return 1 + len;}static int ois_adjust_data_coding_scheme(Msg *msg, const char *raw){ SAY(3, "ois_adjust_data_coding_scheme"); /* we're using this variable temporarily: * ois_adjust_sm_text will set the correct value */ msg->sms.coding = (raw[0] & 0xff) + 1; return 1;}static int ois_ignore_protocol_id(const char *raw){ int value; SAY(3, "ois_ignore_protocol_id"); value = raw[0] & 0xff; return 1;}static int ois_adjust_additional_information(Msg *msg, const char *raw){ SAY(3, "ois_adjust_additional_information"); /* we're using this variable temporarily: * ois_adjust_sm_text will set the correct value */ msg->sms.mclass = raw[0] & 0xff; return 1;}static int ois_adjust_sm_text(Msg *msg, const char *raw){ int msglen7, msglen8; char buffer[BUFLEN+1]; SAY(3, "ois_adjust_sm_text"); /* calculate lengths */ msglen7 = raw[0] & 0xff; msglen8 = raw[1] & 0xff; /* copy text, note: flag contains temporarily the raw type description */ switch ((msg->sms.coding - 1) & 0xff) { case 0x00: /* gsm7 */ ois_expand_gsm7(buffer, &raw[2], msglen7); ois_convert_to_iso88591(buffer, msglen7); if (msg->sms.mclass & 0x02) { /* XXX mclass temporarily */ msg->sms.msgdata = octstr_create(""); msg->sms.udhdata = octstr_create_from_data(buffer, msglen7); } else { msg->sms.msgdata = octstr_create_from_data(buffer, msglen7); msg->sms.udhdata = octstr_create(""); } msg->sms.coding = DC_7BIT; break; case 0x0f: /* ia5 */ memcpy(buffer, &raw[2], msglen8); ois_convert_to_iso88591(buffer, msglen8); if (msg->sms.mclass & 0x02) { /* XXX mclass temporarily */ msg->sms.msgdata = octstr_create(""); msg->sms.udhdata = octstr_create_from_data(buffer, msglen8); } else { msg->sms.msgdata = octstr_create_from_data(buffer, msglen8); msg->sms.udhdata = octstr_create(""); } msg->sms.coding = DC_7BIT; break; default: /* 0xf4, 0xf5, 0xf6, 0xf7; 8bit to disp, mem, sim or term */ if (msg->sms.mclass & 0x02) { /* XXX mclass temporarily */ msg->sms.msgdata = octstr_create(""); msg->sms.udhdata = octstr_create_from_data(&raw[2], msglen8); } else { msg->sms.msgdata = octstr_create_from_data(&raw[2], msglen8); msg->sms.udhdata = octstr_create(""); } msg->sms.coding = DC_8BIT; break; } msg->sms.mclass = MC_UNDEF; if (octstr_len(msg->sms.udhdata)) { IOTRACE("decoded udh", octstr_get_cstr(msg->sms.udhdata), octstr_len(msg->sms.udhdata)); } else { IOTRACE("decoded", octstr_get_cstr(msg->sms.msgdata), octstr_len(msg->sms.msgdata)); } return 2 + msglen8;}static int ois_ignore_time(const char *raw){ char str[15]; SAY(3, "ois_ignore_time"); strncpy(str, raw, 14); str[14] = '\0'; return 14;}static int ois_deliver_sm_result(SMSCenter *smsc, int result, const char *str){ char body[BUFLEN+1]; char buffer[BUFLEN+1]; int len; int ret; SAY(2, "ois_deliver_sm_result"); /* construct a message */ len = ois_encode_deliver_sm_result(body, result); /* first and only part */ sprintf(buffer, "%c%c%.4s%.121s%c", 'm', /* deliver sm result */ (char)(0x50), /* ia5 encoding, the only part */ &str[2], &body[0], EOL); IOTRACE("sending", buffer, strlen(buffer)); ret = write_to_socket(smsc->socket, buffer); if (ret < 0) { goto error; } return 0; error: return -1;}static int ois_encode_deliver_sm_result(char *str, int result){ char raw[4]; SAY(3, "ois_encode_deliver_sm_result"); /* construct the deliver sm result body content */ raw[0] = (char) result; return ois_convert_to_ia5(str, raw, 1);}static int ois_expand_gsm7(char *raw8, const char *raw7, int len){ int i; char bits[8*(BUFLEN+1)]; SAY2(3, "ois_expand_gsm7 len=%d", len); /* yeah, there are also better algorithms, but... */ /* well, at least this is fairly portable and ok for small messages... */ ois_expand_gsm7_to_bits(bits, raw7, len); for (i = 0; i < len; ++i) { raw8[i] = ois_expand_gsm7_from_bits(bits, i); } SAY2(5, "ois_expand_gsm7 gave [%s]", ois_debug_str(raw8, i)); return i;}static int ois_expand_gsm7_to_bits(char *bits, const char *raw7, int len){ int i, j, k; char ch; SAY(3, "ois_expand_gsm7_to_bits"); len *= 7; /* number of bits in the gms 7-bit msg */ for (j = i = 0; j < len; ++i) { ch = raw7[i]; for (k = 0; k < 8; ++k) { bits[j++] = (char) (ch & 0x01); ch >>= 1; } } return j;}static char ois_expand_gsm7_from_bits(const char *bits, int pos){ int i; char ch; SAY2(8, "ois_expand_gsm7_from_bits pos=%d", pos); pos *= 7; /* septet position in bits */ ch = '\0'; for (i = 6; i >= 0; --i) { ch <<= 1; ch |= bits[pos+i]; } return ch;}static int ois_convert_to_ia5(char *str, const char *raw, int len){ int j; int i; int ch; SAY2(3, "ois_convert_to_ia5 len=%d", len); for (j = i = 0; i < len; ++i) { ch = raw[i] & 0xff; if (ch == 0x5c || ch == 0x5e || ch == 0x60 || ch == 0x7e) { str[j++] = (char) 0x5c; str[j++] = (char) ch; } else if (0x20 <= ch && ch < 0x7f) { str[j++] = (char) ch; } else if (0x00 <= ch && ch < 0x20) { str[j++] = (char) 0x5e; str[j++] = (char) ch + 0x40; } else if (0xa0 <= ch && ch < 0xff) { str[j++] = (char) 0x60; str[j++] = (char) ch - 0x80; } else if (0x80 <= ch && ch < 0xa0) { str[j++] = (char) 0x7e; str[j++] = (char) ch - 0x40; } else if (ch == 0x7f) { str[j++] = (char) 0x5e; str[j++] = (char) 0x7e; } else { /* ch == 0xff */ str[j++] = (char) 0x7e; str[j++] = (char) 0x7e; } } str[j] = '\0'; SAY2(5, "ois_convert_to_ia5 gave [%s]", ois_debug_str(str, j)); return j;}static int ois_convert_from_ia5(char *raw, const char *str){ int j; int i; int ch; SAY(3, "ois_convert_from_ia5"); for (j = i = 0; ; ++i) { ch = str[i] & 0xff; if (ch < 0x20 || 0x7f <= ch) { break; } else if (ch == 0x5c) { ch = str[++i] & 0xff; if (ch == 0x5c || ch == 0x5e || ch == 0x60 || ch == 0x7e) { raw[j++] = (char) ch; } else { break; } } else if (ch == 0x5e) { ch = str[++i] & 0xff; if (0x40 <= ch && ch < 0x60) { raw[j++] = (char) ch - 0x40; } else if (ch == 0x7e) { raw[j++] = (char) 0x7f; } else { break; } } else if (ch == 0x60) { ch = str[++i] & 0xff; if (0x20 <= ch && ch < 0x7f) { raw[j++] = (char) ch + 0x80; } else { break; } } else if (ch == 0x7e) { ch = str[++i] & 0xff; if (0x40 <= ch && ch < 0x60) { raw[j++] = (char) ch + 0x40; } else if (ch == 0x7e) { raw[j++] = (char) 0xff; } else { break; } } else { /* 0x20 <= ch && ch < 0x7f */ raw[j++] = (char) ch; } } SAY2(5, "ois_convert_from_ia5 gave [%s]", ois_debug_str(raw, j)); return j;}static int ois_convert_to_iso88591(char *raw, int len){ /* a best effort 1-to-1 conversion according to ois appendix a */ static const char gsm_to_iso88591[] = { '@', 0xa3,'$', 0xa5,0xe8,0xe9,0xf9,0xec, /* 0x00 - 0x07 */ 0xf2,0xc7,'\n',0xd8,0xf8,'\r',0xc5,0xe5, /* 0x08 - 0x0f */ 'D', ' ', 'F', 'G', 'L', 'W', 'P', 'Y', /* 0x10 - 0x17, poor! */ 'Y', 'S', 'X', ' ', 0xc6,0xe6,'b', 0xc9, /* 0x18 - 0x1f, poor! */ ' ', '!', '"', '#', 0xa4, '%', '&', '\'',/* 0x20 - 0x27 */ '(', ')', '*', '+', ',', '-', '.', '/', /* 0x28 - 0x2f */ '0', '1', '2', '3', '4', '5', '6', '7', /* 0x30 - 0x37 */ '8', '9', ':', ';', '<', '=', '>', '?', /* 0x38 - 0x3f */ 0xa1,'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 0x40 - 0x47 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 0x48 - 0x4f */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 0x50 - 0x57 */ 'X', 'Y', 'Z', 0xc4,0xd6,0xd1,0xdc,0xa7, /* 0x58 - 0x5f */ 0xbf,'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 0x60 - 0x67 */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 0x68 - 0x6f */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 0x70 - 0x77 */ 'x', 'y', 'z', 0xe4,0xf6,0xf1,0xfc,0xe0 /* 0x78 - 0x7f */ }; int i; SAY2(3, "ois_convert_to_iso88591 len=%d", len); for (i = 0; i < len; ++i) { raw[i] = gsm_to_iso88591[raw[i] & 0x7f]; } SAY2(5, "ois_convert_to_iso88591 gave [%s]", ois_debug_str(raw, i)); return i;}/* * Extract a message from the internal buffer. */static int ois_extract_msg_from_buffer(char *str, SMSCenter *smsc){ int len; int count; SAY2(8, "ois_extract_msg_from_buffer buflen=%ld", (long)smsc->buflen); str[0] = '\0'; if (smsc->buflen < 7) { /* 7 = 6 + 1 */ return 0; /* we don't have a message yet */ } if (strchr("SRDATECQLMPOVsrdatecqlmpov", smsc->buffer[0]) == NULL || (smsc->buffer[1] & 0xf0) != 0x50) { goto error; } /* a valid message type, find the end of the message */ count = smsc->buffer[1] & 0x0f; for (len = 0; (size_t) len < smsc->buflen; ++len) { if (smsc->buffer[len] == EOL) { if (--count < 0) { ++len; break; } } } if (count >= 0) { /* we don't have all the pieces */ if (len < BUFLEN) { return 0; /* ...but maybe later */ } goto error; } /* the buffer contains a promising message candidate */ memcpy(str, smsc->buffer, len); str[len] = '\0'; smscenter_remove_from_buffer(smsc, len); /* just the message */ return len; error: for (len = 0; (size_t) len < smsc->buflen && smsc->buffer[len] != EOL; ++len) ; if (len > BUFLEN) len = BUFLEN; memcpy(str, smsc->buffer, len); str[len] = '\0'; smscenter_remove_from_buffer(smsc, smsc->buflen); /* everything */ return -len;}/* * Extract a line from the internal buffer. */static int ois_extract_line_from_buffer(char *str, SMSCenter *smsc){ int len; SAY2(3, "ois_extract_line_from_buffer buflen=%ld", (long)smsc->buflen); str[0] = '\0'; for (len = 0; (size_t) len < smsc->buflen && smsc->buffer[len] != '\n'; ++len) ; if ((size_t) len >= smsc->buflen) { return 0; } else { ++len; } /* the buffer contains a line */ memcpy(str, smsc->buffer, len); str[len] = '\0'; smscenter_remove_from_buffer(smsc, len); /* just the line */ return len;}static void ois_swap_buffering(SMSCenter *smsc){ time_t alive; int socket; char *buffer; size_t bufsize; size_t buflen; SAY(8, "ois_swap_buffering"); if (smsc->ois_bufsize == 0) { smsc->ois_buflen = 0; smsc->ois_bufsize = smsc->bufsize; smsc->ois_buffer = gw_malloc(smsc->ois_bufsize); memset(smsc->ois_buffer, 0, smsc->ois_bufsize); } alive = smsc->ois_alive; smsc->ois_alive = smsc->ois_alive2; smsc->ois_alive2 = alive; socket = smsc->socket; smsc->socket = smsc->ois_socket; smsc->ois_socket = socket; buffer = smsc->buffer; smsc->buffer = smsc->ois_buffer; smsc->ois_buffer = buffer; buflen = smsc->buflen; smsc->buflen = smsc->ois_buflen; smsc->ois_buflen = buflen; bufsize = smsc->bufsize; smsc->bufsize = smsc->ois_bufsize; smsc->ois_bufsize = bufsize; return;}static const char *ois_debug_str(const char *raw, int len){ static const char hex[] = "0123456789abcdef"; static char str[4*(BUFLEN+1)+1]; int pos; int ch; int i; pos = 0; for (i = 0; i < len; ++i) { ch = raw[i] & 0xff; if (0x20 <= ch && ch < 0x7f && ch != 0x5c) { str[pos++] = (char) ch; } else { str[pos++] = '\\'; str[pos++] = 'x'; str[pos++] = hex[ch/16]; str[pos++] = hex[ch%16]; } } str[pos] = '\0'; return str;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -