Commit 38213bab authored by Pekka Pessi's avatar Pekka Pessi

nua: added extension methods (nua_method()).

darcs-hash:20061113140837-65a35-47805bb055f99a90bba156f88357c4b06efacfc7.gz
parent c2744f25
......@@ -44,6 +44,7 @@ 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_extension.c \
nua_dialog.c nua_dialog.h \
outbound.c outbound.h \
nua_params.c nua_params.h \
......@@ -83,6 +84,7 @@ test_nua_SOURCES = test_nua.c test_nua.h test_ops.c \
test_call_hold.c test_session_timer.c \
test_refer.c test_100rel.c \
test_simple.c test_sip_events.c \
test_extension.c \
test_proxy.h test_proxy.c \
test_nat.h test_nat.c test_nat_tags.c
......
......@@ -648,6 +648,12 @@ void nua_message(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
NUA_SIGNAL(nh, nua_r_message, tag, value);
}
/* Documented with nua_stack_method() */
void nua_method(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
{
NUA_SIGNAL(nh, nua_r_method, tag, value);
}
/** Send a chat message.
*
* A chat channel can be established during call setup using "message" media.
......
......@@ -2145,23 +2145,9 @@ NUTAG_AUTOANSWER(0) on B side, NUTAG_AUTOACK(0) on A side.
* @END_NUA_EVENT
*/
/* nua_r_message is documented with nua_stack_process_message() */
/* nua_i_message is documented with nua_stack_process_message() */
/** @NUA_EVENT nua_i_method
*
* Unknown incoming request method.
*
* The extension method must be listed using NUTAG_ALLOW() or SIPTAG_ALLOW()
* tag in nua_set_params().
*
* @param nh operation handle associated with the request
* @param hmagic operation magic associated with the handle
* @param status statuscode of response sent automatically by stack
* @param sip incoming request with unknown method
* @param tags empty
*
* @END_NUA_EVENT
*/
/* nua_i_method is documented with nua_stack_process_method() */
/** @NUA_EVENT nua_i_network_changed
*
......
/*
* 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_extension.c
* @brief Extension method
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
*
* @date Created: Mon Nov 13 15:18:54 EET 2006
*/
#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"
static int process_response_to_method(nua_handle_t *nh,
nta_outgoing_t *orq,
sip_t const *sip);
static void restart_method(nua_handle_t *nh, tagi_t *tags);
static int respond_to_method(nua_server_request_t *sr, tagi_t const *tags);
/** Send an extension request.
*
* Send an entension request message.
*
* @param nh Pointer to operation handle
* @param tag, value, ... List of tagged parameters
*
* @return
* nothing
*
* @par Related Tags:
* NUTAG_METHOD() \n
* NUTAG_URL() \n
* Tags of nua_set_hparams() \n
* Tags in <sip_tag.h>
*
* @par Events:
* #nua_r_method
*
* @sa SIP_METHOD_UNKNOWN(), #nua_r_method, #nua_i_method
*
* @since New in @VERSION_1_12_4.
*/
int
nua_stack_method(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags)
{
nua_client_request_t *cr = nh->nh_ds->ds_cr;
msg_t *msg;
if (cr->cr_orq)
return UA_EVENT2(e, 900, "Request already in progress");
nua_stack_init_handle(nua, nh, TAG_NEXT(tags));
msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count,
SIP_METHOD_UNKNOWN,
TAG_NEXT(tags));
if (msg)
cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta,
process_response_to_method, nh, NULL,
msg,
SIPTAG_END(),
TAG_NEXT(tags));
if (!cr->cr_orq) {
msg_destroy(msg);
return UA_EVENT1(e, NUA_INTERNAL_ERROR);
}
return cr->cr_event = e;
}
/** @NUA_EVENT nua_r_method
*
* Response to an outgoing extension request.
*
* @param status response status code
* (if the request is retried, @a status is 100, the @a
* sip->sip_status->st_status contain the real status code
* from the response method, e.g., 302, 401, or 407)
* @param phrase a short textual description of @a status code
* @param nh operation handle associated with the method
* @param hmagic application context associated with the handle
* @param sip response to the extension request or NULL upon an error
* (status code is in @a status and
* descriptive method in @a phrase parameters)
* @param tags empty
*
* @sa nua_method(), #nua_i_method, @RFC3428
*
* @END_NUA_EVENT
*/
static int process_response_to_method(nua_handle_t *nh,
nta_outgoing_t *orq,
sip_t const *sip)
{
if (nua_creq_check_restart(nh, nh->nh_ds->ds_cr, orq, sip, restart_method))
return 0;
return nua_stack_process_response(nh, nh->nh_ds->ds_cr, orq, sip, TAG_END());
}
void restart_method(nua_handle_t *nh, tagi_t *tags)
{
nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_method, tags);
}
/** @NUA_EVENT nua_i_method
*
* @brief Incoming extension request.
*
* The extension request does not create a dialog. If the incoming request
* was not assiciated with an existing dialog the stack creates a new handle
* for it. If the handle @a nh is not bound, you should probably destroy it
* after responding to the request.
*
* @param status status code of response sent automatically by stack
* @param phrase a short textual description of @a status code
* @param nh operation handle associated with the method
* @param hmagic application context associated with the handle
* (maybe NULL if outside session)
* @param sip incoming request
* @param tags NUTAG_METHOD()
*
* The extension name is in sip->sip_request->rq_method_name, too.
*
* @sa nua_method(), #nua_r_method
*
* @END_NUA_EVENT
*/
int nua_stack_process_method(nua_t *nua,
nua_handle_t *nh,
nta_incoming_t *irq,
sip_t const *sip)
{
nua_server_request_t *sr, sr0[1];
sr = SR_INIT(sr0);
sr = nua_server_request(nua, nh, irq, sip, sr, sizeof *sr,
respond_to_method, 0);
return nua_stack_server_event(nua, sr, nua_i_method, TAG_END());
}
static
int respond_to_method(nua_server_request_t *sr, tagi_t const *tags)
{
nua_handle_t *nh = sr->sr_owner;
nua_t *nua = nh->nh_nua;
msg_t *msg;
msg = nua_server_response(sr, sr->sr_status, sr->sr_phrase, TAG_NEXT(tags));
if (msg) {
nta_incoming_mreply(sr->sr_irq, msg);
}
else {
SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);
nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END());
nua_stack_event(nua, nh, NULL,
nua_i_error, 900, "Response to Extension Method Fails",
TAG_END());
}
return sr->sr_status >= 200 ? sr->sr_status : 0;
}
......@@ -1076,6 +1076,8 @@ msg_t *nua_creq_msg(nua_t *nua,
has_contact = 1;
else if (t->t_tag == nutag_url)
url = (url_string_t const *)t->t_value;
else if (t->t_tag == nutag_method && method == sip_method_unknown)
name = (char const *)t->t_value;
else if (t->t_tag == nutag_use_dialog)
use_dialog = t->t_value != 0;
else if (t->t_tag == _nutag_add_contact)
......@@ -1385,13 +1387,6 @@ int nua_stack_process_unknown(nua_t *nua,
return 501;
}
int
nua_stack_method(nua_t *nua, nua_handle_t *nh, nua_event_t e,
tagi_t const *tags)
{
return UA_EVENT1(e, SIP_501_NOT_IMPLEMENTED);
}
/**@internal
* Relay response message to the application.
*
......@@ -1819,6 +1814,9 @@ int nua_stack_process_request(nua_handle_t *nh,
/* Send nua_i_error ? */
return 481;
case sip_method_unknown:
return nua_stack_process_method(nua, nh, irq, sip);
default:
return nua_stack_process_unknown(nua, nh, irq, sip);
}
......
......@@ -436,6 +436,7 @@ nua_stack_process_request_t nua_stack_process_notify;
nua_stack_process_request_t nua_stack_process_refer;
nua_stack_process_request_t nua_stack_process_unknown;
nua_stack_process_request_t nua_stack_process_register;
nua_stack_process_request_t nua_stack_process_method;
nua_client_request_t
*nua_client_request_pending(nua_client_request_t const *),
......
......@@ -46,6 +46,7 @@ tag_typedef_t nutag_any = NSTAG_TYPEDEF(*);
tag_typedef_t nutag_url = URLTAG_TYPEDEF(url);
tag_typedef_t nutag_address = STRTAG_TYPEDEF(address);
tag_typedef_t nutag_method = STRTAG_TYPEDEF(method);
tag_typedef_t nutag_uicc = STRTAG_TYPEDEF(uicc);
tag_typedef_t nutag_media_features = BOOLTAG_TYPEDEF(media_features);
tag_typedef_t nutag_callee_caps = BOOLTAG_TYPEDEF(callee_caps);
......
......@@ -328,6 +328,9 @@ SOFIAPUBFUN void nua_authorize(nua_handle_t *, tag_type_t, tag_value_t, ...);
/*# Redirect an operation. @deprecated */
SOFIAPUBFUN void nua_redirect(nua_handle_t *, tag_type_t, tag_value_t, ...);
/** Extension request method. */
SOFIAPUBFUN void nua_method(nua_handle_t *, tag_type_t, tag_value_t, ...);
/** Respond with given status. */
SOFIAPUBFUN void nua_respond(nua_handle_t *nh,
int status, char const *phrase,
......
......@@ -161,6 +161,31 @@ SOFIAPUBVAR tag_typedef_t nutag_retry_count;
#define NUTAG_RETRY_COUNT_REF(x) nutag_retry_count_ref, tag_uint_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_retry_count_ref;
/** Extension method name.
*
* Specify extension method name with nua_method() function.
*
* @par Used with
* nua_method() \n
*
* @par Parameter type
* char const *
*
* @par Values
* Extension method name (e.g., "SERVICE")
*
* Corresponding tag taking reference parameter is NUTAG_METHOD_REF()
*
* @sa nua_method(), SIP_METHOD_UNKNOWN()
*
* @since New in @VERSION_1_12_4.
*/
#define NUTAG_METHOD(x) nutag_method, tag_str_v(x)
SOFIAPUBVAR tag_typedef_t nutag_method;
#define NUTAG_METHOD_REF(x) nutag_method_ref, tag_str_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_method_ref;
/**Set maximum number of simultaneous subscribers per single event server.
*
* Determines how many subscribers can simultaneously subscribe to a single
......
/*
* 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
*
*/
/**@CFILE test_extension.c
* @brief NUA-12: Test extension methods.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
*
* @date Created: Mon Nov 13 15:37:05 EET 2006
*/
#include "config.h"
#include "test_nua.h"
#include <sofia-sip/su_tag_class.h>
#if HAVE_FUNC
#elif HAVE_FUNCTION
#define __func__ __FUNCTION__
#else
#define __func__ "test_extension"
#endif
int respond_to_extension(CONDITION_PARAMS)
{
msg_t *with = nua_current_request(nua);
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
switch (event) {
case nua_i_method:
RESPOND(ep, call, nh, SIP_200_OK,
NUTAG_WITH(with),
SIPTAG_SUBJECT_STR("extended"),
TAG_END());
return 1;
default:
return 0;
}
}
int test_extension(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
sip_t const *sip;
/* Test for EXTENSION
A B
|------EXTENSION---->|
|<--------501--------| (method not recognized)
| |
|------EXTENSION---->|
|<-------200---------| (method allowed, responded)
| |
*/
if (print_headings)
printf("TEST NUA-13.1: EXTENSION\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
/* Test first without NUTAG_METHOD() */
METHOD(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, NULL);
/* Client events:
nua_method(), nua_r_method
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_method);
TEST(e->data->e_status, 900); /* Internal error */
TEST_1(!e->e_msg);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
METHOD(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
NUTAG_METHOD("EXTENSION"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, NULL);
/* Client events:
nua_method(), nua_r_method
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_method);
TEST(e->data->e_status, 501);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
nua_set_params(b->nua, NUTAG_ALLOW("EXTENSION"), TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
METHOD(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
NUTAG_METHOD("EXTENSION"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, respond_to_extension);
/* Client events:
nua_method(), nua_r_method
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_method);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(!e->next);
/*
Server events:
nua_i_method
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_method);
TEST(e->data->e_status, 100);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-13.1: PASSED\n");
END();
}
......@@ -278,6 +278,7 @@ int main(int argc, char *argv[])
retval |= test_nat_timeout(ctx);
if (retval == 0) {
retval |= test_extension(ctx); SINGLE_FAILURE_CHECK();
retval |= test_basic_call(ctx); SINGLE_FAILURE_CHECK();
retval |= test_reject_a(ctx); SINGLE_FAILURE_CHECK();
retval |= test_reject_b(ctx); SINGLE_FAILURE_CHECK();
......
......@@ -246,7 +246,7 @@ typedef int operation_f(struct endpoint *ep, struct call *call,
...);
operation_f INVITE, ACK, BYE, CANCEL, AUTHENTICATE, UPDATE, INFO, PRACK,
REFER, MESSAGE, OPTIONS, PUBLISH, UNPUBLISH, REGISTER, UNREGISTER,
REFER, MESSAGE, METHOD, OPTIONS, PUBLISH, UNPUBLISH, REGISTER, UNREGISTER,
SUBSCRIBE, UNSUBSCRIBE, NOTIFY, NOTIFIER, TERMINATE, AUTHORIZE;
int RESPOND(struct endpoint *ep,
......@@ -333,4 +333,6 @@ int test_100rel(struct context *ctx);
int test_simple(struct context *ctx);
int test_events(struct context *ctx);
int test_extension(struct context *ctx);
#endif
......@@ -344,6 +344,7 @@ OPERATION(INFO, info);
OPERATION(PRACK, prack);
OPERATION(REFER, refer);
OPERATION(MESSAGE, message);
OPERATION(METHOD, method);
OPERATION(OPTIONS, options);
OPERATION(PUBLISH, publish);
OPERATION(UNPUBLISH, unpublish);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment