📄 smsc_smpp.c
字号:
{ long reason = SMPP_ESME_ROK; if (addr == NULL) return reason; switch(ton) { case GSM_ADDR_TON_INTERNATIONAL: /* * Checks to perform: * 1) assume international number has at least 7 chars * 2) the whole source addr consist of digits, exception '+' in front */ if (octstr_len(addr) < 7) { /* We consider this as a "non-hard" condition, since there "may" * be international numbers routable that are < 7 digits. Think * of 2 digit country code + 3 digit emergency code. */ warning(0, "SMPP[%s]: Mallformed addr `%s', generally expected at least 7 digits. ", octstr_get_cstr(id), octstr_get_cstr(addr)); } else if (octstr_get_char(addr, 0) == '+' && !octstr_check_range(addr, 1, 256, gw_isdigit)) { error(0, "SMPP[%s]: Mallformed addr `%s', expected all digits. ", octstr_get_cstr(id), octstr_get_cstr(addr)); reason = SMPP_ESME_RINVSRCADR; goto error; } else if (octstr_get_char(addr, 0) != '+' && !octstr_check_range(addr, 0, 256, gw_isdigit)) { error(0, "SMPP[%s]: Mallformed addr `%s', expected all digits. ", octstr_get_cstr(id), octstr_get_cstr(addr)); reason = SMPP_ESME_RINVSRCADR; goto error; } /* check if we received leading '00', then remove it*/ if (octstr_search(addr, octstr_imm("00"), 0) == 0) octstr_delete(addr, 0, 2); /* international, insert '+' if not already here */ if (octstr_get_char(addr, 0) != '+') octstr_insert_char(addr, 0, '+'); break; case GSM_ADDR_TON_ALPHANUMERIC: if (octstr_len(addr) > 11) { /* alphanum sender, max. allowed length is 11 (according to GSM specs) */ error(0, "SMPP[%s]: Mallformed addr `%s', alphanum length greater 11 chars. ", octstr_get_cstr(id), octstr_get_cstr(addr)); reason = SMPP_ESME_RINVSRCADR; goto error; } if (alt_addr_charset) { if (octstr_str_case_compare(alt_addr_charset, "gsm") == 0) charset_gsm_to_utf8(addr); else if (charset_convert(addr, octstr_get_cstr(alt_addr_charset), SMPP_DEFAULT_CHARSET) != 0) error(0, "Failed to convert address from charset <%s> to <%s>, leave as is.", octstr_get_cstr(alt_addr_charset), SMPP_DEFAULT_CHARSET); } break; default: /* otherwise don't touch addr, user should handle it */ break; } error: return reason;}/* * Convert SMPP PDU to internal Msgs structure. * Return the Msg if all was fine and NULL otherwise, while getting * the failing reason delivered back in *reason. * XXX semantical check on the incoming values can be extended here. */static Msg *pdu_to_msg(SMPP *smpp, SMPP_PDU *pdu, long *reason){ Msg *msg; int ton, npi; gw_assert(pdu->type == deliver_sm); msg = msg_create(sms); gw_assert(msg != NULL); *reason = SMPP_ESME_ROK; /* * Reset source addr to have a prefixed '+' in case we have an * intl. TON to allow backend boxes (ie. smsbox) to distinguish * between national and international numbers. */ ton = pdu->u.deliver_sm.source_addr_ton; npi = pdu->u.deliver_sm.source_addr_npi; /* check source addr */ if ((*reason = convert_addr_from_pdu(smpp->conn->id, pdu->u.deliver_sm.source_addr, ton, npi, smpp->alt_addr_charset)) != SMPP_ESME_ROK) goto error; msg->sms.sender = pdu->u.deliver_sm.source_addr; pdu->u.deliver_sm.source_addr = NULL; /* * Follows SMPP spec. v3.4. issue 1.2 * it's not allowed to have destination_addr NULL */ if (pdu->u.deliver_sm.destination_addr == NULL) { error(0, "SMPP[%s]: Mallformed destination_addr `%s', may not be empty. " "Discarding MO message.", octstr_get_cstr(smpp->conn->id), octstr_get_cstr(pdu->u.deliver_sm.destination_addr)); *reason = SMPP_ESME_RINVDSTADR; goto error; } /* Same reset of destination number as for source */ ton = pdu->u.deliver_sm.dest_addr_ton; npi = pdu->u.deliver_sm.dest_addr_npi; /* check destination addr */ if ((*reason = convert_addr_from_pdu(smpp->conn->id, pdu->u.deliver_sm.destination_addr, ton, npi, smpp->alt_addr_charset)) != SMPP_ESME_ROK) goto error; msg->sms.receiver = pdu->u.deliver_sm.destination_addr; pdu->u.deliver_sm.destination_addr = NULL; /* SMSCs use service_type for billing information */ msg->sms.binfo = pdu->u.deliver_sm.service_type; pdu->u.deliver_sm.service_type = NULL; if (pdu->u.deliver_sm.esm_class & ESM_CLASS_SUBMIT_RPI) msg->sms.rpi = 1; /* * Check for message_payload if version > 0x33 and sm_length == 0 * Note: SMPP spec. v3.4. doesn't allow to send both: message_payload & short_message! */ if (smpp->version > 0x33 && pdu->u.deliver_sm.sm_length == 0 && pdu->u.deliver_sm.message_payload) { msg->sms.msgdata = pdu->u.deliver_sm.message_payload; pdu->u.deliver_sm.message_payload = NULL; } else { msg->sms.msgdata = pdu->u.deliver_sm.short_message; pdu->u.deliver_sm.short_message = NULL; } /* * Encode udh if udhi set * for reference see GSM03.40, section 9.2.3.24 */ if (pdu->u.deliver_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR) { int udhl; udhl = octstr_get_char(msg->sms.msgdata, 0) + 1; debug("bb.sms.smpp",0,"SMPP[%s]: UDH length read as %d", octstr_get_cstr(smpp->conn->id), udhl); if (udhl > octstr_len(msg->sms.msgdata)) { error(0, "SMPP[%s]: Mallformed UDH length indicator 0x%03x while message length " "0x%03lx. Discarding MO message.", octstr_get_cstr(smpp->conn->id), udhl, octstr_len(msg->sms.msgdata)); *reason = SMPP_ESME_RINVESMCLASS; goto error; } msg->sms.udhdata = octstr_copy(msg->sms.msgdata, 0, udhl); octstr_delete(msg->sms.msgdata, 0, udhl); } dcs_to_fields(&msg, pdu->u.deliver_sm.data_coding); /* handle default data coding */ switch (pdu->u.deliver_sm.data_coding) { case 0x00: /* default SMSC alphabet */ /* * try to convert from something interesting if specified so * unless it was specified binary, ie. UDH indicator was detected */ if (smpp->alt_charset && msg->sms.coding != DC_8BIT) { if (charset_convert(msg->sms.msgdata, octstr_get_cstr(smpp->alt_charset), SMPP_DEFAULT_CHARSET) != 0) error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave as is.", octstr_get_cstr(smpp->alt_charset), SMPP_DEFAULT_CHARSET); msg->sms.coding = DC_7BIT; } else { /* assume GSM 03.38 7-bit alphabet */ charset_gsm_to_utf8(msg->sms.msgdata); msg->sms.coding = DC_7BIT; } break; case 0x01: /* ASCII or IA5 - not sure if I need to do anything */ case 0x03: /* ISO-8859-1 - do nothing */ msg->sms.coding = DC_7BIT; break; case 0x02: /* 8 bit binary - do nothing */ case 0x04: /* 8 bit binary - do nothing */ msg->sms.coding = DC_8BIT; break; case 0x05: /* JIS - what do I do with that ? */ break; case 0x06: /* Cyrllic - iso-8859-5, I'll convert to unicode */ if (charset_convert(msg->sms.msgdata, "ISO-8859-5", "UTF-8") != 0) error(0, "Failed to convert msgdata from cyrllic to UTF-8, will leave as is"); msg->sms.coding = DC_7BIT; break; case 0x07: /* Hebrew iso-8859-8, I'll convert to unicode */ if (charset_convert(msg->sms.msgdata, "ISO-8859-8", "UTF-8") != 0) error(0, "Failed to convert msgdata from hebrew to UTF-8, will leave as is"); msg->sms.coding = DC_7BIT; break; case 0x08: /* unicode UCS-2, yey */ msg->sms.coding = DC_UCS2; break; /* * don't much care about the others, * you implement them if you feel like it */ default: /* * some of smsc send with dcs from GSM 03.38 , but these are reserved in smpp spec. * So we just look decoded values from dcs_to_fields and if none there make our assumptions. * if we have an UDH indicator, we assume DC_8BIT. */ if (msg->sms.coding == DC_UNDEF && pdu->u.deliver_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR) msg->sms.coding = DC_8BIT; else if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) { /* assume GSM 7Bit , reencode */ msg->sms.coding = DC_7BIT; charset_gsm_to_utf8(msg->sms.msgdata); } } msg->sms.pid = pdu->u.deliver_sm.protocol_id; /* set priority flag */ msg->sms.priority = pdu->u.deliver_sm.priority_flag; return msg;error: msg_destroy(msg); return NULL;}/* * Convert SMPP PDU to internal Msgs structure. * Return the Msg if all was fine and NULL otherwise, while getting * the failing reason delivered back in *reason. * XXX semantical check on the incoming values can be extended here. */static Msg *data_sm_to_msg(SMPP *smpp, SMPP_PDU *pdu, long *reason){ Msg *msg; int ton, npi; gw_assert(pdu->type == data_sm); msg = msg_create(sms); gw_assert(msg != NULL); *reason = SMPP_ESME_ROK; /* * Reset source addr to have a prefixed '+' in case we have an * intl. TON to allow backend boxes (ie. smsbox) to distinguish * between national and international numbers. */ ton = pdu->u.data_sm.source_addr_ton; npi = pdu->u.data_sm.source_addr_npi; /* check source addr */ if ((*reason = convert_addr_from_pdu(smpp->conn->id, pdu->u.data_sm.source_addr, ton, npi, smpp->alt_addr_charset)) != SMPP_ESME_ROK) goto error; msg->sms.sender = pdu->u.data_sm.source_addr; pdu->u.data_sm.source_addr = NULL; /* * Follows SMPP spec. v3.4. issue 1.2 * it's not allowed to have destination_addr NULL */ if (pdu->u.data_sm.destination_addr == NULL) { error(0, "SMPP[%s]: Mallformed destination_addr `%s', may not be empty. " "Discarding MO message.", octstr_get_cstr(smpp->conn->id), octstr_get_cstr(pdu->u.data_sm.destination_addr)); *reason = SMPP_ESME_RINVDSTADR; goto error; } /* Same reset of destination number as for source */ ton = pdu->u.data_sm.dest_addr_ton; npi = pdu->u.data_sm.dest_addr_npi; /* check destination addr */ if ((*reason = convert_addr_from_pdu(smpp->conn->id, pdu->u.data_sm.destination_addr, ton, npi, smpp->alt_addr_charset)) != SMPP_ESME_ROK) goto error; msg->sms.receiver = pdu->u.data_sm.destination_addr; pdu->u.data_sm.destination_addr = NULL; /* SMSCs use service_type for billing information */ msg->sms.binfo = pdu->u.data_sm.service_type; pdu->u.data_sm.service_type = NULL; if (pdu->u.data_sm.esm_class & ESM_CLASS_SUBMIT_RPI) msg->sms.rpi = 1; msg->sms.msgdata = pdu->u.data_sm.message_payload; pdu->u.data_sm.message_payload = NULL; /* * Encode udh if udhi set * for reference see GSM03.40, section 9.2.3.24 */ if (pdu->u.data_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR) { int udhl; udhl = octstr_get_char(msg->sms.msgdata, 0) + 1; debug("bb.sms.smpp",0,"SMPP[%s]: UDH length read as %d", octstr_get_cstr(smpp->conn->id), udhl); if (udhl > octstr_len(msg->sms.msgdata)) { error(0, "SMPP[%s]: Mallformed UDH length indicator 0x%03x while message length " "0x%03lx. Discarding MO message.", octstr_get_cstr(smpp->conn->id), udhl, octstr_len(msg->sms.msgdata)); *reason = SMPP_ESME_RINVESMCLASS; goto error; } msg->sms.udhdata = octstr_copy(msg->sms.msgdata, 0, udhl); octstr_delete(msg->sms.msgdata, 0, udhl); } dcs_to_fields(&msg, pdu->u.data_sm.data_coding); /* handle default data coding */ switch (pdu->u.data_sm.data_coding) { case 0x00: /* default SMSC alphabet */ /* * try to convert from something interesting if specified so * unless it was specified binary, ie. UDH indicator was detected */ if (smpp->alt_charset && msg->sms.coding != DC_8BIT) { if (charset_convert(msg->sms.msgdata, octstr_get_cstr(smpp->alt_charset), SMPP_DEFAULT_CHARSET) != 0) error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave as is.", octstr_get_cstr(smpp->alt_charset), SMPP_DEFAULT_CHARSET); msg->sms.coding = DC_7BIT; } else { /* assume GSM 03.38 7-bit alphabet */ charset_gsm_to_utf8(msg->sms.msgdata); msg->sms.coding = DC_7BIT; } break; case 0x01: /* ASCII or IA5 - not sure if I need to do anything */ case 0x03: /* ISO-8859-1 - do nothing */ msg->sms.coding = DC_7BIT; break; case 0x02: /* 8 bit binary - do nothing */ case 0x04: /* 8 bit binary - do nothing */ msg->sms.coding = DC_8BIT; break; case 0x05: /* JIS - what do I do with that ? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -