Coverage Report

Created: 2026-07-16 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rtpproxy/src/rtpp_netaddr.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016 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 <pthread.h>
31
#include <stddef.h>
32
#include <stdint.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <stdatomic.h>
36
37
#include "config.h"
38
39
#include "rtpp_types.h"
40
#include "rtpp_codeptr.h"
41
#include "rtpp_refcnt.h"
42
#include "rtpp_mallocs.h"
43
#include "rtpp_netaddr.h"
44
#include "rtpp_netaddr_fin.h"
45
#include "rtpp_network.h"
46
#include "rtpp_debug.h"
47
48
struct rtpp_netaddr_priv {
49
    struct rtpp_netaddr pub;
50
    struct sockaddr_storage sas;
51
    _Atomic(socklen_t) rlen;
52
    pthread_mutex_t lock;
53
};
54
55
static void rtpp_netaddr_set(struct rtpp_netaddr *, const struct sockaddr *, size_t);
56
static void rtpp_netaddr_dtor(struct rtpp_netaddr_priv *);
57
static void rtpp_netaddr_set(struct rtpp_netaddr *, const struct sockaddr *, size_t);
58
static int rtpp_netaddr_isempty(struct rtpp_netaddr *);
59
static int rtpp_netaddr_cmp(struct rtpp_netaddr *, const struct sockaddr *, size_t);
60
static int rtpp_netaddr_isaddrseq(struct rtpp_netaddr *, const struct sockaddr *);
61
static int rtpp_netaddr_cmphost(struct rtpp_netaddr *, const struct sockaddr *);
62
static void rtpp_netaddr_copy(struct rtpp_netaddr *, struct rtpp_netaddr *);
63
static size_t rtpp_netaddr_get(struct rtpp_netaddr *, struct sockaddr *, size_t);
64
static size_t rtpp_netaddr_sip_print(struct rtpp_netaddr *, char *, size_t,
65
  char);
66
67
DEFINE_SMETHODS(rtpp_netaddr,
68
    .set = &rtpp_netaddr_set,
69
    .isempty = &rtpp_netaddr_isempty,
70
    .cmp = &rtpp_netaddr_cmp,
71
    .isaddrseq = &rtpp_netaddr_isaddrseq,
72
    .cmphost = &rtpp_netaddr_cmphost,
73
    .copy = &rtpp_netaddr_copy,
74
    .get = &rtpp_netaddr_get,
75
    .sip_print = &rtpp_netaddr_sip_print
76
);
77
78
struct rtpp_netaddr *
79
rtpp_netaddr_ctor(void)
80
0
{
81
0
    struct rtpp_netaddr_priv *pvt;
82
83
0
    pvt = rtpp_rzmalloc(sizeof(struct rtpp_netaddr_priv), PVT_RCOFFS(pvt));
84
0
    if (pvt == NULL) {
85
0
        goto e0;
86
0
    }
87
0
    if (pthread_mutex_init(&pvt->lock, NULL) != 0) {
88
0
        goto e1;
89
0
    }
90
0
    atomic_init(&pvt->rlen, 0);
91
0
    PUBINST_FININIT(&pvt->pub, pvt, rtpp_netaddr_dtor);
92
0
    return ((&pvt->pub));
93
94
0
e1:
95
0
    RTPP_OBJ_DECREF(&(pvt->pub));
96
0
e0:
97
0
    return (NULL);
98
0
}
99
100
static void
101
rtpp_netaddr_set(struct rtpp_netaddr *self, const struct sockaddr *addr, size_t alen)
102
0
{
103
0
    struct rtpp_netaddr_priv *pvt;
104
105
0
    PUB2PVT(self, pvt);
106
0
    RTPP_DBG_ASSERT(alen <= sizeof(pvt->sas));
107
108
0
    pthread_mutex_lock(&pvt->lock);
109
0
    memcpy(&pvt->sas, addr, alen);
110
0
    atomic_store_explicit(&pvt->rlen, alen, memory_order_relaxed);
111
0
    pthread_mutex_unlock(&pvt->lock);
112
0
}
113
114
static void
115
rtpp_netaddr_dtor(struct rtpp_netaddr_priv *pvt)
116
0
{
117
118
0
    rtpp_netaddr_fin(&(pvt->pub));
119
0
    pthread_mutex_destroy(&pvt->lock);
120
0
}
121
122
static int
123
rtpp_netaddr_isempty(struct rtpp_netaddr *self)
124
0
{
125
0
    struct rtpp_netaddr_priv *pvt;
126
0
    int rval;
127
128
0
    RTPP_DBG_ASSERT(self != NULL);
129
0
    PUB2PVT(self, pvt);
130
0
    rval = (atomic_load_explicit(&pvt->rlen, memory_order_relaxed) == 0);
131
0
    return (rval);
132
0
}
133
134
static int
135
rtpp_netaddr_cmp(struct rtpp_netaddr *self, const struct sockaddr *sap, size_t salen)
136
0
{
137
0
    struct rtpp_netaddr_priv *pvt;
138
0
    int rval;
139
0
    socklen_t rlen;
140
141
0
    PUB2PVT(self, pvt);
142
0
    RTPP_DBG_ASSERT(salen <= sizeof(pvt->sas));
143
0
    pthread_mutex_lock(&pvt->lock);
144
0
    rlen = atomic_load_explicit(&pvt->rlen, memory_order_relaxed);
145
0
    if (salen != rlen) {
146
0
        rval = -1;
147
0
        goto unlock_and_return;
148
0
    }
149
0
    rval = memcmp(&pvt->sas, sap, salen);
150
0
unlock_and_return:
151
0
    pthread_mutex_unlock(&pvt->lock);
152
0
    return (rval);
153
0
}
154
155
static int
156
rtpp_netaddr_isaddrseq(struct rtpp_netaddr *self, const struct sockaddr *sap)
157
0
{
158
0
    struct rtpp_netaddr_priv *pvt;
159
0
    int rval;
160
0
    MAYBE_UNUSED socklen_t rlen;
161
162
0
    PUB2PVT(self, pvt);
163
0
    pthread_mutex_lock(&pvt->lock);
164
0
    rlen = atomic_load_explicit(&pvt->rlen, memory_order_relaxed);
165
0
    RTPP_DBG_ASSERT(rlen > 0);
166
0
    rval = isaddrseq(sstosa(&pvt->sas), sap);
167
0
    pthread_mutex_unlock(&pvt->lock);
168
0
    return (rval);
169
0
}
170
171
static int
172
rtpp_netaddr_cmphost(struct rtpp_netaddr *self, const struct sockaddr *sap)
173
0
{
174
0
    struct rtpp_netaddr_priv *pvt;
175
0
    int rval;
176
0
    MAYBE_UNUSED socklen_t rlen;
177
178
0
    PUB2PVT(self, pvt);
179
0
    pthread_mutex_lock(&pvt->lock);
180
0
    rlen = atomic_load_explicit(&pvt->rlen, memory_order_relaxed);
181
0
    RTPP_DBG_ASSERT(rlen > 0);
182
0
    rval = ishostseq(sstosa(&pvt->sas), sap);
183
0
    pthread_mutex_unlock(&pvt->lock);
184
0
    return (rval);
185
0
}
186
187
static void
188
rtpp_netaddr_copy(struct rtpp_netaddr *self, struct rtpp_netaddr *other)
189
0
{
190
0
    struct sockaddr_storage tmp;
191
0
    socklen_t rlen;
192
193
0
    rlen = CALL_SMETHOD(other, get, sstosa(&tmp), sizeof(tmp));
194
0
    rtpp_netaddr_set(self, sstosa(&tmp), rlen);
195
0
}
196
197
static size_t
198
rtpp_netaddr_get(struct rtpp_netaddr *self, struct sockaddr *sap, size_t salen)
199
0
{
200
0
    struct rtpp_netaddr_priv *pvt;
201
0
    socklen_t rlen;
202
203
0
    PUB2PVT(self, pvt);
204
0
    pthread_mutex_lock(&pvt->lock);
205
0
    rlen = atomic_load_explicit(&pvt->rlen, memory_order_relaxed);
206
0
    RTPP_DBG_ASSERT((salen >= rlen) && (rlen > 0));
207
0
    memcpy(sap, &pvt->sas, rlen);
208
0
    pthread_mutex_unlock(&pvt->lock);
209
0
    return (rlen);
210
0
}
211
212
static size_t
213
rtpp_netaddr_sip_print(struct rtpp_netaddr *self, char *buf, size_t blen,
214
  char portsep)
215
0
{
216
0
    char *rval;
217
0
    struct rtpp_netaddr_priv *pvt;
218
0
    MAYBE_UNUSED socklen_t rlen;
219
220
0
    PUB2PVT(self, pvt);
221
0
    pthread_mutex_lock(&pvt->lock);
222
0
    rlen = atomic_load_explicit(&pvt->rlen, memory_order_relaxed);
223
0
    RTPP_DBG_ASSERT(rlen > 0);
224
0
    rval = addrport2char_r(sstosa(&pvt->sas), buf, blen, portsep);
225
0
    pthread_mutex_unlock(&pvt->lock);
226
0
    RTPP_DBG_ASSERT(rval != NULL);
227
0
    return (strlen(rval));
228
0
}