952 lines
25 KiB
C
952 lines
25 KiB
C
/*
|
|
* 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 nta_compat.c
|
|
* @brief Compatibility functions for Nokia SIP Transaction API
|
|
*
|
|
* These functions are deprecated and should not be used anymore.
|
|
*
|
|
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
|
*
|
|
* @date Created: Tue Jul 24 22:28:34 2001 ppessi
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include <sofia-sip/su_tagarg.h>
|
|
|
|
#include "sofia-sip/nta.h"
|
|
#include "nta_compat.h"
|
|
#include "nta_internal.h"
|
|
|
|
#include <sofia-sip/sip_header.h>
|
|
#include <sofia-sip/sip_util.h>
|
|
|
|
/** Set UAS flag value.
|
|
*
|
|
* The function nta_agent_set_uas() is used to set or clear User Agent
|
|
* Server flag.
|
|
*
|
|
* Currently, the flag determines how the agent handles 2XX replies to an
|
|
* incoming INVITE request. If flag is set, the agent resends the 2XX final
|
|
* responses to an INVITE.
|
|
*
|
|
* @deprecated Use nta_agent_set_params() and NTATAG_UA() instead.
|
|
*/
|
|
int nta_agent_set_uas(nta_agent_t *agent, int value)
|
|
{
|
|
int retval = 1;
|
|
|
|
nta_agent_set_params(agent, NTATAG_UA(value != 0), TAG_END());
|
|
nta_agent_get_params(agent, NTATAG_UA_REF(retval), TAG_END());
|
|
|
|
return retval;
|
|
}
|
|
|
|
/** Set branch key.
|
|
*
|
|
* @deprecated Use nta_agent_set_params() and NTATAG_BRANCH_KEY() instead.
|
|
*/
|
|
msg_param_t nta_agent_set_branch(nta_agent_t *agent,
|
|
msg_param_t branch)
|
|
{
|
|
msg_param_t retval = "";
|
|
|
|
nta_agent_set_params(agent, NTATAG_BRANCH_KEY(branch), TAG_END());
|
|
nta_agent_get_params(agent, NTATAG_BRANCH_KEY_REF(retval), TAG_END());
|
|
|
|
return retval;
|
|
}
|
|
|
|
/** Set default proxy.
|
|
*
|
|
* @deprecated Use nta_agent_set_params() and NTATAG_DEFAULT_PROXY() instead.
|
|
*/
|
|
int nta_agent_set_proxy(nta_agent_t *agent, url_string_t const *u)
|
|
{
|
|
if (agent)
|
|
nta_agent_set_params(agent, NTATAG_DEFAULT_PROXY(u), TAG_END());
|
|
return 0;
|
|
}
|
|
|
|
/**Return default @b Tag.
|
|
*
|
|
* The function nta_agent_tag() returns the default @To @b tag
|
|
* which is used by NTA agent.
|
|
*
|
|
* @param agent NTA agent object
|
|
*
|
|
* @return The default tag used by NTA agent.
|
|
*
|
|
* @deprecated Use nta_agent_newtag() to generate a new, unique tag value.
|
|
*
|
|
* @sa NTATAG_TAG_3261().
|
|
*/
|
|
msg_param_t nta_agent_tag(nta_agent_t const *agent)
|
|
{
|
|
return
|
|
(agent && agent->sa_2543_tag)
|
|
? agent->sa_2543_tag + strlen("tag=")
|
|
: NULL;
|
|
}
|
|
|
|
/** Reply to the request message. */
|
|
int nta_msg_reply(nta_agent_t *agent,
|
|
msg_t *msg,
|
|
int status, char const *phrase,
|
|
void *extra, ...)
|
|
{
|
|
int retval;
|
|
va_list(headers);
|
|
va_start(headers, extra);
|
|
retval = nta_msg_vreply(agent, msg, status, phrase, extra, headers);
|
|
va_end(headers);
|
|
return retval;
|
|
}
|
|
|
|
/** Reply to the request message (stdarg version of nta_msg_reply()). */
|
|
int nta_msg_vreply(nta_agent_t *agent,
|
|
msg_t *req_msg,
|
|
int status, char const *phrase,
|
|
void *extra, va_list headers)
|
|
{
|
|
msg_t *reply = nta_msg_create(agent, 0);
|
|
sip_t *sip = sip_object(reply);
|
|
|
|
if (sip_add_headers(reply, sip, extra, headers) < 0)
|
|
sip = NULL;
|
|
|
|
return nta_msg_mreply(agent, reply, sip,
|
|
status, phrase, req_msg, TAG_END());
|
|
}
|
|
|
|
/** Send the message (stdarg version of nta_msg_send()). */
|
|
int nta_msg_vsend(nta_agent_t *agent, msg_t *msg, url_string_t const *u,
|
|
void *extra, va_list headers)
|
|
{
|
|
sip_t *sip = sip_object(msg);
|
|
|
|
if (extra && sip_add_headers(msg, sip, extra, headers) < 0) {
|
|
msg_destroy(msg);
|
|
return -1;
|
|
}
|
|
|
|
return nta_msg_tsend(agent, msg, u, TAG_END());
|
|
}
|
|
|
|
/** Send the message. */
|
|
int nta_msg_send(nta_agent_t *agent, msg_t *msg, url_string_t const *u,
|
|
void *extra, ...)
|
|
{
|
|
int retval;
|
|
va_list headers;
|
|
va_start(headers, extra);
|
|
retval = nta_msg_vsend(agent, msg, u, extra, headers);
|
|
va_end(headers);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* Create a new leg object for incoming request message.
|
|
*
|
|
* @param agent agent object
|
|
* @param callback function which is called for each
|
|
* incoming request belonging to this leg
|
|
* @param magic call leg context
|
|
* @param msg a request message
|
|
*
|
|
* @note The ownership of @a msg will pass back to NTA upon successful call
|
|
* to the function nta_msg_leg(). In other words, if the call to @a
|
|
* nta_msg_leg() is successful, the application may not do anything with @a
|
|
* msg anymore. Instead of that, NTA will create of a new incoming request
|
|
* object for the @a msg and eventually return the request to application by
|
|
* calling the @a callback function.
|
|
*
|
|
* @deprecated Use nta_leg_stateful() instead.
|
|
*/
|
|
nta_leg_t *nta_msg_leg(nta_agent_t *agent,
|
|
msg_t *msg,
|
|
nta_request_f *callback,
|
|
nta_leg_magic_t *magic,
|
|
...)
|
|
{
|
|
nta_leg_t *leg;
|
|
sip_t *sip = sip_object(msg);
|
|
|
|
SU_DEBUG_9(("\tnta_msg_leg(): called\n"));
|
|
|
|
assert(msg && sip && sip->sip_request);
|
|
|
|
if (!msg || !sip || !sip->sip_request || !callback)
|
|
return NULL;
|
|
|
|
leg = nta_leg_tcreate(agent, callback, magic,
|
|
SIPTAG_CALL_ID(sip->sip_call_id),
|
|
SIPTAG_FROM(sip->sip_to), /* local address */
|
|
SIPTAG_TO(sip->sip_from), /* remote address */
|
|
TAG_END());
|
|
if (!leg)
|
|
/* xyzzy */;
|
|
else if (nta_leg_server_route(leg, sip->sip_record_route,
|
|
sip->sip_contact) < 0)
|
|
nta_leg_destroy(leg), leg = NULL;
|
|
else if (nta_leg_stateful(leg, msg) < 0)
|
|
nta_leg_destroy(leg), leg = NULL;
|
|
|
|
SU_DEBUG_9(("\tnta_msg_leg(): returns %p\n", leg));
|
|
|
|
return leg;
|
|
}
|
|
|
|
static void sm_leg_recv(su_root_magic_t *rm,
|
|
su_msg_r msg,
|
|
union sm_arg_u *u);
|
|
|
|
/** Process msg statefully using the leg. */
|
|
int nta_leg_stateful(nta_leg_t *leg, msg_t *msg)
|
|
{
|
|
su_msg_r su_msg = SU_MSG_RINITIALIZER;
|
|
nta_agent_t *agent = leg->leg_agent;
|
|
su_root_t *root = agent->sa_root;
|
|
struct leg_recv_s *a;
|
|
|
|
/* Create a su message that is passed to NTA network thread */
|
|
if (su_msg_create(su_msg,
|
|
su_root_task(root),
|
|
su_root_task(root),
|
|
sm_leg_recv, /* Function to call */
|
|
sizeof(struct leg_recv_s)) == SU_FAILURE)
|
|
return -1;
|
|
|
|
agent->sa_stats->as_trless_to_tr++;
|
|
|
|
a = su_msg_data(su_msg)->a_leg_recv;
|
|
|
|
a->leg = leg;
|
|
a->msg = msg;
|
|
|
|
a->tport = tport_incref(tport_delivered_by(agent->sa_tports, msg));
|
|
|
|
return su_msg_send(su_msg);
|
|
}
|
|
|
|
/** @internal Delayed leg_recv(). */
|
|
static
|
|
void sm_leg_recv(su_root_magic_t *rm,
|
|
su_msg_r msg,
|
|
union sm_arg_u *u)
|
|
{
|
|
struct leg_recv_s *a = u->a_leg_recv;
|
|
leg_recv(a->leg, a->msg, sip_object(a->msg), a->tport);
|
|
tport_decref(&a->tport);
|
|
}
|
|
|
|
/**Create a new leg object
|
|
*
|
|
* @param agent agent object
|
|
* @param callback function which is called for each
|
|
* incoming request belonging to this leg
|
|
* @param magic call leg context
|
|
* @param i optional @CallID
|
|
* (if @c NULL, an ID generated by @b NTA is used)
|
|
* @param from optional @From (local address)
|
|
* @param to optional @To (remote address)
|
|
* @param extra, ... optional extra headers, terminated with a @c NULL
|
|
*
|
|
* @deprecated Use nta_leg_tcreate() instead.
|
|
*/
|
|
nta_leg_t *nta_leg_create(nta_agent_t *agent,
|
|
nta_request_f *callback,
|
|
nta_leg_magic_t *magic,
|
|
sip_call_id_t const *i,
|
|
sip_from_t const *from,
|
|
sip_to_t const *to,
|
|
void const *extra, ...)
|
|
{
|
|
nta_leg_t *leg;
|
|
va_list headers;
|
|
va_start(headers, extra);
|
|
leg = nta_leg_vcreate(agent, callback, magic,
|
|
i, from, to,
|
|
extra, headers);
|
|
va_end(headers);
|
|
return leg;
|
|
}
|
|
|
|
/**
|
|
* Create a new leg object
|
|
*
|
|
* @param agent agent object
|
|
* @param callback function which is called for each
|
|
* incoming request belonging to this leg
|
|
* @param magic call leg context
|
|
* @param i optional @CallID
|
|
* (if @c NULL, an ID generated by @b NTA is used)
|
|
* @param from optional @From (local address)
|
|
* @param to optional @To (remote address)
|
|
* @param extra optional extra header
|
|
* @param headers va_list of optional extra headers
|
|
*
|
|
* @deprecated Use nta_leg_tcreate() instead.
|
|
*/
|
|
nta_leg_t *nta_leg_vcreate(nta_agent_t *agent,
|
|
nta_request_f *callback,
|
|
nta_leg_magic_t *magic,
|
|
sip_call_id_t const *i,
|
|
sip_from_t const *from,
|
|
sip_to_t const *to,
|
|
void const *extra, va_list headers)
|
|
{
|
|
sip_route_t const *route = NULL;
|
|
sip_cseq_t const *cseq = NULL;
|
|
|
|
for (; extra ; extra = va_arg(headers, void *)) {
|
|
sip_header_t const *h = (sip_header_t const *)extra;
|
|
|
|
if (h == SIP_NONE)
|
|
continue;
|
|
else if (sip_call_id_p(h)) {
|
|
if (i == NULL) i = h->sh_call_id;
|
|
}
|
|
else if (sip_from_p(h)) {
|
|
if (from == NULL) from = h->sh_from;
|
|
}
|
|
else if (sip_to_p(h)) {
|
|
if (to == NULL) to = h->sh_to;
|
|
}
|
|
else if (sip_route_p(h)) {
|
|
route = h->sh_route;
|
|
}
|
|
else if (sip_cseq_p(h)) {
|
|
cseq = h->sh_cseq;
|
|
}
|
|
else {
|
|
SU_DEBUG_3(("nta_leg_create: extra header %s\n",
|
|
sip_header_name(h, 0)));
|
|
}
|
|
}
|
|
|
|
return nta_leg_tcreate(agent, callback, magic,
|
|
NTATAG_NO_DIALOG(i == SIP_NONE->sh_call_id),
|
|
TAG_IF(i != SIP_NONE->sh_call_id, SIPTAG_CALL_ID(i)),
|
|
TAG_IF(from != SIP_NONE->sh_from, SIPTAG_FROM(from)),
|
|
TAG_IF(to != SIP_NONE->sh_to, SIPTAG_TO(to)),
|
|
SIPTAG_ROUTE(route),
|
|
SIPTAG_CSEQ(cseq),
|
|
TAG_END());
|
|
}
|
|
|
|
/**Mark leg as branchable.
|
|
*
|
|
* This function does currently absolutely nothing.
|
|
*
|
|
* @param leg leg to be marked branchable.
|
|
*
|
|
* @note Currently, all legs @b are branchable.
|
|
*
|
|
* @deprecated Do not use.
|
|
*/
|
|
int nta_leg_branch(nta_leg_t *leg)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/** Add route from final response
|
|
*
|
|
* @deprecated Use nta_leg_client_route().
|
|
*/
|
|
int nta_leg_route(nta_leg_t *leg,
|
|
sip_record_route_t const *route,
|
|
sip_contact_t const *contact,
|
|
url_string_t const *url)
|
|
{
|
|
return nta_leg_client_route(leg, route, contact);
|
|
}
|
|
|
|
#if 0
|
|
/**Get response message.
|
|
*
|
|
* The function nta_incoming_getresponse() retrieves a copy of the latest
|
|
* outgoing response message. The response message is copied; the original
|
|
* copy is kept by the transaction.
|
|
*
|
|
* @param irq incoming (server) transaction handle
|
|
*
|
|
* @retval
|
|
* A pointer to the copy of the response message is returned, or NULL if an
|
|
* error occurred.
|
|
*/
|
|
msg_t *nta_incoming_getresponse(nta_incoming_t *irq)
|
|
{
|
|
if (irq && irq->irq_response) {
|
|
msg_t *msg = nta_msg_create(irq->irq_agent, 0);
|
|
sip_t *sip = sip_object(msg);
|
|
|
|
msg_clone(msg, irq->irq_response);
|
|
|
|
/* Copy the SIP headers from the old message */
|
|
if (msg_copy_all(msg, sip, sip_object(irq->irq_response)) >= 0)
|
|
return msg;
|
|
|
|
msg_destroy(msg);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**Get request message.
|
|
*
|
|
* The function nta_outgoing_getrequest() retrieves the request message sent
|
|
* to the network. The request message is copied; the original copy is kept
|
|
* by the transaction.
|
|
*
|
|
* @param orq outgoing transaction handle
|
|
*
|
|
* @retval
|
|
* A pointer to the copy of the request message is returned, or NULL if an
|
|
* error occurred.
|
|
*/
|
|
msg_t *nta_outgoing_getrequest(nta_outgoing_t *orq)
|
|
{
|
|
if (orq && orq->orq_request) {
|
|
msg_t *msg = nta_msg_create(orq->orq_agent, 0);
|
|
sip_t *sip = sip_object(msg);
|
|
|
|
msg_clone(msg, orq->orq_request);
|
|
|
|
/* Copy the SIP headers from the old message */
|
|
if (sip_copy_all(msg, sip, sip_object(orq->orq_request)) >= 0)
|
|
return msg;
|
|
|
|
msg_destroy(msg);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**Get latest response message.
|
|
*
|
|
* The function nta_outgoing_getresponse() retrieves the latest incoming
|
|
* response message to the outgoing transaction. Note that the message is
|
|
* not copied, but removed from the transaction.
|
|
*
|
|
* @param orq outgoing transaction handle
|
|
*
|
|
* @retval
|
|
* A pointer to response message is returned, or NULL if no response message
|
|
* has been received or the response message has already been retrieved.
|
|
*/
|
|
msg_t *nta_outgoing_getresponse(nta_outgoing_t *orq)
|
|
{
|
|
msg_t *msg = NULL;
|
|
|
|
if (orq && orq->orq_response)
|
|
msg = orq->orq_response, orq->orq_response = NULL;
|
|
|
|
return msg;
|
|
}
|
|
#endif
|
|
|
|
/** Create an outgoing request belonging to the leg.
|
|
*
|
|
* The function nta_outgoing_create() creates an outgoing transaction and
|
|
* sends the request. The request is sent to the @a route_url (if
|
|
* non-NULL), default proxy (as specified by nta_agent_set_proxy()), or to
|
|
* the address specified by @a request_uri. In the latest case, all the
|
|
* tranport parameters are stripped from the request_uri. If no @a
|
|
* request_uri is specified, it is taken from the @To header.
|
|
*
|
|
* When NTA receives response to the request, it invokes the @c callback
|
|
* function.
|
|
*
|
|
* @param leg call leg object
|
|
* @param callback callback function (may be @c NULL)
|
|
* @param magic application context pointer
|
|
* @param route_url URL used to route transaction requests
|
|
* @param method method type
|
|
* @param name method name
|
|
* @param request_uri Request-URI
|
|
* @param extra, ... list of extra headers
|
|
*
|
|
* @return
|
|
* The function nta_outgoing_create() returns a pointer to newly created
|
|
* outgoing transaction object if successful, and NULL otherwise.
|
|
*
|
|
* @deprecated
|
|
* Use nta_outgoing_tcreate() or nta_outgoing_mcreate() instead.
|
|
*/
|
|
nta_outgoing_t *nta_outgoing_create(nta_leg_t *leg,
|
|
nta_response_f *callback,
|
|
nta_outgoing_magic_t *magic,
|
|
url_string_t const *route_url,
|
|
sip_method_t method,
|
|
char const *name,
|
|
url_string_t const *request_uri,
|
|
void const *extra, ...)
|
|
{
|
|
nta_outgoing_t *orq;
|
|
va_list headers;
|
|
|
|
va_start(headers, extra);
|
|
orq = nta_outgoing_vcreate(leg, callback, magic,
|
|
route_url, method, name, request_uri,
|
|
extra, headers);
|
|
va_end(headers);
|
|
return orq;
|
|
}
|
|
|
|
/**Create a request belonging to the leg
|
|
* (stdarg version of nta_outgoing_create()).
|
|
*
|
|
* @deprecated
|
|
* Use nta_outgoing_tcreate() or nta_outgoing_mcreate() instead.
|
|
*/
|
|
nta_outgoing_t *nta_outgoing_vcreate(nta_leg_t *leg,
|
|
nta_response_f *callback,
|
|
nta_outgoing_magic_t *magic,
|
|
url_string_t const *route_url,
|
|
sip_method_t method,
|
|
char const *name,
|
|
url_string_t const *request_uri,
|
|
void const *extra,
|
|
va_list headers)
|
|
{
|
|
nta_agent_t *agent = leg->leg_agent;
|
|
msg_t *msg = nta_msg_create(agent, 0);
|
|
sip_t *sip = sip_object(msg);
|
|
nta_outgoing_t *orq;
|
|
|
|
if (extra &&
|
|
sip_add_headers(msg, sip, extra, headers) < 0)
|
|
orq = NULL;
|
|
else if (route_url && leg->leg_route && !sip->sip_route &&
|
|
sip_add_dup(msg, sip, (sip_header_t *)leg->leg_route) < 0)
|
|
orq = NULL;
|
|
else if (nta_msg_request_complete(msg, leg, method, name, request_uri) < 0)
|
|
orq = NULL;
|
|
else
|
|
orq = nta_outgoing_mcreate(agent, callback, magic, route_url, msg);
|
|
|
|
if (!orq)
|
|
msg_destroy(msg);
|
|
|
|
return orq;
|
|
}
|
|
|
|
/**Forward a request.
|
|
*
|
|
* @deprecated
|
|
* Use nta_outgoing_mcreate() instead.
|
|
*/
|
|
nta_outgoing_t *nta_outgoing_tclone(nta_agent_t *agent,
|
|
nta_response_f *callback,
|
|
nta_outgoing_magic_t *magic,
|
|
url_string_t const *route_url,
|
|
msg_t *parent,
|
|
tag_type_t tag, tag_value_t value, ...)
|
|
{
|
|
ta_list ta;
|
|
msg_t *msg;
|
|
nta_outgoing_t *orq = NULL;
|
|
|
|
if (parent == NULL)
|
|
return NULL;
|
|
if ((msg = nta_msg_create(agent, 0)) == NULL)
|
|
return NULL;
|
|
|
|
ta_start(ta, tag, value);
|
|
|
|
msg_clone(msg, parent);
|
|
|
|
if (parent && sip_copy_all(msg, sip_object(msg), sip_object(parent)) < 0)
|
|
;
|
|
else if (sip_add_tl(msg, sip_object(msg), ta_tags(ta)) < 0)
|
|
;
|
|
else
|
|
orq = nta_outgoing_mcreate(agent, callback, magic, route_url, msg);
|
|
|
|
ta_end(ta);
|
|
|
|
if (!orq)
|
|
msg_destroy(msg);
|
|
|
|
return orq;
|
|
|
|
}
|
|
|
|
/** Forward a request belonging to the leg.
|
|
*
|
|
* The function nta_outgoing_forward() will create an outgoing transaction
|
|
* based on the incoming transaction. The forwarded message is specified by
|
|
* @a isip parameter. The caller rewrite the URL by giving non-NULL @a
|
|
* request_url.
|
|
*
|
|
* The request is sent to the server specified by @a route_url if it is
|
|
* non-NULL.
|
|
*
|
|
* @deprecated
|
|
* Use nta_outgoing_mcreate() instead.
|
|
*/
|
|
nta_outgoing_t *nta_outgoing_forward(nta_leg_t *leg,
|
|
nta_response_f *callback,
|
|
nta_outgoing_magic_t *magic,
|
|
url_string_t const *route_url,
|
|
url_string_t const *request_uri,
|
|
nta_incoming_t *ireq,
|
|
sip_t const *isip,
|
|
void const *extra, ...)
|
|
{
|
|
nta_outgoing_t *orq;
|
|
va_list headers;
|
|
|
|
va_start(headers, extra);
|
|
orq = nta_outgoing_vforward(leg, callback, magic, route_url, request_uri,
|
|
ireq, isip, extra, headers);
|
|
va_end(headers);
|
|
return orq;
|
|
}
|
|
|
|
/**Forward a request belonging to the leg
|
|
* (stdarg version of nta_outgoing_forward()).
|
|
*
|
|
* @deprecated
|
|
* Use nta_outgoing_mcreate() instead.
|
|
*/
|
|
nta_outgoing_t *nta_outgoing_vforward(nta_leg_t *leg,
|
|
nta_response_f *callback,
|
|
nta_outgoing_magic_t *magic,
|
|
url_string_t const *route_url,
|
|
url_string_t const *request_uri,
|
|
nta_incoming_t const *ireq,
|
|
sip_t const *isip,
|
|
void const *extra,
|
|
va_list headers)
|
|
{
|
|
nta_agent_t *agent = leg->leg_agent;
|
|
nta_outgoing_t *orq = NULL;
|
|
msg_t *msg, *imsg;
|
|
sip_t *sip;
|
|
su_home_t *home;
|
|
|
|
assert(leg); assert(ireq);
|
|
|
|
if (isip == NULL)
|
|
imsg = ireq->irq_request, isip = sip_object(ireq->irq_request);
|
|
else if (isip == sip_object(ireq->irq_request))
|
|
imsg = ireq->irq_request;
|
|
else if (isip == sip_object(ireq->irq_request2))
|
|
imsg = ireq->irq_request2;
|
|
else {
|
|
SU_DEBUG_3(("nta_outgoing_forward: invalid arguments\n"));
|
|
return NULL;
|
|
}
|
|
|
|
assert(isip); assert(isip->sip_request);
|
|
|
|
if (!route_url)
|
|
route_url = (url_string_t *)agent->sa_default_proxy;
|
|
|
|
if (!(msg = nta_msg_create(agent, 0)))
|
|
return NULL;
|
|
|
|
msg_clone(msg, imsg);
|
|
|
|
sip = sip_object(msg);
|
|
home = msg_home(msg);
|
|
|
|
/* Copy the SIP headers from the @c imsg message */
|
|
do {
|
|
if (sip_copy_all(msg, sip, isip) < 0)
|
|
break;
|
|
if (sip_add_headers(msg, sip, extra, headers) < 0)
|
|
break;
|
|
if (!route_url && sip->sip_route) {
|
|
request_uri = (url_string_t *)sip->sip_route->r_url;
|
|
if (!sip_route_remove(msg, sip))
|
|
break;
|
|
}
|
|
if (request_uri) {
|
|
sip_request_t *rq;
|
|
|
|
rq = sip_request_create(home,
|
|
sip->sip_request->rq_method,
|
|
sip->sip_request->rq_method_name,
|
|
request_uri,
|
|
NULL);
|
|
|
|
if (!rq || sip_header_insert(msg, sip, (sip_header_t *)rq) < 0)
|
|
break;
|
|
}
|
|
|
|
if ((orq = nta_outgoing_mcreate(agent, callback, magic, route_url, msg)))
|
|
return orq;
|
|
|
|
} while (0);
|
|
|
|
msg_destroy(msg);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/** Fork an outgoing request toward another destination.
|
|
*
|
|
* @deprecated
|
|
* Use nta_outgoing_mcreate() instead.
|
|
*/
|
|
nta_outgoing_t *nta_outgoing_fork(nta_outgoing_t *old_orq,
|
|
nta_response_f *callback,
|
|
nta_outgoing_magic_t *magic,
|
|
url_string_t const *route_url,
|
|
url_string_t const *request_uri,
|
|
void const *extra, ...)
|
|
{
|
|
nta_outgoing_t *orq;
|
|
va_list headers;
|
|
|
|
va_start(headers, extra);
|
|
orq = nta_outgoing_vfork(old_orq, callback, magic, route_url,
|
|
request_uri, extra, headers);
|
|
va_end(headers);
|
|
return orq;
|
|
}
|
|
|
|
/** Fork an outgoing request (stdarg version of nta_outgoing_fork()).
|
|
*
|
|
* @deprecated
|
|
* Use nta_outgoing_mcreate() instead.
|
|
*/
|
|
nta_outgoing_t *nta_outgoing_vfork(nta_outgoing_t *old_orq,
|
|
nta_response_f *callback,
|
|
nta_outgoing_magic_t *magic,
|
|
url_string_t const *route_url,
|
|
url_string_t const *request_uri,
|
|
void const *extra,
|
|
va_list headers)
|
|
{
|
|
nta_outgoing_t * orq;
|
|
msg_t *msg, *imsg;
|
|
sip_t *sip, *isip;
|
|
nta_agent_t *agent;
|
|
su_home_t *home;
|
|
|
|
if (!old_orq || !old_orq->orq_request || !request_uri)
|
|
return NULL;
|
|
|
|
agent = old_orq->orq_agent;
|
|
imsg = old_orq->orq_request;
|
|
|
|
if (!(msg = nta_msg_create(agent, 0)))
|
|
return NULL;
|
|
|
|
msg_clone(msg, imsg);
|
|
|
|
sip = sip_object(msg); isip = sip_object(imsg);
|
|
home = msg_home(msg);
|
|
|
|
/* Copy the SIP headers from the imsg message */
|
|
if (sip_copy_all(msg, sip, isip) < 0)
|
|
orq = NULL;
|
|
else if (sip_via_remove(msg, sip) == NULL)
|
|
orq = NULL;
|
|
else if (sip_add_dup(msg, sip_object(msg),
|
|
(sip_header_t const *)
|
|
sip_request_create(home,
|
|
sip->sip_request->rq_method,
|
|
sip->sip_request->rq_method_name,
|
|
request_uri,
|
|
NULL)) < 0)
|
|
orq = NULL;
|
|
else if (sip_add_headers(msg, sip, extra, headers) < 0)
|
|
orq = NULL;
|
|
else
|
|
orq = nta_outgoing_mcreate(agent, callback, magic, route_url, msg);
|
|
|
|
if (!orq)
|
|
msg_destroy(msg);
|
|
|
|
return orq;
|
|
}
|
|
|
|
/**
|
|
* Reply to an incoming transaction request.
|
|
*
|
|
* This function creates and sends a response message to an incoming request.
|
|
* It is possible to send several non-final (1xx) responses, but only one
|
|
* final response.
|
|
*
|
|
* @param irq incoming request
|
|
* @param status status code
|
|
* @param phrase status phrase (may be NULL if status code is well-known)
|
|
* @param extra, ... optional additional headers terminated by NULL
|
|
*
|
|
* @deprecated
|
|
* Use nta_incoming_treply() instead.
|
|
*/
|
|
int nta_incoming_reply(nta_incoming_t *irq,
|
|
int status,
|
|
char const *phrase,
|
|
void const *extra,
|
|
...)
|
|
{
|
|
int retval;
|
|
va_list headers;
|
|
va_start(headers, extra);
|
|
retval = nta_incoming_vreply(irq, status, phrase, extra, headers);
|
|
va_end(headers);
|
|
return retval;
|
|
}
|
|
|
|
/**Reply to an incoming transaction request (stdarg version).
|
|
*
|
|
* @deprecated
|
|
* Use nta_incoming_treply() instead.
|
|
*/
|
|
int nta_incoming_vreply(nta_incoming_t *irq,
|
|
int status,
|
|
char const *phrase,
|
|
void const *extra, va_list headers)
|
|
{
|
|
if (irq->irq_status < 200 || status < 200 ||
|
|
(irq->irq_method == sip_method_invite && status < 300)) {
|
|
msg_t *msg = nta_msg_create(irq->irq_agent, 0);
|
|
sip_t *sip = sip_object(msg);
|
|
|
|
if (!msg)
|
|
return -1;
|
|
else if (nta_msg_response_complete(msg, irq, status, phrase) < 0)
|
|
msg_destroy(msg);
|
|
else if (sip_add_headers(msg, sip, extra, headers) < 0 )
|
|
msg_destroy(msg);
|
|
else if (sip_message_complete(msg) < 0)
|
|
msg_destroy(msg);
|
|
else if (nta_incoming_mreply(irq, msg) < 0)
|
|
msg_destroy(msg);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/**
|
|
* Forward a response to incoming transaction.
|
|
*
|
|
* This function forwards a response message from outgoing request to an
|
|
* incoming request. It copies the message save the first via field, and
|
|
* send the response message to the address specified in the second via.
|
|
*
|
|
* It is possible to send several non-final (1xx) responses, but only one
|
|
* final response.
|
|
*
|
|
* @param irq incoming request
|
|
* @param orq
|
|
* @param sip message structure for outgoing transaction
|
|
* @param extra, ... list of optional additional headers terminated by NULL
|
|
*
|
|
* @bug Adding extra headers is unimplemented.
|
|
*
|
|
* @deprecated Use nta_incoming_mreply() instead.
|
|
*/
|
|
int nta_incoming_forward(nta_incoming_t *irq,
|
|
nta_outgoing_t *orq,
|
|
sip_t const *sip,
|
|
void const *extra, ...)
|
|
{
|
|
msg_t *msg = nta_outgoing_response(orq);
|
|
int status;
|
|
|
|
if (irq == NULL || sip == NULL || msg == NULL || sip != sip_object(msg))
|
|
return -1;
|
|
|
|
status = sip->sip_status->st_status;
|
|
|
|
sip_via_remove(msg, (sip_t *)sip); /* Remove topmost via */
|
|
|
|
if (sip_message_complete(msg) < 0)
|
|
msg_destroy(msg);
|
|
if (nta_incoming_mreply(irq, msg) < 0)
|
|
msg_destroy(msg);
|
|
else
|
|
return 0;
|
|
|
|
return -1;
|
|
}
|
|
|
|
/** Send a BYE to an INVITE.
|
|
*
|
|
* @deprecated
|
|
* This function should used only if application requires
|
|
* RFC2543 compatibility.
|
|
*/
|
|
nta_outgoing_t *nta_outgoing_tbye(nta_outgoing_t *orq,
|
|
nta_response_f *callback,
|
|
nta_outgoing_magic_t *magic,
|
|
url_string_t const *route_url,
|
|
tag_type_t tag, tag_value_t value, ...)
|
|
{
|
|
msg_t *msg;
|
|
sip_t *sip, *inv;
|
|
sip_cseq_t *cs;
|
|
sip_request_t *rq;
|
|
su_home_t *home;
|
|
url_string_t *url;
|
|
|
|
if (orq == NULL || orq->orq_method != sip_method_invite)
|
|
return NULL;
|
|
|
|
inv = sip_object(orq->orq_request);
|
|
msg = nta_msg_create(orq->orq_agent, 0);
|
|
home = msg_home(msg);
|
|
sip = sip_object(msg);
|
|
|
|
if (inv == NULL || sip == NULL) {
|
|
msg_destroy(msg);
|
|
return NULL;
|
|
}
|
|
|
|
sip_add_tl(msg, sip,
|
|
SIPTAG_TO(inv->sip_to),
|
|
SIPTAG_FROM(inv->sip_from),
|
|
SIPTAG_CALL_ID(inv->sip_call_id),
|
|
SIPTAG_ROUTE(inv->sip_route),
|
|
TAG_END());
|
|
|
|
url = (url_string_t *)inv->sip_request->rq_url;
|
|
|
|
rq = sip_request_create(home, SIP_METHOD_BYE, url, NULL);
|
|
sip_header_insert(msg, sip, (sip_header_t*)rq);
|
|
|
|
cs = sip_cseq_create(home, inv->sip_cseq->cs_seq + 1, SIP_METHOD_BYE);
|
|
sip_header_insert(msg, sip, (sip_header_t*)cs);
|
|
|
|
return nta_outgoing_mcreate(orq->orq_agent, callback, magic,
|
|
route_url, msg);
|
|
}
|