I have a sip server with a domain, that looks like 111.111.111.111:1111 (UDP), and there is a conference with 2222 number (i think it's a listening port), to which i should call. Also i have login and password to the sip account: 3333/Test3333. How do i create an account with PJSIP library and call to conference.
This error i get when trying to create an account:
FAILED TO CREATE ACCOUNT
java.lang.Exception: Title: pjsua_acc_add(&pj_acc_cfg, make_default, &
Code: 171039
Description: Invalid URI (PJSIP_EINVALIDURI)
Location: ../src/pjsua2/account.cpp:997
Here's my pjsip manager class:
class PJSipManager {
private val ep = Endpoint()
private val acc = SipAccount()
private var call: SipCall? = null
private var coroutineScope: CoroutineScope? = null
private val _callInfoFlow = MutableSharedFlow<CallInfo>()
val callInfoFlow = _callInfoFlow.asSharedFlow()
fun initLib(scope: CoroutineScope) {
coroutineScope = scope
if (ep.libGetState() == pjsua_state.PJSUA_STATE_NULL) {
val epConfig = EpConfig()
epConfig.logConfig.writer = BaseSipViewModel.PJLogger()
epConfig.logConfig.decor = epConfig.logConfig.decor and
(pj_log_decoration.PJ_LOG_HAS_CR or
pj_log_decoration.PJ_LOG_HAS_NEWLINE).inv().toLong()
try {
ep.libCreate()
ep.libInit(epConfig)
} catch (e: Exception) {
Log.e("PJSIP", "LIB DIDNT CREATED")
}
try {
val sipTpConfig = TransportConfig().apply {
port = SIP_LISTENING_PORT.toLong()
}
ep.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_UDP, sipTpConfig)
val accCfg = AccountConfig().apply {
idUri = ACC_ID_URI
}
acc.create(accCfg, true)
} catch (e:Exception) {
Log.e("PJSIP", "FAILED TO CREATE ACCOUNT", e)
}
try {
ep.libStart()
Log.d("PJSIP", "LIB STARTED")
} catch (e: Exception) {
Log.e("PJSIP", "LIB DIDNT STARTED", e)
}
}
}
fun tryStart() {
Log.i("PJSIP", "is lib running = ${ep.libGetState() == pjsua_state.PJSUA_STATE_RUNNING}")
if (ep.libGetState() == pjsua_state.PJSUA_STATE_RUNNING) {
if (call == null) {
try {
ep.audDevManager().setNullDev()
val mCall = SipCall(acc, -1)
val prm = CallOpParam(true)
mCall.makeCall(CALL_DST_URI, prm)
call = mCall
} catch (e: Exception) {
Log.e("PJSIP", "FAILED TO CALL", e)
}
} else {
try {
ep.hangupAllCalls()
} catch (e: Exception) {
Log.e("PJSIP", "FAILED TO hangup CALL", e)
}
}
}
}
inner class SipAccount: Account() {
override fun onIncomingCall(prm: OnIncomingCallParam?) {
if (prm != null) {
val mCall = SipCall(acc, prm.callId)
val ansPrm = CallOpParam(true)
ansPrm.statusCode =
if (call == null) pjsip_status_code.PJSIP_SC_OK else pjsip_status_code.PJSIP_SC_BUSY_HERE
try {
mCall.answer(ansPrm)
if (call == null)
call = mCall
} catch (e: Exception) {
println(e)
}
}
}
}
inner class SipCall(acc: Account, callId: Int): Call(acc, callId) {
private fun getCallInfo(call: Call): CallInfo? {
var ci : CallInfo? = null
try {
ci = call.info
} catch (e: Exception) {
println("Failed getting call info: $e")
}
return ci
}
override fun onCallState(prm: OnCallStateParam?) {
val ci : CallInfo = getCallInfo(this) ?: return
ep.utilLogWrite(3, "MyCall", "Call state changed to: " + ci.stateText)
coroutineScope.launch {
_callInfoFlow.emit(ci)
}
if (ci.state == pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED) {
call = null
ep.utilLogWrite(3, "MyCall", this.dump(true, ""))
}
}
override fun onCallMediaState(prm: OnCallMediaStateParam?) {
val ci : CallInfo = getCallInfo(this) ?: return
val cmiv = ci.media
for (i in cmiv.indices) {
val cmi = cmiv[i]
Log.i("PJSIP", cmi.type.toString() + " " + cmi.status.toString())
if (cmi.type == pjmedia_type.PJMEDIA_TYPE_AUDIO &&
(cmi.status == pjsua_call_media_status.PJSUA_CALL_MEDIA_ACTIVE ||
cmi.status == pjsua_call_media_status.PJSUA_CALL_MEDIA_REMOTE_HOLD))
{
/* Connect ports */
try {
val am = getAudioMedia(i)
ep.audDevManager().captureDevMedia.startTransmit(am)
am.startTransmit(ep.audDevManager().playbackDevMedia)
} catch (e: Exception) {
println("Failed connecting media ports" + e.message)
}
}
}
}
}
companion object {
const val ACC_ID_URI = "sip:3333:Test333"
const val CALL_DST_URI = "sip:111.111.111.111:1111"
const val SIP_LISTENING_PORT = 2222
}
}
EDIT 1
I figured it out, here's the right URIs for successful connection.
const val ACC_ID_URI = "sip:[email protected]"
const val ACC_REGISTRAR_URI = "sip:111.111.111.1111"
const val CALL_DST_URI = "sip:[email protected]:1111"
const val SIP_LISTENING_PORT = 5061 // this you can specify how you want
Also you should specify registrarUri, becouse without it sip server wont receive any messages from. Account config should look like this:
val accCfg = AccountConfig().apply {
idUri = ACC_ID_URI
regConfig.registrarUri = ACC_REGISTRAR_URI
sipConfig.authCreds.add(
AuthCredInfo(
"digest" ,
"*",
"3333",
0,
"Test3333"
)
)
}