📄 smsc_oisd.c
字号:
octstr_append_char(raw8, oisd_expand_gsm7_from_bits(bits, i)); } gw_free(bits); return raw8;}static void oisd_shrink_gsm7(Octstr *str){ Octstr *result; int len, i; int numbits, value; result = octstr_create(""); len = octstr_len(str); value = 0; numbits = 0; for (i = 0; i < len; i++) { value += octstr_get_char(str, i) << numbits; numbits += 7; if (numbits >= 8) { octstr_append_char(result, value & 0xff); value >>= 8; numbits -= 8; } } if (numbits > 0) octstr_append_char(result, value); octstr_delete(str, 0, LONG_MAX); octstr_append(str, result); octstr_destroy(result);}/**************************************************************************** * Packet encoding functions. They do not allow the creation of invalid * OISD packets. ***************************************************************************//* Build a new packet struct with this operation code and sequence number. */static struct packet *packet_create(int operation, unsigned long opref){ struct packet *packet; unsigned char header[10]; packet = gw_malloc(sizeof(*packet)); packet->operation = operation; packet->opref = opref; /* Opref */ header[0] = opref & 0xff; header[1] = (opref >> 8) & 0xff; header[2] = (opref >> 16) & 0xff; header[3] = (opref >> 24) & 0xff; /* Message Type & Operation */ if (operation > RESPONSE) { header[4] = RESULT; header[5] = operation - RESPONSE; } else { header[4] = INVOKE; header[5] = operation; } /* Unused */ header[6] = 0; header[7] = 0; /* Data Size */ header[8] = 0; header[9] = 0; packet->data = octstr_create_from_data(header, 10); return packet;}static void packet_set_data_size(struct packet *packet){ int len; gw_assert(packet != NULL); len = octstr_len(packet->data) - 10; octstr_set_char(packet->data, 8, len & 0xff); /* Data Size */ octstr_set_char(packet->data, 9, (len >> 8) & 0xff);}static void packet_set_sequence(struct packet *packet, unsigned long opref){ gw_assert(packet != NULL); octstr_set_char(packet->data, 0, opref & 0xff); octstr_set_char(packet->data, 1, (opref >> 8) & 0xff); octstr_set_char(packet->data, 2, (opref >> 16) & 0xff); octstr_set_char(packet->data, 3, (opref >> 24) & 0xff); packet->opref = opref;}static struct packet *packet_encode_message(Msg *msg, SMSCConn *conn){ struct packet *packet; PrivData *pdata = conn->data; int DCS; int setvalidity = 0; int so = 0; int udhlen7, udhlen8; int msglen7, msglen8; Octstr *udhdata = NULL; Octstr *msgdata = NULL; gw_assert(msg != NULL); gw_assert(msg->type == sms); gw_assert(msg->sms.receiver != NULL); DCS = fields_to_dcs(msg, 0); if (msg->sms.sender == NULL) msg->sms.sender = octstr_create(""); if (!parm_valid_address(msg->sms.receiver)) { warning(0, "OISD[%s]: non-digits in destination phone number '%s', discarded", octstr_get_cstr(conn->id), octstr_get_cstr(msg->sms.receiver)); return NULL; } if (!parm_valid_address(msg->sms.sender)) { warning(0, "OISD[%s]: non-digits in originating phone number '%s', discarded", octstr_get_cstr(conn->id), octstr_get_cstr(msg->sms.sender)); return NULL; } packet = packet_create(SUBMIT_SM, BOGUS_SEQUENCE); gw_assert(octstr_check_range(msg->sms.receiver, 0, octstr_len(msg->sms.receiver), isphonedigit)); /* MSISDN length */ octstr_append_char(packet->data, (unsigned char) octstr_len(msg->sms.receiver)); /* MSISDN */ octstr_append(packet->data, msg->sms.receiver); /* Duplicate msg. behaviour */ /* 1=reject duplicates, 2=allow duplicates */ octstr_append_char(packet->data, 2); /* SME ref. no. unused in this protocol implementation, but set */ octstr_append_char(packet->data, 0); octstr_append_char(packet->data, 0); octstr_append_char(packet->data, 0); octstr_append_char(packet->data, 0); /* Priority 0=high, 1=normal */ octstr_append_char(packet->data, 1); gw_assert(octstr_check_range(msg->sms.sender, 0, octstr_len(msg->sms.sender), isphonedigit)); /* Originating address length */ octstr_append_char(packet->data, (unsigned char) (octstr_len(msg->sms.sender) + 2)); /* XXX: GSM operator dependent ? */ /* TON */ octstr_append_char(packet->data, 0x42); /* NPI */ octstr_append_char(packet->data, 0x44); /* Originating address */ octstr_append(packet->data, msg->sms.sender); /* Validity period type 0=none, 1=absolute, 2=relative */ /* * Validity-Period (TP-VP) * see GSM 03.40 section 9.2.3.12 */ if ((setvalidity = msg->sms.validity) != SMS_PARAM_UNDEFINED || (setvalidity = pdata->validityperiod) != SMS_PARAM_UNDEFINED) { /* Validity period type 0=none, 1=absolute, 2=relative */ octstr_append_char(packet->data, 2); if (setvalidity > 635040) setvalidity = 255; else if (setvalidity >= 50400 && setvalidity <= 635040) setvalidity = (setvalidity - 1) / 7 / 24 / 60 + 192 + 1; else if (setvalidity > 43200 && setvalidity < 50400) setvalidity = 197; else if (setvalidity >= 2880 && setvalidity <= 43200) setvalidity = (setvalidity - 1) / 24 / 60 + 166 + 1; else if (setvalidity > 1440 && setvalidity < 2880) setvalidity = 168; else if (setvalidity >= 750 && setvalidity <= 1440) setvalidity = (setvalidity - 720 - 1) / 30 + 143 + 1; else if (setvalidity > 720 && setvalidity < 750) setvalidity = 144; else if (setvalidity >= 5 && setvalidity <= 720) setvalidity = (setvalidity - 1) / 5 - 1 + 1; else if (setvalidity < 5) setvalidity = 0; octstr_append_char(packet->data, setvalidity); } else { /* Validity period type 0=none, 1=absolute, 2=relative */ octstr_append_char(packet->data, 0); setvalidity = 0; /* reset */ } if (setvalidity >= 0 && setvalidity <= 143) debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d minutes", octstr_get_cstr(conn->id), (setvalidity + 1)*5); else if (setvalidity >= 144 && setvalidity <= 167) debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %3.1f hours", octstr_get_cstr(conn->id), ((float)(setvalidity - 143) / 2) + 12); else if (setvalidity >= 168 && setvalidity <= 196) debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d days", octstr_get_cstr(conn->id), (setvalidity - 166)); else debug("bb.smsc.oisd", 0, "OISD[%s]: Validity-Period: %d weeks", octstr_get_cstr(conn->id), (setvalidity - 192)); /* Data coding scheme */ octstr_append_char(packet->data, DCS); /* Explicitly ask not to get status reports. * If we do not do this, the server's default might be to * send status reports in some cases, and we don't do anything * with those reports anyway. */ /* ask for the delivery reports if needed*/ if (!pdata->no_dlr) if (DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask)) octstr_append_char(packet->data, 7); else octstr_append_char(packet->data, 0); else if (pdata->no_dlr && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask)) warning(0, "OISD[%s]: dlr request make no sense while no-dlr set to true", octstr_get_cstr(conn->id)); /* Protocol id 0=default */ octstr_append_char(packet->data, 0); if (octstr_len(msg->sms.udhdata)) so |= 0x02; if (msg->sms.coding == DC_8BIT) so |= 0x10; /* Submission options */ octstr_append_char(packet->data, so); udhlen8 = octstr_len(msg->sms.udhdata); msglen8 = octstr_len(msg->sms.msgdata); udhdata = octstr_duplicate(msg->sms.udhdata); msgdata = octstr_duplicate(msg->sms.msgdata); if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) { debug("bb.sms.oisd", 0, "OISD[%s]: sending latin1=%s", octstr_get_cstr(conn->id), octstr_get_cstr(msg->sms.msgdata)); charset_latin1_to_gsm(msgdata); oisd_shrink_gsm7(msgdata); } /* calculate lengths */ udhlen7 = octstr_len(udhdata); msglen7 = octstr_len(msgdata); octstr_append_char(packet->data, (unsigned char) (udhlen8 + msglen8)); octstr_append_char(packet->data, (unsigned char) (udhlen7 + msglen7)); /* * debug("bb.sms.oisd", 0, "OISD[%s]: packet_encode_message udhlen8=%d, msglen8=%d", * octstr_get_cstr(conn->id), udhlen8, msglen8); * debug("bb.sms.oisd", 0, "OISD[%s]: packet_encode_message udhlen7=%d, msglen7=%d", * octstr_get_cstr(conn->id), udhlen7, msglen7); */ /* copy text */ octstr_append(packet->data, udhdata); octstr_append(packet->data, msgdata); /* Sub-logical SME number */ octstr_append_char(packet->data, 0); octstr_append_char(packet->data, 0); octstr_destroy(udhdata); octstr_destroy(msgdata); return packet;}/*************************************************************************** * Protocol functions. These implement various transactions. * ***************************************************************************//* Give this packet a proper sequence number for sending. */static void packet_set_send_sequence(struct packet *packet, PrivData *pdata){ gw_assert(pdata != NULL); packet_set_sequence(packet, pdata->send_seq); pdata->send_seq++;}static struct packet *oisd_get_packet(PrivData *pdata, Octstr **ts){ struct packet *packet = NULL; gw_assert(pdata != NULL); /* If packet is already available, don't try to read anything */ packet = packet_extract(pdata->inbuffer, pdata->conn); while (packet == NULL) { if (read_available(pdata->socket, RESPONSE_TIMEOUT) != 1) { warning(0, "OISD[%s]: SMSC is not responding", octstr_get_cstr(pdata->conn->id)); return NULL; } if (octstr_append_from_socket(pdata->inbuffer, pdata->socket) <= 0) { error(0, "OISD[%s]: oisd_get_packet: read failed", octstr_get_cstr(pdata->conn->id)); return NULL; } packet = packet_extract(pdata->inbuffer, pdata->conn); } packet_check_can_receive(packet, pdata->conn); debug("bb.sms.oisd", 0, "OISD[%s]: received", octstr_get_cstr(pdata->conn->id)); if (packet->operation != RETRIEVE_REQUEST + RESPONSE) octstr_dump(packet->data, 0); if (ts) *ts = octstr_copy(packet->data, 15, 14); if (pdata->keepalive > 0) pdata->next_ping = time(NULL) + pdata->keepalive; return packet;}/* * Acknowledge a request. */static void oisd_send_response(struct packet *request, PrivData *pdata){ struct packet *response; gw_assert(request != NULL); gw_assert(request->operation < RESPONSE); response = packet_create(request->operation + RESPONSE, request->opref); octstr_append_char(response->data, (char) RESULT_SUCCESS); packet_set_data_size(response); debug("bb.sms.oisd", 0, "OISD[%s]: sending response", octstr_get_cstr(pdata->conn->id)); octstr_dump(response->data, 0); /* Don't check errors here because if there is something * wrong with the socket, the main loop will detect it. */ octstr_write_to_socket(pdata->socket, response->data); packet_destroy(response);}static Msg *oisd_accept_message(struct packet *request, SMSCConn *conn){ Msg *msg = NULL; int DCS; int dest_len; int origin_len; int add_info; int msglen7, msglen8; int udh_len; msg = msg_create(sms); /* See GSM 03.38. The bit patterns we can handle are: * 000xyyxx Uncompressed text, yy indicates alphabet. * yy = 00, default alphabet * yy = 01, 8-bit data * yy = 10, UCS2 * yy = 11, reserved * 1111xyxx Data, y indicates alphabet. * y = 0, default alphabet * y = 1, 8-bit data */ /* Additional information * xxxxxxyz This field conveys additional information to assist
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -