1
2 /*
3 * pnat.cxx
4 *
5 * NAT Strategy support for Portable Windows Library.
6 *
7 *
8 * Copyright (c) 2004 ISVO (Asia) Pte Ltd. All Rights Reserved.
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 *
21 * The Original Code is derived from and used in conjunction with the
22 * OpenH323 Project (www.openh323.org/)
23 *
24 * The Initial Developer of the Original Code is ISVO (Asia) Pte Ltd.
25 *
26 *
27 * Contributor(s): ______________________________________.
28 *
29 * $Revision: 24883 $
30 * $Author: shorne $
31 * $Date: 2010-11-18 06:08:04 -0600 (Thu, 18 Nov 2010) $
32 */
33
34 #include <ptlib.h>
35 #include <ptclib/pnat.h>
36 #include <ptclib/random.h>
37
38
39 static const char PNatMethodBaseClass[] = "PNatMethod";
Create(const PString & method) const40 template <> PNatMethod * PDevicePluginFactory<PNatMethod>::Worker::Create(const PString & method) const
41 {
42 return PNatMethod::Create(method);
43 }
44
45 typedef PDevicePluginAdapter<PNatMethod> PDevicePluginPNatMethod;
46 PFACTORY_CREATE(PFactory<PDevicePluginAdapterBase>, PDevicePluginPNatMethod, PNatMethodBaseClass, true);
47
48
PNatStrategy()49 PNatStrategy::PNatStrategy()
50 {
51 pluginMgr = NULL;
52 }
53
~PNatStrategy()54 PNatStrategy::~PNatStrategy()
55 {
56 natlist.RemoveAll();
57 }
58
AddMethod(PNatMethod * method)59 void PNatStrategy::AddMethod(PNatMethod * method)
60 {
61 natlist.Append(method);
62 }
63
GetMethod(const PIPSocket::Address & address)64 PNatMethod * PNatStrategy::GetMethod(const PIPSocket::Address & address)
65 {
66 for (PNatList::iterator i = natlist.begin(); i != natlist.end(); i++) {
67 if (i->IsAvailable(address))
68 return &*i;
69 }
70
71 return NULL;
72 }
73
GetMethodByName(const PString & name)74 PNatMethod * PNatStrategy::GetMethodByName(const PString & name)
75 {
76 for (PNatList::iterator i = natlist.begin(); i != natlist.end(); i++) {
77 if (i->GetName() == name) {
78 return &*i;
79 }
80 }
81
82 return NULL;
83 }
84
RemoveMethod(const PString & meth)85 PBoolean PNatStrategy::RemoveMethod(const PString & meth)
86 {
87 for (PNatList::iterator i = natlist.begin(); i != natlist.end(); i++) {
88 if (i->GetName() == meth) {
89 natlist.erase(i);
90 return true;
91 }
92 }
93
94 return false;
95 }
96
SetPortRanges(WORD portBase,WORD portMax,WORD portPairBase,WORD portPairMax)97 void PNatStrategy::SetPortRanges(WORD portBase, WORD portMax, WORD portPairBase, WORD portPairMax)
98 {
99 for (PNatList::iterator i = natlist.begin(); i != natlist.end(); i++)
100 i->SetPortRanges(portBase, portMax, portPairBase, portPairMax);
101 }
102
103
LoadNatMethod(const PString & name)104 PNatMethod * PNatStrategy::LoadNatMethod(const PString & name)
105 {
106 if (pluginMgr == NULL)
107 pluginMgr = &PPluginManager::GetPluginManager();
108
109 return (PNatMethod *)pluginMgr->CreatePluginsDeviceByName(name, PNatMethodBaseClass);
110 }
111
GetRegisteredList()112 PStringArray PNatStrategy::GetRegisteredList()
113 {
114 PPluginManager * plugMgr = &PPluginManager::GetPluginManager();
115 return plugMgr->GetPluginsProviding(PNatMethodBaseClass);
116 }
117
118 ///////////////////////////////////////////////////////////////////////
119
PNatMethod()120 PNatMethod::PNatMethod()
121 {
122
123 }
124
~PNatMethod()125 PNatMethod::~PNatMethod()
126 {
127
128 }
129
Create(const PString & name,PPluginManager * pluginMgr)130 PNatMethod * PNatMethod::Create(const PString & name, PPluginManager * pluginMgr)
131 {
132 if (pluginMgr == NULL)
133 pluginMgr = &PPluginManager::GetPluginManager();
134
135 return (PNatMethod *)pluginMgr->CreatePluginsDeviceByName(name, PNatMethodBaseClass,0);
136 }
137
CreateSocketPair(PUDPSocket * & socket1,PUDPSocket * & socket2,const PIPSocket::Address & binding,void *)138 PBoolean PNatMethod::CreateSocketPair(PUDPSocket * & socket1,PUDPSocket * & socket2,
139 const PIPSocket::Address & binding, void * /*userData*/)
140 {
141 return CreateSocketPair(socket1,socket2,binding);
142 }
143
PrintOn(ostream & strm) const144 void PNatMethod::PrintOn(ostream & strm) const
145 {
146 strm << GetName() << " server " << GetServer();
147 }
148
GetServer() const149 PString PNatMethod::GetServer() const
150 {
151 PStringStream str;
152 PIPSocket::Address serverAddress;
153 WORD serverPort;
154 if (GetServerAddress(serverAddress, serverPort))
155 str << serverAddress << ':' << serverPort;
156 return str;
157 }
158
159
SetPortRanges(WORD portBase,WORD portMax,WORD portPairBase,WORD portPairMax)160 void PNatMethod::SetPortRanges(WORD portBase, WORD portMax, WORD portPairBase, WORD portPairMax)
161 {
162 singlePortInfo.mutex.Wait();
163
164 singlePortInfo.basePort = portBase;
165 if (portBase == 0)
166 singlePortInfo.maxPort = 0;
167 else if (portMax == 0)
168 singlePortInfo.maxPort = (WORD)(singlePortInfo.basePort+99);
169 else if (portMax < portBase)
170 singlePortInfo.maxPort = portBase;
171 else
172 singlePortInfo.maxPort = portMax;
173
174 singlePortInfo.currentPort = singlePortInfo.basePort;
175
176 singlePortInfo.mutex.Signal();
177
178 pairedPortInfo.mutex.Wait();
179
180 pairedPortInfo.basePort = (WORD)((portPairBase+1)&0xfffe);
181 if (portPairBase == 0) {
182 pairedPortInfo.basePort = 0;
183 pairedPortInfo.maxPort = 0;
184 }
185 else if (portPairMax == 0)
186 pairedPortInfo.maxPort = (WORD)(pairedPortInfo.basePort+99);
187 else if (portPairMax < portPairBase)
188 pairedPortInfo.maxPort = portPairBase;
189 else
190 pairedPortInfo.maxPort = portPairMax;
191
192 pairedPortInfo.currentPort = pairedPortInfo.basePort;
193
194 pairedPortInfo.mutex.Signal();
195 }
196
Activate(bool)197 void PNatMethod::Activate(bool /*active*/)
198 {
199
200 }
201
SetAlternateAddresses(const PStringArray &,void *)202 void PNatMethod::SetAlternateAddresses(const PStringArray & /*addresses*/, void * /*userData*/)
203 {
204
205 }
206
RandomPortPair(unsigned int start,unsigned int end)207 WORD PNatMethod::RandomPortPair(unsigned int start, unsigned int end)
208 {
209 WORD num;
210 PRandom rand;
211 num = (WORD)rand.Generate(start,end);
212 if (PString(num).Right(1).FindOneOf("13579") != P_MAX_INDEX)
213 num++; // Make sure the number is even
214
215 return num;
216 }
217
218