static int rtpp_stream_check_latch_override(struct rtpp_stream *self, struct rtp_packet *packet) { const char *actor; struct rtpp_stream_priv *pvt; char saddr[MAX_AP_STRBUF]; pvt = PUB2PVT(self); if (self->session_type == SESS_RTCP || self->latch_info.ssrc == 0) return (0); if (rtp_packet_parse(packet) != RTP_PARSER_OK) return (0); if (packet->parsed->ssrc != self->latch_info.ssrc) return (0); if (packet->parsed->seq < self->latch_info.seq && self->latch_info.seq - packet->parsed->seq < 536) return (0); actor = rtpp_stream_get_actor(self); addrport2char_r(sstosa(&packet->raddr), saddr, sizeof(saddr)); RTPP_LOG(pvt->pub.log, RTPP_LOG_INFO, "%s's address re-latched: %s (%s), SSRC=" SSRC_FMT ", Seq=%u->%u", actor, saddr, "RTP", self->latch_info.ssrc, self->latch_info.seq, packet->parsed->seq); self->latch_info.seq = packet->parsed->seq; return (1); }
static int rtpp_notify_schedule(struct rtpp_notify *pub, struct rtpp_tnotify_target *rttp, const char *notify_tag) { struct rtpp_notify_wi *wi_data; struct rtpp_wi *wi; int len; struct rtpp_notify_priv *pvt; pvt = PUB2PVT(pub); /* string, \0 and \n */ len = strlen(notify_tag) + 2; wi = rtpp_wi_malloc_udata((void **)&wi_data, sizeof(struct rtpp_notify_wi) + len); if (wi == NULL) { return (-1); } memset(wi_data, '\0', sizeof(struct rtpp_notify_wi) + len); wi_data->rttp = rttp; wi_data->len = len; len = snprintf(wi_data->notify_buf, len, "%s\n", notify_tag); CALL_METHOD(pvt->glog->rcnt, incref); wi->log = pvt->glog; rtpp_queue_put_item(wi, pvt->nqueue); return (0); }
static struct rtp_packet * rtpp_socket_rtp_recv_simple(struct rtpp_socket *self, const struct rtpp_timestamp *dtime, struct sockaddr *laddr, int port) { struct rtpp_socket_priv *pvt; struct rtp_packet *packet; packet = rtp_packet_alloc(); if (packet == NULL) { return NULL; } pvt = PUB2PVT(self); packet->rlen = sizeof(packet->raddr); packet->size = recvfrom(pvt->fd, packet->data.buf, sizeof(packet->data.buf), 0, sstosa(&packet->raddr), &packet->rlen); if (packet->size == -1) { rtp_packet_free(packet); return (NULL); } packet->laddr = laddr; packet->lport = port; if (dtime != NULL) { packet->rtime.wall = dtime->wall; packet->rtime.mono = dtime->mono; } return (packet); }
static void rtpp_tnotify_set_dtor(struct rtpp_tnotify_set_obj *pub) { struct rtpp_tnotify_set *pvt; struct rtpp_tnotify_target *tp; int i; pvt = PUB2PVT(pub); for (i = 0; i < pvt->tp_len; i++) { tp = pvt->tp[i]; if (tp->socket_name != NULL) free(tp->socket_name); if (tp->connected) { assert(tp->fd >= 0); close(tp->fd); } if (tp->local != NULL) free(tp->local); free(tp); } for (i = 0; i < pvt->wp_len; i++) { free(pvt->wp[i]->socket_name); free(pvt->wp[i]); } free(pvt); }
static void rtpp_command_async_dtor(struct rtpp_cmd_async_obj *pub) { struct rtpp_cmd_async_cf *cmd_cf; int i; cmd_cf = PUB2PVT(pub); pthread_mutex_lock(&cmd_cf->cmd_mutex); cmd_cf->tstate_queue = TSTATE_CEASE; /* nudge acceptor thread */ if (cmd_cf->acceptor_started != 0) { cmd_cf->tstate_acceptor = TSTATE_CEASE; for (i = 0; i < cmd_cf->aset.pfds_used; i ++) { close(cmd_cf->aset.pfds[i].fd); } } /* notify worker thread */ pthread_cond_signal(&cmd_cf->cmd_cond); pthread_mutex_unlock(&cmd_cf->cmd_mutex); pthread_join(cmd_cf->thread_id, NULL); if (cmd_cf->acceptor_started != 0) { pthread_join(cmd_cf->acpt_thread_id, NULL); } CALL_METHOD(cmd_cf->rcache, dtor); pthread_cond_destroy(&cmd_cf->cmd_cond); pthread_mutex_destroy(&cmd_cf->cmd_mutex); free_pollset(&cmd_cf->pset); free_accptset(&cmd_cf->aset); free(cmd_cf); }
static int rtpp_stream_guess_addr(struct rtpp_stream *self, struct rtp_packet *packet) { int rport; const char *actor, *ptype; struct rtpp_stream_priv *pvt; pvt = PUB2PVT(self); if (self->addr != NULL && ishostseq(self->addr, sstosa(&packet->raddr))) { return (0); } if (self->addr == NULL) { self->addr = malloc(packet->rlen); if (self->addr == NULL) { return (-1); } } actor = rtpp_stream_get_actor(self); ptype = rtpp_stream_get_proto(self); rport = ntohs(satosin(&packet->raddr)->sin_port); if (IS_LAST_PORT(rport)) { return (-1); } memcpy(self->addr, &packet->raddr, packet->rlen); satosin(self->addr)->sin_port = htons(rport + 1); /* Use guessed value as the only true one for asymmetric clients */ self->latch_info.latched = self->asymmetric; RTPP_LOG(pvt->pub.log, RTPP_LOG_INFO, "guessing %s port " "for %s to be %d", ptype, actor, rport + 1); return (0); }
static int rtpp_socket_settos(struct rtpp_socket *self, int tos) { struct rtpp_socket_priv *pvt; pvt = PUB2PVT(self); return (setsockopt(pvt->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))); }
static int rtpp_wref_purge(struct rtpp_weakref_obj *pub) { struct rtpp_weakref_priv *pvt; pvt = PUB2PVT(pub); return (CALL_METHOD(pvt->ht, purge)); }
static int rtpp_wref_get_length(struct rtpp_weakref_obj *pub) { struct rtpp_weakref_priv *pvt; pvt = PUB2PVT(pub); return (CALL_METHOD(pvt->ht, get_length)); }
static int rtpp_tnotify_set_isenabled(struct rtpp_tnotify_set_obj *pub) { struct rtpp_tnotify_set *pvt; pvt = PUB2PVT(pub); return (pvt->wp_len > 0 || pvt->tp_len > 0); }
static int rtpp_socket_getfd(struct rtpp_socket *self) { struct rtpp_socket_priv *pvt; pvt = PUB2PVT(self); return (pvt->fd); }
static const char * rtpp_stream_get_actor(struct rtpp_stream *self) { struct rtpp_stream_priv *pvt; pvt = PUB2PVT(self); return ((pvt->side == RTPP_SSIDE_CALLER) ? "caller" : "callee"); }
static int rtpp_tnotify_set_append(struct rtpp_tnotify_set_obj *pub, const char *socket_name, const char **e) { int rval; struct rtpp_tnotify_set *pvt; struct rtpp_tnotify_target *tntp; struct rtpp_tnotify_wildcard *tnwp; union rtpp_tnotify_entry rte; pvt = PUB2PVT(pub); memset(&rte, '\0', sizeof(union rtpp_tnotify_entry)); rval = parse_timeout_sock(socket_name, &rte, e); if (rval < 0) { goto e0; } tntp = NULL; tnwp = NULL; if (rval == 0) { if (pvt->tp_len == RTPP_TNOTIFY_TARGETS_MAX) { *e = "Number of notify targets exceeds RTPP_TNOTIFY_TARGETS_MAX"; goto e0; } tntp = malloc(sizeof(struct rtpp_tnotify_target)); if (tntp == NULL) { *e = strerror(errno); goto e1; } memcpy(tntp, &rte.rtt, sizeof(struct rtpp_tnotify_target)); tntp->connected = 0; tntp->fd = -1; pvt->tp[pvt->tp_len] = tntp; pvt->tp_len += 1; } else { if (pvt->wp_len == RTPP_TNOTIFY_WILDCARDS_MAX) { *e = "Number of notify wildcards exceeds RTPP_TNOTIFY_WILDCARDS_MAX"; goto e0; } tnwp = malloc(sizeof(struct rtpp_tnotify_wildcard)); if (tnwp == NULL) { *e = strerror(errno); goto e1; } memcpy(tnwp, &rte.rtw, sizeof(struct rtpp_tnotify_wildcard)); pvt->wp[pvt->wp_len] = tnwp; pvt->wp_len += 1; } return (0); e1: if (tntp != NULL) free(tntp); if (tnwp != NULL) free(tnwp); e0: return (-1); }
static void rtpp_wref_foreach(struct rtpp_weakref_obj *pub, rtpp_weakref_foreach_t foreach_f, void *foreach_d) { struct rtpp_weakref_priv *pvt; pvt = PUB2PVT(pub); CALL_METHOD(pvt->ht, foreach, foreach_f, foreach_d); }
static int rtpp_socket_bind(struct rtpp_socket *self, const struct sockaddr *addr, int addrlen) { struct rtpp_socket_priv *pvt; pvt = PUB2PVT(self); return (bind(pvt->fd, addr, addrlen)); }
static int rtpp_socket_setrbuf(struct rtpp_socket *self, int so_rcvbuf) { struct rtpp_socket_priv *pvt; pvt = PUB2PVT(self); return (setsockopt(pvt->fd, SOL_SOCKET, SO_RCVBUF, &so_rcvbuf, sizeof(so_rcvbuf))); }
static void rtpp_pcount_get_stats(struct rtpp_pcount *self, struct rtpps_pcount *ocnt) { struct rtpp_pcount_priv *pvt; pvt = PUB2PVT(self); pthread_mutex_lock(&pvt->lock); memcpy(ocnt, &pvt->cnt, sizeof(struct rtpps_pcount)); pthread_mutex_unlock(&pvt->lock); }
static void rtpp_pcount_reg_reld(struct rtpp_pcount *self) { struct rtpp_pcount_priv *pvt; pvt = PUB2PVT(self); pthread_mutex_lock(&pvt->lock); pvt->cnt.nrelayed++; pthread_mutex_unlock(&pvt->lock); }
static void rtpp_weakref_dtor(struct rtpp_weakref_obj *pub) { struct rtpp_weakref_priv *pvt; pvt = PUB2PVT(pub); CALL_METHOD(pvt->ht, dtor); free(pvt); }
static void rtpp_ttl_reset(struct rtpp_ttl *self) { struct rtpp_ttl_priv *pvt; pvt = PUB2PVT(self); pthread_mutex_lock(&pvt->lock); pvt->ttl = pvt->max_ttl; pthread_mutex_unlock(&pvt->lock); }
static int rtpp_socket_setnonblock(struct rtpp_socket *self) { int flags; struct rtpp_socket_priv *pvt; pvt = PUB2PVT(self); flags = fcntl(pvt->fd, F_GETFL); return (fcntl(pvt->fd, F_SETFL, flags | O_NONBLOCK)); }
static int rtpp_stream_handle_play(struct rtpp_stream *self, char *codecs, char *pname, int playcount, struct rtpp_command *cmd, int ptime) { struct rtpp_stream_priv *pvt; int n; char *cp; struct rtpp_server *rsrv; uint16_t seq; uint32_t ssrc; const char *plerror; pvt = PUB2PVT(self); pthread_mutex_lock(&pvt->lock); plerror = "reason unknown"; while (*codecs != '\0') { n = strtol(codecs, &cp, 10); if (cp == codecs) { plerror = "invalid codecs"; break; } codecs = cp; if (*codecs != '\0') codecs++; rsrv = rtpp_server_ctor(pname, n, playcount, cmd->dtime, ptime); if (rsrv == NULL) { RTPP_LOG(pvt->pub.log, RTPP_LOG_DBUG, "rtpp_server_ctor(\"%s\", %d, %d) failed", pname, n, playcount); plerror = "rtpp_server_ctor() failed"; continue; } rsrv->stuid = self->stuid; ssrc = CALL_METHOD(rsrv, get_ssrc); seq = CALL_METHOD(rsrv, get_seq); if (CALL_METHOD(pvt->servers_wrt, reg, rsrv->rcnt, rsrv->sruid) != 0) { CALL_METHOD(rsrv->rcnt, decref); plerror = "servers_wrt->reg() method failed"; break; } assert(pvt->rtps == RTPP_UID_NONE); pvt->rtps = rsrv->sruid; pthread_mutex_unlock(&pvt->lock); cmd->csp->nplrs_created.cnt++; CALL_METHOD(rsrv->rcnt, reg_pd, (rtpp_refcnt_dtor_t)player_predestroy_cb, pvt->rtpp_stats); CALL_METHOD(rsrv->rcnt, decref); RTPP_LOG(pvt->pub.log, RTPP_LOG_INFO, "%d times playing prompt %s codec %d: SSRC=" SSRC_FMT ", seq=%u", playcount, pname, n, ssrc, seq); return 0; } pthread_mutex_unlock(&pvt->lock); RTPP_LOG(pvt->pub.log, RTPP_LOG_ERR, "can't create player: %s", plerror); return -1; }
static int rtpp_socket_send_pkt_na(struct rtpp_socket *self, struct sthread_args *str, struct rtpp_netaddr *daddr, struct rtp_packet *pkt, struct rtpp_log *log) { struct rtpp_socket_priv *pvt; pvt = PUB2PVT(self); return (rtpp_anetio_send_pkt_na(str, pvt->fd, daddr, pkt, self->rcnt, log)); }
static struct rtpp_refcnt * rtpp_weakref_unreg(struct rtpp_weakref_obj *pub, uint64_t suid) { struct rtpp_weakref_priv *pvt; struct rtpp_refcnt *sp; pvt = PUB2PVT(pub); sp = CALL_METHOD(pvt->ht, remove_by_key, &suid); return (sp); }
static void rtpp_notify_dtor(struct rtpp_notify_obj *pub) { struct rtpp_notify_priv *pvt; pvt = PUB2PVT(pub); rtpp_queue_put_item(pvt->sigterm, pvt->nqueue); pthread_join(pvt->thread_id, NULL); rtpp_queue_destroy(pvt->nqueue); free(pvt); }
static void rtpp_log_obj_setlevel(struct rtpp_log *self, int log_level) { struct rtpp_log_priv *pvt; pvt = PUB2PVT(self); if (log_level != -1) { rtpp_log_setlevel(pvt->log, log_level); } else { rtpp_log_setlevel(pvt->log, RTPP_LOG_ERR); } }
static int rtpp_ttl_get_remaining(struct rtpp_ttl *self) { struct rtpp_ttl_priv *pvt; int rval; pvt = PUB2PVT(self); pthread_mutex_lock(&pvt->lock); rval = pvt->ttl; pthread_mutex_unlock(&pvt->lock); return (rval); }
static uint64_t rtpp_stream_get_rtps(struct rtpp_stream *self) { struct rtpp_stream_priv *pvt; uint64_t rval; pvt = PUB2PVT(self); pthread_mutex_lock(&pvt->lock); rval = pvt->rtps; pthread_mutex_unlock(&pvt->lock); return (rval); }
static int rtpp_stream_isplayer_active(struct rtpp_stream *self) { struct rtpp_stream_priv *pvt; int rval; pvt = PUB2PVT(self); pthread_mutex_lock(&pvt->lock); rval = (pvt->rtps != RTPP_UID_NONE) ? 1 : 0; pthread_mutex_unlock(&pvt->lock); return (rval); }
static void rtpp_notify_dtor(struct rtpp_notify *pub) { struct rtpp_notify_priv *pvt; pvt = PUB2PVT(pub); rtpp_queue_put_item(pvt->sigterm, pvt->nqueue); pthread_join(pvt->thread_id, NULL); rtpp_queue_destroy(pvt->nqueue); CALL_METHOD(pvt->glog->rcnt, decref); free(pvt); }