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