cipher-shield 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +666 -0
- package/index.js +75 -0
- package/package.json +57 -0
- package/src/core/aesEngine.js +369 -0
- package/src/core/blacklistMem.js +510 -0
- package/src/core/defconSystem.js +301 -0
- package/src/magicAuth.js +272 -0
- package/src/modules/aiScanner.js +482 -0
- package/src/modules/ghostHandler.js +279 -0
- package/src/modules/shadowHandler.js +266 -0
- package/src/shield.js +694 -0
- package/src/smartLogger.js +268 -0
- package/src/sslManager.js +345 -0
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory IP Blacklist Manager v2.1
|
|
3
|
+
*
|
|
4
|
+
* High-performance IP blacklist system with automatic expiry, cleanup,
|
|
5
|
+
* and threat intelligence tracking. Optimized for concurrent access
|
|
6
|
+
* patterns typical in web security middleware.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Automatic entry expiration to prevent memory leaks
|
|
10
|
+
* - Background cleanup to maintain performance
|
|
11
|
+
* - Threat categorization and statistics
|
|
12
|
+
* - Memory-efficient data structures
|
|
13
|
+
* - Thread-safe operations for concurrent requests
|
|
14
|
+
*
|
|
15
|
+
* @module blacklistMem
|
|
16
|
+
* @version 1.0.0
|
|
17
|
+
* @author Omindu Dissanayaka
|
|
18
|
+
* @license MIT
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const EventEmitter = require('events');
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Default configuration constants with security limits
|
|
25
|
+
* @readonly
|
|
26
|
+
*/
|
|
27
|
+
const DEFAULT_CONFIG = Object.freeze({
|
|
28
|
+
BLACKLIST_EXPIRY: 3600000,
|
|
29
|
+
CLEANUP_INTERVAL: 300000,
|
|
30
|
+
MAX_ENTRIES: 10000,
|
|
31
|
+
MAX_ENTRIES_PER_IP: 5,
|
|
32
|
+
CLEANUP_BATCH_SIZE: 100,
|
|
33
|
+
ENTRY_SIZE_LIMIT: 1000
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Blacklist entry structure
|
|
38
|
+
* @typedef {Object} BlacklistEntry
|
|
39
|
+
* @property {string} reason - Reason for blacklisting
|
|
40
|
+
* @property {number} timestamp - When the IP was blacklisted
|
|
41
|
+
* @property {number} hits - Number of times this IP triggered security
|
|
42
|
+
* @property {string} category - Threat category (e.g., 'ghost_route', 'ai_threat')
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Internal blacklist storage using Map for O(1) lookups with mutex protection
|
|
47
|
+
* @private
|
|
48
|
+
* @type {Map<string, BlacklistEntry>}
|
|
49
|
+
*/
|
|
50
|
+
const blacklist = new Map();
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Mutex for thread-safe operations
|
|
54
|
+
* @private
|
|
55
|
+
* @type {boolean}
|
|
56
|
+
*/
|
|
57
|
+
let blacklistMutex = false;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Executes operation with mutex protection to prevent race conditions
|
|
61
|
+
* @private
|
|
62
|
+
* @param {Function} operation - Operation to execute safely
|
|
63
|
+
* @returns {*} Result of the operation
|
|
64
|
+
*/
|
|
65
|
+
function withMutex(operation) {
|
|
66
|
+
while (blacklistMutex) {
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
blacklistMutex = true;
|
|
70
|
+
try {
|
|
71
|
+
return operation();
|
|
72
|
+
} finally {
|
|
73
|
+
blacklistMutex = false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Statistics tracking
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
|
+
let stats = {
|
|
82
|
+
totalAdded: 0,
|
|
83
|
+
totalExpired: 0,
|
|
84
|
+
totalRemoved: 0,
|
|
85
|
+
peakSize: 0,
|
|
86
|
+
lastCleanup: Date.now()
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Background cleanup timer
|
|
91
|
+
* @private
|
|
92
|
+
* @type {NodeJS.Timeout|null}
|
|
93
|
+
*/
|
|
94
|
+
let cleanupTimer = null;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Event emitter for monitoring blacklist events
|
|
98
|
+
* @private
|
|
99
|
+
*/
|
|
100
|
+
const events = new EventEmitter();
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Starts the automatic background cleanup process
|
|
104
|
+
*
|
|
105
|
+
* Runs periodic cleanup to remove expired entries and maintain performance.
|
|
106
|
+
* Cleanup happens in batches to avoid blocking the event loop.
|
|
107
|
+
*
|
|
108
|
+
* @private
|
|
109
|
+
* @returns {void}
|
|
110
|
+
*/
|
|
111
|
+
function startBackgroundCleanup() {
|
|
112
|
+
if (cleanupTimer) {
|
|
113
|
+
clearInterval(cleanupTimer);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
cleanupTimer = setInterval(() => {
|
|
117
|
+
const now = Date.now();
|
|
118
|
+
const expired = [];
|
|
119
|
+
let processed = 0;
|
|
120
|
+
|
|
121
|
+
for (const [ip, entry] of blacklist.entries()) {
|
|
122
|
+
if (processed >= DEFAULT_CONFIG.CLEANUP_BATCH_SIZE) break;
|
|
123
|
+
|
|
124
|
+
if (now - entry.timestamp > DEFAULT_CONFIG.BLACKLIST_EXPIRY) {
|
|
125
|
+
expired.push(ip);
|
|
126
|
+
processed++;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
expired.forEach(ip => {
|
|
131
|
+
blacklist.delete(ip);
|
|
132
|
+
stats.totalExpired++;
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
stats.lastCleanup = now;
|
|
136
|
+
stats.peakSize = Math.max(stats.peakSize, blacklist.size);
|
|
137
|
+
|
|
138
|
+
if (expired.length > 0 && process.env.NODE_ENV === 'development') {
|
|
139
|
+
console.log(`[BLACKLIST] Cleaned up ${expired.length} expired entries`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
}, DEFAULT_CONFIG.CLEANUP_INTERVAL);
|
|
143
|
+
|
|
144
|
+
cleanupTimer.unref();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Stops the background cleanup process
|
|
149
|
+
*
|
|
150
|
+
* @private
|
|
151
|
+
* @returns {void}
|
|
152
|
+
*/
|
|
153
|
+
function stopBackgroundCleanup() {
|
|
154
|
+
if (cleanupTimer) {
|
|
155
|
+
clearInterval(cleanupTimer);
|
|
156
|
+
cleanupTimer = null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Initializes the blacklist system
|
|
162
|
+
*
|
|
163
|
+
* Sets up background cleanup and prepares the system for operation.
|
|
164
|
+
* Should be called during application startup.
|
|
165
|
+
*
|
|
166
|
+
* @function initialize
|
|
167
|
+
* @returns {void}
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```javascript
|
|
171
|
+
* const blacklistMem = require('./blacklistMem');
|
|
172
|
+
* blacklistMem.initialize();
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
function initialize() {
|
|
176
|
+
blacklist.clear();
|
|
177
|
+
|
|
178
|
+
stats = {
|
|
179
|
+
totalAdded: 0,
|
|
180
|
+
totalExpired: 0,
|
|
181
|
+
totalRemoved: 0,
|
|
182
|
+
peakSize: 0,
|
|
183
|
+
lastCleanup: Date.now()
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
startBackgroundCleanup();
|
|
187
|
+
|
|
188
|
+
if (process.env.NODE_ENV === 'development') {
|
|
189
|
+
console.log('[BLACKLIST] Initialized with background cleanup');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Adds an IP address to the blacklist with reason tracking
|
|
195
|
+
*
|
|
196
|
+
* Automatically prevents duplicate entries and updates hit counts.
|
|
197
|
+
* Enforces maximum entry limits to prevent memory exhaustion.
|
|
198
|
+
*
|
|
199
|
+
* @function add
|
|
200
|
+
* @param {string} ip - IP address to blacklist
|
|
201
|
+
* @param {string} reason - Reason for blacklisting (e.g., 'ghost_route_access', 'ai_high_threat')
|
|
202
|
+
* @returns {boolean} True if IP was added/updated, false if at capacity limit
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```javascript
|
|
206
|
+
* blacklistMem.add('192.168.1.100', 'ghost_route_access');
|
|
207
|
+
* blacklistMem.add('10.0.0.1', 'ai_high_threat');
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
function add(ip, reason = 'unknown') {
|
|
211
|
+
return withMutex(() => {
|
|
212
|
+
if (!ip || typeof ip !== 'string') {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (!isValidIP(ip)) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const sanitizedReason = sanitizeReason(reason);
|
|
221
|
+
|
|
222
|
+
if (blacklist.size >= DEFAULT_CONFIG.MAX_ENTRIES) {
|
|
223
|
+
if (process.env.NODE_ENV === 'development') {
|
|
224
|
+
console.warn(`[BLACKLIST] At capacity limit (${DEFAULT_CONFIG.MAX_ENTRIES}), cannot add ${ip}`);
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const now = Date.now();
|
|
230
|
+
const existing = blacklist.get(ip);
|
|
231
|
+
|
|
232
|
+
if (existing) {
|
|
233
|
+
if (existing.hits >= DEFAULT_CONFIG.MAX_ENTRIES_PER_IP) {
|
|
234
|
+
if (process.env.NODE_ENV === 'development') {
|
|
235
|
+
console.warn(`[BLACKLIST] IP ${ip} has reached max entries (${DEFAULT_CONFIG.MAX_ENTRIES_PER_IP})`);
|
|
236
|
+
}
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
existing.hits = (existing.hits || 1) + 1;
|
|
241
|
+
existing.timestamp = now;
|
|
242
|
+
existing.lastReason = sanitizedReason;
|
|
243
|
+
} else {
|
|
244
|
+
blacklist.set(ip, {
|
|
245
|
+
reason: sanitizedReason,
|
|
246
|
+
timestamp: now,
|
|
247
|
+
hits: 1,
|
|
248
|
+
category: categorizeReason(sanitizedReason)
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
stats.totalAdded++;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
events.emit('added', { ip, reason: sanitizedReason, existing: !!existing });
|
|
255
|
+
|
|
256
|
+
return true;
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Validates IP address format
|
|
262
|
+
* @private
|
|
263
|
+
* @param {string} ip - IP address to validate
|
|
264
|
+
* @returns {boolean} True if valid IP format
|
|
265
|
+
*/
|
|
266
|
+
function isValidIP(ip) {
|
|
267
|
+
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
|
268
|
+
return ipv4Regex.test(ip) || ip === 'unknown';
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Sanitizes blacklist reason to prevent injection and limit size
|
|
273
|
+
* @private
|
|
274
|
+
* @param {string} reason - Raw reason string
|
|
275
|
+
* @returns {string} Sanitized reason
|
|
276
|
+
*/
|
|
277
|
+
function sanitizeReason(reason) {
|
|
278
|
+
if (!reason || typeof reason !== 'string') {
|
|
279
|
+
return 'unknown';
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return reason.substring(0, DEFAULT_CONFIG.ENTRY_SIZE_LIMIT)
|
|
283
|
+
.replace(/[<>'"&]/g, '')
|
|
284
|
+
.trim();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Categorizes blacklist reasons for better threat intelligence
|
|
289
|
+
*
|
|
290
|
+
* @private
|
|
291
|
+
* @param {string} reason - The blacklist reason
|
|
292
|
+
* @returns {string} Threat category
|
|
293
|
+
*/
|
|
294
|
+
function categorizeReason(reason) {
|
|
295
|
+
if (reason.includes('ghost')) return 'ghost_route';
|
|
296
|
+
if (reason.includes('ai')) return 'ai_detected';
|
|
297
|
+
if (reason.includes('aes') || reason.includes('decrypt')) return 'encryption_attack';
|
|
298
|
+
if (reason.includes('shadow')) return 'timing_attack';
|
|
299
|
+
return 'other';
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Checks if an IP address is currently blacklisted
|
|
304
|
+
*
|
|
305
|
+
* Performs automatic cleanup of expired entries during lookup.
|
|
306
|
+
* This lazy cleanup approach minimizes background processing.
|
|
307
|
+
*
|
|
308
|
+
* @function isBlacklisted
|
|
309
|
+
* @param {string} ip - IP address to check
|
|
310
|
+
* @returns {boolean} True if IP is blacklisted and not expired
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```javascript
|
|
314
|
+
* if (blacklistMem.isBlacklisted('192.168.1.100')) {
|
|
315
|
+
* // Apply shadow ban or blocking
|
|
316
|
+
* }
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
function isBlacklisted(ip) {
|
|
320
|
+
return withMutex(() => {
|
|
321
|
+
if (!ip || !blacklist.has(ip)) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const entry = blacklist.get(ip);
|
|
326
|
+
const age = Date.now() - entry.timestamp;
|
|
327
|
+
|
|
328
|
+
if (age > DEFAULT_CONFIG.BLACKLIST_EXPIRY) {
|
|
329
|
+
blacklist.delete(ip);
|
|
330
|
+
stats.totalExpired++;
|
|
331
|
+
|
|
332
|
+
if (process.env.NODE_ENV === 'development') {
|
|
333
|
+
console.log(`[BLACKLIST] Expired entry removed: ${ip}`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return true;
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Removes an IP address from the blacklist
|
|
345
|
+
*
|
|
346
|
+
* @function remove
|
|
347
|
+
* @param {string} ip - IP address to remove
|
|
348
|
+
* @returns {boolean} True if IP was removed, false if not found
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```javascript
|
|
352
|
+
* const removed = blacklistMem.remove('192.168.1.100');
|
|
353
|
+
* console.log(removed ? 'IP removed' : 'IP not found');
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
function remove(ip) {
|
|
357
|
+
const existed = blacklist.delete(ip);
|
|
358
|
+
|
|
359
|
+
if (existed) {
|
|
360
|
+
stats.totalRemoved++;
|
|
361
|
+
events.emit('removed', { ip });
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return existed;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Retrieves all current blacklist entries
|
|
369
|
+
*
|
|
370
|
+
* Returns a snapshot of current entries with metadata.
|
|
371
|
+
* Note: This creates a new array, so avoid calling frequently in hot paths.
|
|
372
|
+
*
|
|
373
|
+
* @function getAll
|
|
374
|
+
* @returns {Array<BlacklistEntry & {ip: string}>} Array of blacklist entries
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```javascript
|
|
378
|
+
* const entries = blacklistMem.getAll();
|
|
379
|
+
* console.log(`Blacklisted IPs: ${entries.length}`);
|
|
380
|
+
* ```
|
|
381
|
+
*/
|
|
382
|
+
function getAll() {
|
|
383
|
+
const result = [];
|
|
384
|
+
|
|
385
|
+
for (const [ip, entry] of blacklist.entries()) {
|
|
386
|
+
result.push({
|
|
387
|
+
ip,
|
|
388
|
+
...entry
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Retrieves detailed statistics about blacklist operations
|
|
397
|
+
*
|
|
398
|
+
* @function getStats
|
|
399
|
+
* @returns {Object} Blacklist statistics
|
|
400
|
+
* @property {number} size - Current number of entries
|
|
401
|
+
* @property {number} totalAdded - Total IPs ever added
|
|
402
|
+
* @property {number} totalExpired - Total IPs expired
|
|
403
|
+
* @property {number} totalRemoved - Total IPs manually removed
|
|
404
|
+
* @property {number} peakSize - Maximum size reached
|
|
405
|
+
* @property {number} lastCleanup - Timestamp of last cleanup
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```javascript
|
|
409
|
+
* const stats = blacklistMem.getStats();
|
|
410
|
+
* console.log(`Current size: ${stats.size}, Peak: ${stats.peakSize}`);
|
|
411
|
+
* ```
|
|
412
|
+
*/
|
|
413
|
+
function getStats() {
|
|
414
|
+
return {
|
|
415
|
+
size: blacklist.size,
|
|
416
|
+
...stats,
|
|
417
|
+
config: DEFAULT_CONFIG
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Clears all blacklist entries
|
|
423
|
+
*
|
|
424
|
+
* Emergency function to reset the blacklist. Use with caution.
|
|
425
|
+
*
|
|
426
|
+
* @function clear
|
|
427
|
+
* @returns {number} Number of entries cleared
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* ```javascript
|
|
431
|
+
* const cleared = blacklistMem.clear();
|
|
432
|
+
* console.log(`Cleared ${cleared} entries`);
|
|
433
|
+
* ```
|
|
434
|
+
*/
|
|
435
|
+
function clear() {
|
|
436
|
+
const previousSize = blacklist.size;
|
|
437
|
+
blacklist.clear();
|
|
438
|
+
|
|
439
|
+
stats.peakSize = 0;
|
|
440
|
+
stats.lastCleanup = Date.now();
|
|
441
|
+
|
|
442
|
+
events.emit('cleared', { previousSize });
|
|
443
|
+
|
|
444
|
+
if (process.env.NODE_ENV === 'development') {
|
|
445
|
+
console.log(`[BLACKLIST] Cleared ${previousSize} entries`);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return previousSize;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Gets the current number of blacklisted IPs
|
|
453
|
+
*
|
|
454
|
+
* More efficient than getAll().length for size checks.
|
|
455
|
+
*
|
|
456
|
+
* @function size
|
|
457
|
+
* @returns {number} Current blacklist size
|
|
458
|
+
*/
|
|
459
|
+
function size() {
|
|
460
|
+
return blacklist.size;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Checks if the blacklist contains a specific IP
|
|
465
|
+
*
|
|
466
|
+
* Similar to isBlacklisted() but doesn't perform expiry checks.
|
|
467
|
+
*
|
|
468
|
+
* @function has
|
|
469
|
+
* @param {string} ip - IP address to check
|
|
470
|
+
* @returns {boolean} True if IP exists in blacklist (may be expired)
|
|
471
|
+
*/
|
|
472
|
+
function has(ip) {
|
|
473
|
+
return blacklist.has(ip);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Gets detailed information about a specific blacklisted IP
|
|
478
|
+
*
|
|
479
|
+
* @function getEntry
|
|
480
|
+
* @param {string} ip - IP address to query
|
|
481
|
+
* @returns {BlacklistEntry|null} Entry details or null if not found/expired
|
|
482
|
+
*/
|
|
483
|
+
function getEntry(ip) {
|
|
484
|
+
if (!isBlacklisted(ip)) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return { ...blacklist.get(ip) };
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
initialize();
|
|
492
|
+
|
|
493
|
+
process.on('exit', stopBackgroundCleanup);
|
|
494
|
+
process.on('SIGINT', stopBackgroundCleanup);
|
|
495
|
+
process.on('SIGTERM', stopBackgroundCleanup);
|
|
496
|
+
|
|
497
|
+
module.exports = {
|
|
498
|
+
initialize,
|
|
499
|
+
add,
|
|
500
|
+
isBlacklisted,
|
|
501
|
+
remove,
|
|
502
|
+
getAll,
|
|
503
|
+
getStats,
|
|
504
|
+
clear,
|
|
505
|
+
size,
|
|
506
|
+
has,
|
|
507
|
+
getEntry,
|
|
508
|
+
events, // For advanced monitoring
|
|
509
|
+
DEFAULT_CONFIG
|
|
510
|
+
};
|