Commit 92cad624 authored by Pekka Pessi's avatar Pekka Pessi

Split nua_stack.c into multiple files.

darcs-hash:20060308162955-65a35-a80f73008ddae5845d2dc72deef893af15e73c9f.gz
parent ff1e0e09
......@@ -29,6 +29,8 @@ noinst_PROGRAMS = test_nua
TESTS = test_nua
CLEANFILES = tmp_sippasswd.??????
# ----------------------------------------------------------------------
# Rules for building the targets
......@@ -38,6 +40,10 @@ nobase_include_sofia_HEADERS = \
sofia-sip/nua.h sofia-sip/nua_tag.h
libnua_la_SOURCES = nua.c nua_stack.h nua_common.c nua_stack.c \
nua_dialog.c \
nua_register.c nua_session.c nua_options.c \
nua_message.c nua_publish.c nua_subnotref.c \
nua_event_server.c \
nua_tag.c nua_tag_ref.c
COVERAGE_INPUT = $(libnua_la_SOURCES) $(include_sofia_HEADERS)
......
......@@ -25,6 +25,8 @@
/**@CFILE nua.c Nokia User Agent API.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <Kai.Vehmanen@nokia.com>
* @author Pasi Rinne-Rahkola
*
* @date Created: Wed Feb 14 18:32:58 2001 ppessi
*
......@@ -35,18 +37,10 @@
/* From AM_INIT/AC_INIT in our "config.h" */
char const nua_version[] = VERSION;
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sofia-sip/su_tag.h>
#include <sofia-sip/su_tag_class.h>
#include <sofia-sip/su_tagarg.h>
#include <stdio.h>
#include <sofia-sip/su_tag_io.h>
#define SU_LOG (nua_log)
......@@ -54,54 +48,21 @@ char const nua_version[] = VERSION;
#define SU_ROOT_MAGIC_T struct nua_s
#define SU_MSG_ARG_T struct event_s
#include <sofia-sip/su_wait.h>
#include <sofia-sip/su_strlst.h>
#define NUA_SAVED_EVENT_T su_msg_t *
#include "sofia-sip/nua.h"
#include "sofia-sip/nua_tag.h"
#define NTA_AGENT_MAGIC_T struct nua_s
#define NTA_LEG_MAGIC_T struct nua_handle_s
#define NTA_OUTGOING_MAGIC_T struct nua_handle_s
#define NTA_INCOMING_MAGIC_T struct nua_handle_s
#define NTR_AGENT_MAGIC_T struct nua_s
#define NTR_SESSION_MAGIC_T struct nua_handle_s
#define NTR_OUTGOING_MAGIC_T struct nua_handle_s
#define NTR_INCOMING_MAGIC_T struct nua_handle_s
#define NEA_SMAGIC_T nua_handle_t
#define NEA_EMAGIC_T nua_handle_t
#include <sofia-sip/sip.h>
#include <sofia-sip/sip_header.h>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/sip_util.h>
#include <sofia-sip/sip_header.h>
#include <sofia-sip/nta.h>
#include <sofia-sip/nea.h>
#include <sofia-sip/tport_tag.h>
#if HAVE_UICC_H
#include <uicc.h>
#endif
#include <sofia-sip/auth_client.h>
#if HAVE_SMIME /* Start NRC Boston */
#include "smimec.h"
#endif /* End NRC Boston */
#include <sofia-sip/sdp.h>
#include <sofia-sip/sl_utils.h>
#include "sofia-sip/nua.h"
#include "sofia-sip/nua_tag.h"
#include "nua_stack.h"
#undef nua_default
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
/**@var NUA_DEBUG
*
......@@ -191,8 +152,8 @@ nua_t *nua_create(su_root_t *root,
if (su_clone_start(root,
nua->nua_clone,
nua,
ua_init,
ua_deinit) == SU_SUCCESS) {
nua_stack_init,
nua_stack_deinit) == SU_SUCCESS) {
su_task_copy(nua->nua_server, su_clone_task(nua->nua_clone));
nua->nua_callback = callback;
nua->nua_magic = magic;
......@@ -1400,7 +1361,7 @@ void nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, int always,
xtra = tl_xtra(ta_args(ta), len);
if (su_msg_create(sumsg, nua->nua_server, nua->nua_client,
ua_signal,
nua_stack_signal,
e_len + len + l_len + xtra + l_xtra) == 0) {
event_t *e = su_msg_data(sumsg);
tagi_t *t = e->e_tags;
......
This diff is collapsed.
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef NUA_DIALOG_H /** Defined when <nua_dialog.h> has been included. */
#define NUA_DIALOG_H
/**@file nua_dialog.h
* @brief Dialog and dialog usage handling
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <Kai.Vehmanen@nokia.com>
*
* @date Created: Wed Mar 8 11:38:18 EET 2006 ppessi
*/
typedef struct nua_dialog_state nua_dialog_state_t;
typedef struct nua_dialog_usage nua_dialog_usage_t;
#ifndef NUA_H
#include <sofia-sip/nua.h>
#endif
#ifndef NTA_H
#include <sofia-sip/nta.h>
#endif
struct nua_dialog_state
{
/** Dialog usages. */
nua_dialog_usage_t *ds_usage;
/* Dialog and subscription state */
unsigned ds_route:1; /**< We have route */
unsigned ds_terminated:1; /**< Being terminated */
unsigned ds_has_session:1; /**< We have session */
unsigned ds_has_register:1; /**< We have registration */
unsigned ds_has_publish:1; /**< We have publish */
unsigned :0;
unsigned ds_has_events; /**< We have events */
unsigned ds_has_subscribes; /**< We have subscriptions */
unsigned ds_has_notifys; /**< We have notifiers */
sip_from_t const *ds_local; /**< Local address */
sip_to_t const *ds_remote; /**< Remote address */
nta_leg_t *ds_leg;
char const *ds_remote_tag; /**< Remote tag (if any).
* Should be non-NULL
* if dialog is established.
*/
struct nua_remote_s {
sip_allow_t *nr_allow;
sip_accept_t *nr_accept;
sip_require_t *nr_require;
sip_supported_t *nr_supported;
sip_user_agent_t *nr_user_agent;
} ds_remote_ua[1];
};
typedef void nh_pending_f(nua_handle_t *nh,
nua_dialog_usage_t *du,
sip_time_t now);
enum nua_dialog_usage_e
{
nua_is_transaction_usage = 0,
nua_is_session_usage,
nua_is_notifier_usage,
nua_is_subscriber_usage,
nua_is_register_usage,
nua_is_publish_usage
};
typedef struct {
unsigned usage_size, usage_class_size;
int (*usage_add)(nua_handle_t *nh,
nua_dialog_state_t *ds,
nua_dialog_usage_t *du);
void (*usage_remove)(nua_handle_t *nh,
nua_dialog_state_t *ds,
nua_dialog_usage_t *du);
char const *(*usage_name)(nua_dialog_usage_t const *du);
} nua_usage_class;
struct nua_dialog_usage {
nua_dialog_usage_t *du_next;
nua_usage_class const *du_class;
unsigned du_terminating:1; /**< Now trying to terminate usage */
unsigned du_ready:1; /**< Established usage */
unsigned:0;
/** Pending operation.
*
* The du_pending() is called
* a) when current time sip_now() will soon exceed du_refresh (now > 1)
* b) when operation is restarted (now is 1)
* c) when usage is destroyed (now is 0)
*/
nh_pending_f *du_pending;
sip_time_t du_refresh; /**< When execute du_pending */
sip_event_t const *du_event; /**< Event of usage */
msg_t *du_msg; /**< Template message */
};
void nua_dialog_uac_route(nua_handle_t *nh, sip_t const *sip, int rtag);
void nua_dialog_uas_route(nua_handle_t *nh, sip_t const *sip, int rtag);
void nua_dialog_get_peer_info(nua_handle_t *nh, sip_t const *sip);
char const *nua_dialog_usage_name(nua_dialog_usage_t const *du);
nua_dialog_usage_t *nua_dialog_usage_add(nua_handle_t *nh,
struct nua_dialog_state *ds,
nua_usage_class const *uclass,
sip_event_t const *event);
nua_dialog_usage_t *nua_dialog_usage_get(nua_dialog_state_t const *ds,
nua_usage_class const *uclass,
sip_event_t const *event);
void nua_dialog_usage_remove(nua_handle_t *nh,
nua_dialog_state_t *ds,
nua_dialog_usage_t *du);
void nua_dialog_terminated(nua_handle_t *nh,
struct nua_dialog_state *ds,
int status,
char const *phrase);
void nua_dialog_usage_set_refresh(nua_dialog_usage_t *du, unsigned delta);
static inline
int nua_dialog_is_established(nua_dialog_state_t const *ds)
{
return ds->ds_remote_tag != NULL;
}
#if 0
static inline
void *nua_dialog_usage_private(nua_dialog_usage_t const *du)
{
return (void *)(du + 1);
}
#else
#define nua_dialog_usage_private(du) ((void*)((du) + 1))
#endif
#ifndef NUA_STACK_H
#include <nua_stack.h>
#endif
#endif /* NUA_DIALOG_H */
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2006 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/**@CFILE nua_event_server.c
* @brief Easy event server
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
*
* @date Created: Wed Mar 8 11:48:49 EET 2006 ppessi
*/
#include "config.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <sofia-sip/string0.h>
#include <sofia-sip/sip_protos.h>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/su_tagarg.h>
#define NTA_LEG_MAGIC_T struct nua_handle_s
#define NTA_OUTGOING_MAGIC_T struct nua_handle_s
#define NEA_SMAGIC_T struct nua_handle_s
#define NEA_EMAGIC_T struct nua_handle_s
#include "nua_stack.h"
/* ======================================================================== */
/* Event server */
static
nea_event_t *nh_notifier_event(nua_handle_t *nh,
su_home_t *home,
sip_event_t const *event,
tagi_t const *tags);
static
void authorize_watcher(nea_server_t *nes,
nua_handle_t *nh,
nea_event_t *ev,
nea_subnode_t *sn,
sip_t const *sip);
void
nua_stack_notifier(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags)
{
su_home_t home[1] = { SU_HOME_INIT(home) };
sip_event_t const *event = NULL;
sip_content_type_t const *ct = NULL;
sip_payload_t const *pl = NULL;
url_string_t const *url = NULL;
char const *event_s = NULL, *ct_s = NULL, *pl_s = NULL;
nea_event_t *ev;
int status = 500;
char const *phrase = "Internal NUA Error";
nua_stack_init_handle(nua, nh, nh_has_nothing, NULL, TAG_NEXT(tags));
tl_gets(tags,
NUTAG_URL_REF(url),
SIPTAG_EVENT_REF(event),
SIPTAG_EVENT_STR_REF(event_s),
SIPTAG_CONTENT_TYPE_STR_REF(ct_s),
SIPTAG_PAYLOAD_REF(pl),
SIPTAG_PAYLOAD_STR_REF(pl_s),
TAG_END());
if (!event && !event_s)
status = 400, phrase = "Missing Event";
else if (!ct && !ct_s)
status = 400, phrase = "Missing Content-Type";
else if (!nh->nh_notifier &&
!(nh->nh_notifier =
nea_server_create(nua->nua_nta, nua->nua_root,
url->us_url,
NH_PGET(nh, max_subscriptions),
NULL, nh,
TAG_NEXT(tags))))
status = 500, phrase = "Internal NUA Error";
else if (!event && !(event = sip_event_make(home, event_s)))
status = 500, phrase = "Could not create an event header";
else if (!(ev = nh_notifier_event(nh, home, event, tags)))
status = 500, phrase = "Could not create an event view";
else if (nea_server_update(nh->nh_notifier, ev, TAG_NEXT(tags)) < 0)
status = 500, phrase = "No content for event";
else if (nea_server_notify(nh->nh_notifier, ev) < 0)
status = 500, phrase = "Error when notifying watchers";
else
nua_stack_event(nua, nh, NULL, e, status = SIP_200_OK,
SIPTAG_EVENT(event),
SIPTAG_CONTENT_TYPE(ct),
TAG_END());
if (status != 200)
nua_stack_event(nua, nh, NULL, e, status, phrase, TAG_END());
su_home_deinit(home);
}
/* Create a event view for notifier */
static
nea_event_t *nh_notifier_event(nua_handle_t *nh,
su_home_t *home,
sip_event_t const *event,
tagi_t const *tags)
{
nea_event_t *ev = nea_event_get(nh->nh_notifier, event->o_type);
sip_accept_t const *accept = NULL;
char const *accept_s = NULL;
sip_content_type_t const *ct = NULL;
char const *ct_s = NULL;
if (ev == NULL) {
char *o_type = su_strdup(home, event->o_type);
char *o_subtype = strchr(o_type, '.');
if (o_subtype)
*o_subtype++ = '\0';
tl_gets(tags,
SIPTAG_ACCEPT_REF(accept),
SIPTAG_ACCEPT_STR_REF(accept_s),
SIPTAG_CONTENT_TYPE_REF(ct),
SIPTAG_CONTENT_TYPE_STR_REF(ct_s),
TAG_END());
/*
* XXX - We really should build accept header when we add new content
* types
*/
if (accept_s == NULL && accept)
accept_s = sip_header_as_string(home, (sip_header_t *)accept);
if (accept_s == NULL && ct)
accept_s = ct->c_type;
if (accept_s == NULL && ct_s)
accept_s = ct_s;
ev = nea_event_create(nh->nh_notifier,
authorize_watcher, nh,
o_type, o_subtype,
ct ? ct->c_type : ct_s,
accept_s);
}
return ev;
}
/* Callback from nea_server asking nua to authorize subscription */
static
void authorize_watcher(nea_server_t *nes,
nua_handle_t *nh,
nea_event_t *ev,
nea_subnode_t *sn,
sip_t const *sip)
{
nua_t *nua = nh->nh_nua;
msg_t *msg = NULL;
nta_incoming_t *irq = NULL;
int substate = sn->sn_state;
int status; char const *phrase;
SET_STATUS1(SIP_200_OK);
/* OK. In nhp (nua_handle_preferences_t) structure we have the
current default action (or state) for incoming
subscriptions.
Action can now be modified by the application with NUTAG_SUBSTATE().
*/
irq = nea_sub_get_request(sn->sn_subscriber);
msg = nta_incoming_getrequest(irq);
if (sn->sn_state == nea_embryonic) {
char const *what;
substate = NH_PGET(nh, substate);
if (substate == nua_substate_embryonic)
substate = nua_substate_pending;
if (substate == nua_substate_terminated) {
what = "rejected"; SET_STATUS1(SIP_403_FORBIDDEN);
}
else if (substate == nua_substate_pending) {
what = "pending"; SET_STATUS1(SIP_202_ACCEPTED);
}
else {
what = "active";
}
SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n", nh, what));
nea_sub_auth(sn->sn_subscriber, substate,
TAG_IF(substate == nua_substate_pending,
NEATAG_FAKE(1)),
TAG_IF(substate == nua_substate_terminated,
NEATAG_REASON("rejected")),
TAG_END());
}
else if (sn->sn_state == nea_terminated || sn->sn_expires == 0) {
substate = nua_substate_terminated;
nea_server_flush(nes, NULL);
SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n",
nh, "watcher is removed"));
}
nua_stack_event(nua, nh, msg, nua_i_subscription, status, phrase,
NUTAG_SUBSTATE(substate),
NEATAG_SUB(sn->sn_subscriber),
TAG_END());
}
/* ---------------------------------------------------------------------- */
/* Authorization by application */
void
nua_stack_authorize(nua_t *nua, nua_handle_t *nh, nua_event_t e,
tagi_t const *tags)
{
nea_sub_t *sub = NULL;
nea_state_t state = nea_extended;
tl_gets(tags,
NEATAG_SUB_REF(sub),
NUTAG_SUBSTATE_REF(state),
TAG_END());
if (sub && state > 0) {
nea_sub_auth(sub, state, TAG_NEXT(tags));
nua_stack_event(nua, nh, NULL, e, SIP_200_OK, TAG_END());
}
else {
nua_stack_event(nua, nh, NULL, e, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
}
return;
}
/** Shutdown notifier object */
int
nh_notifier_shutdown(nua_handle_t *nh, nea_event_t *ev,
tag_type_t t, tag_value_t v, ...)
{
nea_server_t *nes = nh->nh_notifier;
nea_subnode_t const **subs;
int busy = 0;
if (nes == NULL)
return 0;
subs = nea_server_get_subscribers(nes, ev);
if (subs) {
int i;
ta_list ta;
ta_start(ta, t, v);
for (i = 0; subs[i]; i++)
nea_sub_auth(subs[i]->sn_subscriber, nea_terminated, ta_tags(ta));
ta_end(ta);
busy++;
}
nea_server_free_subscribers(nes, subs);
nea_server_flush(nh->nh_notifier, NULL);
if (ev == NULL)
nea_server_destroy(nh->nh_notifier), nh->nh_notifier = NULL;
return busy;
}
/** Terminate notifier. */
void
nua_stack_terminate(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags)
{
sip_event_t const *event = NULL;
sip_content_type_t const *ct = NULL;
sip_payload_t const *pl = NULL;
char const *event_s = NULL, *ct_s = NULL, *pl_s = NULL;
nea_event_t *nev = NULL;
if (nh->nh_notifier == NULL) {
UA_EVENT2(e, 500, "No event server to terminate");
return;
}
tl_gets(tags,
SIPTAG_EVENT_REF(event),
SIPTAG_EVENT_STR_REF(event_s),
SIPTAG_CONTENT_TYPE_REF(ct),
SIPTAG_CONTENT_TYPE_STR_REF(ct_s),
SIPTAG_PAYLOAD_REF(pl),
SIPTAG_PAYLOAD_STR_REF(pl_s),
TAG_END());
nev = nea_event_get(nh->nh_notifier,
event ? event->o_type : event_s);
if (nev && (pl || pl_s) && (ct || ct_s)) {
nea_server_update(nh->nh_notifier, nev, TAG_NEXT(tags));
}
nh_notifier_shutdown(nh, NULL,
NEATAG_REASON("noresource"),
TAG_NEXT(tags));
nua_stack_event(nua, nh, NULL, e, SIP_200_OK, TAG_END());
}
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2006 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/**@CFILE nua_message.c
* @brief MESSAGE method
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
*
* @date Created: Wed Mar 8 17:01:22 EET 2006 ppessi
*/
#include "config.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <sofia-sip/string0.h>
#include <sofia-sip/sip_protos.h>
#include <sofia-sip/sip_status.h>
#define NTA_LEG_MAGIC_T struct nua_handle_s
#define NTA_OUTGOING_MAGIC_T struct nua_handle_s
#include "nua_stack.h"
/* ======================================================================== */
/* MESSAGE */
static int process_response_to_message(nua_handle_t *nh,
nta_outgoing_t *orq,
sip_t const *sip);
int
nua_stack_message(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags)
{
struct nua_client_request *cr = nh->nh_cr;
msg_t *msg;
sip_t *sip;
if (nh_is_special(nh)) {
return UA_EVENT2(e, 500, "Invalid handle for MESSAGE");
}
else if (cr->cr_orq) {
return UA_EVENT2(e, 500, "Request already in progress");
}
nua_stack_init_handle(nua, nh, nh_has_nothing, NULL, TAG_NEXT(tags));
msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count,
SIP_METHOD_MESSAGE,
NUTAG_ADD_CONTACT(NH_PGET(nh, win_messenger_enable)),
TAG_NEXT(tags));
sip = sip_object(msg);