📄 smsc_smasi.c
字号:
*/static Octstr *get_dest_addr_ton(SMASI *smasi, Msg *msg) { return get_ton_npi_value(smasi->dest_addr_ton, GSM_ADDR_TON_INTERNATIONAL);}/* * Gets the value to be used as dest_addr_npi. Will use override values * if configured. Will use values from message otherwise. Or fall back to * defaults if nothing given. */static Octstr *get_dest_addr_npi(SMASI *smasi, Msg *msg) { return get_ton_npi_value(smasi->dest_addr_npi, GSM_ADDR_NPI_E164);}/* * Determine the originator (sender number) type based on the number. Will * change the originator number if necessary. */static Octstr *get_originator_type(SMASI *smasi, Octstr *originator) { /* International or alphanumeric sender? */ if (octstr_get_char(originator, 0) == '+') { if (!octstr_check_range(originator, 1, 256, gw_isdigit)) { return octstr_format("%ld", GSM_ADDR_TON_ALPHANUMERIC); } else { /* Numeric sender address with + in front: The + has to be * removed from this international number. */ octstr_delete(originator, 0, 1); return octstr_format("%ld", GSM_ADDR_TON_INTERNATIONAL); } } else if (!octstr_check_range(originator, 0, 256, gw_isdigit)) { return octstr_format("%ld", GSM_ADDR_TON_ALPHANUMERIC); } /* Return the default value. */ return octstr_format("%ld", GSM_ADDR_TON_INTERNATIONAL);}/* * Creates a SubmitReq PDU from an outgoing message. */static SMASI_PDU *msg_to_pdu(SMASI *smasi, Msg *msg) { SMASI_PDU *pdu = smasi_pdu_create(SubmitReq); pdu->u.SubmitReq.Destination = octstr_duplicate(msg->sms.receiver); pdu->u.SubmitReq.Body = octstr_duplicate(msg->sms.msgdata); pdu->u.SubmitReq.Originator = octstr_duplicate(msg->sms.sender); pdu->u.SubmitReq.OriginatorType = get_originator_type(smasi, pdu->u.SubmitReq.Originator); pdu->u.SubmitReq.Sequence = octstr_format("%ld", counter_increase(smasi->message_id_counter)); /* If its a international number starting with +, lets remove the +. */ if (octstr_get_char(pdu->u.SubmitReq.Destination, 0) == '+') octstr_delete(pdu->u.SubmitReq.Destination, 0,1); /* Do ton and npi override - if configured. Use values from message * otherwise. */ pdu->u.SubmitReq.OriginatorType = get_source_addr_ton(smasi, msg); pdu->u.SubmitReq.OriginatorPlan = get_source_addr_npi(smasi, msg); pdu->u.SubmitReq.DestinationType = get_dest_addr_ton(smasi, msg); pdu->u.SubmitReq.DestinationPlan = get_dest_addr_npi(smasi, msg); /* Set priority. */ if (smasi->priority >= 0 && smasi->priority <= 3) { pdu->u.SubmitReq.MqPriority = octstr_format("%ld", smasi->priority); } else { pdu->u.SubmitReq.MqPriority = octstr_format("%ld", 0); } /* Set encoding. */ if (msg->sms.coding != 0) { if (msg->sms.coding == 1) pdu->u.SubmitReq.MsEncoding = octstr_create("7bit"); else if (msg->sms.coding == 2) pdu->u.SubmitReq.MsEncoding = octstr_create("8bit"); else if (msg->sms.coding == 2) pdu->u.SubmitReq.MsEncoding = octstr_create("16bit"); /* Everything else will default to 7bit. */ } /* Set messaging class - if within defined parameter range. */ if (msg->sms.mclass >= 0 && msg->sms.mclass <= 4) pdu->u.SubmitReq.Class = octstr_format("%ld", (msg->sms.mclass - 1)); /* Set Protocol ID. */ pdu->u.SubmitReq.ProtocolID = octstr_format("%ld", msg->sms.pid); /* Check if SMS is binary. */ if (msg->sms.udhdata && octstr_len(msg->sms.udhdata) > 0) { pdu->u.SubmitReq.UserDataHeader = octstr_duplicate(msg->sms.udhdata); pdu->u.SubmitReq.BodyEncoding = octstr_create("Data"); if (pdu->u.SubmitReq.MsEncoding) octstr_destroy(pdu->u.SubmitReq.MsEncoding); pdu->u.SubmitReq.MsEncoding = octstr_create("transparent"); /* Encode data. */ encode_binary_data(pdu->u.SubmitReq.UserDataHeader); encode_binary_data(pdu->u.SubmitReq.Body); } else { /* Otherwise do data escaping. */ escape_data(pdu->u.SubmitReq.Body); } return pdu;} /* * Create a message structure from an incoming DeliverReq PDU. */static Msg *pdu_to_msg(SMASI_PDU *pdu) { Msg *msg = NULL; gw_assert(pdu->type == DeliverReq); gw_assert(pdu->u.DeliverReq.Originator); gw_assert(pdu->u.DeliverReq.Destination); gw_assert(pdu->u.DeliverReq.Body); msg = msg_create(sms);; msg->sms.sender = octstr_duplicate(pdu->u.DeliverReq.Originator); msg->sms.receiver = octstr_duplicate(pdu->u.DeliverReq.Destination); msg->sms.msgdata = octstr_duplicate(pdu->u.DeliverReq.Body); /* Unescape (non-binary) or decode (binary) data. */ if (pdu->u.DeliverReq.UserDataHeader && octstr_len(pdu->u.DeliverReq.UserDataHeader) > 0) { msg->sms.udhdata = octstr_duplicate(pdu->u.DeliverReq.UserDataHeader); decode_binary_data(msg->sms.msgdata); decode_binary_data(msg->sms.udhdata); } else { unescape_data(msg->sms.msgdata); } /* Read priority. */ if (pdu->u.DeliverReq.ProtocolId) if (octstr_parse_long(&msg->sms.pid, pdu->u.DeliverReq.ProtocolId, 0, 10) == -1) msg->sms.pid = 0; /* Read Coding. */ if (pdu->u.SubmitReq.MsEncoding) { /* Use specified coding. */ if (octstr_str_compare(pdu->u.SubmitReq.MsEncoding, "7bit") == 0) msg->sms.coding = 1; else if (octstr_str_compare(pdu->u.SubmitReq.MsEncoding, "8bit") == 0) msg->sms.coding = 2; else if (octstr_str_compare(pdu->u.SubmitReq.MsEncoding, "UCS2") == 0) msg->sms.coding = 3; else if (octstr_str_compare(pdu->u.SubmitReq.MsEncoding, "transparent") == 0) msg->sms.coding = 2; } else { /* Determine specified coding according to udhdata presence. */ if (pdu->u.SubmitReq.UserDataHeader) msg->sms.coding = 2; else msg->sms.coding = 1; } /* Read message class. */ if (pdu->u.SubmitReq.Class) { if (octstr_parse_long(&msg->sms.mclass, pdu->u.SubmitReq.Class, 0, 10) == -1) msg->sms.mclass = 0; /* Set to unspecified. */ else msg->sms.mclass++; /* Correct value mapping. */ } /* Read protocol ID. */ if (pdu->u.SubmitReq.ProtocolID) if (octstr_parse_long(&msg->sms.pid, pdu->u.SubmitReq.ProtocolID, 0, 10) == -1) msg->sms.pid = 0; return msg;} /************************************************************************//* PDU HANDLING *//************************************************************************/static void send_logoff(SMASI *smasi, Connection *conn) { SMASI_PDU *pdu = NULL; Octstr *os = NULL; counter_increase(smasi->message_id_counter); pdu = smasi_pdu_create(LogoffReq); pdu->u.LogoffReq.Reason = octstr_create("Client shutting down"); dump_pdu("Sending !LogoffReq:", smasi->conn->id, pdu); os = smasi_pdu_pack(pdu); conn_write(conn, os); octstr_destroy(os); smasi_pdu_destroy(pdu);} static void send_enquire_link(SMASI *smasi, Connection *conn, long *last_sent) { SMASI_PDU *pdu = NULL; Octstr *os = NULL; if (date_universal_now() - *last_sent < smasi->enquire_link_interval) return; *last_sent = date_universal_now(); pdu = smasi_pdu_create(EnquireLinkReq); dump_pdu("Sending EnquireLinkReq:", smasi->conn->id, pdu); os = smasi_pdu_pack(pdu); if (os) conn_write(conn, os); /* Write errors checked by caller. */ octstr_destroy(os); smasi_pdu_destroy(pdu); } static int send_pdu(Connection *conn, Octstr *id, SMASI_PDU *pdu){ Octstr * os = NULL; int ret = 0; dump_pdu("Sending PDU:", id, pdu); os = smasi_pdu_pack(pdu); if (os) ret = conn_write(conn, os); else ret = -1; octstr_destroy(os); return ret;} /* * Try to read a SMASI PDU from a connection. Return -1 for error (caller * should close the connection), 0 for no PDU ready yet, or 1 for PDU read * and unpacked. Return a pointer to the PDU in `*pdu'. */static int read_pdu(SMASI *smasi, Connection *conn, SMASI_PDU **pdu) { Octstr *os; os = smasi_pdu_read(conn); if (os == NULL) { if (conn_eof(conn) || conn_read_error(conn)) return -1; return 0; } *pdu = smasi_pdu_unpack(os); if (*pdu == NULL) { error(0, "SMASI[%s]: PDU unpacking failed.", octstr_get_cstr(smasi->conn->id)); debug("bb.sms.smasi", 0, "SMASI[%s]: Failed PDU follows.", octstr_get_cstr(smasi->conn->id)); octstr_dump(os, 0); octstr_destroy(os); return -1; } octstr_destroy(os); return 1;}static void handle_pdu(SMASI *smasi, Connection *conn, SMASI_PDU *pdu, long *pending_submits) { SMASI_PDU *resp = NULL; Msg *msg = NULL; long reason; switch (pdu->type) { case DeliverReq: msg = pdu_to_msg(pdu); if (smasi->my_number && octstr_len(smasi->my_number)) { octstr_destroy(msg->sms.receiver); msg->sms.receiver = octstr_duplicate(smasi->my_number); } time(&msg->sms.time); msg->sms.smsc_id = octstr_duplicate(smasi->conn->id); bb_smscconn_receive(smasi->conn, msg); resp = smasi_pdu_create(DeliverConf); if (pdu->u.DeliverReq.Sequence) resp->u.DeliverConf.Sequence = octstr_duplicate(pdu->u.DeliverReq.Sequence); if (pdu->u.DeliverReq.MsgReference) resp->u.DeliverConf.MsgReference = octstr_duplicate(pdu->u.DeliverReq.MsgReference); break; case SubmitConf: if (pdu->u.SubmitConf.Sequence) { msg = dict_remove(smasi->sent_msgs, pdu->u.SubmitConf.Sequence); } else { msg = NULL; } if (msg == NULL) { warning(0, "SMASI[%s]: SMSC sent SubmitConf for unknown message.", octstr_get_cstr(smasi->conn->id)); } else { debug("bb.sms.smasi",0, "SMSC[%s]: SMSC confirmed msg seq <%s> ref <%s>", octstr_get_cstr(smasi->conn->id), octstr_get_cstr(pdu->u.SubmitConf.Sequence), octstr_get_cstr(pdu->u.SubmitConf.MsgReference)); bb_smscconn_sent(smasi->conn, msg); --(*pending_submits); } break; case SubmitRej: if (pdu->u.SubmitRej.Sequence) { msg = dict_remove(smasi->sent_msgs, pdu->u.SubmitRej.Sequence); } else { msg = NULL; } error(0, "SMASI[%s]: SMSC returned error code %s for " "message ref <%s>", octstr_get_cstr(smasi->conn->id), octstr_get_cstr(pdu->u.SubmitRej.RejectCode), octstr_get_cstr(pdu->u.SubmitRej.MsgReference)); if (msg == NULL) { warning(0, "SMASI[%s]: SMSC sent SubmitRej for unknown message.", octstr_get_cstr(smasi->conn->id)); } else { reason = SMSCCONN_FAILED_REJECTED; bb_smscconn_send_failed(smasi->conn, msg, reason); --(*pending_submits);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -