/** * Lookup a SIP uri in all registered contacts * * @param contacts Contacts container * @param uri SIP uri to lookup * * @return Matching contact if found, otherwise NULL */ struct contact *contact_find(const struct contacts *contacts, const char *uri) { if (!contacts) return NULL; return list_ledata(hash_lookup(contacts->cht, hash_joaat_str(uri), find_handler, (void *)uri)); }
int sip_ctrans_request(struct sip_ctrans **ctp, struct sip *sip, enum sip_transp tp, const struct sa *dst, char *met, char *branch, struct mbuf *mb, sip_resp_h *resph, void *arg) { struct sip_ctrans *ct; int err; if (!sip || !dst || !met || !branch || !mb) return EINVAL; ct = mem_zalloc(sizeof(*ct), destructor); if (!ct) return ENOMEM; hash_append(sip->ht_ctrans, hash_joaat_str(branch), &ct->he, ct); ct->invite = !strcmp(met, "INVITE"); ct->branch = mem_ref(branch); ct->met = mem_ref(met); ct->mb = mem_ref(mb); ct->dst = *dst; ct->tp = tp; ct->sip = sip; ct->state = ct->invite ? CALLING : TRYING; ct->resph = resph ? resph : dummy_handler; ct->arg = arg; err = sip_transp_send(&ct->qent, sip, NULL, tp, dst, mb, transport_handler, ct); if (err) goto out; tmr_start(&ct->tmr, 64 * SIP_T1, tmr_handler, ct); if (!sip_transp_reliable(ct->tp)) tmr_start(&ct->tmre, SIP_T1, retransmit_handler, ct); out: if (err) mem_deref(ct); else if (ctp) *ctp = ct; return err; }
int device_connect(struct device **devp, const char *device, struct auplay_st *auplay, struct ausrc_st *ausrc) { struct device *dev; int err = 0; if (!devp) return EINVAL; if (!str_isset(device)) return ENODEV; dev = find_device(device); if (dev) { *devp = mem_ref(dev); } else { dev = mem_zalloc(sizeof(*dev), destructor); if (!dev) return ENOMEM; str_ncpy(dev->name, device, sizeof(dev->name)); hash_append(ht_device, hash_joaat_str(device), &dev->le, dev); *devp = dev; debug("aubridge: created device '%s'\n", device); } if (auplay) dev->auplay = auplay; if (ausrc) dev->ausrc = ausrc; /* wait until we have both SRC+PLAY */ if (dev->ausrc && dev->auplay && !dev->run) { dev->run = true; err = pthread_create(&dev->thread, NULL, device_thread, dev); if (err) { dev->run = false; } } return err; }
int vidbridge_disp_alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp_st *st; int err = 0; (void)prm; (void)resizeh; (void)arg; if (!stp || !vd || !dev) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vd = vd; err = str_dup(&st->device, dev); if (err) goto out; /* find the vidsrc with the same device-name */ st->vidsrc = vidbridge_src_find(dev); if (st->vidsrc) { st->vidsrc->vidisp = st; } hash_append(ht_disp, hash_joaat_str(dev), &st->le, st); out: if (err) mem_deref(st); else *stp = st; return err; }
struct vidisp_st *vidbridge_disp_find(const char *device) { return list_ledata(hash_lookup(ht_disp, hash_joaat_str(device), list_apply_handler, (void *)device)); }
/** * Accept an incoming SIP Session connection * * @param sessp Pointer to allocated SIP Session * @param sock SIP Session socket * @param msg Incoming SIP message * @param scode Response status code * @param reason Response reason phrase * @param cuser Contact username * @param ctype Session content-type * @param desc Content description (e.g. SDP) * @param authh SIP Authentication handler * @param aarg Authentication handler argument * @param aref True to mem_ref() aarg * @param offerh Session offer handler * @param answerh Session answer handler * @param estabh Session established handler * @param infoh Session info handler * @param referh Session refer handler * @param closeh Session close handler * @param arg Handler argument * @param fmt Formatted strings with extra SIP Headers * * @return 0 if success, otherwise errorcode */ int sipsess_accept(struct sipsess **sessp, struct sipsess_sock *sock, const struct sip_msg *msg, uint16_t scode, const char *reason, const char *cuser, const char *ctype, struct mbuf *desc, sip_auth_h *authh, void *aarg, bool aref, sipsess_offer_h *offerh, sipsess_answer_h *answerh, sipsess_estab_h *estabh, sipsess_info_h *infoh, sipsess_refer_h *referh, sipsess_close_h *closeh, void *arg, const char *fmt, ...) { struct sipsess *sess; va_list ap; int err; if (!sessp || !sock || !msg || scode < 101 || scode > 299 || !cuser || !ctype) return EINVAL; err = sipsess_alloc(&sess, sock, cuser, ctype, NULL, authh, aarg, aref, offerh, answerh, NULL, estabh, infoh, referh, closeh, arg); if (err) return err; err = sip_dialog_accept(&sess->dlg, msg); if (err) goto out; hash_append(sock->ht_sess, hash_joaat_str(sip_dialog_callid(sess->dlg)), &sess->he, sess); sess->msg = mem_ref((void *)msg); err = sip_strans_alloc(&sess->st, sess->sip, msg, cancel_handler, sess); if (err) goto out; va_start(ap, fmt); if (scode >= 200) err = sipsess_reply_2xx(sess, msg, scode, reason, desc, fmt, &ap); else err = sip_treplyf(&sess->st, NULL, sess->sip, msg, true, scode, reason, "Contact: <sip:%s@%J%s>\r\n" "%v" "%s%s%s" "Content-Length: %zu\r\n" "\r\n" "%b", sess->cuser, &msg->dst, sip_transp_param(msg->tp), fmt, &ap, desc ? "Content-Type: " : "", desc ? sess->ctype : "", desc ? "\r\n" : "", desc ? mbuf_get_left(desc) : (size_t)0, desc ? mbuf_buf(desc) : NULL, desc ? mbuf_get_left(desc) : (size_t)0); va_end(ap); if (err) goto out; out: if (err) mem_deref(sess); else *sessp = sess; return err; }
/** * Connect to a remote SIP useragent * * @param sessp Pointer to allocated SIP Session * @param sock SIP Session socket * @param to_uri To SIP uri * @param from_name From display name * @param from_uri From SIP uri * @param cuser Contact username or URI * @param routev Outbound route vector * @param routec Outbound route vector count * @param ctype Session content-type * @param desc Content description (e.g. SDP) * @param authh SIP Authentication handler * @param aarg Authentication handler argument * @param aref True to mem_ref() aarg * @param offerh Session offer handler * @param answerh Session answer handler * @param progrh Session progress handler * @param estabh Session established handler * @param infoh Session info handler * @param referh Session refer handler * @param closeh Session close handler * @param arg Handler argument * @param fmt Formatted strings with extra SIP Headers * * @return 0 if success, otherwise errorcode */ int sipsess_connect(struct sipsess **sessp, struct sipsess_sock *sock, const char *to_uri, const char *from_name, const char *from_uri, const char *cuser, const char *routev[], uint32_t routec, const char *ctype, struct mbuf *desc, sip_auth_h *authh, void *aarg, bool aref, sipsess_offer_h *offerh, sipsess_answer_h *answerh, sipsess_progr_h *progrh, sipsess_estab_h *estabh, sipsess_info_h *infoh, sipsess_refer_h *referh, sipsess_close_h *closeh, void *arg, const char *fmt, ...) { struct sipsess *sess; int err; if (!sessp || !sock || !to_uri || !from_uri || !cuser || !ctype) return EINVAL; err = sipsess_alloc(&sess, sock, cuser, ctype, desc, authh, aarg, aref, offerh, answerh, progrh, estabh, infoh, referh, closeh, arg); if (err) return err; /* Custom SIP headers */ if (fmt) { va_list ap; sess->hdrs = mbuf_alloc(256); if (!sess->hdrs) { err = ENOMEM; goto out; } va_start(ap, fmt); err = mbuf_vprintf(sess->hdrs, fmt, ap); sess->hdrs->pos = 0; va_end(ap); if (err) goto out; } sess->owner = true; err = sip_dialog_alloc(&sess->dlg, to_uri, to_uri, from_name, from_uri, routev, routec); if (err) goto out; hash_append(sock->ht_sess, hash_joaat_str(sip_dialog_callid(sess->dlg)), &sess->he, sess); err = invite(sess); if (err) goto out; out: if (err) mem_deref(sess); else *sessp = sess; return err; }
static struct device *find_device(const char *device) { return list_ledata(hash_lookup(ht_device, hash_joaat_str(device), list_apply_handler, (void *)device)); }
int sipevent_accept(struct sipnot **notp, struct sipevent_sock *sock, const struct sip_msg *msg, struct sip_dialog *dlg, const struct sipevent_event *event, uint16_t scode, const char *reason, uint32_t expires_min, uint32_t expires_dfl, uint32_t expires_max, const char *cuser, const char *ctype, sip_auth_h *authh, void *aarg, bool aref, sipnot_close_h *closeh, void *arg, const char *fmt, ...) { struct sipnot *not; uint32_t expires; int err; if (!notp || !sock || !msg || !scode || !reason || !expires_dfl || !expires_max || !cuser || !ctype || expires_dfl < expires_min) return EINVAL; not = mem_zalloc(sizeof(*not), destructor); if (!not) return ENOMEM; if (!pl_strcmp(&msg->met, "REFER")) { err = str_dup(¬->event, "refer"); if (err) goto out; err = re_sdprintf(¬->id, "%u", msg->cseq.num); if (err) goto out; } else { if (!event) { err = EINVAL; goto out; } err = pl_strdup(¬->event, &event->event); if (err) goto out; if (pl_isset(&event->id)) { err = pl_strdup(¬->id, &event->id); if (err) goto out; } } if (dlg) { not->dlg = mem_ref(dlg); } else { err = sip_dialog_accept(¬->dlg, msg); if (err) goto out; } hash_append(sock->ht_not, hash_joaat_str(sip_dialog_callid(not->dlg)), ¬->he, not); err = sip_auth_alloc(¬->auth, authh, aarg, aref); if (err) goto out; err = str_dup(¬->cuser, cuser); if (err) goto out; err = str_dup(¬->ctype, ctype); if (err) goto out; if (fmt) { va_list ap; va_start(ap, fmt); err = re_vsdprintf(¬->hdrs, fmt, ap); va_end(ap); if (err) goto out; } not->expires_min = expires_min; not->expires_dfl = expires_dfl; not->expires_max = expires_max; not->substate = SIPEVENT_PENDING; not->sock = mem_ref(sock); not->sip = mem_ref(sock->sip); not->closeh = closeh ? closeh : internal_close_handler; not->arg = arg; if (pl_isset(&msg->expires)) expires = pl_u32(&msg->expires); else expires = not->expires_dfl; sipnot_refresh(not, expires); err = sipnot_reply(not, msg, scode, reason); if (err) goto out; not->subscribed = true; out: if (err) mem_deref(not); else *notp = not; return err; }