/** Invite us to the focus callback */ static gboolean process_invite_conf_focus_response(struct sipe_core_private *sipe_private, struct sipmsg *msg, SIPE_UNUSED_PARAMETER struct transaction *trans) { struct sip_session *session = NULL; char *focus_uri = parse_from(sipmsg_find_header(msg, "To")); session = sipe_session_find_conference(sipe_private, focus_uri); if (!session) { SIPE_DEBUG_INFO("process_invite_conf_focus_response: unable to find conf session with focus=%s", focus_uri); g_free(focus_uri); return FALSE; } if (!session->focus_dialog) { SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: session's focus_dialog is NULL"); g_free(focus_uri); return FALSE; } sipe_dialog_parse(session->focus_dialog, msg, TRUE); if (msg->response >= 200) { /* send ACK to focus */ session->focus_dialog->cseq = 0; sip_transport_ack(sipe_private, session->focus_dialog); session->focus_dialog->outgoing_invite = NULL; session->focus_dialog->is_established = TRUE; } if (msg->response >= 400) { SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: INVITE response is not 200. Failed to join focus."); /* @TODO notify user of failure to join focus */ sipe_session_remove(sipe_private, session); g_free(focus_uri); return FALSE; } else if (msg->response == 200) { sipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen); const gchar *code = sipe_xml_attribute(xn_response, "code"); if (sipe_strequal(code, "success")) { /* subscribe to focus */ sipe_subscribe_conference(sipe_private, session, FALSE); } sipe_xml_free(xn_response); } g_free(focus_uri); return TRUE; }
static void call_accept_cb(struct sipe_core_private *sipe_private, struct conf_accept_ctx *ctx) { struct sip_session *session; session = sipe_session_find_conference(sipe_private, ctx->focus_uri); sipe_private->sessions_to_accept = g_slist_remove(sipe_private->sessions_to_accept, ctx); if (session) { sipe_core_media_connect_conference(SIPE_CORE_PUBLIC, session->chat_session); } conf_accept_ctx_free(ctx); }
void sipe_process_conference(struct sipe_core_private *sipe_private, struct sipmsg *msg) { sipe_xml *xn_conference_info; const sipe_xml *node; const sipe_xml *xn_subject; const gchar *focus_uri; struct sip_session *session; gboolean just_joined = FALSE; #ifdef HAVE_VV gboolean audio_was_added = FALSE; #endif if (msg->response != 0 && msg->response != 200) return; if (msg->bodylen == 0 || msg->body == NULL || !sipe_strequal(sipmsg_find_header(msg, "Event"), "conference")) return; xn_conference_info = sipe_xml_parse(msg->body, msg->bodylen); if (!xn_conference_info) return; focus_uri = sipe_xml_attribute(xn_conference_info, "entity"); session = sipe_session_find_conference(sipe_private, focus_uri); if (!session) { SIPE_DEBUG_INFO("sipe_process_conference: unable to find conf session with focus=%s", focus_uri); return; } if (!session->chat_session->backend) { gchar *self = sip_uri_self(sipe_private); /* create chat */ session->chat_session->backend = sipe_backend_chat_create(SIPE_CORE_PUBLIC, session->chat_session, session->chat_session->title, self); just_joined = TRUE; /* @TODO ask for full state (re-subscribe) if it was a partial one - * this is to obtain full list of conference participants. */ g_free(self); } /* subject */ if ((xn_subject = sipe_xml_child(xn_conference_info, "conference-description/subject"))) { g_free(session->subject); session->subject = sipe_xml_data(xn_subject); sipe_backend_chat_topic(session->chat_session->backend, session->subject); SIPE_DEBUG_INFO("sipe_process_conference: subject=%s", session->subject ? session->subject : ""); } /* IM MCU URI */ if (!session->im_mcu_uri) { for (node = sipe_xml_child(xn_conference_info, "conference-description/conf-uris/entry"); node; node = sipe_xml_twin(node)) { gchar *purpose = sipe_xml_data(sipe_xml_child(node, "purpose")); if (sipe_strequal("chat", purpose)) { g_free(purpose); session->im_mcu_uri = sipe_xml_data(sipe_xml_child(node, "uri")); SIPE_DEBUG_INFO("sipe_process_conference: im_mcu_uri=%s", session->im_mcu_uri); break; } g_free(purpose); } } /* users */ for (node = sipe_xml_child(xn_conference_info, "users/user"); node; node = sipe_xml_twin(node)) { const gchar *user_uri = sipe_xml_attribute(node, "entity"); const gchar *state = sipe_xml_attribute(node, "state"); gchar *role = sipe_xml_data(sipe_xml_child(node, "roles/entry")); gboolean is_operator = sipe_strequal(role, "presenter"); gboolean is_in_im_mcu = FALSE; gchar *self = sip_uri_self(sipe_private); if (sipe_strequal("deleted", state)) { if (sipe_backend_chat_find(session->chat_session->backend, user_uri)) { sipe_backend_chat_remove(session->chat_session->backend, user_uri); } } else { /* endpoints */ const sipe_xml *endpoint; for (endpoint = sipe_xml_child(node, "endpoint"); endpoint; endpoint = sipe_xml_twin(endpoint)) { const gchar *session_type; gchar *status = sipe_xml_data(sipe_xml_child(endpoint, "status")); gboolean connected = sipe_strequal("connected", status); g_free(status); if (!connected) continue; session_type = sipe_xml_attribute(endpoint, "session-type"); if (sipe_strequal("chat", session_type)) { is_in_im_mcu = TRUE; if (!sipe_backend_chat_find(session->chat_session->backend, user_uri)) { sipe_backend_chat_add(session->chat_session->backend, user_uri, !just_joined && g_ascii_strcasecmp(user_uri, self)); } if (is_operator) { sipe_backend_chat_operator(session->chat_session->backend, user_uri); } } else if (sipe_strequal("audio-video", session_type)) { #ifdef HAVE_VV if (!session->is_call) audio_was_added = TRUE; #endif } } if (!is_in_im_mcu) { if (sipe_backend_chat_find(session->chat_session->backend, user_uri)) { sipe_backend_chat_remove(session->chat_session->backend, user_uri); } } } g_free(role); g_free(self); } #ifdef HAVE_VV if (audio_was_added) { session->is_call = TRUE; ask_accept_voice_conference(sipe_private, focus_uri, NULL, (SipeUserAskCb) call_accept_cb, (SipeUserAskCb) call_decline_cb); } #endif /* entity-view, locked */ for (node = sipe_xml_child(xn_conference_info, "conference-view/entity-view"); node; node = sipe_xml_twin(node)) { const sipe_xml *xn_type = sipe_xml_child(node, "entity-state/media/entry/type"); gchar *tmp = NULL; if (xn_type && sipe_strequal("chat", (tmp = sipe_xml_data(xn_type)))) { const sipe_xml *xn_locked = sipe_xml_child(node, "entity-state/locked"); if (xn_locked) { gchar *locked = sipe_xml_data(xn_locked); gboolean prev_locked = session->locked; session->locked = sipe_strequal(locked, "true"); if (prev_locked && !session->locked) { sipe_user_present_info(sipe_private, session, _("This conference is no longer locked. Additional participants can now join.")); } if (!prev_locked && session->locked) { sipe_user_present_info(sipe_private, session, _("This conference is locked. Nobody else can join the conference while it is locked.")); } SIPE_DEBUG_INFO("sipe_process_conference: session->locked=%s", session->locked ? "TRUE" : "FALSE"); g_free(locked); } } g_free(tmp); } sipe_xml_free(xn_conference_info); if (session->im_mcu_uri) { struct sip_dialog *dialog = sipe_dialog_find(session, session->im_mcu_uri); if (!dialog) { dialog = sipe_dialog_add(session); dialog->callid = g_strdup(session->callid); dialog->with = g_strdup(session->im_mcu_uri); /* send INVITE to IM MCU */ sipe_im_invite(sipe_private, session, dialog->with, NULL, NULL, NULL, FALSE); } } sipe_process_pending_invite_queue(sipe_private, session); }
/** Invite us to the focus callback */ static gboolean process_invite_conf_focus_response(struct sipe_core_private *sipe_private, struct sipmsg *msg, SIPE_UNUSED_PARAMETER struct transaction *trans) { struct sip_session *session = NULL; char *focus_uri = parse_from(sipmsg_find_header(msg, "To")); session = sipe_session_find_conference(sipe_private, focus_uri); if (!session) { SIPE_DEBUG_INFO("process_invite_conf_focus_response: unable to find conf session with focus=%s", focus_uri); g_free(focus_uri); return FALSE; } if (!session->focus_dialog) { SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: session's focus_dialog is NULL"); g_free(focus_uri); return FALSE; } sipe_dialog_parse(session->focus_dialog, msg, TRUE); if (msg->response >= 200) { /* send ACK to focus */ session->focus_dialog->cseq = 0; sip_transport_ack(sipe_private, session->focus_dialog); session->focus_dialog->outgoing_invite = NULL; session->focus_dialog->is_established = TRUE; } if (msg->response >= 400) { gchar *reason = sipmsg_get_ms_diagnostics_reason(msg); SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: INVITE response is not 200. Failed to join focus."); sipe_backend_notify_error(SIPE_CORE_PUBLIC, _("Failed to join the conference"), reason ? reason : _("no reason given")); g_free(reason); sipe_session_remove(sipe_private, session); g_free(focus_uri); return FALSE; } else if (msg->response == 200) { sipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen); const gchar *code = sipe_xml_attribute(xn_response, "code"); if (sipe_strequal(code, "success")) { /* subscribe to focus */ sipe_subscribe_conference(sipe_private, session->chat_session->id, FALSE); #ifdef HAVE_VV if (session->is_call) sipe_core_media_connect_conference(SIPE_CORE_PUBLIC, session->chat_session); #endif } sipe_xml_free(xn_response); } g_free(focus_uri); return TRUE; }