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