summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-02-09 00:13:40 +0000
committerBenny Prijono <bennylp@teluu.com>2006-02-09 00:13:40 +0000
commit1a7571f62112ae25317663cba5df39c8ff1690c7 (patch)
tree4bb56c9bc0d9a941ef274a2545c83a5243821465
parent86871987528c71dfa0e666e663ed66f5eb776342 (diff)
Integration of pjmedia and pjsip error subsystem to pjlib
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@162 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/include/pjmedia.h4
-rw-r--r--pjmedia/include/pjmedia/errno.h19
-rw-r--r--pjmedia/include/pjmedia/session.h2
-rw-r--r--pjmedia/include/pjmedia/types.h3
-rw-r--r--pjmedia/src/pjmedia/endpoint.c32
-rw-r--r--pjmedia/src/pjmedia/errno.c21
-rw-r--r--pjmedia/src/pjmedia/sdp.c4
-rw-r--r--pjsip/include/pjsip/sip_errno.h18
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c61
-rw-r--r--pjsip/src/pjsip/sip_endpoint.c29
-rw-r--r--pjsip/src/pjsip/sip_resolve.c4
-rw-r--r--pjsip/src/pjsip/sip_transaction.c20
-rw-r--r--pjsip/src/pjsua/pjsua.h44
-rw-r--r--pjsip/src/pjsua/pjsua_core.c180
14 files changed, 307 insertions, 134 deletions
diff --git a/pjmedia/include/pjmedia.h b/pjmedia/include/pjmedia.h
index 7587b73e..2f160601 100644
--- a/pjmedia/include/pjmedia.h
+++ b/pjmedia/include/pjmedia.h
@@ -23,10 +23,10 @@
#include <pjmedia/errno.h>
#include <pjmedia/codec.h>
#include <pjmedia/jbuf.h>
-#include <pjmedia/mediamgr.h>
+#include <pjmedia/endpoint.h>
#include <pjmedia/rtcp.h>
#include <pjmedia/rtp.h>
-//#include <pjmedia/session.h>
+#include <pjmedia/session.h>
#include <pjmedia/sound.h>
#include <pjmedia/sdp.h>
#include <pjmedia/sdp_neg.h>
diff --git a/pjmedia/include/pjmedia/errno.h b/pjmedia/include/pjmedia/errno.h
index 8d1f6e14..d57a23b6 100644
--- a/pjmedia/include/pjmedia/errno.h
+++ b/pjmedia/include/pjmedia/errno.h
@@ -25,25 +25,6 @@ PJ_BEGIN_DECL
/**
- * Guidelines on error message length.
- */
-#define PJMEDIA_ERR_MSG_SIZE 64
-
-/**
- * Get error message for the specified error code.
- *
- * @param status The error code.
- * @param buffer The buffer where to put the error message.
- * @param bufsize Size of the buffer.
- *
- * @return The error message as NULL terminated string,
- * wrapped with pj_str_t.
- */
-PJ_DECL(pj_str_t) pjmedia_strerror( pj_status_t status, char *buffer,
- pj_size_t bufsize);
-
-
-/**
* Start of error code relative to PJ_ERRNO_START_USER.
*/
#define PJMEDIA_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE)
diff --git a/pjmedia/include/pjmedia/session.h b/pjmedia/include/pjmedia/session.h
index f6a9fc11..cbef4424 100644
--- a/pjmedia/include/pjmedia/session.h
+++ b/pjmedia/include/pjmedia/session.h
@@ -40,7 +40,7 @@ PJ_BEGIN_DECL
/**
* Create new session offering based on the local and remote SDP.
- * The session initially will be inactive.
+ * The session will start immediately.
*
* @param endpt The PJMEDIA endpoint instance.
* @param stream_cnt Maximum number of streams to be created. This
diff --git a/pjmedia/include/pjmedia/types.h b/pjmedia/include/pjmedia/types.h
index 6dd44bf7..726a33ec 100644
--- a/pjmedia/include/pjmedia/types.h
+++ b/pjmedia/include/pjmedia/types.h
@@ -133,8 +133,9 @@ typedef struct pjmedia_sock_info
{
pj_sock_t rtp_sock;
- pj_sock_t rtcp_sock;
pj_sockaddr_in rtp_addr_name;
+ pj_sock_t rtcp_sock;
+ pj_sockaddr_in rtcp_addr_name;
} pjmedia_sock_info;
diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c
index 0100bd3f..e2524fd1 100644
--- a/pjmedia/src/pjmedia/endpoint.c
+++ b/pjmedia/src/pjmedia/endpoint.c
@@ -40,6 +40,32 @@ static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool);
PJ_DECL(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory);
+/* Flag to indicate whether pjmedia error subsystem has been registered
+ * to pjlib.
+ */
+static int error_subsys_registered;
+
+
+/**
+ * Defined in pjmedia/errno.c
+ *
+ * Get error message for the specified error code. Note that this
+ * function is only able to decode PJMEDIA specific error code.
+ * Application should use pj_strerror(), which should be able to
+ * decode all error codes belonging to all subsystems (e.g. pjlib,
+ * pjmedia, pjsip, etc).
+ *
+ * @param status The error code.
+ * @param buffer The buffer where to put the error message.
+ * @param bufsize Size of the buffer.
+ *
+ * @return The error message as NULL terminated string,
+ * wrapped with pj_str_t.
+ */
+PJ_DECL(pj_str_t) pjmedia_strerror( pj_status_t status, char *buffer,
+ pj_size_t bufsize);
+
+
/** Concrete declaration of media endpoint. */
struct pjmedia_endpt
@@ -65,6 +91,12 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
pjmedia_codec_factory *factory;
pj_status_t status;
+ if (!error_subsys_registered) {
+ pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE,
+ &pjmedia_strerror);
+ error_subsys_registered = 1;
+ }
+
PJ_ASSERT_RETURN(pf && p_endpt, PJ_EINVAL);
pool = pj_pool_create(pf, "med-ept", 512, 512, NULL);
diff --git a/pjmedia/src/pjmedia/errno.c b/pjmedia/src/pjmedia/errno.c
index aca50aef..f02ffa1c 100644
--- a/pjmedia/src/pjmedia/errno.c
+++ b/pjmedia/src/pjmedia/errno.c
@@ -132,20 +132,15 @@ PJ_DEF(pj_str_t) pjmedia_strerror( pj_status_t statcode,
pj_strncpy_with_null(&errstr, &msg, bufsize);
return errstr;
- } else {
- /* Error not found. */
- errstr.ptr = buf;
- errstr.slen = pj_snprintf(buf, bufsize,
- "Unknown error %d",
- statcode);
-
- return errstr;
- }
- }
- else {
- /* Not our code. Give it to PJLIB. */
- return pj_strerror(statcode, buf, bufsize);
+ }
}
+ /* Error not found. */
+ errstr.ptr = buf;
+ errstr.slen = pj_snprintf(buf, bufsize,
+ "Unknown error %d",
+ statcode);
+
+ return errstr;
}
diff --git a/pjmedia/src/pjmedia/sdp.c b/pjmedia/src/pjmedia/sdp.c
index edd83aa5..92f01251 100644
--- a/pjmedia/src/pjmedia/sdp.c
+++ b/pjmedia/src/pjmedia/sdp.c
@@ -989,8 +989,8 @@ PJ_DEF(pj_status_t) pjmedia_sdp_parse( pj_pool_t *pool,
}
PJ_CATCH(SYNTAX_ERROR) {
- char errmsg[PJMEDIA_ERR_MSG_SIZE];
- pjmedia_strerror(ctx.last_error, errmsg, sizeof(errmsg));
+ char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(ctx.last_error, errmsg, sizeof(errmsg));
PJ_LOG(4, (THIS_FILE, "Error parsing SDP in line %d col %d: %s",
scanner.line, pj_scan_get_col(&scanner),
diff --git a/pjsip/include/pjsip/sip_errno.h b/pjsip/include/pjsip/sip_errno.h
index f7dc18cc..d5000955 100644
--- a/pjsip/include/pjsip/sip_errno.h
+++ b/pjsip/include/pjsip/sip_errno.h
@@ -23,11 +23,6 @@
PJ_BEGIN_DECL
-/**
- * Guidelines on error message length.
- */
-#define PJSIP_ERR_MSG_SIZE 64
-
/*
* PJSIP error codes occupies 170000 - 219000, and mapped as follows:
* - 170100 - 170799: mapped to SIP status code in response msg.
@@ -35,19 +30,6 @@ PJ_BEGIN_DECL
*/
/**
- * Get error message for the specified error code.
- *
- * @param status The error code.
- * @param buffer The buffer where to put the error message.
- * @param bufsize Size of the buffer.
- *
- * @return The error message as NULL terminated string,
- * wrapped with pj_str_t.
- */
-PJ_DECL(pj_str_t) pjsip_strerror( pj_status_t status, char *buffer,
- pj_size_t bufsize);
-
-/**
* Start of error code relative to PJ_ERRNO_START_USER.
*/
#define PJSIP_ERRNO_START (PJ_ERRNO_START_USER)
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index 2a5e14ae..28a8bd62 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -23,6 +23,7 @@
#include <pjsip/sip_transaction.h>
#include <pjmedia/sdp.h>
#include <pjmedia/sdp_neg.h>
+#include <pjmedia/errno.h>
#include <pj/string.h>
#include <pj/pool.h>
#include <pj/assert.h>
@@ -760,9 +761,7 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uas( pjsip_dialog *dlg,
status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, local_sdp,
&inv->neg);
} else {
- pj_assert(!"UAS dialog without remote and local offer is not supported!");
- PJ_TODO(IMPLEMENT_DELAYED_UAS_OFFER);
- status = PJ_ENOTSUP;
+ status = PJ_SUCCESS;
}
if (status != PJ_SUCCESS)
@@ -875,6 +874,25 @@ PJ_DEF(pj_status_t) pjsip_inv_invite( pjsip_inv_session *inv,
/*
+ * Negotiate SDP.
+ */
+static pj_status_t inv_negotiate_sdp( pjsip_inv_session *inv )
+{
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(pjmedia_sdp_neg_get_state(inv->neg) ==
+ PJMEDIA_SDP_NEG_STATE_WAIT_NEGO,
+ PJMEDIA_SDPNEG_EINSTATE);
+
+ status = pjmedia_sdp_neg_negotiate(inv->pool, inv->neg, 0);
+
+ if (mod_inv.cb.on_media_update)
+ (*mod_inv.cb.on_media_update)(inv, status);
+
+ return status;
+}
+
+/*
* Answer initial INVITE.
*/
PJ_DEF(pj_status_t) pjsip_inv_answer( pjsip_inv_session *inv,
@@ -898,12 +916,23 @@ PJ_DEF(pj_status_t) pjsip_inv_answer( pjsip_inv_session *inv,
/* If local_sdp is specified, then we MUST NOT have answered the
* offer before.
*/
- PJ_ASSERT_RETURN(!local_sdp ||
- (pjmedia_sdp_neg_get_state(inv->neg)==PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER),
- PJ_EINVALIDOP);
if (local_sdp) {
- status = pjmedia_sdp_neg_set_local_answer(inv->pool, inv->neg,
- local_sdp);
+
+ if (inv->neg == NULL) {
+ status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, local_sdp,
+ &inv->neg);
+ } else if (pjmedia_sdp_neg_get_state(inv->neg)==
+ PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER)
+ {
+ status = pjmedia_sdp_neg_set_local_answer(inv->pool, inv->neg,
+ local_sdp);
+ } else {
+
+ /* Can not specify local SDP at this state. */
+ pj_assert(0);
+ status = PJMEDIA_SDPNEG_EINSTATE;
+ }
+
if (status != PJ_SUCCESS)
return status;
}
@@ -915,18 +944,26 @@ PJ_DEF(pj_status_t) pjsip_inv_answer( pjsip_inv_session *inv,
if (status != PJ_SUCCESS)
return status;
- /* Include SDP for 18x and 2xx response. */
+ /* Include SDP for 18x and 2xx response.
+ * Also if SDP negotiator is ready, start negotiation.
+ */
if (st_code/10 == 18 || st_code/10 == 20) {
const pjmedia_sdp_session *local;
status = pjmedia_sdp_neg_get_neg_local(inv->neg, &local);
if (status == PJ_SUCCESS)
last_res->msg->body = create_sdp_body(last_res->pool, local);
- ;
+
+ /* Start negotiation, if ready. */
+ if (pjmedia_sdp_neg_get_state(inv->neg) == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) {
+ status = inv_negotiate_sdp(inv);
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(last_res);
+ return status;
+ }
+ }
}
- /* Do we need to increment tdata'inv reference counter? */
- PJ_TODO(INV_ANSWER_MAY_HAVE_TO_INCREMENT_REF_COUNTER);
*p_tdata = last_res;
diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
index 0cc8b270..df4c5ccb 100644
--- a/pjsip/src/pjsip/sip_endpoint.c
+++ b/pjsip/src/pjsip/sip_endpoint.c
@@ -106,6 +106,28 @@ pj_status_t pjsip_tel_uri_subsys_init(void);
/* Defined in sip_util_statefull.c */
extern pjsip_module mod_stateful_util;
+
+/* Specifies whether error subsystem has been registered to pjlib. */
+static int error_subsys_initialized;
+
+/**
+ * Defined in sip_errno.c
+ *
+ * Get error message for the specified error code. This can only get
+ * PJSIP specific error message. To get all types of error message,
+ * use pj_strerror() instead.
+ *
+ * @param status The error code.
+ * @param buffer The buffer where to put the error message.
+ * @param bufsize Size of the buffer.
+ *
+ * @return The error message as NULL terminated string,
+ * wrapped with pj_str_t.
+ */
+PJ_DECL(pj_str_t) pjsip_strerror( pj_status_t status, char *buffer,
+ pj_size_t bufsize);
+
+
/*
* This is the global handler for memory allocation failure, for pools that
* are created by the endpoint (by default, all pools ARE allocated by
@@ -394,6 +416,13 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
pjsip_max_fwd_hdr *mf_hdr;
pj_lock_t *lock = NULL;
+
+ if (!error_subsys_initialized) {
+ pj_register_strerror(PJSIP_ERRNO_START, PJ_ERRNO_SPACE_SIZE,
+ &pjsip_strerror);
+ error_subsys_initialized = 1;
+ }
+
PJ_LOG(5, (THIS_FILE, "Creating endpoint instance..."));
*p_endpt = NULL;
diff --git a/pjsip/src/pjsip/sip_resolve.c b/pjsip/src/pjsip/sip_resolve.c
index 4712b7f7..5b920be5 100644
--- a/pjsip/src/pjsip/sip_resolve.c
+++ b/pjsip/src/pjsip/sip_resolve.c
@@ -129,12 +129,12 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver,
}
if (status != PJ_SUCCESS) {
- char errmsg[PJSIP_ERR_MSG_SIZE];
+ char errmsg[PJ_ERR_MSG_SIZE];
PJ_LOG(4,(THIS_FILE, "Failed to resolve '%.*s'. Err=%d (%s)",
target->addr.host.slen,
target->addr.host.ptr,
status,
- pjsip_strerror(status,errmsg,sizeof(errmsg)).ptr));
+ pj_strerror(status,errmsg,sizeof(errmsg)).ptr));
(*cb)(status, token, &svr_addr);
return;
}
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
index 6dae0370..dcb09131 100644
--- a/pjsip/src/pjsip/sip_transaction.c
+++ b/pjsip/src/pjsip/sip_transaction.c
@@ -1442,12 +1442,12 @@ static void send_msg_callback( pjsip_send_state *send_state,
}
if (!*cont) {
- char errmsg[PJSIP_ERR_MSG_SIZE];
+ char errmsg[PJ_ERR_MSG_SIZE];
PJ_LOG(4,(tsx->obj_name,
"Failed to send %s! err=%d (%s)",
pjsip_tx_data_get_info(send_state->tdata), -sent,
- pjsip_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
+ pj_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
/* Clear pending transport flag. */
tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT);
@@ -1465,13 +1465,13 @@ static void send_msg_callback( pjsip_send_state *send_state,
}
} else {
- char errmsg[PJSIP_ERR_MSG_SIZE];
+ char errmsg[PJ_ERR_MSG_SIZE];
PJ_LOG(4,(tsx->obj_name,
"Temporary failure in sending %s, "
"will try next server. Err=%d (%s)",
pjsip_tx_data_get_info(send_state->tdata), -sent,
- pjsip_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
+ pj_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
}
}
@@ -1486,11 +1486,11 @@ static void transport_callback(void *token, pjsip_tx_data *tdata,
if (sent < 0) {
pjsip_transaction *tsx = token;
struct tsx_lock_data lck;
- char errmsg[PJSIP_ERR_MSG_SIZE];
+ char errmsg[PJ_ERR_MSG_SIZE];
PJ_LOG(4,(tsx->obj_name, "Transport failed to send %s! Err=%d (%s)",
pjsip_tx_data_get_info(tdata), -sent,
- pjsip_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
+ pj_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
lock_tsx(tsx, &lck);
@@ -1534,12 +1534,12 @@ static pj_status_t tsx_send_msg( pjsip_transaction *tsx,
status = PJ_SUCCESS;
if (status != PJ_SUCCESS) {
- char errmsg[PJSIP_ERR_MSG_SIZE];
+ char errmsg[PJ_ERR_MSG_SIZE];
PJ_LOG(4,(tsx->obj_name,
"Error sending %s: Err=%d (%s)",
pjsip_tx_data_get_info(tdata), status,
- pjsip_strerror(status, errmsg, sizeof(errmsg)).ptr));
+ pj_strerror(status, errmsg, sizeof(errmsg)).ptr));
/* On error, release transport to force using full transport
* resolution procedure.
@@ -1568,7 +1568,7 @@ static pj_status_t tsx_send_msg( pjsip_transaction *tsx,
*/
if (tsx->transport_flag & TSX_HAS_RESOLVED_SERVER) {
- char errmsg[PJSIP_ERR_MSG_SIZE];
+ char errmsg[PJ_ERR_MSG_SIZE];
if (status == PJ_SUCCESS) {
pj_assert(!"Unexpected status!");
@@ -1582,7 +1582,7 @@ static pj_status_t tsx_send_msg( pjsip_transaction *tsx,
"Transport error, terminating transaction. "
"Err=%d (%s)",
status,
- pjsip_strerror(status, errmsg, sizeof(errmsg)).ptr));
+ pj_strerror(status, errmsg, sizeof(errmsg)).ptr));
tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
diff --git a/pjsip/src/pjsua/pjsua.h b/pjsip/src/pjsua/pjsua.h
index 53b46e58..37740c3a 100644
--- a/pjsip/src/pjsua/pjsua.h
+++ b/pjsip/src/pjsua/pjsua.h
@@ -38,16 +38,22 @@
PJ_BEGIN_DECL
/* PJSUA application variables. */
-struct pjsua_t
+struct pjsua
{
/* Control: */
- pj_caching_pool cp; /**< Global pool factory. */
- pjsip_endpoint *endpt; /**< Global endpoint. */
- pj_pool_t *pool; /**< pjsua's private pool. */
- pjsip_module mod; /**< pjsua's PJSIP module. */
+ pj_caching_pool cp; /**< Global pool factory. */
+ pjsip_endpoint *endpt; /**< Global endpoint. */
+ pj_pool_t *pool; /**< pjsua's private pool. */
+ pjsip_module mod; /**< pjsua's PJSIP module. */
+ /* Media: */
+
+ pjmedia_endpt *med_endpt; /**< Media endpoint. */
+ pj_bool_t null_audio;
+ pjmedia_sock_info med_skinfo;
+
/* User info: */
pj_str_t local_uri; /**< Uri in From: header. */
@@ -57,6 +63,8 @@ struct pjsua_t
pj_str_t proxy;
pj_str_t outbound_proxy;
+ pjsip_route_hdr route_set;
+
/* Registration: */
@@ -83,10 +91,6 @@ struct pjsua_t
pj_uint16_t sip_port; /**< SIP signaling port. */
pj_sock_t sip_sock; /**< SIP UDP socket. */
pj_sockaddr_in sip_sock_name; /**< Public/STUN UDP socket addr. */
- pj_sock_t rtp_sock; /**< RTP socket. */
- pj_sockaddr_in rtp_sock_name; /**< Public/STUN UDP socket addr. */
- pj_sock_t rtcp_sock; /**< RTCP socket. */
- pj_sockaddr_in rtcp_sock_name;/**< Public/STUN UDP socket addr. */
@@ -98,12 +102,6 @@ struct pjsua_t
int stun_port2;
- /* Media stack: */
-
- pj_bool_t null_audio;
- pj_med_mgr_t *mmgr;
-
-
/* Misc: */
int log_level; /**< Logging verbosity. */
@@ -113,7 +111,21 @@ struct pjsua_t
};
-extern struct pjsua_t pjsua;
+
+/** PJSUA instance. */
+extern struct pjsua pjsua;
+
+
+/**
+ * Structure to be attached to all dialog.
+ * Given a dialog "dlg", application can retrieve this structure
+ * by accessing dlg->mod_data[pjsua.mod.id].
+ */
+struct pjsua_inv_data
+{
+ pjmedia_session *session;
+};
+
/*****************************************************************************
* PJSUA API.
diff --git a/pjsip/src/pjsua/pjsua_core.c b/pjsip/src/pjsua/pjsua_core.c
index 46f7fde7..272339f1 100644
--- a/pjsip/src/pjsua/pjsua_core.c
+++ b/pjsip/src/pjsua/pjsua_core.c
@@ -21,27 +21,14 @@
#define THIS_FILE "pjsua.c"
-struct pjsua_t pjsua;
+struct pjsua pjsua;
+/*
+ * Default local URI, if not specified in cmd-line
+ */
#define PJSUA_LOCAL_URI "<sip:user@127.0.0.1>"
-static char *PJSUA_DUMMY_SDP_OFFER =
- "v=0\r\n"
- "o=offer 2890844526 2890844526 IN IP4 127.0.0.1\r\n"
- "s= \r\n"
- "c=IN IP4 127.0.0.1\r\n"
- "t=0 0\r\n"
- "m=audio 49170 RTP/AVP 0\r\n"
- "a=rtpmap:0 PCMU/8000\r\n";
-
-static char *PJSUA_DUMMY_SDP_ANSWER =
- "v=0\r\n"
- "o=answer 2890844730 2890844730 IN IP4 127.0.0.1\r\n"
- "s= \r\n"
- "c=IN IP4 127.0.0.1\r\n"
- "t=0 0\r\n"
- "m=audio 49920 RTP/AVP 0\r\n"
- "a=rtpmap:0 PCMU/8000\r\n";
+
/*
* Init default application parameters.
@@ -74,6 +61,10 @@ void pjsua_default(void)
/* Default URIs: */
pjsua.local_uri = pj_str(PJSUA_LOCAL_URI);
+
+ /* Init route set list: */
+
+ pj_list_init(&pjsua.route_set);
}
@@ -143,14 +134,14 @@ static pj_bool_t mod_pjsua_on_rx_request(pjsip_rx_data *rdata)
* Yes we can handle the incoming INVITE request.
*/
pjsip_inv_session *inv;
+ struct pjsua_inv_data *inv_data;
pjmedia_sdp_session *answer;
- /* Create dummy SDP answer: */
+ /* Get media capability from media endpoint: */
- status = pjmedia_sdp_parse(pjsua.pool, PJSUA_DUMMY_SDP_ANSWER,
- pj_native_strlen(PJSUA_DUMMY_SDP_ANSWER),
- &answer);
+ status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool,
+ 1, &pjsua.med_skinfo, &answer );
if (status != PJ_SUCCESS) {
pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL,
@@ -181,6 +172,13 @@ static pj_bool_t mod_pjsua_on_rx_request(pjsip_rx_data *rdata)
}
+
+ /* Create and attach pjsua data to the dialog: */
+
+ inv_data = pj_pool_zalloc(dlg->pool, sizeof(struct pjsua_inv_data));
+ dlg->mod_data[pjsua.mod.id] = inv_data;
+
+
/* Answer with 100 (using the dialog, not invite): */
status = pjsip_dlg_create_response(dlg, rdata, 100, NULL, &response);
@@ -222,6 +220,19 @@ static pj_bool_t mod_pjsua_on_rx_response(pjsip_rx_data *rdata)
*/
static void pjsua_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
{
+
+ /* Destroy media session when invite session is disconnected. */
+ if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+ struct pjsua_inv_data *inv_data;
+
+ inv_data = inv->dlg->mod_data[pjsua.mod.id];
+ if (inv_data && inv_data->session) {
+ pjmedia_session_destroy(inv_data->session);
+ inv_data->session = NULL;
+ }
+
+ }
+
pjsua_ui_inv_on_state_changed(inv, e);
}
@@ -238,6 +249,60 @@ static void pjsua_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
PJ_TODO(HANDLE_FORKED_DIALOG);
}
+/*
+ *
+ */
+static void pjsua_inv_on_media_update(pjsip_inv_session *inv,
+ pj_status_t status)
+{
+ struct pjsua_inv_data *inv_data;
+ const pjmedia_sdp_session *local_sdp;
+ const pjmedia_sdp_session *remote_sdp;
+
+ if (status != PJ_SUCCESS) {
+
+ pjsua_perror("SDP negotiation has failed", status);
+ return;
+
+ }
+
+ /* Destroy existing media session, if any. */
+
+ inv_data = inv->dlg->mod_data[pjsua.mod.id];
+ if (inv_data && inv_data->session) {
+ pjmedia_session_destroy(inv_data->session);
+ inv_data->session = NULL;
+ }
+
+ /* Get local and remote SDP */
+
+ status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror("Unable to retrieve currently active local SDP", status);
+ return;
+ }
+
+
+ status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror("Unable to retrieve currently active remote SDP", status);
+ return;
+ }
+
+
+ /* Create new media session.
+ * The media session is active immediately.
+ */
+
+ status = pjmedia_session_create( pjsua.med_endpt, 1, &pjsua.med_skinfo,
+ local_sdp, remote_sdp, &inv_data->session );
+ if (status != PJ_SUCCESS) {
+ pjsua_perror("Unable to create media session", status);
+ return;
+ }
+
+}
+
/*
* Initialize sockets and optionally get the public address via STUN.
*/
@@ -363,20 +428,24 @@ static pj_status_t init_sockets()
pjsua.sip_sock = sock[SIP_SOCK];
pj_memcpy(&pjsua.sip_sock_name, &mapped_addr[SIP_SOCK], sizeof(pj_sockaddr_in));
- pjsua.rtp_sock = sock[RTP_SOCK];
- pj_memcpy(&pjsua.rtp_sock_name, &mapped_addr[RTP_SOCK], sizeof(pj_sockaddr_in));
- pjsua.rtcp_sock = sock[RTCP_SOCK];
- pj_memcpy(&pjsua.rtcp_sock_name, &mapped_addr[RTCP_SOCK], sizeof(pj_sockaddr_in));
+
+ pjsua.med_skinfo.rtp_sock = sock[RTP_SOCK];
+ pj_memcpy(&pjsua.med_skinfo.rtp_addr_name,
+ &mapped_addr[RTP_SOCK], sizeof(pj_sockaddr_in));
+
+ pjsua.med_skinfo.rtcp_sock = sock[RTCP_SOCK];
+ pj_memcpy(&pjsua.med_skinfo.rtcp_addr_name,
+ &mapped_addr[RTCP_SOCK], sizeof(pj_sockaddr_in));
PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d",
pj_inet_ntoa(pjsua.sip_sock_name.sin_addr),
pj_ntohs(pjsua.sip_sock_name.sin_port)));
PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s:%d",
- pj_inet_ntoa(pjsua.rtp_sock_name.sin_addr),
- pj_ntohs(pjsua.rtp_sock_name.sin_port)));
+ pj_inet_ntoa(pjsua.med_skinfo.rtp_addr_name.sin_addr),
+ pj_ntohs(pjsua.med_skinfo.rtp_addr_name.sin_port)));
PJ_LOG(4,(THIS_FILE, "RTCP UDP socket reachable at %s:%d",
- pj_inet_ntoa(pjsua.rtcp_sock_name.sin_addr),
- pj_ntohs(pjsua.rtcp_sock_name.sin_port)));
+ pj_inet_ntoa(pjsua.med_skinfo.rtcp_addr_name.sin_addr),
+ pj_ntohs(pjsua.med_skinfo.rtcp_addr_name.sin_port)));
return PJ_SUCCESS;
@@ -478,6 +547,7 @@ static pj_status_t init_stack(void)
pj_memset(&inv_cb, 0, sizeof(inv_cb));
inv_cb.on_state_changed = &pjsua_inv_on_state_changed;
inv_cb.on_new_session = &pjsua_inv_on_new_session;
+ inv_cb.on_media_update = &pjsua_inv_on_media_update;
/* Initialize invite session module: */
status = pjsip_inv_usage_init(pjsua.endpt, &pjsua.mod, &inv_cb);
@@ -554,6 +624,16 @@ pj_status_t pjsua_init(void)
return status;
}
+
+ /* Init media endpoint: */
+
+ status = pjmedia_endpt_create(&pjsua.cp.factory, &pjsua.med_endpt);
+ if (status != PJ_SUCCESS) {
+ pj_caching_pool_destroy(&pjsua.cp);
+ pjsua_perror("Media stack initialization has returned error", status);
+ return status;
+ }
+
/* Done. */
return PJ_SUCCESS;
}
@@ -676,9 +756,25 @@ pj_status_t pjsua_start(void)
}
- /* Initialize global route_set: */
+ /* If outbound_proxy is specified, put it in the route_set: */
+
+ if (pjsua.outbound_proxy.slen) {
- PJ_TODO(INIT_GLOBAL_ROUTE_SET);
+ pjsip_route_hdr *route;
+ const pj_str_t hname = { "Route", 5 };
+ int parsed_len;
+
+ route = pjsip_parse_hdr( pjsua.pool, &hname,
+ pjsua.outbound_proxy.ptr,
+ pjsua.outbound_proxy.slen,
+ &parsed_len);
+ if (route == NULL) {
+ pjsua_perror("Invalid outbound proxy URL", PJSIP_EINVALIDURI);
+ return PJSIP_EINVALIDURI;
+ }
+
+ pj_list_push_back(&pjsua.route_set, route);
+ }
/* Create worker thread(s), if required: */
@@ -769,6 +865,7 @@ pj_status_t pjsua_invite(const char *cstr_dest_uri,
pjsip_dialog *dlg;
pjmedia_sdp_session *offer;
pjsip_inv_session *inv;
+ struct pjsua_inv_data *inv_data;
pjsip_tx_data *tdata;
pj_status_t status;
@@ -786,13 +883,12 @@ pj_status_t pjsua_invite(const char *cstr_dest_uri,
return status;
}
- /* Create dummy SDP for offer: */
+ /* Get media capability from media endpoint: */
- status = pjmedia_sdp_parse(dlg->pool, PJSUA_DUMMY_SDP_OFFER,
- pj_native_strlen(PJSUA_DUMMY_SDP_OFFER),
- &offer);
+ status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool,
+ 1, &pjsua.med_skinfo, &offer);
if (status != PJ_SUCCESS) {
- pjsua_perror("Dummy SDP offer parsing failed", status);
+ pjsua_perror("pjmedia unable to create SDP", status);
goto on_error;
}
@@ -805,9 +901,17 @@ pj_status_t pjsua_invite(const char *cstr_dest_uri,
}
+ /* Create and associate our data in the session. */
+
+ inv_data = pj_pool_zalloc( dlg->pool, sizeof(struct pjsua_inv_data));
+ dlg->mod_data[pjsua.mod.id] = inv_data;
+
+
/* Set dialog Route-Set: */
- PJ_TODO(INIT_DIALOG_ROUTE_SET);
+ if (!pj_list_empty(&pjsua.route_set))
+ pjsip_dlg_set_route_set(dlg, &pjsua.route_set);
+
/* Set credentials: */