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 <pthread.h>
30 #include <stddef.h>
31 #include <stdlib.h>
32
33 #include "rtpp_types.h"
34 #include "rtpp_mallocs.h"
35 #include "rtpp_refcnt.h"
36 #include "rtpp_ttl.h"
37 #include "rtpp_ttl_fin.h"
38
39 struct rtpp_ttl_priv {
40 struct rtpp_ttl pub;
41 int max_ttl;
42 int ttl;
43 pthread_mutex_t lock;
44 };
45
46 static void rtpp_ttl_dtor(struct rtpp_ttl_priv *);
47 static void rtpp_ttl_reset(struct rtpp_ttl *);
48 static void rtpp_ttl_reset_with(struct rtpp_ttl *, int);
49 static int rtpp_ttl_get_remaining(struct rtpp_ttl *);
50 static int rtpp_ttl_decr(struct rtpp_ttl *);
51
52 #define PUB2PVT(pubp) \
53 ((struct rtpp_ttl_priv *)((char *)(pubp) - offsetof(struct rtpp_ttl_priv, pub)))
54
55 struct rtpp_ttl *
rtpp_ttl_ctor(int max_ttl)56 rtpp_ttl_ctor(int max_ttl)
57 {
58 struct rtpp_ttl_priv *pvt;
59 struct rtpp_refcnt *rcnt;
60
61 pvt = rtpp_rzmalloc(sizeof(struct rtpp_ttl_priv), &rcnt);
62 if (pvt == NULL) {
63 goto e0;
64 }
65 pvt->pub.rcnt = rcnt;
66 if (pthread_mutex_init(&pvt->lock, NULL) != 0) {
67 goto e1;
68 }
69 pvt->pub.reset = &rtpp_ttl_reset;
70 pvt->pub.reset_with = &rtpp_ttl_reset_with;
71 pvt->pub.get_remaining = &rtpp_ttl_get_remaining;
72 pvt->pub.decr = &rtpp_ttl_decr;
73 pvt->ttl = pvt->max_ttl = max_ttl;
74 CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_ttl_dtor,
75 pvt);
76 return ((&pvt->pub));
77
78 e1:
79 CALL_SMETHOD(pvt->pub.rcnt, decref);
80 free(pvt);
81 e0:
82 return (NULL);
83 }
84
85 static void
rtpp_ttl_dtor(struct rtpp_ttl_priv * pvt)86 rtpp_ttl_dtor(struct rtpp_ttl_priv *pvt)
87 {
88
89 rtpp_ttl_fin(&(pvt->pub));
90 pthread_mutex_destroy(&pvt->lock);
91 free(pvt);
92 }
93
94 static void
rtpp_ttl_reset(struct rtpp_ttl * self)95 rtpp_ttl_reset(struct rtpp_ttl *self)
96 {
97 struct rtpp_ttl_priv *pvt;
98
99 pvt = PUB2PVT(self);
100 pthread_mutex_lock(&pvt->lock);
101 pvt->ttl = pvt->max_ttl;
102 pthread_mutex_unlock(&pvt->lock);
103 }
104
105 static void
rtpp_ttl_reset_with(struct rtpp_ttl * self,int max_ttl)106 rtpp_ttl_reset_with(struct rtpp_ttl *self, int max_ttl)
107 {
108 struct rtpp_ttl_priv *pvt;
109
110 pvt = PUB2PVT(self);
111 pthread_mutex_lock(&pvt->lock);
112 pvt->ttl = max_ttl;
113 pvt->max_ttl = max_ttl;
114 pthread_mutex_unlock(&pvt->lock);
115 }
116
117 static int
rtpp_ttl_get_remaining(struct rtpp_ttl * self)118 rtpp_ttl_get_remaining(struct rtpp_ttl *self)
119 {
120 struct rtpp_ttl_priv *pvt;
121 int rval;
122
123 pvt = PUB2PVT(self);
124 pthread_mutex_lock(&pvt->lock);
125 rval = pvt->ttl;
126 pthread_mutex_unlock(&pvt->lock);
127 return (rval);
128 }
129
130 static int
rtpp_ttl_decr(struct rtpp_ttl * self)131 rtpp_ttl_decr(struct rtpp_ttl *self)
132 {
133 struct rtpp_ttl_priv *pvt;
134 int rval;
135
136 pvt = PUB2PVT(self);
137 pthread_mutex_lock(&pvt->lock);
138 rval = pvt->ttl;
139 if (pvt->ttl > 0)
140 pvt->ttl--;
141 pthread_mutex_unlock(&pvt->lock);
142 return (rval);
143 }
144