Msi should be done; toxav.c need a cleanup and adjustments

This commit is contained in:
mannol 2015-02-18 23:23:46 +01:00
parent 483a6ffa32
commit 6e259d5fcb
3 changed files with 464 additions and 498 deletions

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,12 @@
* Error codes.
*/
typedef enum {
msi_ErrorNone,
msi_InvalidMessage,
msi_InvalidParam,
msi_InvalidState,
msi_StrayMessage,
msi_SystemError,
msi_ErrUndisclosed,
} MSIError;
@ -69,7 +75,7 @@ typedef enum {
msi_OnStart, /* Call (RTP transmission) started */
msi_OnReject, /* The side that was invited rejected the call */
msi_OnEnd, /* Call that was active ended */
msi_OnError, /* Call that was active ended */
msi_OnError, /* On protocol error */
msi_OnPeerTimeout, /* Peer timed out; stop the call */
msi_OnCapabilities, /* Peer requested capabilities change */
} MSICallbackID;
@ -90,6 +96,10 @@ typedef struct MSICall_s {
uint32_t friend_id; /* Index of this call in MSISession */
MSIError error; /* Last error */
void* av_call; /* Pointer to av call handler */
struct MSICall_s* next;
struct MSICall_s* prev;
} MSICall;
@ -109,8 +119,8 @@ typedef struct MSISession_s {
uint32_t calls_tail;
uint32_t calls_head;
void *agent_handler;
Messenger *messenger_handle;
void *av;
Messenger *messenger;
pthread_mutex_t mutex[1];
MSICallbackType callbacks[8];
@ -119,7 +129,7 @@ typedef struct MSISession_s {
/**
* Start the control session.
*/
MSISession *msi_new ( Messenger *messenger, int32_t max_calls );
MSISession *msi_new ( Messenger *messenger );
/**
* Terminate control session. NOTE: all calls will be freed

View File

@ -49,8 +49,8 @@ typedef struct iToxAVCall
RTPSession *rtps[2]; /** Audio is first and video is second */
CSSession *cs;
bool active;
int32_t friend_number;
int32_t call_idx; /* FIXME msi compat, remove */
int32_t friend_id;
MSICall* msi_call;
struct iToxAVCall *prev;
struct iToxAVCall *next;
@ -80,21 +80,20 @@ struct toxAV
};
void i_toxav_msi_callback_invite(void* toxav_inst, int32_t call_idx, void *data);
void i_toxav_msi_callback_ringing(void* toxav_inst, int32_t call_idx, void *data);
void i_toxav_msi_callback_start(void* toxav_inst, int32_t call_idx, void *data);
void i_toxav_msi_callback_reject(void* toxav_inst, int32_t call_idx, void *data);
void i_toxav_msi_callback_end(void* toxav_inst, int32_t call_idx, void *data);
void i_toxav_msi_callback_request_to(void* toxav_inst, int32_t call_idx, void *data); /* TODO remove */
void i_toxav_msi_callback_peer_to(void* toxav_inst, int32_t call_idx, void *data);
void i_toxav_msi_callback_state_change(void* toxav_inst, int32_t call_idx, void *data);
void i_callback_invite(void* toxav_inst, MSICall* call);
void i_callback_ringing(void* toxav_inst, MSICall* call);
void i_callback_start(void* toxav_inst, MSICall* call);
void i_callback_end(void* toxav_inst, MSICall* call);
void i_callback_error(void* toxav_inst, MSICall* call);
void i_callback_capabilites(void* toxav_inst, MSICall* call);
TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities);
IToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number);
IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number);
void i_toxav_remove_call(ToxAV* av, uint32_t friend_number);
IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error);
bool i_toxav_audio_bitrate_invalid(uint32_t bitrate);
bool i_toxav_video_bitrate_invalid(uint32_t bitrate);
IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error);
bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call);
void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number);
@ -124,7 +123,7 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
}
av->m = (Messenger *)tox;
av->msi = msi_new(av->m, 100); /* TODO remove max calls */
av->msi = msi_new(av->m);
if (av->msi == NULL) {
rc = TOXAV_ERR_NEW_MALLOC;
@ -132,17 +131,16 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
}
av->interval = 200;
av->msi->agent_handler = av;
av->msi->av = av;
msi_register_callback(av->msi, i_toxav_msi_callback_invite, msi_OnInvite, NULL);
msi_register_callback(av->msi, i_toxav_msi_callback_ringing, msi_OnRinging, NULL);
msi_register_callback(av->msi, i_toxav_msi_callback_start, msi_OnStart, NULL);
msi_register_callback(av->msi, i_toxav_msi_callback_reject, msi_OnReject, NULL);
msi_register_callback(av->msi, i_toxav_msi_callback_end, msi_OnEnd, NULL);
msi_register_callback(av->msi, i_toxav_msi_callback_request_to, msi_OnRequestTimeout, NULL);
msi_register_callback(av->msi, i_toxav_msi_callback_peer_to, msi_OnPeerTimeout, NULL);
msi_register_callback(av->msi, i_toxav_msi_callback_state_change, msi_OnPeerCSChange, NULL);
msi_register_callback(av->msi, i_toxav_msi_callback_state_change, msi_OnSelfCSChange, NULL);
msi_register_callback(av->msi, i_callback_invite, msi_OnInvite);
msi_register_callback(av->msi, i_callback_ringing, msi_OnRinging);
msi_register_callback(av->msi, i_callback_start, msi_OnStart);
msi_register_callback(av->msi, i_callback_end, msi_OnReject);
msi_register_callback(av->msi, i_callback_end, msi_OnEnd);
msi_register_callback(av->msi, i_callback_error, msi_OnError);
msi_register_callback(av->msi, i_callback_error, msi_OnPeerTimeout);
msi_register_callback(av->msi, i_callback_capabilites, msi_OnCapabilities);
if (error)
@ -209,7 +207,7 @@ void toxav_iteration(ToxAV* av)
bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error)
{
IToxAVCall* call = i_toxav_init_call(av, friend_number, audio_bit_rate, video_bit_rate, error);
IToxAVCall* call = i_toxav_init_call(av, friend_number, error);
if (call == NULL) {
return false;
}
@ -528,111 +526,89 @@ void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb*
*
******************************************************************************/
/** TODO:
* - In msi call_idx can be the same as friend id
* - If crutial callback not present send error
* - Remove *data from msi
* - Remove CSettings from msi
* - If crutial callback not present send error.
* - Error handling by return values from callbacks and setting 'error'.
*/
void i_toxav_msi_callback_invite(void* toxav_inst, int32_t call_idx, void* data)
void i_callback_invite(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
uint32_t ab = toxav->msi->calls[call_idx]->csettings_peer[0].audio_bitrate;
uint32_t vb = toxav->msi->calls[call_idx]->csettings_peer[0].video_bitrate;
IToxAVCall* call = i_toxav_init_call(toxav, toxav->msi->calls[call_idx]->peers[0], ab, vb, NULL);
if (call == NULL) {
LOGGER_WARNING("No call, rejecting...");
msi_reject(toxav->msi, call_idx, NULL);
}
call->call_idx = call_idx;
if (toxav->ccb.first)
toxav->ccb.first(toxav, toxav->msi->calls[call_idx]->peers[0], true, true, toxav->ccb.second);
}
void i_toxav_msi_callback_ringing(void* toxav_inst, int32_t call_idx, void* data)
{
ToxAV* toxav = toxav_inst;
if (toxav->scb.first)
toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
TOXAV_CALL_STATE_RINGING, toxav->scb.second);
}
void i_toxav_msi_callback_start(void* toxav_inst, int32_t call_idx, void* data)
{
ToxAV* toxav = toxav_inst;
IToxAVCall* call = i_toxav_get_call(toxav, toxav->msi->calls[call_idx]->peers[0]);
if (call == NULL || !i_toxav_prepare_transmission(toxav, call)) {
/* TODO send error */
i_toxav_remove_call(toxav, toxav->msi->calls[call_idx]->peers[0]);
IToxAVCall* av_call = i_toxav_init_call(toxav, call->friend_id, NULL);
if (av_call == NULL) {
LOGGER_WARNING("Failed to start call, rejecting...");
msi_reject(toxav->msi, call);
return;
}
TOXAV_CALL_STATE state;
const MSICSettings* csets = &toxav->msi->calls[call_idx]->csettings_peer[0];
call->av_call = av_call;
av_call->msi_call = call;
if (csets->audio_bitrate && csets->video_bitrate)
state = TOXAV_CALL_STATE_SENDING_AV;
else if (csets->video_bitrate == 0)
state = TOXAV_CALL_STATE_SENDING_A;
else
state = TOXAV_CALL_STATE_SENDING_V;
if (toxav->scb.first) /* TODO this */
toxav->scb.first(toxav, call->friend_number, state, toxav->scb.second);
if (toxav->ccb.first)
toxav->ccb.first(toxav, call->friend_id, call->peer_capabilities & msi_CapSAudio,
call->peer_capabilities & msi_CapSVideo, toxav->ccb.second);
}
void i_toxav_msi_callback_reject(void* toxav_inst, int32_t call_idx, void* data)
{
ToxAV* toxav = toxav_inst;
i_toxav_kill_transmission(toxav, toxav->msi->calls[call_idx]->peers[0]);
i_toxav_remove_call(toxav, toxav->msi->calls[call_idx]->peers[0]);
if (toxav->scb.first)
toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
TOXAV_CALL_STATE_END, toxav->scb.second);
}
void i_toxav_msi_callback_end(void* toxav_inst, int32_t call_idx, void* data)
{
ToxAV* toxav = toxav_inst;
i_toxav_kill_transmission(toxav, toxav->msi->calls[call_idx]->peers[0]);
i_toxav_remove_call(toxav, toxav->msi->calls[call_idx]->peers[0]);
if (toxav->scb.first)
toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
TOXAV_CALL_STATE_END, toxav->scb.second);
}
void i_toxav_msi_callback_request_to(void* toxav_inst, int32_t call_idx, void* data)
{
/* TODO remove */
ToxAV* toxav = toxav_inst;
if (toxav->scb.first)
toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
TOXAV_CALL_STATE_ERROR, toxav->scb.second);
}
void i_toxav_msi_callback_peer_to(void* toxav_inst, int32_t call_idx, void* data)
void i_callback_ringing(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
if (toxav->scb.first)
toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
TOXAV_CALL_STATE_ERROR, toxav->scb.second);
toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_RINGING, toxav->scb.second);
}
void i_toxav_msi_callback_state_change(void* toxav_inst, int32_t call_idx, void* data)
void i_callback_start(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
IToxAVCall* call = i_toxav_get_call(toxav, call->friend_id);
if (call == NULL || !i_toxav_prepare_transmission(toxav, call)) {
/* TODO send error */
i_toxav_remove_call(toxav, call->friend_id);
return;
}
TOXAV_CALL_STATE state = capabilities_to_state(call->msi_call->peer_capabilities);
if (toxav->scb.first)
toxav->scb.first(toxav, call->friend_id, state, toxav->scb.second);
}
void i_callback_end(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
i_toxav_kill_transmission(toxav, call->friend_id);
i_toxav_remove_call(toxav, call->friend_id);
if (toxav->scb.first)
toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second);
}
void i_callback_error(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
if (toxav->scb.first)
toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second);
}
void i_callback_capabilites(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
/* TODO something something msi */
}
TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities)
{
if ((capabilities & msi_CapSAudio) && (capabilities & msi_CapSVideo))
return TOXAV_CALL_STATE_SENDING_AV;
else if (capabilities & msi_CapSAudio)
return TOXAV_CALL_STATE_SENDING_A;
else if (capabilities & msi_CapSVideo)
return TOXAV_CALL_STATE_SENDING_V;
else
return TOXAV_CALL_STATE_PAUSED;
}
IToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number)
{
if (av->calls == NULL || av->calls_tail < friend_number)
@ -648,7 +624,7 @@ IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
if (rc == NULL)
return NULL;
rc->friend_number = friend_number;
rc->friend_id = friend_number;
if (create_recursive_mutex(rc->mutex_control) != 0) {
free(rc);
@ -724,13 +700,13 @@ void i_toxav_remove_call(ToxAV* av, uint32_t friend_number)
if (prev)
prev->next = next;
else if (next)
av->calls_head = next->friend_number;
av->calls_head = next->friend_id;
else goto CLEAR;
if (next)
next->prev = prev;
else if (prev)
av->calls_tail = prev->friend_number;
av->calls_tail = prev->friend_id;
else goto CLEAR;
av->calls[friend_number] = NULL;
@ -742,21 +718,7 @@ CLEAR:
av->calls = NULL;
}
bool i_toxav_audio_bitrate_invalid(uint32_t bitrate)
{
/* Opus RFC 6716 section-2.1.1 dictates the following:
* Opus supports all bitrates from 6 kbit/s to 510 kbit/s.
*/
return bitrate < 6 || bitrate > 510;
}
bool i_toxav_video_bitrate_invalid(uint32_t bitrate)
{
/* TODO: If anyone knows the answer to this one please fill it up */
return false;
}
IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error)
IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error)
{
TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK;
IToxAVCall* call = NULL;
@ -776,25 +738,32 @@ IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, uint32_t audio_
goto END;
}
if ((audio_bit_rate && i_toxav_audio_bitrate_invalid(audio_bit_rate))
||(video_bit_rate && i_toxav_video_bitrate_invalid(video_bit_rate))
) {
rc = TOXAV_ERR_CALL_INVALID_BIT_RATE;
goto END;
}
call = i_toxav_add_call(av, friend_number);
if (call == NULL) {
rc = TOXAV_ERR_CALL_MALLOC;
}
END:
END:
if (error)
*error = rc;
return call;
}
bool i_toxav_audio_bitrate_invalid(uint32_t bitrate)
{
/* Opus RFC 6716 section-2.1.1 dictates the following:
* Opus supports all bitrates from 6 kbit/s to 510 kbit/s.
*/
return bitrate < 6 || bitrate > 510;
}
bool i_toxav_video_bitrate_invalid(uint32_t bitrate)
{
/* TODO: If anyone knows the answer to this one please fill it up */
return false;
}
bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call)
{
pthread_mutex_lock(call->mutex_control);
@ -838,7 +807,7 @@ bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call)
memcpy(&call->cs->acb, &av->acb, sizeof(av->acb));
memcpy(&call->cs->vcb, &av->vcb, sizeof(av->vcb));
call->cs->friend_number = call->friend_number;
call->cs->friend_number = call->friend_id;
call->cs->call_idx = call->call_idx;
@ -929,4 +898,4 @@ void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number)
pthread_mutex_destroy(call->mutex_do);
pthread_mutex_unlock(call->mutex_control);
}
}