Skip to content

Commit 40f6c97

Browse files
Defer response for incoming SIP MESSAGE requests (#4598)
1 parent 9cc0309 commit 40f6c97

File tree

11 files changed

+696
-50
lines changed

11 files changed

+696
-50
lines changed

pjsip-apps/build/Samples.mak

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ SAMPLES := auddemo \
4848
vid_codec_test \
4949
vid_streamutil
5050

51-
PJSUA2_SAMPLES := pjsua2_demo \
52-
pjsua2_hello_reg
51+
PJSUA2_SAMPLES = pjsua2_demo pjsua2_hello_reg
5352

5453
ifeq ($(EXCLUDE_APP),0)
5554
EXES := $(foreach file, $(SAMPLES), $(file)$(HOST_EXE))

pjsip/build/Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ export PJSUA2_LIB_LDFLAGS += $(PJSUA_LIB_LDLIB) \
161161
#
162162
export PJSUA2_TEST_SRCDIR = ../src/pjsua2-test
163163
export PJSUA2_TEST_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
164-
main.o
164+
main.o instant_messaging.o
165165
export PJSUA2_TEST_CFLAGS += $(_CFLAGS) $(PJ_VIDEO_CFLAGS)
166166
export PJSUA2_TEST_CXXFLAGS = $(_CXXFLAGS) $(PJSUA2_LIB_CFLAGS) $(PJ_VIDEO_CFLAGS)
167167
export PJSUA2_TEST_LDFLAGS += $(PJ_LDXXFLAGS) $(PJ_LDXXLIBS) $(LDFLAGS)
@@ -170,7 +170,6 @@ export PJSUA2_TEST_EXE := pjsua2-test-$(TARGET_NAME)$(HOST_EXE)
170170
endif
171171
export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT
172172

173-
174173
###############################################################################
175174
# Defines for building test application
176175
#

pjsip/include/pjsua-lib/pjsua.h

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4782,6 +4782,28 @@ typedef struct pjsua_acc_config
47824782
*/
47834783
pj_bool_t use_shared_auth;
47844784

4785+
/**
4786+
* Specify whether incoming SIP MESSAGE requests are responded
4787+
* automatically.
4788+
*
4789+
* If set to PJ_TRUE (automatic response), incoming MESSAGE requests
4790+
* will be responded to immediately with SIP 200 OK (legacy behavior).
4791+
*
4792+
* If set to PJ_FALSE, incoming MESSAGE requests will create UAS
4793+
* transactions supporting explicit responses and defering responses.
4794+
*
4795+
* The application may either respond immediately in the on_pager() or
4796+
* on_pager2() callbacks by using pjsua_acc_send_response(), or defer the
4797+
* response to later time. In the latter case, the application must clone the
4798+
* rx_data by calling pjsip_rx_data_clone() within on_pager() or on_pager2()
4799+
* callbacks. The cloned rx_data and the pointer to the transaction can then
4800+
* be used later for pjsua_acc_send_response().
4801+
*
4802+
* Default: PJ_TRUE (automatic response for backward compatibility)
4803+
*/
4804+
pj_bool_t auto_repond_sip_message;
4805+
4806+
47854807
} pjsua_acc_config;
47864808

47874809

@@ -5116,6 +5138,34 @@ PJ_DECL(pj_status_t) pjsua_acc_get_config(pjsua_acc_id acc_id,
51165138
PJ_DECL(pj_status_t) pjsua_acc_modify(pjsua_acc_id acc_id,
51175139
const pjsua_acc_config *acc_cfg);
51185140

5141+
/**
5142+
* Send response to incoming request (e.g. SIP MESSAGE) that was
5143+
* processed by a UAS transaction.
5144+
*
5145+
* This function can be used when the application wants to defer a
5146+
* response to an incoming request that was processed by
5147+
* a UAS transaction.
5148+
*
5149+
* @param acc_id The account that will send the response.
5150+
* @param rdata The received request data.
5151+
* @param tsx The UAS transaction that was created for the incoming
5152+
* request.
5153+
* @param st_code Status code to be sent (e.g., 200 for OK, 400 for
5154+
* Bad Request, etc.).
5155+
* @param st_text Optional status text. If NULL, default status text for
5156+
* the status code will be used.
5157+
* @param msg_data Optional headers etc. to be added to the outgoing
5158+
* response, or NULL if no custom header is desired.
5159+
*
5160+
* @return PJ_SUCCESS on success, or the appropriate error code.
5161+
*/
5162+
PJ_DECL(pj_status_t) pjsua_acc_send_response(pjsua_acc_id acc_id,
5163+
pjsip_rx_data *rdata,
5164+
pjsip_transaction *tsx,
5165+
int st_code,
5166+
const pj_str_t *st_text,
5167+
const pjsua_msg_data *msg_data);
5168+
51195169
/**
51205170
* Send arbitrary out-of-dialog requests from an account, e.g. OPTIONS.
51215171
* The application should use the call or presence API to create
@@ -5125,7 +5175,8 @@ PJ_DECL(pj_status_t) pjsua_acc_modify(pjsua_acc_id acc_id,
51255175
* @param dest_uri URI to be put into the To header (normally is the same
51265176
* as the target URI).
51275177
* @param method The SIP method of the request.
5128-
* @param options This is for future use (currently only NULL is supported).
5178+
* @param options This is for future use (currently only NULL is
5179+
* supported).
51295180
* @param token Arbitrary token (user data owned by the application)
51305181
* to be passed back to the application in callback
51315182
* on_acc_send_request().
@@ -7284,7 +7335,6 @@ PJ_DECL(pj_status_t) pjsua_im_typing(pjsua_acc_id acc_id,
72847335
const pjsua_msg_data *msg_data);
72857336

72867337

7287-
72887338
/**
72897339
* @}
72907340
*/

pjsip/include/pjsua2/account.hpp

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,17 @@ struct AccountSipConfig : public PersistentObject
311311
*/
312312
bool useSharedAuth;
313313

314+
/**
315+
* Configure automatic SIP-MESSAGE processing behavior for this account.
316+
* When set to true, incoming SIP MESSAGE requests will be responded to
317+
* immediately with a 200 OK response (legacy behavior). When set to false,
318+
* incoming SIP MESSAGE requests will create UAS transactions allowing for
319+
* deferred responses, cf. Account::sendResponse() and DeferredResponse.
320+
*
321+
* Default: true (automatic response for backward compatibility)
322+
*/
323+
bool autoRespondSipMessage;
324+
314325
public:
315326
/**
316327
* Read this object from a container node.
@@ -860,8 +871,6 @@ struct SendRequestParam
860871
SendRequestParam();
861872
};
862873

863-
864-
865874
/**
866875
* SRTP crypto.
867876
*/
@@ -1931,6 +1940,86 @@ class FindBuddyMatch
19311940
virtual ~FindBuddyMatch() {}
19321941
};
19331942

1943+
/**
1944+
* This class is used to store the received parsed SIP MESSAGE request and
1945+
* its transaction for use in sendResponse().
1946+
*/
1947+
class DeferredResponse
1948+
{
1949+
friend class Account;
1950+
public:
1951+
/**
1952+
* Constructor that clones the rx_data and keeps a non-owning pointer
1953+
* to the transaction.
1954+
* @param param The instant message parameters from the callback.
1955+
*/
1956+
explicit
1957+
DeferredResponse(const OnInstantMessageParam& param) PJSUA2_THROW(Error);
1958+
1959+
/**
1960+
* Constructs an empty object. Must be assigned to before use.
1961+
*/
1962+
DeferredResponse();
1963+
1964+
/**
1965+
* Copies the deferred response object by cloning the rx_data.
1966+
*/
1967+
DeferredResponse(const DeferredResponse& deferredResponse)
1968+
PJSUA2_THROW(Error);
1969+
1970+
/**
1971+
* Copies the deferred response object by cloning the rx_data.
1972+
*/
1973+
DeferredResponse& operator=(const DeferredResponse& deferredResponse)
1974+
PJSUA2_THROW(Error);
1975+
1976+
/**
1977+
* Moves the deferred response object.
1978+
*/
1979+
DeferredResponse(DeferredResponse&& deferredResponse) noexcept;
1980+
1981+
/**
1982+
* Moves the deferred response object.
1983+
*/
1984+
DeferredResponse& operator=(DeferredResponse&& deferredResponse) noexcept;
1985+
1986+
/**
1987+
* Destructor that frees possible cloned rx_data.
1988+
*/
1989+
virtual ~DeferredResponse();
1990+
1991+
private:
1992+
/**
1993+
* Non-owning pointer to the registered transaction.
1994+
*/
1995+
pjsip_transaction* transaction;
1996+
1997+
/**
1998+
* Owning pointer to the cloned rx_data.
1999+
*/
2000+
pjsip_rx_data* data = nullptr;
2001+
};
2002+
2003+
/**
2004+
* Parameters for Account::sendResponse().
2005+
*/
2006+
struct SendResponseParam
2007+
{
2008+
/**
2009+
* Deferred response object, which is valid until the response is sent.
2010+
*/
2011+
DeferredResponse deferredResponse;
2012+
2013+
/**
2014+
* Status code of the response.
2015+
*/
2016+
int code;
2017+
2018+
/**
2019+
* Optional reason phrase of the response.
2020+
*/
2021+
string reason;
2022+
};
19342023

19352024
/**
19362025
* Account.
@@ -2052,6 +2141,19 @@ class Account
20522141
*/
20532142
void sendRequest(const pj::SendRequestParam& prm) PJSUA2_THROW(Error);
20542143

2144+
/**
2145+
* Send response for incoming request that was deferred earlier
2146+
* using DeferredResponse object.
2147+
*
2148+
* @param prm The response's parameters.
2149+
* @param prm.deferredResponse The deferred response object
2150+
* identifying the incoming request to
2151+
* respond to.
2152+
* @param prm.code The status code of the response.
2153+
* @param prm.reason Optional reason phrase of the response.
2154+
*/
2155+
void sendResponse(const pj::SendResponseParam& prm) PJSUA2_THROW(Error);
2156+
20552157
/**
20562158
* Update registration or perform unregistration. Application normally
20572159
* only needs to call this function if it wants to manually update the

pjsip/src/pjsua-lib/pjsua_acc.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4751,3 +4751,55 @@ void pjsua_acc_end_ip_change(pjsua_acc *acc)
47514751
}
47524752
PJSUA_UNLOCK();
47534753
}
4754+
4755+
/*
4756+
* Send response to incoming SIP MESSAGE request.
4757+
*/
4758+
PJ_DEF(pj_status_t) pjsua_acc_send_response(pjsua_acc_id acc_id,
4759+
pjsip_rx_data *rdata,
4760+
pjsip_transaction *tsx,
4761+
int st_code,
4762+
const pj_str_t *st_text,
4763+
const pjsua_msg_data *msg_data)
4764+
{
4765+
pjsip_tx_data *tdata = NULL;
4766+
pj_status_t status;
4767+
4768+
PJ_ASSERT_RETURN(rdata != NULL, PJ_EINVAL);
4769+
PJ_ASSERT_RETURN(st_code >= 200 && st_code < 700, PJ_EINVAL);
4770+
PJ_UNUSED_ARG(acc_id);
4771+
4772+
if (!tsx) {
4773+
PJ_LOG(1,(THIS_FILE, "UAS transaction not found for MESSAGE response"));
4774+
return PJ_ENOTFOUND;
4775+
}
4776+
4777+
PJ_ASSERT_RETURN(tsx->role == PJSIP_ROLE_UAS, PJ_EINVAL);
4778+
PJ_ASSERT_RETURN(pjsip_method_cmp(&tsx->method, &pjsip_message_method) == 0,
4779+
PJ_EINVAL);
4780+
4781+
status = pjsip_endpt_create_response(pjsua_var.endpt, rdata,
4782+
st_code, st_text, &tdata);
4783+
if (status != PJ_SUCCESS) {
4784+
pjsua_perror(THIS_FILE, "Unable to create response", status);
4785+
return status;
4786+
}
4787+
4788+
if (msg_data) {
4789+
pjsip_hdr *hdr;
4790+
for (hdr = &msg_data->hdr_list; hdr && hdr != &msg_data->hdr_list;
4791+
hdr=hdr->next) {
4792+
pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(
4793+
tdata->pool, hdr));
4794+
}
4795+
}
4796+
4797+
status = pjsip_tsx_send_msg(tsx, tdata);
4798+
if (status != PJ_SUCCESS) {
4799+
pjsua_perror(THIS_FILE, "Unable to send response", status);
4800+
pjsip_tx_data_dec_ref(tdata);
4801+
return status;
4802+
}
4803+
4804+
return PJ_SUCCESS;
4805+
}

pjsip/src/pjsua-lib/pjsua_core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg)
398398
PJSUA_CALL_UPDATE_VIA;
399399
cfg->enable_rtcp_xr = (PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR);
400400
cfg->use_shared_auth = PJ_FALSE;
401+
402+
cfg->auto_repond_sip_message = PJ_TRUE;
401403
}
402404

403405
PJ_DEF(void) pjsua_buddy_config_default(pjsua_buddy_config *cfg)

0 commit comments

Comments
 (0)