/[resiprocate]/main/reTurn/TurnManager.cxx
ViewVC logotype

Contents of /main/reTurn/TurnManager.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10215 - (show annotations) (download)
Mon May 20 18:36:21 2013 UTC (6 years, 5 months ago) by sgodin
File MIME type: text/plain
File size: 8481 byte(s)
-fix bugs with port allocation logic 
 -properly detect wrap around when end of range is max ushort = 65535
 -properly allocate even or odd port after wrap around from end of range
1 #include <rutil/Lock.hxx>
2
3 #include "TurnManager.hxx"
4 #include "TurnAllocation.hxx"
5 #include <rutil/Logger.hxx>
6 #include "ReTurnSubsystem.hxx"
7
8 #define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN
9
10 using namespace std;
11
12 namespace reTurn {
13
14 TurnManager::TurnManager(asio::io_service& ioService, const ReTurnConfig& config) :
15 mLastAllocatedUdpPort(config.mAllocationPortRangeMin-1),
16 mLastAllocatedTcpPort(config.mAllocationPortRangeMin-1),
17 mIOService(ioService),
18 mConfig(config)
19 {
20 // Initialize Allocation Ports
21 for(unsigned short i = config.mAllocationPortRangeMin; i <= config.mAllocationPortRangeMax && i != 0; i++) // i != 0 catches case where we increment 65535 (as an unsigned short)
22 {
23 mUdpAllocationPorts[i] = PortStateUnallocated;
24 mTcpAllocationPorts[i] = PortStateUnallocated;
25 }
26 }
27
28 TurnManager::~TurnManager()
29 {
30 InfoLog(<< "Turn Manager destroyed.");
31 }
32
33 unsigned short
34 TurnManager::allocateAnyPort(StunTuple::TransportType transport)
35 {
36 PortAllocationMap& portAllocationMap = getPortAllocationMap(transport);
37 unsigned short startPortToCheck = advanceLastAllocatedPort(transport);
38 unsigned short portToCheck = startPortToCheck;
39 while(portAllocationMap[portToCheck] != PortStateUnallocated)
40 {
41 portToCheck = advanceLastAllocatedPort(transport);
42 if(portToCheck == startPortToCheck) return 0; // If we checked all available ports and none found - then return 0
43 }
44 portAllocationMap[portToCheck] = PortStateAllocated;
45 return portToCheck;
46 }
47
48 unsigned short
49 TurnManager::allocateEvenPort(StunTuple::TransportType transport)
50 {
51 PortAllocationMap& portAllocationMap = getPortAllocationMap(transport);
52 unsigned short startPortToCheck = advanceLastAllocatedPort(transport);
53 // Ensure start port is even
54 while(startPortToCheck % 2 != 0)
55 {
56 startPortToCheck = advanceLastAllocatedPort(transport);
57 }
58 unsigned short portToCheck = startPortToCheck;
59 while(portAllocationMap[portToCheck] != PortStateUnallocated)
60 {
61 portToCheck = advanceLastAllocatedPort(transport, 2);
62 if(portToCheck == startPortToCheck) return 0; // If we checked all available ports and none found - then return 0
63 }
64 portAllocationMap[portToCheck] = PortStateAllocated;
65 return portToCheck;
66 }
67
68 // Note: This is not used, since requesting an odd port was removed
69 unsigned short
70 TurnManager::allocateOddPort(StunTuple::TransportType transport)
71 {
72 PortAllocationMap& portAllocationMap = getPortAllocationMap(transport);
73 unsigned short startPortToCheck = advanceLastAllocatedPort(transport);
74 // Ensure start port is odd
75 while(startPortToCheck % 2 != 1)
76 {
77 startPortToCheck = advanceLastAllocatedPort(transport);
78 }
79 unsigned short portToCheck = startPortToCheck;
80 while(portAllocationMap[portToCheck] != PortStateUnallocated)
81 {
82 portToCheck = advanceLastAllocatedPort(transport, 2);
83 if(portToCheck == startPortToCheck) return 0; // If we checked all available ports and none found - then return 0
84 }
85 portAllocationMap[portToCheck] = PortStateAllocated;
86 return portToCheck;
87 }
88
89 unsigned short
90 TurnManager::allocateEvenPortPair(StunTuple::TransportType transport)
91 {
92 PortAllocationMap& portAllocationMap = getPortAllocationMap(transport);
93 unsigned short startPortToCheck = advanceLastAllocatedPort(transport);
94 // Ensure start port is even and that start port + 1 is in range
95 while(startPortToCheck % 2 != 0 ||
96 startPortToCheck + 1 == 0 ||
97 startPortToCheck + 1 > mConfig.mAllocationPortRangeMax )
98 {
99 startPortToCheck = advanceLastAllocatedPort(transport);
100 }
101 unsigned short portToCheck = startPortToCheck;
102 while(portAllocationMap[portToCheck] != PortStateUnallocated || portAllocationMap[portToCheck+1] != PortStateUnallocated)
103 {
104 portToCheck = advanceLastAllocatedPort(transport, 2);
105 if(portToCheck == startPortToCheck) return 0; // If we checked all available ports and none found - then return 0
106 }
107 portAllocationMap[portToCheck] = PortStateAllocated;
108 portAllocationMap[portToCheck+1] = PortStateReserved;
109 return portToCheck;
110 }
111
112 bool
113 TurnManager::allocatePort(StunTuple::TransportType transport, unsigned short port, bool reserved)
114 {
115 if(port >= mConfig.mAllocationPortRangeMin && port <= mConfig.mAllocationPortRangeMax)
116 {
117 PortAllocationMap& portAllocationMap = getPortAllocationMap(transport);
118 if(reserved)
119 {
120 if(portAllocationMap[port] == PortStateReserved)
121 {
122 portAllocationMap[port] = PortStateAllocated;
123 return true;
124 }
125 }
126 else
127 {
128 if(portAllocationMap[port] == PortStateUnallocated)
129 {
130 portAllocationMap[port] = PortStateAllocated;
131 return true;
132 }
133 }
134 }
135 return false;
136 }
137
138 void
139 TurnManager::deallocatePort(StunTuple::TransportType transport, unsigned short port)
140 {
141 if(port >= mConfig.mAllocationPortRangeMin && port <= mConfig.mAllocationPortRangeMax)
142 {
143 PortAllocationMap& portAllocationMap = getPortAllocationMap(transport);
144 portAllocationMap[port] = PortStateUnallocated;
145
146 // If port is even - check if next higher port is reserved - if so unallocate it
147 if(port % 2 == 0 && portAllocationMap[port+1] == PortStateReserved)
148 {
149 portAllocationMap[port+1] = PortStateUnallocated;
150 }
151 }
152 }
153
154 TurnManager::PortAllocationMap&
155 TurnManager::getPortAllocationMap(StunTuple::TransportType transport)
156 {
157 switch(transport)
158 {
159 case StunTuple::TCP:
160 case StunTuple::TLS:
161 return mTcpAllocationPorts;
162 case StunTuple::UDP:
163 default:
164 return mUdpAllocationPorts;
165 }
166 }
167
168 unsigned short
169 TurnManager::advanceLastAllocatedPort(StunTuple::TransportType transport, unsigned int numToAdvance)
170 {
171 switch(transport)
172 {
173 case StunTuple::TCP:
174 case StunTuple::TLS:
175 mLastAllocatedTcpPort+=numToAdvance;
176 if(mLastAllocatedTcpPort > mConfig.mAllocationPortRangeMax)
177 {
178 mLastAllocatedTcpPort = mConfig.mAllocationPortRangeMin+(mLastAllocatedTcpPort-mConfig.mAllocationPortRangeMax-1);
179 }
180 else if(mLastAllocatedTcpPort == 0 /* Wrap around */)
181 {
182 mLastAllocatedTcpPort = mConfig.mAllocationPortRangeMin;
183 }
184 return mLastAllocatedTcpPort;
185 case StunTuple::UDP:
186 default:
187 mLastAllocatedUdpPort+=numToAdvance;
188 if(mLastAllocatedUdpPort > mConfig.mAllocationPortRangeMax)
189 {
190 mLastAllocatedUdpPort = mConfig.mAllocationPortRangeMin+(mLastAllocatedUdpPort-mConfig.mAllocationPortRangeMax-1);
191 }
192 else if(mLastAllocatedUdpPort == 0 /* Wrap around */)
193 {
194 mLastAllocatedUdpPort = mConfig.mAllocationPortRangeMin;
195 }
196 return mLastAllocatedUdpPort;
197 }
198 }
199
200 } // namespace
201
202
203 /* ====================================================================
204
205 Copyright (c) 2007-2008, Plantronics, Inc.
206 All rights reserved.
207
208 Redistribution and use in source and binary forms, with or without
209 modification, are permitted provided that the following conditions are
210 met:
211
212 1. Redistributions of source code must retain the above copyright
213 notice, this list of conditions and the following disclaimer.
214
215 2. Redistributions in binary form must reproduce the above copyright
216 notice, this list of conditions and the following disclaimer in the
217 documentation and/or other materials provided with the distribution.
218
219 3. Neither the name of Plantronics nor the names of its contributors
220 may be used to endorse or promote products derived from this
221 software without specific prior written permission.
222
223 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
224 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
225 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
226 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
227 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
228 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
230 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
231 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
232 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
233 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
234
235 ==================================================================== */

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27