update toxcore, toxav fixes merged
Some checks are pending
ContinuousDelivery / linux-ubuntu (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousDelivery / windows (push) Waiting to run
ContinuousDelivery / windows-asan (push) Waiting to run
ContinuousDelivery / release (push) Blocked by required conditions
ContinuousIntegration / linux (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousIntegration / macos (push) Waiting to run
ContinuousIntegration / windows (push) Waiting to run
Some checks are pending
ContinuousDelivery / linux-ubuntu (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Waiting to run
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousDelivery / windows (push) Waiting to run
ContinuousDelivery / windows-asan (push) Waiting to run
ContinuousDelivery / release (push) Blocked by required conditions
ContinuousIntegration / linux (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Waiting to run
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Waiting to run
ContinuousIntegration / macos (push) Waiting to run
ContinuousIntegration / windows (push) Waiting to run
Merge commit 'cae0ab9c5c75eda665d21dc36cfeef48c1e04b53'
This commit is contained in:
462
external/toxcore/c-toxcore/toxav/msi.c
vendored
462
external/toxcore/c-toxcore/toxav/msi.c
vendored
@ -9,8 +9,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "toxav_hacks.h"
|
||||
|
||||
#include "../toxcore/ccompat.h"
|
||||
#include "../toxcore/logger.h"
|
||||
#include "../toxcore/net_crypto.h"
|
||||
#include "../toxcore/tox.h"
|
||||
#include "../toxcore/tox_private.h"
|
||||
#include "../toxcore/util.h"
|
||||
|
||||
#define MSI_MAXMSG_SIZE 256
|
||||
@ -55,20 +60,20 @@ typedef struct MSIMessage {
|
||||
} MSIMessage;
|
||||
|
||||
static void msg_init(MSIMessage *dest, MSIRequest request);
|
||||
static void kill_call(const Logger *log, MSICall *call);
|
||||
static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint16_t length);
|
||||
static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const uint8_t *value, uint8_t value_len,
|
||||
uint16_t *length);
|
||||
static int send_message(const Messenger *m, uint32_t friend_number, const MSIMessage *msg);
|
||||
static int send_error(const Messenger *m, uint32_t friend_number, MSIError error);
|
||||
static bool invoke_callback(MSICall *call, MSICallbackID cb);
|
||||
static int send_message(const Logger *log, Tox *tox, uint32_t friend_number, const MSIMessage *msg);
|
||||
static int send_error(const Logger *log, Tox *tox, uint32_t friend_number, MSIError error);
|
||||
static MSICall *get_call(MSISession *session, uint32_t friend_number);
|
||||
static MSICall *new_call(MSISession *session, uint32_t friend_number);
|
||||
static void kill_call(MSICall *call);
|
||||
static void on_peer_status(Messenger *m, uint32_t friend_number, bool is_online, void *user_data);
|
||||
static void handle_init(MSICall *call, const MSIMessage *msg);
|
||||
static void handle_push(MSICall *call, const MSIMessage *msg);
|
||||
static void handle_pop(MSICall *call, const MSIMessage *msg);
|
||||
static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *user_data);
|
||||
static bool invoke_callback(const Logger *log, MSICall *call, MSICallbackID cb);
|
||||
static void handle_init(const Logger *log, MSICall *call, const MSIMessage *msg);
|
||||
static void handle_push(const Logger *log, MSICall *call, const MSIMessage *msg);
|
||||
static void handle_pop(const Logger *log, MSICall *call, const MSIMessage *msg);
|
||||
static void handle_msi_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
|
||||
void *user_data);
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
@ -99,43 +104,43 @@ void msi_callback_capabilities(MSISession *session, msi_action_cb *callback)
|
||||
session->capabilities_callback = callback;
|
||||
}
|
||||
|
||||
MSISession *msi_new(Messenger *m)
|
||||
MSISession *msi_new(const Logger *log, Tox *tox)
|
||||
{
|
||||
if (m == nullptr) {
|
||||
if (tox == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MSISession *retu = (MSISession *)calloc(1, sizeof(MSISession));
|
||||
|
||||
if (retu == nullptr) {
|
||||
LOGGER_ERROR(m->log, "Allocation failed! Program might misbehave!");
|
||||
LOGGER_ERROR(log, "Allocation failed! Program might misbehave!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (create_recursive_mutex(retu->mutex) != 0) {
|
||||
LOGGER_ERROR(m->log, "Failed to init mutex! Program might misbehave");
|
||||
LOGGER_ERROR(log, "Failed to init mutex! Program might misbehave");
|
||||
free(retu);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
retu->messenger = m;
|
||||
retu->tox = tox;
|
||||
|
||||
m_callback_msi_packet(m, handle_msi_packet, retu);
|
||||
// register callback
|
||||
tox_callback_friend_lossless_packet_per_pktid(tox, handle_msi_packet, PACKET_ID_MSI);
|
||||
|
||||
/* This is called when remote terminates session */
|
||||
m_callback_connectionstatus_internal_av(m, on_peer_status, retu);
|
||||
|
||||
LOGGER_DEBUG(m->log, "New msi session: %p ", (void *)retu);
|
||||
LOGGER_DEBUG(log, "New msi session: %p ", (void *)retu);
|
||||
return retu;
|
||||
}
|
||||
int msi_kill(MSISession *session, const Logger *log)
|
||||
|
||||
int msi_kill(const Logger *log, Tox *tox, MSISession *session)
|
||||
{
|
||||
if (session == nullptr) {
|
||||
LOGGER_ERROR(log, "Tried to terminate non-existing session");
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_callback_msi_packet(session->messenger, nullptr, nullptr);
|
||||
// UN-register callback
|
||||
tox_callback_friend_lossless_packet_per_pktid(tox, nullptr, PACKET_ID_MSI);
|
||||
|
||||
if (pthread_mutex_trylock(session->mutex) != 0) {
|
||||
LOGGER_ERROR(log, "Failed to acquire lock on msi mutex");
|
||||
@ -149,10 +154,10 @@ int msi_kill(MSISession *session, const Logger *log)
|
||||
MSICall *it = get_call(session, session->calls_head);
|
||||
|
||||
while (it != nullptr) {
|
||||
send_message(session->messenger, it->friend_number, &msg);
|
||||
send_message(log, session->tox, it->friend_number, &msg);
|
||||
MSICall *temp_it = it;
|
||||
it = it->next;
|
||||
kill_call(temp_it); /* This will eventually free session->calls */
|
||||
kill_call(log, temp_it); /* This will eventually free session->calls */
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,21 +168,57 @@ int msi_kill(MSISession *session, const Logger *log)
|
||||
free(session);
|
||||
return 0;
|
||||
}
|
||||
int msi_invite(MSISession *session, MSICall **call, uint32_t friend_number, uint8_t capabilities)
|
||||
|
||||
/*
|
||||
* return true if friend is offline and the call was canceled.
|
||||
*/
|
||||
bool check_peer_offline_status(const Logger *log, const Tox *tox, MSISession *session, uint32_t friend_number)
|
||||
{
|
||||
if (tox == nullptr || session == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Tox_Err_Friend_Query f_con_query_error;
|
||||
const Tox_Connection f_con_status = tox_friend_get_connection_status(tox, friend_number, &f_con_query_error);
|
||||
|
||||
if (f_con_status == TOX_CONNECTION_NONE) {
|
||||
/* Friend is now offline */
|
||||
LOGGER_DEBUG(log, "Friend %d is now offline", friend_number);
|
||||
|
||||
pthread_mutex_lock(session->mutex);
|
||||
MSICall *call = get_call(session, friend_number);
|
||||
|
||||
if (call == nullptr) {
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
invoke_callback(log, call, MSI_ON_PEERTIMEOUT); /* Failure is ignored */
|
||||
kill_call(log, call);
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int msi_invite(const Logger *log, MSISession *session, MSICall **call, uint32_t friend_number, uint8_t capabilities)
|
||||
{
|
||||
LOGGER_DEBUG(log, "msi_invite:session:%p", (void *)session);
|
||||
|
||||
if (session == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGGER_DEBUG(session->messenger->log, "Session: %p Inviting friend: %u", (void *)session, friend_number);
|
||||
LOGGER_DEBUG(log, "Session: %p Inviting friend: %u", (void *)session, friend_number);
|
||||
|
||||
if (pthread_mutex_trylock(session->mutex) != 0) {
|
||||
LOGGER_ERROR(session->messenger->log, "Failed to acquire lock on msi mutex");
|
||||
LOGGER_ERROR(log, "Failed to acquire lock on msi mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_call(session, friend_number) != nullptr) {
|
||||
LOGGER_ERROR(session->messenger->log, "Already in a call");
|
||||
LOGGER_ERROR(log, "Already in a call");
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return -1;
|
||||
}
|
||||
@ -197,17 +238,18 @@ int msi_invite(MSISession *session, MSICall **call, uint32_t friend_number, uint
|
||||
msg.capabilities.exists = true;
|
||||
msg.capabilities.value = capabilities;
|
||||
|
||||
send_message(temp->session->messenger, temp->friend_number, &msg);
|
||||
send_message(log, temp->session->tox, temp->friend_number, &msg);
|
||||
|
||||
temp->state = MSI_CALL_REQUESTING;
|
||||
|
||||
*call = temp;
|
||||
|
||||
LOGGER_DEBUG(session->messenger->log, "Invite sent");
|
||||
LOGGER_DEBUG(log, "Invite sent");
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return 0;
|
||||
}
|
||||
int msi_hangup(MSICall *call)
|
||||
|
||||
int msi_hangup(const Logger *log, MSICall *call)
|
||||
{
|
||||
if (call == nullptr || call->session == nullptr) {
|
||||
return -1;
|
||||
@ -215,16 +257,16 @@ int msi_hangup(MSICall *call)
|
||||
|
||||
MSISession *session = call->session;
|
||||
|
||||
LOGGER_DEBUG(session->messenger->log, "Session: %p Hanging up call with friend: %u", (void *)call->session,
|
||||
LOGGER_DEBUG(log, "Session: %p Hanging up call with friend: %u", (void *)call->session,
|
||||
call->friend_number);
|
||||
|
||||
if (pthread_mutex_trylock(session->mutex) != 0) {
|
||||
LOGGER_ERROR(session->messenger->log, "Failed to acquire lock on msi mutex");
|
||||
LOGGER_ERROR(log, "Failed to acquire lock on msi mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (call->state == MSI_CALL_INACTIVE) {
|
||||
LOGGER_ERROR(session->messenger->log, "Call is in invalid state!");
|
||||
LOGGER_ERROR(log, "Call is in invalid state!");
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return -1;
|
||||
}
|
||||
@ -232,13 +274,14 @@ int msi_hangup(MSICall *call)
|
||||
MSIMessage msg;
|
||||
msg_init(&msg, REQU_POP);
|
||||
|
||||
send_message(session->messenger, call->friend_number, &msg);
|
||||
send_message(log, session->tox, call->friend_number, &msg);
|
||||
|
||||
kill_call(call);
|
||||
kill_call(log, call);
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return 0;
|
||||
}
|
||||
int msi_answer(MSICall *call, uint8_t capabilities)
|
||||
|
||||
int msi_answer(const Logger *log, MSICall *call, uint8_t capabilities)
|
||||
{
|
||||
if (call == nullptr || call->session == nullptr) {
|
||||
return -1;
|
||||
@ -246,18 +289,18 @@ int msi_answer(MSICall *call, uint8_t capabilities)
|
||||
|
||||
MSISession *session = call->session;
|
||||
|
||||
LOGGER_DEBUG(session->messenger->log, "Session: %p Answering call from: %u", (void *)call->session,
|
||||
LOGGER_DEBUG(log, "Session: %p Answering call from: %u", (void *)call->session,
|
||||
call->friend_number);
|
||||
|
||||
if (pthread_mutex_trylock(session->mutex) != 0) {
|
||||
LOGGER_ERROR(session->messenger->log, "Failed to acquire lock on msi mutex");
|
||||
LOGGER_ERROR(log, "Failed to acquire lock on msi mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (call->state != MSI_CALL_REQUESTED) {
|
||||
/* Though sending in invalid state will not cause anything weird
|
||||
* Its better to not do it like a maniac */
|
||||
LOGGER_ERROR(session->messenger->log, "Call is in invalid state!");
|
||||
LOGGER_ERROR(log, "Call is in invalid state!");
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return -1;
|
||||
}
|
||||
@ -270,14 +313,15 @@ int msi_answer(MSICall *call, uint8_t capabilities)
|
||||
msg.capabilities.exists = true;
|
||||
msg.capabilities.value = capabilities;
|
||||
|
||||
send_message(session->messenger, call->friend_number, &msg);
|
||||
send_message(log, session->tox, call->friend_number, &msg);
|
||||
|
||||
call->state = MSI_CALL_ACTIVE;
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int msi_change_capabilities(MSICall *call, uint8_t capabilities)
|
||||
|
||||
int msi_change_capabilities(const Logger *log, MSICall *call, uint8_t capabilities)
|
||||
{
|
||||
if (call == nullptr || call->session == nullptr) {
|
||||
return -1;
|
||||
@ -285,16 +329,16 @@ int msi_change_capabilities(MSICall *call, uint8_t capabilities)
|
||||
|
||||
MSISession *session = call->session;
|
||||
|
||||
LOGGER_DEBUG(session->messenger->log, "Session: %p Trying to change capabilities to friend %u", (void *)call->session,
|
||||
LOGGER_DEBUG(log, "Session: %p Trying to change capabilities to friend %u", (void *)call->session,
|
||||
call->friend_number);
|
||||
|
||||
if (pthread_mutex_trylock(session->mutex) != 0) {
|
||||
LOGGER_ERROR(session->messenger->log, "Failed to acquire lock on msi mutex");
|
||||
LOGGER_ERROR(log, "Failed to acquire lock on msi mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (call->state != MSI_CALL_ACTIVE) {
|
||||
LOGGER_ERROR(session->messenger->log, "Call is in invalid state!");
|
||||
LOGGER_ERROR(log, "Call is in invalid state!");
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return -1;
|
||||
}
|
||||
@ -307,7 +351,7 @@ int msi_change_capabilities(MSICall *call, uint8_t capabilities)
|
||||
msg.capabilities.exists = true;
|
||||
msg.capabilities.value = capabilities;
|
||||
|
||||
send_message(call->session->messenger, call->friend_number, &msg);
|
||||
send_message(log, call->session->tox, call->friend_number, &msg);
|
||||
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return 0;
|
||||
@ -351,10 +395,51 @@ static bool check_enum_high(const Logger *log, const uint8_t *bytes, uint8_t enu
|
||||
return true;
|
||||
}
|
||||
|
||||
static const uint8_t *msg_parse_one(const Logger *log, MSIMessage *dest, const uint8_t *it, int *size_constraint)
|
||||
{
|
||||
switch (*it) {
|
||||
case ID_REQUEST: {
|
||||
if (!check_size(log, it, size_constraint, 1) ||
|
||||
!check_enum_high(log, it, REQU_POP)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dest->request.value = (MSIRequest)it[2];
|
||||
dest->request.exists = true;
|
||||
return it + 3;
|
||||
}
|
||||
|
||||
case ID_ERROR: {
|
||||
if (!check_size(log, it, size_constraint, 1) ||
|
||||
!check_enum_high(log, it, MSI_E_UNDISCLOSED)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dest->error.value = (MSIError)it[2];
|
||||
dest->error.exists = true;
|
||||
return it + 3;
|
||||
}
|
||||
|
||||
case ID_CAPABILITIES: {
|
||||
if (!check_size(log, it, size_constraint, 1)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dest->capabilities.value = it[2];
|
||||
dest->capabilities.exists = true;
|
||||
return it + 3;
|
||||
}
|
||||
|
||||
default: {
|
||||
LOGGER_ERROR(log, "Invalid id byte: %d", *it);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
/* Parse raw data received from socket into MSIMessage struct */
|
||||
|
||||
assert(dest != nullptr);
|
||||
|
||||
if (length == 0 || data[length - 1] != 0) { /* End byte must have value 0 */
|
||||
@ -368,46 +453,10 @@ static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data
|
||||
int size_constraint = length;
|
||||
|
||||
while (*it != 0) {/* until end byte is hit */
|
||||
switch (*it) {
|
||||
case ID_REQUEST: {
|
||||
if (!check_size(log, it, &size_constraint, 1) ||
|
||||
!check_enum_high(log, it, REQU_POP)) {
|
||||
return -1;
|
||||
}
|
||||
it = msg_parse_one(log, dest, it, &size_constraint);
|
||||
|
||||
dest->request.value = (MSIRequest)it[2];
|
||||
dest->request.exists = true;
|
||||
it += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_ERROR: {
|
||||
if (!check_size(log, it, &size_constraint, 1) ||
|
||||
!check_enum_high(log, it, MSI_E_UNDISCLOSED)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest->error.value = (MSIError)it[2];
|
||||
dest->error.exists = true;
|
||||
it += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_CAPABILITIES: {
|
||||
if (!check_size(log, it, &size_constraint, 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest->capabilities.value = it[2];
|
||||
dest->capabilities.exists = true;
|
||||
it += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
LOGGER_ERROR(log, "Invalid id byte");
|
||||
return -1;
|
||||
}
|
||||
if (it == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,6 +467,7 @@ static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const uint8_t *value, uint8_t value_len,
|
||||
uint16_t *length)
|
||||
{
|
||||
@ -437,11 +487,48 @@ static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const uint8_
|
||||
|
||||
return dest + value_len; /* Set to next position ready to be written */
|
||||
}
|
||||
static int send_message(const Messenger *m, uint32_t friend_number, const MSIMessage *msg)
|
||||
{
|
||||
/* Parse and send message */
|
||||
assert(m != nullptr);
|
||||
|
||||
/* Send an msi packet.
|
||||
*
|
||||
* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
static int m_msi_packet(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
// TODO(Zoff): make this better later! -------------------
|
||||
/* we need to prepend 1 byte (packet id) to data
|
||||
* do this without malloc, memcpy and free in the future
|
||||
*/
|
||||
const size_t length_new = (size_t)length + 1;
|
||||
uint8_t *data_new = (uint8_t *)malloc(length_new);
|
||||
|
||||
if (data_new == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
data_new[0] = PACKET_ID_MSI;
|
||||
|
||||
if (length != 0) {
|
||||
memcpy(data_new + 1, data, length);
|
||||
}
|
||||
|
||||
Tox_Err_Friend_Custom_Packet error;
|
||||
tox_friend_send_lossless_packet(tox, friendnumber, data_new, length_new, &error);
|
||||
|
||||
free(data_new);
|
||||
|
||||
if (error == TOX_ERR_FRIEND_CUSTOM_PACKET_OK) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_message(const Logger *log, Tox *tox, uint32_t friend_number, const MSIMessage *msg)
|
||||
{
|
||||
assert(tox != nullptr);
|
||||
|
||||
/* Parse and send message */
|
||||
uint8_t parsed[MSI_MAXMSG_SIZE];
|
||||
|
||||
uint8_t *it = parsed;
|
||||
@ -452,7 +539,7 @@ static int send_message(const Messenger *m, uint32_t friend_number, const MSIMes
|
||||
it = msg_parse_header_out(ID_REQUEST, it, &cast,
|
||||
sizeof(cast), &size);
|
||||
} else {
|
||||
LOGGER_DEBUG(m->log, "Must have request field");
|
||||
LOGGER_DEBUG(log, "Must have request field");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -468,26 +555,27 @@ static int send_message(const Messenger *m, uint32_t friend_number, const MSIMes
|
||||
}
|
||||
|
||||
if (it == parsed) {
|
||||
LOGGER_WARNING(m->log, "Parsing message failed; empty message");
|
||||
LOGGER_WARNING(log, "Parsing message failed; empty message");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*it = 0;
|
||||
++size;
|
||||
|
||||
if (m_msi_packet(m, friend_number, parsed, size)) {
|
||||
LOGGER_DEBUG(m->log, "Sent message");
|
||||
if (m_msi_packet(tox, friend_number, parsed, size) == 1) {
|
||||
LOGGER_DEBUG(log, "Sent message");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
static int send_error(const Messenger *m, uint32_t friend_number, MSIError error)
|
||||
{
|
||||
/* Send error message */
|
||||
assert(m != nullptr);
|
||||
|
||||
LOGGER_DEBUG(m->log, "Sending error: %d to friend: %d", error, friend_number);
|
||||
static int send_error(const Logger *log, Tox *tox, uint32_t friend_number, MSIError error)
|
||||
{
|
||||
assert(tox != nullptr);
|
||||
|
||||
/* Send error message */
|
||||
LOGGER_DEBUG(log, "Sending error: %d to friend: %d", error, friend_number);
|
||||
|
||||
MSIMessage msg;
|
||||
msg_init(&msg, REQU_POP);
|
||||
@ -495,13 +583,14 @@ static int send_error(const Messenger *m, uint32_t friend_number, MSIError error
|
||||
msg.error.exists = true;
|
||||
msg.error.value = error;
|
||||
|
||||
send_message(m, friend_number, &msg);
|
||||
send_message(log, tox, friend_number, &msg);
|
||||
return 0;
|
||||
}
|
||||
static int invoke_callback_inner(MSICall *call, MSICallbackID id)
|
||||
|
||||
static int invoke_callback_inner(const Logger *log, MSICall *call, MSICallbackID id)
|
||||
{
|
||||
MSISession *session = call->session;
|
||||
LOGGER_DEBUG(session->messenger->log, "invoking callback function: %d", id);
|
||||
LOGGER_DEBUG(log, "invoking callback function: %d", id);
|
||||
|
||||
switch (id) {
|
||||
case MSI_ON_INVITE:
|
||||
@ -523,15 +612,16 @@ static int invoke_callback_inner(MSICall *call, MSICallbackID id)
|
||||
return session->capabilities_callback(session->av, call);
|
||||
}
|
||||
|
||||
LOGGER_FATAL(session->messenger->log, "invalid callback id: %d", id);
|
||||
LOGGER_FATAL(log, "invalid callback id: %d", id);
|
||||
return -1;
|
||||
}
|
||||
static bool invoke_callback(MSICall *call, MSICallbackID cb)
|
||||
|
||||
static bool invoke_callback(const Logger *log, MSICall *call, MSICallbackID cb)
|
||||
{
|
||||
assert(call != nullptr);
|
||||
|
||||
if (invoke_callback_inner(call, cb) != 0) {
|
||||
LOGGER_WARNING(call->session->messenger->log,
|
||||
if (invoke_callback_inner(log, call, cb) != 0) {
|
||||
LOGGER_WARNING(log,
|
||||
"Callback state handling failed, sending error");
|
||||
|
||||
/* If no callback present or error happened while handling,
|
||||
@ -546,6 +636,7 @@ static bool invoke_callback(MSICall *call, MSICallbackID cb)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static MSICall *get_call(MSISession *session, uint32_t friend_number)
|
||||
{
|
||||
assert(session != nullptr);
|
||||
@ -556,6 +647,7 @@ static MSICall *get_call(MSISession *session, uint32_t friend_number)
|
||||
|
||||
return session->calls[friend_number];
|
||||
}
|
||||
|
||||
static MSICall *new_call(MSISession *session, uint32_t friend_number)
|
||||
{
|
||||
assert(session != nullptr);
|
||||
@ -607,7 +699,8 @@ static MSICall *new_call(MSISession *session, uint32_t friend_number)
|
||||
session->calls[friend_number] = rc;
|
||||
return rc;
|
||||
}
|
||||
static void kill_call(MSICall *call)
|
||||
|
||||
static void kill_call(const Logger *log, MSICall *call)
|
||||
{
|
||||
/* Assume that session mutex is locked */
|
||||
if (call == nullptr) {
|
||||
@ -616,7 +709,7 @@ static void kill_call(MSICall *call)
|
||||
|
||||
MSISession *session = call->session;
|
||||
|
||||
LOGGER_DEBUG(session->messenger->log, "Killing call: %p", (void *)call);
|
||||
LOGGER_DEBUG(log, "Killing call: %p", (void *)call);
|
||||
|
||||
MSICall *prev = call->prev;
|
||||
MSICall *next = call->next;
|
||||
@ -648,37 +741,12 @@ CLEAR_CONTAINER:
|
||||
free(call);
|
||||
session->calls = nullptr;
|
||||
}
|
||||
static void on_peer_status(Messenger *m, uint32_t friend_number, bool is_online, void *user_data)
|
||||
|
||||
|
||||
static bool try_handle_init(const Logger *log, MSICall *call, const MSIMessage *msg)
|
||||
{
|
||||
MSISession *session = (MSISession *)user_data;
|
||||
|
||||
if (is_online) {
|
||||
// Friend is online.
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER_DEBUG(m->log, "Friend %d is now offline", friend_number);
|
||||
|
||||
pthread_mutex_lock(session->mutex);
|
||||
MSICall *call = get_call(session, friend_number);
|
||||
|
||||
if (call == nullptr) {
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
invoke_callback(call, MSI_ON_PEERTIMEOUT); /* Failure is ignored */
|
||||
kill_call(call);
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
}
|
||||
static bool try_handle_init(MSICall *call, const MSIMessage *msg)
|
||||
{
|
||||
assert(call != nullptr);
|
||||
LOGGER_DEBUG(call->session->messenger->log,
|
||||
"Session: %p Handling 'init' friend: %d", (void *)call->session, call->friend_number);
|
||||
|
||||
if (!msg->capabilities.exists) {
|
||||
LOGGER_WARNING(call->session->messenger->log, "Session: %p Invalid capabilities on 'init'", (void *)call->session);
|
||||
LOGGER_WARNING(log, "Session: %p Invalid capabilities on 'init'", (void *)call->session);
|
||||
call->error = MSI_E_INVALID_MESSAGE;
|
||||
return false;
|
||||
}
|
||||
@ -689,7 +757,7 @@ static bool try_handle_init(MSICall *call, const MSIMessage *msg)
|
||||
call->peer_capabilities = msg->capabilities.value;
|
||||
call->state = MSI_CALL_REQUESTED;
|
||||
|
||||
if (!invoke_callback(call, MSI_ON_INVITE)) {
|
||||
if (!invoke_callback(log, call, MSI_ON_INVITE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -704,7 +772,7 @@ static bool try_handle_init(MSICall *call, const MSIMessage *msg)
|
||||
* we can automatically answer the re-call.
|
||||
*/
|
||||
|
||||
LOGGER_INFO(call->session->messenger->log, "Friend is recalling us");
|
||||
LOGGER_INFO(log, "Friend is recalling us");
|
||||
|
||||
MSIMessage out_msg;
|
||||
msg_init(&out_msg, REQU_PUSH);
|
||||
@ -712,7 +780,7 @@ static bool try_handle_init(MSICall *call, const MSIMessage *msg)
|
||||
out_msg.capabilities.exists = true;
|
||||
out_msg.capabilities.value = call->self_capabilities;
|
||||
|
||||
send_message(call->session->messenger, call->friend_number, &out_msg);
|
||||
send_message(log, call->session->tox, call->friend_number, &out_msg);
|
||||
|
||||
/* If peer changed capabilities during re-call they will
|
||||
* be handled accordingly during the next step
|
||||
@ -722,7 +790,7 @@ static bool try_handle_init(MSICall *call, const MSIMessage *msg)
|
||||
|
||||
case MSI_CALL_REQUESTED: // fall-through
|
||||
case MSI_CALL_REQUESTING: {
|
||||
LOGGER_WARNING(call->session->messenger->log, "Session: %p Invalid state on 'init'", (void *)call->session);
|
||||
LOGGER_WARNING(log, "Session: %p Invalid state on 'init'", (void *)call->session);
|
||||
call->error = MSI_E_INVALID_STATE;
|
||||
return false;
|
||||
}
|
||||
@ -730,26 +798,28 @@ static bool try_handle_init(MSICall *call, const MSIMessage *msg)
|
||||
|
||||
return true;
|
||||
}
|
||||
static void handle_init(MSICall *call, const MSIMessage *msg)
|
||||
|
||||
static void handle_init(const Logger *log, MSICall *call, const MSIMessage *msg)
|
||||
{
|
||||
assert(call != nullptr);
|
||||
LOGGER_DEBUG(call->session->messenger->log,
|
||||
LOGGER_DEBUG(log,
|
||||
"Session: %p Handling 'init' friend: %d", (void *)call->session, call->friend_number);
|
||||
|
||||
if (!try_handle_init(call, msg)) {
|
||||
send_error(call->session->messenger, call->friend_number, call->error);
|
||||
kill_call(call);
|
||||
if (!try_handle_init(log, call, msg)) {
|
||||
send_error(log, call->session->tox, call->friend_number, call->error);
|
||||
kill_call(log, call);
|
||||
}
|
||||
}
|
||||
static void handle_push(MSICall *call, const MSIMessage *msg)
|
||||
|
||||
static void handle_push(const Logger *log, MSICall *call, const MSIMessage *msg)
|
||||
{
|
||||
assert(call != nullptr);
|
||||
|
||||
LOGGER_DEBUG(call->session->messenger->log, "Session: %p Handling 'push' friend: %d", (void *)call->session,
|
||||
LOGGER_DEBUG(log, "Session: %p Handling 'push' friend: %d", (void *)call->session,
|
||||
call->friend_number);
|
||||
|
||||
if (!msg->capabilities.exists) {
|
||||
LOGGER_WARNING(call->session->messenger->log, "Session: %p Invalid capabilities on 'push'", (void *)call->session);
|
||||
LOGGER_WARNING(log, "Session: %p Invalid capabilities on 'push'", (void *)call->session);
|
||||
call->error = MSI_E_INVALID_MESSAGE;
|
||||
goto FAILURE;
|
||||
}
|
||||
@ -757,12 +827,11 @@ static void handle_push(MSICall *call, const MSIMessage *msg)
|
||||
switch (call->state) {
|
||||
case MSI_CALL_ACTIVE: {
|
||||
if (call->peer_capabilities != msg->capabilities.value) {
|
||||
/* Only act if capabilities changed */
|
||||
LOGGER_INFO(call->session->messenger->log, "Friend is changing capabilities to: %u", msg->capabilities.value);
|
||||
LOGGER_INFO(log, "Friend is changing capabilities to: %u", msg->capabilities.value);
|
||||
|
||||
call->peer_capabilities = msg->capabilities.value;
|
||||
|
||||
if (!invoke_callback(call, MSI_ON_CAPABILITIES)) {
|
||||
if (!invoke_callback(log, call, MSI_ON_CAPABILITIES)) {
|
||||
goto FAILURE;
|
||||
}
|
||||
}
|
||||
@ -771,13 +840,13 @@ static void handle_push(MSICall *call, const MSIMessage *msg)
|
||||
}
|
||||
|
||||
case MSI_CALL_REQUESTING: {
|
||||
LOGGER_INFO(call->session->messenger->log, "Friend answered our call");
|
||||
LOGGER_INFO(log, "Friend answered our call");
|
||||
|
||||
/* Call started */
|
||||
call->peer_capabilities = msg->capabilities.value;
|
||||
call->state = MSI_CALL_ACTIVE;
|
||||
|
||||
if (!invoke_callback(call, MSI_ON_START)) {
|
||||
if (!invoke_callback(log, call, MSI_ON_START)) {
|
||||
goto FAILURE;
|
||||
}
|
||||
|
||||
@ -786,8 +855,7 @@ static void handle_push(MSICall *call, const MSIMessage *msg)
|
||||
|
||||
case MSI_CALL_INACTIVE: // fall-through
|
||||
case MSI_CALL_REQUESTED: {
|
||||
/* Pushes during initialization state are ignored */
|
||||
LOGGER_WARNING(call->session->messenger->log, "Ignoring invalid push");
|
||||
LOGGER_WARNING(log, "Ignoring invalid push");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -795,76 +863,102 @@ static void handle_push(MSICall *call, const MSIMessage *msg)
|
||||
return;
|
||||
|
||||
FAILURE:
|
||||
send_error(call->session->messenger, call->friend_number, call->error);
|
||||
kill_call(call);
|
||||
send_error(log, call->session->tox, call->friend_number, call->error);
|
||||
kill_call(log, call);
|
||||
}
|
||||
static void handle_pop(MSICall *call, const MSIMessage *msg)
|
||||
|
||||
static void handle_pop(const Logger *log, MSICall *call, const MSIMessage *msg)
|
||||
{
|
||||
assert(call != nullptr);
|
||||
|
||||
LOGGER_DEBUG(call->session->messenger->log, "Session: %p Handling 'pop', friend id: %d", (void *)call->session,
|
||||
LOGGER_DEBUG(log, "Session: %p Handling 'pop', friend id: %d", (void *)call->session,
|
||||
call->friend_number);
|
||||
|
||||
/* callback errors are ignored */
|
||||
|
||||
if (msg->error.exists) {
|
||||
LOGGER_WARNING(call->session->messenger->log, "Friend detected an error: %d", msg->error.value);
|
||||
LOGGER_WARNING(log, "Friend detected an error: %d", msg->error.value);
|
||||
call->error = msg->error.value;
|
||||
invoke_callback(call, MSI_ON_ERROR);
|
||||
invoke_callback(log, call, MSI_ON_ERROR);
|
||||
} else {
|
||||
switch (call->state) {
|
||||
case MSI_CALL_INACTIVE: {
|
||||
LOGGER_FATAL(call->session->messenger->log, "Handling what should be impossible case");
|
||||
LOGGER_FATAL(log, "Handling what should be impossible case");
|
||||
break;
|
||||
}
|
||||
|
||||
case MSI_CALL_ACTIVE: {
|
||||
/* Hangup */
|
||||
LOGGER_INFO(call->session->messenger->log, "Friend hung up on us");
|
||||
invoke_callback(call, MSI_ON_END);
|
||||
LOGGER_INFO(log, "Friend hung up on us");
|
||||
invoke_callback(log, call, MSI_ON_END);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSI_CALL_REQUESTING: {
|
||||
/* Reject */
|
||||
LOGGER_INFO(call->session->messenger->log, "Friend rejected our call");
|
||||
invoke_callback(call, MSI_ON_END);
|
||||
LOGGER_INFO(log, "Friend rejected our call");
|
||||
invoke_callback(log, call, MSI_ON_END);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSI_CALL_REQUESTED: {
|
||||
/* Cancel */
|
||||
LOGGER_INFO(call->session->messenger->log, "Friend canceled call invite");
|
||||
invoke_callback(call, MSI_ON_END);
|
||||
LOGGER_INFO(log, "Friend canceled call invite");
|
||||
invoke_callback(log, call, MSI_ON_END);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kill_call(call);
|
||||
kill_call(log, call);
|
||||
}
|
||||
static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *user_data)
|
||||
|
||||
static void handle_msi_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
|
||||
void *user_data)
|
||||
{
|
||||
MSISession *session = (MSISession *)user_data;
|
||||
const ToxAV *toxav = (ToxAV *)tox_get_av_object(tox);
|
||||
|
||||
LOGGER_DEBUG(m->log, "Got msi message");
|
||||
|
||||
MSIMessage msg;
|
||||
|
||||
if (msg_parse_in(m->log, &msg, data, length) == -1) {
|
||||
LOGGER_WARNING(m->log, "Error parsing message");
|
||||
send_error(m, friend_number, MSI_E_INVALID_MESSAGE);
|
||||
if (toxav == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER_DEBUG(m->log, "Successfully parsed message");
|
||||
const Logger *log = toxav_get_logger(toxav);
|
||||
|
||||
if (length < 2) {
|
||||
LOGGER_ERROR(log, "MSI packet is less than 2 bytes in size");
|
||||
// we need more than the ID byte for MSI messages
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16_t payload_length = (uint16_t)(length - 1);
|
||||
|
||||
// Zoff: do not show the first byte, its always "PACKET_ID_MSI"
|
||||
const uint8_t *data_strip_id_byte = data + 1;
|
||||
|
||||
LOGGER_DEBUG(log, "Got msi message");
|
||||
|
||||
MSISession *session = tox_av_msi_get(toxav);
|
||||
|
||||
if (session == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
MSIMessage msg;
|
||||
|
||||
if (msg_parse_in(log, &msg, data_strip_id_byte, payload_length) == -1) {
|
||||
LOGGER_WARNING(log, "Error parsing message");
|
||||
send_error(log, tox, friend_number, MSI_E_INVALID_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER_DEBUG(log, "Successfully parsed message");
|
||||
|
||||
pthread_mutex_lock(session->mutex);
|
||||
MSICall *call = get_call(session, friend_number);
|
||||
|
||||
if (call == nullptr) {
|
||||
if (msg.request.value != REQU_INIT) {
|
||||
send_error(m, friend_number, MSI_E_STRAY_MESSAGE);
|
||||
send_error(log, tox, friend_number, MSI_E_STRAY_MESSAGE);
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return;
|
||||
}
|
||||
@ -872,7 +966,7 @@ static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_
|
||||
call = new_call(session, friend_number);
|
||||
|
||||
if (call == nullptr) {
|
||||
send_error(m, friend_number, MSI_E_SYSTEM);
|
||||
send_error(log, tox, friend_number, MSI_E_SYSTEM);
|
||||
pthread_mutex_unlock(session->mutex);
|
||||
return;
|
||||
}
|
||||
@ -880,17 +974,17 @@ static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_
|
||||
|
||||
switch (msg.request.value) {
|
||||
case REQU_INIT: {
|
||||
handle_init(call, &msg);
|
||||
handle_init(log, call, &msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case REQU_PUSH: {
|
||||
handle_push(call, &msg);
|
||||
handle_push(log, call, &msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case REQU_POP: {
|
||||
handle_pop(call, &msg); /* always kills the call */
|
||||
handle_pop(log, call, &msg); /* always kills the call */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user