1 /*
2 * Copyright (c) 2014 Sippy Software, Inc., http://www.sippysoft.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <assert.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "rtpp_types.h"
36 #include "rtpp_refcnt.h"
37 #include "rtpp_log_obj.h"
38 #include "rtp.h"
39 #include "rtp_packet.h"
40 #include "rtpp_network.h"
41 #include "rtpp_wi.h"
42 #include "rtpp_wi_private.h"
43 #include "rtpp_netaddr.h"
44
45 struct rtpp_wi_sendto {
46 struct rtpp_wi wi;
47 struct sockaddr_storage to;
48 char msg[0];
49 };
50
51 struct rtpp_wi *
rtpp_wi_malloc(int sock,const void * msg,size_t msg_len,int flags,const struct sockaddr * sendto,size_t tolen)52 rtpp_wi_malloc(int sock, const void *msg, size_t msg_len, int flags,
53 const struct sockaddr *sendto, size_t tolen)
54 {
55 struct rtpp_wi_sendto *wis;
56
57 wis = malloc(sizeof(struct rtpp_wi_sendto) + msg_len);
58 if (wis == NULL) {
59 return (NULL);
60 }
61 memset(wis, '\0', sizeof(struct rtpp_wi_sendto));
62 wis->wi.free_ptr = &(wis->wi);
63 wis->wi.wi_type = RTPP_WI_TYPE_OPKT;
64 wis->wi.sock = sock;
65 wis->wi.flags = flags;
66 wis->wi.msg = &(wis->msg);
67 wis->wi.sendto = sstosa(&(wis->to));
68 wis->wi.msg_len = msg_len;
69 wis->wi.nsend = 1;
70 memcpy(wis->msg, msg, msg_len);
71 wis->wi.tolen = tolen;
72 memcpy(&(wis->to), sendto, tolen);
73 return (&(wis->wi));
74 }
75
76 struct rtpp_wi *
rtpp_wi_malloc_pkt(int sock,struct rtp_packet * pkt,const struct sockaddr * sendto,size_t tolen,int nsend,struct rtpp_refcnt * sock_rcnt)77 rtpp_wi_malloc_pkt(int sock, struct rtp_packet *pkt,
78 const struct sockaddr *sendto, size_t tolen, int nsend,
79 struct rtpp_refcnt *sock_rcnt)
80 {
81 struct rtpp_wi *wi;
82
83 wi = pkt->wi;
84 wi->free_ptr = (struct rtpp_wi *)pkt;
85 wi->wi_type = RTPP_WI_TYPE_OPKT;
86 wi->sock = sock;
87 if (sock_rcnt != NULL) {
88 CALL_SMETHOD(sock_rcnt, incref);
89 }
90 wi->sock_rcnt = sock_rcnt;
91 wi->flags = 0;
92 wi->msg = pkt->data.buf;
93 wi->msg_len = pkt->size;
94 wi->sendto = sstosa(&pkt->raddr);
95 wi->tolen = tolen;
96 memcpy(wi->sendto, sendto, tolen);
97 wi->nsend = nsend;
98 return (wi);
99 }
100
101 struct rtpp_wi *
rtpp_wi_malloc_pkt_na(int sock,struct rtp_packet * pkt,struct rtpp_netaddr * sendto,int nsend,struct rtpp_refcnt * sock_rcnt)102 rtpp_wi_malloc_pkt_na(int sock, struct rtp_packet *pkt,
103 struct rtpp_netaddr *sendto, int nsend,
104 struct rtpp_refcnt *sock_rcnt)
105 {
106 struct rtpp_wi *wi;
107
108 wi = pkt->wi;
109 wi->free_ptr = (struct rtpp_wi *)pkt;
110 wi->wi_type = RTPP_WI_TYPE_OPKT;
111 wi->sock = sock;
112 if (sock_rcnt != NULL) {
113 CALL_SMETHOD(sock_rcnt, incref);
114 }
115 wi->sock_rcnt = sock_rcnt;
116 wi->flags = 0;
117 wi->msg = pkt->data.buf;
118 wi->msg_len = pkt->size;
119 wi->sendto = sstosa(&pkt->raddr);
120 wi->tolen = CALL_SMETHOD(sendto, get, wi->sendto, sizeof(pkt->raddr));
121 wi->nsend = nsend;
122 return (wi);
123 }
124
125 struct rtpp_wi *
126 #if !defined(RTPP_CHECK_LEAKS)
rtpp_wi_malloc_sgnl(int signum,const void * data,size_t datalen)127 rtpp_wi_malloc_sgnl(int signum, const void *data, size_t datalen)
128 #else
129 rtpp_wi_malloc_sgnl_memdeb(const char *fname, int linen, const char *funcn, int signum, const void *data, size_t datalen)
130 #endif
131 {
132 struct rtpp_wi *wi;
133 #if !defined(RTPP_CHECK_LEAKS)
134 wi = malloc(sizeof(struct rtpp_wi) + datalen);
135 #else
136 wi = rtpp_memdeb_malloc(sizeof(struct rtpp_wi) + datalen, _rtpproxy_memdeb, fname, linen, funcn);
137 #endif
138 if (wi == NULL) {
139 return (NULL);
140 }
141 memset(wi, '\0', sizeof(struct rtpp_wi));
142 wi->free_ptr = wi;
143 wi->wi_type = RTPP_WI_TYPE_SGNL;
144 wi->flags = signum;
145 if (datalen > 0) {
146 wi->msg = wi->data;
147 wi->msg_len = datalen;
148 memcpy(wi->data, data, datalen);
149 }
150 return (wi);
151 }
152
153 struct rtpp_wi *
rtpp_wi_malloc_apis(const char * apiname,void * data,size_t datalen)154 rtpp_wi_malloc_apis(const char *apiname, void *data, size_t datalen)
155 {
156 struct rtpp_wi *wi;
157
158 wi = malloc(sizeof(struct rtpp_wi) + datalen);
159 if (wi == NULL) {
160 return (NULL);
161 }
162 memset(wi, '\0', sizeof(struct rtpp_wi));
163 wi->free_ptr = wi;
164 wi->wi_type = RTPP_WI_TYPE_API_STR;
165 wi->sendto = (void *)apiname;
166 if (datalen > 0) {
167 wi->msg = wi->data;
168 wi->msg_len = datalen;
169 memcpy(wi->data, data, datalen);
170 }
171 return (wi);
172 }
173
174 struct rtpp_wi *
rtpp_wi_malloc_data(void * dataptr,size_t datalen)175 rtpp_wi_malloc_data(void *dataptr, size_t datalen)
176 {
177 struct rtpp_wi *wi;
178
179 wi = malloc(sizeof(struct rtpp_wi) + datalen);
180 if (wi == NULL) {
181 return (NULL);
182 }
183 memset(wi, '\0', sizeof(struct rtpp_wi));
184 wi->free_ptr = wi;
185 wi->wi_type = RTPP_WI_TYPE_DATA;
186 if (datalen > 0) {
187 wi->msg = wi->data;
188 wi->msg_len = datalen;
189 memcpy(wi->data, dataptr, datalen);
190 }
191 return (wi);
192 }
193
194 struct rtpp_wi *
rtpp_wi_malloc_udata(void ** dataptr,size_t datalen)195 rtpp_wi_malloc_udata(void **dataptr, size_t datalen)
196 {
197 struct rtpp_wi *wi;
198
199 wi = malloc(sizeof(struct rtpp_wi) + datalen);
200 if (wi == NULL) {
201 return (NULL);
202 }
203 memset(wi, '\0', sizeof(struct rtpp_wi));
204 wi->free_ptr = wi;
205 wi->wi_type = RTPP_WI_TYPE_DATA;
206 if (datalen > 0) {
207 wi->msg = wi->data;
208 wi->msg_len = datalen;
209 *dataptr = wi->data;
210 }
211 return (wi);
212 }
213
214 enum rtpp_wi_type
rtpp_wi_get_type(struct rtpp_wi * wi)215 rtpp_wi_get_type(struct rtpp_wi *wi)
216 {
217
218 return (wi->wi_type);
219 }
220
221 void *
rtpp_wi_sgnl_get_data(struct rtpp_wi * wi,size_t * datalen)222 rtpp_wi_sgnl_get_data(struct rtpp_wi *wi, size_t *datalen)
223 {
224
225 assert(wi->wi_type == RTPP_WI_TYPE_SGNL);
226 if (datalen != NULL) {
227 *datalen = wi->msg_len;
228 }
229 return(wi->msg);
230 }
231
232 int
rtpp_wi_sgnl_get_signum(struct rtpp_wi * wi)233 rtpp_wi_sgnl_get_signum(struct rtpp_wi *wi)
234 {
235
236 assert(wi->wi_type == RTPP_WI_TYPE_SGNL);
237 return (wi->flags);
238 }
239
240 void *
rtpp_wi_data_get_ptr(struct rtpp_wi * wi,size_t min_len,size_t max_len)241 rtpp_wi_data_get_ptr(struct rtpp_wi *wi, size_t min_len, size_t max_len)
242 {
243
244 assert(wi->wi_type == RTPP_WI_TYPE_DATA);
245 assert(wi->msg_len >= min_len);
246 assert(max_len == 0 || wi->msg_len <= max_len);
247
248 return(wi->msg);
249 }
250
251 const char *
rtpp_wi_apis_getnamearg(struct rtpp_wi * wi,void ** datap,size_t datalen)252 rtpp_wi_apis_getnamearg(struct rtpp_wi *wi, void **datap, size_t datalen)
253 {
254
255 assert(wi->wi_type == RTPP_WI_TYPE_API_STR);
256 assert(wi->msg_len == datalen);
257 if (datap != NULL && datalen > 0) {
258 memcpy(datap, wi->data, datalen);
259 }
260 return ((const char *)wi->sendto);
261 }
262
263 void
rtpp_wi_free(struct rtpp_wi * wi)264 rtpp_wi_free(struct rtpp_wi *wi)
265 {
266
267 if (wi->sock_rcnt != NULL) {
268 CALL_SMETHOD(wi->sock_rcnt, decref);
269 }
270 if (wi->log != NULL) {
271 CALL_SMETHOD(wi->log->rcnt, decref);
272 }
273 free(wi->free_ptr);
274 }
275