?? smsc_ois.c
字號:
ois_disconnect(smsc); /* smsc->socket */ ois_swap_buffering(smsc); SAY(4, "ois_disconnect_all: ois_disconnect"); ois_disconnect(smsc); /* smsc->socket */ if (smsc->ois_listening_socket != -1) { if (close(smsc->ois_listening_socket) == -1) { warning(errno, "ois_disconnect_all: close failed..."); } smsc->ois_listening_socket = -1; } return;}static void ois_disconnect(SMSCenter *smsc){ SAY2(2, "ois_disconnect fd=%d", smsc->socket); if (smsc->socket != -1) { if (close(smsc->socket) == -1) { warning(errno, "ois_disconnect: close failed..."); } smsc->socket = -1; } return;}static int ois_read_into_buffer(SMSCenter *smsc, long wait_usec){ int ret; SAY(8, "ois_read_into_buffer"); if (smsc->socket == -1) { if ((smsc->ois_flags & OIS_FLAG_CLOSED) == 0) { debug("bb.sms.ois", 0, "attempting to read from a closed socket"); smsc->ois_flags |= OIS_FLAG_CLOSED; } return 0; } else { smsc->ois_flags &= ~OIS_FLAG_CLOSED; } ret = read_available(smsc->socket, wait_usec); if (ret > 0) { time(&smsc->ois_alive); ret = smscenter_read_into_buffer(smsc); if (ret > 0 || (ret == 0 && smsc->buflen > 0)) { SAY(2, "ois_read_into_buffer got something"); } else if (ret == 0) { if (smsc->buflen > 0) { SAY(2, "ois_read_into_buffer has something"); ret = 1; } SAY(4, "ois_read_into_buffer: ois_disconnect"); ois_disconnect(smsc); } } return ret;}static int ois_check_input(SMSCenter *smsc, long wait_usec){ char buffer[BUFLEN+1]; time_t now; int ret; SAY(8, "ois_check_input"); ret = ois_read_into_buffer(smsc, wait_usec); if (ret < 0) { goto error; } ret = ois_extract_msg_from_buffer(buffer, smsc); if (ret > 0) { IOTRACE("received", buffer, ret); switch (buffer[0]) { case 's': ret = ois_submit_sm_result(smsc, buffer); if (ret > 0) { warning(0, "ois_check_input: submit sm result signals (%d)...", ret); } else if (ret < 0) { error(0, "ois_check_input: invalid submit sm result"); goto error; } --smsc->ois_ack_debt; time(&smsc->ois_alive); break; case 'M': ret = ois_deliver_sm_invoke(smsc, buffer); if (ret >= 0) { ret = ois_deliver_sm_result(smsc, ret, buffer); if (ret < 0) { goto error; } } else { error(0, "ois_check_input: invalid deliver sm invoke"); goto error; } time(&smsc->ois_alive); break; default: warning(0, "ois_check_input: unexpected message [%s]...", ois_debug_str(buffer, ret)); break; } } else { if (smsc->socket != -1) { time(&now); if ((now - smsc->ois_alive) > OIS_MESSAGE_WAITTIME) { debug("bb.sms.ois", 0, "closing an idle connection"); SAY(4, "ois_check_input: ois_disconnect"); ois_disconnect(smsc); } } } if (ret < 0) { error(0, "ois_check_input: malformatted message [%s]", ois_debug_str(buffer, -ret)); goto error; } if (smsc->ois_received_mo != NULL || (smsc->ois_flags & OIS_FLAG_ERROR) != 0) { SAY(2, "ois_check_input has something"); return 1; /* at least one message in the queue or an error pending */ } else { return 0; /* no messages this time */ } error: smsc->ois_flags |= OIS_FLAG_ERROR; return 1;}static int ois_check_incoming(SMSCenter *smsc, long wait_usec){ fd_set read_fd; struct timeval tv; int ret; SAY(8, "ois_check_incoming"); tv.tv_sec = 0; tv.tv_usec = wait_usec; FD_ZERO(&read_fd); FD_SET(smsc->ois_listening_socket, &read_fd); ret = select(smsc->ois_listening_socket + 1, &read_fd, NULL, NULL, &tv); if (ret == -1) { if (errno == EINTR || errno == EAGAIN) { return 0; } else { error(errno, "ois_check_incoming: select failed"); smsc->ois_flags |= OIS_FLAG_ERROR; return -1; } } else if (ret == 0) { return 0; } /* if we end up here, someone is trying to connect */ if (smsc->socket != -1) { if ((smsc->ois_flags & OIS_FLAG_MULTIPLE_CALL) == 0) { /* if you see lots of these, maybe we should accept */ /* multiple incoming connections at a time... */ debug("bb.sms.ois", 0, "letting an incoming call to wait until the old one disconnects"); smsc->ois_flags |= OIS_FLAG_MULTIPLE_CALL; } return 0; } smsc->ois_flags &= ~OIS_FLAG_MULTIPLE_CALL; return ois_open_receiver(smsc);}static void ois_append_to_list(ois_listentry **head, Msg *msg){ ois_listentry *item; ois_listentry *tail; SAY(2, "ois_append_to_list"); item = gw_malloc(sizeof(ois_listentry)); item->next = NULL; item->msg = msg; if (*head == NULL) { *head = item; } else { /* not so bright algorithm, but ok with relatively short lists */ for (tail = *head; tail->next != NULL; tail = tail->next) ; tail->next = item; } return;}static int ois_int_to_i4(char *raw, int nbr){ int pos; SAY(3, "ois_int_to_i4"); for (pos = 0; pos < 4; ++pos) { raw[pos] = (char)(nbr % 0x100); nbr /= 0x100; } return 4;}static int ois_increment_counter(void){ SAY(3, "ois_increment_counter"); ois_counter = (ois_counter+1) % MAXCOUNTER; return ois_counter;}static int ois_submit_sm_invoke(SMSCenter *smsc, const Msg *msg){ char body[BUFLEN+1]; char buffer[BUFLEN+1]; int len; int count; int i; int ret; SAY(2, "ois_submit_sm_invoke"); /* construct a message */ ois_increment_counter(); /* once per invoke */ len = ois_encode_submit_sm_invoke(body, msg); /* the x.25 gear should be capable to fragment large messages, but... */ /* let's just use an explicit 128 byte blocks */ count = (len-1) / 121; /* 121 = 128 - 6 - 1 */ /* first part */ sprintf(buffer, "%c%c%04d%.121s%c", 'S', /* submit sm invoke */ (char)(0x50|count), /* ia5 encoding, first part */ ois_counter, &body[0], EOL); IOTRACE("sending", buffer, strlen(buffer)); ret = write_to_socket(smsc->socket, buffer); if (ret < 0) { goto error; } /* additional parts */ for (i = 1; i <= count; ++i) { sprintf(buffer, "%c%c%04d%.121s%c", 'S', /* submit sm invoke */ (char)(0x60|(count-i)), /* ia5, additional part */ ois_counter, &body[i*121], EOL); IOTRACE("sending", buffer, strlen(buffer)); ret = write_to_socket(smsc->socket, buffer); if (ret < 0) { goto error; } } SAY(2, "ois_submit_sm_invoke ok"); return 0; error: SAY(2, "ois_submit_sm_invoke error"); return -1;}static int ois_encode_submit_sm_invoke(char *str, const Msg *msg){ char raw[BUFLEN]; int pos; int ret; SAY(3, "ois_encode_submit_sm_invoke"); /* construct the submit sm invoke body content */ pos = 0; pos += ois_append_msisdn(&raw[pos], msg); pos += ois_append_sme_reference_number(&raw[pos]); pos += ois_append_priority(&raw[pos]); pos += ois_append_originating_address(&raw[pos]); pos += ois_append_validity_period(&raw[pos]); pos += ois_append_data_coding_scheme(&raw[pos], msg); pos += ois_append_status_report_request(&raw[pos]); pos += ois_append_protocol_id(&raw[pos]); pos += ois_append_submission_options(&raw[pos], msg); pos += ois_append_sm_text(&raw[pos], msg); ret = ois_convert_to_ia5(str, raw, pos); return ret;}static int ois_append_msisdn(char *raw, const Msg *msg){ int len; SAY(3, "ois_append_msisdn"); len = octstr_len(msg->sms.receiver); raw[0] = (char) len; memcpy(&raw[1], octstr_get_cstr(msg->sms.receiver), len); return 1 + len;}static int ois_append_sme_reference_number(char *raw){ SAY(3, "ois_append_sme_reference_number"); /* 1=key, 2=not key (OIS 4.5) */ /* or 1=reject duplicates, 2=allow duplicates (OIS 5.0) */ raw[0] = (char) 2; return 1 + ois_int_to_i4(&raw[1], ois_counter);}static int ois_append_priority(char *raw){ SAY(3, "ois_append_priority"); raw[0] = (char) 1; /* 0=high, 1=normal */ return 1;}static int ois_append_originating_address(char *raw){ SAY(3, "ois_append_originating_address"); raw[0] = (char) 2; /* length */ raw[1] = 'A'; /* A3=address type, actual address is unnecessary */ raw[2] = '3'; return 3;}static int ois_append_validity_period(char *raw){ SAY(3, "ois_append_validity_period"); raw[0] = (char) 2; /* 0=none, 1=absolute, 2=relative */ raw[1] = (char) 1; /* relative, (v+1)*5 minutes, v<144 */ return 2;}static int ois_append_data_coding_scheme(char *raw, const Msg *msg){ SAY(3, "ois_append_data_coding_scheme"); /* 0x0f is a special code for ASCII text, the SMSC will convert * this to GSM and set the DCS to 0. * FIXME: Convert to GSM ourselves and use DCS_GSM_TEXT. * FIXME: use fields_to_dcs and try to support DC_UCS2 too ;) */ raw[0] = (char) (msg->sms.coding == DC_8BIT ? DCS_OCTET_DATA : 0x0f); return 1;}static int ois_append_status_report_request(char *raw){ SAY(3, "ois_append_status_report_request"); raw[0] = (char) 0x00; /* bit field, bit 0=abandoned, bit 2=delivered */ return 1;}static int ois_append_protocol_id(char *raw){ SAY(3, "ois_append_protocol_id"); raw[0] = (char) 0; /* 0=default */ return 1;}static int ois_append_submission_options(char *raw, const Msg *msg){ SAY(3, "ois_append_submission_options"); /* bit field, bit 0=reply path, bit 1=udh, bits 3-4=dcs interpretation */ raw[0] = (char) 0x00; if (octstr_len(msg->sms.udhdata)) { raw[0] |= (char) 0x02; } if (msg->sms.coding == DC_8BIT) { /* XXX and UCS-2? */ raw[0] |= (char) 0x10; } return 1;}static int ois_append_sm_text(char *raw, const Msg *msg){ int udhlen7, udhlen8; int msglen7, msglen8; int len; SAY(3, "ois_append_sm_text"); if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) { charset_latin1_to_gsm(msg->sms.udhdata); charset_latin1_to_gsm(msg->sms.msgdata); } /* calculate lengths */ udhlen8 = octstr_len(msg->sms.udhdata); msglen8 = octstr_len(msg->sms.msgdata); udhlen7 = udhlen8; msglen7 = msglen8; len = udhlen8 + msglen8; /* copy text */ raw[0] = (char) (len); raw[1] = (char) (udhlen7 + msglen7); memcpy(&raw[2], octstr_get_cstr(msg->sms.udhdata), udhlen8); memcpy(&raw[2+udhlen8], octstr_get_cstr(msg->sms.msgdata), msglen8); IOTRACE("encoding", &raw[2], len); return 2 + len;}static int ois_submit_sm_result(SMSCenter *smsc, const char *buffer){ int status; int ret; SAY(2, "ois_submit_sm_result"); ret = ois_decode_submit_sm_result(&status, buffer); if (ret < 0) { goto error; } return status; error: return -1;}static int ois_decode_submit_sm_result(int *code, const char *str){ int buflen; char raw[BUFLEN]; int len; SAY(3, "ois_decode_submit_sm_result"); buflen = strlen(str) - 1; if (buflen < 7 || str[0] != 's' || str[1] != 0x50 || str[buflen] != EOL) { goto error; } len = ois_convert_from_ia5(raw, &str[6]); if (len <= 0) { goto error; } *code = raw[0]; *code &= 0xff; /* there is smsc reference number and accept time, but we ignore them */ return 0; error: return -1;}static int ois_deliver_sm_invoke(SMSCenter *smsc, const char *buffer){ Msg *msg; int ret; SAY(2, "ois_deliver_sm_invoke"); msg = msg_create(sms); ret = ois_decode_deliver_sm_invoke(msg, buffer); if (ret < 0) { goto error; } ois_append_to_list((ois_listentry **) &smsc->ois_received_mo, msg); return 0; error: msg_destroy(msg); return -1;}static int ois_decode_deliver_sm_invoke(Msg *msg, const char *str){ char body[BUFLEN+1]; char raw[BUFLEN]; int len; int i; int pos; int ret; SAY(3, "ois_decode_deliver_sm_invoke"); ret = ois_check_deliver_sm_invoke(str); if (ret < 0) { goto error; } /* extract body */ len = strlen(str); for (pos = 0, i = 6; i < len; ++i) { if (str[i] != EOL) { body[pos++] = str[i]; } else { i += 6; } } body[pos] = '\0'; memset(raw, '\0', sizeof(raw)); len = ois_convert_from_ia5(raw, body); /* adjust msg values */ pos = 0; pos += ois_adjust_destination_address(msg, &raw[pos]); pos += ois_ignore_smsc_reference_number(&raw[pos]); pos += ois_adjust_originating_address(msg, &raw[pos]); pos += ois_adjust_data_coding_scheme(msg, &raw[pos]); pos += ois_ignore_protocol_id(&raw[pos]); pos += ois_adjust_additional_information(msg, &raw[pos]); pos += ois_adjust_sm_text(msg, &raw[pos]); pos += ois_ignore_time(&raw[pos]); /* accept time */ pos += ois_ignore_time(&raw[pos]); /* invoke time */ if (pos != len) { error(0, "ois_decode_deliver_sm_invoke: message parsing error (%d!=%d)", pos, len); goto error; } return 0; error: return -1;}static int ois_check_deliver_sm_invoke(const char *str){ int buflen; char buffer[BUFLEN+1]; int count; SAY(3, "ois_check_deliver_sm_invoke");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -