static void mqueue_handler(int id, void *data, void *arg) { struct gtk_mod *mod = arg; const char *uri; struct call *call; int err; struct ua *ua = uag_current(); (void)mod; switch ((enum gtk_mod_events)id) { case MQ_POPUP: gdk_threads_enter(); popup_menu(mod, NULL, NULL, 0, GPOINTER_TO_UINT(data)); gdk_threads_leave(); break; case MQ_CONNECT: uri = data; err = ua_connect(ua, &call, NULL, uri, NULL, VIDMODE_ON); if (err) { gdk_threads_enter(); warning_dialog("Call failed", "Connecting to \"%s\" failed.\n" "Error: %m", uri, err); gdk_threads_leave(); break; } gdk_threads_enter(); err = new_call_window(mod, call) == NULL; gdk_threads_leave(); if (err) { ua_hangup(ua, call, 500, "Server Error"); } break; case MQ_HANGUP: call = data; ua_hangup(ua, call, 0, NULL); break; case MQ_QUIT: ua_stop_all(false); break; case MQ_ANSWER: call = data; err = ua_answer(ua, call); if (err) { gdk_threads_enter(); warning_dialog("Call failed", "Answering the call " "from \"%s\" failed.\n" "Error: %m", call_peername(call), err); gdk_threads_leave(); break; } gdk_threads_enter(); err = new_call_window(mod, call) == NULL; gdk_threads_leave(); if (err) { ua_hangup(ua, call, 500, "Server Error"); } break; case MQ_SELECT_UA: ua = data; uag_current_set(ua); break; } }
/** * Allocate a SIP User-Agent * * @param uap Pointer to allocated User-Agent object * @param aor SIP Address-of-Record (AOR) * * @return 0 if success, otherwise errorcode */ int ua_alloc(struct ua **uap, const char *aor) { struct ua *ua; int err; if (!aor) return EINVAL; ua = mem_zalloc(sizeof(*ua), ua_destructor); if (!ua) return ENOMEM; MAGIC_INIT(ua); list_init(&ua->calls); #if HAVE_INET6 ua->af = uag.prefer_ipv6 ? AF_INET6 : AF_INET; #else ua->af = AF_INET; #endif /* Decode SIP address */ err = account_alloc(&ua->acc, aor); if (err) goto out; /* generate a unique contact-user, this is needed to route incoming requests when using multiple useragents */ err = re_sdprintf(&ua->cuser, "%r-%p", &ua->acc->luri.user, ua); if (err) goto out; if (ua->acc->sipnat) { ua_printf(ua, "Using sipnat: `%s'\n", ua->acc->sipnat); } if (ua->acc->mnat) { ua_printf(ua, "Using medianat `%s'\n", ua->acc->mnat->id); if (0 == str_casecmp(ua->acc->mnat->id, "ice")) add_extension(ua, "ice"); } if (ua->acc->menc) { ua_printf(ua, "Using media encryption `%s'\n", ua->acc->menc->id); } /* Register clients */ if (str_isset(uag.cfg->uuid)) add_extension(ua, "gruu"); if (0 == str_casecmp(ua->acc->sipnat, "outbound")) { size_t i; add_extension(ua, "path"); add_extension(ua, "outbound"); if (!str_isset(uag.cfg->uuid)) { warning("ua: outbound requires valid UUID!\n"); err = ENOSYS; goto out; } for (i=0; i<ARRAY_SIZE(ua->acc->outbound); i++) { if (ua->acc->outbound[i] && ua->acc->regint) { err = reg_add(&ua->regl, ua, (int)i+1); if (err) break; } } } else if (ua->acc->regint) { err = reg_add(&ua->regl, ua, 0); } if (err) goto out; list_append(&uag.ual, &ua->le, ua); if (ua->acc->regint) { err = ua_register(ua); } if (!uag_current()) uag_current_set(ua); out: if (err) mem_deref(ua); else if (uap) { *uap = ua; ua->uap = uap; } return err; }