[pjsip] What about python?

Turnaev Eugeny turnaev at t72.ru
Wed May 21 02:07:37 EDT 2008

Suppose situation:

I have an active call and valid call_id,
now i want to connect or disconnect port from conference.
So i have to call for example:

status = py_pjsua.conf_connect(player_port, call_port)

How can i check in python that player_port, call_port and call port are valid?

Well seems easy... 
call_port = py_pjsua.call_get_conf_port(call_id)
player_port = py_pjsua.player_get_conf_port(player_id)

if call_port >= 0 and player_port >= 0:
	do stuff.. ports are valid

Now imagine:

if call_port >= 0 and player_port >= 0:
	# here context switch ! .. callback is called
	# and call becomes invalid .. and also 
	# call_port becomes invalid..
	# context switch back to this function

	status = py_pjsua.conf_connect(player_port, call_port)

	# a call to py_pjsua.conf_connect(player_port, call_port)
	# will fail and application will  suddenly exit!

#				py_pjsua.c

static PyObject *py_pjsua_conf_connect
(PyObject *pSelf, PyObject *pArgs)

    status = pjsua_conf_connect(source, sink);

    return Py_BuildValue("i", status);

# 				pjsua_media.c

PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
                                        pjsua_conf_port_id sink)
    return pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 0);

#				conference.c

PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
                                               unsigned src_slot,
                                               unsigned sink_slot,
                                               int level )
    /* Check arguments */
    PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports &&
                     sink_slot<conf->max_ports, PJ_EINVAL);

    /* Ports must be valid. */
    PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL);
    PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL);

as i understand.. this macro will return from function PJ_EINVAL
and PJ_EINVAL and then must be returned from python envelope
as return Py_BuildValue("i", status);

but i see in console:

 11:43:59.968 os_core_unix.c pjlib 0.8.0-trunk for POSIX initialized
 11:43:59.969 sip_endpoint.c Creating endpoint instance...
 11:43:59.969          pjlib select() I/O Queue created (0xb7799098)
 11:43:59.969 sip_endpoint.c Module "mod-msg-print" registered
 11:43:59.969 sip_transport. Transport manager created.
python: ../src/pjmedia/conference.c:914: pjmedia_conf_connect_port: Assertion `conf && src_slot<conf->max_ports && sink_slot<conf->max_ports' failed.

and application exits..

How i can workaround this ?

I think the correct way would be to return status 
	status = py_pjsua.conf_connect(player_port, call_port)
from conf_connect call as invalid status..
or at least raise an exception in py_pjsua.c -> static PyObject *py_pjsua_conf_connect function.

Also this problem mirrors in
conf_disconnect and i suspect many other python envelopes.
(For example call_id .. i can retrieve call_id with enum_calls in python.. then a context may be switched.. call become invalid
 context switch back and i would call something that PJ_ASSERT_RETURN( call_id is valid ) -> that would crash my python app too 
 i guess )

More information about the pjsip mailing list