/** * Start registration of a User-Agent * * @param ua User-Agent * * @return 0 if success, otherwise errorcode */ int ua_register(struct ua *ua) { struct account *acc; struct le *le; struct uri uri; char reg_uri[64]; char params[256] = ""; unsigned i; int err; info("baresip.ua.ua_register()\n"); if (!ua) return EINVAL; acc = ua->acc; uri = ua->acc->luri; uri.user = uri.password = pl_null; if (re_snprintf(reg_uri, sizeof(reg_uri), "%H", uri_encode, &uri) < 0) return ENOMEM; if (str_isset(uag.cfg->uuid)) { if (re_snprintf(params, sizeof(params), ";+sip.instance=\"<urn:uuid:%s>\"", uag.cfg->uuid) < 0) return ENOMEM; } if (acc->regq) { if (re_snprintf(¶ms[strlen(params)], sizeof(params) - strlen(params), ";q=%s", acc->regq) < 0) return ENOMEM; } if (acc->mnat && acc->mnat->ftag) { if (re_snprintf(¶ms[strlen(params)], sizeof(params) - strlen(params), ";%s", acc->mnat->ftag) < 0) return ENOMEM; } ua_event(ua, UA_EVENT_REGISTERING, NULL, NULL); for (le = ua->regl.head, i=0; le; le = le->next, i++) { struct reg *reg = le->data; info("outbound[i]: "); info(acc->outbound[i]); err = reg_register(reg, reg_uri, params, acc->regint, acc->outbound[i]); if (err) { warning("ua: SIP register failed: %m\n", err); return err; } } return 0; }
/** * Unregister all Register clients of a User-Agent * * @param ua User-Agent */ void ua_unregister(struct ua *ua) { struct le *le; if (!ua) return; ua_event(ua, UA_EVENT_UNREGISTERING, NULL, NULL); for (le = ua->regl.head; le; le = le->next) { struct reg *reg = le->data; reg_unregister(reg); } }
static void ua_destructor(void *arg) { struct ua *ua = arg; if (ua->uap) { *ua->uap = NULL; ua->uap = NULL; } list_unlink(&ua->le); ua_event(ua, UA_EVENT_UNREGISTERING, NULL, NULL); list_flush(&ua->calls); list_flush(&ua->regl); mem_deref(ua->play); mem_deref(ua->cuser); mem_deref(ua->pub_gruu); mem_deref(ua->acc); }
static void call_event_handler(struct call *call, enum call_event ev, const char *str, void *arg) { struct ua *ua = arg; const char *peeruri; struct call *call2 = NULL; int err; MAGIC_CHECK(ua); peeruri = call_peeruri(call); /* stop any ringtones */ ua->play = mem_deref(ua->play); switch (ev) { case CALL_EVENT_INCOMING: if (contact_block_access(peeruri)) { info("ua: blocked access: \"%s\"\n", peeruri); ua_event(ua, UA_EVENT_CALL_CLOSED, call, str); mem_deref(call); break; } switch (ua->acc->answermode) { case ANSWERMODE_EARLY: (void)call_progress(call); break; case ANSWERMODE_AUTO: (void)call_answer(call, 200); break; case ANSWERMODE_MANUAL: default: if (list_count(&ua->calls) > 1) { (void)play_file(&ua->play, "callwaiting.wav", 3); } else { /* Alert user */ (void)play_file(&ua->play, "ring.wav", -1); } ua_event(ua, UA_EVENT_CALL_INCOMING, call, peeruri); break; } break; case CALL_EVENT_RINGING: (void)play_file(&ua->play, "ringback.wav", -1); ua_event(ua, UA_EVENT_CALL_RINGING, call, peeruri); break; case CALL_EVENT_PROGRESS: ua_printf(ua, "Call in-progress: %s\n", peeruri); ua_event(ua, UA_EVENT_CALL_PROGRESS, call, peeruri); break; case CALL_EVENT_ESTABLISHED: ua_printf(ua, "Call established: %s\n", peeruri); ua_event(ua, UA_EVENT_CALL_ESTABLISHED, call, peeruri); break; case CALL_EVENT_CLOSED: if (call_scode(call)) { const char *tone; tone = translate_errorcode(call_scode(call)); if (tone) (void)play_file(&ua->play, tone, 1); } ua_event(ua, UA_EVENT_CALL_CLOSED, call, str); mem_deref(call); break; case CALL_EVENT_TRANSFER: /* * Create a new call to transfer target. * * NOTE: we will automatically connect a new call to the * transfer target */ ua_printf(ua, "transferring call to %s\n", str); err = ua_call_alloc(&call2, ua, VIDMODE_ON, NULL, call, call_localuri(call)); if (!err) { struct pl pl; pl_set_str(&pl, str); err = call_connect(call2, &pl); if (err) { warning("ua: transfer: connect error: %m\n", err); } } if (err) { (void)call_notify_sipfrag(call, 500, "Call Error"); mem_deref(call2); } break; case CALL_EVENT_TRANSFER_FAILED: ua_event(ua, UA_EVENT_CALL_TRANSFER_FAILED, call, str); break; } }