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); }
struct rtpp_acct_rtcp * rtpp_acct_rtcp_ctor(const char *call_id, const struct rtp_packet *pp) { struct rtpp_acct_rtcp_priv *pvt; pvt = rtpp_rzmalloc(sizeof(struct rtpp_acct_rtcp_priv), PVT_RCOFFS(pvt)); if (pvt == NULL) { goto e0; } pvt->pub.pkt = rtp_packet_alloc(); if (pvt->pub.pkt == NULL) { goto e1; } rtp_packet_dup(pvt->pub.pkt, pp, 0); pvt->pub.call_id = strdup(call_id); if (pvt->pub.call_id == NULL) { goto e2; } pvt->pub.jt = &pvt->_jt; CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_acct_rtcp_dtor, pvt); return ((&pvt->pub)); e2: rtp_packet_free(pvt->pub.pkt); e1: CALL_SMETHOD(pvt->pub.rcnt, decref); free(pvt); e0: return (NULL); }
int rtpp_anetio_send_pkt(struct sthread_args *sender, int sock, \ const struct sockaddr *sendto, socklen_t tolen, struct rtp_packet *pkt) { struct rtpp_wi *wi; int nsend; if (sender->dmode != 0 && pkt->size < LBR_THRS) { nsend = 2; } else { nsend = 1; } wi = rtpp_wi_malloc_pkt(sock, pkt, sendto, tolen, nsend); if (wi == NULL) { rtp_packet_free(pkt); return (-1); } /* * rtpp_wi_malloc_pkt() consumes pkt and returns wi, so no need to * call rtp_packet_free() here. */ rtpp_queue_put_item(wi, sender->out_q); return (0); }
static void rtpp_acct_rtcp_dtor(struct rtpp_acct_rtcp_priv *pvt) { /*rtpp_acct_rtcp_fin(&(pvt->pub));*/ free(pvt->pub.call_id); rtp_packet_free(pvt->pub.pkt); free(pvt); }
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); }
static int process_rtp_servers_foreach(void *dp, void *ap) { struct foreach_args *fap; struct rtpp_server *rsrv; struct rtp_packet *pkt; int len; struct rtpp_stream *rsop; fap = (struct foreach_args *)ap; /* * This method does not need us to bump ref, since we are in the * locked context of the rtpp_hash_table, which holds its own ref. */ rsrv = (struct rtpp_server *)dp; rsop = CALL_METHOD(fap->rtp_streams_wrt, get_by_idx, rsrv->stuid); if (rsop == NULL) { return (RTPP_WR_MATCH_CONT); } for (;;) { pkt = CALL_SMETHOD(rsrv, get, fap->dtime, &len); if (pkt == NULL) { if (len == RTPS_EOF) { CALL_SMETHOD(rsop, finish_playback, rsrv->sruid); CALL_SMETHOD(rsop->rcnt, decref); return (RTPP_WR_MATCH_DEL); } else if (len != RTPS_LATER) { /* XXX some error, brag to logs */ } break; } if (CALL_SMETHOD(rsop, issendable) == 0) { /* We have a packet, but nowhere to send it, drop */ rtp_packet_free(pkt); continue; } CALL_SMETHOD(rsop, send_pkt, fap->sender, pkt); fap->rsp->npkts_played.cnt++; } CALL_SMETHOD(rsop->rcnt, decref); return (RTPP_WR_MATCH_CONT); }
int main() { struct rtp_packet *pkt; pkt = rtp_packet_new(); if (!pkt) { fprintf(stderr, "malloc error\n"); } fprintf(stderr, "rtp header size %ld\n", sizeof(struct rtp_hdr_t)); fprintf(stderr, "rtp packet size %ld\n", sizeof(struct rtp_packet)); fprintf(stderr, "rtcp packet size %ld\n", sizeof(struct rtcp_packet)); rtp_packet_build(pkt, NULL, 0); fprintf(stderr, "random = 0x%x\n", random32()); fprintf(stderr, "random = 0x%8x\n", random32()); rtp_packet_free(pkt); return 0; }
struct rtp_packet * rtp_recv(int fd) { struct rtp_packet *pkt; pkt = rtp_packet_alloc(); if (pkt == NULL) return NULL; pkt->rlen = sizeof(pkt->raddr); pkt->size = recvfrom(fd, pkt->data.buf, sizeof(pkt->data.buf), 0, sstosa(&pkt->raddr), &pkt->rlen); if (pkt->size == -1) { rtp_packet_free(pkt); return NULL; } return pkt; }
struct rtp_packet *rtp_packet_new(void) { struct rtp_packet *pkt; if ((pkt = calloc(1, sizeof(struct rtp_packet))) == NULL) { fprintf(stderr, "%s: calloc rtp_packet", __func__); goto err; } if ((pkt->hdr = calloc(1, sizeof(struct rtp_hdr_t))) == NULL) { fprintf(stderr, "%s: calloc rtp_hdr_t", __func__); goto err; } if ((pkt->ext = calloc(1, sizeof(struct rtp_hdr_ext))) == NULL) { fprintf(stderr, "%s: calloc rtp_hdr_ext", __func__); goto err; } return pkt; err: rtp_packet_free(pkt); return NULL; }
int rtpp_anetio_send_pkt_na(struct sthread_args *sender, int sock, \ struct rtpp_netaddr *sendto, struct rtp_packet *pkt, struct rtpp_refcnt *sock_rcnt, struct rtpp_log *plog) { struct rtpp_wi *wi; int nsend; if (sender->dmode != 0 && pkt->size < LBR_THRS) { nsend = 2; } else { nsend = 1; } wi = rtpp_wi_malloc_pkt_na(sock, pkt, sendto, nsend, sock_rcnt); if (wi == NULL) { rtp_packet_free(pkt); return (-1); } /* * rtpp_wi_malloc_pkt() consumes pkt and returns wi, so no need to * call rtp_packet_free() here. */ #if RTPP_DEBUG_netio >= 2 wi->debug = 1; if (plog == NULL) { plog = sender->glog; } CALL_SMETHOD(plog->rcnt, incref); wi->log = plog; RTPP_LOG(plog, RTPP_LOG_DBUG, "send_pkt(%d, %p, %d, %d, %p, %d)", wi->sock, wi->msg, wi->msg_len, wi->flags, wi->sendto, wi->tolen); #endif rtpp_queue_put_item(wi, sender->out_q); return (0); }
static void process_rtp(struct cfg *cf, double dtime, int alarm_tick) { int readyfd, skipfd, ridx; struct rtpp_session *sp; struct rtp_packet *packet; /* Relay RTP/RTCP */ skipfd = 0; pthread_mutex_lock(&cf->sessinfo.lock); for (readyfd = 0; readyfd < cf->sessinfo.nsessions; readyfd++) { sp = cf->sessinfo.sessions[readyfd]; if (alarm_tick != 0 && sp != NULL && sp->rtcp != NULL && sp->sidx[0] == readyfd) { if (get_ttl(sp) == 0) { rtpp_log_write(RTPP_LOG_INFO, sp->log, "session timeout"); rtpp_notify_schedule(cf, sp); remove_session(cf, sp); } else { if (sp->ttl[0] != 0) sp->ttl[0]--; if (sp->ttl[1] != 0) sp->ttl[1]--; } } if (cf->sessinfo.pfds[readyfd].fd == -1) { /* Deleted session, count and move one */ skipfd++; continue; } /* Find index of the call leg within a session */ for (ridx = 0; ridx < 2; ridx++) if (cf->sessinfo.pfds[readyfd].fd == sp->fds[ridx]) break; /* * Can't happen. */ assert(ridx != 2); /* Compact pfds[] and sessions[] by eliminating removed sessions */ if (skipfd > 0) { cf->sessinfo.pfds[readyfd - skipfd] = cf->sessinfo.pfds[readyfd]; cf->sessinfo.sessions[readyfd - skipfd] = cf->sessinfo.sessions[readyfd]; sp->sidx[ridx] = readyfd - skipfd; } if (sp->complete != 0) { if ((cf->sessinfo.pfds[readyfd].revents & POLLIN) != 0) rxmit_packets(cf, sp, ridx, dtime); if (sp->resizers[ridx].output_nsamples > 0) { while ((packet = rtp_resizer_get(&sp->resizers[ridx], dtime)) != NULL) { send_packet(cf, sp, ridx, packet); rtp_packet_free(packet); } } } } /* Trim any deleted sessions at the end */ cf->sessinfo.nsessions -= skipfd; pthread_mutex_unlock(&cf->sessinfo.lock); }
static void rxmit_packets(struct cfg *cf, struct rtpp_session *sp, int ridx, double dtime) { int ndrain, i, port; struct rtp_packet *packet = NULL; /* Repeat since we may have several packets queued on the same socket */ for (ndrain = 0; ndrain < 5; ndrain++) { if (packet != NULL) rtp_packet_free(packet); packet = rtp_recv(sp->fds[ridx]); if (packet == NULL) break; packet->laddr = sp->laddr[ridx]; packet->rport = sp->ports[ridx]; packet->rtime = dtime; i = 0; if (sp->addr[ridx] != NULL) { /* Check that the packet is authentic, drop if it isn't */ if (sp->asymmetric[ridx] == 0) { if (memcmp(sp->addr[ridx], &packet->raddr, packet->rlen) != 0) { if (sp->canupdate[ridx] == 0) { /* * Continue, since there could be good packets in * queue. */ continue; } /* Signal that an address has to be updated */ i = 1; } else if (sp->canupdate[ridx] != 0 && sp->last_update[ridx] != 0 && dtime - sp->last_update[ridx] > UPDATE_WINDOW) { sp->canupdate[ridx] = 0; } } else { /* * For asymmetric clients don't check * source port since it may be different. */ if (!ishostseq(sp->addr[ridx], sstosa(&packet->raddr))) /* * Continue, since there could be good packets in * queue. */ continue; } sp->pcount[ridx]++; } else { sp->pcount[ridx]++; sp->addr[ridx] = malloc(packet->rlen); if (sp->addr[ridx] == NULL) { sp->pcount[3]++; rtpp_log_write(RTPP_LOG_ERR, sp->log, "can't allocate memory for remote address - " "removing session"); remove_session(cf, GET_RTP(sp)); /* Break, sp is invalid now */ break; } /* Signal that an address have to be updated. */ i = 1; } /* * Update recorded address if it's necessary. Set "untrusted address" * flag in the session state, so that possible future address updates * from that client won't get address changed immediately to some * bogus one. */ if (i != 0) { sp->untrusted_addr[ridx] = 1; memcpy(sp->addr[ridx], &packet->raddr, packet->rlen); if (sp->prev_addr[ridx] == NULL || memcmp(sp->prev_addr[ridx], &packet->raddr, packet->rlen) != 0) { sp->canupdate[ridx] = 0; } port = ntohs(satosin(&packet->raddr)->sin_port); rtpp_log_write(RTPP_LOG_INFO, sp->log, "%s's address filled in: %s:%d (%s)", (ridx == 0) ? "callee" : "caller", addr2char(sstosa(&packet->raddr)), port, (sp->rtp == NULL) ? "RTP" : "RTCP"); /* * Check if we have updated RTP while RTCP is still * empty or contains address that differs from one we * used when updating RTP. Try to guess RTCP if so, * should be handy for non-NAT'ed clients, and some * NATed as well. */ if (sp->rtcp != NULL && (sp->rtcp->addr[ridx] == NULL || !ishostseq(sp->rtcp->addr[ridx], sstosa(&packet->raddr)))) { if (sp->rtcp->addr[ridx] == NULL) { sp->rtcp->addr[ridx] = malloc(packet->rlen); if (sp->rtcp->addr[ridx] == NULL) { sp->pcount[3]++; rtpp_log_write(RTPP_LOG_ERR, sp->log, "can't allocate memory for remote address - " "removing session"); remove_session(cf, sp); /* Break, sp is invalid now */ break; } } memcpy(sp->rtcp->addr[ridx], &packet->raddr, packet->rlen); satosin(sp->rtcp->addr[ridx])->sin_port = htons(port + 1); /* Use guessed value as the only true one for asymmetric clients */ sp->rtcp->canupdate[ridx] = NOT(sp->rtcp->asymmetric[ridx]); rtpp_log_write(RTPP_LOG_INFO, sp->log, "guessing RTCP port " "for %s to be %d", (ridx == 0) ? "callee" : "caller", port + 1); } } if (sp->resizers[ridx].output_nsamples > 0) rtp_resizer_enqueue(&sp->resizers[ridx], &packet); if (packet != NULL) send_packet(cf, sp, ridx, packet); } if (packet != NULL) rtp_packet_free(packet); }
void *mod_cin (void *ptr) { int rtpfd; /* RTP socket file descriptor */ int rtcpfd; /* RTCP socket file descriptor */ socklen_t addr_len; /* Data size, Bytes received */ struct sockaddr_in rtps; /* RTP socket */ struct sockaddr_in rtcps; /* RTCP socket */ struct sockaddr_in remote; /* Remote address information */ vstr_t recv_data; /* Received data */ rtp_packet_t *packet; /* Parsed RTP packet */ fd_set readset; int fdmax; fprintf(stderr, "+ Communication input module loaded.\n"); vstr_init (&recv_data, RTP_MTU_SIZE); if ((rtpfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Error opening socket"); exit(1); } if ((rtcpfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("Error opening socket"); exit(1); } rtps.sin_family = AF_INET; /* Internet protocol */ rtps.sin_port = htons(RTP_PORT); /* Port */ rtps.sin_addr.s_addr = htonl(INADDR_ANY); /* rtps address */ memset(&(rtps.sin_zero), '\0', 8); /* Zero the rest */ if (bind(rtpfd, (struct sockaddr *) &rtps, sizeof(struct sockaddr)) < 0) { perror("Error binding socket"); exit(1); } rtcps.sin_family = AF_INET; /* Internet protocol */ rtcps.sin_port = htons(RTCP_PORT); /* Port */ rtcps.sin_addr.s_addr = htonl(INADDR_ANY); /* rtcps address */ memset(&(rtcps.sin_zero), '\0', 8); /* Zero the rest */ if (bind(rtcpfd, (struct sockaddr *) &rtcps, sizeof(struct sockaddr)) < 0) { perror("Error binding socket"); exit(1); } fprintf(stderr, "+ RTP Listening at %s:%d...\n", inet_ntoa(rtps.sin_addr), ntohs(rtps.sin_port)); fprintf(stderr, "+ RTCP Listening at %s:%d...\n", inet_ntoa(rtcps.sin_addr), ntohs(rtcps.sin_port)); addr_len = sizeof(struct sockaddr); while(1) { FD_ZERO (&readset); FD_SET (rtpfd, &readset); FD_SET (rtcpfd, &readset); fdmax = (rtpfd < rtcpfd) ? rtcpfd : rtpfd; select (fdmax + 1, &readset, NULL, NULL, NULL); if (FD_ISSET(rtpfd, &readset)) { /* Receive data from network */ recv_data.size = recvfrom (rtpfd, recv_data.data, RTP_MTU_SIZE, 0, (struct sockaddr *)&remote, &addr_len); printf("receive data, size = %d!!!!!!!!!!!!!!!!!\n", recv_data.size); vstr_adv_tail (&recv_data, recv_data.size); if (recv_data.size < 0) { perror("Error receiving data from socket"); exit(1); } /* Write to buffer */ packet = rtp_recv (&rtp, &recv_data); if (packet != NULL && rtp_enqueue (&rtp, packet) == -1) rtp_packet_free (packet); vstr_flush (&recv_data); } if (FD_ISSET(rtcpfd, &readset)) { /* Receive data from network */ recv_data.size = recvfrom (rtcpfd, recv_data.data, RTP_MTU_SIZE, 0, (struct sockaddr *)&remote, &addr_len); vstr_adv_tail (&recv_data, recv_data.size); if (recv_data.size < 0) { perror("Error receiving data from socket"); exit(1); } rtcp_recv (&rtp, &recv_data); vstr_flush (&recv_data); } } }
struct rtp_packet * rtp_server_get(struct rtp_server *rp, double dtime, int *rval) { struct rtp_packet *pkt; uint32_t ts; int rlen, rticks, bytes_per_frame, ticks_per_frame, number_of_frames; int hlen; if (rp->btime == -1) rp->btime = dtime; ts = ntohl(rp->rtp->ts); if (rp->btime + ((double)ts / RTPS_SRATE) > dtime) { *rval = RTPS_LATER; return (NULL); } switch (rp->rtp->pt) { case RTP_PCMU: case RTP_PCMA: bytes_per_frame = 8; ticks_per_frame = 1; break; case RTP_G729: /* 10 ms per 8 kbps G.729 frame */ bytes_per_frame = 10; ticks_per_frame = 10; break; case RTP_G723: /* 30 ms per 6.3 kbps G.723 frame */ bytes_per_frame = 24; ticks_per_frame = 30; break; case RTP_GSM: /* 20 ms per 13 kbps GSM frame */ bytes_per_frame = 33; ticks_per_frame = 20; break; case RTP_G722: bytes_per_frame = 8; ticks_per_frame = 1; break; default: *rval = RTPS_ERROR; return (NULL); } number_of_frames = RTPS_TICKS_MIN / ticks_per_frame; if (RTPS_TICKS_MIN % ticks_per_frame != 0) number_of_frames++; rlen = bytes_per_frame * number_of_frames; rticks = ticks_per_frame * number_of_frames; pkt = rtp_packet_alloc(); if (pkt == NULL) { *rval = RTPS_ENOMEM; return (NULL); } hlen = RTP_HDR_LEN(rp->rtp); if (read(rp->fd, pkt->data.buf + hlen, rlen) != rlen) { if (rp->loop == 0 || lseek(rp->fd, 0, SEEK_SET) == -1 || read(rp->fd, pkt->data.buf + hlen, rlen) != rlen) { *rval = RTPS_EOF; rtp_packet_free(pkt); return (NULL); } if (rp->loop != -1) rp->loop -= 1; } if (rp->rtp->m != 0 && ntohs(rp->rtp->seq) != 0) { rp->rtp->m = 0; } rp->rtp->ts = htonl(ts + (RTPS_SRATE * rticks / 1000)); rp->rtp->seq = htons(ntohs(rp->rtp->seq) + 1); memcpy(&pkt->data.header, rp->rtp, hlen); pkt->size = hlen + rlen; return (pkt); }