Beispiel #1
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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);
}
Beispiel #7
0
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;
}
Beispiel #8
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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);
}
Beispiel #11
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);
}
Beispiel #12
0
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);
}
Beispiel #13
0
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);
    }

  }
}
Beispiel #14
0
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);
}