[Freeswitch-branches] [commit] r2261 - in freeswitch/branches/bennylp: conf src/mod/endpoints/mod_pjsip src/mod/endpoints/mod_pjsip/pjsdp
Freeswitch SVN
bennylp at freeswitch.org
Fri Aug 11 14:24:07 EDT 2006
Author: bennylp
Date: Fri Aug 11 14:24:06 2006
New Revision: 2261
Removed:
freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/pjsdp/
Modified:
freeswitch/branches/bennylp/conf/freeswitch.xml
freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/Makefile
freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip.c
freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip_sdp.c
Log:
Bug hunting season in mod_pjsip. Looks a bit better, but who knows...
Modified: freeswitch/branches/bennylp/conf/freeswitch.xml
==============================================================================
--- freeswitch/branches/bennylp/conf/freeswitch.xml (original)
+++ freeswitch/branches/bennylp/conf/freeswitch.xml Fri Aug 11 14:24:06 2006
@@ -27,7 +27,9 @@
<!-- <load module="mod_ldap"/> -->
<!-- Endpoints -->
- <load module="mod_exosip"/>
+ <!-- load module="mod_exosip"/> -->
+ <load module="mod_pjsip"/>
+ <!-- load module="mod_pjsip_sdp"/> -->
<!--<load module="mod_iax"/>-->
<load module="mod_portaudio"/>
<!-- <load module="mod_woomera"/> -->
@@ -82,6 +84,17 @@
</settings>
</configuration>
+ <configuration name="pjsip.conf" description="PJSIP Configuration">
+ <profile name="default">
+ <!-- <param name="ip" value="1.2.3.4"/> -->
+ <!-- note: only udp transport supported for now! -->
+ <!-- <param name="transport" value="udp,tcp,tls"/> -->
+ <param name="port" value="5060"/>
+ <param name="max-calls" value="10"/>
+ <param name="dialplan" value="XML"/>
+ </profile>
+ </configuration>
+
<configuration name="iax.conf" description="IAX Configuration">
<settings>
<param name="debug" value="0"/>
@@ -369,8 +382,8 @@
<!-- Enter an existing conference -->
<extension name="1000">
- <condition field="destination_number" expression="^1000$">
- <action application="conference" data="freeswitch"/>
+ <condition field="destination_number" expression=".*">
+ <action application="playback" data="/usr/local/freeswitch/cluecon1.wav"/>
</condition>
</extension>
Modified: freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/Makefile
==============================================================================
--- freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/Makefile (original)
+++ freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/Makefile Fri Aug 11 14:24:06 2006
@@ -6,8 +6,8 @@
LINKER=$(CC)
endif
-PJ_PROJECT=pjproject-0.5.6
-PJ_DIR=$(BASE)/libs/$(PJ_PROJECT)
+PJ_PROJECT=/root/project/pjproject
+PJ_DIR=/root/project/pjproject
ifeq ($(MAKECMDGOALS),build)
CC_DEF=-D
@@ -17,29 +17,25 @@
include $(PJ_DIR)/build/os-$(OS_NAME).mak
CFLAGS += -I$(PJ_DIR)/pjlib/include -I$(PJ_DIR)/pjlib-util/include -I$(PJ_DIR)/pjsip/include
-CFLAGS += -I$(PJ_DIR)/pjmedia/include -I./pjsdp/pjsdp/include
+CFLAGS += -I$(PJ_DIR)/pjmedia/include
CFLAGS += $(OS_CFLAGS) $(M_CFLAGS)
-LDFLAGS += -L$(PJ_DIR)/pjlib/lib -L$(PJ_DIR)/pjlib-util/lib -L$(PJ_DIR)/pjsip/lib -L./pjsdp/pjsdp/lib
+LDFLAGS += -L$(PJ_DIR)/pjlib/lib -L$(PJ_DIR)/pjlib-util/lib -L$(PJ_DIR)/pjsip/lib -L$(PJ_DIR)/pjmedia/lib
LDFLAGS += -lpjsip-$(TARGET_NAME) -lpjsip-ua-$(TARGET_NAME) -lpjsip-simple-$(TARGET_NAME)
LDFLAGS += -lpjsdp-$(TARGET_NAME) -lpjlib-util-$(TARGET_NAME) -lpj-$(TARGET_NAME)
endif
OBJS=mod_pjsip_sdp.o
-.PHONY: pjsdp
+.PHONY:
all: depends
$(MAKE) build
-build: pjsdp $(OBJS) $(MODNAME).$(DYNAMIC_LIB_EXTEN)
+build: $(OBJS) $(MODNAME).$(DYNAMIC_LIB_EXTEN)
-pjsdp:
- $(MAKE) CFLAGS="$(filter-out -Werror,$(CFLAGS)) -fPIC" -C pjsdp
-
depends:
- MAKE=$(MAKE) $(BASE)/build/buildlib.sh $(BASE) $(PJ_PROJECT).tar.gz --prefix=$(PREFIX)
- (cd pjsdp; ./configure)
+# MAKE=$(MAKE) $(BASE)/build/buildlib.sh $(BASE) $(PJ_PROJECT).tar.gz --prefix=$(PREFIX)
%.o: %.c
$(CC) -fPIC $(CFLAGS) -c -o $@ $<
@@ -50,7 +46,6 @@
clean:
rm -fr *.$(DYNAMIC_LIB_EXTEN) *.o *~
- $(MAKE) -C pjsdp realclean
install:
cp -f $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(DESTDIR)$(PREFIX)/mod
Modified: freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip.c
==============================================================================
--- freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip.c (original)
+++ freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip.c Fri Aug 11 14:24:06 2006
@@ -29,7 +29,7 @@
#define HAVE_APR
#include <switch.h>
#include <pjsip.h>
-#include <pjsdp.h>
+#include <pjmedia.h>
#include <pjsip_ua.h>
#include <pjsip_simple.h>
#include <pjlib-util.h>
@@ -40,11 +40,19 @@
static const char modname[] = "mod_pjsip";
#define MOD_PJSIP_CFG "pjsip.conf"
+#define THIS_FILE pj_thread_get_name(pj_thread_this())
+#if 0
+#define TRACE_(x) PJ_LOG(4,x)
+#else
+#define TRACE_(x)
+#endif
+
static switch_memory_pool_t *module_pool = NULL;
static pj_caching_pool cp;
static pjsip_inv_callback invite_cb;
static pj_pool_t *pjsip_pool;
+static pj_str_t FREESWITCH_SERVER;
#define DEFAULT_PORT 5060
@@ -182,6 +190,31 @@
/*.application_interface */ NULL
};
+
+void log_func(int level, const char *data, int len)
+{
+#if 1
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, (char *) data);
+#else
+ static FILE *pjsip_log;
+ if (pjsip_log == NULL)
+ pjsip_log = fopen("/tmp/pjsip-fs.log", "w");
+
+ if (pjsip_log != NULL) {
+ fwrite(data, len, 1, pjsip_log);
+ fflush(pjsip_log);
+ }
+#endif
+}
+
+static void perror_(const char *sender, const char *title, pj_status_t status)
+{
+ char errmsg[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ PJ_LOG(1,(sender, "ERROR: %s: %s", title, errmsg));
+}
+
/* */
static int pjsip_strncpy( char *dst, const pj_str_t *src, int maxlen )
{
@@ -193,6 +226,21 @@
return len;
}
+
+static void add_server_header(pjsip_tx_data *tdata)
+{
+ const pj_str_t SERVER = { "Server", 6};
+ pjsip_hdr *h;
+
+ h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool,
+ &SERVER,
+ &FREESWITCH_SERVER);
+ pjsip_msg_add_hdr(tdata->msg, h);
+
+}
+
+
+
static switch_status_t pjsip_on_init(switch_core_session_t *session)
{
struct pjsip_profile *profile;
@@ -200,6 +248,7 @@
switch_channel_t *channel;
pj_status_t status;
+
channel = switch_core_session_get_channel( session );
assert( channel != NULL );
@@ -212,11 +261,13 @@
/* register switch thread to pjsip core */
status = pj_thread_register( NULL, tech_pvt->thread_desc, &tech_pvt->thread );
if( status != PJ_SUCCESS ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not register switch session thread to pjlib\n" );
+ perror_(THIS_FILE, "Could not register switch session thread to pjlib", status);
switch_core_session_destroy( &session );
return SWITCH_STATUS_GENERR;
}
+ TRACE_((THIS_FILE, "ENTER pjsip_on_init"));
+
if( switch_channel_test_flag( channel, CF_OUTBOUND ) )
{
pjsip_tx_data *txdata = NULL;
@@ -226,18 +277,21 @@
switch_copy_string( tmp, tech_pvt->caller_profile->destination_number, sizeof( tmp ) );
if( !(destination = strchr( tmp, '/' )) ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Malformed URL!\n" );
+ PJ_LOG(1,(THIS_FILE, "Malformed URL!"));
switch_core_session_destroy( &session );
+ TRACE_((THIS_FILE, "LEAVE pjsip_on_init"));
return SWITCH_STATUS_GENERR;
}
*destination++ = '\0';
pj_ansi_sprintf( tmp, "<sip:%s:%d>", destination, 5060 );
- pj_cstr( &dst, tmp );
+ dst = pj_str( tmp );
tech_pvt->sip_ua = pjsip_ua_instance();
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dst: %s, Local: %s %s\n", tmp, tech_pvt->profile->local_uri.ptr, tech_pvt->profile->local_contact.ptr );
+ PJ_LOG(5,(THIS_FILE, "Dst: %s, Local: %s %s", tmp,
+ tech_pvt->profile->local_uri.ptr,
+ tech_pvt->profile->local_contact.ptr));
/* create new UAC dialog */
status = pjsip_dlg_create_uac( tech_pvt->sip_ua,
@@ -248,20 +302,23 @@
&tech_pvt->sip_dialog );
if ( status != PJ_SUCCESS ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new UAC dialog for call\n" );
+ perror_(THIS_FILE,"Failed to create new UAC dialog for call", status);
switch_core_session_destroy( &session );
+ TRACE_((THIS_FILE, "LEAVE pjsip_on_init"));
return SWITCH_STATUS_GENERR;
}
/* create SDP */
create_sdp( tech_pvt->sip_dialog->pool, tech_pvt, &sdp, NULL );
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initial SDP created\n" );
+ PJ_LOG(5,(THIS_FILE, "Initial SDP created"));
/* create INVITE session */
- if ((status = pjsip_inv_create_uac( tech_pvt->sip_dialog, sdp, 0, &tech_pvt->sip_invite ) != PJ_SUCCESS )) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new INVITE session for call %s\n" );
+ status = pjsip_inv_create_uac( tech_pvt->sip_dialog, sdp, 0, &tech_pvt->sip_invite );
+ if (status != PJ_SUCCESS ) {
+ perror_(tech_pvt->sip_dialog->obj_name, "Failed to create new INVITE session", status);
pjsip_dlg_terminate( tech_pvt->sip_dialog );
+ TRACE_((THIS_FILE, "LEAVE pjsip_on_init"));
return SWITCH_STATUS_GENERR;
}
@@ -269,52 +326,38 @@
/* attach private object to pjsip session data */
tech_pvt->sip_invite->mod_data[globals.mod_app.id] = tech_pvt;
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Invite UAC created\n" );
-
/* create invite request */
status = pjsip_inv_invite( tech_pvt->sip_invite, &txdata );
if ( status != PJ_SUCCESS ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create initial INVITE request for call %s\n" );
- pjsip_dlg_terminate( tech_pvt->sip_dialog );
+ perror_( tech_pvt->sip_dialog->obj_name, "Failed to create initial INVITE request", status );
+ pjsip_inv_terminate(tech_pvt->sip_invite, 500, PJ_FALSE);
+ TRACE_((THIS_FILE, "LEAVE pjsip_on_init"));
return SWITCH_STATUS_GENERR;
}
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initial INVITE created\n" );
+ /* set call id (now, before invite is sent, so that when callback is called,
+ * tech_pvt has the correct call_id)
+ */
+ strncpy( tech_pvt->call_id, tech_pvt->sip_invite->dlg->call_id->id.ptr,
+ PJ_MAX_STRLEN( tech_pvt->call_id, tech_pvt->sip_invite->dlg->call_id->id ) );
/* send request */
+ add_server_header(txdata);
status = pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
if ( status != PJ_SUCCESS ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send INVITE request for call %s\n" );
- pjsip_dlg_terminate( tech_pvt->sip_dialog );
+ perror_(tech_pvt->sip_dialog->obj_name, "Failed to send INVITE request for call", status);
+ pjsip_inv_terminate(tech_pvt->sip_invite, 500, PJ_FALSE);
+ TRACE_((THIS_FILE, "LEAVE pjsip_on_init"));
return SWITCH_STATUS_GENERR;
}
-
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INVITE sent\n" );
-
- /* set call id */
- strncpy( tech_pvt->call_id, tech_pvt->sip_invite->dlg->call_id->id.ptr, PJ_MAX_STRLEN( tech_pvt->call_id, tech_pvt->sip_invite->dlg->call_id->id ) );
- } else {
- pjsip_tx_data *txdata;
-
- /* Send 180 Ring */
- status = pjsip_inv_answer( tech_pvt->sip_invite, 180, NULL, NULL, &txdata );
- if( status != PJ_SUCCESS ) {
- status = pjsip_inv_answer( tech_pvt->sip_invite, PJSIP_SC_NOT_ACCEPTABLE, NULL, NULL, &txdata );
-
- if( status == PJ_SUCCESS )
- pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
- else
- pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_FALSE );
-
- switch_core_session_destroy( &session );
- return SWITCH_STATUS_GENERR;
- }
- pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
}
+
+
/* add call to hash */
switch_core_hash_insert( profile->call_hash, tech_pvt->call_id, tech_pvt );
switch_channel_set_state( channel, CS_RING );
+ TRACE_((THIS_FILE, "LEAVE pjsip_on_init"));
return SWITCH_STATUS_SUCCESS;
}
@@ -323,6 +366,8 @@
struct private_object *tech_pvt;
switch_channel_t *channel;
+ TRACE_((THIS_FILE, "ENTER pjsip_on_ring"));
+
assert( session != NULL );
channel = switch_core_session_get_channel( session );
@@ -331,8 +376,9 @@
tech_pvt = switch_core_session_get_private( session );
assert( tech_pvt != NULL );
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RING %s\n", switch_channel_get_name( channel ) );
+ PJ_LOG(4,(THIS_FILE, "RING %s", switch_channel_get_name( channel )));
+ TRACE_((THIS_FILE, "LEAVE pjsip_on_ring"));
return SWITCH_STATUS_SUCCESS;
}
@@ -344,6 +390,8 @@
pj_status_t status;
pjsip_tx_data *txdata;
+ TRACE_((THIS_FILE, "ENTER pjsip_on_hangup"));
+
assert( session != NULL );
channel = switch_core_session_get_channel( session );
@@ -355,7 +403,8 @@
profile = tech_pvt->profile;
assert( profile != NULL );
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Hangup call %s\n", tech_pvt->call_id );
+ PJ_LOG(4,(THIS_FILE, "Hangup call %s dialog=%s", tech_pvt->call_id,
+ tech_pvt->sip_invite->dlg->obj_name));
/* remove call from hash */
switch_core_hash_delete( profile->call_hash, tech_pvt->call_id );
@@ -365,20 +414,24 @@
stop_rtp( tech_pvt );
- if( tech_pvt->sip_invite->state < PJSIP_INV_STATE_CONFIRMED ) {
- pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_TRUE );
- } else {
- status = pjsip_inv_end_session( tech_pvt->sip_invite, 200, NULL, &txdata );
- if( status != PJ_SUCCESS )
- pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_TRUE );
- else
- pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
+ //PJ_TODO(should_we_clear_dlg_data_here);
+
+ status = pjsip_inv_end_session( tech_pvt->sip_invite, 200, NULL, &txdata );
+ if( status == PJ_SUCCESS ) {
+ add_server_header(txdata);
+ status = pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
}
- if ( switch_test_flag( tech_pvt, TFLAG_USING_CODEC ) ) {
+ if (status != PJ_SUCCESS) {
+ perror_(tech_pvt->sip_invite->dlg->obj_name, "Unable to hangup", status);
+ }
+
+ if (switch_test_flag( tech_pvt, TFLAG_USING_CODEC ) ) {
switch_core_codec_destroy( &tech_pvt->read_codec );
switch_core_codec_destroy( &tech_pvt->write_codec );
}
+
+ TRACE_((THIS_FILE, "LEAVE pjsip_on_hangup"));
return SWITCH_STATUS_SUCCESS;
}
@@ -422,6 +475,8 @@
struct private_object *tech_pvt;
switch_channel_t *channel;
+ TRACE_((THIS_FILE, "ENTER pjsip_answer_channel"));
+
assert( session != NULL );
channel = switch_core_session_get_channel( session );
@@ -430,7 +485,7 @@
tech_pvt = switch_core_session_get_private( session );
assert( tech_pvt != NULL );
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "* Answering call %s\n", tech_pvt->call_id );
+ PJ_LOG(4,(THIS_FILE, "* Answering call %s", tech_pvt->call_id));
if( !switch_test_flag( tech_pvt, TFLAG_ANSWERED ) &&
!switch_channel_test_flag( channel, CF_OUTBOUND ) )
@@ -440,24 +495,33 @@
assert( tech_pvt->sip_invite != NULL );
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "* Sending 200 on INVITE to %s (%s)\n", tech_pvt->call_id, switch_channel_get_name( channel ) );
+ PJ_LOG(4,(THIS_FILE, "* Sending 200 on INVITE to %s (%s)",
+ tech_pvt->call_id, switch_channel_get_name( channel ) ));
/* create SIP 200 with SDP */
status = pjsip_inv_answer( tech_pvt->sip_invite, 200, NULL, NULL, &txdata );
if( status != PJ_SUCCESS ) {
+ perror_(tech_pvt->sip_invite->dlg->obj_name, "pjsip_inv_answer error", status);
+
pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_TRUE );
switch_core_session_destroy( &session );
+ TRACE_((THIS_FILE, "LEAVE pjsip_answer_channel"));
return SWITCH_STATUS_GENERR;
}
+ add_server_header(txdata);
status = pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
if( status != PJ_SUCCESS ) {
+ perror_(tech_pvt->sip_invite->dlg->obj_name, "pjsip_inv_send_msg(200) error", status);
+
pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_TRUE );
switch_core_session_destroy( &session );
+ TRACE_((THIS_FILE, "LEAVE pjsip_answer_channel"));
return SWITCH_STATUS_GENERR;
}
}
switch_set_flag_locked( tech_pvt, TFLAG_ANSWERED );
+ TRACE_((THIS_FILE, "LEAVE pjsip_answer_channel"));
return SWITCH_STATUS_SUCCESS;
}
@@ -467,6 +531,8 @@
struct private_object *tech_pvt;
switch_channel_t *channel;
+ TRACE_((THIS_FILE, "ENTER pjsip_kill_channel"));
+
assert( session != NULL );
channel = switch_core_session_get_channel( session );
@@ -475,12 +541,17 @@
tech_pvt = switch_core_session_get_private( session );
assert( tech_pvt != NULL );
- switch_clear_flag_locked( tech_pvt, TFLAG_IO );
- switch_set_flag_locked( tech_pvt, TFLAG_BYE );
-
- if( tech_pvt->rtp_session ) {
- switch_rtp_kill_socket( tech_pvt->rtp_session );
+ if (sig == SWITCH_SIG_KILL) {
+ switch_mutex_lock(tech_pvt->flag_mutex);
+ switch_clear_flag( tech_pvt, TFLAG_IO );
+ switch_set_flag( tech_pvt, TFLAG_BYE );
+ if( tech_pvt->rtp_session ) {
+ switch_rtp_kill_socket( tech_pvt->rtp_session );
+ }
+ switch_mutex_unlock(tech_pvt->flag_mutex);
}
+
+ TRACE_((THIS_FILE, "LEAVE pjsip_kill_channel"));
return SWITCH_STATUS_SUCCESS;
}
@@ -502,8 +573,10 @@
/* create new call */
-static switch_status_t pjsip_outgoing_channel(switch_core_session_t *session, switch_caller_profile_t *outbound_profile,
- switch_core_session_t **new_session, switch_memory_pool_t *pool)
+static switch_status_t pjsip_outgoing_channel(switch_core_session_t *session,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session,
+ switch_memory_pool_t *pool)
{
struct private_object *tech_pvt = NULL;
switch_channel_t *channel = NULL;
@@ -524,24 +597,32 @@
return SWITCH_STATUS_GENERR;
}
- if( !( profile = (struct pjsip_profile *) switch_core_hash_find( globals.profiles_hash, profile_name ) )) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown profile: %s\n", profile_name );
+ profile = (struct pjsip_profile *) switch_core_hash_find( globals.profiles_hash, profile_name );
+ if( !profile) {
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Unknown profile: %s\n", profile_name );
return SWITCH_STATUS_GENERR;
}
- if ( !( *new_session = switch_core_session_request( &pjsip_endpoint_interface, pool ) ) ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new session for call\n" );
+ *new_session = switch_core_session_request( &pjsip_endpoint_interface, pool );
+ if ( !(*new_session) ) {
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Failed to create new session for call\n" );
return SWITCH_STATUS_GENERR;
}
switch_core_session_add_stream( *new_session, NULL );
/* create new call */
- if (!(tech_pvt = (struct private_object *) switch_core_session_alloc(*new_session, sizeof(struct private_object)))) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new private object for call\n" );
+ tech_pvt = (struct private_object *)
+ switch_core_session_alloc(*new_session, sizeof(struct private_object));
+ if (!tech_pvt) {
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Failed to create new private object for call\n" );
goto err;
}
tech_pvt->session = *new_session;
- switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(*new_session));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED,
+ switch_core_session_get_pool(*new_session));
tech_pvt->profile = profile;
switch_core_session_set_private( *new_session, tech_pvt );
@@ -552,8 +633,10 @@
switch_channel_set_name( channel, tmp );
/* get list of all available codecs */
- tech_pvt->num_codecs = switch_loadable_module_get_codecs( switch_core_session_get_pool(tech_pvt->session), tech_pvt->codecs,
- sizeof(tech_pvt->codecs) / sizeof(tech_pvt->codecs[0]) );
+ tech_pvt->num_codecs =
+ switch_loadable_module_get_codecs( switch_core_session_get_pool(tech_pvt->session),
+ tech_pvt->codecs,
+ sizeof(tech_pvt->codecs) / sizeof(tech_pvt->codecs[0]) );
caller_profile = switch_caller_profile_clone( *new_session, outbound_profile );
switch_channel_set_caller_profile( channel, caller_profile );
@@ -571,8 +654,9 @@
}
-static switch_status_t pjsip_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout,
- switch_io_flag_t flags, int stream_id)
+static switch_status_t pjsip_read_frame(switch_core_session_t *session,
+ switch_frame_t **frame, int timeout,
+ switch_io_flag_t flags, int stream_id)
{
struct private_object *tech_pvt = NULL;
size_t bytes = 0, samples = 0, frames = 0, ms = 0;
@@ -609,7 +693,10 @@
tech_pvt->read_frame.datalen = 0;
- while (!switch_test_flag(tech_pvt, TFLAG_BYE) && switch_test_flag(tech_pvt, TFLAG_IO) && tech_pvt->read_frame.datalen == 0) {
+ while (!switch_test_flag(tech_pvt, TFLAG_BYE) &&
+ switch_test_flag(tech_pvt, TFLAG_IO) &&
+ tech_pvt->read_frame.datalen == 0)
+ {
now = switch_time_now();
tech_pvt->read_frame.flags = 0;
@@ -651,7 +738,6 @@
switch_channel_queue_dtmf(channel, dtmf);
}
-
if (tech_pvt->read_frame.datalen > 0) {
tech_pvt->last_read = switch_time_now();
if (tech_pvt->read_codec.implementation->encoded_bytes_per_frame) {
@@ -685,8 +771,9 @@
}
-static switch_status_t pjsip_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout,
- switch_io_flag_t flags, int stream_id)
+static switch_status_t pjsip_write_frame(switch_core_session_t *session,
+ switch_frame_t *frame, int timeout,
+ switch_io_flag_t flags, int stream_id)
{
struct private_object *tech_pvt;
switch_channel_t *channel = NULL;
@@ -711,7 +798,6 @@
switch_set_flag_locked(tech_pvt, TFLAG_WRITING);
-
if (tech_pvt->read_codec.implementation->encoded_bytes_per_frame) {
bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
frames = ((int) frame->datalen / bytes);
@@ -730,6 +816,7 @@
/* END: freeswitch callbacks */
+
/* BEGIN: pjsip callbacks */
/*
@@ -741,13 +828,16 @@
struct pjsip_profile *profile;
pj_status_t status;
+ TRACE_((THIS_FILE, "ENTER on_incoming_call"));
+
/* How to map rxdata / transport -> profile? */
- if( !( profile = switch_core_hash_find( globals.transport_hash, rxdata->tp_info.transport->obj_name )) ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile not found\n" );
- return;
+ profile = switch_core_hash_find( globals.transport_hash, rxdata->tp_info.transport->obj_name );
+ if( !profile ) {
+ PJ_LOG(1,(THIS_FILE,"Profile not found" ));
+ goto on_return;
}
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "*** New incoming call for profile %s\n", profile->name );
+ PJ_LOG(4,(THIS_FILE, "*** New incoming call for profile %s", profile->name ));
/* check call limit */
if( profile->max_calls && ( profile->calls + 1 ) > profile->max_calls ) {
@@ -756,12 +846,10 @@
500, &reason,
NULL, NULL);
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many calls (profile: %s)\n", profile->name );
- return;
+ PJ_LOG(1,(THIS_FILE, "Too many calls (profile: %s)", profile->name ));
+ goto on_return;
}
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "PJSIP process id %lu, thread name %s\n", pj_getpid(), pj_thread_get_name( pj_thread_this() ) );
-
if ((session = switch_core_session_request( &pjsip_endpoint_interface, NULL ))) {
struct private_object *tech_pvt;
switch_channel_t *channel;
@@ -775,30 +863,26 @@
/* allocate new session */
switch_core_session_add_stream( session, NULL );
- if (!(tech_pvt = (struct private_object *) switch_core_session_alloc( session, sizeof(struct private_object) ))) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new channel for inbound call\n" );
+ tech_pvt = (struct private_object *)
+ switch_core_session_alloc( session, sizeof(struct private_object) );
+ if (!tech_pvt) {
+ perror_(THIS_FILE, "Failed to create new channel for inbound call", -1);
switch_core_session_destroy( &session );
- return;
+ goto on_return;
}
- switch_core_session_set_private( session, tech_pvt );
tech_pvt->session = session;
+ switch_core_session_set_private( session, tech_pvt );
- switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED,
+ switch_core_session_get_pool(session));
+ switch_mutex_lock(tech_pvt->flag_mutex);
+
/* need the invite data in pjsip_on_init */
tech_pvt->sip_ua = pjsip_ua_instance();
tech_pvt->profile = profile;
- /* give the new session a name */
- pj_strdup_with_null( pjsip_pool, &tmp, &((pjsip_sip_uri *)rxdata->msg_info.from->uri)->host );
- snprintf( name, sizeof(name), "pjsip/%s/%s-%04x", profile->name, tmp.ptr, rand() & 0xffff );
- switch_channel_set_name( channel, name );
-
- switch_channel_clear_flag( channel, CF_OUTBOUND );
-
-
-
/* create UAS dialog */
status = pjsip_dlg_create_uas( tech_pvt->sip_ua, rxdata, NULL, &dialog );
if( status != PJ_SUCCESS ) {
@@ -806,14 +890,30 @@
pjsip_endpt_respond_stateless( globals.sip_endpt, rxdata,
500, &reason,
NULL, NULL);
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new pjsip dialog for inbound call\n" );
+ perror_(THIS_FILE,"Failed to create new pjsip dialog for inbound call", status);
+ switch_mutex_unlock(tech_pvt->flag_mutex);
switch_core_session_destroy( &session );
- return;
+ goto on_return;
}
+ /* give the new session a name */
+ pj_strdup_with_null( dialog->pool, &tmp,
+ &((pjsip_sip_uri *)rxdata->msg_info.from->uri)->host );
+ snprintf( name, sizeof(name), "pjsip/%s/%s-%04x", profile->name, tmp.ptr, rand() & 0xffff );
+ switch_channel_set_name( channel, name );
+
+ switch_channel_clear_flag( channel, CF_OUTBOUND );
+
+ /* lock dialog, to prevent callbacks to be called while we're setting
+ * up the dialog
+ */
+ pjsip_dlg_inc_lock(dialog);
+
/* load codecs */
- tech_pvt->num_codecs = switch_loadable_module_get_codecs( switch_core_session_get_pool(tech_pvt->session), tech_pvt->codecs,
- sizeof(tech_pvt->codecs) / sizeof(tech_pvt->codecs[0]) );
+ tech_pvt->num_codecs =
+ switch_loadable_module_get_codecs( switch_core_session_get_pool(tech_pvt->session),
+ tech_pvt->codecs,
+ sizeof(tech_pvt->codecs) / sizeof(tech_pvt->codecs[0]) );
/* Create our initial sdp */
create_sdp( dialog->pool, tech_pvt, &sdp, NULL );
@@ -821,35 +921,68 @@
/* Create UAS invite session */
- if ((status = pjsip_inv_create_uas( dialog, rxdata, sdp, 0, &tech_pvt->sip_invite ) != PJ_SUCCESS )) {
- pjsip_dlg_create_response( dialog, rxdata, 500, NULL, &txdata );
- pjsip_dlg_send_response( dialog, pjsip_rdata_get_tsx( rxdata ), txdata );
+ status = pjsip_inv_create_uas( dialog, rxdata, sdp, 0, &tech_pvt->sip_invite );
+ if (status != PJ_SUCCESS) {
+ pjsip_hdr hdr_list;
+ pjsip_warning_hdr *w;
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new pjsip dialog for inbound call\n" );
+ perror_(THIS_FILE, "Failed to create new pjsip dialog for inbound call", status );
+
+ /* Send 500, adding Warning header to explain why it went wrong */
+ w = pjsip_warning_hdr_create_from_status(dialog->pool,
+ pjsip_endpt_name(globals.sip_endpt),
+ status);
+ pj_list_init(&hdr_list);
+ pj_list_push_back(&hdr_list, w);
+
+ pjsip_dlg_respond(dialog, rxdata, 500, NULL, &hdr_list, NULL);
+
switch_core_session_destroy( &session );
- return;
+
+ /* unlock (and probably destroy) dialog */
+ pjsip_dlg_dec_lock(dialog);
+ switch_mutex_unlock(tech_pvt->flag_mutex);
+ goto on_return;
}
-
+
tech_pvt->sip_invite->mod_data[globals.mod_app.id] = tech_pvt;
tech_pvt->profile = profile;
- pj_strdup_with_null( pjsip_pool, &username, &((pjsip_sip_uri *)rxdata->msg_info.from->uri)->user );
- pj_strdup_with_null( pjsip_pool, &host, &((pjsip_sip_uri *)rxdata->msg_info.from->uri)->host );
- pj_strdup_with_null( pjsip_pool, &destination, &((pjsip_sip_uri *)rxdata->msg_info.to->uri)->host );
+ if (PJSIP_URI_SCHEME_IS_SIP(rxdata->msg_info.from->uri)) {
+ pjsip_sip_uri *sip_uri;
- if ( (tech_pvt->caller_profile = switch_caller_profile_new( switch_core_session_get_pool( session ),
- username.ptr,
- profile->dialplan,
- username.ptr,
- username.ptr,
- host.ptr,
- NULL,
- NULL,
- NULL,
- (char *)modname,
- NULL,
- destination.ptr)) != 0 ) {
+ sip_uri = pjsip_uri_get_uri(rxdata->msg_info.from->uri);
+ pj_strdup_with_null( dialog->pool, &username, &sip_uri->user );
+ pj_strdup_with_null( dialog->pool, &host, &sip_uri->host );
+ } else {
+ username = pj_str("anonymous");
+ username = pj_str("unknown");
+ }
+
+ if (PJSIP_URI_SCHEME_IS_SIP(rxdata->msg_info.to->uri)) {
+ pjsip_sip_uri *sip_uri;
+
+ sip_uri = pjsip_uri_get_uri(rxdata->msg_info.from->uri);
+ pj_strdup_with_null( dialog->pool, &destination, &sip_uri->user);
+ } else {
+ destination = pj_str("unknown");
+ }
+
+ tech_pvt->caller_profile =
+ switch_caller_profile_new( switch_core_session_get_pool( session ),
+ username.ptr,
+ profile->dialplan,
+ username.ptr,
+ username.ptr,
+ host.ptr,
+ NULL,
+ NULL,
+ NULL,
+ (char *)modname,
+ NULL,
+ destination.ptr);
+ if ( tech_pvt->caller_profile != 0 ) {
switch_channel_set_caller_profile( channel, tech_pvt->caller_profile );
}
@@ -861,51 +994,168 @@
/* Send 100 Trying */
status = pjsip_inv_initial_answer( tech_pvt->sip_invite, rxdata, 100, NULL, NULL, &txdata );
if( status != PJ_SUCCESS ) {
- status = pjsip_inv_initial_answer( tech_pvt->sip_invite, rxdata, PJSIP_SC_NOT_ACCEPTABLE, NULL, NULL, &txdata );
+ perror_(tech_pvt->sip_invite->dlg->obj_name, "Error in pjsip_inv_initial_answer", status);
- if( status == PJ_SUCCESS )
- pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
- else
- pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_FALSE );
+ pjsip_dlg_respond(dialog, rxdata, 500, NULL, NULL, NULL);
+ pjsip_inv_terminate(tech_pvt->sip_invite, 500, PJ_FALSE);
switch_core_session_destroy( &session );
- return;
+
+ /* unlock (and probably destroy) dialog */
+ pjsip_dlg_dec_lock(dialog);
+ switch_mutex_unlock(tech_pvt->flag_mutex);
+ goto on_return;
}
- pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
+ add_server_header(txdata);
+ status = pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
+ if( status != PJ_SUCCESS ) {
+ perror_(tech_pvt->sip_invite->dlg->obj_name, "Error in pjsip_inv_send_msg", status);
+ pjsip_dlg_respond(dialog, rxdata, 500, NULL, NULL, NULL);
+ pjsip_inv_terminate(tech_pvt->sip_invite, 500, PJ_FALSE);
+
+ switch_core_session_destroy( &session );
+
+ /* unlock (and probably destroy) dialog */
+ pjsip_dlg_dec_lock(dialog);
+ switch_mutex_unlock(tech_pvt->flag_mutex);
+ goto on_return;
+ }
+
/* Print the initial SDP to the console / log */
- {
+ if (0) {
char tmp_sdp[1024];
int len = pjmedia_sdp_print( sdp, tmp_sdp, sizeof(tmp_sdp)-1 );
if( len > 0 ) {
tmp_sdp[len] = '\0';
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
- "\n** Our initial SDP **\n%s\n*********************\n", tmp_sdp );
+ PJ_LOG(6,(THIS_FILE,
+ "\n** Our initial SDP **\n%s\n*********************\n", tmp_sdp ));
}
}
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Starting session thread for call %s\n", tech_pvt->call_id );
+ PJ_LOG(4,(THIS_FILE, "Starting session thread for call %s", tech_pvt->call_id ));
/* set initial state */
switch_channel_set_state( channel, CS_INIT );
+
+ /* Ugly hack: force pjsip_inv to negotiate media. */
+ status = pjsip_inv_answer( tech_pvt->sip_invite, 183, NULL, NULL, &txdata );
+ pjsip_tx_data_dec_ref(txdata);
+
+ /* Send 180 Ring */
+ status = pjsip_inv_answer( tech_pvt->sip_invite, 180, NULL, NULL, &txdata );
+ if( status != PJ_SUCCESS ) {
+ perror_(tech_pvt->sip_invite->dlg->obj_name, "pjsip_inv_answer error", status);
+
+ status = pjsip_inv_answer( tech_pvt->sip_invite, PJSIP_SC_NOT_ACCEPTABLE,
+ NULL, NULL, &txdata );
+
+ if( status == PJ_SUCCESS )
+ pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
+ else
+ pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_FALSE );
+
+ switch_core_session_destroy( &session );
+ goto on_return;
+ }
+ add_server_header(txdata);
+ status = pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
+ if( status != PJ_SUCCESS ) {
+ perror_(tech_pvt->sip_invite->dlg->obj_name, "pjsip_inv_send_msg error", status);
+ switch_core_session_destroy( &session );
+ goto on_return;
+ }
+
+ switch_mutex_unlock(tech_pvt->flag_mutex);
switch_core_session_thread_launch( session );
- return;
+
+ /* Done setting up UAS invite session, release lock */
+ pjsip_dlg_dec_lock(dialog);
+ goto on_return;
} else {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new channel for inbound call\n" );
- return;
+ perror_(THIS_FILE, "Failed to create new channel for inbound call", -1);
+ goto on_return;
}
+
+on_return:
+ TRACE_((THIS_FILE, "LEAVE on_incoming_call"));
+
}
+/* Handle incoming OPTIONS request */
+static void on_incoming_options( pjsip_rx_data *rdata )
+{
+ pjsip_tx_data *tdata;
+ pjsip_response_addr res_addr;
+ //pjmedia_sdp_session *sdp;
+ const pjsip_hdr *cap_hdr;
+ pj_status_t status;
+
+ /* Create basic response. */
+ status = pjsip_endpt_create_response(globals.sip_endpt, rdata, 200, NULL, &tdata);
+ if (status != PJ_SUCCESS) {
+ return;
+ }
+
+ /* Add Allow header */
+ cap_hdr = pjsip_endpt_get_capability(globals.sip_endpt, PJSIP_H_ALLOW, NULL);
+ if (cap_hdr) {
+ pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_clone(tdata->pool, cap_hdr));
+ }
+
+ /* Add Accept header */
+ cap_hdr = pjsip_endpt_get_capability(globals.sip_endpt, PJSIP_H_ACCEPT, NULL);
+ if (cap_hdr) {
+ pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_clone(tdata->pool, cap_hdr));
+ }
+
+ /* Add Supported header */
+ cap_hdr = pjsip_endpt_get_capability(globals.sip_endpt, PJSIP_H_SUPPORTED, NULL);
+ if (cap_hdr) {
+ pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_clone(tdata->pool, cap_hdr));
+ }
+
+ /* Add Allow-Events header from the evsub module */
+ cap_hdr = pjsip_evsub_get_allow_events_hdr(NULL);
+ if (cap_hdr) {
+ pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_clone(tdata->pool, cap_hdr));
+ }
+
+ /* Add Server header */
+ add_server_header(tdata);
+
+ /* TODO: it would be nice if we could add SDP body here (dunno how) */
+ //PJ_TODO(ADD_SDP_TO_OPTIONS_RESPONSE);
+#if 0
+ status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, tdata->pool, 1,
+ &pjsua_var.calls[0].skinfo, &sdp);
+ if (status == PJ_SUCCESS) {
+ pjsip_create_sdp_body(tdata->pool, sdp, &tdata->msg->body);
+ }
+#endif
+
+ /* Send response statelessly */
+ pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
+ status = pjsip_endpt_send_response(globals.sip_endpt, &res_addr, tdata, NULL, NULL);
+ if (status != PJ_SUCCESS)
+ pjsip_tx_data_dec_ref(tdata);
+}
+
+
static pj_bool_t on_rx_request( pjsip_rx_data *rxdata )
{
pj_str_t reason;
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s: received new request\n", __FUNCTION__ );
+ PJ_LOG(4,(THIS_FILE,"%s: received new request", __FUNCTION__ ));
switch( rxdata->msg_info.msg->line.req.method.id ) {
case PJSIP_INVITE_METHOD:
on_incoming_call( rxdata );
return PJ_TRUE;
;;
+ case PJSIP_OPTIONS_METHOD:
+ on_incoming_options( rxdata );
+ return PJ_TRUE;
+ ;;
default:
reason = rxdata->msg_info.msg->line.req.method.name;
pjsip_endpt_respond_stateless( rxdata->tp_info.transport->endpt, rxdata,
@@ -923,16 +1173,25 @@
assert( inv != NULL && tsx != NULL );
- tech_pvt = inv->mod_data[globals.mod_app.id];
- assert( tech_pvt != NULL );
+ if (!(tech_pvt = inv->mod_data[globals.mod_app.id])) {
+ return;
+ }
+
+ TRACE_((THIS_FILE, "ENTER call_on_tsx_state_changed"));
+
+ switch_mutex_lock(tech_pvt->flag_mutex);
+
profile = tech_pvt->profile;
assert( profile != NULL );
session = tech_pvt->session;
assert( session != NULL );
- if( inv->state == PJSIP_INV_STATE_EARLY &&
+ switch_mutex_unlock(tech_pvt->flag_mutex);
+
+ if( tsx->method.id == PJSIP_INVITE_METHOD &&
+ inv->state == PJSIP_INV_STATE_EARLY &&
tsx->state == PJSIP_TSX_STATE_PROCEEDING &&
tsx->status_code == PJSIP_SC_RINGING )
{
@@ -941,41 +1200,55 @@
channel = switch_core_session_get_channel( session );
assert( channel != NULL );
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "* Ring received (call %s)\n", tech_pvt->call_id );
+ PJ_LOG(4,(THIS_FILE, "* Ring received (call %s)", tech_pvt->call_id ));
}
+ TRACE_((THIS_FILE, "LEAVE call_on_tsx_state_changed"));
}
static void call_on_forked( pjsip_inv_session *inv,
pjsip_event *evt ) { }
/* pjsip callback for inv session state changes */
-static void call_on_state_changed( pjsip_inv_session *inv,
- pjsip_event *evt )
+static void call_on_state_changed( pjsip_inv_session *inv, pjsip_event *evt )
{
struct private_object *tech_pvt;
struct pjsip_profile *profile;
switch_core_session_t *session;
switch_channel_t *channel;
- assert( evt != NULL && inv != NULL );
+ assert ( evt != NULL);
+ assert ( inv != NULL );
+
+ if (!(tech_pvt = inv->mod_data[globals.mod_app.id])) {
+ return;
+ }
- tech_pvt = inv->mod_data[globals.mod_app.id];
- assert( tech_pvt != NULL );
+ TRACE_((THIS_FILE, "ENTER call_on_state_changed"));
+ assert( tech_pvt->flag_mutex != NULL );
+
+ switch_mutex_lock(tech_pvt->flag_mutex);
+
session = tech_pvt->session;
assert ( session != NULL );
profile = tech_pvt->profile;
assert( profile != NULL );
+ switch_mutex_unlock(tech_pvt->flag_mutex);
+
+
channel = switch_core_session_get_channel( session );
assert( channel != NULL );
+
+
switch( inv->state )
{
case PJSIP_INV_STATE_DISCONNECTED:
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "* Call %s (%s) has been disconnected\n", tech_pvt->call_id,
- switch_channel_get_name( channel ) );
+ inv->mod_data[globals.mod_app.id] = NULL;
+ PJ_LOG(4,(THIS_FILE, "* Call %s (%s) has been disconnected", tech_pvt->call_id,
+ switch_channel_get_name( channel ) ));
if( !switch_test_flag( tech_pvt, TFLAG_BYE ) ) {
switch_call_cause_t cause;
@@ -983,14 +1256,22 @@
switch( evt->body.rx_msg.rdata->msg_info.msg->line.status.code )
{
default:
+ /* bennylp: we can get the INVITE disconnect cause from inv->cause.
+ * and the reason in inv->cause_text.
+ * But how do we map it to switch cause?
+ */
+ //PJ_TODO(MAP_SIP_STATUS_CODE_TO_SWITCH_CAUSE_CODE);
cause = SWITCH_CAUSE_NORMAL_CLEARING;
}
+ TRACE_((THIS_FILE, "LOOK HERE!!! Entering switch_channel_hangup for dialog %s",
+ inv->dlg->obj_name));
switch_channel_hangup( channel, cause );
+ TRACE_((THIS_FILE, "LOOK HERE!!! Leaving switch_channel_hangup"));
}
break;
case PJSIP_INV_STATE_CONFIRMED:
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "* Call %s (%s) has been connected\n", tech_pvt->call_id,
- switch_channel_get_name( channel ) );
+ PJ_LOG(4,(THIS_FILE, "* Call %s (%s) has been connected", tech_pvt->call_id,
+ switch_channel_get_name( channel ) ));
/* -> connected */
if( switch_channel_test_flag( channel, CF_OUTBOUND ) ) {
@@ -999,9 +1280,9 @@
break;
case PJSIP_INV_STATE_EARLY:
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "* Call %s (%s), state %s\n", tech_pvt->call_id,
+ PJ_LOG(4,(THIS_FILE, "* Call %s (%s), state %s", tech_pvt->call_id,
switch_channel_get_name( channel ),
- pjsip_inv_state_name( inv->state ) );
+ pjsip_inv_state_name( inv->state ) ));
#if 0
/* -> inbound ringing */
@@ -1015,9 +1296,9 @@
break;
case PJSIP_INV_STATE_CONNECTING:
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "* Call %s (%s), state %s\n", tech_pvt->call_id,
+ PJ_LOG(4,(THIS_FILE, "* Call %s (%s), state %s", tech_pvt->call_id,
switch_channel_get_name( channel ),
- pjsip_inv_state_name( inv->state ) );
+ pjsip_inv_state_name( inv->state ) ));
#if 0
/* -> outbound ringing */
@@ -1030,16 +1311,18 @@
break;
case PJSIP_INV_STATE_CALLING:
case PJSIP_INV_STATE_INCOMING:
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "* Call %s (%s), state %s\n", tech_pvt->call_id,
+ PJ_LOG(4,(THIS_FILE, "* Call %s (%s), state %s", tech_pvt->call_id,
switch_channel_get_name( channel ),
- pjsip_inv_state_name( inv->state ) );
+ pjsip_inv_state_name( inv->state ) ));
break;
default:
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "* Call %s (%s), UNHANDLED state %s\n", tech_pvt->call_id,
+ PJ_LOG(4,( THIS_FILE, "* Call %s (%s), UNHANDLED state %s", tech_pvt->call_id,
switch_channel_get_name( channel ),
- pjsip_inv_state_name( inv->state ) );
+ pjsip_inv_state_name( inv->state ) ));
break;
}
+
+ TRACE_((THIS_FILE, "LEAVE call_on_state_changed"));
}
/* pjsip callback for sdp negotiation changes */
@@ -1057,11 +1340,15 @@
int ms, rate;
pj_sockaddr addr;
+ TRACE_((THIS_FILE, "ENTER call_on_media_update"));
+
tech_pvt = inv->mod_data[globals.mod_app.id];
assert( tech_pvt != NULL );
+ switch_mutex_lock(tech_pvt->flag_mutex);
profile = tech_pvt->profile;
assert( profile != NULL );
+ switch_mutex_unlock(tech_pvt->flag_mutex);
pool = inv->dlg->pool;
assert( pool != NULL );
@@ -1072,23 +1359,24 @@
channel = switch_core_session_get_channel( tech_pvt->session );
assert( channel != NULL );
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "-- SDP negotiation status change %s (state %s, status %d)\n", tech_pvt->call_id,
- pjmedia_sdp_neg_state_str(pjmedia_sdp_neg_get_state( inv->neg )), status );
+ PJ_LOG(4,(THIS_FILE, "-- SDP negotiation status change %s (state %s, status %d)", tech_pvt->call_id,
+ pjmedia_sdp_neg_state_str(pjmedia_sdp_neg_get_state( inv->neg )), status ));
if( pjmedia_sdp_neg_get_state( inv->neg ) != PJMEDIA_SDP_NEG_STATE_DONE ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "---- SDP negotiation still ongoing for call %s\n", tech_pvt->call_id );
+ PJ_LOG(4,( THIS_FILE, "---- SDP negotiation still ongoing for call %s", tech_pvt->call_id ));
}
if( status != PJ_SUCCESS ) {
char tmp[1024];
pj_strerror( status, tmp, sizeof(tmp) );
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SDP negotiation failed for call %s, reason: %s\n", tech_pvt->call_id, tmp );
+ PJ_LOG(1,(THIS_FILE, "SDP negotiation failed for call %s, reason: %s", tech_pvt->call_id, tmp ));
switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
+ TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
return;
}
if( tech_pvt->rtp_session ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SDP re-negotiation received %s\n", tech_pvt->call_id );
+ PJ_LOG(1,(THIS_FILE, "SDP re-negotiation received %s", tech_pvt->call_id ));
stop_rtp( tech_pvt );
switch_clear_flag_locked( tech_pvt, TFLAG_IO );
@@ -1104,33 +1392,42 @@
pjmedia_sdp_neg_get_active_remote( inv->neg, &remote_sdp );
/* Print the final(?) SDPs to the console / log */
- {
+ if (0) {
char tmp_sdp[1024];
int len;
len = pjmedia_sdp_print( local_sdp, tmp_sdp, sizeof(tmp_sdp)-1 );
if( len > 0 ) {
tmp_sdp[len] = '\0';
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
- "\n** Our final SDP **\n%s\n*********************\n", tmp_sdp );
+ PJ_LOG(5,(THIS_FILE,
+ "\n** Our final SDP **\n%s\n*********************\n", tmp_sdp ));
}
len = pjmedia_sdp_print( remote_sdp, tmp_sdp, sizeof(tmp_sdp)-1 );
if( len > 0 ) {
tmp_sdp[len] = '\0';
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
- "\n** Remote final SDP **\n%s\n*************************\n", tmp_sdp );
+ PJ_LOG(5,(THIS_FILE,
+ "\n** Remote final SDP **\n%s\n*************************\n", tmp_sdp ));
}
}
+ /* Check if call is put on hold. */
+ if (local_sdp->media_count == 0 ||
+ pjmedia_sdp_media_find_attr2(local_sdp->media[0], "inactive", NULL) != NULL)
+ {
+ //PJ_TODO(HANDLE_CALL_HOLD);
+ }
+
+
/* retrieve stream (= codec) information */
status = mod_pjsip_codec_from_sdp( tech_pvt, pool, local_sdp, remote_sdp, 0, &codec, &imp );
if( status != PJ_SUCCESS ) {
/* No valid codec found */
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SDP negotation failed, codec unknown\n" );
+ perror_(THIS_FILE, "SDP negotation failed, codec unknown", status );
switch_set_flag_locked( tech_pvt, TFLAG_BYE );
switch_clear_flag_locked( tech_pvt, TFLAG_IO );
switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
+ TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
return;
}
@@ -1138,7 +1435,7 @@
rate = imp->bits_per_second / 8;
ms = imp->microseconds_per_frame / 1000;
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Codec %s, rate: %d, ms per frame: %d\n", codec->iananame, rate, ms );
+ PJ_LOG(4,(THIS_FILE, "Codec %s, rate: %d, ms per frame: %d", codec->iananame, rate, ms ));
/* initialize codecs */
ret = switch_core_codec_init(&tech_pvt->read_codec, codec->iananame, rate, ms, 1,
@@ -1146,8 +1443,9 @@
NULL, switch_core_session_get_pool( session ));
if( ret != SWITCH_STATUS_SUCCESS ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize read codec\n" );
+ perror_(THIS_FILE, "Failed to initialize read codec", -1);
switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
+ TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
return;
}
@@ -1156,8 +1454,9 @@
NULL, switch_core_session_get_pool( session ));
if( ret != SWITCH_STATUS_SUCCESS ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize write codec\n" );
+ perror_(THIS_FILE, "ERROR: Failed to initialize write codec", -1 );
switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
+ TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
return;
}
@@ -1170,7 +1469,7 @@
/* update remote rtp IP and port, restart rtp */
status = mod_pjsip_addr_from_sdp( remote_sdp, 0, &addr );
if( status != PJ_SUCCESS ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get remote RTP endpoint address and port\n" );
+ perror_(THIS_FILE, "Failed to get remote RTP endpoint address and port", status);
switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
} else {
pj_in_addr tmp_addr;
@@ -1180,16 +1479,20 @@
strncpy( tech_pvt->remote_sdp_audio_addr, pj_inet_ntoa( tmp_addr ),
sizeof(tech_pvt->remote_sdp_audio_addr) );
}
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Codec %s, %s:%d\n", codec->iananame, tech_pvt->remote_sdp_audio_addr, tech_pvt->remote_sdp_audio_port );
+ PJ_LOG(4,(THIS_FILE, "Codec %s, %s:%d", codec->iananame,
+ tech_pvt->remote_sdp_audio_addr, tech_pvt->remote_sdp_audio_port ));
/* start rtp */
start_rtp( tech_pvt );
/* activate io */
switch_set_flag_locked( tech_pvt, TFLAG_IO );
+
+ TRACE_((THIS_FILE, "LEAVE call_on_media_update"));
}
-static switch_status_t pjsip_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+static switch_status_t pjsip_receive_message(switch_core_session_t *session,
+ switch_core_session_message_t *msg)
{
struct private_object *tech_pvt;
switch_channel_t *channel;
@@ -1222,16 +1525,19 @@
/* Send 183 Session Progress */
status = pjsip_inv_answer( tech_pvt->sip_invite, 183, NULL, NULL, &txdata );
if( status != PJ_SUCCESS ) {
- status = pjsip_inv_answer( tech_pvt->sip_invite, PJSIP_SC_NOT_ACCEPTABLE, NULL, NULL, &txdata );
+ status = pjsip_inv_answer( tech_pvt->sip_invite, PJSIP_SC_NOT_ACCEPTABLE,
+ NULL, NULL, &txdata );
- if( status == PJ_SUCCESS )
+ if( status == PJ_SUCCESS ) {
+ add_server_header(txdata);
pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
- else
+ } else
pjsip_inv_terminate( tech_pvt->sip_invite, 500, PJ_FALSE );
switch_core_session_destroy( &session );
return SWITCH_STATUS_GENERR;
}
+ add_server_header(txdata);
pjsip_inv_send_msg( tech_pvt->sip_invite, txdata );
}
switch_channel_set_flag( channel, CF_EARLY_MEDIA );
@@ -1295,7 +1601,8 @@
media->desc.port_count = 1;
media->desc.transport = pj_str( "RTP/AVP" );
- strncpy( tech_pvt->local_sdp_audio_addr, profile->local_addr, sizeof(tech_pvt->local_sdp_audio_addr) );
+ strncpy( tech_pvt->local_sdp_audio_addr, profile->local_addr,
+ sizeof(tech_pvt->local_sdp_audio_addr) );
/* codec rtpmap list */
media->desc.fmt_count = 0;
@@ -1374,20 +1681,24 @@
assert( tech_pvt != NULL );
+ TRACE_((THIS_FILE, "ENTER start_rtp"));
+
channel = switch_core_session_get_channel( tech_pvt->session );
assert( channel != NULL );
if( tech_pvt->rtp_session ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP already initialized %s\n", tech_pvt->call_id );
+ PJ_LOG(4,(THIS_FILE, "RTP already initialized %s", tech_pvt->call_id ));
+ TRACE_((THIS_FILE, "LEAVE start_rtp"));
return SWITCH_STATUS_SUCCESS;
}
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting RTP for call %s\n", tech_pvt->call_id );
+ PJ_LOG(4,(THIS_FILE, "Starting RTP for call %s", tech_pvt->call_id ));
rate = tech_pvt->read_codec.implementation->bits_per_second;
ms = tech_pvt->read_codec.implementation->microseconds_per_frame;
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP parameters for call %s: src (%s:%d) -> dst (%s:%d), using codec %s @ %d b/s, framelen %d ms\n",
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
+ "RTP parameters for call %s: src (%s:%d) -> dst (%s:%d), using codec %s @ %d b/s, framelen %d ms\n",
tech_pvt->call_id,
tech_pvt->local_sdp_audio_addr,
tech_pvt->local_sdp_audio_port,
@@ -1411,8 +1722,10 @@
&err, switch_core_session_get_pool( tech_pvt->session ) );
if( !tech_pvt->rtp_session ) {
+ PJ_LOG(1,(THIS_FILE, "RTP ERROR [%s]", err));
switch_channel_hangup( channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER );
switch_set_flag_locked( tech_pvt, TFLAG_BYE );
+ TRACE_((THIS_FILE, "LEAVE start_rtp"));
return SWITCH_STATUS_FALSE;
}
@@ -1420,6 +1733,7 @@
switch_set_flag_locked( tech_pvt, TFLAG_IO);
+ TRACE_((THIS_FILE, "LEAVE start_rtp"));
return SWITCH_STATUS_SUCCESS;
}
@@ -1430,6 +1744,8 @@
if( !tech_pvt->rtp_session )
return SWITCH_STATUS_SUCCESS;
+ TRACE_((THIS_FILE, "ENTER stop_rtp"));
+
while( loop < 10 &&
( switch_test_flag( tech_pvt, TFLAG_READING ) ||
switch_test_flag( tech_pvt, TFLAG_WRITING ) ) )
@@ -1438,9 +1754,12 @@
loop++;
}
+ switch_mutex_lock(tech_pvt->flag_mutex);
switch_rtp_destroy( &tech_pvt->rtp_session );
tech_pvt->rtp_session = NULL;
-
+ switch_mutex_unlock(tech_pvt->flag_mutex);
+
+ TRACE_((THIS_FILE, "LEAVE stop_rtp"));
return SWITCH_STATUS_SUCCESS;
}
@@ -1465,7 +1784,8 @@
}
if( !(profile = switch_core_alloc( module_pool, sizeof(struct pjsip_profile))) ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to allocate new profile %s\n", profile_name );
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
+ "Failed to allocate new profile %s\n", profile_name );
result = SWITCH_STATUS_TERM;
goto out;
}
@@ -1488,7 +1808,8 @@
pj_str_t tmp;
if( !pj_inet_aton( pj_cstr( &tmp, val ), &profile->sip_addr.sin_addr ) ) {
- switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid address: %s\n", val );
+ switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Invalid address: %s\n", val );
result = SWITCH_STATUS_TERM;
goto out;
}
@@ -1585,6 +1906,88 @@
return SWITCH_STATUS_SUCCESS;
}
+
+/*****************************************************************************
+ * This is a very simple PJSIP module, whose sole purpose is to display
+ * incoming and outgoing messages to log. This module will have priority
+ * higher than transport layer, which means:
+ *
+ * - incoming messages will come to this module first before reaching
+ * transaction layer.
+ *
+ * - outgoing messages will come to this module last, after the message
+ * has been 'printed' to contiguous buffer by transport layer and
+ * appropriate transport instance has been decided for this message.
+ *
+ */
+
+/* Notification on incoming messages */
+static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
+{
+ PJ_LOG(5,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ rdata->msg_info.len,
+ pjsip_rx_data_get_info(rdata),
+ rdata->tp_info.transport->type_name,
+ rdata->pkt_info.src_name,
+ rdata->pkt_info.src_port,
+ (int)rdata->msg_info.len,
+ rdata->msg_info.msg_buf));
+
+ /* Always return false, otherwise messages will not get processed! */
+ return PJ_FALSE;
+}
+
+/* Notification on outgoing messages */
+static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
+{
+
+ /* Important note:
+ * tp_info field is only valid after outgoing messages has passed
+ * transport layer. So don't try to access tp_info when the module
+ * has lower priority than transport layer.
+ */
+
+ PJ_LOG(5,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
+ "%.*s\n"
+ "--end msg--",
+ (tdata->buf.cur - tdata->buf.start),
+ pjsip_tx_data_get_info(tdata),
+ tdata->tp_info.transport->type_name,
+ tdata->tp_info.dst_name,
+ tdata->tp_info.dst_port,
+ (int)(tdata->buf.cur - tdata->buf.start),
+ tdata->buf.start));
+
+ /* Always return success, otherwise message will not get sent! */
+ return PJ_SUCCESS;
+}
+
+/* The module instance. */
+static pjsip_module pjsua_msg_logger =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-pjsua-log", 13 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &logging_on_rx_msg, /* on_rx_request() */
+ &logging_on_rx_msg, /* on_rx_response() */
+ &logging_on_tx_msg, /* on_tx_request. */
+ &logging_on_tx_msg, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+
+};
+
+
+
+
+
+
SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
{
switch_hash_index_t *p_entry;
@@ -1597,7 +2000,8 @@
return SWITCH_STATUS_TERM;
}
- pj_log_set_level(0);
+ pj_log_set_log_func(log_func);
+ pj_log_set_level(4);
/* next: pjlib_util */
status = pjlib_util_init();
@@ -1616,6 +2020,9 @@
return SWITCH_STATUS_TERM;
}
+ /* Initialize server name */
+ pj_strdup2_with_null(pjsip_pool, &FREESWITCH_SERVER, "FreeSWITCH (mod_pjsip)");
+
if( config_pjsip( ) != SWITCH_STATUS_SUCCESS ) {
switch_log_printf( SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load configuration\n" );
return SWITCH_STATUS_TERM;
@@ -1635,6 +2042,11 @@
invite_cb.on_tsx_state_changed = &call_on_tsx_state_changed;
/*
+ * Register logger module.
+ */
+ pjsip_endpt_register_module(globals.sip_endpt, &pjsua_msg_logger);
+
+ /*
*
*/
for( p_entry = switch_hash_first( module_pool, globals.profiles_hash ); p_entry; p_entry = switch_hash_next( p_entry ) )
@@ -1747,7 +2159,9 @@
globals.running = 1;
while ( globals.running > 0 ) {
pj_time_val timeout = { 1, 0 };
+ TRACE_((THIS_FILE, "ENTER pjsip_endpt_handle_events"));
pjsip_endpt_handle_events( globals.sip_endpt, &timeout );
+ TRACE_((THIS_FILE, "LEAVE pjsip_endpt_handle_events"));
}
globals.running = 0;
@@ -1755,3 +2169,4 @@
return SWITCH_STATUS_TERM;
}
+
Modified: freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip_sdp.c
==============================================================================
--- freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip_sdp.c (original)
+++ freeswitch/branches/bennylp/src/mod/endpoints/mod_pjsip/mod_pjsip_sdp.c Fri Aug 11 14:24:06 2006
@@ -21,7 +21,7 @@
#include <switch.h>
#include <pjlib.h>
#include <pjsip_ua.h>
-#include <pjsdp.h>
+#include <pjmedia.h>
#include "mod_pjsip.h"
More information about the Freeswitch-branches
mailing list