enum update_rtpp_stats_rval update_rtpp_stats(struct rtpp_log *rlog, struct rtpp_session_stat *stat, rtp_hdr_t *header, struct rtp_info *rinfo, double rtime) { uint32_t seq; uint16_t idx; uint32_t mask; const struct rtp_profile *rpp; struct rtp_analyze_jdata *jdp; rpp = rinfo->rtp_profile; jdp = jdata_by_ssrc(stat->jdata, rinfo->ssrc); if (stat->ssrc_changes == 0) { RTPP_DBG_ASSERT(stat->last.pcount == 0); RTPP_DBG_ASSERT(stat->psent == 0); RTPP_DBG_ASSERT(stat->precvd == 0); stat->last.ssrc.val = rinfo->ssrc; stat->last.ssrc.inited = 1; stat->last.max_seq = stat->last.min_seq = rinfo->seq; stat->last.base_ts = rinfo->ts; stat->last.base_rtime = rtime; stat->last.pcount = 1; stat->ssrc_changes = 1; idx = (rinfo->seq % 131072) >> 5; stat->last.seen[idx] |= 1 << (rinfo->seq & 31); stat->last.seq = rinfo->seq; if (rpp->ts_rate > 0 && jdp != NULL) { update_jitter_stats(jdp, rinfo, rtime, RTP_NORMAL); } return (UPDATE_OK); }
static struct rtp_analyze_jdata * jdata_by_ssrc(struct rtp_analyze_jitter *jp, uint32_t ssrc) { struct rtp_analyze_jdata *rjdp, *jdp_last, *jdp_prelast; if (jp->first->ssrc.inited == 0) { jp->first->ssrc.val = ssrc; jp->first->ssrc.inited = 1; return (jp->first); } jdp_last = jdp_prelast = NULL; for (rjdp = jp->first; rjdp != NULL; rjdp = rjdp->next) { if (rjdp->ssrc.val == ssrc) { return (rjdp); } jdp_prelast = jdp_last; jdp_last = rjdp; } if (jp->jdlen == RTPC_JDATA_MAX) { /* Re-use the last per-ssrc data */ rjdp = jdp_last; if (jdp_prelast != NULL) { RTPP_DBG_ASSERT(jdp_prelast->next == jdp_last); jdp_prelast->next = NULL; } else { jp->first = NULL; } CALL_METHOD(rjdp->ts_dedup, flush); if (rjdp->jss.pcount >= 2) { if (jp->jmax_acum < rjdp->jss.jmax) { jp->jmax_acum = rjdp->jss.jmax; } jp->jtotal_acum += rjdp->jss.jtotal; jp->jvcount_acum += rjdp->jss.pcount - 1; jp->pcount_acum += rjdp->jss.pcount; } memset(&rjdp->jss, '\0', sizeof(rjdp->jss)); RTPP_DBG_ASSERT(rjdp->ssrc.inited == 1); } else { /* Allocate per-ssrc data */ rjdp = rtp_analyze_jdata_ctor(); if (rjdp == NULL) { return (NULL); } rjdp->ssrc.inited = 1; jp->jdlen += 1; } rjdp->ssrc.val = ssrc; rjdp->next = jp->first; jp->first = rjdp; return (rjdp); }
void rtpp_netaddr_fin(struct rtpp_netaddr *pub) { RTPP_DBG_ASSERT(pub->smethods->cmp != (rtpp_netaddr_cmp_t)NULL); RTPP_DBG_ASSERT(pub->smethods->cmphost != (rtpp_netaddr_cmphost_t)NULL); RTPP_DBG_ASSERT(pub->smethods->copy != (rtpp_netaddr_copy_t)NULL); RTPP_DBG_ASSERT(pub->smethods->get != (rtpp_netaddr_get_t)NULL); RTPP_DBG_ASSERT(pub->smethods->isaddrseq != (rtpp_netaddr_isaddrseq_t)NULL); RTPP_DBG_ASSERT(pub->smethods->isempty != (rtpp_netaddr_isempty_t)NULL); RTPP_DBG_ASSERT(pub->smethods->set != (rtpp_netaddr_set_t)NULL); RTPP_DBG_ASSERT(pub->smethods->sip_print != (rtpp_netaddr_sip_print_t)NULL); RTPP_DBG_ASSERT(pub->smethods != &rtpp_netaddr_smethods_fin && pub->smethods != NULL); pub->smethods = &rtpp_netaddr_smethods_fin; }
void rtpp_pcount_fin(struct rtpp_pcount *pub) { RTPP_DBG_ASSERT(pub->get_stats != (rtpp_pcount_get_stats_t)NULL); RTPP_DBG_ASSERT(pub->get_stats != (rtpp_pcount_get_stats_t)&rtpp_pcount_get_stats_fin); pub->get_stats = (rtpp_pcount_get_stats_t)&rtpp_pcount_get_stats_fin; RTPP_DBG_ASSERT(pub->reg_drop != (rtpp_pcount_reg_drop_t)NULL); RTPP_DBG_ASSERT(pub->reg_drop != (rtpp_pcount_reg_drop_t)&rtpp_pcount_reg_drop_fin); pub->reg_drop = (rtpp_pcount_reg_drop_t)&rtpp_pcount_reg_drop_fin; RTPP_DBG_ASSERT(pub->reg_ignr != (rtpp_pcount_reg_ignr_t)NULL); RTPP_DBG_ASSERT(pub->reg_ignr != (rtpp_pcount_reg_ignr_t)&rtpp_pcount_reg_ignr_fin); pub->reg_ignr = (rtpp_pcount_reg_ignr_t)&rtpp_pcount_reg_ignr_fin; RTPP_DBG_ASSERT(pub->reg_reld != (rtpp_pcount_reg_reld_t)NULL); RTPP_DBG_ASSERT(pub->reg_reld != (rtpp_pcount_reg_reld_t)&rtpp_pcount_reg_reld_fin); pub->reg_reld = (rtpp_pcount_reg_reld_t)&rtpp_pcount_reg_reld_fin; }
static void rtp_analyze_jt_destroy(struct rtp_analyze_jitter *jp) { struct rtp_analyze_jdata *jdp, *jdp_next; for (jdp = jp->first; jdp != NULL; jdp = jdp_next) { jdp_next = jdp->next; CALL_SMETHOD(jdp->ts_dedup->rcnt, decref); free(jdp); jp->jdlen -= 1; } RTPP_DBG_ASSERT(jp->jdlen == 0); free(jp); }
static struct rtp_packet * rtpp_socket_rtp_recv(struct rtpp_socket *self, const struct rtpp_timestamp *dtime, struct sockaddr *laddr, int port) { struct rtpp_socket_priv *pvt; struct rtp_packet *packet; struct timeval rtime; size_t llen; packet = rtp_packet_alloc(); if (packet == NULL) { return NULL; } pvt = PUB2PVT(self); packet->rlen = sizeof(packet->raddr); llen = sizeof(packet->_laddr); memset(&rtime, '\0', sizeof(rtime)); packet->size = recvfromto(pvt->fd, packet->data.buf, sizeof(packet->data.buf), sstosa(&packet->raddr), &packet->rlen, sstosa(&packet->_laddr), &llen, &rtime); if (packet->size == -1) { rtp_packet_free(packet); return (NULL); } if (llen > 0) { packet->laddr = sstosa(&packet->_laddr); packet->lport = getport(packet->laddr); } else { packet->laddr = laddr; packet->lport = port; } if (!timevaliszero(&rtime)) { packet->rtime.wall = timeval2dtime(&rtime); } else { packet->rtime.wall = dtime->wall; } RTPP_DBG_ASSERT(packet->rtime.wall > 0); packet->rtime.mono = dtime->mono; return (packet); }
int rtpp_command_ul_handle(struct cfg *cf, struct rtpp_command *cmd, struct ul_opts *ulop, int sidx) { int pidx, lport, sessions_active; struct rtpp_socket *fds[2]; const char *actor; struct rtpp_session *spa, *spb; pidx = 1; lport = 0; spa = spb = NULL; fds[0] = fds[1] = NULL; if (sidx != -1) { RTPP_DBG_ASSERT(cmd->cca.op == UPDATE || cmd->cca.op == LOOKUP); spa = cmd->sp; if (spa->rtp->stream[sidx]->fd == NULL || ulop->new_port != 0) { if (ulop->local_addr != NULL) { spa->rtp->stream[sidx]->laddr = ulop->local_addr; } if (rtpp_create_listener(cf, spa->rtp->stream[sidx]->laddr, &lport, fds) == -1) { RTPP_LOG(spa->log, RTPP_LOG_ERR, "can't create listener"); reply_error(cmd, ECODE_LSTFAIL_1); goto err_undo_0; } if (spa->rtp->stream[sidx]->fd != NULL && ulop->new_port != 0) { RTPP_LOG(spa->log, RTPP_LOG_INFO, "new port requested, releasing %d/%d, replacing with %d/%d", spa->rtp->stream[sidx]->port, spa->rtcp->stream[sidx]->port, lport, lport + 1); CALL_METHOD(cf->stable->sessinfo, update, spa, sidx, fds); } else { RTPP_DBG_ASSERT(spa->rtp->stream[sidx]->fd == NULL); spa->rtp->stream[sidx]->fd = fds[0]; RTPP_DBG_ASSERT(spa->rtcp->stream[sidx]->fd == NULL); spa->rtcp->stream[sidx]->fd = fds[1]; CALL_METHOD(cf->stable->sessinfo, append, spa, sidx); } spa->rtp->stream[sidx]->port = lport; spa->rtcp->stream[sidx]->port = lport + 1; if (spa->complete == 0) { cmd->csp->nsess_complete.cnt++; } spa->complete = 1; } if (ulop->weak) spa->rtp->stream[sidx]->weak = 1; else if (cmd->cca.op == UPDATE) spa->strong = 1; lport = spa->rtp->stream[sidx]->port; ulop->lia[0] = spa->rtp->stream[sidx]->laddr; pidx = (sidx == 0) ? 1 : 0; if (cmd->cca.op == UPDATE) { CALL_METHOD(spa->rtp->stream[0]->ttl, reset_with, cf->stable->max_setup_ttl); CALL_METHOD(spa->rtp->stream[1]->ttl, reset_with, cf->stable->max_setup_ttl); RTPP_LOG(spa->log, RTPP_LOG_INFO, "adding %s flag to existing session, new=%d/%d/%d", ulop->weak ? ( sidx ? "weak[1]" : "weak[0]" ) : "strong", spa->strong, spa->rtp->stream[0]->weak, spa->rtp->stream[1]->weak); } else { CALL_METHOD(spa->rtp->stream[0]->ttl, reset_with, cf->stable->max_ttl); CALL_METHOD(spa->rtp->stream[1]->ttl, reset_with, cf->stable->max_ttl); } RTPP_LOG(spa->log, RTPP_LOG_INFO, "lookup on ports %d/%d, session timer restarted", spa->rtp->stream[0]->port, spa->rtp->stream[1]->port); } else { struct rtpp_hash_table_entry *hte; RTPP_DBG_ASSERT(cmd->cca.op == UPDATE); RTPP_LOG(cf->stable->glog, RTPP_LOG_INFO, "new session %s, tag %s requested, type %s", cmd->cca.call_id, cmd->cca.from_tag, ulop->weak ? "weak" : "strong"); if (cf->stable->slowshutdown != 0) { RTPP_LOG(cf->stable->glog, RTPP_LOG_INFO, "proxy is in the deorbiting-burn mode, new session rejected"); reply_error(cmd, ECODE_SLOWSHTDN); goto err_undo_0; } if (ulop->local_addr != NULL) { ulop->lia[0] = ulop->lia[1] = ulop->local_addr; } if (rtpp_create_listener(cf, ulop->lia[0], &lport, fds) == -1) { RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "can't create listener"); reply_error(cmd, ECODE_LSTFAIL_2); goto err_undo_0; } /* * Session creation. If creation is requested with weak flag, * set weak[0]. */ spa = rtpp_session_ctor(cf->stable, &cmd->cca, cmd->dtime, ulop->lia, ulop->weak, lport, fds); if (spa == NULL) { handle_nomem(cf, cmd, ECODE_NOMEM_4, ulop, fds, NULL); return (-1); } hte = CALL_METHOD(cf->stable->sessions_ht, append_refcnt, spa->call_id, spa->rcnt); if (hte == NULL) { handle_nomem(cf, cmd, ECODE_NOMEM_5, ulop, NULL, spa); return (-1); } if (CALL_METHOD(cf->stable->sessions_wrt, reg, spa->rcnt, spa->seuid) != 0) { CALL_METHOD(cf->stable->sessions_ht, remove, spa->call_id, hte); handle_nomem(cf, cmd, ECODE_NOMEM_8, ulop, NULL, spa); return (-1); } cmd->csp->nsess_created.cnt++; /* * Each session can consume up to 5 open file descriptors (2 RTP, * 2 RTCP and 1 logging) so that warn user when he is likely to * exceed 80% mark on hard limit. */ sessions_active = CALL_METHOD(cf->stable->sessions_wrt, get_length); if (sessions_active > (rtpp_rlim_max(cf) * 80 / (100 * 5)) && cf->nofile_limit_warned == 0) { cf->nofile_limit_warned = 1; RTPP_LOG(cf->stable->glog, RTPP_LOG_WARN, "passed 80%% " "threshold on the open file descriptors limit (%d), " "consider increasing the limit using -L command line " "option", (int)rtpp_rlim_max(cf)); } RTPP_LOG(spa->log, RTPP_LOG_INFO, "new session on a port %d created, " "tag %s", lport, cmd->cca.from_tag); if (cf->stable->record_all != 0) { handle_copy(cf, spa, 0, NULL, 0); handle_copy(cf, spa, 1, NULL, 0); } /* Save ref, it will be decref'd by the command disposal code */ RTPP_DBG_ASSERT(cmd->sp == NULL); cmd->sp = spa; } if (cmd->cca.op == UPDATE) { if (!CALL_METHOD(cf->stable->rtpp_tnset_cf, isenabled) && ulop->notify_socket != NULL) RTPP_LOG(spa->log, RTPP_LOG_ERR, "must permit notification socket with -n"); if (spa->timeout_data.notify_tag != NULL) { free(spa->timeout_data.notify_tag); spa->timeout_data.notify_tag = NULL; } if (ulop->notify_socket != NULL) { struct rtpp_tnotify_target *rttp; rttp = CALL_METHOD(cf->stable->rtpp_tnset_cf, lookup, ulop->notify_socket, (cmd->rlen > 0) ? sstosa(&cmd->raddr) : NULL, (cmd->rlen > 0) ? cmd->laddr : NULL); if (rttp == NULL) { RTPP_LOG(spa->log, RTPP_LOG_ERR, "invalid socket name %s", ulop->notify_socket); ulop->notify_socket = NULL; } else { RTPP_LOG(spa->log, RTPP_LOG_INFO, "setting timeout handler"); spa->timeout_data.notify_target = rttp; spa->timeout_data.notify_tag = strdup(ulop->notify_tag); } } else if (spa->timeout_data.notify_target != NULL) { spa->timeout_data.notify_target = NULL; RTPP_LOG(spa->log, RTPP_LOG_INFO, "disabling timeout handler"); } } if (ulop->ia[0] != NULL && ulop->ia[1] != NULL) { CALL_METHOD(spa->rtp->stream[pidx], prefill_addr, &(ulop->ia[0]), cmd->dtime); CALL_METHOD(spa->rtcp->stream[pidx], prefill_addr, &(ulop->ia[1]), cmd->dtime); } spa->rtp->stream[pidx]->asymmetric = spa->rtcp->stream[pidx]->asymmetric = ulop->asymmetric; spa->rtp->stream[pidx]->latch_info.latched = spa->rtcp->stream[pidx]->latch_info.latched = ulop->asymmetric; if (spa->rtp->stream[pidx]->codecs != NULL) { free(spa->rtp->stream[pidx]->codecs); spa->rtp->stream[pidx]->codecs = NULL; } if (ulop->codecs != NULL) { spa->rtp->stream[pidx]->codecs = ulop->codecs; ulop->codecs = NULL; } spa->rtp->stream[NOT(pidx)]->ptime = ulop->requested_ptime; actor = CALL_METHOD(spa->rtp->stream[pidx], get_actor); if (ulop->requested_ptime > 0) { RTPP_LOG(spa->log, RTPP_LOG_INFO, "RTP packets from %s " "will be resized to %d milliseconds", actor, ulop->requested_ptime); } else if (spa->rtp->stream[pidx]->resizer != NULL) { RTPP_LOG(spa->log, RTPP_LOG_INFO, "Resizing of RTP " "packets from %s has been disabled", actor); } if (ulop->requested_ptime > 0) { if (spa->rtp->stream[pidx]->resizer != NULL) { rtp_resizer_set_ptime(spa->rtp->stream[pidx]->resizer, ulop->requested_ptime); } else { spa->rtp->stream[pidx]->resizer = rtp_resizer_new(ulop->requested_ptime); } } else if (spa->rtp->stream[pidx]->resizer != NULL) { rtp_resizer_free(cf->stable->rtpp_stats, spa->rtp->stream[pidx]->resizer); spa->rtp->stream[pidx]->resizer = NULL; } RTPP_DBG_ASSERT(lport != 0); ulop->reply.port = lport; ulop->reply.ia = ulop->lia[0]; if (cf->stable->advaddr[0] != NULL) { if (cf->stable->bmode != 0 && cf->stable->advaddr[1] != NULL && ulop->lia[0] == cf->stable->bindaddr[1]) { ulop->reply.ia_ov = cf->stable->advaddr[1]; } else { ulop->reply.ia_ov = cf->stable->advaddr[0]; } } ul_reply_port(cmd, &ulop->reply); rtpp_command_ul_opts_free(ulop); return (0); err_undo_0: rtpp_command_ul_opts_free(ulop); return (-1); }
void rtpp_timed_task_fin(struct rtpp_timed_task *pub) { RTPP_DBG_ASSERT(pub->cancel != (rtpp_timed_task_cancel_t)NULL); RTPP_DBG_ASSERT(pub->cancel != (rtpp_timed_task_cancel_t)&rtpp_timed_task_cancel_fin); pub->cancel = (rtpp_timed_task_cancel_t)&rtpp_timed_task_cancel_fin; }