1 /*
2  * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3  * Copyright (c) 2006-2015 Sippy Software, Inc., http://www.sippysoft.com
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 
29 #include <sys/types.h>
30 #include <netinet/in.h>
31 #include <stdlib.h>
32 
33 #include "rtpp_defines.h"
34 #include "rtpp_cfg_stable.h"
35 #include "rtpp_types.h"
36 #include "rtpp_refcnt.h"
37 #include "rtpp_weakref.h"
38 #include "rtpp_hash_table.h"
39 #include "rtp.h"
40 #include "rtp_packet.h"
41 #include "rtpp_proc.h"
42 #include "rtpp_proc_servers.h"
43 #include "rtpp_server.h"
44 #include "rtpp_stream.h"
45 #include "rtpp_netaddr.h"
46 
47 struct foreach_args {
48     double dtime;
49     struct sthread_args *sender;
50     struct rtpp_proc_rstats *rsp;
51     struct rtpp_weakref_obj *rtp_streams_wrt;
52     struct rtpp_weakref_obj *rtcp_streams_wrt;
53 };
54 
55 static int
process_rtp_servers_foreach(void * dp,void * ap)56 process_rtp_servers_foreach(void *dp, void *ap)
57 {
58     struct foreach_args *fap;
59     struct rtpp_server *rsrv;
60     struct rtp_packet *pkt;
61     int len;
62     struct rtpp_stream *rsop;
63 
64     fap = (struct foreach_args *)ap;
65     /*
66      * This method does not need us to bump ref, since we are in the
67      * locked context of the rtpp_hash_table, which holds its own ref.
68      */
69     rsrv = (struct rtpp_server *)dp;
70     rsop = CALL_METHOD(fap->rtp_streams_wrt, get_by_idx, rsrv->stuid);
71     if (rsop == NULL) {
72         return (RTPP_WR_MATCH_CONT);
73     }
74     for (;;) {
75         pkt = CALL_SMETHOD(rsrv, get, fap->dtime, &len);
76         if (pkt == NULL) {
77             if (len == RTPS_EOF) {
78                 CALL_SMETHOD(rsop, finish_playback, rsrv->sruid);
79                 CALL_SMETHOD(rsop->rcnt, decref);
80                 return (RTPP_WR_MATCH_DEL);
81             } else if (len != RTPS_LATER) {
82                 /* XXX some error, brag to logs */
83             }
84             break;
85         }
86         if (CALL_SMETHOD(rsop, issendable) == 0) {
87             /* We have a packet, but nowhere to send it, drop */
88             rtp_packet_free(pkt);
89             continue;
90         }
91         CALL_SMETHOD(rsop, send_pkt, fap->sender, pkt);
92         fap->rsp->npkts_played.cnt++;
93     }
94     CALL_SMETHOD(rsop->rcnt, decref);
95     return (RTPP_WR_MATCH_CONT);
96 }
97 
98 void
rtpp_proc_servers(struct cfg * cf,double dtime,struct sthread_args * sender,struct rtpp_proc_rstats * rsp)99 rtpp_proc_servers(struct cfg *cf, double dtime, struct sthread_args *sender,
100   struct rtpp_proc_rstats *rsp)
101 {
102     struct foreach_args fargs;
103 
104     fargs.dtime = dtime;
105     fargs.sender = sender;
106     fargs.rsp = rsp;
107     fargs.rtp_streams_wrt = cf->stable->rtp_streams_wrt;
108     fargs.rtcp_streams_wrt = cf->stable->rtcp_streams_wrt;
109 
110     CALL_METHOD(cf->stable->servers_wrt, foreach, process_rtp_servers_foreach,
111       &fargs);
112 }
113