📄 smsc_smpp.c
字号:
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.data_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); } } 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; int validity; 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 */ if (smpp->alt_addr_charset) { if (octstr_str_case_compare(smpp->alt_addr_charset, "gsm") == 0) { /* @ would break PDU if converted into GSM*/ octstr_replace(pdu->u.submit_sm.source_addr, octstr_imm("@"), octstr_imm("?")); charset_latin1_to_gsm(pdu->u.submit_sm.source_addr); } else if (charset_convert(pdu->u.submit_sm.source_addr, SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset)) != 0) error(0, "Failed to convert source_addr from charset <%s> to <%s>, will send as is.", SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset)); } } 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; if (smpp->alt_addr_charset) { if (octstr_str_case_compare(smpp->alt_addr_charset, "gsm") == 0) { /* @ would break PDU if converted into GSM */ octstr_replace(pdu->u.submit_sm.source_addr, octstr_imm("@"), octstr_imm("?")); charset_latin1_to_gsm(pdu->u.submit_sm.source_addr); } else if (charset_convert(pdu->u.submit_sm.source_addr, SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset)) != 0) error(0, "Failed to convert source_addr from charset <%s> to <%s>, will send as is.", SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset)); } } } } /* 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.submit_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 protocol 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, SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_charset)) != 0) error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.", SMPP_DEFAULT_CHARSET, 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 * were message value has higher priiority then smsc config group value */ validity = msg->sms.validity >= 0 ? msg->sms.validity : smpp->validityperiod; if (validity >= 0) { struct tm tm = gw_gmtime(time(NULL) + validity * 60); pdu->u.submit_sm.validity_period = octstr_format("%02d%02d%02d%02d%02d%02d000+", tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } if (msg->sms.deferred >= 0) { struct tm tm = gw_gmtime(time(NULL) + msg->sms.deferred * 60); pdu->u.submit_sm.schedule_delivery_time = octstr_format("%02d%02d%02d%02d%02d%02d000+", tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } /* ask for the delivery reports if needed */ if (DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask)) pdu->u.submit_sm.registered_delivery = 1; else if (DLR_IS_FAIL(msg->sms.dlr_mask) && !DLR_IS_SUCCESS(msg->sms.dlr_mask)) pdu->u.submit_sm.registered_delivery = 2; /* set priority */ if (msg->sms.priority >= 0 && msg->sms.priority <= 3) pdu->u.submit_sm.priority_flag = msg->sms.priority; else pdu->u.submit_sm.priority_flag = smpp->priority; /* set more messages to send */ if (smpp->version > 0x33 && msg->sms.msg_left > 0) pdu->u.submit_sm.more_messages_to_send = 1; return pdu;}static void send_enquire_link(SMPP *smpp, Connection *conn, long *last_sent){ SMPP_PDU *pdu; Octstr *os; if (date_universal_now() - *last_sent < smpp->enquire_link_interval) return; *last_sent = date_universal_now(); pdu = smpp_pdu_create(enquire_link, counter_increase(smpp->message_id_counter)); dump_pdu("Sending enquire link:", smpp->conn->id, pdu); os = smpp_pdu_pack(pdu); if (os) conn_write(conn, os); /* Write errors checked by caller. */ octstr_destroy(os); smpp_pdu_destroy(pdu);}static void send_unbind(SMPP *smpp, Connection *conn){ SMPP_PDU *pdu; Octstr *os; pdu = smpp_pdu_create(unbind, counter_increase(smpp->message_id_counter)); dump_pdu("Sending unbind:", smpp->conn->id, pdu); os = smpp_pdu_pack(pdu); conn_write(conn, os); octstr_destroy(os); smpp_pdu_destroy(pdu);}static int send_pdu(Connection *conn, Octstr *id, SMPP_PDU *pdu){ Octstr *os; int ret; dump_pdu("Sending PDU:", id, pdu); os = smpp_pdu_pack(pdu); if (os) ret = conn_write(conn, os); /* Caller checks for write errors later */ else ret = -1; octstr_destroy(os); return ret;}static void send_messages(SMPP *smpp, Connection *conn, long *pending_submits){ Msg *msg; SMPP_PDU *pdu; Octstr *os; double delay = 0; if (*pending_submits == -1) return; if (smpp->conn->throughput > 0) { delay = 1.0 / smpp->conn->throughput; } while (*pending_submits < smpp->max_pending_submits) { /* Get next message, quit if none to be sent */ msg = gwlist_extract_first(smpp->msgs_to_send); if (msg == NULL) break; /* Send PDU, record it as waiting for ack from SMS center */ pdu = msg_to_pdu(smpp, msg); if (pdu == NULL) { bb_smscconn_send_failed(smpp->conn, msg, SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED SMS")); continue; } /* check for write errors */ if (send_pdu(conn, smpp->conn->id, pdu) == 0) { struct smpp_msg *smpp_msg = smpp_msg_create(msg); os = octstr_format("%ld", pdu->u.submit_sm.sequence_number); dict_put(smpp->sent_msgs, os, smpp_msg); smpp_pdu_destroy(pdu);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -