forked from willamowius/gnugk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RasTbl.h
2427 lines (2003 loc) · 77.7 KB
/
RasTbl.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
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//////////////////////////////////////////////////////////////////
//
// bookkeeping for RAS-Server in H.323 gatekeeper
//
// Copyright (c) 2000-2022, 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 RASTBL_H
#define RASTBL_H "@(#) $Id$"
#include <list>
#include <map>
#include <string>
#include "rwlock.h"
#include "singleton.h"
#include "h225.h"
#include "sigmsg.h"
#include "config.h"
#include "gktimer.h"
#include "h323util.h"
#include "gkh235.h"
#ifdef HAS_H235_MEDIA
#include "h235auth.h"
#endif
namespace Routing {
class Route;
}
class USocket;
class CallSignalSocket;
class RasServer;
class Q931;
class H323TransportAddress;
class CallRec;
enum CallLeg { Caller, Called };
enum RerouteState { NoReroute, RerouteInitiated, Rerouting };
enum H46019Side { SideA, SideB };
const int INVALID_OSSOCKET = -1;
const WORD INVALID_RTP_SESSION = 0;
const DWORD INVALID_MULTIPLEX_ID = 0;
const BYTE GNUGK_KEEPALIVE_RTP_PAYLOADTYPE = 116; // must at least be 1 less than MAX_DYNAMIC_PAYLOAD_TYPE
const BYTE MIN_DYNAMIC_PAYLOAD_TYPE = 96;
const BYTE MAX_DYNAMIC_PAYLOAD_TYPE = 127;
const unsigned WAIT_DELETE_AFTER_DISCONNECT = 30; // time to wait after disconnect before deleting call object
enum PortType { RASPort=1, Q931Port=2, H245Port=3, RTPPort=4, T120Port=5, RadiusPort=6, StatusPort=7 };
enum PortAction { PortOpen=1, PortClose=2 };
PString PortTypeAsString(PortType t);
class DynamicPort
{
public:
DynamicPort(PortType type, PIPSocket::Address ip, WORD port) { m_type = type; m_ip = ip; m_port = port; }
bool operator==(const DynamicPort & other) const { return m_type == other.m_type && m_ip == other.m_ip && m_port == other.m_port; }
PortType m_type;
PIPSocket::Address m_ip;
WORD m_port;
};
// Template of smart pointer
// The class T must have Lock() & Unlock() methods
template<class T> class SmartPtr {
public:
explicit SmartPtr(T *t = NULL) : pt(t) { Inc(); }
SmartPtr(const SmartPtr<T> & p) : pt(p.pt) { Inc(); }
~SmartPtr() { Dec(); }
operator bool() const { return pt != NULL; }
T *operator->() const { return pt; }
bool operator==(const SmartPtr<T> & p) const { return pt == p.pt; }
bool operator!=(const SmartPtr<T> & p) const { return pt != p.pt; }
SmartPtr<T> &operator=(const SmartPtr<T> & p) {
if (pt != p.pt)
Dec(), pt = p.pt, Inc();
return *this;
}
private:
void Inc() const { if (pt) pt->Lock(); }
void Dec() const { if (pt) pt->Unlock(); }
T &operator*();
T *pt;
};
enum H46019TraversalType { None, TraversalClient, TraversalServer };
class EndpointRec
{
public:
/** Construct internal/out-of-zone endpoint from the specified RAS message.
RRQ builds an internal zone endpoint, ARQ, ACF and LCF build out-of-zone
endpoints.
*/
EndpointRec(
/// RRQ, ARQ, ACF or LCF that contains a description of the endpoint
const H225_RasMessage & ras,
/// permanent endpoint flag
bool permanent = false
);
virtual ~EndpointRec();
// public interface to access EndpointRec
H225_TransportAddress GetRasAddress() const;
H225_TransportAddress GetCallSignalAddress() const;
PIPSocket::Address GetIP() const;
// for multi-homed servers: the IP that the endpoint sent his RAS messages to (needed for H.460.18 SCI)
PIPSocket::Address GetRasServerIP() const { return m_rasServerIP; } // caller need to check for IsValid()
H225_EndpointIdentifier GetEndpointIdentifier() const;
H225_ArrayOf_AliasAddress GetAliases() const;
H225_EndpointType GetEndpointType() const;
bool GetEndpointInfo(PString & vendor, PString & version) const;
int GetTimeToLive() const;
PIPSocket::Address GetNATIP() const;
CallSignalSocket *GetSocket();
CallSignalSocket *GetAndRemoveSocket();
int GetCallTypeOfNumber(bool called = true) const { return called ? m_calledTypeOfNumber : m_callingTypeOfNumber; }
int GetCallPlanOfNumber(bool called = true) const { return called ? m_calledPlanOfNumber : m_callingPlanOfNumber; }
int GetProxyType() const { return m_proxy; }
virtual void SetRasAddress(const H225_TransportAddress &);
virtual void SetCallSignalAddress(const H225_TransportAddress &);
virtual void SetRasServerIP(const PIPSocket::Address & ip) { m_rasServerIP = ip; }
virtual void SetTimeToLive(int);
virtual bool SetAliases(const H225_ArrayOf_AliasAddress &, PBoolean = false);
virtual bool RemoveAliases(const H225_ArrayOf_AliasAddress &);
virtual void AddNumbers(const PString & numbers);
virtual void SetEndpointType(const H225_EndpointType &);
virtual void SetEndpointInfo(const PString & vendor, const PString & version);
virtual long GetBandwidth() const { return m_bandwidth; }
virtual void SetBandwidth(long bw) { m_bandwidth = bw; if (m_bandwidth < 0) m_bandwidth = 0; }
virtual int GetMaxBandwidth() const { return m_maxBandwidth; }
virtual void Update(const H225_RasMessage & lightweightRRQ);
#ifdef HAS_AVAYA_SUPPORT
virtual void Update();
#endif
virtual bool IsGateway() const { return false; }
virtual void SetAdditiveRegistrant();
virtual bool IsAdditiveRegistrant() const;
/** Find if one of the given aliases matches any alias for this endpoint.
@return
true if the match has been found, false otherwise.
*/
virtual bool CompareAlias(
/// aliases to be matched (one of them)
const H225_ArrayOf_AliasAddress* aliases
) const;
virtual void LoadAliases(
/// aliases to be matched (one of them)
const H225_ArrayOf_AliasAddress& aliases,
const H225_EndpointType & type
);
/** Load additional endpoint settings from the config file.
Derived classes should call LoadConfig method of their base class
at the beginning of the overridden LoadConfig.
@return
True if the configuration has been updated successfully.
*/
virtual bool LoadConfig();
GkH235Authenticators * GetH235Authenticators();
void SetH235Authenticators(GkH235Authenticators * auth);
virtual EndpointRec *Unregisterpreempt(int type);
virtual EndpointRec *Reregister();
virtual EndpointRec *Unregister();
virtual EndpointRec *UnregisterWithAlternate(H225_ArrayOf_AlternateGK * setAlternate);
virtual EndpointRec *Expired();
virtual PString PrintOn(bool verbose) const;
PString PrintPrefixCapacities() const;
PString PrintNatInfo(bool verbose) const;
void SetNAT(bool nat);
void SetNATAddress(const PIPSocket::Address &, WORD port = 0);
void SetNATSocket(CallSignalSocket * socket);
void RemoveNATSocket();
void NullNATSocket();
void SetH46024(bool support);
void SetH46024A(bool support);
void SetH46024B(bool support);
enum EPNatTypes {
NatUnknown,
NatOpen,
NatCone,
NatRestricted,
NatPortRestricted,
NatSymmetric,
FirewallSymmetric,
NatBlocked,
NatPartialBlocked
};
void SetEPNATType(int nattype) {m_epnattype = (EPNatTypes)nattype; }
void SetNATProxy(PBoolean support) {m_natproxy = support; }
void SetInternal(PBoolean internal) { m_internal = internal; }
void SetUsesH46023(bool uses) { m_usesH46023 = uses; }
void SetPriority(int priority) { m_registrationPriority = priority; }
void SetPreemption(bool support) { m_registrationPreemption = support; }
void SetAssignedGatekeeper(const H225_AlternateGK & gk) { m_assignedGatekeeper = gk; }
bool SetAssignedAliases(H225_ArrayOf_AliasAddress & assigned);
/** @return
true if this is a permanent endpoint loaded from the config file entry.
*/
bool IsPermanent() const;
bool IsUsed() const;
bool IsUpdated(const PTime *) const;
void DeferTTL();
bool IsNATed() const;
bool SupportH46024() const;
bool SupportH46024A() const;
bool SupportH46024B() const;
bool UseH46024B() const;
bool UsesH46023() const { return m_usesH46023; }
bool HasNATProxy() const;
bool IsInternal() const;
bool IsRemote() const;
int GetEPNATType() const { return (int)m_epnattype; }
static PString GetEPNATTypeString(EPNatTypes nat);
bool SupportPreemption() const { return m_registrationPreemption; }
int Priority() const { return m_registrationPriority; }
PTime GetUpdatedTime() const;
PTime GetRegistrationTime() const;
void SetUsesH460P(bool uses);
bool UsesH460P() const { return m_usesH460P; }
#ifdef HAS_H460P
void ParsePresencePDU(const PASN_OctetString & pdu);
#ifdef HAS_H460P_VER_3
bool HasPresenceData();
#else
bool BuildPresencePDU(unsigned msgtag, PASN_OctetString & pdu);
#endif // HAS_H460P_VER_3
#endif // HAS_H460P
/** If this Endpoint would be register itself again with all the same data
* how would this RRQ would look like? May be implemented with a
* built-together-RRQ, but for the moment a stored RRQ.
*/
H225_RasMessage GetCompleteRegistrationRequest() const;
void AddCall(const PString & dest);
void AddConnectedCall();
void RemoveCall(const PString & dest);
void Lock();
void Unlock();
bool SendIRQ();
#ifdef HAS_AVAYA_SUPPORT
bool SendCCMSUpdate();
#endif
bool HasCallCreditCapabilities() const;
/** Append a call credit related service control descriptor to the array
of service control sessions, if the endpoint supports call credit
capabilities.
*/
virtual bool AddCallCreditServiceControl(
H225_ArrayOf_ServiceControlSession& sessions, /// array to add the service control descriptor to
const PString& amountStr, /// user's account balance amount string
int billingMode, /// user's account billing mode (-1 if not set)
long callDurationLimit /// call duration limit (-1 if not set)
);
/** Append a URL related service control descriptor to the array
of service control sessions
*/
virtual bool AddHTTPServiceControl(
H225_ArrayOf_ServiceControlSession& sessions /// array to add the service control descriptor to
);
#if H323_H350
/** Append a H.350 related service control descriptor to the array
of service control sessions
*/
virtual bool AddH350ServiceControl(
H225_ArrayOf_ServiceControlSession& sessions /// array to add the service control descriptor to
);
#endif
/** @return
True if the endpoint can handle at least one more concurrent call.
*/
bool HasAvailableCapacity(const H225_ArrayOf_AliasAddress & aliases) const;
unsigned GetActiveCalls() const { return m_activeCall; }
// void DumpPrefixCapacity() const;
string LongestPrefixMatch(const PString & alias, int & capacity) const;
void UpdatePrefixStats(const PString & dest, int update);
// cause code translation
unsigned TranslateReceivedCause(unsigned cause) const;
unsigned TranslateSentCause(unsigned cause) const;
// adding a fixed alias to all calls _to_ this endpoint
PString GetAdditionalDestinationAlias() const { return m_additionalDestAlias; }
bool IsH46017Disabled() const { return m_h46017disabled; }
void SetUsesH46017(bool val) { m_usesH46017 = val; }
bool UsesH46017() const { return m_usesH46017; }
bool IsH46018Disabled() const { return m_h46018disabled; }
void SetUsesH46026(bool val) { m_usesH46026 = val; }
bool UsesH46026() const { return m_usesH46026; }
#ifdef HAS_H46026
unsigned GetH46026BW() const { return (m_maxBandwidth > 0) ? (m_maxBandwidth / 2) : 384000; }
#endif
void SetTraversalRole(H46019TraversalType val) { m_traversalType = val; m_nat = (val == TraversalClient); }
H46019TraversalType GetTraversalRole() const { return m_traversalType; }
bool IsTraversalServer() const { return m_traversalType == TraversalServer; }
bool IsTraversalClient() const { return m_traversalType == TraversalClient; }
void SetUseTLS(bool val) { m_useTLS = val; }
bool UseTLS() const { return m_useTLS; }
void SetTLSAddress(const H323TransportAddress & addr) { m_tlsAddress = addr; }
H323TransportAddress GetTLSAddress() const;
void SetUseIPSec(bool val) { m_useIPSec = val; }
bool UseIPSec() const { return m_useIPSec; }
#ifdef HAS_LANGUAGE
bool SetAssignedLanguage(const H225_RegistrationRequest_language & rrqLang, H225_RegistrationConfirm_language & rcfLang);
bool SetAssignedLanguage(H225_LocationConfirm_language & lcfLang);
#endif // HAS_LANGUAGE
void SetLanguages(const PStringList & languages) { m_languages = languages; }
const PStringList & GetLanguages() { return m_languages; }
PString GetDefaultLanguage();
bool AddCallingPartyToSourceAddress() const { return m_addCallingPartyToSourceAddress; }
PString GetDisabledCodecs() const { return m_disabledcodecs; }
int GetForceTerminalType() const { return m_forceTerminalType; }
bool GetForceDirectMode() const { return m_forceDirectMode; }
void SetGnuGkAssignedGk(const PIPSocket::Address & addr) { m_hasGnuGkAssignedGk = true; m_GnuGkAssignedGk = addr; }
bool HasGnuGkAssignedGk() const { return m_hasGnuGkAssignedGk; }
PIPSocket::Address GetGnuGkAssignedGk() const { return m_GnuGkAssignedGk; }
// smart pointer for EndpointRec
typedef SmartPtr<EndpointRec> Ptr;
bool IsAvaya() const;
#ifdef HAS_AVAYA_SUPPORT
// Avaya hack
CallRec* GetCCMS() const { return m_ccmsCall; }
void SetCCMS(CallRec* addr) { m_ccmsCall = addr; }
WORD GetNextCRV();
enum HookStates {
hsUnknown,
hsOnhook,
hsOffhook
};
void SetHook(int hook_state) { m_hookstate = (enum HookStates) hook_state; }
int GetHook() const { return (int)m_hookstate; }
PString GetHookString() const;
#endif
protected:
void SetEndpointRec(H225_RegistrationRequest &);
void SetEndpointRec(H225_AdmissionRequest &);
void SetEndpointRec(H225_AdmissionConfirm &);
void SetEndpointRec(H225_LocationConfirm &);
void SetEndpointRec(H225_UnregistrationRequest &); // used for temp objects
bool SendURQ(H225_UnregRequestReason::Choices, int preemption, H225_ArrayOf_AlternateGK * setAlternate = NULL);
private:
/// Load general endpoint settings from the config
void LoadEndpointConfig();
void AddPrefixCapacities(const PString & prefixes);
EndpointRec();
EndpointRec(const EndpointRec &);
EndpointRec & operator= (const EndpointRec &);
protected:
/**This field may disappear sometime when GetCompleteRegistrationRequest() can
* build its return value itself.
* @see GetCompleteRegistrationRequest()
*/
H225_RasMessage m_RasMsg;
H225_TransportAddress m_rasAddress;
H225_TransportAddress m_callSignalAddress;
PIPSocket::Address m_rasServerIP;
H225_EndpointIdentifier m_endpointIdentifier;
H225_ArrayOf_AliasAddress m_terminalAliases;
H225_EndpointType *m_terminalType;
H225_VendorIdentifier *m_endpointVendor;
int m_timeToLive; // seconds
int m_defaultKeepAliveInterval; // for H.460.10 in seconds
int m_activeCall, m_connectedCall, m_totalCall;
/// active calls per prefix (regex)
std::map<string, int> m_activePrefixCalls;
int m_pollCount, m_usedCount;
mutable PMutex m_usedLock;
PTime m_updatedTime; // last update from EP
PTime m_registrationTime; // time when the EP registered
bool m_fromParent, m_nat;
PIPSocket::Address m_natip;
CallSignalSocket *m_natsocket;
/// permanent (preconfigured) endpoint flag
bool m_permanent;
/// can understand H.225 CallCreditServiceControl
bool m_hasCallCreditCapabilities;
/// session number for call credit service control session
int m_callCreditSession;
/// endpoint call capacity, -1 means no limit
long m_capacity;
/// capacity per prefix (regex)
list<pair<string, int> > m_prefixCapacities;
int m_calledTypeOfNumber, m_callingTypeOfNumber;
int m_calledPlanOfNumber, m_callingPlanOfNumber;
/// Proxy Type
int m_proxy;
/// Registration Priority Number
int m_registrationPriority;
/// Support Registration PreEmption
bool m_registrationPreemption;
/// Assigned Gatekeeper
H225_AlternateGK m_assignedGatekeeper;
/// cause code translation
std::map<unsigned, unsigned> m_receivedCauseMap;
std::map<unsigned, unsigned> m_sentCauseMap;
/// additional alias to be added to all calls TO this endpoint
PString m_additionalDestAlias;
EPNatTypes m_epnattype;
#ifdef HAS_AVAYA_SUPPORT
// Avaya hack
HookStates m_hookstate; // current hook state of endpoint
CallRec* m_ccmsCall; // reference to relative CallRec with CCMS
WORD m_nextcrv; // next available CRV for AsteriskGW
#endif
bool m_usesH46023, m_H46024, m_H46024a, m_H46024b, m_natproxy, m_internal, m_remote;
bool m_h46017disabled;
bool m_h46018disabled;
bool m_usesH460P;
bool m_hasH460PData;
bool m_usesH46017;
bool m_usesH46026;
H46019TraversalType m_traversalType; // this is not what GnuGk acts like, but what this EPRec is a proxy for
long m_bandwidth; // bandwidth currently occupied by this endpoint
long m_maxBandwidth; // maximum bandwidth allowed for this endpoint
bool m_useTLS;
H323TransportAddress m_tlsAddress;
bool m_useIPSec; // for H.460.22 negotiation
bool m_additiveRegistrant;
PStringList m_languages; // languages the user of this endpoint supports
bool m_addCallingPartyToSourceAddress; // per endpoint switch
/// list of disabled codes
PString m_disabledcodecs;
int m_forceTerminalType; // for endpoint type in master/slave decision to this, -1 leave alone
bool m_forceDirectMode; // always use direct mode for this endpoint
/// H.235 used to authenticate this endpoint
GkH235Authenticators * m_authenticators;
bool m_hasGnuGkAssignedGk;
PIPSocket::Address m_GnuGkAssignedGk;
};
typedef EndpointRec::Ptr endptr;
class GatewayRec : public EndpointRec {
public:
typedef std::map<std::string, int>::iterator prefix_iterator;
typedef std::map<std::string, int>::const_iterator const_prefix_iterator;
GatewayRec(const H225_RasMessage & completeRAS, bool Permanent=false);
virtual void SetEndpointType(const H225_EndpointType &);
virtual void Update(const H225_RasMessage & lightweightRRQ);
virtual bool IsGateway() const { return true; }
/// Overridden from EndpointRec
virtual bool LoadConfig();
/** Find if at least one of the given aliases matches any prefix
for this gateway.
@return
Length (number of characters) of the match, 0 if no match has been
found and this is the default gateway, -1 if no match has been found
and this is not the default gateway.
*/
virtual int PrefixMatch(
/// aliases to be matched (one of them)
const H225_ArrayOf_AliasAddress& aliases
) const;
/** Find if at least one of the given aliases matches any prefix
for this gateway and return an index of the matched alias.
@return
Length (number of characters) of the match, 0 if no match has been
found and this is the default gateway, -1 if no match has been found
and this is not the default gateway.
*/
virtual int PrefixMatch(
/// aliases to be matched (one of them)
const H225_ArrayOf_AliasAddress & aliases,
/// filled with an index of the matching alias (if found)
int & matchedalias,
/// priority of matched prefix
int & priority
) const;
virtual PString PrintOn(bool verbose) const;
void AddPrefixes(const H225_ArrayOf_SupportedProtocols &);
void AddPrefixes(const PString &);
void SortPrefixes();
/** @return
Priority for this gateway, when more than one gateway matches
a dialed number.
*/
int GetPriority() const { return priority; }
//void DumpPriorities() const;
private:
/// Load gateway specific settings from the config
void LoadGatewayConfig();
GatewayRec();
GatewayRec(const GatewayRec &);
GatewayRec & operator=(const GatewayRec &);
protected:
std::map<std::string, int> Prefixes;
bool defaultGW;
/// priority for this gateway (when more than one gw matches a dialed number)
int priority;
};
class OutOfZoneEPRec : public EndpointRec {
public:
OutOfZoneEPRec(const H225_RasMessage & completeRAS, const H225_EndpointIdentifier &);
virtual EndpointRec *Unregister() { return this; }
virtual EndpointRec *Expired() { return this; }
};
class OutOfZoneGWRec : public GatewayRec {
public:
OutOfZoneGWRec(const H225_RasMessage & completeRAS, const H225_EndpointIdentifier &);
virtual EndpointRec *Unregister() { return this; }
virtual EndpointRec *Expired() { return this; }
};
class EPQoS {
public:
EPQoS() { Init(); }
EPQoS(PTime lastMsg) { Init(); m_lastMsg = lastMsg; }
~EPQoS() { }
void Init();
PString AsString() const;
void IncrementCalls() { m_numCalls++; }
void SetAudioPacketLossPercent(float val) { m_audioPacketLossPercent = val; }
void SetAudioJitter(unsigned val) { m_audioJitter = val; }
void SetVideoPacketLossPercent(float val) { m_videoPacketLossPercent = val; }
void SetVideoJitter(unsigned val) { m_videoJitter = val; }
protected:
PTime m_lastMsg;
unsigned m_numCalls;
float m_audioPacketLossPercent;
unsigned long m_audioJitter;
float m_videoPacketLossPercent;
unsigned long m_videoJitter;
};
class RegistrationTable : public Singleton<RegistrationTable> {
public:
typedef std::list<EndpointRec *>::iterator iterator;
typedef std::list<EndpointRec *>::const_iterator const_iterator;
RegistrationTable();
~RegistrationTable();
endptr InsertRec(H225_RasMessage & rrq, PIPSocket::Address = GNUGK_INADDR_ANY);
endptr InsertRec(const H225_Setup_UUIE & setupBody, H225_TransportAddress addr);
void RemoveByEndptr(const endptr & eptr);
endptr FindByEndpointId(const H225_EndpointIdentifier & endpointId) const;
endptr FindBySignalAdr(const H225_TransportAddress &, PIPSocket::Address = GNUGK_INADDR_ANY) const;
endptr FindBySignalAdrIgnorePort(const H225_TransportAddress &, PIPSocket::Address = GNUGK_INADDR_ANY) const;
endptr FindOZEPBySignalAdr(const H225_TransportAddress &) const;
endptr FindByAliases(const H225_ArrayOf_AliasAddress & alias) const;
endptr FindFirstEndpoint(const H225_ArrayOf_AliasAddress & alias);
bool FindEndpoint(
const H225_ArrayOf_AliasAddress &aliases,
bool roundRobin,
bool leastUsedRouting,
bool searchOutOfZone,
std::list<Routing::Route> &routes
);
void ClearTable();
void UpdateTable();
void CheckEndpoints();
// handle remote closing of a NAT socket
void OnNATSocketClosed(CallSignalSocket * s);
#ifdef HAS_H46017
void UnregisterAllH46017Endpoints();
#endif
void UnregisterAllEndpointsNotInCall();
void PrintAllRegistrations(USocket *client, bool verbose = FALSE);
void PrintAllCached(USocket *client, bool verbose = FALSE);
void PrintRemoved(USocket *client, bool verbose = FALSE);
void PrintPrefixCapacities(USocket *client, PString alias) const;
void PrintEndpointQoS(USocket *client) const;
PString PrintStatistics() const;
// void PrintOn( ostream &strm ) const;
/** Updates Prefix + Flags for all aliases */
void LoadConfig();
PINDEX Size() const { return regSize; }
private:
endptr InternalInsertEP(H225_RasMessage &);
endptr InternalInsertOZEP(H225_RasMessage &, H225_LocationConfirm &);
endptr InternalInsertOZEP(H225_RasMessage &, H225_AdmissionConfirm &);
endptr InternalInsertOZEP(const H225_Setup_UUIE & setupBody, H225_TransportAddress addr);
void InternalPrint(USocket *, bool, std::list<EndpointRec *> *, PString &);
void InternalStatistics(const std::list<EndpointRec *> *, unsigned & s, unsigned & t, unsigned & g, unsigned & n) const;
void InternalRemove(iterator);
template<class F> endptr InternalFind(const F & FindObject) const
{ return InternalFind(FindObject, &EndpointList); }
template<class F> endptr InternalFind(const F & FindObject, const std::list<EndpointRec *> *ListToBeFound) const
{ // The function body must be put here,
// or the stupid VC would fail to instantiate it
ReadLock lock(listLock);
const_iterator Iter(find_if(ListToBeFound->begin(), ListToBeFound->end(), FindObject));
return endptr((Iter != ListToBeFound->end()) ? *Iter : NULL);
}
endptr InternalFindFirstEP(const H225_ArrayOf_AliasAddress & alias, std::list<EndpointRec *> *ListToBeFound);
bool InternalFindEP(const H225_ArrayOf_AliasAddress & alias, std::list<EndpointRec *> *ListToBeFound, bool roundrobin, bool leastUsedRouting, std::list<Routing::Route> &routes);
void GenerateEndpointId(H225_EndpointIdentifier & NewEndpointId, PString prefix = "");
void GenerateAlias(H225_ArrayOf_AliasAddress &, const H225_EndpointIdentifier &) const;
std::list<EndpointRec *> EndpointList;
std::list<EndpointRec *> OutOfZoneList;
std::list<EndpointRec *> RemovedList;
int regSize;
mutable PReadWriteMutex listLock;
PMutex findmutex; // Endpoint Find Mutex
PString endpointIdSuffix; // Suffix of the generated Endpoint IDs
// not assignable
RegistrationTable(const RegistrationTable &);
RegistrationTable& operator=(const RegistrationTable &);
};
template<class> class RasPDU;
#ifdef HAS_H46018
enum KeepAliveType { RTP, RTCP };
class H46019KeepAlive
{
public:
H46019KeepAlive();
~H46019KeepAlive();
void SendKeepAlive(GkTimer* timer);
void StopKeepAlive();
unsigned flcn;
KeepAliveType type;
IPAndPortAddress dest;
unsigned interval;
unsigned seq;
int ossocket;
DWORD multiplexID;
BYTE payloadType;
PIPSocket::Address gkIP; // source IP
PIPSocket::Address * gkIPptr; // source IP pointer if valid
GkTimerManager::GkTimerHandle timer;
};
#endif
// record of one active call
#ifdef HAS_H460
class H4609_QosMonitoringReportData;
#endif // HAS_H460
#ifdef HAS_H46018
// direction definitions for H.460.19
#define H46019_NONE 0 // m_h46019dir = 0 ' No party needs H.460.19, so skip the code
#define H46019_CALLER 1 // m_h46019dir = 1 ' Caller needs H.460.19
#define H46019_CALLED 2 // m_h46019dir = 2 ' Called needs H.460.19
#define H46019_BOTH (H46019_CALLER + H46019_CALLED) // m_h46019dir = 3 ' Both need it
#endif // HAS_H46018
class CallRec {
public:
/// flag to overwrite proxy settings for the call
enum ProxyMode {
ProxyDetect, /// use global settings from the config
ProxyEnabled, /// force full proxy mode
ProxyDisabled, /// disable full proxy mode
#ifdef HAS_AVAYA_SUPPORT
ProxyCCMS /// CCMS interworking mode
#endif
};
/// the combination of ProxyMode, RoutedMode and H245 routing
enum RoutingMode {
Undefined = 0,
SignalRouted,
H245Routed,
Proxied
};
/// who disconnected the call
enum ReleaseSource {
ReleasedByGatekeeper,
ReleasedByCaller,
ReleasedByCallee
};
/// build a new call record from the received ARQ message
CallRec(
/// ARQ with call information
const RasPDU<H225_AdmissionRequest> & arq,
/// bandwidth occupied by the call
long bandwidth,
/// called party's aliases in a string form
const PString & destInfo,
/// override proxy mode global setting from the config
int proxyMode = ProxyDetect
);
/// build a new call record from the received Setup message
CallRec(
/// Q.931 Setup pdu with call information
const Q931 & q931pdu,
/// H.225.0 Setup-UUIE pdu with call information
const H225_Setup_UUIE & setup,
/// force H.245 routed mode
bool routeH245,
/// called party's aliases in a string form
const PString & destInfo,
/// override proxy mode global setting from the config
int proxyMode = ProxyDetect
);
/// build a new call record with just a callID and transport adr (after H.460.18 SCI)
CallRec(const H225_CallIdentifier & callID, H225_TransportAddress sigAdr);
CallRec(CallRec * oldCall);
virtual ~CallRec();
enum NATType { // who is nated?
none = 0,
callingParty = 1,
calledParty = 2,
both = 3
};
PINDEX GetCallNumber() const { return m_CallNumber; }
const H225_CallIdentifier & GetCallIdentifier() const { return m_callIdentifier; }
void ClearCallIdentifier() { m_callIdentifier = 0; }
unsigned GetCallRef() const { return m_crv; }
void SetCallRefFixup(bool val) { m_callRefFixup = val; }
bool IsCallRefFixup() const { return m_callRefFixup; }
const H225_ConferenceIdentifier & GetConferenceIdentifier() const { return m_conferenceIdentifier; }
endptr GetCallingParty() const { return m_Calling; }
endptr GetCalledParty() const { return m_Called; }
endptr GetForwarder() const { return m_Forwarder; }
long GetBandwidth() const { return m_bandwidth; }
bool HasPostDialDigits() const { return !m_postdialdigits.IsEmpty(); }
PString GetPostDialDigits() const { return m_postdialdigits; }
void SetPostDialDigits(const PString & digits) { m_postdialdigits = digits; }
/** @return
A bit mask with NAT flags for calling and called parties.
See #NATType enum# for more details.
*/
int GetNATType() const { return m_nattype; }
int GetNATType(
/// filled with NAT IP of the calling party (if nat type is callingParty)
PIPSocket::Address& callingPartyNATIP,
/// filled with NAT IP of the called party (if nat type is calledParty)
PIPSocket::Address& calledPartyNATIP
) const;
#ifdef HAS_H46023
// Override the calculated NAT type
void SetNATType(int newNatType) { m_nattype = newNatType; }
/** Can the call party be used to bypass proxy for NAT
*/
enum NatStrategy {
e_natUnknown,
e_natNoassist,
e_natLocalMaster,
e_natRemoteMaster,
e_natLocalProxy,
e_natRemoteProxy,
e_natFullProxy,
e_natAnnexA, // Same NAT
e_natAnnexB, // Nat Offload
e_natFailure = 100
};
/** Return whether a call can be offloaded from having to proxy
*/
bool NATOffLoad(bool iscalled, NatStrategy & natinst);
/** Return whether an unknown incoming call can be offloaded from having to proxy
*/
bool NATAssistCallerUnknown(NatStrategy & natinst);
/** Set Receive Side Strategy
*/
void SetReceiveNATStategy(NatStrategy & type, int & proxyMode);
/** Get String representation of the NATStrategy */
PString GetNATOffloadString(NatStrategy nat) const;
/** Get the NATStrategy Default is Unknown */
NatStrategy GetNATStrategy() const { return m_natstrategy; }
/** Set the NATStrategy */
void SetNATStrategy(NatStrategy strategy) { m_natstrategy = strategy; }
/** Can signaling be offloaded
*/
bool NATSignallingOffload(bool isAnswer) const;
#ifdef HAS_H46024A
/** Whether Annex A passthrough
*/
bool IsH46024APassThrough();
/** Send a H.460.24 Annex A indication
*/
PBoolean H46024AMessage();
/** GetSignalingSocket */
CallSignalSocket * H46024ASignalSocket();
#endif // HAS_H46024A
#ifdef HAS_H46024B
/** GetSignalingSocket */
CallSignalSocket * H46024BSignalSocket(bool response);
/** Initiate Probe */
void H46024BInitiate(WORD sessionID, const IPAndPortAddress & fwd, const IPAndPortAddress & rev, unsigned muxID_fwd = 0, unsigned muxID_rev = 0);
/** Response Probe */
void H46024BRespond();
/** Set session callback flag */
void H46024BSessionFlag(WORD sessionID);
/** Handle H46024B Request */
bool HandleH46024BRequest(const H245_ArrayOf_GenericParameter & content);
#endif // HAS_H46024B
/** Return whether the endpoints are registered at the same gatekeeper so
only 1 gatekeeper is involved in the call
*/
bool SingleGatekeeper() const;
#endif // HAS_H46023
/** Return remote party device information
*/
bool GetRemoteInfo(PString & vendor, PString & version);
/** @return
Current proxy mode flag (see #ProxyMode enum#).
*/
int GetProxyMode() const { return m_proxyMode; }
/// Override proxy mode global setting from the config
void SetProxyMode(
int mode /// proxy mode flag (see #ProxyMode enum#)
);
CallSignalSocket *GetCallSignalSocketCalled() { return m_calledSocket; }
CallSignalSocket *GetCallSignalSocketCalling() { return m_callingSocket; }
const H225_ArrayOf_CryptoH323Token & GetAccessTokens() const { return m_accessTokens; }
PString GetInboundRewriteId() const { return m_inbound_rewrite_id; }
PString GetOutboundRewriteId() const { return m_outbound_rewrite_id; }
void SetCallNumber(PINDEX i) { m_CallNumber = i; }
void SetCalling(const endptr & NewCalling);
void SetCalled(const endptr & NewCalled);
void SetForward(CallSignalSocket *, const H225_TransportAddress &, const endptr &, const PString &, const PString &);
void RerouteDropCalling();
void RerouteDropCalled();
void AddChannelFlcn(WORD flcn) { m_channelFlcnList.push_back(flcn); } // list of all channel Flcn every _tried_ to open
vector<WORD> GetChannelFlcnList() const { return m_channelFlcnList; } // list of all channel Flcn every _tried_ to open
void ClearChannelFlcnList() { m_channelFlcnList.clear(); }
bool DropCalledAndTryNextRoute();
void SetBandwidth(long bandwidth) { m_bandwidth = bandwidth; if (m_bandwidth < 0) m_bandwidth = 0; }
void SetSocket(CallSignalSocket *, CallSignalSocket *);
void SetCallSignalSocketCalling(CallSignalSocket* socket);
void SetCallSignalSocketCalled(CallSignalSocket* socket);
#ifdef HAS_H46018
void SetH245OSSocket(int socket, bool isAnswer, const PString & name);
#endif
void SetToParent(bool toParent) { m_toParent = toParent; }
void SetFromParent(bool fromParent) { m_fromParent = fromParent; }
void SetAccessTokens(const H225_ArrayOf_CryptoH323Token & tokens) { m_accessTokens = tokens; }
void SetInboundRewriteId(PString id) { m_inbound_rewrite_id = id; }
void SetOutboundRewriteId(PString id) { m_outbound_rewrite_id = id; }
void SetConnected();
void Disconnect(bool = false); // send ReleaseComplete ?
void RemoveAll();
void RemoveSocket();
void SendReleaseComplete(const H225_CallTerminationCause * = NULL);
void BuildDRQ(H225_DisengageRequest &, unsigned reason) const;
bool CompareCallId(const H225_CallIdentifier *CallId) const;
bool CompareCRV(WORD crv) const;
bool CompareCallNumber(PINDEX CallNumber) const;
bool CompareEndpoint(const endptr *) const;
bool CompareSigAdr(const H225_TransportAddress *adr) const;
bool CompareSigAdrIgnorePort(const H225_TransportAddress *adr) const;
/** @return
true if the call has been connected - a Connect message
has been received in gk routed signaling or the call has been admitted
(ARQ->ACF) in direct signaling. Does not necessary mean
that the call is still in progress (may have been already disconnected).
*/
bool IsConnected() const { return (m_connectTime != 0); }
void SetH245Routed(PBoolean routed) { m_h245Routed = routed; }
bool IsH245Routed() const { return m_h245Routed; }
bool IsToParent() const { return m_toParent; } // to _or_ from parent