static int mwi_subscribe(struct ua *ua) { const char *routev[1]; struct mwi *mwi; int err; mwi = mem_zalloc(sizeof(*mwi), destructor); if (!mwi) return ENOMEM; list_append(&mwil, &mwi->le, mwi); mwi->ua = ua; routev[0] = ua_outbound(ua); info("mwi: subscribing to messages for %s\n", ua_aor(ua)); err = sipevent_subscribe(&mwi->sub, uag_sipevent_sock(), ua_aor(ua), NULL, ua_aor(ua), "message-summary", NULL, 600, ua_cuser(ua), routev, routev[0] ? 1 : 0, auth_handler, ua_prm(ua), true, NULL, notify_handler, close_handler, mwi, "Accept:" " application/simple-message-summary\r\n"); if (err) { warning("mwi: subscribe ERROR: %m\n", err); } if (err) mem_deref(mwi); return err; }
static GtkMenuItem *accounts_menu_add_item(struct gtk_mod *mod, struct ua *ua) { GtkMenuShell *accounts_menu = GTK_MENU_SHELL(mod->accounts_menu); GtkWidget *item; GSList *group = mod->accounts_menu_group; struct ua *ua_current = uag_current(); char buf[256]; re_snprintf(buf, sizeof buf, "%s%s", ua_aor(ua), ua_isregistered(ua) ? " (OK)" : ""); item = gtk_radio_menu_item_new_with_label(group, buf); group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM (item)); if (ua == ua_current) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); g_object_set_data(G_OBJECT(item), "ua", ua); g_signal_connect(item, "toggled", G_CALLBACK(menu_on_account_toggled), mod); gtk_menu_shell_append(accounts_menu, item); mod->accounts_menu_group = group; return GTK_MENU_ITEM(item); }
static int subscribe(struct presence *pres) { const char *routev[1]; struct ua *ua; char uri[256]; int err; /* We use the first UA */ ua = uag_find_aor(NULL); if (!ua) { warning("presence: no UA found\n"); return ENOENT; } pl_strcpy(&contact_addr(pres->contact)->auri, uri, sizeof(uri)); routev[0] = ua_outbound(ua); err = sipevent_subscribe(&pres->sub, uag_sipevent_sock(), uri, NULL, ua_aor(ua), "presence", NULL, 600, ua_cuser(ua), routev, routev[0] ? 1 : 0, auth_handler, ua_prm(ua), true, NULL, notify_handler, close_handler, pres, "%H", ua_print_supported, ua); if (err) { warning("presence: sipevent_subscribe failed: %m\n", err); } return err; }
static void response_handler(int err, const struct sip_msg *msg, void *arg) { struct publisher *pub = arg; const struct sip_hdr *etag_hdr; if (err) return; if (msg->scode < 200) { return; } if (msg->scode < 300) { if (pub->expires == 0) return; etag_hdr = sip_msg_xhdr(msg, "SIP-ETag"); if (etag_hdr) { mem_deref(pub->etag); pl_strdup(&(pub->etag), &(etag_hdr->val)); pub->refresh = 1; tmr_start(&pub->tmr, pub->expires * 900, tmr_handler, pub); } else { warning("%s: publisher got 200 OK without etag\n", ua_aor(pub->ua)); } } else if (msg->scode == 412) { mem_deref(pub->etag); pub->etag = NULL; pub->refresh = 0; publish(pub); } else { warning("%s: publisher got error response %u %r\n", ua_aor(pub->ua), msg->scode, &msg->reason); } return; }
static void accounts_menu_set_status(struct gtk_mod *mod, struct ua *ua, enum ua_event ev) { GtkMenuItem *item = accounts_menu_get_item(mod, ua); char buf[256]; re_snprintf(buf, sizeof buf, "%s (%s)", ua_aor(ua), ua_event_reg_str(ev)); gtk_menu_item_set_label(item, buf); }
static void notify_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct mwi *mwi = arg; if (mbuf_get_left(msg->mb)) { re_printf("----- MWI for %s -----\n", ua_aor(mwi->ua)); re_printf("%b\n", mbuf_buf(msg->mb), mbuf_get_left(msg->mb)); } (void)sip_treply(NULL, sip, msg, 200, "OK"); }
int sip_req_send(struct ua *ua, const char *method, const char *uri, sip_resp_h *resph, void *arg, const char *fmt, ...) { const char *routev[1]; struct sip_req *sr; int err; info("baresip.sipreq.sip_req_send()\n"); if (!ua || !method || !uri || !fmt) return EINVAL; routev[0] = ua_outbound(ua); sr = mem_zalloc(sizeof(*sr), destructor); if (!sr) return ENOMEM; sr->resph = resph; sr->arg = arg; err = str_dup(&sr->method, method); if (fmt) { va_list ap; va_start(ap, fmt); err |= re_vsdprintf(&sr->fmt, fmt, ap); va_end(ap); } if (err) goto out; err = sip_dialog_alloc(&sr->dlg, uri, uri, NULL, ua_aor(ua), routev[0] ? routev : NULL, routev[0] ? 1 : 0); if (err) goto out; err = sip_auth_alloc(&sr->auth, auth_handler, ua_prm(ua), true); if (err) goto out; err = request(sr); out: if (err) mem_deref(sr); return err; }
static void close_handler(int err, const struct sip_msg *msg, const struct sipevent_substate *substate, void *arg) { struct mwi *mwi = arg; (void)substate; info("mwi: subscription for %s closed: %s (%u %r)\n", ua_aor(mwi->ua), err ? strerror(err) : "", err ? 0 : msg->scode, err ? 0 : &msg->reason); mem_deref(mwi); }
static void notify_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct mwi *mwi = arg; if (mbuf_get_left(msg->mb)) { ui_output("----- MWI for %s -----\n", ua_aor(mwi->ua)); ui_output("%b\n", mbuf_buf(msg->mb), mbuf_get_left(msg->mb)); } (void)sip_treply(NULL, sip, msg, 200, "OK"); if (mwi->shutdown) mem_deref(mwi); }
static int notify(struct notifier *not, enum presence_status status) { const char *aor = ua_aor(not->ua); struct mbuf *mb; int err; mb = mbuf_alloc(1024); if (!mb) return ENOMEM; err = mbuf_printf(mb, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n" "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\r\n" " xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\"\r\n" " xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\"\r\n" " entity=\"%s\">\r\n" " <dm:person id=\"p4159\"><rpid:activities/></dm:person>\r\n" " <tuple id=\"t4109\">\r\n" " <status>\r\n" " <basic>%s</basic>\r\n" " </status>\r\n" " <contact>%s</contact>\r\n" " </tuple>\r\n" "</presence>\r\n" ,aor, presence_status_str(status), aor); if (err) goto out; mb->pos = 0; err = sipevent_notify(not->not, mb, SIPEVENT_ACTIVE, 0, 0); if (err) { warning("presence: notify to %s failed (%m)\n", aor, err); } out: mem_deref(mb); return err; }
static int publish(struct publisher *pub) { int err; const char *aor = ua_aor(pub->ua); struct mbuf *mb; mb = mbuf_alloc(1024); if (!mb) return ENOMEM; if (pub->expires && !pub->refresh) err = mbuf_printf(mb, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n" "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\r\n" " xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\"\r\n" " xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\"\r\n" " entity=\"%s\">\r\n" " <dm:person id=\"p4159\"><rpid:activities/></dm:person>\r\n" " <tuple id=\"t4109\">\r\n" " <status>\r\n" " <basic>%s</basic>\r\n" " </status>\r\n" " <contact>%s</contact>\r\n" " </tuple>\r\n" "</presence>\r\n" ,aor, presence_status_str(ua_presence_status(pub->ua)), aor); else err = mbuf_printf(mb, ""); if (err) goto out; mb->pos = 0; /* XXX: can be simplified with 1 function call, by adding a print-handler that prints "SIP-If-Match: ETAG" */ if (pub->etag) err = sip_req_send(pub->ua, "PUBLISH", aor, pub->expires ? response_handler : NULL, pub, "%s" "Event: presence\r\n" "Expires: %u\r\n" "SIP-If-Match: %s\r\n" "Content-Length: %zu\r\n" "\r\n" "%b", pub->expires ? "Content-Type: application/pidf+xml\r\n" : "", pub->expires, pub->etag, mbuf_get_left(mb), mbuf_buf(mb), mbuf_get_left(mb)); else err = sip_req_send(pub->ua, "PUBLISH", aor, pub->expires ? response_handler : NULL, pub, "%s" "Event: presence\r\n" "Expires: %u\r\n" "Content-Length: %zu\r\n" "\r\n" "%b", pub->expires ? "Content-Type: application/pidf+xml\r\n" : "", pub->expires, mbuf_get_left(mb), mbuf_buf(mb), mbuf_get_left(mb)); if (err) { warning("publisher: send PUBLISH: (%m)\n", err); } out: mem_deref(mb); return err; }