📄 smsc_smpp.c
字号:
octstr_destroy(os); ++(*pending_submits); /* * obey throughput speed limit, if any. */ if (smpp->conn->throughput > 0) gwthread_sleep(delay); } else { /* write error occurs */ smpp_pdu_destroy(pdu); bb_smscconn_send_failed(smpp->conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL); break; } }}/* * Open transmission connection to SMS center. Return NULL for error, * open Connection for OK. Caller must set smpp->conn->status correctly * before calling this. */static Connection *open_transmitter(SMPP *smpp){ SMPP_PDU *bind; Connection *conn; conn = conn_open_tcp(smpp->host, smpp->transmit_port, smpp->conn->our_host ); if (conn == NULL) { error(0, "SMPP[%s]: Couldn't connect to server.", octstr_get_cstr(smpp->conn->id)); return NULL; } bind = smpp_pdu_create(bind_transmitter, counter_increase(smpp->message_id_counter)); bind->u.bind_transmitter.system_id = octstr_duplicate(smpp->username); bind->u.bind_transmitter.password = octstr_duplicate(smpp->password); if (smpp->system_type == NULL) bind->u.bind_transmitter.system_type = octstr_create("VMA"); else bind->u.bind_transmitter.system_type = octstr_duplicate(smpp->system_type); bind->u.bind_transmitter.interface_version = smpp->version; bind->u.bind_transmitter.address_range = octstr_duplicate(smpp->address_range); bind->u.bind_transmitter.addr_ton = smpp->bind_addr_ton; bind->u.bind_transmitter.addr_npi = smpp->bind_addr_npi; send_pdu(conn, smpp->conn->id, bind); smpp_pdu_destroy(bind); return conn; } /* * Open transceiver connection to SMS center. Return NULL for error, * open Connection for OK. Caller must set smpp->conn->status correctly * before calling this. */ static Connection *open_transceiver(SMPP *smpp) { SMPP_PDU *bind; Connection *conn; conn = conn_open_tcp(smpp->host, smpp->transmit_port, smpp->conn->our_host ); if (conn == NULL) { error(0, "SMPP[%s]: Couldn't connect to server.", octstr_get_cstr(smpp->conn->id)); return NULL; } bind = smpp_pdu_create(bind_transceiver, counter_increase(smpp->message_id_counter)); bind->u.bind_transceiver.system_id = octstr_duplicate(smpp->username); bind->u.bind_transceiver.password = octstr_duplicate(smpp->password); if (smpp->system_type == NULL) bind->u.bind_transceiver.system_type = octstr_create("VMA"); else bind->u.bind_transceiver.system_type = octstr_duplicate(smpp->system_type); bind->u.bind_transceiver.interface_version = smpp->version; bind->u.bind_transceiver.address_range = octstr_duplicate(smpp->address_range); bind->u.bind_transceiver.addr_ton = smpp->bind_addr_ton; bind->u.bind_transceiver.addr_npi = smpp->bind_addr_npi; send_pdu(conn, smpp->conn->id, bind); smpp_pdu_destroy(bind); return conn; } /* * Open reception connection to SMS center. Return NULL for error, * open Connection for OK. Caller must set smpp->conn->status correctly * before calling this. */ static Connection *open_receiver(SMPP *smpp){ SMPP_PDU *bind; Connection *conn; conn = conn_open_tcp(smpp->host, smpp->receive_port, smpp->conn->our_host ); if (conn == NULL) { error(0, "SMPP[%s]: Couldn't connect to server.", octstr_get_cstr(smpp->conn->id)); return NULL; } bind = smpp_pdu_create(bind_receiver, counter_increase(smpp->message_id_counter)); bind->u.bind_receiver.system_id = octstr_duplicate(smpp->username); bind->u.bind_receiver.password = octstr_duplicate(smpp->password); if (smpp->system_type == NULL) bind->u.bind_receiver.system_type = octstr_create("VMA"); else bind->u.bind_receiver.system_type = octstr_duplicate(smpp->system_type); bind->u.bind_receiver.interface_version = smpp->version; bind->u.bind_receiver.address_range = octstr_duplicate(smpp->address_range); bind->u.bind_receiver.addr_ton = smpp->bind_addr_ton; bind->u.bind_receiver.addr_npi = smpp->bind_addr_npi; send_pdu(conn, smpp->conn->id, bind); smpp_pdu_destroy(bind); return conn;}static Msg *handle_dlr(SMPP *smpp, Octstr *destination_addr, Octstr *short_message, Octstr *message_payload, Octstr *receipted_message_id, long message_state){ Msg *dlrmsg = NULL; Octstr *respstr = NULL, *msgid = NULL, *tmp; int dlrstat = -1; /* first check for SMPP v3.4 and above */ if (smpp->version > 0x33 && receipted_message_id) { msgid = octstr_duplicate(receipted_message_id); switch(message_state) { case 1: /* ENROUTE */ case 6: /* ACCEPTED */ dlrstat = DLR_BUFFERED; break; case 2: /* DELIVERED */ dlrstat = DLR_SUCCESS; break; case 3: /* EXPIRED */ case 4: /* DELETED */ case 5: /* UNDELIVERABLE */ case 7: /* UNKNOWN */ case 8: /* REJECTED */ dlrstat = DLR_FAIL; break; default: warning(0, "SMPP[%s]: Got DLR with unknown 'message_state' (%ld).", octstr_get_cstr(smpp->conn->id), message_state); dlrstat = DLR_FAIL; break; } } /* check for SMPP v.3.4. and message_payload */ if (smpp->version > 0x33 && octstr_len(short_message) == 0) respstr = message_payload; else respstr = short_message; /* still no msgid ? */ if (!msgid && respstr) { long curr = 0, vpos = 0; Octstr *stat = NULL; char id_cstr[65], stat_cstr[16], sub_d_cstr[13], done_d_cstr[13]; int sub, dlrvrd, ret; /* get server message id */ /* first try sscanf way if thus failed then old way */ ret = sscanf(octstr_get_cstr(respstr), "id:%64[^s] sub:%d dlvrd:%d submit date:%12[0-9] done date:%12[0-9] stat:%10[^t^e]", id_cstr, &sub, &dlrvrd, sub_d_cstr, done_d_cstr, stat_cstr); if (ret == 6) { msgid = octstr_create(id_cstr); octstr_strip_blanks(msgid); stat = octstr_create(stat_cstr); octstr_strip_blanks(stat); } else { debug("bb.sms.smpp", 0, "SMPP[%s]: Couldnot parse DLR string sscanf way," "fallback to old way. Please report!", octstr_get_cstr(smpp->conn->id)); if ((curr = octstr_search(respstr, octstr_imm("id:"), 0)) != -1) { vpos = octstr_search_char(respstr, ' ', curr); if ((vpos-curr >0) && (vpos != -1)) msgid = octstr_copy(respstr, curr+3, vpos-curr-3); } else { msgid = NULL; } /* get err & status code */ if ((curr = octstr_search(respstr, octstr_imm("stat:"), 0)) != -1) { vpos = octstr_search_char(respstr, ' ', curr); if ((vpos-curr >0) && (vpos != -1)) stat = octstr_copy(respstr, curr+5, vpos-curr-5); } else { stat = NULL; } } /* * we get the following status: * DELIVRD, ACCEPTD, EXPIRED, DELETED, UNDELIV, UNKNOWN, REJECTD * * Note: some buggy SMSC's send us immediately delivery notifications although * we doesn't requested these. */ if (stat != NULL && octstr_compare(stat, octstr_imm("DELIVRD")) == 0) dlrstat = DLR_SUCCESS; else if (stat != NULL && (octstr_compare(stat, octstr_imm("ACCEPTD")) == 0 || octstr_compare(stat, octstr_imm("ACKED")) == 0 || octstr_compare(stat, octstr_imm("BUFFRED")) == 0 || octstr_compare(stat, octstr_imm("BUFFERD")) == 0 || octstr_compare(stat, octstr_imm("ENROUTE")) == 0)) dlrstat = DLR_BUFFERED; else dlrstat = DLR_FAIL; if (stat != NULL) octstr_destroy(stat); } if (msgid != NULL) { /* * Obey which SMPP msg_id type this SMSC is using, where we * have the following semantics for the variable smpp_msg_id: * * bit 1: type for submit_sm_resp, bit 2: type for deliver_sm * * if bit is set value is hex otherwise dec * * 0x00 deliver_sm dec, submit_sm_resp dec * 0x01 deliver_sm dec, submit_sm_resp hex * 0x02 deliver_sm hex, submit_sm_resp dec * 0x03 deliver_sm hex, submit_sm_resp hex * * Default behaviour is SMPP spec compliant, which means * msg_ids should be C strings and hence non modified. */ if (smpp->smpp_msg_id_type == -1) { /* the default, C string */ tmp = octstr_duplicate(msgid); } else { if ((smpp->smpp_msg_id_type & 0x02) || (!octstr_check_range(msgid, 0, octstr_len(msgid), gw_isdigit))) { tmp = octstr_format("%lu", strtoll(octstr_get_cstr(msgid), NULL, 16)); } else { tmp = octstr_format("%lu", strtoll(octstr_get_cstr(msgid), NULL, 10)); } } dlrmsg = dlr_find(smpp->conn->id, tmp, /* smsc message id */ destination_addr, /* destination */ dlrstat); octstr_destroy(msgid); } else tmp = octstr_create(""); if (dlrmsg != NULL) { /* * we found the delivery report in our storage, so recode the * message structure. * The DLR trigger URL is indicated by msg->sms.dlr_url. */ dlrmsg->sms.msgdata = octstr_duplicate(respstr); dlrmsg->sms.sms_type = report_mo; } else { error(0,"SMPP[%s]: got DLR but could not find message or was not interested " "in it id<%s> dst<%s>, type<%d>", octstr_get_cstr(smpp->conn->id), octstr_get_cstr(tmp), octstr_get_cstr(destination_addr), dlrstat); } octstr_destroy(tmp); return dlrmsg;}static long smscconn_failure_reason_to_smpp_status(long reason){ switch (reason) { case SMSCCONN_FAILED_REJECTED: return SMPP_ESME_RX_R_APPN; case SMSCCONN_SUCCESS: return SMPP_ESME_ROK; case SMSCCONN_FAILED_QFULL: case SMSCCONN_FAILED_TEMPORARILY: return SMPP_ESME_RX_T_APPN; } return SMPP_ESME_RX_T_APPN;}static void handle_pdu(SMPP *smpp, Connection *conn, SMPP_PDU *pdu, long *pending_submits){ SMPP_PDU *resp; Octstr *os; Msg *msg, *dlrmsg = NULL; long reason; long cmd_stat; struct smpp_msg *smpp_msg = NULL; resp = NULL; switch (pdu->type) { case data_sm: resp = smpp_pdu_create(data_sm_resp, pdu->u.data_sm.sequence_number); /* * If SMSCConn stopped then send temp. error code */ mutex_lock(smpp->conn->flow_mutex); if (smpp->conn->is_stopped) { mutex_unlock(smpp->conn->flow_mutex); resp->u.data_sm.command_status = SMPP_ESME_RX_T_APPN; break; } mutex_unlock(smpp->conn->flow_mutex); /* got a deliver ack (DLR)? * NOTE: following SMPP v3.4. spec. we are interested * only on bits 2-5 (some SMSC's send 0x44, and it's * spec. conforme) */ if (pdu->u.data_sm.esm_class & (0x04|0x08)) { debug("bb.sms.smpp",0,"SMPP[%s] handle_pdu, got DLR", octstr_get_cstr(smpp->conn->id)); dlrmsg = handle_dlr(smpp, pdu->u.data_sm.source_addr, NULL, pdu->u.data_sm.message_payload,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -