Coverage Report

Created: 2024-01-13 07:07

/src/ndpi/src/lib/ndpi_bitmap64.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * ndpi_bitmap64.c
3
 *
4
 * Copyright (C) 2011-23 - ntop.org and contributors
5
 *
6
 * nDPI is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * nDPI is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 */
20
21
22
#include <stdlib.h>
23
#include <errno.h>
24
#include <math.h>
25
#include <sys/types.h>
26
27
#define NDPI_CURRENT_PROTO       NDPI_PROTOCOL_UNKNOWN
28
29
#include "ndpi_config.h"
30
#include "ndpi_api.h"
31
#include "third_party/include/binaryfusefilter.h"
32
33
48.2k
#define NDPI_BITMAP64_REALLOC_SIZE  4096
34
35
// #define PRINT_DUPLICATED_HASHS
36
37
typedef struct {
38
  u_int32_t num_allocated_entries, num_used_entries;
39
  u_int64_t *entries;
40
  bool is_compressed;
41
  binary_fuse16_t bitmap;
42
} ndpi_bitmap64_t;
43
44
/* ********************************************************** */
45
46
51.3k
ndpi_bitmap64* ndpi_bitmap64_alloc() {
47
51.3k
  ndpi_bitmap64_t *rc = (ndpi_bitmap64_t*)ndpi_malloc(sizeof(ndpi_bitmap64_t));
48
49
51.3k
  if(!rc) return(rc);
50
51
48.2k
  rc->num_allocated_entries = NDPI_BITMAP64_REALLOC_SIZE, rc->num_used_entries = 0;
52
48.2k
  if((rc->entries = (u_int64_t*)ndpi_calloc(rc->num_allocated_entries, sizeof(u_int64_t))) == NULL) {
53
3.02k
    ndpi_free(rc);
54
3.02k
    return(NULL);
55
3.02k
  }
56
57
45.2k
  rc->is_compressed = false;
58
59
45.2k
  return((ndpi_bitmap64*)rc);
60
48.2k
}
61
62
/* ********************************************************** */
63
64
363k
static int ndpi_bitmap64_entry_compare(const void *_a, const void *_b) {
65
363k
  u_int64_t *a = (u_int64_t*)_a, *b = (u_int64_t*)_b;
66
67
363k
  if(*a < *b) return -1;
68
168k
  else if(*a > *b) return 1;
69
0
  else return 0;
70
363k
}
71
72
/* ********************************************************** */
73
74
/* Sort and compact memory before searching */
75
44.1k
bool ndpi_bitmap64_compress(ndpi_bitmap64 *_b) {
76
44.1k
  ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b;
77
44.1k
  u_int32_t i;
78
79
44.1k
  if(!b)
80
0
    return(false);
81
82
44.1k
  if(b->is_compressed)
83
0
    return(true);
84
85
44.1k
  if(b->num_used_entries > 0) {
86
44.1k
    if(b->num_used_entries > 1)
87
23.4k
      qsort(b->entries, b->num_used_entries,
88
23.4k
      sizeof(u_int64_t),
89
23.4k
      ndpi_bitmap64_entry_compare);
90
91
    /* Now remove duplicates */
92
44.1k
    u_int64_t old_value = b->entries[0], new_len = 1;
93
94
197k
    for(i=1; i<b->num_used_entries; i++) {
95
153k
      if(b->entries[i] != old_value) {
96
153k
  if(new_len != i)
97
0
    memcpy(&b->entries[new_len], &b->entries[i], sizeof(u_int64_t));
98
99
153k
  old_value = b->entries[i];
100
153k
  new_len++;
101
153k
      } else {
102
#ifdef PRINT_DUPLICATED_HASHS
103
  printf("Skipping duplicate hash %lluu [id: %u/%u]\n",
104
         b->entries[i].value, i, b->num_used_entries);
105
#endif
106
0
      }
107
153k
    }
108
109
44.1k
    b->num_used_entries = b->num_allocated_entries = new_len;
110
44.1k
  }
111
112
44.1k
  if(binary_fuse16_allocate(b->num_used_entries, &b->bitmap)) {
113
41.4k
    if(binary_fuse16_populate(b->entries, b->num_used_entries, &b->bitmap)) {
114
28.3k
      ndpi_free(b->entries), b->num_used_entries = b->num_allocated_entries = 0;
115
28.3k
      b->entries = NULL;
116
28.3k
    } else {
117
13.1k
      binary_fuse16_free(&b->bitmap);
118
13.1k
      return(false);
119
13.1k
    }
120
41.4k
  } else {
121
2.63k
    return(false);
122
2.63k
  }
123
124
28.3k
  b->is_compressed = true;
125
126
28.3k
  return(true);
127
44.1k
}
128
129
/* ********************************************************** */
130
131
201k
bool ndpi_bitmap64_set(ndpi_bitmap64 *_b, u_int64_t value) {
132
201k
  ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b;
133
134
201k
  if(!b)
135
6.11k
    return(false);
136
137
195k
  if(b->is_compressed) {
138
    /*
139
      We need to discard the filter and start over as this
140
      datastructure is immutable
141
    */
142
143
0
    binary_fuse16_free(&b->bitmap);
144
    /* No need to call b->is_compressed = false; as it will be set below */
145
0
  }
146
147
195k
  if(b->num_used_entries >= b->num_allocated_entries) {
148
0
    u_int64_t *rc;
149
0
    u_int32_t new_len = b->num_allocated_entries + NDPI_BITMAP64_REALLOC_SIZE;
150
151
0
    rc = (u_int64_t*)ndpi_realloc(b->entries,
152
0
          sizeof(u_int64_t)*b->num_allocated_entries,
153
0
          sizeof(u_int64_t)*new_len);
154
0
    if(rc == NULL) {
155
0
      b->is_compressed = false;
156
0
      return(false);
157
0
    }
158
159
0
    b->entries = rc, b->num_allocated_entries = new_len;
160
0
  }
161
162
195k
  b->entries[b->num_used_entries] = value;
163
195k
  b->num_used_entries++, b->is_compressed = false;
164
165
195k
  return(true);
166
195k
}
167
168
/* ********************************************************** */
169
170
8.76k
bool ndpi_bitmap64_isset(ndpi_bitmap64 *_b, u_int64_t value) {
171
8.76k
  ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b;
172
173
8.76k
  if(!b)
174
0
    return(false);
175
176
8.76k
  if(!b->is_compressed) ndpi_bitmap64_compress(b);
177
8.76k
  if(!b->is_compressed)
178
327
    return(false);
179
180
8.43k
  return(binary_fuse16_contain(value, &b->bitmap));
181
8.76k
}
182
183
/* ********************************************************** */
184
185
45.2k
void ndpi_bitmap64_free(ndpi_bitmap64 *_b) {
186
45.2k
  ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b;
187
188
45.2k
  if(!b)
189
0
    return;
190
191
45.2k
  if(b->entries)        ndpi_free(b->entries);
192
193
45.2k
  if(b->is_compressed)
194
28.3k
    binary_fuse16_free(&b->bitmap);
195
196
45.2k
  ndpi_free(b);
197
45.2k
}
198
199
/* ********************************************************** */
200
201
0
u_int32_t ndpi_bitmap64_size(ndpi_bitmap64 *_b) {
202
0
  ndpi_bitmap64_t *b = (ndpi_bitmap64_t*)_b;
203
204
0
  if(!b)
205
0
    return(0);
206
207
0
  return(sizeof(ndpi_bitmap64) + binary_fuse16_size_in_bytes(&b->bitmap));
208
0
}