static void sms_tx_queue_remove_entry(struct ofono_sms *sms, GList *entry_list, enum message_state tx_state) { struct tx_queue_entry *entry = entry_list->data; struct ofono_modem *modem = __ofono_atom_get_modem(sms->atom); g_queue_delete_link(sms->txq, entry_list); DBG("%p", entry); if (entry->cb) entry->cb(tx_state == MESSAGE_STATE_SENT, entry->data); if (entry->flags & OFONO_SMS_SUBMIT_FLAG_RECORD_HISTORY) { enum ofono_history_sms_status hs; switch(tx_state) { case MESSAGE_STATE_SENT: hs = OFONO_HISTORY_SMS_STATUS_SUBMITTED; break; case MESSAGE_STATE_FAILED: hs = OFONO_HISTORY_SMS_STATUS_SUBMIT_FAILED; break; case MESSAGE_STATE_CANCELLED: hs = OFONO_HISTORY_SMS_STATUS_SUBMIT_CANCELLED; break; default: ofono_error("Unexpected sms state %d", tx_state); goto done; } __ofono_history_sms_send_status(modem, &entry->uuid, time(NULL), hs); } if (entry->flags & OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS) { struct message *m; sms_tx_backup_free(sms->imsi, entry->id, entry->flags, ofono_uuid_to_str(&entry->uuid)); m = g_hash_table_lookup(sms->messages, &entry->uuid); if (m != NULL) { message_set_state(m, tx_state); g_hash_table_remove(sms->messages, &entry->uuid); message_emit_removed(m, OFONO_MESSAGE_MANAGER_INTERFACE); message_dbus_unregister(m); } } done: tx_queue_entry_destroy(entry); }
const char *message_path_from_uuid(struct ofono_atom *atom, const struct ofono_uuid *uuid) { static char path[256]; const char *atompath = __ofono_atom_get_path(atom); snprintf(path, sizeof(path), "%s/message_%s", atompath, ofono_uuid_to_str(uuid)); return path; }
static void example_history_sms_send_status( struct ofono_history_context *context, const struct ofono_uuid *uuid, time_t when, enum ofono_history_sms_status s) { char buf[128]; strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", localtime(&when)); buf[127] = '\0'; switch (s) { case OFONO_HISTORY_SMS_STATUS_PENDING: break; case OFONO_HISTORY_SMS_STATUS_SUBMITTED: ofono_debug("SMS %s submitted successfully", ofono_uuid_to_str(uuid)); ofono_debug("Submission Time: %s", buf); break; case OFONO_HISTORY_SMS_STATUS_SUBMIT_FAILED: ofono_debug("Sending SMS %s failed", ofono_uuid_to_str(uuid)); ofono_debug("Failure Time: %s", buf); break; case OFONO_HISTORY_SMS_STATUS_SUBMIT_CANCELLED: ofono_debug("Submission of SMS %s was canceled", ofono_uuid_to_str(uuid)); ofono_debug("Cancel time: %s", buf); break; case OFONO_HISTORY_SMS_STATUS_DELIVERED: ofono_debug("SMS delivered, msg_id: %s, time: %s", ofono_uuid_to_str(uuid), buf); break; case OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED: ofono_debug("SMS undeliverable, msg_id: %s, time: %s", ofono_uuid_to_str(uuid), buf); break; default: break; } }
static void example_history_sms_send_pending(struct ofono_history_context *context, const struct ofono_uuid *uuid, const char *to, time_t when, const char *text) { char buf[128]; ofono_debug("Sending SMS on modem: %p", context->modem); ofono_debug("InternalMessageId: %s", ofono_uuid_to_str(uuid)); ofono_debug("To: %s:", to); strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", localtime(&when)); buf[127] = '\0'; ofono_debug("Local Time: %s", buf); ofono_debug("Text: %s", text); }
static void example_history_sms_received(struct ofono_history_context *context, const struct ofono_uuid *uuid, const char *from, const struct tm *remote, const struct tm *local, const char *text) { char buf[128]; ofono_debug("Incoming SMS on modem: %p", context->modem); ofono_debug("InternalMessageId: %s", ofono_uuid_to_str(uuid)); ofono_debug("From: %s", from); strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", local); buf[127] = '\0'; ofono_debug("Local Sent Time: %s", buf); strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", remote); buf[127] = '\0'; ofono_debug("Remote Sent Time: %s", buf); ofono_debug("Text: %s", text); }
static void tx_finished(const struct ofono_error *error, int mr, void *data) { struct ofono_sms *sms = data; struct tx_queue_entry *entry = g_queue_peek_head(sms->txq); gboolean ok = error->type == OFONO_ERROR_TYPE_NO_ERROR; enum message_state tx_state; DBG("tx_finished %p", entry); sms->flags &= ~MESSAGE_MANAGER_FLAG_TXQ_ACTIVE; if (ok == FALSE) { /* Retry again when back in online mode */ /* Note this does not increment retry count */ if (sms->registered == FALSE) return; tx_state = MESSAGE_STATE_FAILED; /* Retry done only for Network Timeout failure */ if (error->type == OFONO_ERROR_TYPE_CMS && error->error != NETWORK_TIMEOUT) goto next_q; if (!(entry->flags & OFONO_SMS_SUBMIT_FLAG_RETRY)) goto next_q; entry->retry += 1; if (entry->retry < TXQ_MAX_RETRIES) { DBG("Sending failed, retry in %d secs", entry->retry * 5); sms->tx_source = g_timeout_add_seconds(entry->retry * 5, tx_next, sms); return; } DBG("Max retries reached, giving up"); goto next_q; } if (entry->flags & OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS) sms_tx_backup_remove(sms->imsi, entry->id, entry->flags, ofono_uuid_to_str(&entry->uuid), entry->cur_pdu); entry->cur_pdu += 1; entry->retry = 0; if (entry->flags & OFONO_SMS_SUBMIT_FLAG_REQUEST_SR) status_report_assembly_add_fragment(sms->sr_assembly, entry->uuid.uuid, &entry->receiver, mr, time(NULL), entry->num_pdus); if (entry->cur_pdu < entry->num_pdus) { sms->tx_source = g_timeout_add(0, tx_next, sms); return; } tx_state = MESSAGE_STATE_SENT; next_q: sms_tx_queue_remove_entry(sms, g_queue_peek_head_link(sms->txq), tx_state); if (sms->registered == FALSE) return; if (g_queue_peek_head(sms->txq)) { DBG("Scheduling next"); sms->tx_source = g_timeout_add(0, tx_next, sms); } }
int __ofono_sms_txq_submit(struct ofono_sms *sms, GSList *list, unsigned int flags, struct ofono_uuid *uuid, ofono_sms_txq_queued_cb_t cb, void *data) { struct message *m = NULL; struct tx_queue_entry *entry; entry = tx_queue_entry_new(list, flags); if (entry == NULL) return -ENOMEM; if (flags & OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS) { m = message_create(&entry->uuid, sms->atom); if (m == NULL) goto err; if (message_dbus_register(m) == FALSE) goto err; message_set_data(m, entry); g_hash_table_insert(sms->messages, &entry->uuid, m); } if (list->next != NULL) { if (sms->ref == 65536) sms->ref = 1; else sms->ref = sms->ref + 1; } entry->id = sms->tx_counter++; g_queue_push_tail(sms->txq, entry); if (sms->registered && g_queue_get_length(sms->txq) == 1) sms->tx_source = g_timeout_add(0, tx_next, sms); if (uuid) memcpy(uuid, &entry->uuid, sizeof(*uuid)); if (flags & OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS) { const char *uuid_str; unsigned char i; uuid_str = ofono_uuid_to_str(&entry->uuid); for (i = 0; i < entry->num_pdus; i++) { struct pending_pdu *pdu; pdu = &entry->pdus[i]; sms_tx_backup_store(sms->imsi, entry->id, entry->flags, uuid_str, i, pdu->pdu, pdu->pdu_len, pdu->tpdu_len); } } if (cb) cb(sms, &entry->uuid, data); if (m && (flags & OFONO_SMS_SUBMIT_FLAG_EXPOSE_DBUS)) message_emit_added(m, OFONO_MESSAGE_MANAGER_INTERFACE); return 0; err: tx_queue_entry_destroy(entry); return -EINVAL; }
static void sms_history_sms_send_status( struct ofono_history_context *context, const struct ofono_uuid *uuid, time_t when, enum ofono_history_sms_status s) { if ((s == OFONO_HISTORY_SMS_STATUS_DELIVERED) || (s == OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED)) { DBusMessage *signal; DBusMessageIter iter; DBusMessageIter dict; const char *uuid_str; char *msg_uuid_str; size_t msg_len; struct ofono_atom *atom; const char *path; DBusConnection *conn; int delivered; atom = __ofono_modem_find_atom(context->modem, OFONO_ATOM_TYPE_SMS); if (atom == NULL) return; path = __ofono_atom_get_path(atom); if (path == NULL) return; conn = ofono_dbus_get_connection(); if (conn == NULL) return; delivered = (s == OFONO_HISTORY_SMS_STATUS_DELIVERED); uuid_str = ofono_uuid_to_str(uuid); /* sizeof adds extra space for one '\0' */ msg_len = strlen(path) + sizeof(msg_prefix) + strlen(uuid_str); msg_uuid_str = g_try_malloc(msg_len); if (msg_uuid_str == NULL) return; /* modem path + msg_prefix + UUID as string */ snprintf(msg_uuid_str, msg_len, "%s%s%s", path, msg_prefix, uuid_str); DBG("SMS %s delivery success: %d", msg_uuid_str, delivered); signal = dbus_message_new_signal(path, OFONO_MESSAGE_MANAGER_INTERFACE, "StatusReport"); if (signal != NULL) { dbus_message_iter_init_append(signal, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &msg_uuid_str); dbus_message_iter_open_container( &iter, DBUS_TYPE_ARRAY, OFONO_PROPERTIES_ARRAY_SIGNATURE, &dict); ofono_dbus_dict_append(&dict, "Delivered", DBUS_TYPE_BOOLEAN, &delivered); dbus_message_iter_close_container(&iter, &dict); g_dbus_send_message(conn, signal); } g_free(msg_uuid_str); } }