/* * Copyright (c) 2014 HÃ¥vard Pettersson * * This file is part of Tox-WeeChat. * * Tox-WeeChat is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Tox-WeeChat is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Tox-WeeChat. If not, see . */ #include #include #include #include "twc.h" #include "twc-list.h" #include "twc-profile.h" #include "twc-utils.h" #include "twc-message-queue.h" /** * Get a message queue for a friend, or create one if it does not exist. */ struct t_twc_list * twc_message_queue_get_or_create(struct t_twc_profile *profile, int32_t friend_number) { struct t_twc_list *message_queue = weechat_hashtable_get(profile->message_queues, &friend_number); if (!message_queue) { message_queue = twc_list_new(); weechat_hashtable_set(profile->message_queues, &friend_number, message_queue); } return message_queue; } /** * Add a friend message to the message queue and tries to send it if the * friend is online. Handles splitting of messages. (TODO: actually split messages) */ void twc_message_queue_add_friend_message(struct t_twc_profile *profile, int32_t friend_number, const char *message, enum TWC_MESSAGE_TYPE message_type) { struct t_twc_queued_message *queued_message = malloc(sizeof(struct t_twc_queued_message)); time_t rawtime = time(NULL); queued_message->time = malloc(sizeof(struct tm)); memcpy(queued_message->time, gmtime(&rawtime), sizeof(struct tm)); queued_message->message = strdup(message); queued_message->message_type = message_type; // create a queue if needed and add message struct t_twc_list *message_queue = twc_message_queue_get_or_create(profile, friend_number); twc_list_item_new_data_add(message_queue, queued_message); // flush if friend is online if (profile->tox && tox_get_friend_connection_status(profile->tox, friend_number) == 1) twc_message_queue_flush_friend(profile, friend_number); } /** * Try sending queued messages for a friend. */ void twc_message_queue_flush_friend(struct t_twc_profile *profile, int32_t friend_number) { struct t_twc_list *message_queue = twc_message_queue_get_or_create(profile, friend_number); size_t index; struct t_twc_list_item *item; twc_list_foreach(message_queue, index, item) { struct t_twc_queued_message *queued_message = item->queued_message; // TODO: store and deal with message IDs uint32_t rc; switch(queued_message->message_type) { case TWC_MESSAGE_TYPE_MESSAGE: rc = tox_send_message(profile->tox, friend_number, (uint8_t *)queued_message->message, strlen(queued_message->message)); break; case TWC_MESSAGE_TYPE_ACTION: rc = tox_send_action(profile->tox, friend_number, (uint8_t *)queued_message->message, strlen(queued_message->message)); break; } if (rc == 0) { // break if message send failed break; } else { // message was sent, free it twc_message_queue_free_message(queued_message); item->queued_message = NULL; } } // remove any now-empty items while (message_queue->head && !(message_queue->head->queued_message)) twc_list_remove(message_queue->head); } /** * Free a queued message. */ void twc_message_queue_free_message(struct t_twc_queued_message *message) { free(message->time); free(message->message); free(message); } void twc_message_queue_free_map_callback(void *data, struct t_hashtable *hashtable, const void *key, const void *value) { struct t_twc_list *message_queue = ((struct t_twc_list *)value); struct t_twc_queued_message *message; while ((message = twc_list_pop(message_queue))) twc_message_queue_free_message(message); free(message_queue); } void twc_message_queue_free_profile(struct t_twc_profile *profile) { weechat_hashtable_map(profile->message_queues, twc_message_queue_free_map_callback, NULL); weechat_hashtable_free(profile->message_queues); }