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