📄 smsc_smpp.c
字号:
((octstr_get_char(pdu->u.deliver_sm.source_addr, 0) == '+' && octstr_check_range(pdu->u.deliver_sm.source_addr, 1, 256, gw_isdigit)) || octstr_check_range(pdu->u.deliver_sm.source_addr, 0, 256, gw_isdigit))) { /* check if we received leading '00', then remove it*/ if (octstr_search(pdu->u.deliver_sm.source_addr, octstr_imm("00"), 0) == 0) octstr_delete(pdu->u.deliver_sm.source_addr, 0, 2); /* international, insert '+' if not already here */ if (octstr_get_char(pdu->u.deliver_sm.source_addr, 0) != '+') octstr_insert_char(pdu->u.deliver_sm.source_addr, 0, '+'); } else if ((ton == GSM_ADDR_TON_ALPHANUMERIC || !octstr_check_range(pdu->u.deliver_sm.source_addr, 0, 256, gw_isdigit)) && octstr_len(pdu->u.deliver_sm.source_addr) > 11) { /* alphanum sender, max. allowed length is 11 (according to GSM specs) */ *reason = SMPP_ESME_RINVSRCADR; 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) { *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 ton and destination addr */ if (ton == GSM_ADDR_TON_INTERNATIONAL && octstr_get_char(pdu->u.deliver_sm.destination_addr, 0) != '+') { /* check for leading '00' and delete them */ if (octstr_search(pdu->u.deliver_sm.destination_addr, octstr_imm("00"), 0) == 0) octstr_delete(pdu->u.deliver_sm.destination_addr, 0, 2); /* add leading '+'*/ octstr_insert_char(pdu->u.deliver_sm.destination_addr, 0, '+'); } /* now check dest addr range */ if (!octstr_check_range(pdu->u.deliver_sm.destination_addr, 1, 256, gw_isdigit)) { *reason = SMPP_ESME_RINVDSTADR; 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), "ISO-8859-1") != 0) error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave as is.", octstr_get_cstr(smpp->alt_charset), "ISO-8859-1"); msg->sms.coding = DC_7BIT; } else { /* assume GSM 03.38 7-bit alphabet */ charset_gsm_to_latin1(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", "UCS-2BE") != 0) error(0, "Failed to convert msgdata from cyrllic to UCS-2, will leave as is"); msg->sms.coding = DC_UCS2; break; case 0x07: /* Hebrew iso-8859-8, I'll convert to unicode */ if (charset_convert(msg->sms.msgdata, "ISO-8859-8", "UCS-2BE") != 0) error(0, "Failed to convert msgdata from hebrew to UCS-2, will leave as is"); msg->sms.coding = DC_UCS2; 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_latin1(msg->sms.msgdata); } } msg->sms.pid = pdu->u.deliver_sm.protocol_id; return msg;error: msg_destroy(msg); return NULL;}static long smpp_status_to_smscconn_failure_reason(long status){ switch(status) { case SMPP_ESME_RMSGQFUL: case SMPP_ESME_RTHROTTLED: case SMPP_ESME_RX_T_APPN: case SMPP_ESME_RSYSERR: return SMSCCONN_FAILED_TEMPORARILY; break; default: return SMSCCONN_FAILED_REJECTED; }}static SMPP_PDU *msg_to_pdu(SMPP *smpp, Msg *msg){ SMPP_PDU *pdu; Octstr *buffer; Octstr *relation_UTC_time = NULL; struct tm gmtime, localtime, tm; int gwqdiff; pdu = smpp_pdu_create(submit_sm, counter_increase(smpp->message_id_counter)); pdu->u.submit_sm.source_addr = octstr_duplicate(msg->sms.sender); pdu->u.submit_sm.destination_addr = octstr_duplicate(msg->sms.receiver); /* Set the service type of the outgoing message. We'll use the config * directive as default and 'binfo' as specific parameter. */ pdu->u.submit_sm.service_type = octstr_len(msg->sms.binfo) ? octstr_duplicate(msg->sms.binfo) : octstr_duplicate(smpp->service_type); /* Check for manual override of source ton and npi values */ if(smpp->source_addr_ton > -1 && smpp->source_addr_npi > -1) { pdu->u.submit_sm.source_addr_ton = smpp->source_addr_ton; pdu->u.submit_sm.source_addr_npi = smpp->source_addr_npi; debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced source addr ton = %d, source add npi = %d", octstr_get_cstr(smpp->conn->id), smpp->source_addr_ton, smpp->source_addr_npi); } else { /* setup default values */ pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */ pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */ } if (smpp->autodetect_addr) { /* lets see if its international or alphanumeric sender */ if (octstr_get_char(pdu->u.submit_sm.source_addr, 0) == '+') { if (!octstr_check_range(pdu->u.submit_sm.source_addr, 1, 256, gw_isdigit)) { pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; /* alphanum */ pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN; /* short code */ } else { /* numeric sender address with + in front -> international (remove the +) */ octstr_delete(pdu->u.submit_sm.source_addr, 0, 1); pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_INTERNATIONAL; } } else { if (!octstr_check_range(pdu->u.submit_sm.source_addr,0, 256, gw_isdigit)) { pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN; } } } /* Check for manual override of destination ton and npi values */ if (smpp->dest_addr_ton > -1 && smpp->dest_addr_npi > -1) { pdu->u.submit_sm.dest_addr_ton = smpp->dest_addr_ton; pdu->u.submit_sm.dest_addr_npi = smpp->dest_addr_npi; debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced dest addr ton = %d, dest add npi = %d", octstr_get_cstr(smpp->conn->id), smpp->dest_addr_ton, smpp->dest_addr_npi); } else { pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */ pdu->u.submit_sm.dest_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */ } /* * if its a international number starting with +, lets remove the * '+' and set number type to international instead */ if (octstr_get_char(pdu->u.submit_sm.destination_addr,0) == '+') { octstr_delete(pdu->u.submit_sm.destination_addr, 0,1); pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_INTERNATIONAL; } /* check length of src/dst address */ if (octstr_len(pdu->u.submit_sm.destination_addr) > 20 || octstr_len(pdu->u.submit_sm.source_addr) > 20) { smpp_pdu_destroy(pdu); return NULL; } /* * set the data coding scheme (DCS) field * check if we have a forced value for this from the smsc-group. * Note: if message class is set, then we _must_ force alt_dcs otherwise * dcs has reserved values (e.g. mclass=2, dcs=0x11). We check MWI flag * first here, because MWI and MCLASS can not be set at the same time and * function fields_to_dcs check MWI first, so we have no need to force alt_dcs * if MWI is set. */ if (msg->sms.mwi == MWI_UNDEF && msg->sms.mclass != MC_UNDEF) pdu->u.deliver_sm.data_coding = fields_to_dcs(msg, 1); /* force alt_dcs */ else pdu->u.submit_sm.data_coding = fields_to_dcs(msg, (msg->sms.alt_dcs != SMS_PARAM_UNDEFINED ? msg->sms.alt_dcs : smpp->conn->alt_dcs)); /* set protocoll id */ if(msg->sms.pid != SMS_PARAM_UNDEFINED) pdu->u.submit_sm.protocol_id = msg->sms.pid; /* * set the esm_class field * default is store and forward, plus udh and rpi if requested */ pdu->u.submit_sm.esm_class = ESM_CLASS_SUBMIT_STORE_AND_FORWARD_MODE; if (octstr_len(msg->sms.udhdata)) pdu->u.submit_sm.esm_class = pdu->u.submit_sm.esm_class | ESM_CLASS_SUBMIT_UDH_INDICATOR; if (msg->sms.rpi > 0) pdu->u.submit_sm.esm_class = pdu->u.submit_sm.esm_class | ESM_CLASS_SUBMIT_RPI; /* * set data segments and length */ pdu->u.submit_sm.short_message = octstr_duplicate(msg->sms.msgdata); /* * only re-encoding if using default smsc charset that is defined via * alt-charset in smsc group and if MT is not binary */ if (msg->sms.coding == DC_7BIT || (msg->sms.coding == DC_UNDEF && octstr_len(msg->sms.udhdata))) { /* * consider 3 cases: * a) data_coding 0xFX: encoding should always be GSM 03.38 charset * b) data_coding 0x00: encoding may be converted according to alt-charset * c) data_coding 0x00: assume GSM 03.38 charset if alt-charset is not defined */ if ((pdu->u.submit_sm.data_coding & 0xF0) || (!smpp->alt_charset && pdu->u.submit_sm.data_coding == 0)) { charset_latin1_to_gsm(pdu->u.submit_sm.short_message); } else if (pdu->u.submit_sm.data_coding == 0 && smpp->alt_charset) { /* * convert to the given alternative charset */ if (charset_convert(pdu->u.submit_sm.short_message, "ISO-8859-1", octstr_get_cstr(smpp->alt_charset)) != 0) error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.", "ISO-8859-1", octstr_get_cstr(smpp->alt_charset)); } } /* prepend udh if present */ if (octstr_len(msg->sms.udhdata)) { octstr_insert(pdu->u.submit_sm.short_message, msg->sms.udhdata, 0); } pdu->u.submit_sm.sm_length = octstr_len(pdu->u.submit_sm.short_message); /* * check for validity and defered settings */ if (msg->sms.validity >= 0 || msg->sms.deferred >= 0) { /* work out 1/4 hour difference between local time and UTC/GMT */ gmtime = gw_gmtime(time(NULL)); localtime = gw_localtime(time(NULL)); gwqdiff = ((localtime.tm_hour - gmtime.tm_hour) * 4) + ((localtime.tm_min - gmtime.tm_min) / 15); if (gwqdiff >= 0) { relation_UTC_time = octstr_create("+"); } else { relation_UTC_time = octstr_create("-"); gwqdiff *= -1; /* make absolute */ } if (msg->sms.validity >= 0) { tm = gw_localtime(time(NULL) + msg->sms.validity * 60); buffer = octstr_format("%02d%02d%02d%02d%02d%02d0%02d%1s", tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, gwqdiff, octstr_get_cstr(relation_UTC_time)); pdu->u.submit_sm.validity_period = octstr_copy(buffer,0,16); octstr_destroy(buffer); } if (msg->sms.deferred >= 0) { tm = gw_localtime(time(NULL) + msg->sms.deferred * 60);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -