forked from willamowius/gnugk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gkacct.h
462 lines (401 loc) · 13.3 KB
/
gkacct.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
/*
* gkacct.h
*
* Accounting modules for GNU Gatekeeper. Provides generic
* support for accounting to the gatekeeper.
*
* Copyright (c) 2003, Quarcom FHU, Michal Zygmuntowicz
* Copyright (c) 2005-2018, Jan Willamowius
*
* This work is published under the GNU Public License version 2 (GPLv2)
* see file COPYING for details.
* We also explicitly grant the right to link this code
* with the OpenH323/H323Plus and OpenSSL library.
*
*/
#ifndef __GKACCT_H
#define __GKACCT_H "@(#) $Id$"
#include <list>
#include "name.h"
#include "factory.h"
#include "RasTbl.h"
/** Module for logging accounting events
generated by the gatekeeper.
*/
class GkAcctLogger : public NamedObject
{
public:
/// Processing type for this module
enum Control
{
/// if cannot log an accounting event
/// silently ignore the module and process remaining acct modules
Optional,
/// if cannot log an accounting event do not allow further
/// call processing (e.g. call should not be connected, etc.)
/// always process remaining acct modules
Required,
/// if cannot log an accounting event do not allow further
/// call processing (e.g. call should not be connected, etc.)
/// - always process remaining acct modules,
/// if the event has been logged, do not process remaining acct modules
/// and allow further call processing
Sufficient,
/// if cannot log an accounting event ignore the module
/// and process remaining acct modules,
/// if the event has been logged, do not process remaining acct modules
/// and allow further call processing
Alternative
};
/// status of the acct event processing
enum Status
{
Ok = 1, /// acct event has been logged
Fail = -1, /// acct event has not been logged (failure)
Next = 0 /// acct event has not been logged because the event type
/// is not supported/not configured for this module
};
/// accounting event types
enum AcctEvent
{
AcctStart = 0x0001, /// log call start
AcctStop = 0x0002, /// log call stop (disconnect)
AcctUpdate = 0x0004, /// /// call progress update
AcctOn = 0x0008, /// accounting enabled (GK start)
AcctOff = 0x0010, /// accounting disabled (GK stop)
AcctConnect = 0x0020, /// call connected
AcctAlert = 0x0040, /// call alerting
AcctRegister = 0x0100, /// endpoint registered
AcctUnregister = 0x0200, /// endpoint unregistered
AcctReject = 0x0400, /// rejected calls (ARJ)
AcctMediaFail = 0x0800, /// media failure
AcctAll = -1,
AcctNone = 0
};
/// Construct new accounting logger object.
GkAcctLogger(
/// module name (should be unique among different module types)
const char* moduleName,
/// name for a config section with logger settings
/// pass NULL to use the moduleName as the section name
const char* cfgSecName = NULL
);
virtual ~GkAcctLogger();
/** @return
Control flag determining processing behavior for this module
(optional,sufficient,required).
*/
Control GetControlFlag() const { return m_controlFlag; }
/** @return
Flags signaling which accounting events (see #AcctEvent enum#)
should be logged. The flags are ORed.
*/
int GetEnabledEvents() const { return m_enabledEvents; }
/** @return
All events supported by the module ORed together.
*/
int GetSupportedEvents() const { return m_supportedEvents; }
/** Log an accounting event with this logger.
@return
Status of this logging operation (see #Status enum#)
*/
virtual Status Log(
AcctEvent evt, /// accounting event to log
const callptr & call /// a call associated with the event (if any)
);
/** Log an accounting event with this logger.
@return
Status of this logging operation (see #Status enum#)
*/
virtual Status Log(
AcctEvent evt, /// accounting event to log
const endptr & ep /// endpoint associated with the event
);
/** Get human readable information about current module state
that can be displayed on the status port interface.
@return
A string (may contain multiple lines) with module information.
Each line (including the last one) has to be ended with \r\n.
*/
virtual PString GetInfo();
protected:
/** @return
A pointer to configuration settings for this logger.
*/
PConfig* GetConfig() const { return m_config; }
/** @return
A name of the config file section with settings for the logger module.
*/
const PString & GetConfigSectionName() const { return m_configSectionName; }
/** Set which accounting events should be processed by this module.
It is important to call this from derived module constructor
to set which accounting events are recognized by this module.
*/
void SetSupportedEvents(const int events) { m_supportedEvents = events; }
/** Fill the map with accounting parameters for calls (name => value associations).
*/
virtual void SetupAcctParams(
/// accounting parameters (name => value) associations
std::map<PString, PString> & params,
/// call (if any) associated with an accounting event being logged
const callptr & call,
/// timestamp formatting string
const PString & timestampFormat
) const;
/** Fill the map with accounting parameters for endpoints (name => value associations).
*/
virtual void SetupAcctEndpointParams(
/// accounting parameters (name => value) associations
std::map<PString, PString> & params,
/// endpoint associated with an accounting event being logged
const endptr & ep,
/// timestamp formatting string
const PString & timestampFormat
) const;
/** Fill the map with accounting parameters for On/Off events (name => value associations).
*/
virtual void SetupAcctParams(
/// accounting parameters (name => value) associations
std::map<PString, PString> & params
) const;
/** Replace accounting parameters placeholders (%a, %{Name}, ...) with
actual values.
@return
New string with all parameters replaced.
*/
PString ReplaceAcctParams(
/// parametrized accounting string
const PString & cdrStr,
/// parameter values
const std::map<PString, PString> & params
) const;
/** Escape accounting parameters; called for each value before inserting.
Subclass this for all accounting modules that need escaping.
Default implementation doesn't modify the parameter.
@return
escaped string
*/
virtual PString EscapeAcctParam(const PString & param) const;
/** Read a list of events to be logged (ORed #AccEvent enum# constants)
from the passed tokens. Override this method if new event types
are being introduced in derived loggers, then invoked it from constructor.
@return
Resulting event mask.
*/
int GetEvents(
const PStringArray & tokens /// event names (start from index 1)
) const;
/** @return
A string that can be used to identify an account name
associated with the call.
*/
virtual PString GetUsername(
/// call (if any) associated with the RAS message
const callptr & call
) const;
/** @return
A string that can be used to identify a calling number.
*/
virtual PString GetCallingStationId(
/// call associated with the accounting event
const callptr & call
) const;
/** @return
A string that can be used to identify a calling number.
*/
virtual PString GetCalledStationId(
/// call associated with the accounting event
const callptr & call
) const;
/// @return A number actually dialed by the user (before rewrite)
virtual PString GetDialedNumber(
/// call associated with the accounting event
const callptr & call
) const;
private:
GkAcctLogger();
GkAcctLogger(const GkAcctLogger &);
GkAcctLogger & operator=(const GkAcctLogger &);
private:
/// processing behavior (see #Control enum#)
Control m_controlFlag;
/// status for "default" logger - accept (Ok) or reject (Fail)
Status m_defaultStatus;
/// ORed #AcctEvent enum# constants - define which events are logged
int m_enabledEvents;
/// all supported (recognized) event types ORed together
int m_supportedEvents;
/// module settings
PConfig* m_config;
/// name for the config section with logger settings
PString m_configSectionName;
};
/**
Plain text file accounting module for GNU Gatekeeper.
Based on source source code from Tamas Jalsovszky
Copyright (c) 2003, eWorld Com, Tamas Jalsovszky
*/
class GkTimer;
class FileAcct : public GkAcctLogger
{
public:
enum Constants {
/// events recognized by this module
FileAcctEvents = AcctStop
};
enum RotationIntervals {
Hourly,
Daily,
Weekly,
Monthly,
RotationIntervalMax
};
/// Create GkAcctLogger for plain text file accounting
FileAcct(
/// name from Gatekeeper::Acct section
const char* moduleName,
/// name for a config section with logger settings
/// pass NULL to use the moduleName as the section name
const char* cfgSecName = NULL
);
/// Destroy the accounting logger
virtual ~FileAcct();
/// override from GkAcctLogger
virtual Status Log(AcctEvent evt, const callptr & call);
/** Rotate the detail file, saving old file contents to a different
file and starting with a new one. This is a callback function
called when the rotation timer expires.
*/
void RotateOnTimer(
GkTimer* timer /// timer object that triggered rotation
);
protected:
/** Called to get CDR text to be stored in the CDR file.
Can be overridden to provide custom CDR text.
@return
true if the text is available, false otherwise
*/
virtual bool GetCDRText(
PString & cdrString, /// PString for the resulting CDR line
AcctEvent evt, /// accounting event being processed
const callptr & call /// call associated with this request (if any)
);
/** @return
True if the CDR file should be rotated.
*/
virtual bool IsRotationNeeded();
/** @return
Pointer to the opened file or NULL, if the operation failed.
*/
virtual PTextFile* OpenCDRFile(
const PFilePath & fn /// name of the file to open
);
/** Rotate the detail file, saving old file contents to a different
file and starting with a new one.
*/
void Rotate();
private:
/// parse rotation interval from the config
void GetRotateInterval(
PConfig & cfg, /// the config
const PString& section /// name of the config section to check
);
/* No default constructor allowed */
FileAcct();
/* No copy constructor allowed */
FileAcct(const FileAcct &);
/* No operator= allowed */
FileAcct & operator=(const FileAcct &);
private:
/// Plain text file name
PString m_cdrFilename;
/// File object
PTextFile* m_cdrFile;
/// for mutual file access
PMutex m_cdrFileMutex;
/// rotate file after the specified amount of lines is reached (if > 0)
long m_rotateLines;
/// rotate file after the specified file size is reached (if > 0)
long m_rotateSize;
/// rotate file after the specified period of time (if >= 0)
int m_rotateInterval;
/// a minute when the interval based rotation should occur
int m_rotateMinute;
/// an hour when the interval based rotation should occur
int m_rotateHour;
/// day of the month (or of the week) for the interval based rotation
int m_rotateDay;
/// timer for rotation events
GkTimer* m_rotateTimer;
/// number of CDRs written (if rotation per number of lines is enabled)
long m_cdrLines;
/// if true, ignore CDR string and write CDRs in a standard format
bool m_standardCDRFormat;
/// parametrized CDR string
PString m_cdrString;
/// timestamp formatting string
PString m_timestampFormat;
/// human readable names for rotation intervals
static const char* const m_intervalNames[];
};
/// Factory for instances of GkAcctLogger-derived classes
template<class Acct>
struct GkAcctLoggerCreator : public Factory<GkAcctLogger>::Creator0 {
GkAcctLoggerCreator(const char* moduleName) : Factory<GkAcctLogger>::Creator0(moduleName) {}
virtual GkAcctLogger* operator()() const { return new Acct(m_id); }
};
class GkAcctLoggerList
{
public:
/** Construct an empty list of accounting loggers.
*/
GkAcctLoggerList();
/** Destroy the list of accounting loggers.
*/
virtual ~GkAcctLoggerList();
/** Apply configuration changes to the list of accounting loggers.
Usually it means destroying the old list and creating a new one.
*/
void OnReload();
/** Log accounting event with all active accounting loggers.
@return
true if the event has been successfully logged, false otherwise.
*/
bool LogAcctEvent(
GkAcctLogger::AcctEvent evt, /// the accounting event to be logged
const callptr & call, /// a call associated with the event (if any)
time_t now = 0 /// "now" timestamp for accounting update events
);
/** Log accounting event with all active accounting loggers.
@return
true if the event has been successfully logged, false otherwise.
*/
bool LogAcctEvent(
GkAcctLogger::AcctEvent evt, /// the accounting event to be logged
const endptr & ep /// endpoint associated with the event
);
/** Get a module information string for the selected module.
@return
The module information string for status port display.
*/
PString GetInfo(
const PString & moduleName /// module to retrieve information for
) {
std::list<GkAcctLogger*>::const_iterator i = m_loggers.begin();
while (i != m_loggers.end()) {
GkAcctLogger* acct = *i++;
if (acct->GetName() == moduleName)
return acct->GetInfo();
}
return moduleName + " module not found\r\n";
}
private:
GkAcctLoggerList(const GkAcctLogger &);
GkAcctLoggerList & operator=(const GkAcctLoggerList &);
private:
/// head of the accounting loggers list
std::list<GkAcctLogger*> m_loggers;
/// interval (seconds) between subsequent accounting updates for calls
long m_acctUpdateInterval;
};
#endif /* __GKACCT_H */