コード例 #1
0
ファイル: rtp_analyze.c プロジェクト: JustRight/rtpproxy
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);
    }
コード例 #2
0
ファイル: rtp_analyze.c プロジェクト: JustRight/rtpproxy
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);
}
コード例 #3
0
ファイル: rtpp_netaddr_fin.c プロジェクト: sippy/rtpproxy
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;
}
コード例 #4
0
ファイル: rtpp_pcount_fin.c プロジェクト: sippy/rtpproxy
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;
}
コード例 #5
0
ファイル: rtp_analyze.c プロジェクト: JustRight/rtpproxy
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);
}
コード例 #6
0
ファイル: rtpp_socket.c プロジェクト: sippy/rtpproxy
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);
}
コード例 #7
0
ファイル: rtpp_command_ul.c プロジェクト: kcratie/rtpproxy
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);
}
コード例 #8
0
ファイル: rtpp_timed_task_fin.c プロジェクト: sippy/rtpproxy
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;
}