1
0
Fork 0
mirror of https://gitlab.gnome.org/GNOME/calls.git synced 2024-11-17 16:05:36 +00:00

sip: initial call handling

* implement answering and hangup
 * (de)activate media pipeline
This commit is contained in:
Evangelos Ribeiro Tzaras 2021-02-19 17:34:57 +01:00
parent 967f30d688
commit e0482fc6e6
4 changed files with 106 additions and 27 deletions

View file

@ -22,6 +22,8 @@
*
*/
#define G_LOG_DOMAIN "CallsSipCall"
#include "calls-sip-call.h"
#include "calls-message-source.h"
@ -94,18 +96,34 @@ static void
answer (CallsCall *call)
{
CallsSipCall *self;
g_autofree gchar *local_sdp = NULL;
g_assert (CALLS_IS_CALL (call));
g_assert (CALLS_IS_SIP_CALL (call));
self = CALLS_SIP_CALL (call);
g_assert (self->nh);
if (self->state != CALLS_CALL_STATE_INCOMING) {
g_warning ("Call must be in 'incoming' state in order to answer");
return;
}
/* need to include SDP answer here */
/* XXX dynamically get free ports */
calls_sip_call_setup_local_media (self, 19042, 19043);
local_sdp = calls_sip_media_manager_static_capabilities (self->manager,
19042,
FALSE);
g_assert (local_sdp);
g_debug ("Setting local SDP to string:\n%s", local_sdp);
nua_respond (self->nh, 200, NULL,
SOATAG_USER_SDP_STR (local_sdp),
SOATAG_AF (SOA_AF_IP4_IP6),
TAG_END ());
change_state (self, CALLS_CALL_STATE_ACTIVE);
}
@ -120,6 +138,31 @@ hang_up (CallsCall *call)
self = CALLS_SIP_CALL (call);
switch (self->state) {
case CALLS_CALL_STATE_DIALING:
nua_cancel (self->nh, TAG_END ());
g_debug ("Hanging up on outgoing ringing call");
break;
case CALLS_CALL_STATE_ACTIVE:
nua_bye (self->nh, TAG_END ());
g_debug ("Hanging up ongoing call");
break;
case CALLS_CALL_STATE_INCOMING:
nua_respond (self->nh, 480, NULL, TAG_END ());
g_debug ("Hanging up incoming call");
break;
case CALLS_CALL_STATE_DISCONNECTED:
g_warning ("Tried hanging up already disconnected call");
return;
default:
g_warning ("Hanging up not possible in state %d", self->state);
}
change_state (self, CALLS_CALL_STATE_DISCONNECTED);
}
@ -301,14 +344,15 @@ calls_sip_call_setup_remote_media (CallsSipCall *self,
void
calls_sip_call_activate_media (CallsSipCall *self,
gboolean enabled)
gboolean enabled)
{
g_return_if_fail (CALLS_IS_SIP_CALL (self));
g_return_if_fail (CALLS_IS_SIP_MEDIA_PIPELINE (self->pipeline));
if (enabled) {
;
calls_sip_media_pipeline_start (self->pipeline);
} else {
;
calls_sip_media_pipeline_stop (self->pipeline);
}
}
@ -336,3 +380,15 @@ calls_sip_call_new (const gchar *number,
return call;
}
void
calls_sip_call_set_state (CallsSipCall *self,
CallsCallState state)
{
g_return_if_fail (CALLS_IS_SIP_CALL (self));
g_print ("Changed call state to %d\n", state);
self->state = state;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CALL_STATE]);
}

View file

@ -24,6 +24,8 @@
#pragma once
#include "calls-call.h"
#include <glib-object.h>
#include <sofia-sip/nua.h>
@ -45,5 +47,7 @@ void calls_sip_call_setup_local_media (CallsSipCall *self
guint port_rtcp);
void calls_sip_call_activate_media (CallsSipCall *self,
gboolean enabled);
void calls_sip_call_set_state (CallsSipCall *self,
CallsCallState state);
G_END_DECLS

View file

@ -269,8 +269,8 @@ sip_i_state (int status,
default:
return;
}
g_object_set (call, "state", state, NULL);
calls_sip_call_set_state (call, state);
}
@ -288,20 +288,22 @@ sip_callback (nua_event_t event,
CallsSipOrigin *origin = CALLS_SIP_ORIGIN (magic);
/* op currently unused */
CallsSipHandles *op = hmagic;
const char * from = NULL;
switch (event) {
case nua_i_invite:
/* This needs to be handled by CallsSipCall */
//g_debug ("incoming call INVITE: %03d %s", status, phrase);
//origin->oper->incoming_call_handle = nh;
///* We can only handle a single call */
//if (origin->call_state != SIP_CALL_READY) {
// const char * from = NULL;
tl_gets (tags, SIPTAG_FROM_STR_REF (from), TAG_END ());
// tl_gets (tags, SIPTAG_FROM_STR_REF (from), TAG_END ());
g_debug ("incoming call INVITE: %03d %s from %s", status, phrase, from);
/* reject if there already is a ongoing call */
if (op->call_handle) {
nua_respond (nh, 486, NULL, TAG_END ());
g_debug ("Cannot handle more than one call. Rejecting");
}
else
calls_sip_origin_create_inbound (origin, from, nh);
// g_debug ("Rejecting call from %s", from);
// nua_respond (nh, 486, NULL, TAG_END ());
//}
break;
case nua_r_invite:
@ -440,7 +442,6 @@ setup_sip_handles (CallsSipOrigin *self)
NUTAG_REGISTRAR (self->host),
TAG_END ());
oper->call_handle = NULL;
oper->incoming_call_handle = NULL;
return oper;
}
@ -564,6 +565,10 @@ remove_call (CallsSipOrigin *self,
"nua-handle", &nh,
NULL);
/* TODO support multiple simultaneous calls */
if (self->oper->call_handle == nh)
self->oper->call_handle = NULL;
g_hash_table_remove (self->call_handles, nh);
nua_handle_unref (nh);
@ -596,7 +601,6 @@ remove_calls (CallsSipOrigin *self,
g_hash_table_remove_all (self->call_handles);
g_clear_pointer (&self->oper->call_handle, nua_handle_unref);
g_clear_pointer (&self->oper->incoming_call_handle, nua_handle_unref);
}
@ -646,15 +650,26 @@ add_call (CallsSipOrigin *self,
SOATAG_AF (SOA_AF_IP4_IP6),
TAG_END ());
if (self->oper->call_handle)
nua_handle_unref (self->oper->call_handle);
self->oper->call_handle = handle;
g_hash_table_insert (self->call_handles, handle, sip_call);
if (!inbound)
nua_invite (self->oper->call_handle,
SIPTAG_TO_STR (address),
SOATAG_RTP_SORT (SOA_RTP_SORT_REMOTE),
SOATAG_RTP_SELECT (SOA_RTP_SELECT_ALL),
TAG_END ());
call = CALLS_CALL (sip_call);
g_signal_connect_swapped (call, "state-changed",
G_CALLBACK (on_call_state_changed_cb),
self);
self->calls = g_list_append (self->calls, sip_call);
g_hash_table_insert (self->call_handles, handle, sip_call);
g_signal_emit_by_name (CALLS_ORIGIN (self), "call-added", call);
}
@ -665,6 +680,7 @@ dial (CallsOrigin *origin,
const gchar *address)
{
CallsSipOrigin *self;
nua_handle_t *nh;
g_assert (CALLS_ORIGIN (origin));
g_assert (CALLS_IS_SIP_ORIGIN (origin));
@ -676,15 +692,14 @@ dial (CallsOrigin *origin,
self = CALLS_SIP_ORIGIN (origin);
if (self->oper->call_handle)
nua_handle_unref (self->oper->call_handle);
nh = nua_handle (self->nua, self->oper,
NUTAG_MEDIA_ENABLE (1),
SOATAG_ACTIVE_AUDIO (SOA_ACTIVE_SENDRECV),
TAG_END ());
self->oper->call_handle = nua_handle (self->nua, self->oper,
NUTAG_MEDIA_ENABLE (1),
SOATAG_ACTIVE_AUDIO (SOA_ACTIVE_SENDRECV),
TAG_END ());
g_debug ("Calling `%s'", address);
add_call (CALLS_SIP_ORIGIN (origin), address, FALSE, self->oper->call_handle);
add_call (CALLS_SIP_ORIGIN (origin), address, FALSE, nh);
}
@ -821,7 +836,6 @@ calls_sip_origin_dispose (GObject *object)
if (self->oper) {
g_clear_pointer (&self->oper->call_handle, nua_handle_unref);
g_clear_pointer (&self->oper->incoming_call_handle, nua_handle_unref);
g_clear_pointer (&self->oper->register_handle, nua_handle_unref);
}
@ -978,6 +992,12 @@ calls_sip_origin_create_inbound (CallsSipOrigin *self,
g_return_if_fail (address != NULL);
g_return_if_fail (CALLS_IS_SIP_ORIGIN (self));
/* TODO support multiple calls */
if (self->oper->call_handle)
nua_handle_unref (self->oper->call_handle);
self->oper->call_handle = handle;
add_call (self, address, TRUE, handle);
}

View file

@ -38,7 +38,6 @@ typedef struct
{
nua_handle_t *register_handle;
nua_handle_t *call_handle;
nua_handle_t *incoming_call_handle;
CallsSipContext *context;
} CallsSipHandles;