static int cand_add(struct flow *flow, struct json_object *jcand) { const char *mid = jzon_str(jcand, "sdp_mid"); const char *rcand = jzon_str(jcand, "sdp"); int idx; int err; err = jzon_int(&idx, jcand, "sdp_mline_index"); if (err) return err; debug("cand_add: mid=%s idx=%d sdp=%s\n", mid, idx, rcand); if (flow->got_sdp) { struct mediaflow *mf = userflow_mediaflow(flow->userflow); return mediaflow_add_rcand(mf, rcand, mid, idx); } else { struct cand *cand = mem_zalloc(sizeof(*cand), cand_destructor); if (!cand) return ENOMEM; str_ncpy(cand->sdp, rcand, sizeof(cand->sdp)); str_ncpy(cand->mid, mid, sizeof(cand->mid)); cand->idx = idx; list_append(&flow->pendingl, &cand->le, cand); return 0; } }
int zapi_connection_decode(struct json_object *jobj, struct zapi_connection *conn) { if (!jobj || !conn) return EINVAL; conn->status = jzon_str(jobj, "status"); conn->conversation = jzon_str(jobj, "conversation"); conn->to = jzon_str(jobj, "to"); conn->from = jzon_str(jobj, "from"); conn->last_update = jzon_str(jobj, "last_update"); conn->message = jzon_str(jobj, "message"); return 0; }
int flow_sdp_handler(struct flow *flow, struct json_object *jobj, bool replayed) { struct mediaflow *mf; const char *sdp; const char *state; bool strm_chg = false; bool isoffer; int err = 0; if (!flow || !jobj) { return EINVAL; } sdp = jzon_str(jobj, "sdp"); state = jzon_str(jobj, "state"); isoffer = streq(state, "offer"); mf = userflow_mediaflow(flow->userflow); debug("flow_sdp_handler(%p): state=%s uf=%p mf=%p\n", flow, state, flow->userflow, mf); if (mf && mediaflow_sdp_is_complete(mf)) { if (replayed) return 0; strm_chg = strstr(sdp, "x-streamchange") != NULL; if (strm_chg) { info("flow_sdp_handler: x-streamchange\n"); mediaflow_stop_media(mf); mediaflow_sdpstate_reset(mf); mediaflow_reset_media(mf); } else if (isoffer) { info("flow_sdp_handler: SDP re-offer detected.\n"); flow_restart(flow); } else { warning("flow_sdp_handler: SDP already complete"); return 0; } } if (isoffer) { err = userflow_accept(flow->userflow, sdp); if (strm_chg) { mediaflow_start_media(mf); } } else if (streq(state, "answer")) { err = userflow_update(flow->userflow, sdp); } else { warning("flowmgr: flow_sdp_handler: unknown state: %s\n", state); err = EINVAL; } flow->got_sdp = true; /* flush list of any pending ICE-candidates */ if (!list_isempty(&flow->pendingl)) { struct le *le = list_head(&flow->pendingl); info("flowmgr: got SDP - adding %u pending candidates\n", list_count(&flow->pendingl)); while (le) { struct cand *cand = le->data; le = le->next; err |= mediaflow_add_rcand( userflow_mediaflow(flow->userflow), cand->sdp, cand->mid, cand->idx); mem_deref(cand); } } return err; }