summaryrefslogtreecommitdiff
path: root/pjsip-apps
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-03-17 18:01:27 +0000
committerBenny Prijono <bennylp@teluu.com>2006-03-17 18:01:27 +0000
commit0dcbe1ea68c039b92076083137062b4cc6363967 (patch)
tree3a47d1a6f6aff0e66e58d2850308dc67e258792c /pjsip-apps
parenta53456a95969fe64e907bc7a5abcf4f1dcdce0ba (diff)
Added samples (finally!!)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@328 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip-apps')
-rw-r--r--pjsip-apps/build/Samples-vc.mak51
-rw-r--r--pjsip-apps/build/Samples.mak66
-rw-r--r--pjsip-apps/build/pjsip_apps.dsw36
-rw-r--r--pjsip-apps/build/samples.dsp108
-rw-r--r--pjsip-apps/src/pjsip-perf/handler_call.c8
-rw-r--r--pjsip-apps/src/samples/simpleua.c519
-rw-r--r--pjsip-apps/src/samples/util.h123
7 files changed, 907 insertions, 4 deletions
diff --git a/pjsip-apps/build/Samples-vc.mak b/pjsip-apps/build/Samples-vc.mak
new file mode 100644
index 00000000..cc80e557
--- /dev/null
+++ b/pjsip-apps/build/Samples-vc.mak
@@ -0,0 +1,51 @@
+
+MACHINE_NAME = i386
+OS_NAME = win32
+CC_NAME = vc6-$(BUILD_MODE)
+LIBEXT = .lib
+
+!if "$(BUILD_MODE)" == "debug"
+BUILD_FLAGS = /MTd /Od /Zi
+!else
+BUILD_FLAGS = /Ox /MD /DNDEBUG
+!endif
+
+PJLIB_LIB = ..\..\pjlib\lib\pjlib-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJLIB_UTIL_LIB = ..\..\pjlib-util\lib\pjlib-util-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJMEDIA_LIB = ..\..\pjmedia\lib\pjmedia-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJMEDIA_CODEC_LIB = ..\..\pjmedia\lib\pjmedia-codec-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJSIP_LIB = ..\..\pjsip\lib\pjsip-core-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJSIP_UA_LIB = ..\..\pjsip\lib\pjsip-ua-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJSIP_SIMPLE_LIB = ..\..\pjsip\lib\pjsip-simple-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJSUA_LIB_LIB = ..\..\pjsip\lib\pjsua-lib-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+
+LIBS = $(PJSUA_LIB_LIB) $(PJSIP_UA_LIB) $(PJSIP_SIMPLE_LIB) \
+ $(PJSIP_LIB) $(PJMEDIA_CODEC_LIB) $(PJMEDIA_LIB) \
+ $(PJLIB_UTIL_LIB) $(PJLIB_LIB)
+
+CFLAGS = /DPJ_WIN32=1 /DPJ_M_I386=1 \
+ $(BUILD_FLAGS) \
+ -I..\..\pjsip\include \
+ -I..\..\pjlib\include -I..\..\pjlib-util\include \
+ -I..\..\pjmedia\include
+LDFLAGS = $(BUILD_FLAGS) $(LIBS) \
+ ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib \
+ mswsock.lib ws2_32.lib
+
+SRCDIR = ..\src\samples
+OBJDIR = .\output\samples-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)
+BINDIR = ..\bin\samples
+
+
+SAMPLES = $(BINDIR)\simpleua.exe
+
+all: $(OBJDIR) $(SAMPLES)
+
+$(SAMPLES): $(SRCDIR)\$(@B).c $(LIBS) Samples-vc.mak
+ cl -nologo -c $(SRCDIR)\$(@B).c /Fo$(OBJDIR)\$(@B).obj $(CFLAGS)
+ cl /nologo $(OBJDIR)\$(@B).obj /Fe$@ /Fm$(OBJDIR)\$(@B).map $(LDFLAGS)
+
+$(OBJDIR):
+ mkdir $(OBJDIR)
+
+
diff --git a/pjsip-apps/build/Samples.mak b/pjsip-apps/build/Samples.mak
new file mode 100644
index 00000000..e3d89904
--- /dev/null
+++ b/pjsip-apps/build/Samples.mak
@@ -0,0 +1,66 @@
+
+include ../../build/common.mak
+
+PJLIB_LIB:=../../pjlib/lib/libpj-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJLIB_UTIL_LIB:=../../pjlib-util/lib/libpjlib-util-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJMEDIA_LIB:=../../pjmedia/lib/libpjmedia-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJMEDIA_CODEC_LIB:=../../pjmedia/lib/libpjmedia-codec-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJSIP_LIB:=../../pjsip/lib/libpjsip-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJSIP_UA_LIB:=../../pjsip/lib/libpjsip-ua-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJSIP_SIMPLE_LIB:=../../pjsip/lib/libpjsip-simple-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+PJSUA_LIB_LIB=../../pjsip/lib/libpjsua-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT)
+
+
+###############################################################################
+# Gather all flags.
+#
+export _CFLAGS := $(CC_CFLAGS) $(OS_CFLAGS) $(HOST_CFLAGS) $(M_CFLAGS) \
+ $(CFLAGS) $(CC_INC)../../pjsip/include $(CC_INC)../../pjlib/include \
+ $(CC_INC)../../pjlib-util/include $(CC_INC)../../pjmedia/include
+export _CXXFLAGS:= $(_CFLAGS) $(CC_CXXFLAGS) $(OS_CXXFLAGS) $(M_CXXFLAGS) \
+ $(HOST_CXXFLAGS) $(CXXFLAGS)
+export _LDFLAGS := $(subst /,$(HOST_PSEP),$(PJSUA_LIB_LIB)) \
+ $(subst /,$(HOST_PSEP),$(PJSIP_UA_LIB)) \
+ $(subst /,$(HOST_PSEP),$(PJSIP_SIMPLE_LIB)) \
+ $(subst /,$(HOST_PSEP),$(PJSIP_LIB)) \
+ $(subst /,$(HOST_PSEP),$(PJMEDIA_CODEC_LIB)) \
+ $(subst /,$(HOST_PSEP),$(PJMEDIA_LIB)) \
+ $(subst /,$(HOST_PSEP),$(PJLIB_UTIL_LIB)) \
+ $(subst /,$(HOST_PSEP),$(PJLIB_LIB)) \
+ $(CC_LDFLAGS) $(OS_LDFLAGS) $(M_LDFLAGS) $(HOST_LDFLAGS) \
+ $(LDFLAGS) -lm
+
+SRCDIR := ../src/samples
+OBJDIR := ./output/samples-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)
+BINDIR := ../bin/samples
+
+CFLAGS = $(_CFLAGS)
+LDFLAGS = $(_LDFLAGS)
+
+SAMPLES := simpleua
+EXES := $(foreach file, $(SAMPLES), $(BINDIR)/$(file)-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(HOST_EXE))
+
+all: $(OBJDIR) $(EXES)
+
+$(BINDIR)/%-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(HOST_EXE): $(OBJDIR)/%$(OBJEXT)
+ $(LD) $(LDOUT)$(subst /,$(HOST_PSEP),$@) \
+ $(subst /,$(HOST_PSEP),$<) \
+ $(_LDFLAGS)
+
+$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.c
+ $(CC) $(CFLAGS) \
+ $(CC_OUT)$(subst /,$(HOST_PSEP),$@) \
+ $(subst /,$(HOST_PSEP),$<)
+
+$(OBJDIR):
+ $(subst @@,$(subst /,$(HOST_PSEP),$@),$(HOST_MKDIR))
+
+clean:
+ $(subst @@,$(subst /,$(HOST_PSEP),$(OBJDIR)/*),$(HOST_RMR))
+ $(subst @@,$(subst /,$(HOST_PSEP),$(OBJDIR)),$(HOST_RMDIR))
+
+distclean realclean: clean
+ $(subst @@,$(EXES),$(HOST_RM))
+# $(subst @@,$(subst /,$(HOST_PSEP),$(EXES)) $(subst /,$(HOST_PSEP),$(EXES)),$(HOST_RM))
+# $(subst @@,$(DEP_FILE),$(HOST_RM))
+
diff --git a/pjsip-apps/build/pjsip_apps.dsw b/pjsip-apps/build/pjsip_apps.dsw
index 21645077..63bec1d3 100644
--- a/pjsip-apps/build/pjsip_apps.dsw
+++ b/pjsip-apps/build/pjsip_apps.dsw
@@ -168,6 +168,42 @@ Package=<4>
###############################################################################
+Project: "samples"=".\samples.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name pjlib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjlib_util
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjmedia_codec
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_core
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_simple
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_ua
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsua_lib
+ End Project Dependency
+}}}
+
+###############################################################################
+
Global:
Package=<5>
diff --git a/pjsip-apps/build/samples.dsp b/pjsip-apps/build/samples.dsp
new file mode 100644
index 00000000..2fb8cddb
--- /dev/null
+++ b/pjsip-apps/build/samples.dsp
@@ -0,0 +1,108 @@
+# Microsoft Developer Studio Project File - Name="samples" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=samples - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "samples.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "samples.mak" CFG="samples - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "samples - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "samples - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "samples - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "./output/samples-i386-win32-vc6-release"
+# PROP BASE Intermediate_Dir "./output/samples-i386-win32-vc6-release"
+# PROP BASE Cmd_Line "NMAKE /f samples.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "samples.exe"
+# PROP BASE Bsc_Name "samples.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "./output/samples-i386-win32-vc6-release"
+# PROP Intermediate_Dir "./output/samples-i386-win32-vc6-release"
+# PROP Cmd_Line "nmake /f Samples-vc.mak BUILD_MODE=release"
+# PROP Rebuild_Opt "/a"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF "$(CFG)" == "samples - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "./output/samples-i386-win32-vc6-debug"
+# PROP BASE Intermediate_Dir "./output/samples-i386-win32-vc6-debug"
+# PROP BASE Cmd_Line "NMAKE /f samples.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "samples.exe"
+# PROP BASE Bsc_Name "samples.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "./output/samples-i386-win32-vc6-debug"
+# PROP Intermediate_Dir "./output/samples-i386-win32-vc6-debug"
+# PROP Cmd_Line "nmake /NOLOGO /S /f Samples-vc.mak BUILD_MODE=debug"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "../bin/samples/simpleua.exe"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF
+
+# Begin Target
+
+# Name "samples - Win32 Release"
+# Name "samples - Win32 Debug"
+
+!IF "$(CFG)" == "samples - Win32 Release"
+
+!ELSEIF "$(CFG)" == "samples - Win32 Debug"
+
+!ENDIF
+
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\src\samples\simpleua.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\src\samples\util.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=".\Samples-vc.mak"
+# End Source File
+# End Target
+# End Project
diff --git a/pjsip-apps/src/pjsip-perf/handler_call.c b/pjsip-apps/src/pjsip-perf/handler_call.c
index 5683ffa9..bc7ae339 100644
--- a/pjsip-apps/src/pjsip-perf/handler_call.c
+++ b/pjsip-apps/src/pjsip-perf/handler_call.c
@@ -165,7 +165,7 @@ static pj_bool_t mod_call_on_rx_request(pjsip_rx_data *rdata)
// TODO: Need to delete dialog
} else {
- status = pjsip_inv_send_msg(inv, response, NULL);
+ status = pjsip_inv_send_msg(inv, response);
if (status != PJ_SUCCESS)
app_perror(THIS_FILE, "Unable to send 100 response", status);
}
@@ -247,7 +247,7 @@ pj_status_t call_spawn_test( const pj_str_t *target,
/* Send initial INVITE: */
- status = pjsip_inv_send_msg(inv, tdata, NULL);
+ status = pjsip_inv_send_msg(inv, tdata);
if (status != PJ_SUCCESS) {
app_perror( THIS_FILE, "Unable to send initial INVITE request",
status);
@@ -283,7 +283,7 @@ static void bye_callback( pj_timer_heap_t *ht, pj_timer_entry *e)
return;
}
- status = pjsip_inv_send_msg(call_data->inv, tdata, NULL);
+ status = pjsip_inv_send_msg(call_data->inv, tdata);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to send BYE", status);
return;
@@ -391,7 +391,7 @@ pj_status_t call_handler_init(void)
inv_cb.on_new_session = &call_on_forked;
/* Initialize invite session module: */
- status = pjsip_inv_usage_init(settings.endpt, &mod_call, &inv_cb);
+ status = pjsip_inv_usage_init(settings.endpt, &inv_cb);
if (status != PJ_SUCCESS) {
app_perror( THIS_FILE, "Unable to initialize INVITE session module",
status);
diff --git a/pjsip-apps/src/samples/simpleua.c b/pjsip-apps/src/samples/simpleua.c
new file mode 100644
index 00000000..d8b551fe
--- /dev/null
+++ b/pjsip-apps/src/samples/simpleua.c
@@ -0,0 +1,519 @@
+
+/* Include all PJSIP core headers. */
+#include <pjsip.h>
+
+/* Include all PJMEDIA headers. */
+#include <pjmedia.h>
+
+/* Include all PJMEDIA-CODEC headers. */
+#include <pjmedia-codec.h>
+
+/* Include all PJSIP-UA headers */
+#include <pjsip_ua.h>
+
+/* Include all PJSIP-SIMPLE headers */
+#include <pjsip_simple.h>
+
+/* Include all PJLIB-UTIL headers. */
+#include <pjlib-util.h>
+
+/* Include all PJLIB headers. */
+#include <pjlib.h>
+
+
+#define THIS_FILE "simpleua.c"
+
+
+/*
+ * Static variables.
+ */
+static pj_bool_t g_complete;
+
+/* Global endpoint instance. */
+static pjsip_endpoint *g_endpt;
+
+/* Global caching pool factory. */
+static pj_caching_pool cp;
+
+/* Global media endpoint. */
+static pjmedia_endpt *g_med_endpt;
+static pjmedia_sock_info g_med_skinfo;
+
+/* Call variables. */
+static pjsip_inv_session *g_inv;
+static pjmedia_session *g_med_session;
+static pjmedia_snd_port *g_snd_player;
+static pjmedia_snd_port *g_snd_rec;
+
+
+/*
+ * Prototypes.
+ */
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status);
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e);
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e);
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata );
+
+
+/* Module to receive incoming requests (e.g. INVITE). */
+static pjsip_module mod_simpleua =
+{
+ NULL, NULL, /* prev, next. */
+ { "mod-simpleua", 12 }, /* Name. */
+ -1, /* Id */
+ PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
+ NULL, /* load() */
+ NULL, /* start() */
+ NULL, /* stop() */
+ NULL, /* unload() */
+ &on_rx_request, /* on_rx_request() */
+ NULL, /* on_rx_response() */
+ NULL, /* on_tx_request. */
+ NULL, /* on_tx_response() */
+ NULL, /* on_tsx_state() */
+};
+
+
+/*
+ * Show error.
+ */
+static int app_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, "%s: %s [code=%d]", title, errmsg, status));
+ return 1;
+}
+
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+ pj_status_t status;
+
+ /* Init PJLIB */
+ status = pj_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Init memory pool: */
+
+ /* Init caching pool. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /* Create global endpoint: */
+ {
+ const pj_str_t *hostname;
+ const char *endpt_name;
+
+ /* Endpoint MUST be assigned a globally unique name.
+ * The name will be used as the hostname in Warning header.
+ */
+
+ /* For this implementation, we'll use hostname for simplicity */
+ hostname = pj_gethostname();
+ endpt_name = hostname->ptr;
+
+ /* Create the endpoint: */
+
+ status = pjsip_endpt_create(&cp.factory, endpt_name,
+ &g_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+ /*
+ * Add UDP transport.
+ */
+ {
+ pj_sockaddr_in addr;
+
+ addr.sin_family = PJ_AF_INET;
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = pj_htons(5060);
+
+ status = pjsip_udp_transport_start( g_endpt, &addr, NULL, 1, NULL);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to start UDP transport", status);
+ return 1;
+ }
+ }
+
+
+ /*
+ * Init transaction layer.
+ */
+ status = pjsip_tsx_layer_init_module(g_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /*
+ * Initialize UA layer module:
+ */
+ status = pjsip_ua_init_module( g_endpt, NULL );
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /*
+ * Init invite session module.
+ */
+ {
+ pjsip_inv_callback inv_cb;
+
+ /* Init the callback for INVITE session: */
+ pj_memset(&inv_cb, 0, sizeof(inv_cb));
+ inv_cb.on_state_changed = &call_on_state_changed;
+ inv_cb.on_new_session = &call_on_forked;
+ inv_cb.on_media_update = &call_on_media_update;
+
+ /* Initialize invite session module: */
+ status = pjsip_inv_usage_init(g_endpt, &inv_cb);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+ }
+
+
+ /*
+ * Register module to receive incoming requests.
+ */
+ status = pjsip_endpt_register_module( g_endpt, &mod_simpleua);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /*
+ * Init media endpoint:
+ */
+ status = pjmedia_endpt_create(&cp.factory, &g_med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /*
+ * Add PCMA/PCMU codec to the media endpoint.
+ */
+ status = pjmedia_codec_g711_init(g_med_endpt);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /*
+ * Initialize RTP socket info for the media.
+ */
+ status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &g_med_skinfo.rtp_sock);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ pj_sockaddr_in_init( &g_med_skinfo.rtp_addr_name,
+ pjsip_endpt_name(g_endpt), 4000);
+
+ status = pj_sock_bind(g_med_skinfo.rtp_sock, &g_med_skinfo.rtp_addr_name,
+ sizeof(pj_sockaddr_in));
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE,
+ "Unable to bind RTP socket",
+ status);
+ return 1;
+ }
+
+
+ /* For simplicity, ignore RTCP socket. */
+ g_med_skinfo.rtcp_sock = PJ_INVALID_SOCKET;
+ g_med_skinfo.rtcp_addr_name = g_med_skinfo.rtp_addr_name;
+
+
+ /*
+ * If URL is specified, then make call immediately.
+ */
+ if (argc > 1) {
+ char temp[80];
+ pj_str_t dst_uri = pj_str(argv[1]);
+ pj_str_t local_uri;
+ pjsip_dialog *dlg;
+ pjmedia_sdp_session *local_sdp;
+ pjsip_tx_data *tdata;
+
+ pj_ansi_sprintf(temp, "sip:simpleuac@%s", pjsip_endpt_name(g_endpt)->ptr);
+ local_uri = pj_str(temp);
+
+ /* Create UAC dialog */
+ status = pjsip_dlg_create_uac( pjsip_ua_instance(),
+ &local_uri, /* local URI */
+ NULL, /* local Contact */
+ &dst_uri, /* remote URI */
+ &dst_uri, /* remote target */
+ &dlg); /* dialog */
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create UAC dialog", status);
+ return 1;
+ }
+
+ /* Get media capability from media endpoint: */
+ status = pjmedia_endpt_create_sdp( g_med_endpt, dlg->pool, 1,
+ &g_med_skinfo, &local_sdp);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Create the INVITE session: */
+ status = pjsip_inv_create_uac( dlg, local_sdp, 0, &g_inv);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+
+ /* Create initial INVITE request: */
+ status = pjsip_inv_invite(g_inv, &tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ /* Send initial INVITE request: */
+ status = pjsip_inv_send_msg(g_inv, tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+ } else {
+ PJ_LOG(3,(THIS_FILE, "Ready to accept incoming calls..."));
+ }
+
+
+ /* Loop until one call is completed */
+ for (;!g_complete;) {
+ pj_time_val timeout = {0, 10};
+ pjsip_endpt_handle_events(g_endpt, &timeout);
+ }
+
+ return 0;
+}
+
+
+
+/*
+ * Callback when INVITE session state has changed.
+ */
+static void call_on_state_changed( pjsip_inv_session *inv,
+ pjsip_event *e)
+{
+ if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+
+ PJ_LOG(3,(THIS_FILE, "Call DISCONNECTED [reason=%d (%s)]",
+ inv->cause,
+ pjsip_get_status_text(inv->cause)->ptr));
+
+ PJ_LOG(3,(THIS_FILE, "One call completed, application quitting..."));
+ g_complete = 1;
+
+ } else {
+
+ PJ_LOG(3,(THIS_FILE, "Call state changed to %s",
+ pjsip_inv_state_name(inv->state)));
+
+ }
+}
+
+/*
+ * Callback when media negotiation has completed.
+ */
+static void call_on_media_update( pjsip_inv_session *inv,
+ pj_status_t status)
+{
+ const pjmedia_sdp_session *local_sdp;
+ const pjmedia_sdp_session *remote_sdp;
+ pjmedia_port *media_port;
+
+ if (status != PJ_SUCCESS) {
+
+ app_perror(THIS_FILE, "SDP negotiation has failed", status);
+
+ /* Here we should disconnect call if we're not in the middle
+ * of initializing an UAS dialog and if this is not a re-INVITE.
+ */
+ return;
+ }
+
+ /* Get local and remote SDP */
+
+ status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
+
+ status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
+
+ /* Create new media session.
+ * The media session is active immediately.
+ */
+ status = pjmedia_session_create( g_med_endpt, 1,
+ &g_med_skinfo,
+ local_sdp, remote_sdp,
+ NULL, &g_med_session );
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE, "Unable to create media session", status);
+ return;
+ }
+
+ /* Get the port interface of the first stream in the session. */
+ pjmedia_session_get_port(g_med_session, 0, &media_port);
+
+ /* Create a sound Player device and connect the media port to the
+ * sound device.
+ */
+ status = pjmedia_snd_port_create_player(
+ inv->pool, /* pool */
+ -1, /* sound dev id */
+ media_port->info.sample_rate, /* clock rate */
+ media_port->info.channel_count, /* channel count */
+ media_port->info.samples_per_frame, /* samples per frame*/
+ media_port->info.bits_per_sample, /* bits per sample */
+ 0, /* options */
+ &g_snd_player);
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE, "Unable to create sound player", status);
+ PJ_LOG(3,(THIS_FILE, "%d %d %d %d",
+ media_port->info.sample_rate, /* clock rate */
+ media_port->info.channel_count, /* channel count */
+ media_port->info.samples_per_frame, /* samples per frame*/
+ media_port->info.bits_per_sample /* bits per sample */
+ ));
+ return;
+ }
+
+ status = pjmedia_snd_port_connect(g_snd_player, media_port);
+
+
+ /* Create a sound recorder device and connect the media port to the
+ * sound device.
+ */
+ status = pjmedia_snd_port_create_rec(
+ inv->pool, /* pool */
+ -1, /* sound dev id */
+ media_port->info.sample_rate, /* clock rate */
+ media_port->info.channel_count, /* channel count */
+ media_port->info.samples_per_frame, /* samples per frame*/
+ media_port->info.bits_per_sample, /* bits per sample */
+ 0, /* options */
+ &g_snd_rec);
+ if (status != PJ_SUCCESS) {
+ app_perror( THIS_FILE, "Unable to create sound recorder", status);
+ return;
+ }
+
+ status = pjmedia_snd_port_connect(g_snd_rec, media_port);
+
+ /* Done with media. */
+}
+
+
+/*
+ * This callback is called when dialog has forked
+ */
+static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e)
+{
+}
+
+/*
+ * Callback when incoming requests outside any transactions and any
+ * dialogs are received
+ */
+static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
+{
+ pjsip_dialog *dlg;
+ pjmedia_sdp_session *local_sdp;
+ pjsip_tx_data *tdata;
+ unsigned options = 0;
+ pj_status_t status;
+
+ /*
+ * Respond (statelessly) any non-INVITE requests with 500
+ */
+ if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {
+
+ pj_str_t reason = pj_str("Simple UA unable to handle this request");
+
+ pjsip_endpt_respond_stateless( g_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /*
+ * Reject INVITE if we already have an INVITE session in progress.
+ */
+ if (g_inv) {
+
+ pj_str_t reason = pj_str("Another call is in progress");
+
+ pjsip_endpt_respond_stateless( g_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return PJ_TRUE;
+
+ }
+
+ /* Verify that we can handle the request. */
+ status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
+ g_endpt, NULL);
+ if (status != PJ_SUCCESS) {
+
+ pj_str_t reason = pj_str("Sorry Simple UA can not handle this INVITE");
+
+ pjsip_endpt_respond_stateless( g_endpt, rdata,
+ 500, &reason,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /*
+ * Create UAS dialog.
+ */
+ status = pjsip_dlg_create_uas( pjsip_ua_instance(),
+ rdata,
+ NULL, /* contact */
+ &dlg);
+ if (status != PJ_SUCCESS) {
+ pjsip_endpt_respond_stateless(g_endpt, rdata, 500, NULL,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ /*
+ * Get media capability from media endpoint:
+ */
+
+ status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool, 1,
+ &g_med_skinfo,
+ &local_sdp);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+ /*
+ * Create invite session:
+ */
+ status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &g_inv);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+ /*
+ * Initially send 180 response.
+ */
+ status = pjsip_inv_initial_answer(g_inv, rdata,
+ 180,
+ NULL, NULL, &tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+ /*
+ * Send the 180 response.
+ */
+ status = pjsip_inv_send_msg(g_inv, tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+ /*
+ * Now send 200 response.
+ */
+ status = pjsip_inv_answer( g_inv,
+ 200, NULL, /* st_code and st_text */
+ NULL, /* SDP already specified */
+ &tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+ /*
+ * Send the 200 response.
+ */
+ status = pjsip_inv_send_msg(g_inv, tdata);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+
+ return PJ_TRUE;
+}
+
+
diff --git a/pjsip-apps/src/samples/util.h b/pjsip-apps/src/samples/util.h
new file mode 100644
index 00000000..fbe1e04f
--- /dev/null
+++ b/pjsip-apps/src/samples/util.h
@@ -0,0 +1,123 @@
+
+/* Include all PJSIP core headers. */
+#include <pjsip.h>
+
+/* Include all PJMEDIA headers. */
+#include <pjmedia.h>
+
+/* Include all PJMEDIA-CODEC headers. */
+#include <pjmedia-codec.h>
+
+/* Include all PJSIP-UA headers */
+#include <pjsip_ua.h>
+
+/* Include all PJSIP-SIMPLE headers */
+#include <pjsip_simple.h>
+
+/* Include all PJLIB-UTIL headers. */
+#include <pjlib-util.h>
+
+/* Include all PJLIB headers. */
+#include <pjlib.h>
+
+
+/* Global endpoint instance. */
+static pjsip_endpoint *g_endpt;
+
+/* Global caching pool factory. */
+static pj_caching_pool cp;
+
+/* Global media endpoint. */
+static pjmedia_endpt *g_med_endpt;
+
+/*
+ * Show error.
+ */
+static int app_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, "%s: %s [code=%d]", title, errmsg, status));
+ return 1;
+}
+
+/*
+ * Perform the very basic initialization:
+ * - init PJLIB.
+ * - init memory pool
+ * - create SIP endpoint instance.
+ */
+static pj_status_t util_init(void)
+{
+ pj_status_t status;
+
+ /* Init PJLIB */
+ status = pj_init();
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "pj_init() error", status);
+ return status;
+ }
+
+ /* Init PJLIB-UTIL: */
+ status = pjlib_util_init();
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "pjlib_util_init() error", status);
+ return status;
+ }
+
+ /* Init memory pool: */
+
+ /* Init caching pool. */
+ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+ /* Create global endpoint: */
+
+ {
+ const pj_str_t *hostname;
+ const char *endpt_name;
+
+ /* Endpoint MUST be assigned a globally unique name.
+ * The name will be used as the hostname in Warning header.
+ */
+
+ /* For this implementation, we'll use hostname for simplicity */
+ hostname = pj_gethostname();
+ endpt_name = hostname->ptr;
+
+ /* Create the endpoint: */
+
+ status = pjsip_endpt_create(&cp.factory, endpt_name,
+ &g_endpt);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to create SIP endpoint", status);
+ return status;
+ }
+ }
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * Add UDP transport to endpoint.
+ */
+static pj_status_t util_add_udp_transport(int port)
+{
+ pj_sockaddr_in addr;
+ pj_status_t status;
+
+ addr.sin_family = PJ_AF_INET;
+ addr.sin_addr.s_addr = 0;
+ addr.sin_port = port;
+
+ status = pjsip_udp_transport_start( g_endpt, &addr, NULL, 1, NULL);
+ if (status != PJ_SUCCESS) {
+ app_perror(THIS_FILE, "Unable to start UDP transport", status);
+ return status;
+ }
+
+ return status;
+}
+