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 <sys/socket.h>
31 #include <netinet/in.h>
32 #include <fcntl.h>
33 #include <stddef.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 #include "rtpp_types.h"
39 #include "rtpp_refcnt.h"
40 #include "rtpp_socket.h"
41 #include "rtpp_socket_fin.h"
42 #include "rtpp_netio_async.h"
43 #include "rtpp_mallocs.h"
44 #include "rtpp_monotime.h"
45 #include "rtpp_time.h"
46 #include "rtpp_network.h"
47 #include "rtpp_network_io.h"
48 #include "rtp.h"
49 #include "rtp_packet.h"
50 
51 struct rtpp_socket_priv {
52     struct rtpp_socket pub;
53     int fd;
54 };
55 
56 static void rtpp_socket_dtor(struct rtpp_socket_priv *);
57 static int rtpp_socket_bind(struct rtpp_socket *, const struct sockaddr *,
58   int);
59 static int rtpp_socket_settos(struct rtpp_socket *, int);
60 static int rtpp_socket_setrbuf(struct rtpp_socket *, int);
61 static int rtpp_socket_setnonblock(struct rtpp_socket *);
62 static int rtpp_socket_settimestamp(struct rtpp_socket *);
63 static int rtpp_socket_send_pkt(struct rtpp_socket *, struct sthread_args *,
64   const struct sockaddr *, int, struct rtp_packet *, struct rtpp_log *);
65 static int rtpp_socket_send_pkt_na(struct rtpp_socket *, struct sthread_args *,
66   struct rtpp_netaddr *, struct rtp_packet *, struct rtpp_log *);
67 static struct rtp_packet * rtpp_socket_rtp_recv_simple(struct rtpp_socket *,
68   double, struct sockaddr *, int);
69 static struct rtp_packet *rtpp_socket_rtp_recv(struct rtpp_socket *, double,
70   struct sockaddr *, int);
71 static int rtpp_socket_getfd(struct rtpp_socket *);
72 
73 #define PUB2PVT(pubp) \
74   ((struct rtpp_socket_priv *)((char *)(pubp) - offsetof(struct rtpp_socket_priv, pub)))
75 
76 struct rtpp_socket *
rtpp_socket_ctor(int domain,int type)77 rtpp_socket_ctor(int domain, int type)
78 {
79     struct rtpp_socket_priv *pvt;
80     struct rtpp_refcnt *rcnt;
81 
82     pvt = rtpp_rzmalloc(sizeof(struct rtpp_socket_priv), &rcnt);
83     if (pvt == NULL) {
84         goto e0;
85     }
86     pvt->pub.rcnt = rcnt;
87     pvt->fd = socket(domain, type, 0);
88     if (pvt->fd < 0) {
89         goto e1;
90     }
91     if (domain == AF_INET6) {
92         /* Disable any automatic IPv4->IPv6 gatewaying */
93         int yes = 1;
94 
95         setsockopt(pvt->fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes));
96     }
97     pvt->pub.bind = &rtpp_socket_bind;
98     pvt->pub.settos = &rtpp_socket_settos;
99     pvt->pub.setrbuf = &rtpp_socket_setrbuf;
100     pvt->pub.setnonblock = &rtpp_socket_setnonblock;
101     pvt->pub.settimestamp = &rtpp_socket_settimestamp;
102     pvt->pub.send_pkt = &rtpp_socket_send_pkt;
103     pvt->pub.send_pkt_na = &rtpp_socket_send_pkt_na;
104     pvt->pub.rtp_recv = &rtpp_socket_rtp_recv_simple;
105     pvt->pub.getfd = &rtpp_socket_getfd;
106     CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_socket_dtor,
107       pvt);
108     return (&pvt->pub);
109 e1:
110     CALL_SMETHOD(pvt->pub.rcnt, decref);
111     free(pvt);
112 e0:
113     return (NULL);
114 }
115 
116 static void
rtpp_socket_dtor(struct rtpp_socket_priv * pvt)117 rtpp_socket_dtor(struct rtpp_socket_priv *pvt)
118 {
119 
120     rtpp_socket_fin(&pvt->pub);
121     shutdown(pvt->fd, SHUT_RDWR);
122     close(pvt->fd);
123     free(pvt);
124 }
125 
126 static int
rtpp_socket_bind(struct rtpp_socket * self,const struct sockaddr * addr,int addrlen)127 rtpp_socket_bind(struct rtpp_socket *self, const struct sockaddr *addr,
128   int addrlen)
129 {
130     struct rtpp_socket_priv *pvt;
131 
132     pvt = PUB2PVT(self);
133     return (bind(pvt->fd, addr, addrlen));
134 }
135 
136 static int
rtpp_socket_settos(struct rtpp_socket * self,int tos)137 rtpp_socket_settos(struct rtpp_socket *self, int tos)
138 {
139     struct rtpp_socket_priv *pvt;
140 
141     pvt = PUB2PVT(self);
142     return (setsockopt(pvt->fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)));
143 }
144 
145 static int
rtpp_socket_setrbuf(struct rtpp_socket * self,int so_rcvbuf)146 rtpp_socket_setrbuf(struct rtpp_socket *self, int so_rcvbuf)
147 {
148     struct rtpp_socket_priv *pvt;
149 
150     pvt = PUB2PVT(self);
151     return (setsockopt(pvt->fd, SOL_SOCKET, SO_RCVBUF, &so_rcvbuf,
152       sizeof(so_rcvbuf)));
153 }
154 
155 static int
rtpp_socket_setnonblock(struct rtpp_socket * self)156 rtpp_socket_setnonblock(struct rtpp_socket *self)
157 {
158     int flags;
159     struct rtpp_socket_priv *pvt;
160 
161     pvt = PUB2PVT(self);
162     flags = fcntl(pvt->fd, F_GETFL);
163     return (fcntl(pvt->fd, F_SETFL, flags | O_NONBLOCK));
164 }
165 
166 static int
rtpp_socket_settimestamp(struct rtpp_socket * self)167 rtpp_socket_settimestamp(struct rtpp_socket *self)
168 {
169     struct rtpp_socket_priv *pvt;
170     int sval, rval;
171 
172     pvt = PUB2PVT(self);
173     sval = 1;
174     rval = setsockopt(pvt->fd, SOL_SOCKET, SO_TIMESTAMP, &sval,
175       sizeof(sval));
176     if (rval != 0) {
177         return (rval);
178     }
179     pvt->pub.rtp_recv = &rtpp_socket_rtp_recv;
180     return (0);
181 }
182 
183 static int
rtpp_socket_send_pkt(struct rtpp_socket * self,struct sthread_args * str,const struct sockaddr * daddr,int addrlen,struct rtp_packet * pkt,struct rtpp_log * log)184 rtpp_socket_send_pkt(struct rtpp_socket *self, struct sthread_args *str,
185   const struct sockaddr *daddr, int addrlen, struct rtp_packet *pkt,
186   struct rtpp_log *log)
187 {
188     struct rtpp_socket_priv *pvt;
189 
190     pvt = PUB2PVT(self);
191     return (rtpp_anetio_send_pkt(str, pvt->fd, daddr, addrlen, pkt,
192       self->rcnt, log));
193 }
194 
195 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)196 rtpp_socket_send_pkt_na(struct rtpp_socket *self, struct sthread_args *str,
197   struct rtpp_netaddr *daddr, struct rtp_packet *pkt,
198   struct rtpp_log *log)
199 {
200     struct rtpp_socket_priv *pvt;
201 
202     pvt = PUB2PVT(self);
203     return (rtpp_anetio_send_pkt_na(str, pvt->fd, daddr, pkt,
204       self->rcnt, log));
205 }
206 
207 static struct rtp_packet *
rtpp_socket_rtp_recv_simple(struct rtpp_socket * self,double dtime,struct sockaddr * laddr,int port)208 rtpp_socket_rtp_recv_simple(struct rtpp_socket *self, double dtime,
209   struct sockaddr *laddr, int port)
210 {
211     struct rtpp_socket_priv *pvt;
212     struct rtp_packet *packet;
213 
214     packet = rtp_packet_alloc();
215     if (packet == NULL) {
216         return NULL;
217     }
218 
219     pvt = PUB2PVT(self);
220 
221     packet->rlen = sizeof(packet->raddr);
222     packet->size = recvfrom(pvt->fd, packet->data.buf, sizeof(packet->data.buf), 0,
223       sstosa(&packet->raddr), &packet->rlen);
224 
225     if (packet->size == -1) {
226         rtp_packet_free(packet);
227         return (NULL);
228     }
229     packet->laddr = laddr;
230     packet->lport = port;
231     packet->rtime = dtime;
232 
233     return (packet);
234 }
235 
236 static struct rtp_packet *
rtpp_socket_rtp_recv(struct rtpp_socket * self,double dtime,struct sockaddr * laddr,int port)237 rtpp_socket_rtp_recv(struct rtpp_socket *self, double dtime,
238   struct sockaddr *laddr, int port)
239 {
240     struct rtpp_socket_priv *pvt;
241     struct rtp_packet *packet;
242     struct timeval rtime;
243     socklen_t llen;
244 
245     packet = rtp_packet_alloc();
246     if (packet == NULL) {
247         return NULL;
248     }
249 
250     pvt = PUB2PVT(self);
251 
252     packet->rlen = sizeof(packet->raddr);
253     llen = sizeof(packet->_laddr);
254     memset(&rtime, '\0', sizeof(rtime));
255     packet->size = recvfromto(pvt->fd, packet->data.buf, sizeof(packet->data.buf),
256       sstosa(&packet->raddr), &packet->rlen, sstosa(&packet->_laddr), &llen,
257       &rtime);
258 
259     if (packet->size == -1) {
260         rtp_packet_free(packet);
261         return (NULL);
262     }
263     if (llen > 0) {
264         packet->laddr = sstosa(&packet->_laddr);
265         packet->lport = getport(packet->laddr);
266     } else {
267         packet->laddr = laddr;
268         packet->lport = port;
269     }
270     if (!timevaliszero(&rtime)) {
271         packet->rtime = rtimeval2dtime(&rtime);
272     } else {
273         packet->rtime = dtime;
274     }
275 
276     return (packet);
277 }
278 
279 static int
rtpp_socket_getfd(struct rtpp_socket * self)280 rtpp_socket_getfd(struct rtpp_socket *self)
281 {
282     struct rtpp_socket_priv *pvt;
283 
284     pvt = PUB2PVT(self);
285     return (pvt->fd);
286 }
287