Skip to content

Commit

Permalink
Add support of out-of-dialog SIP transactions
Browse files Browse the repository at this point in the history
This commit adds support of out-of-dialog transactions to
PJSUA and PJSUA2. The requests are sent in the context of an account.
The API is similar to that of an in-dialog transaction.
  • Loading branch information
wosrediinanatour committed Nov 13, 2024
1 parent 0c6b9fb commit 3dd9625
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 1 deletion.
32 changes: 32 additions & 0 deletions pjsip/include/pjsua-lib/pjsua.h
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,19 @@ typedef struct pjsua_callback
pjsip_transaction *tsx,
pjsip_event *e);

/**
* This is a general notification callback which is called whenever
* a transaction within the account has changed state. Application can
* implement this callback for example to monitor the state of
* outgoing requests, or to answer unhandled incoming requests
* with a final response.
*
* @param acc_id Account identification.
* @param e Transaction event that caused the state change.
*/
void (*on_acc_tsx_state)(pjsua_acc_id acc_id,
pjsip_event *event);

/**
* Notify application when media state in the call has changed.
* Normal application would need to implement this callback, e.g.
Expand Down Expand Up @@ -4921,6 +4934,25 @@ PJ_DECL(pj_status_t) pjsua_acc_get_config(pjsua_acc_id acc_id,
PJ_DECL(pj_status_t) pjsua_acc_modify(pjsua_acc_id acc_id,
const pjsua_acc_config *acc_cfg);

/**
* Send arbitrary requests using the account. Application should only use
* this function to create auxiliary requests outside dialog, such as
* OPTIONS, and use the call or presence API to create dialog related
* requests.
*
* @param acc_id The account ID.
* @param dst_uri URI to be put in the To header (normally is the same
* as the target URI).
* @param method The SIP method of the request.
* @param msg_data Optional headers etc to be added to outgoing
* request, or NULL if no custom header is desired.
*
* @return PJ_SUCCESS or the error code.
*/
PJ_DECL(pj_status_t) pjsua_acc_send_request(pjsua_acc_id acc_id,
const pj_str_t *dest_uri,
const pj_str_t *method_str,
const pjsua_msg_data *msg_data);

/**
* Modify account's presence status to be advertised to remote/presence
Expand Down
59 changes: 59 additions & 0 deletions pjsip/include/pjsua2/account.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,31 @@ struct AccountNatConfig : public PersistentObject
virtual void writeObject(ContainerNode &node) const PJSUA2_THROW(Error);
};

/**
* This structure contains parameters for Account::sendRequest()
*/
struct SendRequestParam
{
/**
* SIP method of the request.
*/
string method;

/**
* Message body and/or list of headers etc to be included in
* outgoing request.
*/
SipTxOption txOption;

public:
/**
* Default constructor initializes with zero/empty values.
*/
SendRequestParam();
};



/**
* SRTP crypto.
*/
Expand Down Expand Up @@ -1725,6 +1750,18 @@ struct OnMwiInfoParam
SipRxData rdata;
};

/**
* This structure contains parameters for Account::onTsxState() callback.
*/
struct OnTsxStateParam
{
/**
* Transaction event that caused the state change.
*/
SipEvent e;
};


/**
* Parameters for presNotify() account method.
*/
Expand Down Expand Up @@ -1901,6 +1938,18 @@ class Account
*/
AccountInfo getInfo() const PJSUA2_THROW(Error);

/**
* Send arbitrary requests using the account. Application should only use
* this function to create auxiliary requests outside dialog, such as
* OPTIONS, and use the call or presence API to create dialog related
* requests.
*
* @param prm.method SIP method of the request.
* @param prm.txOption Optional message body and/or list of headers to be
* included in outgoing request.
*/
void sendRequest(const pj::SendRequestParam& prm) PJSUA2_THROW(Error);

/**
* Update registration or perform unregistration. Application normally
* only needs to call this function if it wants to manually update the
Expand Down Expand Up @@ -2082,6 +2131,16 @@ class Account
virtual void onInstantMessageStatus(OnInstantMessageStatusParam &prm)
{ PJ_UNUSED_ARG(prm); }

/**
* Notify application when call state has changed.
* Application may then query the account info to get the
* detail call states by calling getInfo() function.
*
* @param prm Callback parameter.
*/
virtual void onTsxState(OnTsxStateParam &prm)
{ PJ_UNUSED_ARG(prm); }

/**
* Notify application about typing indication.
*
Expand Down
1 change: 1 addition & 0 deletions pjsip/include/pjsua2/endpoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2023,6 +2023,7 @@ class Endpoint
pj_bool_t renew);
static void on_reg_state2(pjsua_acc_id acc_id,
pjsua_reg_info *info);
static void on_acc_tsx_state(pjsua_acc_id acc_id, pjsip_event *event);
static void on_incoming_subscribe(pjsua_acc_id acc_id,
pjsua_srv_pres *srv_pres,
pjsua_buddy_id buddy_id,
Expand Down
2 changes: 1 addition & 1 deletion pjsip/src/pjsip/sip_transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

#define THIS_FILE "sip_transaction.c"

#if 0
#if 1
#define TSX_TRACE_(expr) PJ_LOG(3,expr)
#else
#define TSX_TRACE_(expr)
Expand Down
52 changes: 52 additions & 0 deletions pjsip/src/pjsua-lib/pjsua_acc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1510,6 +1510,58 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id,
return status;
}

static void on_acc_tsx_state(void *token, pjsip_event *event)
{
pjsua_acc_id acc_id = *(pjsua_acc_id*)token;
(pjsua_var.ua_cfg.cb.on_acc_tsx_state)(acc_id, event);
}

PJ_DEF(pj_status_t) pjsua_acc_send_request(pjsua_acc_id acc_id,
const pj_str_t *dest_uri,
const pj_str_t *method_str,
const pjsua_msg_data *msg_data)
{
const pjsip_hdr *cap_hdr;
pjsip_method method;
pj_status_t status;
pjsip_tx_data *tdata = NULL;
pjsua_acc_id *token = NULL;

PJ_ASSERT_RETURN(acc_id>=0, PJ_EINVAL);

PJ_LOG(4,(THIS_FILE, "Account %d sending %.*s request..",
acc_id, (int)method_str->slen, method_str->ptr));
pj_log_push_indent();

pjsip_method_init_np(&method, (pj_str_t*)method_str);
status = pjsua_acc_create_request(acc_id, &method, &msg_data->target_uri, &tdata);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to create request", status);
goto on_return;
}

token = PJ_POOL_ZALLOC_T(tdata->pool, pjsua_acc_id);
*token = acc_id;

pjsua_process_msg_data(tdata, msg_data);

cap_hdr = pjsip_endpt_get_capability(pjsua_var.endpt, PJSIP_H_ACCEPT, NULL);
if (cap_hdr) {
pjsip_msg_add_hdr(tdata->msg,
(pjsip_hdr*) pjsip_hdr_clone(tdata->pool, cap_hdr));
}

status = pjsip_endpt_send_request(pjsua_var.endpt, tdata, -1, token, &on_acc_tsx_state);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to send request", status);
goto on_return;
}

on_return:
pj_log_pop_indent();
return status;
}


/*
* Modify account's presence status to be advertised to remote/presence
Expand Down
19 changes: 19 additions & 0 deletions pjsip/src/pjsua2/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
using namespace pj;
using namespace std;

#include <pjsua-lib/pjsua_internal.h> /* For retrieving pjsua threads */

#define THIS_FILE "account.cpp"

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -117,6 +119,13 @@ void RtcpFbConfig::writeObject(ContainerNode &node) const PJSUA2_THROW(Error)

///////////////////////////////////////////////////////////////////////////////

SendRequestParam::SendRequestParam()
: method("")
{
}

///////////////////////////////////////////////////////////////////////////////

void SrtpCrypto::fromPj(const pjmedia_srtp_crypto &prm)
{
this->key = pj2Str(prm.key);
Expand Down Expand Up @@ -1062,6 +1071,16 @@ AccountInfo Account::getInfo() const PJSUA2_THROW(Error)
return ai;
}

void Account::sendRequest(const pj::SendRequestParam& prm) PJSUA2_THROW(Error)
{
pj_str_t method = str2Pj(prm.method);
pj_str_t dest_uri = str2Pj(prm.txOption.targetUri);
pjsua_msg_data msg_data;
prm.txOption.toPj(msg_data);

PJSUA2_CHECK_EXPR(pjsua_acc_send_request(id, &dest_uri, &method, &msg_data));
}

void Account::setRegistration(bool renew) PJSUA2_THROW(Error)
{
PJSUA2_CHECK_EXPR( pjsua_acc_set_registration(id, renew) );
Expand Down
14 changes: 14 additions & 0 deletions pjsip/src/pjsua2/endpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,19 @@ void Endpoint::on_reg_state2(pjsua_acc_id acc_id, pjsua_reg_info *info)
acc->onRegState(prm);
}

void Endpoint::on_acc_tsx_state(pjsua_acc_id acc_id, pjsip_event *event)
{
Account *acc = lookupAcc(acc_id, "on_acc_tsx_state:response()");
if (!acc) {
return;
}

OnTsxStateParam prm;
prm.e.fromPj(*event);

acc->onTsxState(prm);
}

void Endpoint::on_incoming_subscribe(pjsua_acc_id acc_id,
pjsua_srv_pres *srv_pres,
pjsua_buddy_id buddy_id,
Expand Down Expand Up @@ -1926,6 +1939,7 @@ void Endpoint::libInit(const EpConfig &prmEpConfig) PJSUA2_THROW(Error)
ua_cfg.cb.on_nat_detect = &Endpoint::on_nat_detect;
ua_cfg.cb.on_transport_state = &Endpoint::on_transport_state;

ua_cfg.cb.on_acc_tsx_state = &Endpoint::on_acc_tsx_state;
ua_cfg.cb.on_incoming_call = &Endpoint::on_incoming_call;
ua_cfg.cb.on_reg_started = &Endpoint::on_reg_started;
ua_cfg.cb.on_reg_state2 = &Endpoint::on_reg_state2;
Expand Down

0 comments on commit 3dd9625

Please sign in to comment.