📄 smsc_emi.c
字号:
/* EMI doesnt understand + so we have to replace it with something useful */ /* we try 00 here. Should really be done in the config instead so this */ /* is only a workaround to make wrong configs work */ octstr_delete(str, 0, 1); octstr_insert_data(str, 0, "00",2); } octstr_truncate(str, 16); /* max length of ADC */ emimsg->fields[E50_ADC] = str; emimsg->fields[E50_XSER] = octstr_create(""); /* XSer 01: UDH */ if (octstr_len(msg->sms.udhdata)) { str = octstr_create(""); octstr_append_char(str, 0x01); octstr_append_char(str, octstr_len(msg->sms.udhdata)); octstr_append(str, msg->sms.udhdata); octstr_binary_to_hex(str, 1); octstr_append(emimsg->fields[E50_XSER], str); octstr_destroy(str); } /* XSer 02: DCS */ dcs = fields_to_dcs(msg, msg->sms.alt_dcs); if (dcs != 0 && dcs != 4) { str = octstr_create(""); octstr_append_char(str, 0x02); octstr_append_char(str, 1); /* len 01 */ octstr_append_char(str, dcs); octstr_binary_to_hex(str, 1); octstr_append(emimsg->fields[E50_XSER], str); octstr_destroy(str); } /* XSer 0c: billing identifier */ if (octstr_len(msg->sms.binfo)) { str = octstr_create(""); octstr_append_char(str, 0x0c); octstr_append_char(str, octstr_len(msg->sms.binfo)); octstr_append(str, msg->sms.binfo); octstr_binary_to_hex(str, 1); octstr_append(emimsg->fields[E50_XSER], str); octstr_destroy(str); } if (msg->sms.coding == DC_8BIT || msg->sms.coding == DC_UCS2) { emimsg->fields[E50_MT] = octstr_create("4"); emimsg->fields[E50_MCLS] = octstr_create("1"); str = octstr_duplicate(msg->sms.msgdata); emimsg->fields[E50_NB] = octstr_format("%04d", 8 * octstr_len(str)); octstr_binary_to_hex(str, 1); emimsg->fields[E50_TMSG] = str; } else { emimsg->fields[E50_MT] = octstr_create("3"); str = octstr_duplicate(msg->sms.msgdata); charset_latin1_to_gsm(str); /* * Check if we have to apply some after GSM transcoding kludges */ if (privdata->alt_charset == EMI_NRC_ISO_21) charset_gsm_to_nrc_iso_21_german(str); /* Could still be too long after truncation if there's an UDH part, * but this is only to notice errors elsewhere (should never happen).*/ if (charset_gsm_truncate(str, 160)) error(0, "EMI2[%s]: Message to send is longer " "than 160 gsm characters", octstr_get_cstr(privdata->name)); octstr_binary_to_hex(str, 1); emimsg->fields[E50_AMSG] = str; } if (msg->sms.validity >= 0) { tm = gw_localtime(time(NULL) + msg->sms.validity * 60); sprintf(p, "%02d%02d%02d%02d%02d", tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, tm.tm_hour, tm.tm_min); str = octstr_create(p); emimsg->fields[E50_VP] = str; } if (msg->sms.deferred >= 0) { str = octstr_create("1"); emimsg->fields[E50_DD] = str; tm = gw_localtime(time(NULL) + msg->sms.deferred * 60); sprintf(p, "%02d%02d%02d%02d%02d", tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 100, tm.tm_hour, tm.tm_min); str = octstr_create(p); emimsg->fields[E50_DDT] = str; } /* if delivery reports are asked, lets ask for them too */ /* even the sender might not be interested in delivery or non delivery */ /* we still need them back to clear out the memory after the message */ /* has been delivered or non delivery has been confirmed */ if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) { emimsg->fields[E50_NRQ] = octstr_create("1"); emimsg->fields[E50_NT] = octstr_create(""); octstr_append_decimal(emimsg->fields[E50_NT], 3 + (DLR_IS_BUFFERED(msg->sms.dlr_mask) ? 4 : 0)); if (privdata->npid) emimsg->fields[E50_NPID] = octstr_duplicate(privdata->npid); if (privdata->nadc) emimsg->fields[E50_NADC] = octstr_duplicate(privdata->nadc); } return emimsg;}/* Return -1 if the connection broke, 0 if the request couldn't be handled * (unknown type), or 1 if everything was successful */static int handle_operation(SMSCConn *conn, Connection *server, struct emimsg *emimsg){ struct emimsg *reply; Octstr *tempstr, *xser; int type, len; Msg *msg = NULL; struct universaltime unitime; int st_code; PrivData *privdata = conn->data; switch(emimsg->ot) { /* * Handle OP/01 call input operation. This operation delivery MO messages * from SMSC to SMT according to [1], section 4.2, p. 9. */ case 01: msg = msg_create(sms); if (emimsg->fields[E01_AMSG] == NULL) emimsg->fields[E01_AMSG] = octstr_create(""); else if (octstr_hex_to_binary(emimsg->fields[E01_AMSG]) == -1) warning(0, "EMI2[%s]: Couldn't decode message text", octstr_get_cstr(privdata->name)); if (emimsg->fields[E01_MT] == NULL) { warning(0, "EMI2[%s]: required field MT missing", octstr_get_cstr(privdata->name)); /* This guess could be incorrect, maybe the message should just be dropped */ emimsg->fields[E01_MT] = octstr_create("3"); } if (octstr_get_char(emimsg->fields[E01_MT], 0) == '3') { msg->sms.msgdata = emimsg->fields[E01_AMSG]; emimsg->fields[E01_AMSG] = NULL; /* So it's not freed */ /* obey the NRC (national replacement codes) */ if (privdata->alt_charset == EMI_NRC_ISO_21) charset_nrc_iso_21_german_to_gsm(msg->sms.msgdata); charset_gsm_to_latin1(msg->sms.msgdata); } else { error(0, "EMI2[%s]: MT == %s isn't supported for operation type 01", octstr_get_cstr(privdata->name), octstr_get_cstr(emimsg->fields[E01_MT])); msg->sms.msgdata = octstr_create(""); } msg->sms.sender = octstr_duplicate(emimsg->fields[E01_OADC]); if (msg->sms.sender == NULL) { warning(0, "EMI2[%s]: Empty sender field in received message", octstr_get_cstr(privdata->name)); msg->sms.sender = octstr_create(""); } if(octstr_len(PRIVDATA(conn)->my_number)) { msg->sms.receiver = octstr_duplicate(PRIVDATA(conn)->my_number); } else { msg->sms.receiver = octstr_duplicate(emimsg->fields[E01_ADC]); } if (msg->sms.receiver == NULL) { warning(0, "EMI2[%s]: Empty receiver field in received message", octstr_get_cstr(privdata->name)); msg->sms.receiver = octstr_create(""); } /* Operation type 01 doesn't have a time stamp field */ time(&msg->sms.time); msg->sms.smsc_id = octstr_duplicate(conn->id); bb_smscconn_receive(conn, msg); reply = emimsg_create_reply(01, emimsg->trn, 1, privdata->name); if (emi2_emimsg_send(conn, server, reply) < 0) { emimsg_destroy(reply); return -1; } emimsg_destroy(reply); return 1; /* * Handle OP/52 delivery short message. This is the MO side of the protocol * implementation. See [1], section 5.4, p. 40. */ case 52: msg = msg_create(sms); /* AMSG is the same field as TMSG */ if (emimsg->fields[E50_AMSG] == NULL) emimsg->fields[E50_AMSG] = octstr_create(""); else if (octstr_hex_to_binary(emimsg->fields[E50_AMSG]) == -1) warning(0, "EMI2[%s]: Couldn't decode message text", octstr_get_cstr(privdata->name)); /* Process XSer fields */ xser = emimsg->fields[E50_XSER]; while (octstr_len(xser) > 0) { int tempint; tempstr = octstr_copy(xser, 0, 4); if (octstr_hex_to_binary(tempstr) == -1) error(0, "EMI2[%s]: Invalid XSer", octstr_get_cstr(privdata->name)); type = octstr_get_char(tempstr, 0); len = octstr_get_char(tempstr, 1); octstr_destroy(tempstr); if (len < 0) { error(0, "EMI2[%s]: Malformed emi XSer field", octstr_get_cstr(privdata->name)); break; } /* Handle supported XSer fields */ switch (type) { case 0x01: /* XSer 01, GSM UDH information */ tempstr = octstr_copy(xser, 4, len * 2); if (octstr_hex_to_binary(tempstr) == -1) error(0, "EMI2[%s]: Invalid UDH contents", octstr_get_cstr(privdata->name)); msg->sms.udhdata = tempstr; break; case 0x02: /* XSer 02, GSM DCS information */ tempstr = octstr_copy(xser, 4, 2); octstr_hex_to_binary(tempstr); tempint = octstr_get_char(tempstr, 0); octstr_destroy(tempstr); if (!dcs_to_fields(&msg, tempint)) { error(0, "EMI2[%s]: Invalid DCS received", octstr_get_cstr(privdata->name)); /* XXX Should we discard message ? */ dcs_to_fields(&msg, 0); } break; /* * XSer 03-0b are for TDMA information exchange and are currently * not implemented in this EMI interface. See CMG EMI/UCP spec 4.0, * section 5.1.2.4 for more information. */ case 0x0c: /* XSer 0c, billing identifier */ tempstr = octstr_copy(xser, 4, len * 2); if (octstr_hex_to_binary(tempstr) == -1) { error(0, "EMI2[%s] Invalid XSer 0c billing identifier <%s>", octstr_get_cstr(privdata->name), octstr_get_cstr(tempstr)); } else { msg->sms.binfo = tempstr; } break; case 0x0d: /* XSer 0d, single shot indicator */ tempstr = octstr_copy(xser, 4, 2); octstr_hex_to_binary(tempstr); tempint = octstr_get_char(tempstr, 0); octstr_destroy(tempstr); if (tempint) info(0, "EMI2[%s]: Single shot indicator set.", octstr_get_cstr(privdata->name)); break; /* XSer fields 0e-ff are reserved for future use. */ default: warning(0, "EMI2[%s]: Unsupported EMI XSer field %d", octstr_get_cstr(privdata->name), type); break; } octstr_delete(xser, 0, 2 * len + 4); } if (emimsg->fields[E50_MT] == NULL) { warning(0, "EMI2[%s]: required field MT missing", octstr_get_cstr(privdata->name)); /* This guess could be incorrect, maybe the message should just be dropped */ emimsg->fields[E50_MT] = octstr_create("3"); } if (octstr_get_char(emimsg->fields[E50_MT], 0) == '3') { msg->sms.msgdata = emimsg->fields[E50_AMSG]; emimsg->fields[E50_AMSG] = NULL; /* So it's not freed */ /* obey the NRC (national replacement codes) */ if (privdata->alt_charset == EMI_NRC_ISO_21) charset_nrc_iso_21_german_to_gsm(msg->sms.msgdata); charset_gsm_to_latin1(msg->sms.msgdata); } else if (octstr_get_char(emimsg->fields[E50_MT], 0) == '4') { msg->sms.msgdata = emimsg->fields[E50_TMSG]; emimsg->fields[E50_TMSG] = NULL; } else { error(0, "EMI2[%s]: MT == %s isn't supported yet", octstr_get_cstr(privdata->name), octstr_get_cstr(emimsg->fields[E50_MT])); msg->sms.msgdata = octstr_create(""); } msg->sms.sender = octstr_duplicate(emimsg->fields[E50_OADC]); if (msg->sms.sender == NULL) { warning(0, "EMI2[%s]: Empty sender field in received message", octstr_get_cstr(privdata->name)); msg->sms.sender = octstr_create(""); } if(octstr_len(PRIVDATA(conn)->my_number)) { msg->sms.receiver = octstr_duplicate(PRIVDATA(conn)->my_number); } else { msg->sms.receiver = octstr_duplicate(emimsg->fields[E50_ADC]); } if (msg->sms.receiver == NULL) { warning(0, "EMI2[%s]: Empty receiver field in received message", octstr_get_cstr(privdata->name)); msg->sms.receiver = octstr_create(""); } tempstr = emimsg->fields[E50_SCTS]; /* Just a shorter name */ if (tempstr == NULL) { warning(0, "EMI2[%s]: Received EMI message doesn't have required timestamp", octstr_get_cstr(privdata->name)); goto notime; } if (octstr_len(tempstr) != 12) { warning(0, "EMI2[%s]: EMI SCTS field must have length 12, now %ld", octstr_get_cstr(privdata->name), octstr_len(tempstr)); goto notime; } if (octstr_parse_long(&unitime.second, tempstr, 10, 10) != 12 || (octstr_delete(tempstr, 10, 2), octstr_parse_long(&unitime.minute, tempstr, 8, 10) != 10) || (octstr_delete(tempstr, 8, 2), octstr_parse_long(&unitime.hour, tempstr, 6, 10) != 8) || (octstr_delete(tempstr, 6, 2), octstr_parse_long(&unitime.year, tempstr, 4, 10) != 6) || (octstr_delete(tempstr, 4, 2), octstr_parse_long(&unitime.month, tempstr, 2, 10) != 4) || (octstr_delete(tempstr, 2, 2), octstr_parse_long(&unitime.day, tempstr, 0, 10) != 2)) { error(0, "EMI2[%s]: EMI delivery time stamp looks malformed", octstr_get_cstr(privdata->name)); notime: time(&msg->sms.time); } else { unitime.year += 2000; /* Conversion function expects full year */ unitime.month -= 1; /* conversion function expects 0-based months */ msg->sms.time = date_convert_universal(&unitime); } msg->sms.smsc_id = octstr_duplicate(conn->id); bb_smscconn_receive(conn, msg); reply = emimsg_create_reply(52, emimsg->trn, 1, privdata->name); if (emi2_emimsg_send(conn, server, reply) < 0) { emimsg_destroy(reply); return -1; } emimsg_destroy(reply); return 1; /* * Handle OP/53 delivery notification. See [1], section 5.5, p. 43. */ case 53: st_code = atoi(octstr_get_cstr(emimsg->fields[E50_DST])); switch(st_code) { case 0: /* delivered */ msg = dlr_find((conn->id ? conn->id : privdata->name), emimsg->fields[E50_SCTS], /* timestamp */ emimsg->fields[E50_OADC], /* destination */ DLR_SUCCESS); break; case 1: /* buffered */ msg = dlr_find((conn->id ? conn->id : privdata->name), emimsg->fields[E50_SCTS], /* timestamp */ emimsg->fields[E50_OADC], /* destination */ DLR_BUFFERED); break; case 2: /* not delivered */ msg = dlr_find((conn->id ? conn->id : privdata->name), emimsg->fields[E50_SCTS], /* timestamp */ emimsg->fields[E50_OADC], /* destination */ DLR_FAIL); break; } if (msg != NULL) { /* * Recode the msg structure with the given msgdata. * Note: the DLR URL is delivered in msg->sms.dlr_url already. */ if((emimsg->fields[E50_AMSG]) == NULL) msg->sms.msgdata = octstr_create("Delivery Report without text"); else msg->sms.msgdata = octstr_duplicate(emimsg->fields[E50_AMSG]); octstr_hex_to_binary(msg->sms.msgdata); bb_smscconn_receive(conn, msg); } reply = emimsg_create_reply(53, emimsg->trn, 1, privdata->name); if (emi2_emimsg_send(conn, server, reply) < 0) { emimsg_destroy(reply); return -1; } emimsg_destroy(reply); return 1; /* * Handle OP/31 from SMSC side. This is not "purely" spec conform since, * the protocol says "This operation can be used by a SMT to alert the SC.", * which implies semantically only the opposite way. For the sake of EMI/UCP * server implementations that send alert messages to SMTs we handle this * without breaking any core protocol concept. * * See [1], section 4.6, p. 19. */ case 31: reply = emimsg_create_reply(31, emimsg->trn, 1, privdata->name); st_code = emi2_emimsg_send(conn, server, reply); emimsg_destroy(reply); return (st_code < 0 ? -1 : 1); default: error(0, "EMI2[%s]: I don't know how to handle operation type %d", octstr_get_cstr(privdata->name), emimsg->ot); return 0; }}/* * get all unacknowledged messages from the ringbuffer and queue them * for retransmission. */static void clear_sent(PrivData *privdata){ int i; debug("smsc.emi2", 0, "EMI2[%s]: clear_sent called",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -