blob: 145efcbc58567e1c04d084f8b0041f42aaade43b [file] [log] [blame]
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:051/*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/test/channel_transport/udp_socket_manager_posix.h"
12
pbos@webrtc.org96001c82013-05-27 15:02:2313#include <stdio.h>
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:0514#include <strings.h>
15#include <sys/time.h>
16#include <sys/types.h>
17#include <time.h>
18#include <unistd.h>
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:0519
Henrik Kjellander78f65d02015-10-28 17:17:4020#include "webrtc/system_wrappers/include/sleep.h"
21#include "webrtc/system_wrappers/include/trace.h"
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:0522#include "webrtc/test/channel_transport/udp_socket_posix.h"
23
24namespace webrtc {
25namespace test {
26
27UdpSocketManagerPosix::UdpSocketManagerPosix()
28 : UdpSocketManager(),
29 _id(-1),
30 _critSect(CriticalSectionWrapper::CreateCriticalSection()),
31 _numberOfSocketMgr(-1),
32 _incSocketMgrNextTime(0),
33 _nextSocketMgrToAssign(0),
34 _socketMgr()
35{
36}
37
pbos@webrtc.org91cab712013-04-09 11:10:2138bool UdpSocketManagerPosix::Init(int32_t id, uint8_t& numOfWorkThreads) {
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:0539 CriticalSectionScoped cs(_critSect);
40 if ((_id != -1) || (_numOfWorkThreads != 0)) {
41 assert(_id != -1);
42 assert(_numOfWorkThreads != 0);
43 return false;
44 }
45
46 _id = id;
47 _numberOfSocketMgr = numOfWorkThreads;
48 _numOfWorkThreads = numOfWorkThreads;
49
50 if(MAX_NUMBER_OF_SOCKET_MANAGERS_LINUX < _numberOfSocketMgr)
51 {
52 _numberOfSocketMgr = MAX_NUMBER_OF_SOCKET_MANAGERS_LINUX;
53 }
54 for(int i = 0;i < _numberOfSocketMgr; i++)
55 {
56 _socketMgr[i] = new UdpSocketManagerPosixImpl();
57 }
58 return true;
59}
60
61
62UdpSocketManagerPosix::~UdpSocketManagerPosix()
63{
64 Stop();
65 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
66 "UdpSocketManagerPosix(%d)::UdpSocketManagerPosix()",
67 _numberOfSocketMgr);
68
69 for(int i = 0;i < _numberOfSocketMgr; i++)
70 {
71 delete _socketMgr[i];
72 }
73 delete _critSect;
74}
75
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:0576bool UdpSocketManagerPosix::Start()
77{
78 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
79 "UdpSocketManagerPosix(%d)::Start()",
80 _numberOfSocketMgr);
81
82 _critSect->Enter();
83 bool retVal = true;
84 for(int i = 0;i < _numberOfSocketMgr && retVal; i++)
85 {
86 retVal = _socketMgr[i]->Start();
87 }
88 if(!retVal)
89 {
90 WEBRTC_TRACE(
91 kTraceError,
92 kTraceTransport,
93 _id,
94 "UdpSocketManagerPosix(%d)::Start() error starting socket managers",
95 _numberOfSocketMgr);
96 }
97 _critSect->Leave();
98 return retVal;
99}
100
101bool UdpSocketManagerPosix::Stop()
102{
103 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
104 "UdpSocketManagerPosix(%d)::Stop()",_numberOfSocketMgr);
105
106 _critSect->Enter();
107 bool retVal = true;
108 for(int i = 0; i < _numberOfSocketMgr && retVal; i++)
109 {
110 retVal = _socketMgr[i]->Stop();
111 }
112 if(!retVal)
113 {
114 WEBRTC_TRACE(
115 kTraceError,
116 kTraceTransport,
117 _id,
118 "UdpSocketManagerPosix(%d)::Stop() there are still active socket "
119 "managers",
120 _numberOfSocketMgr);
121 }
122 _critSect->Leave();
123 return retVal;
124}
125
126bool UdpSocketManagerPosix::AddSocket(UdpSocketWrapper* s)
127{
128 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
129 "UdpSocketManagerPosix(%d)::AddSocket()",_numberOfSocketMgr);
130
131 _critSect->Enter();
132 bool retVal = _socketMgr[_nextSocketMgrToAssign]->AddSocket(s);
133 if(!retVal)
134 {
135 WEBRTC_TRACE(
136 kTraceError,
137 kTraceTransport,
138 _id,
139 "UdpSocketManagerPosix(%d)::AddSocket() failed to add socket to\
140 manager",
141 _numberOfSocketMgr);
142 }
143
144 // Distribute sockets on UdpSocketManagerPosixImpls in a round-robin
145 // fashion.
146 if(_incSocketMgrNextTime == 0)
147 {
148 _incSocketMgrNextTime++;
149 } else {
150 _incSocketMgrNextTime = 0;
151 _nextSocketMgrToAssign++;
152 if(_nextSocketMgrToAssign >= _numberOfSocketMgr)
153 {
154 _nextSocketMgrToAssign = 0;
155 }
156 }
157 _critSect->Leave();
158 return retVal;
159}
160
161bool UdpSocketManagerPosix::RemoveSocket(UdpSocketWrapper* s)
162{
163 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id,
164 "UdpSocketManagerPosix(%d)::RemoveSocket()",
165 _numberOfSocketMgr);
166
167 _critSect->Enter();
168 bool retVal = false;
169 for(int i = 0;i < _numberOfSocketMgr && (retVal == false); i++)
170 {
171 retVal = _socketMgr[i]->RemoveSocket(s);
172 }
173 if(!retVal)
174 {
175 WEBRTC_TRACE(
176 kTraceError,
177 kTraceTransport,
178 _id,
179 "UdpSocketManagerPosix(%d)::RemoveSocket() failed to remove socket\
180 from manager",
181 _numberOfSocketMgr);
182 }
183 _critSect->Leave();
184 return retVal;
185}
186
187
188UdpSocketManagerPosixImpl::UdpSocketManagerPosixImpl()
189{
190 _critSectList = CriticalSectionWrapper::CreateCriticalSection();
191 _thread = ThreadWrapper::CreateThread(UdpSocketManagerPosixImpl::Run, this,
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05192 "UdpSocketManagerPosixImplThread");
193 FD_ZERO(&_readFds);
194 WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1,
195 "UdpSocketManagerPosix created");
196}
197
198UdpSocketManagerPosixImpl::~UdpSocketManagerPosixImpl()
199{
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05200 if (_critSectList != NULL)
201 {
202 UpdateSocketMap();
203
204 _critSectList->Enter();
pbos@webrtc.org52c5c702013-08-12 19:51:57205 for (std::map<SOCKET, UdpSocketPosix*>::iterator it =
206 _socketMap.begin();
207 it != _socketMap.end();
208 ++it) {
209 delete it->second;
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05210 }
pbos@webrtc.org52c5c702013-08-12 19:51:57211 _socketMap.clear();
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05212 _critSectList->Leave();
213
214 delete _critSectList;
215 }
216
217 WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1,
218 "UdpSocketManagerPosix deleted");
219}
220
221bool UdpSocketManagerPosixImpl::Start()
222{
tommi@webrtc.org0e57be82015-03-19 14:44:18223 if (!_thread)
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05224 {
225 return false;
226 }
227
228 WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1,
229 "Start UdpSocketManagerPosix");
tommi@webrtc.org01c14812015-03-22 14:41:46230 if (!_thread->Start())
231 return false;
232 _thread->SetPriority(kRealtimePriority);
233 return true;
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05234}
235
236bool UdpSocketManagerPosixImpl::Stop()
237{
tommi@webrtc.org0e57be82015-03-19 14:44:18238 if (!_thread)
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05239 {
240 return true;
241 }
242
243 WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1,
244 "Stop UdpSocketManagerPosix");
245 return _thread->Stop();
246}
247
248bool UdpSocketManagerPosixImpl::Process()
249{
250 bool doSelect = false;
251 // Timeout = 1 second.
252 struct timeval timeout;
253 timeout.tv_sec = 0;
254 timeout.tv_usec = 10000;
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05255
256 FD_ZERO(&_readFds);
257
258 UpdateSocketMap();
259
pbos@webrtc.org52c5c702013-08-12 19:51:57260 SOCKET maxFd = 0;
261 for (std::map<SOCKET, UdpSocketPosix*>::iterator it = _socketMap.begin();
262 it != _socketMap.end();
263 ++it) {
264 doSelect = true;
265 if (it->first > maxFd)
266 maxFd = it->first;
267 FD_SET(it->first, &_readFds);
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05268 }
269
270 int num = 0;
271 if (doSelect)
272 {
273 num = select(maxFd+1, &_readFds, NULL, NULL, &timeout);
274
275 if (num == SOCKET_ERROR)
276 {
277 // Timeout = 10 ms.
hta@webrtc.orgc9f88712013-04-04 08:56:34278 SleepMs(10);
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05279 return true;
280 }
281 }else
282 {
283 // Timeout = 10 ms.
hta@webrtc.orgc9f88712013-04-04 08:56:34284 SleepMs(10);
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05285 return true;
286 }
287
pbos@webrtc.org52c5c702013-08-12 19:51:57288 for (std::map<SOCKET, UdpSocketPosix*>::iterator it = _socketMap.begin();
289 it != _socketMap.end();
290 ++it) {
291 if (FD_ISSET(it->first, &_readFds)) {
292 it->second->HasIncoming();
293 --num;
294 }
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05295 }
pbos@webrtc.org52c5c702013-08-12 19:51:57296
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05297 return true;
298}
299
tommi@webrtc.org42cc2122015-03-19 14:35:58300bool UdpSocketManagerPosixImpl::Run(void* obj)
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05301{
302 UdpSocketManagerPosixImpl* mgr =
303 static_cast<UdpSocketManagerPosixImpl*>(obj);
304 return mgr->Process();
305}
306
307bool UdpSocketManagerPosixImpl::AddSocket(UdpSocketWrapper* s)
308{
309 UdpSocketPosix* sl = static_cast<UdpSocketPosix*>(s);
310 if(sl->GetFd() == INVALID_SOCKET || !(sl->GetFd() < FD_SETSIZE))
311 {
312 return false;
313 }
314 _critSectList->Enter();
henrike@webrtc.org083049f2014-01-13 15:21:30315 _addList.push_back(s);
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05316 _critSectList->Leave();
317 return true;
318}
319
320bool UdpSocketManagerPosixImpl::RemoveSocket(UdpSocketWrapper* s)
321{
322 // Put in remove list if this is the correct UdpSocketManagerPosixImpl.
323 _critSectList->Enter();
324
325 // If the socket is in the add list it's safe to remove and delete it.
henrike@webrtc.org083049f2014-01-13 15:21:30326 for (SocketList::iterator iter = _addList.begin();
327 iter != _addList.end(); ++iter) {
328 UdpSocketPosix* addSocket = static_cast<UdpSocketPosix*>(*iter);
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05329 unsigned int addFD = addSocket->GetFd();
330 unsigned int removeFD = static_cast<UdpSocketPosix*>(s)->GetFd();
331 if(removeFD == addFD)
332 {
henrike@webrtc.org083049f2014-01-13 15:21:30333 _removeList.push_back(removeFD);
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05334 _critSectList->Leave();
335 return true;
336 }
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05337 }
338
339 // Checking the socket map is safe since all Erase and Insert calls to this
340 // map are also protected by _critSectList.
pbos@webrtc.org52c5c702013-08-12 19:51:57341 if (_socketMap.find(static_cast<UdpSocketPosix*>(s)->GetFd()) !=
342 _socketMap.end()) {
henrike@webrtc.org083049f2014-01-13 15:21:30343 _removeList.push_back(static_cast<UdpSocketPosix*>(s)->GetFd());
pbos@webrtc.org52c5c702013-08-12 19:51:57344 _critSectList->Leave();
345 return true;
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05346 }
347 _critSectList->Leave();
348 return false;
349}
350
351void UdpSocketManagerPosixImpl::UpdateSocketMap()
352{
353 // Remove items in remove list.
354 _critSectList->Enter();
henrike@webrtc.org083049f2014-01-13 15:21:30355 for (FdList::iterator iter = _removeList.begin();
356 iter != _removeList.end(); ++iter) {
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05357 UdpSocketPosix* deleteSocket = NULL;
henrike@webrtc.org083049f2014-01-13 15:21:30358 SOCKET removeFD = *iter;
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05359
360 // If the socket is in the add list it hasn't been added to the socket
361 // map yet. Just remove the socket from the add list.
henrike@webrtc.org083049f2014-01-13 15:21:30362 for (SocketList::iterator iter = _addList.begin();
363 iter != _addList.end(); ++iter) {
364 UdpSocketPosix* addSocket = static_cast<UdpSocketPosix*>(*iter);
pbos@webrtc.org52c5c702013-08-12 19:51:57365 SOCKET addFD = addSocket->GetFd();
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05366 if(removeFD == addFD)
367 {
368 deleteSocket = addSocket;
henrike@webrtc.org083049f2014-01-13 15:21:30369 _addList.erase(iter);
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05370 break;
371 }
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05372 }
373
374 // Find and remove socket from _socketMap.
pbos@webrtc.org52c5c702013-08-12 19:51:57375 std::map<SOCKET, UdpSocketPosix*>::iterator it =
376 _socketMap.find(removeFD);
377 if(it != _socketMap.end())
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05378 {
pbos@webrtc.org52c5c702013-08-12 19:51:57379 deleteSocket = it->second;
380 _socketMap.erase(it);
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05381 }
382 if(deleteSocket)
383 {
384 deleteSocket->ReadyForDeletion();
385 delete deleteSocket;
386 }
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05387 }
henrike@webrtc.org083049f2014-01-13 15:21:30388 _removeList.clear();
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05389
390 // Add sockets from add list.
henrike@webrtc.org083049f2014-01-13 15:21:30391 for (SocketList::iterator iter = _addList.begin();
392 iter != _addList.end(); ++iter) {
393 UdpSocketPosix* s = static_cast<UdpSocketPosix*>(*iter);
pbos@webrtc.org52c5c702013-08-12 19:51:57394 if(s) {
395 _socketMap[s->GetFd()] = s;
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05396 }
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05397 }
henrike@webrtc.org083049f2014-01-13 15:21:30398 _addList.clear();
pwestin@webrtc.orgaf6aa7b2013-03-21 16:38:05399 _critSectList->Leave();
400}
401
402} // namespace test
403} // namespace webrtc